undns 0.4.0a

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ /* (c) neil spring 2002 */
2
+
3
+ #include "nscommon.h"
4
+ #include <netinet/in.h>
5
+
6
+ void origins_init(const char *origins_dat);
7
+ unsigned short origin_for_address(in_addr_t a);
8
+ unsigned short origin_for_address_str(const char *addrstring);
9
+
10
+ boolean origin_prefix_for_address(in_addr_t a,
11
+ /*@out@*/ unsigned short *asn,
12
+ /*@out@*/ in_addr_t *prefix,
13
+ /*@out@*/ unsigned char *prefixlen);
14
+ boolean origin_prefix_for_address_str(const char *addrstring,
15
+ /*@out@*/ unsigned short *asn,
16
+ /*@out@*/ in_addr_t *prefix,
17
+ /*@out@*/ unsigned char *prefixlen);
@@ -0,0 +1,285 @@
1
+ /*
2
+ * Copyright (c) 2002
3
+ * Neil Spring and the University of Washington.
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions
8
+ * are met:
9
+ * 1. Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * 2. Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * 3. The name of the author(s) may not be used to endorse or promote
15
+ * products derived from this software without specific prior
16
+ * written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
19
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
22
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+
30
+ #ifdef HAVE_CONFIG_H
31
+ #include <config.h>
32
+ #endif
33
+ #include<float.h>
34
+ #include<assert.h>
35
+
36
+ #include"nscommon.h"
37
+
38
+ /* gettimeofday */
39
+ #include <sys/time.h>
40
+ #include <unistd.h>
41
+
42
+ #include <string.h>
43
+
44
+ #include"progress.h"
45
+
46
+ /* snprintf */
47
+ #define _GNU_SOURCE
48
+ #include <stdio.h>
49
+ #ifdef HAVE_DMALLOC_H
50
+ #include<dmalloc.h>
51
+ #endif
52
+ #ifndef HAVE_SNPRINTF
53
+ int snprintf ( char *str, size_t n, const char *format, ... );
54
+ #endif
55
+
56
+ __inline static float diffTime(struct timeval bigger, struct timeval smaller) {
57
+ long sec = bigger.tv_sec - smaller.tv_sec;
58
+ long usec = bigger.tv_usec - smaller.tv_usec;
59
+ return((float)sec + (float)usec/1000000.0);
60
+ }
61
+
62
+
63
+ static unsigned int next = 1;
64
+ static float fnext;
65
+ static char barstore[] =
66
+ "==============================================================================";
67
+ static char fmtstring[60];
68
+ static const char *label ="";
69
+ static boolean bAnnotate = FALSE;
70
+ static boolean bEnabled = TRUE;
71
+ static unsigned int spoonum;
72
+ static char ratestring[20];
73
+ static char timestring[20];
74
+
75
+ static void progress_timestring(float rate);
76
+ #define iBAR_WIDTHdefault 51
77
+ #define bBAR_WIDTHdefault 51
78
+ #define fBAR_WIDTHdefault ((float)iBAR_WIDTH)
79
+ #define bfBAR_WIDTHdefault ((float)bBAR_WIDTH)
80
+
81
+ static unsigned int iBAR_WIDTH = iBAR_WIDTHdefault;
82
+ static unsigned int bBAR_WIDTH = bBAR_WIDTHdefault;
83
+ static float fBAR_WIDTH = ((float)iBAR_WIDTHdefault);
84
+ static float bfBAR_WIDTH = ((float)bBAR_WIDTHdefault);
85
+
86
+ void progress_reset() {
87
+ next = 0;
88
+ fnext = 0.0;
89
+ }
90
+ void progress_disable() {
91
+ bEnabled = FALSE;
92
+ }
93
+
94
+ void progress(const float f) {
95
+ // fprintf(stderr,"%f\n",f);
96
+ if(!bEnabled) return;
97
+ if(f < FLT_EPSILON) {
98
+ fprintf(stderr, "\r>");
99
+ next = 1;
100
+ } else {
101
+ if(f >= ((float)(next))/fBAR_WIDTH || f >= (float)1.0) {
102
+ next = (unsigned int)(f*fBAR_WIDTH)+1;
103
+ if(bAnnotate) {
104
+ snprintf(fmtstring, sizeof(fmtstring), "\r%s:%3.0f%%%% %%-%ds| %u", label, f*100.0, iBAR_WIDTH, spoonum);
105
+ }
106
+ else
107
+ snprintf(fmtstring, sizeof(fmtstring), "\r%s:%3.0f%%%% %%-%ds|", label, f*100.0, iBAR_WIDTH);
108
+ if(next > 1 )barstore[next-2]='>';
109
+ barstore[next-1]='\0';
110
+ fprintf(stderr, fmtstring, barstore);
111
+ //fprintf(stderr, "\r%s>", barstore);
112
+ barstore[next-1]='=';
113
+ if(next > 1 )barstore[next-2]='=';
114
+ }
115
+ if(f >= (float)1.0-FLT_EPSILON){
116
+ fprintf(stderr,"\n");
117
+ bAnnotate = FALSE;
118
+ }
119
+ }
120
+ }
121
+
122
+ void progress_label(const char *label_param) {
123
+ if(strlen(label_param) < bBAR_WIDTHdefault - 5) {
124
+ label = label_param;
125
+ bBAR_WIDTH = min(1, (int) bBAR_WIDTHdefault - (int)strlen(label_param));
126
+ iBAR_WIDTH = min(1, (int) iBAR_WIDTHdefault - (int)strlen(label_param));
127
+ }
128
+ fBAR_WIDTH = (float)iBAR_WIDTH;
129
+ bfBAR_WIDTH = (float)bBAR_WIDTH;
130
+ }
131
+ void progress_annotate(unsigned int spoo) {
132
+ bAnnotate = TRUE;
133
+ spoonum = spoo;
134
+ }
135
+
136
+ static struct timeval start;
137
+
138
+ void progress_bytes_of_bytes(unsigned long int bytes,
139
+ unsigned long int total ) {
140
+ struct timeval now;
141
+ if(bytes > total) return;
142
+ if(!bEnabled) return;
143
+ if(isatty(fileno(stderr)) == 0) return;
144
+ if(bytes == 0) {
145
+ gettimeofday(&start, NULL);
146
+ fprintf(stderr, "\r>");
147
+ fnext = 0.01;
148
+ } else {
149
+ float f = (float)bytes/(float)total;
150
+ if(f >= fnext || bytes >= total) {
151
+ float dt;
152
+ unsigned int thisint = (unsigned int)(f*bfBAR_WIDTH);
153
+ fnext = f+0.01;
154
+ gettimeofday(&now, NULL);
155
+ dt = diffTime(now,start);
156
+ progress_ratestring((double)bytes / (double)dt, "B");
157
+ progress_timestring(dt*((float)total-bytes)/((float)bytes));
158
+ snprintf(fmtstring, sizeof(fmtstring), "\r%s:%3.0f%%%% %%-%ds| %9s eta %6s",
159
+ label, f*100.0, bBAR_WIDTH, ratestring, timestring);
160
+ if(thisint > 0 )barstore[thisint-1]='>';
161
+ barstore[thisint]='\0';
162
+ fprintf(stderr, fmtstring, barstore);
163
+ //fprintf(stderr, "\r%s>", barstore);
164
+ barstore[thisint]='=';
165
+ if(thisint > 0 )barstore[thisint-1]='=';
166
+ }
167
+ }
168
+ if(bytes == total){
169
+ float dt = diffTime(now,start);
170
+ fprintf(stderr,"\n");
171
+ if(dt > 2) {
172
+ progress_timestring(dt);
173
+ fprintf(stderr, "%s process rate: %s for %s\n", label, ratestring, timestring);
174
+ }
175
+ }
176
+ }
177
+
178
+ void progress_n_of(unsigned int n,
179
+ unsigned int total ) {
180
+ struct timeval now;
181
+ float f = (float)n/(float)total;
182
+ if(n > total) return;
183
+ if(!bEnabled) return;
184
+ if(isatty(fileno(stderr)) == 0) return;
185
+ if(n == 0) {
186
+ gettimeofday(&start, NULL);
187
+ fprintf(stderr, "\r>");
188
+ fnext = 0;
189
+ progress_ratestring(0, "");
190
+ progress_timestring(0);
191
+ }
192
+ if(f >= fnext || n >= total) {
193
+ float dt;
194
+ unsigned int thisint = (unsigned int)(f*bfBAR_WIDTH);
195
+ fnext = f+0.01;
196
+ if(n != 0) {
197
+ gettimeofday(&now, NULL);
198
+ dt = diffTime(now,start);
199
+ progress_ratestring((double)n / (double)dt, "");
200
+ progress_timestring(dt*((float)total-n)/((float)n));
201
+ }
202
+ snprintf(fmtstring, sizeof(fmtstring), "\r%s:%3.0f%%%% %%-%ds| %9s eta %6s",
203
+ label, f*100.0, bBAR_WIDTH, ratestring, timestring);
204
+ if(thisint != 0 ) barstore[thisint-1]='>';
205
+ barstore[thisint]='\0';
206
+ fprintf(stderr, fmtstring, barstore);
207
+ //fprintf(stderr, "\r%s>", barstore);
208
+ barstore[thisint]='=';
209
+ if(thisint > 0 )barstore[thisint-1]='=';
210
+ }
211
+ if(n == total){
212
+ float dt = diffTime(now,start);
213
+ fprintf(stderr,"\n");
214
+ if(dt > 2) {
215
+ progress_timestring(dt);
216
+ fprintf(stderr, "%s process rate: %s for %s\n", label, ratestring, timestring);
217
+ }
218
+ }
219
+ }
220
+
221
+ /* technique stolen from ncftp. */
222
+ #define KByte 1024u
223
+ #define MByte (1024u*KByte)
224
+ #define GByte (1024u*MByte)
225
+ /* haha */
226
+
227
+
228
+ static void progress_timestring(float timeInSeconds) {
229
+ unsigned int hours=0;
230
+ unsigned int minutes=0;
231
+ unsigned int seconds=0;
232
+ unsigned int deciseconds=0;
233
+ hours = ((unsigned int)timeInSeconds) / 3600;
234
+ timeInSeconds -= hours*3600;
235
+ minutes = ((unsigned int)timeInSeconds) / 60;
236
+ timeInSeconds -= minutes*60;
237
+ seconds = ((unsigned int)timeInSeconds);
238
+ timeInSeconds-=seconds;
239
+ deciseconds = ((unsigned int)(timeInSeconds*10.0))%10;
240
+ if(hours >0) {
241
+ snprintf(timestring, sizeof(timestring), "%uh%02um", hours,minutes);
242
+ } else if(minutes >0) {
243
+ snprintf(timestring, sizeof(timestring), "%um%02us", minutes,seconds);
244
+ } else {
245
+ snprintf(timestring, sizeof(timestring), "%u.%01us", seconds, deciseconds);
246
+ }
247
+ }
248
+
249
+ const char * progress_ratestring(float rate, const char *units) {
250
+ char suff;
251
+ if(rate > 999.5 * GByte) {
252
+ suff = 'T';
253
+ rate = rate / GByte / 1024.0;
254
+ } else if(rate > 999.5 * MByte) {
255
+ suff = 'G';
256
+ rate /= GByte;
257
+ } else if(rate > 999.5 * KByte) {
258
+ suff = 'M';
259
+ rate /= MByte;
260
+ snprintf(ratestring, sizeof(ratestring),
261
+ "%.2fM", (float)rate / (float)MByte);
262
+ } else if(rate >= 999.5 ) {
263
+ suff = 'K';
264
+ rate /= KByte;;
265
+ } else {
266
+ suff = ' ';
267
+ snprintf(ratestring, sizeof(ratestring),
268
+ "%3.0f%s/s", rate, units);
269
+ }
270
+ if(rate >= 99.5) {
271
+ snprintf(ratestring, sizeof(ratestring),
272
+ "%3.0f%c%s/s", rate, suff, units);
273
+ } else if(rate >= 9.5) {
274
+ snprintf(ratestring, sizeof(ratestring),
275
+ "%4.1f%c%s/s", rate, suff, units);
276
+ } else {
277
+ snprintf(ratestring, sizeof(ratestring),
278
+ "%4.2f%c%s/s", rate, suff, units);
279
+ }
280
+ return(ratestring);
281
+ }
282
+
283
+ /*
284
+ vi:ts=2
285
+ */
@@ -0,0 +1,45 @@
1
+ /*
2
+ * Copyright (c) 2002
3
+ * Neil Spring and the University of Washington.
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions
8
+ * are met:
9
+ * 1. Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * 2. Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * 3. The name of the author(s) may not be used to endorse or promote
15
+ * products derived from this software without specific prior
16
+ * written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
19
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
22
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+
30
+ void progress(const float progress_fraction);
31
+ void progress_label(const char *label_param);
32
+ void progress_annotate(unsigned int spoo);
33
+
34
+ void progress_bytes_of_bytes(unsigned long int bytes,
35
+ unsigned long int total );
36
+ void progress_n_of(unsigned int n,
37
+ unsigned int total );
38
+ void progress_disable(void);
39
+ void progress_reset(void);
40
+
41
+ /* internal, but handy */
42
+ const char * progress_ratestring(float rate, const char *units);
43
+ /*
44
+ vi:ts=2
45
+ */
@@ -0,0 +1,346 @@
1
+ /*
2
+ * Copyright (c) 2002
3
+ * Neil Spring and the University of Washington.
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions
8
+ * are met:
9
+ * 1. Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * 2. Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * 3. The name of the author(s) may not be used to endorse or promote
15
+ * products derived from this software without specific prior
16
+ * written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
19
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
22
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+
30
+ #ifdef HAVE_CONFIG_H
31
+ #include <config.h>
32
+ #endif
33
+ #include <stdlib.h>
34
+ #include <stdio.h>
35
+ #include <string.h>
36
+ #include <assert.h>
37
+ #ifdef HAVE_LIBPTHREAD
38
+ #include <pthread.h>
39
+ #else
40
+ // dealt with using AC_NSPRING_NO_PTHREAD typedef void *pthread_mutex_t;
41
+ #define pthread_mutex_lock(x) (0)
42
+ #define pthread_mutex_unlock(x) (0)
43
+ #define pthread_mutex_init(x,y) (0)
44
+ #define pthread_mutex_destroy(x) (0)
45
+ #endif
46
+ #include "queue.h"
47
+ #ifdef HAVE_DMALLOC_H
48
+ #include <dmalloc.h>
49
+ #endif
50
+
51
+ struct queue_element_struct {
52
+ const void *value;
53
+ struct queue_element_struct *next;
54
+ struct queue_element_struct *prev;
55
+ };
56
+
57
+ struct queue_struct {
58
+ q_element head, tail;
59
+ int (*compare)(const void *v1, const void *v2);
60
+ void (*release)(void *v); /* aka free */
61
+ pthread_mutex_t mutex;
62
+ };
63
+
64
+ /*
65
+ #define LOCK { printf("^"); fflush(stdout); assert(pthread_mutex_lock(&q->mutex)==0); }
66
+ #define UNLOCK { assert(pthread_mutex_unlock(&q->mutex)==0); printf("."); fflush(stdout); };
67
+ */
68
+ #define LOCK assert(pthread_mutex_lock(&q->mutex)==0);
69
+ #define UNLOCK assert(pthread_mutex_unlock(&q->mutex)==0);
70
+
71
+ #define check_invariants(q) check_invariants_internal(q, __FILE__, __LINE__)
72
+
73
+ static inline void check_invariants_internal(queue q, const char *str, int line) {
74
+ if(!(q->head == NULL || q->head->prev == NULL)) {
75
+ fprintf(stderr, "!(q->head == NULL || q->head->prev == NULL)) at %s:%d\n", str, line);
76
+ abort();
77
+ }
78
+ if(!(q->head == NULL || q->head->next == NULL || q->head->next->prev == q->head)) {
79
+ fprintf(stderr, "!(q->head == NULL || q->head->next == NULL || q->head->next->prev == q->head)) at %s:%d\n", str, line);
80
+ abort();
81
+ }
82
+ if(!(q->tail == NULL || q->tail->next == NULL)) {
83
+ fprintf(stderr, "!(q->tail == NULL || q->tail->next == NULL)) at %s:%d\n", str, line);
84
+ abort();
85
+ }
86
+ if(!(q->tail == NULL || q->tail->prev == NULL || q->tail->prev->next == q->tail) ) {
87
+ fprintf(stderr, "!(q->tail == NULL || q->tail->prev == NULL || q->tail->prev->next == q->tail)) at %s:%d\n", str, line);
88
+ abort();
89
+ }
90
+ }
91
+
92
+ /* compare has strcmp semantics */
93
+ queue q_new(int (*compare)(const void *v1, const void *v2),
94
+ void (*release)(void *v)) {
95
+ queue q = (queue)malloc(sizeof(struct queue_struct));
96
+ assert(q!=NULL);
97
+ memset(q, 0, sizeof(struct queue_struct));
98
+ q->compare = compare;
99
+ q->release = release;
100
+ (void)pthread_mutex_init(&q->mutex, NULL);
101
+ return(q);
102
+ }
103
+
104
+ void q_delete(/*@only@*/ queue q) {
105
+ void *v;
106
+ v = (void *)q_pop(q);
107
+ while(v) {
108
+ if(q->release) q->release(v); /* aka free */
109
+ v=(void *)q_pop(q);
110
+ }
111
+ (void)pthread_mutex_destroy(&q->mutex);
112
+ free(q);
113
+ }
114
+
115
+ q_element q_insert_fromdir(queue q, const void *v, boolean scan_backwards);
116
+ q_element q_insert(queue q, const void *v) {
117
+ return(q_insert_fromdir(q, v, FALSE));
118
+ }
119
+ q_element q_insert_fromdir(queue q, const void *v, boolean scan_backwards) {
120
+ q_element newelem;
121
+ assert(q!=NULL);
122
+ if(q->compare == NULL) {
123
+ fprintf(stderr, "you used q_insert instead of q_append on an unsorted queue\n");
124
+ assert(q->compare!=NULL); /* insert is sorted; needs a comparator */
125
+ }
126
+
127
+ newelem = malloc(sizeof(struct queue_element_struct));
128
+ assert(newelem!=NULL);
129
+ newelem->value = v;
130
+
131
+ LOCK;
132
+ if(!q->head) {
133
+ assert(q->tail == NULL);
134
+ newelem->prev = newelem->next = NULL;
135
+ q->head = q->tail = newelem;
136
+ } else {
137
+ q_element iter;
138
+ if(scan_backwards) {
139
+ if(q->compare(q->tail->value, v) <= 0) {
140
+ /* append */
141
+ newelem->prev = q->tail;
142
+ newelem->next = NULL;
143
+ if(q->tail) { /* should be trivially true, since q->head was non-null... */
144
+ q->tail->next = newelem;
145
+ }
146
+ q->tail=newelem;
147
+ } else {
148
+ for(iter = q->tail;
149
+ iter!=NULL && q->compare(iter->value, v) >= 0;
150
+ iter = iter->prev);
151
+ if(iter) { // must insert in middle
152
+ newelem->prev = iter;
153
+ newelem->next = iter->next;
154
+ iter->next = newelem;
155
+ if(newelem->next) {
156
+ newelem->next->prev = newelem;
157
+ } else {
158
+ q->tail = newelem;
159
+ }
160
+ } else {
161
+ /* prepend */
162
+ newelem->next = q->head;
163
+ newelem->prev = NULL;
164
+ q->head->prev = newelem;
165
+ q->head=newelem;
166
+ }
167
+ }
168
+ } else {
169
+ for(iter = q->head;
170
+ iter!=NULL && q->compare(iter->value, v) <= 0;
171
+ /* <= there should append equal things. < should prepend equal things */
172
+ iter = iter->next);
173
+ if(iter) { // must insert in middle
174
+ newelem = malloc(sizeof(struct queue_element_struct));
175
+ assert(newelem!=NULL);
176
+ newelem->value = v;
177
+ newelem->next = iter;
178
+ newelem->prev = iter->prev;
179
+ iter->prev = newelem;
180
+ if(newelem->prev) {
181
+ newelem->prev->next = newelem;
182
+ } else {
183
+ q->head = newelem;
184
+ }
185
+ } else {
186
+ /* append */
187
+ newelem->prev = q->tail;
188
+ newelem->next = NULL;
189
+ if(q->tail) { /* should be trivially true, since q->head was non-null... */
190
+ q->tail->next = newelem;
191
+ }
192
+ q->tail=newelem;
193
+ }
194
+ }
195
+ }
196
+ UNLOCK;
197
+ return newelem;
198
+ }
199
+ void q_append(queue q, const void *v) {
200
+ q_element newelem = malloc(sizeof(struct queue_element_struct));
201
+ assert(newelem!=NULL);
202
+ assert(q!=NULL);
203
+ newelem->value = v;
204
+ newelem->next = NULL;
205
+ LOCK;
206
+ check_invariants(q);
207
+ newelem->prev = q->tail;
208
+ if(q->tail) {
209
+ q->tail->next = newelem;
210
+ } else {
211
+ assert(q->head == NULL);
212
+ q->head = newelem;
213
+ }
214
+ q->tail = newelem;
215
+ check_invariants(q);
216
+ UNLOCK;
217
+ }
218
+
219
+ static /*@null@*/ const void *q_top_gotlock(const queue q) {
220
+ const void * retval = NULL;
221
+ if(q->head) {
222
+ retval = q->head->value;
223
+ }
224
+ return retval;
225
+ }
226
+
227
+ /*@null@*/ const void *q_pop(queue q) {
228
+ const void *retval;
229
+ q_element freeme;
230
+ LOCK;
231
+ check_invariants(q);
232
+ freeme = q->head;
233
+ retval = q_top_gotlock(q);
234
+ if(freeme!=NULL) {
235
+ q->head = q->head->next;
236
+ if(q->head)
237
+ q->head->prev=NULL;
238
+ else
239
+ q->tail=NULL;
240
+ free(freeme);
241
+ }
242
+ check_invariants(q);
243
+ UNLOCK;
244
+ return(retval);
245
+ }
246
+
247
+ /*@null@*/ const void *q_top(const queue q) {
248
+ const void * retval;
249
+ LOCK;
250
+ retval = q_top_gotlock(q);
251
+ UNLOCK;
252
+ return(retval);
253
+ }
254
+
255
+ /* returns true if not interrupted by a false callback return val */
256
+ boolean q_iterate(queue q, q_iterator iterator, void *user) {
257
+ q_element i;
258
+ boolean cont = TRUE;
259
+ LOCK;
260
+ check_invariants(q);
261
+ for( i = q->head; i != NULL && cont; i = i->next ) {
262
+ cont = iterator(i->value, user);
263
+ }
264
+ UNLOCK;
265
+ return cont;
266
+ }
267
+
268
+ /* returns true if not interrupted by a false callback return val */
269
+ boolean q_iterate_q(queue q, q_iterator_q iterator, void *user) {
270
+ q_element i;
271
+ boolean cont = TRUE;
272
+ LOCK;
273
+ check_invariants(q);
274
+ for( i = q->head; i != NULL && cont; i = i->next ) {
275
+ cont = iterator(q, i->value, user);
276
+ }
277
+ UNLOCK;
278
+ return cont;
279
+ }
280
+
281
+ static boolean counter(const void *v __attribute__ ((unused)),
282
+ void *count) {
283
+ (*(unsigned long *)count)++;
284
+ assert((*(unsigned long *)count) < 200000);
285
+ return TRUE;
286
+ }
287
+ unsigned long q_length(queue q) {
288
+ unsigned long count=0;
289
+ (void)q_iterate(q, counter, &count);
290
+ return count;
291
+ }
292
+
293
+ static boolean finder(queue q, const void *v, void *user) {
294
+ void **found = (void **)user;
295
+ if(q->compare(v, *found) == 0) {
296
+ *found = (void *)v;
297
+ return FALSE;
298
+ }
299
+ return TRUE;
300
+ }
301
+
302
+ void *q_find(queue q, const void *findme) {
303
+ void *found;
304
+ found = (void *)findme;
305
+ if(q_iterate_q(q, finder, &found) == 0)
306
+ return(found);
307
+ else
308
+ return(NULL);
309
+ }
310
+
311
+ void q_expunge(queue q, /*@owned@*/ q_element p) {
312
+
313
+ q_element prev;
314
+ assert(p!=NULL);
315
+ prev = p->prev;
316
+ if(prev != NULL) {
317
+ prev->next = p->next;
318
+ } else {
319
+ q->head = p->next;
320
+ }
321
+ if(p->next == NULL) {
322
+ q->tail = prev;
323
+ } else {
324
+ p->next->prev = prev;
325
+ }
326
+ free(p);
327
+ }
328
+
329
+ /* find the element with the value pointer equal to removeme */
330
+ /* then expunge that record. */
331
+ /* caller frees removeme as desired */
332
+ boolean q_remove(queue q, void *removeme) {
333
+ // q_element prev = NULL;
334
+ q_element p; /* the one to remove */
335
+ check_invariants(q);
336
+ /* the following should get fixed. */
337
+ for(p=q->head;
338
+ p != NULL && p->value != removeme;
339
+ // prev = p,
340
+ p=p->next);
341
+ if(p != NULL) {
342
+ q_expunge(q, p);
343
+ }
344
+ check_invariants(q);
345
+ return(p!=NULL); /* true if found and removed, false otherwise */
346
+ }