1 /* vector.c ..... store a vector of PPTP_CALL information and search it
3 * C. Scott Ananian <cananian@alumni.princeton.edu>
5 * $Id: vector.c,v 1.3 2003/06/17 10:12:55 reink Exp $
11 #include "pptp_ctrl.h"
13 /* #define VECTOR_DEBUG */
26 struct vector_struct
{
27 struct vector_item
*item
;
35 static struct vector_item
*binary_search(VECTOR
*v
, int key
);
37 /*** vector_create ************************************************************/
38 VECTOR
*vector_create()
40 const int INITIAL_SIZE
= 4;
42 VECTOR
*v
= malloc(sizeof(*v
));
43 if (v
== NULL
) return v
;
46 v
->alloc
= INITIAL_SIZE
;
47 v
->item
= malloc(sizeof(*(v
->item
)) * (v
->alloc
));
51 if (v
->item
== NULL
) { free(v
); return NULL
; }
55 /*** vector_destroy ***********************************************************/
56 void vector_destroy(VECTOR
*v
)
65 /*** vector_size **************************************************************/
66 int vector_size(VECTOR
*v
)
72 /*** vector_insert*************************************************************
73 * nice thing about file descriptors is that we are assured by POSIX
74 * that they are monotonically increasing.
76 int vector_insert(VECTOR
*v
, int key
, PPTP_CALL
* call
)
79 assert(v
!= NULL
&& call
!= NULL
);
80 assert(!vector_contains(v
, key
));
82 assert(v
->key_max
< key
);
84 if (!(v
->size
< v
->alloc
)) {
85 void *tmp
= realloc(v
->item
, sizeof(*(v
->item
)) * 2 * v
->alloc
);
89 } else return FALSE
; /* failed to alloc memory. */
91 assert(v
->size
< v
->alloc
);
92 /* for safety, we make this work in the general case;
93 * but this is optimized for adding call to the end of the vector.
95 for(i
= v
->size
- 1; i
>= 0; i
--)
96 if (v
->item
[i
].key
< key
)
98 /* insert after item i */
99 memmove(&v
->item
[i
+ 2], &v
->item
[i
+ 1],
100 (v
->size
- i
- 1) * sizeof(*(v
->item
)));
101 v
->item
[i
+ 1].key
= key
;
102 v
->item
[i
+ 1].call
= call
;
105 if (v
->key_max
< key
) /* ie, always. */
111 /*** vector_remove ************************************************************/
112 int vector_remove(VECTOR
*v
, int key
)
114 struct vector_item
*tmp
;
116 if ((tmp
=binary_search(v
,key
)) == NULL
) return FALSE
;
117 assert(tmp
>= v
->item
&& tmp
< v
->item
+ v
->size
);
118 memmove(tmp
, tmp
+ 1, (v
->size
- (v
->item
- tmp
) - 1) * sizeof(*(v
->item
)));
123 /*** vector_search ************************************************************/
124 int vector_search(VECTOR
*v
, int key
, PPTP_CALL
**call
)
126 struct vector_item
*tmp
;
128 tmp
= binary_search(v
, key
);
129 if (tmp
==NULL
) return FALSE
;
134 /*** vector_contains **********************************************************/
135 int vector_contains(VECTOR
*v
, int key
)
138 return (binary_search(v
, key
) != NULL
);
141 /*** vector_item **************************************************************/
142 static struct vector_item
*binary_search(VECTOR
*v
, int key
)
149 if (key
< v
->item
[x
].key
) r
= x
- 1; else l
= x
+ 1;
150 if (key
== v
->item
[x
].key
) return &(v
->item
[x
]);
155 /*** vector_scan ***************************************************************
156 * Hmm. Let's be fancy and use a binary search for the first
157 * unused key, taking advantage of the list is stored sorted; ie
158 * we can look at pointers and keys at two different locations,
159 * and if (ptr1 - ptr2) = (key1 - key2) then all the slots
160 * between ptr1 and ptr2 are filled. Note that ptr1-ptr2 should
161 * never be greater than key1-key2 (no duplicate keys!)... we
164 int vector_scan(VECTOR
*v
, int lo
, int hi
, int *key
)
169 if ((v
->size
<1) || (lo
< v
->item
[0].key
)) { *key
= lo
; return TRUE
; }
170 /* our array bounds */
171 l
= 0; r
= v
->size
- 1;
173 /* check for a free spot right after l */
174 if (v
->item
[l
].key
+ 1 < v
->item
[l
+ 1].key
) { /* found it! */
175 *key
= v
->item
[l
].key
+ 1;
178 /* no dice. Let's see if the free spot is before or after the midpoint */
180 /* Okay, we have right (r), left (l) and the probe (x). */
181 assert(x
- l
<= v
->item
[x
].key
- v
->item
[l
].key
);
182 assert(r
- x
<= v
->item
[r
].key
- v
->item
[x
].key
);
183 if (x
- l
< v
->item
[x
].key
- v
->item
[l
].key
)
184 /* room between l and x */
186 else /* no room between l and x */
187 if (r
- x
< v
->item
[r
].key
- v
->item
[x
].key
)
188 /* room between x and r */
190 else /* no room between x and r, either */
191 break; /* game over, man. */
193 /* no room found in already allocated space. Check to see if
194 * there's free space above allocated entries. */
195 if (v
->item
[v
->size
- 1].key
< hi
) {
196 *key
= v
->item
[v
->size
- 1].key
+ 1;
203 /*** vector_get_Nth ***********************************************************/
204 PPTP_CALL
* vector_get_Nth(VECTOR
*v
, int n
)
207 assert(0 <= n
&& n
< vector_size(v
));
208 return v
->item
[n
].call
;