bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / modules / ssl / ssl_util_table.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*                      _             _
18  *  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
19  * | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
20  * | | | | | | (_) | (_| |   \__ \__ \ |
21  * |_| |_| |_|\___/ \__,_|___|___/___/_|
22  *                      |_____|
23  *  ssl_util_table.c
24  *  High Performance Hash Table Functions
25  */
26
27 /*
28  * Generic hash table handler
29  * Table 4.1.0 July-28-1998
30  *
31  * This library is a generic open hash table with buckets and
32  * linked lists.  It is pretty high performance.  Each element
33  * has a key and a data.  The user indexes on the key to find the
34  * data.
35  *
36  * Copyright 1998 by Gray Watson <gray@letters.com>
37  *
38  * Permission to use, copy, modify, and distribute this software for any
39  * purpose and without fee is hereby granted, provided that the above
40  * copyright notice and this permission notice appear in all copies,
41  * and that the name of Gray Watson not be used in advertising or
42  * publicity pertaining to distribution of the document or software
43  * without specific, written prior permission.
44  *
45  * Gray Watson makes no representations about the suitability of the
46  * software described herein for any purpose.  It is provided "as is"
47  * without express or implied warranty.
48  *
49  * Modified in March 1999 by Ralf S. Engelschall <rse@engelschall.com>
50  * for use in the mod_ssl project:
51  *   o merged table_loc.h header into table.c
52  *   o removed fillproto-comments from table.h
53  *   o removed mmap() support because it's too unportable
54  *   o added support for MM library via ta_{malloc,calloc,realloc,free}
55  */
56
57 #include <stdlib.h>
58 #include <string.h>
59
60 /* forward definitions for table.h */
61 typedef struct table_st table_t;
62 typedef struct table_entry_st table_entry_t;
63
64 #define TABLE_PRIVATE
65 #include "ssl_util_table.h"
66 #include "mod_ssl.h"
67
68 /****************************** local defines ******************************/
69
70 #ifndef BITSPERBYTE
71 #define BITSPERBYTE     8
72 #endif
73 #ifndef BITS
74 #define BITS(type)      (BITSPERBYTE * (int)sizeof(type))
75 #endif
76
77 #define TABLE_MAGIC     0xBADF00D       /* very magic magicness */
78 #define LINEAR_MAGIC    0xAD00D00       /* magic value for linear struct */
79 #define DEFAULT_SIZE    1024    /* default table size */
80 #define MAX_ALIGNMENT   128     /* max alignment value */
81 #define MAX_SORT_SPLITS 128     /* qsort can handle 2^128 entries */
82
83 /* returns 1 when we should grow or shrink the table */
84 #define SHOULD_TABLE_GROW(tab)  ((tab)->ta_entry_n > (tab)->ta_bucket_n * 2)
85 #define SHOULD_TABLE_SHRINK(tab) ((tab)->ta_entry_n < (tab)->ta_bucket_n / 2)
86
87 /*
88  * void HASH_MIX
89  *
90  * DESCRIPTION:
91  *
92  * Mix 3 32-bit values reversibly.  For every delta with one or two bits
93  * set, and the deltas of all three high bits or all three low bits,
94  * whether the original value of a,b,c is almost all zero or is
95  * uniformly distributed.
96  *
97  * If HASH_MIX() is run forward or backward, at least 32 bits in a,b,c
98  * have at least 1/4 probability of changing.  If mix() is run
99  * forward, every bit of c will change between 1/3 and 2/3 of the
100  * time.  (Well, 22/100 and 78/100 for some 2-bit deltas.)
101  *
102  * HASH_MIX() takes 36 machine instructions, but only 18 cycles on a
103  * superscalar machine (like a Pentium or a Sparc).  No faster mixer
104  * seems to work, that's the result of my brute-force search.  There
105  * were about 2^68 hashes to choose from.  I only tested about a
106  * billion of those.
107  */
108 #define HASH_MIX(a, b, c) \
109  do { \
110    a -= b; a -= c; a ^= (c >> 13); \
111    b -= c; b -= a; b ^= (a << 8); \
112    c -= a; c -= b; c ^= (b >> 13); \
113    a -= b; a -= c; a ^= (c >> 12); \
114    b -= c; b -= a; b ^= (a << 16); \
115    c -= a; c -= b; c ^= (b >> 5); \
116    a -= b; a -= c; a ^= (c >> 3); \
117    b -= c; b -= a; b ^= (a << 10); \
118    c -= a; c -= b; c ^= (b >> 15); \
119  } while(0)
120
121 #define TABLE_POINTER(table, type, pnt)         (pnt)
122
123 /*
124  * Macros to get at the key and the data pointers
125  */
126 #define ENTRY_KEY_BUF(entry_p)          ((entry_p)->te_key_buf)
127 #define ENTRY_DATA_BUF(tab_p, entry_p)  \
128      (ENTRY_KEY_BUF(entry_p) + (entry_p)->te_key_size)
129
130 /*
131  * Table structures...
132  */
133
134 /*
135  * HACK: this should be equiv as the table_entry_t without the key_buf
136  * char.  We use this with the ENTRY_SIZE() macro above which solves
137  * the problem with the lack of the [0] GNU hack.  We use the
138  * table_entry_t structure to better map the memory and make things
139  * faster.
140  */
141 typedef struct table_shell_st {
142     unsigned int te_key_size;   /* size of data */
143     unsigned int te_data_size;  /* size of data */
144     struct table_shell_st *te_next_p;   /* pointer to next in the list */
145     /* NOTE: this does not have the te_key_buf field here */
146 } table_shell_t;
147
148 /*
149  * Elements in the bucket linked-lists.  The key[1] is the start of
150  * the key with the rest of the key and all of the data information
151  * packed in memory directly after the end of this structure.
152  *
153  * NOTE: if this structure is changed, the table_shell_t must be changed
154  * to match.
155  */
156 struct table_entry_st {
157     unsigned int te_key_size;   /* size of data */
158     unsigned int te_data_size;  /* size of data */
159     struct table_entry_st *te_next_p;   /* pointer to next in the list */
160     unsigned char te_key_buf[1];        /* 1st byte of key buf */
161 };
162
163 /* external structure for debuggers be able to see void */
164 typedef table_entry_t table_entry_ext_t;
165
166 /* main table structure */
167 struct table_st {
168     unsigned int ta_magic;      /* magic number */
169     unsigned int ta_flags;      /* table's flags defined in table.h */
170     unsigned int ta_bucket_n;   /* num of buckets, should be 2^X */
171     unsigned int ta_entry_n;    /* num of entries in all buckets */
172     unsigned int ta_data_align; /* data alignment value */
173     table_entry_t **ta_buckets; /* array of linked lists */
174     table_linear_t ta_linear;   /* linear tracking */
175     unsigned long ta_file_size; /* size of on-disk space */
176     void *(*ta_malloc)(void *opt_param, size_t size);
177     void *(*ta_calloc)(void *opt_param, size_t number, size_t size);
178     void *(*ta_realloc)(void *opt_param, void *ptr, size_t size);
179     void (*ta_free)(void *opt_param, void *ptr);
180     void *opt_param;
181 };
182
183 /* external table structure for debuggers */
184 typedef table_t table_ext_t;
185
186 /* local comparison functions */
187 typedef int (*compare_t) (const void *element1_p, const void *element2_p,
188                           table_compare_t user_compare,
189                           const table_t * table_p);
190
191 /*
192  * to map error to string
193  */
194 typedef struct {
195     int es_error;               /* error number */
196     char *es_string;            /* assocaited string */
197 } error_str_t;
198
199 static error_str_t errors[] =
200 {
201     {TABLE_ERROR_NONE, "no error"},
202     {TABLE_ERROR_PNT, "invalid table pointer"},
203     {TABLE_ERROR_ARG_NULL, "buffer argument is null"},
204     {TABLE_ERROR_SIZE, "incorrect size argument"},
205     {TABLE_ERROR_OVERWRITE, "key exists and no overwrite"},
206     {TABLE_ERROR_NOT_FOUND, "key does not exist"},
207     {TABLE_ERROR_ALLOC, "error allocating memory"},
208     {TABLE_ERROR_LINEAR, "linear access not in progress"},
209     {TABLE_ERROR_OPEN, "could not open file"},
210     {TABLE_ERROR_SEEK, "could not seek to position in file"},
211     {TABLE_ERROR_READ, "could not read from file"},
212     {TABLE_ERROR_WRITE, "could not write to file"},
213     {TABLE_ERROR_EMPTY, "table is empty"},
214     {TABLE_ERROR_NOT_EMPTY, "table contains data"},
215     {TABLE_ERROR_ALIGNMENT, "invalid alignment value"},
216     {0}
217 };
218
219 #define INVALID_ERROR   "invalid error code"
220
221
222 /********************** wrappers for system functions ************************/
223 static void *sys_malloc(void *param, size_t size)
224 {
225     return malloc(size);
226 }
227
228 static void *sys_calloc(void *param, size_t size1, size_t size2)
229 {
230     return calloc(size1, size2);
231 }
232
233 static void *sys_realloc(void *param, void *ptr, size_t size)
234 {
235     return realloc(ptr, size);
236 }
237
238 static void sys_free(void *param, void *ptr)
239 {
240     free(ptr);
241 }
242
243 /****************************** local functions ******************************/
244
245 /*
246  * static table_entry_t *first_entry
247  *
248  * DESCRIPTION:
249  *
250  * Return the first entry in the table.  It will set the linear
251  * structure counter to the position of the first entry.
252  *
253  * RETURNS:
254  *
255  * Success: A pointer to the first entry in the table.
256  *
257  * Failure: NULL if there is no first entry.
258  *
259  * ARGUMENTS:
260  *
261  * table_p - Table whose next entry we are finding.
262  *
263  * linear_p - Pointer to a linear structure which we will advance and
264  * then find the corresponding entry.
265  */
266 static table_entry_t *first_entry(table_t * table_p,
267                                   table_linear_t * linear_p)
268 {
269     table_entry_t *entry_p;
270     unsigned int bucket_c = 0;
271
272     /* look for the first non-empty bucket */
273     for (bucket_c = 0; bucket_c < table_p->ta_bucket_n; bucket_c++) {
274         entry_p = table_p->ta_buckets[bucket_c];
275         if (entry_p != NULL) {
276             if (linear_p != NULL) {
277                 linear_p->tl_bucket_c = bucket_c;
278                 linear_p->tl_entry_c = 0;
279             }
280             return TABLE_POINTER(table_p, table_entry_t *, entry_p);
281         }
282     }
283
284     return NULL;
285 }
286
287 /*
288  * static table_entry_t *next_entry
289  *
290  * DESCRIPTION:
291  *
292  * Return the next entry in the table which is past the position in
293  * our linear pointer.  It will advance the linear structure counters.
294  *
295  * RETURNS:
296  *
297  * Success: A pointer to the next entry in the table.
298  *
299  * Failure: NULL.
300  *
301  * ARGUMENTS:
302  *
303  * table_p - Table whose next entry we are finding.
304  *
305  * linear_p - Pointer to a linear structure which we will advance and
306  * then find the corresponding entry.
307  *
308  * error_p - Pointer to an integer which when the routine returns will
309  * contain a table error code.
310  */
311 static table_entry_t *next_entry(table_t * table_p, table_linear_t * linear_p,
312                                  int *error_p)
313 {
314     table_entry_t *entry_p;
315     int entry_c;
316
317     /* can't next if we haven't first-ed */
318     if (linear_p == NULL) {
319         if (error_p != NULL)
320             *error_p = TABLE_ERROR_LINEAR;
321         return NULL;
322     }
323
324     if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) {
325         /*
326          * NOTE: this might happen if we delete an item which shortens the
327          * table bucket numbers.
328          */
329         if (error_p != NULL)
330             *error_p = TABLE_ERROR_NOT_FOUND;
331         return NULL;
332     }
333
334     linear_p->tl_entry_c++;
335
336     /* find the entry which is the nth in the list */
337     entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];
338     /* NOTE: we swap the order here to be more efficient */
339     for (entry_c = linear_p->tl_entry_c; entry_c > 0; entry_c--) {
340         /* did we reach the end of the list? */
341         if (entry_p == NULL)
342             break;
343         entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p;
344     }
345
346     /* did we find an entry in the current bucket? */
347     if (entry_p != NULL) {
348         if (error_p != NULL)
349             *error_p = TABLE_ERROR_NONE;
350         return TABLE_POINTER(table_p, table_entry_t *, entry_p);
351     }
352
353     /* find the first entry in the next non-empty bucket */
354
355     linear_p->tl_entry_c = 0;
356     for (linear_p->tl_bucket_c++; linear_p->tl_bucket_c < table_p->ta_bucket_n;
357          linear_p->tl_bucket_c++) {
358         entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];
359         if (entry_p != NULL) {
360             if (error_p != NULL)
361                 *error_p = TABLE_ERROR_NONE;
362             return TABLE_POINTER(table_p, table_entry_t *, entry_p);
363         }
364     }
365
366     if (error_p != NULL)
367         *error_p = TABLE_ERROR_NOT_FOUND;
368     return NULL;
369 }
370
371 /*
372  * static unsigned int hash
373  *
374  * DESCRIPTION:
375  *
376  * Hash a variable-length key into a 32-bit value.  Every bit of the
377  * key affects every bit of the return value.  Every 1-bit and 2-bit
378  * delta achieves avalanche.  About (6 * len + 35) instructions.  The
379  * best hash table sizes are powers of 2.  There is no need to use mod
380  * (sooo slow!).  If you need less than 32 bits, use a bitmask.  For
381  * example, if you need only 10 bits, do h = (h & hashmask(10)); In
382  * which case, the hash table should have hashsize(10) elements.
383  *
384  * By Bob Jenkins, 1996.  bob_jenkins@compuserve.com.  You may use
385  * this code any way you wish, private, educational, or commercial.
386  * It's free.  See
387  * http://ourworld.compuserve.com/homepages/bob_jenkins/evahash.htm
388  * Use for hash table lookup, or anything where one collision in 2^^32
389  * is acceptable.  Do NOT use for cryptographic purposes.
390  *
391  * RETURNS:
392  *
393  * Returns a 32-bit hash value.
394  *
395  * ARGUMENTS:
396  *
397  * key - Key (the unaligned variable-length array of bytes) that we
398  * are hashing.
399  *
400  * length - Length of the key in bytes.
401  *
402  * init_val - Initialization value of the hash if you need to hash a
403  * number of strings together.  For instance, if you are hashing N
404  * strings (unsigned char **)keys, do it like this:
405  *
406  * for (i=0, h=0; i<N; ++i) h = hash( keys[i], len[i], h);
407  */
408 static unsigned int hash(const unsigned char *key,
409                          const unsigned int length,
410                          const unsigned int init_val)
411 {
412     const unsigned char *key_p = key;
413     unsigned int a, b, c, len;
414
415     /* set up the internal state */
416     a = 0x9e3779b9;             /* the golden ratio; an arbitrary value */
417     b = 0x9e3779b9;
418     c = init_val;               /* the previous hash value */
419
420     /* handle most of the key */
421     for (len = length; len >= 12; len -= 12) {
422         a += (key_p[0]
423               + ((unsigned long) key_p[1] << 8)
424               + ((unsigned long) key_p[2] << 16)
425               + ((unsigned long) key_p[3] << 24));
426         b += (key_p[4]
427               + ((unsigned long) key_p[5] << 8)
428               + ((unsigned long) key_p[6] << 16)
429               + ((unsigned long) key_p[7] << 24));
430         c += (key_p[8]
431               + ((unsigned long) key_p[9] << 8)
432               + ((unsigned long) key_p[10] << 16)
433               + ((unsigned long) key_p[11] << 24));
434         HASH_MIX(a, b, c);
435         key_p += 12;
436     }
437
438     c += length;
439
440     /* all the case statements fall through to the next */
441     switch (len) {
442     case 11:
443         c += ((unsigned long) key_p[10] << 24);
444     case 10:
445         c += ((unsigned long) key_p[9] << 16);
446     case 9:
447         c += ((unsigned long) key_p[8] << 8);
448         /* the first byte of c is reserved for the length */
449     case 8:
450         b += ((unsigned long) key_p[7] << 24);
451     case 7:
452         b += ((unsigned long) key_p[6] << 16);
453     case 6:
454         b += ((unsigned long) key_p[5] << 8);
455     case 5:
456         b += key_p[4];
457     case 4:
458         a += ((unsigned long) key_p[3] << 24);
459     case 3:
460         a += ((unsigned long) key_p[2] << 16);
461     case 2:
462         a += ((unsigned long) key_p[1] << 8);
463     case 1:
464         a += key_p[0];
465         /* case 0: nothing left to add */
466     }
467     HASH_MIX(a, b, c);
468
469     return c;
470 }
471
472 /*
473  * static int entry_size
474  *
475  * DESCRIPTION:
476  *
477  * Calculates the appropriate size of an entry to include the key and
478  * data sizes as well as any associated alignment to the data.
479  *
480  * RETURNS:
481  *
482  * The associated size of the entry.
483  *
484  * ARGUMENTS:
485  *
486  * table_p - Table associated with the entries whose size we are
487  * determining.
488  *
489  * key_size - Size of the entry key.
490  *
491  * data - Size of the entry data.
492  */
493 static int entry_size(const table_t * table_p, const unsigned int key_size,
494                       const unsigned int data_size)
495 {
496     int size, left;
497
498     /* initial size -- key is already aligned if right after struct */
499     size = sizeof(struct table_shell_st) + key_size;
500
501     /* if there is no alignment then it is easy */
502     if (table_p->ta_data_align == 0)
503         return size + data_size;
504     /* add in our alignement */
505     left = size & (table_p->ta_data_align - 1);
506     if (left > 0)
507         size += table_p->ta_data_align - left;
508     /* we add the data size here after the alignment */
509     size += data_size;
510
511     return size;
512 }
513
514 /*
515  * static unsigned char *entry_data_buf
516  *
517  * DESCRIPTION:
518  *
519  * Companion to the ENTRY_DATA_BUF macro but this handles any
520  * associated alignment to the data in the entry.
521  *
522  * RETURNS:
523  *
524  * Pointer to the data segment of the entry.
525  *
526  * ARGUMENTS:
527  *
528  * table_p - Table associated with the entry.
529  *
530  * entry_p - Entry whose data pointer we are determining.
531  */
532 static unsigned char *entry_data_buf(const table_t * table_p,
533                                      const table_entry_t * entry_p)
534 {
535     const unsigned char *buf_p;
536     int size, pad;
537
538     buf_p = entry_p->te_key_buf + entry_p->te_key_size;
539
540     /* if there is no alignment then it is easy */
541     if (table_p->ta_data_align == 0)
542         return (unsigned char *) buf_p;
543     /* we need the size of the space before the data */
544     size = sizeof(struct table_shell_st) + entry_p->te_key_size;
545
546     /* add in our alignment */
547     pad = size & (table_p->ta_data_align - 1);
548     if (pad > 0)
549         pad = table_p->ta_data_align - pad;
550     return (unsigned char *) buf_p + pad;
551 }
552
553 /******************************* sort routines *******************************/
554
555 /*
556  * static int our_compare
557  *
558  * DESCRIPTION:
559  *
560  * Compare two entries by calling user's compare program or by using
561  * memcmp.
562  *
563  * RETURNS:
564  *
565  * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2.
566  *
567  * ARGUMENTS:
568  *
569  * p1 - First entry pointer to compare.
570  *
571  * p2 - Second entry pointer to compare.
572  *
573  * compare - User comparison function.  Ignored.
574  *
575  * table_p - Associated table being ordered.  Ignored.
576  */
577 static int local_compare(const void *p1, const void *p2,
578                          table_compare_t compare, const table_t * table_p)
579 {
580     const table_entry_t *const *ent1_p = p1, *const *ent2_p = p2;
581     int cmp;
582     unsigned int size;
583
584     /* compare as many bytes as we can */
585     size = (*ent1_p)->te_key_size;
586     if ((*ent2_p)->te_key_size < size)
587         size = (*ent2_p)->te_key_size;
588     cmp = memcmp(ENTRY_KEY_BUF(*ent1_p), ENTRY_KEY_BUF(*ent2_p), size);
589     /* if common-size equal, then if next more bytes, it is larger */
590     if (cmp == 0)
591         cmp = (*ent1_p)->te_key_size - (*ent2_p)->te_key_size;
592     return cmp;
593 }
594
595 /*
596  * static int external_compare
597  *
598  * DESCRIPTION:
599  *
600  * Compare two entries by calling user's compare program or by using
601  * memcmp.
602  *
603  * RETURNS:
604  *
605  * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2.
606  *
607  * ARGUMENTS:
608  *
609  * p1 - First entry pointer to compare.
610  *
611  * p2 - Second entry pointer to compare.
612  *
613  * user_compare - User comparison function.
614  *
615  * table_p - Associated table being ordered.
616  */
617 static int external_compare(const void *p1, const void *p2,
618                             table_compare_t user_compare,
619                             const table_t * table_p)
620 {
621     const table_entry_t *const *ent1_p = p1, *const *ent2_p = p2;
622     /* since we know we are not aligned we can use the EXTRY_DATA_BUF macro */
623     return user_compare(ENTRY_KEY_BUF(*ent1_p), (*ent1_p)->te_key_size,
624                         ENTRY_DATA_BUF(table_p, *ent1_p),
625                         (*ent1_p)->te_data_size,
626                         ENTRY_KEY_BUF(*ent2_p), (*ent2_p)->te_key_size,
627                         ENTRY_DATA_BUF(table_p, *ent2_p),
628                         (*ent2_p)->te_data_size);
629 }
630
631 /*
632  * static int external_compare_align
633  *
634  * DESCRIPTION:
635  *
636  * Compare two entries by calling user's compare program or by using
637  * memcmp.  Alignment information is necessary.
638  *
639  * RETURNS:
640  *
641  * < 0, == 0, or > 0 depending on whether p1 is > p2, == p2, < p2.
642  *
643  * ARGUMENTS:
644  *
645  * p1 - First entry pointer to compare.
646  *
647  * p2 - Second entry pointer to compare.
648  *
649  * user_compare - User comparison function.
650  *
651  * table_p - Associated table being ordered.
652  */
653 static int external_compare_align(const void *p1, const void *p2,
654                                   table_compare_t user_compare,
655                                   const table_t * table_p)
656 {
657     const table_entry_t *const *ent1_p = p1, *const *ent2_p = p2;
658     /* since we are aligned we have to use the entry_data_buf function */
659     return user_compare(ENTRY_KEY_BUF(*ent1_p), (*ent1_p)->te_key_size,
660                         entry_data_buf(table_p, *ent1_p),
661                         (*ent1_p)->te_data_size,
662                         ENTRY_KEY_BUF(*ent2_p), (*ent2_p)->te_key_size,
663                         entry_data_buf(table_p, *ent2_p),
664                         (*ent2_p)->te_data_size);
665 }
666
667 /*
668  * static void split
669  *
670  * DESCRIPTION:
671  *
672  * This sorts an array of longs via the quick sort algorithm (it's
673  * pretty quick)
674  *
675  * RETURNS:
676  *
677  * None.
678  *
679  * ARGUMENTS:
680  *
681  * first_p - Start of the list that we are splitting.
682  *
683  * last_p - Last entry in the list that we are splitting.
684  *
685  * compare - Comparison function which is handling the actual
686  * elements.  This is either a local function or a function to setup
687  * the problem element key and data pointers which then hands off to
688  * the user function.
689  *
690  * user_compare - User comparison function.  Could be NULL if we are
691  * just using a local comparison function.
692  *
693  * table_p - Associated table being sorted.
694  */
695 static void split(void *first_p, void *last_p, compare_t compare,
696                   table_compare_t user_compare, table_t * table_p)
697 {
698     void *pivot_p, *left_p, *right_p, *left_last_p, *right_first_p;
699     void *firsts[MAX_SORT_SPLITS], *lasts[MAX_SORT_SPLITS];
700     int split_c = 0;
701
702     for (;;) {
703
704         /* no need to split the list if it is < 2 elements */
705         while (first_p >= last_p) {
706             if (split_c == 0) {
707                 /* we are done */
708                 return;
709             }
710             split_c--;
711             first_p = firsts[split_c];
712             last_p = lasts[split_c];
713         }
714
715         left_p = first_p;
716         right_p = last_p;
717         pivot_p = first_p;
718
719         do {
720             /* scan from right hand side */
721             while (right_p > left_p
722                    && compare(right_p, pivot_p, user_compare, table_p) > 0)
723                 right_p = (char *) right_p - sizeof(table_entry_t *);
724             /* scan from left hand side */
725             while (right_p > left_p
726                    && compare(pivot_p, left_p, user_compare, table_p) >= 0)
727                 left_p = (char *) left_p + sizeof(table_entry_t *);
728             /* if the pointers haven't met then swap values */
729             if (right_p > left_p) {
730                 /* swap_bytes(left_p, right_p) */
731                 table_entry_t *temp;
732
733                 temp = *(table_entry_t **) left_p;
734                 *(table_entry_t **) left_p = *(table_entry_t **) right_p;
735                 *(table_entry_t **) right_p = temp;
736             }
737         } while (right_p > left_p);
738
739         /* now we swap the pivot with the right-hand side */
740         {
741             /* swap_bytes(pivot_p, right_p); */
742             table_entry_t *temp;
743
744             temp = *(table_entry_t **) pivot_p;
745             *(table_entry_t **) pivot_p = *(table_entry_t **) right_p;
746             *(table_entry_t **) right_p = temp;
747         }
748         pivot_p = right_p;
749
750         /* save the section to the right of the pivot in our stack */
751         right_first_p = (char *) pivot_p + sizeof(table_entry_t *);
752         left_last_p = (char *) pivot_p - sizeof(table_entry_t *);
753
754         /* do we need to save the righthand side? */
755         if (right_first_p < last_p) {
756             if (split_c >= MAX_SORT_SPLITS) {
757                 /* sanity check here -- we should never get here */
758                 abort();
759             }
760             firsts[split_c] = right_first_p;
761             lasts[split_c] = last_p;
762             split_c++;
763         }
764
765         /* do the left hand side of the pivot */
766         /* first_p = first_p */
767         last_p = left_last_p;
768     }
769 }
770
771 /*************************** exported routines *******************************/
772
773 /*
774  * table_t *table_alloc
775  *
776  * DESCRIPTION:
777  *
778  * Allocate a new table structure.
779  *
780  * RETURNS:
781  *
782  * A pointer to the new table structure which must be passed to
783  * table_free to be deallocated.  On error a NULL is returned.
784  *
785  * ARGUMENTS:
786  *
787  * bucket_n - Number of buckets for the hash table.  Our current hash
788  * value works best with base two numbers.  Set to 0 to take the
789  * library default of 1024.
790  *
791  * error_p - Pointer to an integer which, if not NULL, will contain a
792  * table error code.
793  *
794  * malloc_f, realloc_f, free_f - Pointers to malloc(3)-, realloc(3)-
795  * and free(3)-style functions.
796  */
797 table_t *table_alloc(const unsigned int bucket_n, int *error_p,
798                  void *(*malloc_f)(void *opt_param, size_t size),
799                  void *(*calloc_f)(void *opt_param, size_t number, size_t size),
800                  void *(*realloc_f)(void *opt_param, void *ptr, size_t size),
801                  void (*free_f)(void *opt_param, void *ptr), void *opt_param)
802 {
803     table_t *table_p = NULL;
804     unsigned int buck_n;
805
806     /* allocate a table structure */
807     if (malloc_f != NULL)
808         table_p = malloc_f(opt_param, sizeof(table_t));
809     else
810         table_p = malloc(sizeof(table_t));
811     if (table_p == NULL) {
812         if (error_p != NULL)
813             *error_p = TABLE_ERROR_ALLOC;
814         return NULL;
815     }
816
817     if (bucket_n > 0)
818         buck_n = bucket_n;
819     else
820         buck_n = DEFAULT_SIZE;
821     /* allocate the buckets which are NULLed */
822     if (calloc_f != NULL)
823         table_p->ta_buckets = (table_entry_t **)calloc_f(opt_param, buck_n,
824                                                        sizeof(table_entry_t *));
825     else
826         table_p->ta_buckets = (table_entry_t **)calloc(buck_n, sizeof(table_entry_t *));
827     if (table_p->ta_buckets == NULL) {
828         if (error_p != NULL)
829             *error_p = TABLE_ERROR_ALLOC;
830         if (free_f != NULL)
831             free_f(opt_param, table_p);
832         else
833             free(table_p);
834         return NULL;
835     }
836
837     /* initialize structure */
838     table_p->ta_magic = TABLE_MAGIC;
839     table_p->ta_flags = 0;
840     table_p->ta_bucket_n = buck_n;
841     table_p->ta_entry_n = 0;
842     table_p->ta_data_align = 0;
843     table_p->ta_linear.tl_magic = 0;
844     table_p->ta_linear.tl_bucket_c = 0;
845     table_p->ta_linear.tl_entry_c = 0;
846     table_p->ta_file_size = 0;
847     table_p->ta_malloc  = malloc_f  != NULL ? malloc_f  : sys_malloc;
848     table_p->ta_calloc  = calloc_f  != NULL ? calloc_f  : sys_calloc;
849     table_p->ta_realloc = realloc_f != NULL ? realloc_f : sys_realloc;
850     table_p->ta_free    = free_f    != NULL ? free_f    : sys_free;
851     table_p->opt_param = opt_param;
852
853     if (error_p != NULL)
854         *error_p = TABLE_ERROR_NONE;
855     return table_p;
856 }
857
858 /*
859  * int table_attr
860  *
861  * DESCRIPTION:
862  *
863  * Set the attributes for the table.  The available attributes are
864  * specified at the top of table.h.
865  *
866  * RETURNS:
867  *
868  * Success - TABLE_ERROR_NONE
869  *
870  * Failure - Table error code.
871  *
872  * ARGUMENTS:
873  *
874  * table_p - Pointer to a table structure which we will be altering.
875  *
876  * attr - Attribute(s) that we will be applying to the table.
877  */
878 int table_attr(table_t * table_p, const int attr)
879 {
880     if (table_p == NULL)
881         return TABLE_ERROR_ARG_NULL;
882     if (table_p->ta_magic != TABLE_MAGIC)
883         return TABLE_ERROR_PNT;
884     table_p->ta_flags = attr;
885
886     return TABLE_ERROR_NONE;
887 }
888
889 /*
890  * int table_set_data_alignment
891  *
892  * DESCRIPTION:
893  *
894  * Set the alignment for the data in the table.  For data elements
895  * sizeof(long) is recommended unless you use smaller data types
896  * exclusively.
897  *
898  * WARNING: This must be done before any data gets put into the table.
899  *
900  * RETURNS:
901  *
902  * Success - TABLE_ERROR_NONE
903  *
904  * Failure - Table error code.
905  *
906  * ARGUMENTS:
907  *
908  * table_p - Pointer to a table structure which we will be altering.
909  *
910  * alignment - Alignment requested for the data.  Must be a power of
911  * 2.  Set to 0 for none.
912  */
913 int table_set_data_alignment(table_t * table_p, const int alignment)
914 {
915     int val;
916
917     if (table_p == NULL)
918         return TABLE_ERROR_ARG_NULL;
919     if (table_p->ta_magic != TABLE_MAGIC)
920         return TABLE_ERROR_PNT;
921     if (table_p->ta_entry_n > 0)
922         return TABLE_ERROR_NOT_EMPTY;
923     /* defaults */
924     if (alignment < 2)
925         table_p->ta_data_align = 0;
926     else {
927         /* verify we have a base 2 number */
928         for (val = 2; val < MAX_ALIGNMENT; val *= 2) {
929             if (val == alignment)
930                 break;
931         }
932         if (val >= MAX_ALIGNMENT)
933             return TABLE_ERROR_ALIGNMENT;
934         table_p->ta_data_align = alignment;
935     }
936
937     return TABLE_ERROR_NONE;
938 }
939
940 /*
941  * int table_clear
942  *
943  * DESCRIPTION:
944  *
945  * Clear out and free all elements in a table structure.
946  *
947  * RETURNS:
948  *
949  * Success - TABLE_ERROR_NONE
950  *
951  * Failure - Table error code.
952  *
953  * ARGUMENTS:
954  *
955  * table_p - Table structure pointer that we will be clearing.
956  */
957 int table_clear(table_t * table_p)
958 {
959     table_entry_t *entry_p, *next_p;
960     table_entry_t **bucket_p, **bounds_p;
961
962     if (table_p == NULL)
963         return TABLE_ERROR_ARG_NULL;
964     if (table_p->ta_magic != TABLE_MAGIC)
965         return TABLE_ERROR_PNT;
966     /* free the table allocation and table structure */
967     bounds_p = table_p->ta_buckets + table_p->ta_bucket_n;
968     for (bucket_p = table_p->ta_buckets; bucket_p < bounds_p; bucket_p++) {
969         for (entry_p = *bucket_p; entry_p != NULL; entry_p = next_p) {
970             /* record the next pointer before we free */
971             next_p = entry_p->te_next_p;
972             table_p->ta_free(table_p->opt_param, entry_p);
973         }
974         /* clear the bucket entry after we free its entries */
975         *bucket_p = NULL;
976     }
977
978     /* reset table state info */
979     table_p->ta_entry_n = 0;
980     table_p->ta_linear.tl_magic = 0;
981     table_p->ta_linear.tl_bucket_c = 0;
982     table_p->ta_linear.tl_entry_c = 0;
983
984     return TABLE_ERROR_NONE;
985 }
986
987 /*
988  * int table_free
989  *
990  * DESCRIPTION:
991  *
992  * Deallocates a table structure.
993  *
994  * RETURNS:
995  *
996  * Success - TABLE_ERROR_NONE
997  *
998  * Failure - Table error code.
999  *
1000  * ARGUMENTS:
1001  *
1002  * table_p - Table structure pointer that we will be freeing.
1003  */
1004 int table_free(table_t * table_p)
1005 {
1006     int ret;
1007
1008     if (table_p == NULL)
1009         return TABLE_ERROR_ARG_NULL;
1010     if (table_p->ta_magic != TABLE_MAGIC)
1011         return TABLE_ERROR_PNT;
1012     ret = table_clear(table_p);
1013
1014     if (table_p->ta_buckets != NULL)
1015         table_p->ta_free(table_p->opt_param, table_p->ta_buckets);
1016     table_p->ta_magic = 0;
1017     table_p->ta_free(table_p->opt_param, table_p);
1018
1019     return ret;
1020 }
1021
1022 /*
1023  * int table_insert_kd
1024  *
1025  * DESCRIPTION:
1026  *
1027  * Like table_insert except it passes back a pointer to the key and
1028  * the data buffers after they have been inserted into the table
1029  * structure.
1030  *
1031  * This routine adds a key/data pair both of which are made up of a
1032  * buffer of bytes and an associated size.  Both the key and the data
1033  * will be copied into buffers allocated inside the table.  If the key
1034  * exists already, the associated data will be replaced if the
1035  * overwrite flag is set, otherwise an error is returned.
1036  *
1037  * NOTE: be very careful changing the values since the table library
1038  * provides the pointers to its memory.  The key can _never_ be
1039  * changed otherwise you will not find it again.  The data can be
1040  * changed but its length can never be altered unless you delete and
1041  * re-insert it into the table.
1042  *
1043  * WARNING: The pointers to the key and data are not in any specific
1044  * alignment.  Accessing the key and/or data as an short, integer, or
1045  * long pointer directly can cause problems.
1046  *
1047  * WARNING: Replacing a data cell (not inserting) will cause the table
1048  * linked list to be temporarily invalid.  Care must be taken with
1049  * multiple threaded programs which are relying on the first/next
1050  * linked list to be always valid.
1051  *
1052  * RETURNS:
1053  *
1054  * Success - TABLE_ERROR_NONE
1055  *
1056  * Failure - Table error code.
1057  *
1058  * ARGUMENTS:
1059  *
1060  * table_p - Table structure pointer into which we will be inserting a
1061  * new key/data pair.
1062  *
1063  * key_buf - Buffer of bytes of the key that we are inserting.  If you
1064  * are storing an (int) as the key (for example) then key_buf should
1065  * be a (int *).
1066  *
1067  * key_size - Size of the key_buf buffer.  If set to < 0 then the
1068  * library will do a strlen of key_buf and add 1 for the '\0'.  If you
1069  * are storing an (int) as the key (for example) then key_size should
1070  * be sizeof(int).
1071  *
1072  * data_buf - Buffer of bytes of the data that we are inserting.  If
1073  * it is NULL then the library will allocate space for the data in the
1074  * table without copying in any information.  If data_buf is NULL and
1075  * data_size is 0 then the library will associate a NULL data pointer
1076  * with the key.  If you are storing a (long) as the data (for
1077  * example) then data_buf should be a (long *).
1078  *
1079  * data_size - Size of the data_buf buffer.  If set to < 0 then the
1080  * library will do a strlen of data_buf and add 1 for the '\0'.  If
1081  * you are storing an (long) as the key (for example) then key_size
1082  * should be sizeof(long).
1083  *
1084  * key_buf_p - Pointer which, if not NULL, will be set to the address
1085  * of the key storage that was allocated in the table.  If you are
1086  * storing an (int) as the key (for example) then key_buf_p should be
1087  * (int **) i.e. the address of a (int *).
1088  *
1089  * data_buf_p - Pointer which, if not NULL, will be set to the address
1090  * of the data storage that was allocated in the table.  If you are
1091  * storing an (long) as the data (for example) then data_buf_p should
1092  * be (long **) i.e. the address of a (long *).
1093  *
1094  * overwrite - Flag which, if set to 1, will allow the overwriting of
1095  * the data in the table with the new data if the key already exists
1096  * in the table.
1097  */
1098 int table_insert_kd(table_t * table_p,
1099                     const void *key_buf, const int key_size,
1100                     const void *data_buf, const int data_size,
1101                     void **key_buf_p, void **data_buf_p,
1102                     const char overwrite_b)
1103 {
1104     int bucket;
1105     unsigned int ksize, dsize;
1106     table_entry_t *entry_p, *last_p;
1107     void *key_copy_p, *data_copy_p;
1108
1109     /* check the arguments */
1110     if (table_p == NULL)
1111         return TABLE_ERROR_ARG_NULL;
1112     if (table_p->ta_magic != TABLE_MAGIC)
1113         return TABLE_ERROR_PNT;
1114     if (key_buf == NULL)
1115         return TABLE_ERROR_ARG_NULL;
1116     /* data_buf can be null but size must be >= 0, if it isn't null size != 0 */
1117     if ((data_buf == NULL && data_size < 0)
1118         || (data_buf != NULL && data_size == 0))
1119         return TABLE_ERROR_SIZE;
1120     /* determine sizes of key and data */
1121     if (key_size < 0)
1122         ksize = strlen((char *) key_buf) + sizeof(char);
1123     else
1124         ksize = key_size;
1125     if (data_size < 0)
1126         dsize = strlen((char *) data_buf) + sizeof(char);
1127     else
1128         dsize = data_size;
1129     /* get the bucket number via a hash function */
1130     bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n;
1131
1132     /* look for the entry in this bucket, only check keys of the same size */
1133     last_p = NULL;
1134     for (entry_p = table_p->ta_buckets[bucket];
1135          (entry_p != NULL) && (entry_p->te_next_p != last_p);
1136          last_p = entry_p, entry_p = entry_p->te_next_p) {
1137         if (entry_p->te_key_size == ksize
1138             && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0)
1139             break;
1140     }
1141
1142     /* did we find it?  then we are in replace mode. */
1143     if (entry_p != NULL) {
1144
1145         /* can we not overwrite existing data? */
1146         if (!overwrite_b) {
1147             if (key_buf_p != NULL)
1148                 *key_buf_p = ENTRY_KEY_BUF(entry_p);
1149             if (data_buf_p != NULL) {
1150                 if (entry_p->te_data_size == 0)
1151                     *data_buf_p = NULL;
1152                 else {
1153                     if (table_p->ta_data_align == 0)
1154                         *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
1155                     else
1156                         *data_buf_p = entry_data_buf(table_p, entry_p);
1157                 }
1158             }
1159             return TABLE_ERROR_OVERWRITE;
1160         }
1161
1162         /* re-alloc entry's data if the new size != the old */
1163         if (dsize != entry_p->te_data_size) {
1164
1165             /*
1166              * First we delete it from the list to keep the list whole.
1167              * This properly preserves the linked list in case we have a
1168              * thread marching through the linked list while we are
1169              * inserting.  Maybe this is an unnecessary protection but it
1170              * should not harm that much.
1171              */
1172             if (last_p == NULL)
1173                 table_p->ta_buckets[bucket] = entry_p->te_next_p;
1174             else
1175                 last_p->te_next_p = entry_p->te_next_p;
1176             /*
1177              * Realloc the structure which may change its pointer. NOTE:
1178              * this may change any previous data_key_p and data_copy_p
1179              * pointers.
1180              */
1181             entry_p = (table_entry_t *)
1182                        table_p->ta_realloc(table_p->opt_param, entry_p,
1183                              entry_size(table_p, entry_p->te_key_size, dsize));
1184             if (entry_p == NULL)
1185                 return TABLE_ERROR_ALLOC;
1186             /* add it back to the front of the list */
1187             entry_p->te_data_size = dsize;
1188             entry_p->te_next_p = table_p->ta_buckets[bucket];
1189             table_p->ta_buckets[bucket] = entry_p;
1190         }
1191
1192         /* copy or replace data in storage */
1193         if (dsize > 0) {
1194             if (table_p->ta_data_align == 0)
1195                 data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
1196             else
1197                 data_copy_p = entry_data_buf(table_p, entry_p);
1198             if (data_buf != NULL)
1199                 memcpy(data_copy_p, data_buf, dsize);
1200         }
1201         else
1202             data_copy_p = NULL;
1203         if (key_buf_p != NULL)
1204             *key_buf_p = ENTRY_KEY_BUF(entry_p);
1205         if (data_buf_p != NULL)
1206             *data_buf_p = data_copy_p;
1207         /* returning from the section where we were overwriting table data */
1208         return TABLE_ERROR_NONE;
1209     }
1210
1211     /*
1212      * It is a new entry.
1213      */
1214
1215     /* allocate a new entry */
1216     entry_p = (table_entry_t *)
1217                table_p->ta_malloc(table_p->opt_param,
1218                                   entry_size(table_p, ksize, dsize));
1219     if (entry_p == NULL)
1220         return TABLE_ERROR_ALLOC;
1221     /* copy key into storage */
1222     entry_p->te_key_size = ksize;
1223     key_copy_p = ENTRY_KEY_BUF(entry_p);
1224     memcpy(key_copy_p, key_buf, ksize);
1225
1226     /* copy data in */
1227     entry_p->te_data_size = dsize;
1228     if (dsize > 0) {
1229         if (table_p->ta_data_align == 0)
1230             data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
1231         else
1232             data_copy_p = entry_data_buf(table_p, entry_p);
1233         if (data_buf != NULL)
1234             memcpy(data_copy_p, data_buf, dsize);
1235     }
1236     else
1237         data_copy_p = NULL;
1238     if (key_buf_p != NULL)
1239         *key_buf_p = key_copy_p;
1240     if (data_buf_p != NULL)
1241         *data_buf_p = data_copy_p;
1242     /* insert into list, no need to append */
1243     entry_p->te_next_p = table_p->ta_buckets[bucket];
1244     table_p->ta_buckets[bucket] = entry_p;
1245
1246     table_p->ta_entry_n++;
1247
1248     /* do we need auto-adjust? */
1249     if (table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST
1250         && SHOULD_TABLE_GROW(table_p))
1251         return table_adjust(table_p, table_p->ta_entry_n);
1252     return TABLE_ERROR_NONE;
1253 }
1254
1255 /*
1256  * int table_insert
1257  *
1258  * DESCRIPTION:
1259  *
1260  * Exactly the same as table_insert_kd except it does not pass back a
1261  * pointer to the key after they have been inserted into the table
1262  * structure.  This is still here for backwards compatibility.
1263  *
1264  * See table_insert_kd for more information.
1265  *
1266  * RETURNS:
1267  *
1268  * Success - TABLE_ERROR_NONE
1269  *
1270  * Failure - Table error code.
1271  *
1272  * ARGUMENTS:
1273  *
1274  * table_p - Table structure pointer into which we will be inserting a
1275  * new key/data pair.
1276  *
1277  * key_buf - Buffer of bytes of the key that we are inserting.  If you
1278  * are storing an (int) as the key (for example) then key_buf should
1279  * be a (int *).
1280  *
1281  * key_size - Size of the key_buf buffer.  If set to < 0 then the
1282  * library will do a strlen of key_buf and add 1 for the '\0'.  If you
1283  * are storing an (int) as the key (for example) then key_size should
1284  * be sizeof(int).
1285  *
1286  * data_buf - Buffer of bytes of the data that we are inserting.  If
1287  * it is NULL then the library will allocate space for the data in the
1288  * table without copying in any information.  If data_buf is NULL and
1289  * data_size is 0 then the library will associate a NULL data pointer
1290  * with the key.  If you are storing a (long) as the data (for
1291  * example) then data_buf should be a (long *).
1292  *
1293  * data_size - Size of the data_buf buffer.  If set to < 0 then the
1294  * library will do a strlen of data_buf and add 1 for the '\0'.  If
1295  * you are storing an (long) as the key (for example) then key_size
1296  * should be sizeof(long).
1297  *
1298  * data_buf_p - Pointer which, if not NULL, will be set to the address
1299  * of the data storage that was allocated in the table.  If you are
1300  * storing an (long) as the data (for example) then data_buf_p should
1301  * be (long **) i.e. the address of a (long *).
1302  *
1303  * overwrite - Flag which, if set to 1, will allow the overwriting of
1304  * the data in the table with the new data if the key already exists
1305  * in the table.
1306  */
1307 int table_insert(table_t * table_p,
1308                  const void *key_buf, const int key_size,
1309                  const void *data_buf, const int data_size,
1310                  void **data_buf_p, const char overwrite_b)
1311 {
1312     return table_insert_kd(table_p, key_buf, key_size, data_buf, data_size,
1313                            NULL, data_buf_p, overwrite_b);
1314 }
1315
1316 /*
1317  * int table_retrieve
1318  *
1319  * DESCRIPTION:
1320  *
1321  * This routine looks up a key made up of a buffer of bytes and an
1322  * associated size in the table.  If found then it returns the
1323  * associated data information.
1324  *
1325  * RETURNS:
1326  *
1327  * Success - TABLE_ERROR_NONE
1328  *
1329  * Failure - Table error code.
1330  *
1331  * ARGUMENTS:
1332  *
1333  * table_p - Table structure pointer into which we will be searching
1334  * for the key.
1335  *
1336  * key_buf - Buffer of bytes of the key that we are searching for.  If
1337  * you are looking for an (int) as the key (for example) then key_buf
1338  * should be a (int *).
1339  *
1340  * key_size - Size of the key_buf buffer.  If set to < 0 then the
1341  * library will do a strlen of key_buf and add 1 for the '\0'.  If you
1342  * are looking for an (int) as the key (for example) then key_size
1343  * should be sizeof(int).
1344  *
1345  * data_buf_p - Pointer which, if not NULL, will be set to the address
1346  * of the data storage that was allocated in the table and that is
1347  * associated with the key.  If a (long) was stored as the data (for
1348  * example) then data_buf_p should be (long **) i.e. the address of a
1349  * (long *).
1350  *
1351  * data_size_p - Pointer to an integer which, if not NULL, will be set
1352  * to the size of the data stored in the table that is associated with
1353  * the key.
1354  */
1355 int table_retrieve(table_t * table_p,
1356                    const void *key_buf, const int key_size,
1357                    void **data_buf_p, int *data_size_p)
1358 {
1359     int bucket;
1360     unsigned int ksize;
1361     table_entry_t *entry_p, **buckets;
1362
1363     if (table_p == NULL)
1364         return TABLE_ERROR_ARG_NULL;
1365     if (table_p->ta_magic != TABLE_MAGIC)
1366         return TABLE_ERROR_PNT;
1367     if (key_buf == NULL)
1368         return TABLE_ERROR_ARG_NULL;
1369     /* find key size */
1370     if (key_size < 0)
1371         ksize = strlen((char *) key_buf) + sizeof(char);
1372     else
1373         ksize = key_size;
1374     /* get the bucket number via a has function */
1375     bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n;
1376
1377     /* look for the entry in this bucket, only check keys of the same size */
1378     buckets = table_p->ta_buckets;
1379     for (entry_p = buckets[bucket];
1380          entry_p != NULL;
1381          entry_p = entry_p->te_next_p) {
1382         entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p);
1383         if (entry_p->te_key_size == ksize
1384             && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0)
1385             break;
1386     }
1387
1388     /* not found? */
1389     if (entry_p == NULL)
1390         return TABLE_ERROR_NOT_FOUND;
1391     if (data_buf_p != NULL) {
1392         if (entry_p->te_data_size == 0)
1393             *data_buf_p = NULL;
1394         else {
1395             if (table_p->ta_data_align == 0)
1396                 *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
1397             else
1398                 *data_buf_p = entry_data_buf(table_p, entry_p);
1399         }
1400     }
1401     if (data_size_p != NULL)
1402         *data_size_p = entry_p->te_data_size;
1403     return TABLE_ERROR_NONE;
1404 }
1405
1406 /*
1407  * int table_delete
1408  *
1409  * DESCRIPTION:
1410  *
1411  * This routine looks up a key made up of a buffer of bytes and an
1412  * associated size in the table.  If found then it will be removed
1413  * from the table.  The associated data can be passed back to the user
1414  * if requested.
1415  *
1416  * RETURNS:
1417  *
1418  * Success - TABLE_ERROR_NONE
1419  *
1420  * Failure - Table error code.
1421  *
1422  * NOTE: this could be an allocation error if the library is to return
1423  * the data to the user.
1424  *
1425  * ARGUMENTS:
1426  *
1427  * table_p - Table structure pointer from which we will be deleteing
1428  * the key.
1429  *
1430  * key_buf - Buffer of bytes of the key that we are searching for to
1431  * delete.  If you are deleting an (int) key (for example) then
1432  * key_buf should be a (int *).
1433  *
1434  * key_size - Size of the key_buf buffer.  If set to < 0 then the
1435  * library will do a strlen of key_buf and add 1 for the '\0'.  If you
1436  * are deleting an (int) key (for example) then key_size should be
1437  * sizeof(int).
1438  *
1439  * data_buf_p - Pointer which, if not NULL, will be set to the address
1440  * of the data storage that was allocated in the table and that was
1441  * associated with the key.  If a (long) was stored as the data (for
1442  * example) then data_buf_p should be (long **) i.e. the address of a
1443  * (long *).  If a pointer is passed in, the caller is responsible for
1444  * freeing it after use.  If data_buf_p is NULL then the library will
1445  * free up the data allocation itself.
1446  *
1447  * data_size_p - Pointer to an integer which, if not NULL, will be set
1448  * to the size of the data that was stored in the table and that was
1449  * associated with the key.
1450  */
1451 int table_delete(table_t * table_p,
1452                  const void *key_buf, const int key_size,
1453                  void **data_buf_p, int *data_size_p)
1454 {
1455     int bucket;
1456     unsigned int ksize;
1457     unsigned char *data_copy_p;
1458     table_entry_t *entry_p, *last_p;
1459
1460     if (table_p == NULL)
1461         return TABLE_ERROR_ARG_NULL;
1462     if (table_p->ta_magic != TABLE_MAGIC)
1463         return TABLE_ERROR_PNT;
1464     if (key_buf == NULL)
1465         return TABLE_ERROR_ARG_NULL;
1466     /* get the key size */
1467     if (key_size < 0)
1468         ksize = strlen((char *) key_buf) + sizeof(char);
1469     else
1470         ksize = key_size;
1471     /* find our bucket */
1472     bucket = hash(key_buf, ksize, 0) % table_p->ta_bucket_n;
1473
1474     /* look for the entry in this bucket, only check keys of the same size */
1475     for (last_p = NULL, entry_p = table_p->ta_buckets[bucket]; entry_p != NULL;
1476          last_p = entry_p, entry_p = entry_p->te_next_p) {
1477         if (entry_p->te_key_size == ksize
1478             && memcmp(ENTRY_KEY_BUF(entry_p), key_buf, ksize) == 0)
1479             break;
1480     }
1481
1482     /* did we find it? */
1483     if (entry_p == NULL)
1484         return TABLE_ERROR_NOT_FOUND;
1485     /*
1486      * NOTE: we may want to adjust the linear counters here if the entry
1487      * we are deleting is the one we are pointing on or is ahead of the
1488      * one in the bucket list
1489      */
1490
1491     /* remove entry from the linked list */
1492     if (last_p == NULL)
1493         table_p->ta_buckets[bucket] = entry_p->te_next_p;
1494     else
1495         last_p->te_next_p = entry_p->te_next_p;
1496     /* free entry */
1497     if (data_buf_p != NULL) {
1498         if (entry_p->te_data_size == 0)
1499             *data_buf_p = NULL;
1500         else {
1501             /*
1502              * if we were storing it compacted, we now need to malloc some
1503              * space if the user wants the value after the delete.
1504              */
1505             *data_buf_p = table_p->ta_malloc(table_p->opt_param,
1506                                              entry_p->te_data_size);
1507             if (*data_buf_p == NULL)
1508                 return TABLE_ERROR_ALLOC;
1509             if (table_p->ta_data_align == 0)
1510                 data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
1511             else
1512                 data_copy_p = entry_data_buf(table_p, entry_p);
1513             memcpy(*data_buf_p, data_copy_p, entry_p->te_data_size);
1514         }
1515     }
1516     if (data_size_p != NULL)
1517         *data_size_p = entry_p->te_data_size;
1518     table_p->ta_free(table_p->opt_param, entry_p);
1519     entry_p = NULL;
1520
1521     table_p->ta_entry_n--;
1522
1523     /* do we need auto-adjust down? */
1524     if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST)
1525         && (table_p->ta_flags & TABLE_FLAG_ADJUST_DOWN)
1526         && SHOULD_TABLE_SHRINK(table_p))
1527         return table_adjust(table_p, table_p->ta_entry_n);
1528     return TABLE_ERROR_NONE;
1529 }
1530
1531 /*
1532  * int table_delete_first
1533  *
1534  * DESCRIPTION:
1535  *
1536  * This is like the table_delete routines except it deletes the first
1537  * key/data pair in the table instead of an entry corresponding to a
1538  * particular key.  The associated key and data information can be
1539  * passed back to the user if requested.  This routines is handy to
1540  * clear out a table.
1541  *
1542  * RETURNS:
1543  *
1544  * Success - TABLE_ERROR_NONE
1545  *
1546  * Failure - Table error code.
1547  *
1548  * NOTE: this could be an allocation error if the library is to return
1549  * the data to the user.
1550  *
1551  * ARGUMENTS:
1552  *
1553  * table_p - Table structure pointer from which we will be deleteing
1554  * the first key.
1555  *
1556  * key_buf_p - Pointer which, if not NULL, will be set to the address
1557  * of the storage of the first key that was allocated in the table.
1558  * If an (int) was stored as the first key (for example) then
1559  * key_buf_p should be (int **) i.e. the address of a (int *).  If a
1560  * pointer is passed in, the caller is responsible for freeing it
1561  * after use.  If key_buf_p is NULL then the library will free up the
1562  * key allocation itself.
1563  *
1564  * key_size_p - Pointer to an integer which, if not NULL, will be set
1565  * to the size of the key that was stored in the table and that was
1566  * associated with the key.
1567  *
1568  * data_buf_p - Pointer which, if not NULL, will be set to the address
1569  * of the data storage that was allocated in the table and that was
1570  * associated with the key.  If a (long) was stored as the data (for
1571  * example) then data_buf_p should be (long **) i.e. the address of a
1572  * (long *).  If a pointer is passed in, the caller is responsible for
1573  * freeing it after use.  If data_buf_p is NULL then the library will
1574  * free up the data allocation itself.
1575  *
1576  * data_size_p - Pointer to an integer which, if not NULL, will be set
1577  * to the size of the data that was stored in the table and that was
1578  * associated with the key.
1579  */
1580 int table_delete_first(table_t * table_p,
1581                        void **key_buf_p, int *key_size_p,
1582                        void **data_buf_p, int *data_size_p)
1583 {
1584     unsigned char *data_copy_p;
1585     table_entry_t *entry_p;
1586     table_linear_t linear;
1587
1588     if (table_p == NULL)
1589         return TABLE_ERROR_ARG_NULL;
1590     if (table_p->ta_magic != TABLE_MAGIC)
1591         return TABLE_ERROR_PNT;
1592     /* take the first entry */
1593     entry_p = first_entry(table_p, &linear);
1594     if (entry_p == NULL)
1595         return TABLE_ERROR_NOT_FOUND;
1596     /*
1597      * NOTE: we may want to adjust the linear counters here if the entry
1598      * we are deleting is the one we are pointing on or is ahead of the
1599      * one in the bucket list
1600      */
1601
1602     /* remove entry from the linked list */
1603     table_p->ta_buckets[linear.tl_bucket_c] = entry_p->te_next_p;
1604
1605     /* free entry */
1606     if (key_buf_p != NULL) {
1607         if (entry_p->te_key_size == 0)
1608             *key_buf_p = NULL;
1609         else {
1610             /*
1611              * if we were storing it compacted, we now need to malloc some
1612              * space if the user wants the value after the delete.
1613              */
1614             *key_buf_p = table_p->ta_malloc(table_p->opt_param,
1615                                             entry_p->te_key_size);
1616             if (*key_buf_p == NULL)
1617                 return TABLE_ERROR_ALLOC;
1618             memcpy(*key_buf_p, ENTRY_KEY_BUF(entry_p), entry_p->te_key_size);
1619         }
1620     }
1621     if (key_size_p != NULL)
1622         *key_size_p = entry_p->te_key_size;
1623     if (data_buf_p != NULL) {
1624         if (entry_p->te_data_size == 0)
1625             *data_buf_p = NULL;
1626         else {
1627             /*
1628              * if we were storing it compacted, we now need to malloc some
1629              * space if the user wants the value after the delete.
1630              */
1631             *data_buf_p = table_p->ta_malloc(table_p->opt_param,
1632                                              entry_p->te_data_size);
1633             if (*data_buf_p == NULL)
1634                 return TABLE_ERROR_ALLOC;
1635             if (table_p->ta_data_align == 0)
1636                 data_copy_p = ENTRY_DATA_BUF(table_p, entry_p);
1637             else
1638                 data_copy_p = entry_data_buf(table_p, entry_p);
1639             memcpy(*data_buf_p, data_copy_p, entry_p->te_data_size);
1640         }
1641     }
1642     if (data_size_p != NULL)
1643         *data_size_p = entry_p->te_data_size;
1644     table_p->ta_free(table_p->opt_param, entry_p);
1645
1646     table_p->ta_entry_n--;
1647
1648     /* do we need auto-adjust down? */
1649     if ((table_p->ta_flags & TABLE_FLAG_AUTO_ADJUST)
1650         && (table_p->ta_flags & TABLE_FLAG_ADJUST_DOWN)
1651         && SHOULD_TABLE_SHRINK(table_p))
1652         return table_adjust(table_p, table_p->ta_entry_n);
1653     return TABLE_ERROR_NONE;
1654 }
1655
1656 /*
1657  * int table_info
1658  *
1659  * DESCRIPTION:
1660  *
1661  * Get some information about a table_p structure.
1662  *
1663  * RETURNS:
1664  *
1665  * Success - TABLE_ERROR_NONE
1666  *
1667  * Failure - Table error code.
1668  *
1669  * ARGUMENTS:
1670  *
1671  * table_p - Table structure pointer from which we are getting
1672  * information.
1673  *
1674  * num_buckets_p - Pointer to an integer which, if not NULL, will
1675  * contain the number of buckets in the table.
1676  *
1677  * num_entries_p - Pointer to an integer which, if not NULL, will
1678  * contain the number of entries stored in the table.
1679  */
1680 int table_info(table_t * table_p, int *num_buckets_p, int *num_entries_p)
1681 {
1682     if (table_p == NULL)
1683         return TABLE_ERROR_ARG_NULL;
1684     if (table_p->ta_magic != TABLE_MAGIC)
1685         return TABLE_ERROR_PNT;
1686     if (num_buckets_p != NULL)
1687         *num_buckets_p = table_p->ta_bucket_n;
1688     if (num_entries_p != NULL)
1689         *num_entries_p = table_p->ta_entry_n;
1690     return TABLE_ERROR_NONE;
1691 }
1692
1693 /*
1694  * int table_adjust
1695  *
1696  * DESCRIPTION:
1697  *
1698  * Set the number of buckets in a table to a certain value.
1699  *
1700  * RETURNS:
1701  *
1702  * Success - TABLE_ERROR_NONE
1703  *
1704  * Failure - Table error code.
1705  *
1706  * ARGUMENTS:
1707  *
1708  * table_p - Table structure pointer of which we are adjusting.
1709  *
1710  * bucket_n - Number buckets to adjust the table to.  Set to 0 to
1711  * adjust the table to its number of entries.
1712  */
1713 int table_adjust(table_t * table_p, const int bucket_n)
1714 {
1715     table_entry_t *entry_p, *next_p;
1716     table_entry_t **buckets, **bucket_p, **bounds_p;
1717     int bucket;
1718     unsigned int buck_n;
1719
1720     if (table_p == NULL)
1721         return TABLE_ERROR_ARG_NULL;
1722     if (table_p->ta_magic != TABLE_MAGIC)
1723         return TABLE_ERROR_PNT;
1724     /*
1725      * NOTE: we walk through the entries and rehash them.  If we stored
1726      * the hash value as a full int in the table-entry, all we would
1727      * have to do is remod it.
1728      */
1729
1730     /* normalize to the number of entries */
1731     if (bucket_n == 0)
1732         buck_n = table_p->ta_entry_n;
1733     else
1734         buck_n = bucket_n;
1735     /* we must have at least 1 bucket */
1736     if (buck_n == 0)
1737         buck_n = 1;
1738     /* make sure we have somethign to do */
1739     if (buck_n <= table_p->ta_bucket_n)
1740         return TABLE_ERROR_NONE;
1741     /* allocate a new bucket list */
1742     buckets = (table_entry_t **)
1743                table_p->ta_calloc(table_p->opt_param,
1744                                   buck_n, sizeof(table_entry_t *));
1745     if (table_p->ta_buckets == NULL)
1746         return TABLE_ERROR_ALLOC;
1747     /*
1748      * run through each of the items in the current table and rehash
1749      * them into the newest bucket sizes
1750      */
1751     bounds_p = table_p->ta_buckets + table_p->ta_bucket_n;
1752     for (bucket_p = table_p->ta_buckets; bucket_p < bounds_p; bucket_p++) {
1753         for (entry_p = *bucket_p; entry_p != NULL; entry_p = next_p) {
1754
1755             /* hash the old data into the new table size */
1756             bucket = hash(ENTRY_KEY_BUF(entry_p), entry_p->te_key_size, 0) % buck_n;
1757
1758             /* record the next one now since we overwrite next below */
1759             next_p = entry_p->te_next_p;
1760
1761             /* insert into new list, no need to append */
1762             entry_p->te_next_p = buckets[bucket];
1763             buckets[bucket] = entry_p;
1764
1765             /*
1766              * NOTE: we may want to adjust the bucket_c linear entry here to
1767              * keep it current
1768              */
1769         }
1770         /* remove the old table pointers as we go by */
1771         *bucket_p = NULL;
1772     }
1773
1774     /* replace the table buckets with the new ones */
1775     table_p->ta_free(table_p->opt_param, table_p->ta_buckets);
1776     table_p->ta_buckets = buckets;
1777     table_p->ta_bucket_n = buck_n;
1778
1779     return TABLE_ERROR_NONE;
1780 }
1781
1782 /*
1783  * const char *table_strerror
1784  *
1785  * DESCRIPTION:
1786  *
1787  * Return the corresponding string for the error number.
1788  *
1789  * RETURNS:
1790  *
1791  * Success - String equivalient of the error.
1792  *
1793  * Failure - String "invalid error code"
1794  *
1795  * ARGUMENTS:
1796  *
1797  * error - Error number that we are converting.
1798  */
1799 const char *table_strerror(const int error)
1800 {
1801     error_str_t *err_p;
1802
1803     for (err_p = errors; err_p->es_error != 0; err_p++) {
1804         if (err_p->es_error == error)
1805             return err_p->es_string;
1806     }
1807
1808     return INVALID_ERROR;
1809 }
1810
1811 /*
1812  * int table_type_size
1813  *
1814  * DESCRIPTION:
1815  *
1816  * Return the size of the internal table type.
1817  *
1818  * RETURNS:
1819  *
1820  * The size of the table_t type.
1821  *
1822  * ARGUMENTS:
1823  *
1824  * None.
1825  */
1826 int table_type_size(void)
1827 {
1828     return sizeof(table_t);
1829 }
1830
1831 /************************* linear access routines ****************************/
1832
1833 /*
1834  * int table_first
1835  *
1836  * DESCRIPTION:
1837  *
1838  * Find first element in a table and pass back information about the
1839  * key/data pair.  If any of the key/data pointers are NULL then they
1840  * are ignored.
1841  *
1842  * NOTE: This function is not reentrant.  More than one thread cannot
1843  * be doing a first and next on the same table at the same time.  Use
1844  * the table_first_r version below for this.
1845  *
1846  * RETURNS:
1847  *
1848  * Success - TABLE_ERROR_NONE
1849  *
1850  * Failure - Table error code.
1851  *
1852  * ARGUMENTS:
1853  *
1854  * table_p - Table structure pointer from which we are getting the
1855  * first element.
1856  *
1857  * key_buf_p - Pointer which, if not NULL, will be set to the address
1858  * of the storage of the first key that is allocated in the table.  If
1859  * an (int) is stored as the first key (for example) then key_buf_p
1860  * should be (int **) i.e. the address of a (int *).
1861  *
1862  * key_size_p - Pointer to an integer which, if not NULL, will be set
1863  * to the size of the key that is stored in the table and that is
1864  * associated with the first key.
1865  *
1866  * data_buf_p - Pointer which, if not NULL, will be set to the address
1867  * of the data storage that is allocated in the table and that is
1868  * associated with the first key.  If a (long) is stored as the data
1869  * (for example) then data_buf_p should be (long **) i.e. the address
1870  * of a (long *).
1871  *
1872  * data_size_p - Pointer to an integer which, if not NULL, will be set
1873  * to the size of the data that is stored in the table and that is
1874  * associated with the first key.
1875  */
1876 int table_first(table_t * table_p,
1877                 void **key_buf_p, int *key_size_p,
1878                 void **data_buf_p, int *data_size_p)
1879 {
1880     table_entry_t *entry_p;
1881
1882     if (table_p == NULL)
1883         return TABLE_ERROR_ARG_NULL;
1884     if (table_p->ta_magic != TABLE_MAGIC)
1885         return TABLE_ERROR_PNT;
1886     /* initialize our linear magic number */
1887     table_p->ta_linear.tl_magic = LINEAR_MAGIC;
1888
1889     entry_p = first_entry(table_p, &table_p->ta_linear);
1890     if (entry_p == NULL)
1891         return TABLE_ERROR_NOT_FOUND;
1892     if (key_buf_p != NULL)
1893         *key_buf_p = ENTRY_KEY_BUF(entry_p);
1894     if (key_size_p != NULL)
1895         *key_size_p = entry_p->te_key_size;
1896     if (data_buf_p != NULL) {
1897         if (entry_p->te_data_size == 0)
1898             *data_buf_p = NULL;
1899         else {
1900             if (table_p->ta_data_align == 0)
1901                 *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
1902             else
1903                 *data_buf_p = entry_data_buf(table_p, entry_p);
1904         }
1905     }
1906     if (data_size_p != NULL)
1907         *data_size_p = entry_p->te_data_size;
1908     return TABLE_ERROR_NONE;
1909 }
1910
1911 /*
1912  * int table_next
1913  *
1914  * DESCRIPTION:
1915  *
1916  * Find the next element in a table and pass back information about
1917  * the key/data pair.  If any of the key/data pointers are NULL then
1918  * they are ignored.
1919  *
1920  * NOTE: This function is not reentrant.  More than one thread cannot
1921  * be doing a first and next on the same table at the same time.  Use
1922  * the table_next_r version below for this.
1923  *
1924  * RETURNS:
1925  *
1926  * Success - TABLE_ERROR_NONE
1927  *
1928  * Failure - Table error code.
1929  *
1930  * ARGUMENTS:
1931  *
1932  * table_p - Table structure pointer from which we are getting the
1933  * next element.
1934  *
1935  * key_buf_p - Pointer which, if not NULL, will be set to the address
1936  * of the storage of the next key that is allocated in the table.  If
1937  * an (int) is stored as the next key (for example) then key_buf_p
1938  * should be (int **) i.e. the address of a (int *).
1939  *
1940  * key_size_p - Pointer to an integer which, if not NULL, will be set
1941  * to the size of the key that is stored in the table and that is
1942  * associated with the next key.
1943  *
1944  * data_buf_p - Pointer which, if not NULL, will be set to the address
1945  * of the data storage that is allocated in the table and that is
1946  * associated with the next key.  If a (long) is stored as the data
1947  * (for example) then data_buf_p should be (long **) i.e. the address
1948  * of a (long *).
1949  *
1950  * data_size_p - Pointer to an integer which, if not NULL, will be set
1951  * to the size of the data that is stored in the table and that is
1952  * associated with the next key.
1953  */
1954 int table_next(table_t * table_p,
1955                void **key_buf_p, int *key_size_p,
1956                void **data_buf_p, int *data_size_p)
1957 {
1958     table_entry_t *entry_p;
1959     int error;
1960
1961     if (table_p == NULL)
1962         return TABLE_ERROR_ARG_NULL;
1963     if (table_p->ta_magic != TABLE_MAGIC)
1964         return TABLE_ERROR_PNT;
1965     if (table_p->ta_linear.tl_magic != LINEAR_MAGIC)
1966         return TABLE_ERROR_LINEAR;
1967     /* move to the next entry */
1968     entry_p = next_entry(table_p, &table_p->ta_linear, &error);
1969     if (entry_p == NULL)
1970         return error;
1971     if (key_buf_p != NULL)
1972         *key_buf_p = ENTRY_KEY_BUF(entry_p);
1973     if (key_size_p != NULL)
1974         *key_size_p = entry_p->te_key_size;
1975     if (data_buf_p != NULL) {
1976         if (entry_p->te_data_size == 0)
1977             *data_buf_p = NULL;
1978         else {
1979             if (table_p->ta_data_align == 0)
1980                 *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
1981             else
1982                 *data_buf_p = entry_data_buf(table_p, entry_p);
1983         }
1984     }
1985     if (data_size_p != NULL)
1986         *data_size_p = entry_p->te_data_size;
1987     return TABLE_ERROR_NONE;
1988 }
1989
1990 /*
1991  * int table_this
1992  *
1993  * DESCRIPTION:
1994  *
1995  * Find the current element in a table and pass back information about
1996  * the key/data pair.  If any of the key/data pointers are NULL then
1997  * they are ignored.
1998  *
1999  * NOTE: This function is not reentrant.  Use the table_current_r
2000  * version below.
2001  *
2002  * RETURNS:
2003  *
2004  * Success - TABLE_ERROR_NONE
2005  *
2006  * Failure - Table error code.
2007  *
2008  * ARGUMENTS:
2009  *
2010  * table_p - Table structure pointer from which we are getting the
2011  * current element.
2012  *
2013  * key_buf_p - Pointer which, if not NULL, will be set to the address
2014  * of the storage of the current key that is allocated in the table.
2015  * If an (int) is stored as the current key (for example) then
2016  * key_buf_p should be (int **) i.e. the address of a (int *).
2017  *
2018  * key_size_p - Pointer to an integer which, if not NULL, will be set
2019  * to the size of the key that is stored in the table and that is
2020  * associated with the current key.
2021  *
2022  * data_buf_p - Pointer which, if not NULL, will be set to the address
2023  * of the data storage that is allocated in the table and that is
2024  * associated with the current key.  If a (long) is stored as the data
2025  * (for example) then data_buf_p should be (long **) i.e. the address
2026  * of a (long *).
2027  *
2028  * data_size_p - Pointer to an integer which, if not NULL, will be set
2029  * to the size of the data that is stored in the table and that is
2030  * associated with the current key.
2031  */
2032 int table_this(table_t * table_p,
2033                void **key_buf_p, int *key_size_p,
2034                void **data_buf_p, int *data_size_p)
2035 {
2036     table_entry_t *entry_p = NULL;
2037     int entry_c;
2038
2039     if (table_p == NULL)
2040         return TABLE_ERROR_ARG_NULL;
2041     if (table_p->ta_magic != TABLE_MAGIC)
2042         return TABLE_ERROR_PNT;
2043     if (table_p->ta_linear.tl_magic != LINEAR_MAGIC)
2044         return TABLE_ERROR_LINEAR;
2045     /* if we removed an item that shorted the bucket list, we may get this */
2046     if (table_p->ta_linear.tl_bucket_c >= table_p->ta_bucket_n) {
2047         /*
2048          * NOTE: this might happen if we delete an item which shortens the
2049          * table bucket numbers.
2050          */
2051         return TABLE_ERROR_NOT_FOUND;
2052     }
2053
2054     /* find the entry which is the nth in the list */
2055     entry_p = table_p->ta_buckets[table_p->ta_linear.tl_bucket_c];
2056     /* NOTE: we swap the order here to be more efficient */
2057     for (entry_c = table_p->ta_linear.tl_entry_c; entry_c > 0; entry_c--) {
2058         /* did we reach the end of the list? */
2059         if (entry_p == NULL)
2060             break;
2061         entry_p = TABLE_POINTER(table_p, table_entry_t *, entry_p)->te_next_p;
2062     }
2063
2064     /* is this a NOT_FOUND or a LINEAR error */
2065     if (entry_p == NULL)
2066         return TABLE_ERROR_NOT_FOUND;
2067     if (key_buf_p != NULL)
2068         *key_buf_p = ENTRY_KEY_BUF(entry_p);
2069     if (key_size_p != NULL)
2070         *key_size_p = entry_p->te_key_size;
2071     if (data_buf_p != NULL) {
2072         if (entry_p->te_data_size == 0)
2073             *data_buf_p = NULL;
2074         else {
2075             if (table_p->ta_data_align == 0)
2076                 *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
2077             else
2078                 *data_buf_p = entry_data_buf(table_p, entry_p);
2079         }
2080     }
2081     if (data_size_p != NULL)
2082         *data_size_p = entry_p->te_data_size;
2083     return TABLE_ERROR_NONE;
2084 }
2085
2086 /*
2087  * int table_first_r
2088  *
2089  * DESCRIPTION:
2090  *
2091  * Reetrant version of the table_first routine above.  Find first
2092  * element in a table and pass back information about the key/data
2093  * pair.  If any of the key/data pointers are NULL then they are
2094  * ignored.
2095  *
2096  * RETURNS:
2097  *
2098  * Success - TABLE_ERROR_NONE
2099  *
2100  * Failure - Table error code.
2101  *
2102  * ARGUMENTS:
2103  *
2104  * table_p - Table structure pointer from which we are getting the
2105  * first element.
2106  *
2107  * linear_p - Pointer to a table linear structure which is initialized
2108  * here.  The same pointer should then be passed to table_next_r
2109  * below.
2110  *
2111  * key_buf_p - Pointer which, if not NULL, will be set to the address
2112  * of the storage of the first key that is allocated in the table.  If
2113  * an (int) is stored as the first key (for example) then key_buf_p
2114  * should be (int **) i.e. the address of a (int *).
2115  *
2116  * key_size_p - Pointer to an integer which, if not NULL, will be set
2117  * to the size of the key that is stored in the table and that is
2118  * associated with the first key.
2119  *
2120  * data_buf_p - Pointer which, if not NULL, will be set to the address
2121  * of the data storage that is allocated in the table and that is
2122  * associated with the first key.  If a (long) is stored as the data
2123  * (for example) then data_buf_p should be (long **) i.e. the address
2124  * of a (long *).
2125  *
2126  * data_size_p - Pointer to an integer which, if not NULL, will be set
2127  * to the size of the data that is stored in the table and that is
2128  * associated with the first key.
2129  */
2130 int table_first_r(table_t * table_p, table_linear_t * linear_p,
2131                   void **key_buf_p, int *key_size_p,
2132                   void **data_buf_p, int *data_size_p)
2133 {
2134     table_entry_t *entry_p;
2135
2136     if (table_p == NULL)
2137         return TABLE_ERROR_ARG_NULL;
2138     if (table_p->ta_magic != TABLE_MAGIC)
2139         return TABLE_ERROR_PNT;
2140     if (linear_p == NULL)
2141         return TABLE_ERROR_ARG_NULL;
2142     /* initialize our linear magic number */
2143     linear_p->tl_magic = LINEAR_MAGIC;
2144
2145     entry_p = first_entry(table_p, linear_p);
2146     if (entry_p == NULL)
2147         return TABLE_ERROR_NOT_FOUND;
2148     if (key_buf_p != NULL)
2149         *key_buf_p = ENTRY_KEY_BUF(entry_p);
2150     if (key_size_p != NULL)
2151         *key_size_p = entry_p->te_key_size;
2152     if (data_buf_p != NULL) {
2153         if (entry_p->te_data_size == 0)
2154             *data_buf_p = NULL;
2155         else {
2156             if (table_p->ta_data_align == 0)
2157                 *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
2158             else
2159                 *data_buf_p = entry_data_buf(table_p, entry_p);
2160         }
2161     }
2162     if (data_size_p != NULL)
2163         *data_size_p = entry_p->te_data_size;
2164     return TABLE_ERROR_NONE;
2165 }
2166
2167 /*
2168  * int table_next_r
2169  *
2170  * DESCRIPTION:
2171  *
2172  * Reetrant version of the table_next routine above.  Find next
2173  * element in a table and pass back information about the key/data
2174  * pair.  If any of the key/data pointers are NULL then they are
2175  * ignored.
2176  *
2177  * RETURNS:
2178  *
2179  * Success - TABLE_ERROR_NONE
2180  *
2181  * Failure - Table error code.
2182  *
2183  * ARGUMENTS:
2184  *
2185  * table_p - Table structure pointer from which we are getting the
2186  * next element.
2187  *
2188  * linear_p - Pointer to a table linear structure which is incremented
2189  * here.  The same pointer must have been passed to table_first_r
2190  * first so that it can be initialized.
2191  *
2192  * key_buf_p - Pointer which, if not NULL, will be set to the address
2193  * of the storage of the next key that is allocated in the table.  If
2194  * an (int) is stored as the next key (for example) then key_buf_p
2195  * should be (int **) i.e. the address of a (int *).
2196  *
2197  * key_size_p - Pointer to an integer which, if not NULL will be set
2198  * to the size of the key that is stored in the table and that is
2199  * associated with the next key.
2200  *
2201  * data_buf_p - Pointer which, if not NULL, will be set to the address
2202  * of the data storage that is allocated in the table and that is
2203  * associated with the next key.  If a (long) is stored as the data
2204  * (for example) then data_buf_p should be (long **) i.e. the address
2205  * of a (long *).
2206  *
2207  * data_size_p - Pointer to an integer which, if not NULL, will be set
2208  * to the size of the data that is stored in the table and that is
2209  * associated with the next key.
2210  */
2211 int table_next_r(table_t * table_p, table_linear_t * linear_p,
2212                  void **key_buf_p, int *key_size_p,
2213                  void **data_buf_p, int *data_size_p)
2214 {
2215     table_entry_t *entry_p;
2216     int error;
2217
2218     if (table_p == NULL)
2219         return TABLE_ERROR_ARG_NULL;
2220     if (table_p->ta_magic != TABLE_MAGIC)
2221         return TABLE_ERROR_PNT;
2222     if (linear_p == NULL)
2223         return TABLE_ERROR_ARG_NULL;
2224     if (linear_p->tl_magic != LINEAR_MAGIC)
2225         return TABLE_ERROR_LINEAR;
2226     /* move to the next entry */
2227     entry_p = next_entry(table_p, linear_p, &error);
2228     if (entry_p == NULL)
2229         return error;
2230     if (key_buf_p != NULL)
2231         *key_buf_p = ENTRY_KEY_BUF(entry_p);
2232     if (key_size_p != NULL)
2233         *key_size_p = entry_p->te_key_size;
2234     if (data_buf_p != NULL) {
2235         if (entry_p->te_data_size == 0)
2236             *data_buf_p = NULL;
2237         else {
2238             if (table_p->ta_data_align == 0)
2239                 *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
2240             else
2241                 *data_buf_p = entry_data_buf(table_p, entry_p);
2242         }
2243     }
2244     if (data_size_p != NULL)
2245         *data_size_p = entry_p->te_data_size;
2246     return TABLE_ERROR_NONE;
2247 }
2248
2249 /*
2250  * int table_this_r
2251  *
2252  * DESCRIPTION:
2253  *
2254  * Reetrant version of the table_this routine above.  Find current
2255  * element in a table and pass back information about the key/data
2256  * pair.  If any of the key/data pointers are NULL then they are
2257  * ignored.
2258  *
2259  * RETURNS:
2260  *
2261  * Success - TABLE_ERROR_NONE
2262  *
2263  * Failure - Table error code.
2264  *
2265  * ARGUMENTS:
2266  *
2267  * table_p - Table structure pointer from which we are getting the
2268  * current element.
2269  *
2270  * linear_p - Pointer to a table linear structure which is accessed
2271  * here.  The same pointer must have been passed to table_first_r
2272  * first so that it can be initialized.
2273  *
2274  * key_buf_p - Pointer which, if not NULL, will be set to the address
2275  * of the storage of the current key that is allocated in the table.
2276  * If an (int) is stored as the current key (for example) then
2277  * key_buf_p should be (int **) i.e. the address of a (int *).
2278  *
2279  * key_size_p - Pointer to an integer which, if not NULL, will be set
2280  * to the size of the key that is stored in the table and that is
2281  * associated with the current key.
2282  *
2283  * data_buf_p - Pointer which, if not NULL, will be set to the address
2284  * of the data storage that is allocated in the table and that is
2285  * associated with the current key.  If a (long) is stored as the data
2286  * (for example) then data_buf_p should be (long **) i.e. the address
2287  * of a (long *).
2288  *
2289  * data_size_p - Pointer to an integer which, if not NULL, will be set
2290  * to the size of the data that is stored in the table and that is
2291  * associated with the current key.
2292  */
2293 int table_this_r(table_t * table_p, table_linear_t * linear_p,
2294                  void **key_buf_p, int *key_size_p,
2295                  void **data_buf_p, int *data_size_p)
2296 {
2297     table_entry_t *entry_p;
2298     int entry_c;
2299
2300     if (table_p == NULL)
2301         return TABLE_ERROR_ARG_NULL;
2302     if (table_p->ta_magic != TABLE_MAGIC)
2303         return TABLE_ERROR_PNT;
2304     if (linear_p->tl_magic != LINEAR_MAGIC)
2305         return TABLE_ERROR_LINEAR;
2306     /* if we removed an item that shorted the bucket list, we may get this */
2307     if (linear_p->tl_bucket_c >= table_p->ta_bucket_n) {
2308         /*
2309          * NOTE: this might happen if we delete an item which shortens the
2310          * table bucket numbers.
2311          */
2312         return TABLE_ERROR_NOT_FOUND;
2313     }
2314
2315     /* find the entry which is the nth in the list */
2316     for (entry_c = linear_p->tl_entry_c,
2317          entry_p = table_p->ta_buckets[linear_p->tl_bucket_c];
2318          entry_p != NULL && entry_c > 0;
2319          entry_c--, entry_p = TABLE_POINTER(table_p, table_entry_t *,
2320                                             entry_p)->te_next_p) {
2321     }
2322
2323     if (entry_p == NULL)
2324         return TABLE_ERROR_NOT_FOUND;
2325     if (key_buf_p != NULL)
2326         *key_buf_p = ENTRY_KEY_BUF(entry_p);
2327     if (key_size_p != NULL)
2328         *key_size_p = entry_p->te_key_size;
2329     if (data_buf_p != NULL) {
2330         if (entry_p->te_data_size == 0)
2331             *data_buf_p = NULL;
2332         else {
2333             if (table_p->ta_data_align == 0)
2334                 *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
2335             else
2336                 *data_buf_p = entry_data_buf(table_p, entry_p);
2337         }
2338     }
2339     if (data_size_p != NULL)
2340         *data_size_p = entry_p->te_data_size;
2341     return TABLE_ERROR_NONE;
2342 }
2343
2344 /******************************** table order ********************************/
2345
2346 /*
2347  * table_entry_t *table_order
2348  *
2349  * DESCRIPTION:
2350  *
2351  * Order a table by building an array of table entry pointers and then
2352  * sorting this array using the qsort function.  To retrieve the
2353  * sorted entries, you can then use the table_entry routine to access
2354  * each entry in order.
2355  *
2356  * NOTE: This routine is now thread safe in that two table_order calls
2357  * can now happen at the same time, even on the same table.
2358  *
2359  * RETURNS:
2360  *
2361  * An allocated list of entry pointers which must be freed later.
2362  * Returns null on error.
2363  *
2364  * ARGUMENTS:
2365  *
2366  * table_p - Pointer to the table that we are ordering.
2367  *
2368  * compare - Comparison function defined by the user.  Its definition
2369  * is at the top of the table.h file.  If this is NULL then it will
2370  * order the table my memcmp-ing the keys.
2371  *
2372  * num_entries_p - Pointer to an integer which, if not NULL, will
2373  * contain the number of entries in the returned entry pointer array.
2374  *
2375  * error_p - Pointer to an integer which, if not NULL, will contain a
2376  * table error code.
2377  */
2378 table_entry_t **table_order(table_t * table_p, table_compare_t compare,
2379                             int *num_entries_p, int *error_p)
2380 {
2381     table_entry_t *entry_p, **entries, **entries_p;
2382     table_linear_t linear;
2383     compare_t comp_func;
2384     int error;
2385
2386     if (table_p == NULL) {
2387         if (error_p != NULL)
2388             *error_p = TABLE_ERROR_ARG_NULL;
2389         return NULL;
2390     }
2391     if (table_p->ta_magic != TABLE_MAGIC) {
2392         if (error_p != NULL)
2393             *error_p = TABLE_ERROR_PNT;
2394         return NULL;
2395     }
2396
2397     /* there must be at least 1 element in the table for this to work */
2398     if (table_p->ta_entry_n == 0) {
2399         if (error_p != NULL)
2400             *error_p = TABLE_ERROR_EMPTY;
2401         return NULL;
2402     }
2403
2404     entries = (table_entry_t **)
2405                table_p->ta_malloc(table_p->opt_param,
2406                                   table_p->ta_entry_n *sizeof(table_entry_t *));
2407     if (entries == NULL) {
2408         if (error_p != NULL)
2409             *error_p = TABLE_ERROR_ALLOC;
2410         return NULL;
2411     }
2412
2413     /* get a pointer to all entries */
2414     entry_p = first_entry(table_p, &linear);
2415     if (entry_p == NULL) {
2416         if (error_p != NULL)
2417             *error_p = TABLE_ERROR_NOT_FOUND;
2418         return NULL;
2419     }
2420
2421     /* add all of the entries to the array */
2422     for (entries_p = entries;
2423          entry_p != NULL;
2424          entry_p = next_entry(table_p, &linear, &error))
2425         *entries_p++ = entry_p;
2426     if (error != TABLE_ERROR_NOT_FOUND) {
2427         if (error_p != NULL)
2428             *error_p = error;
2429         return NULL;
2430     }
2431
2432     if (compare == NULL) {
2433         /* this is regardless of the alignment */
2434         comp_func = local_compare;
2435     }
2436     else if (table_p->ta_data_align == 0)
2437         comp_func = external_compare;
2438     else
2439         comp_func = external_compare_align;
2440     /* now qsort the entire entries array from first to last element */
2441     split(entries, entries + table_p->ta_entry_n - 1, comp_func, compare,
2442           table_p);
2443
2444     if (num_entries_p != NULL)
2445         *num_entries_p = table_p->ta_entry_n;
2446     if (error_p != NULL)
2447         *error_p = TABLE_ERROR_NONE;
2448     return entries;
2449 }
2450
2451 /*
2452  * int table_entry
2453  *
2454  * DESCRIPTION:
2455  *
2456  * Get information about an element.  The element is one from the
2457  * array returned by the table_order function.  If any of the key/data
2458  * pointers are NULL then they are ignored.
2459  *
2460  * RETURNS:
2461  *
2462  * Success - TABLE_ERROR_NONE
2463  *
2464  * Failure - Table error code.
2465  *
2466  * ARGUMENTS:
2467  *
2468  * table_p - Table structure pointer from which we are getting the
2469  * element.
2470  *
2471  * entry_p - Pointer to a table entry from the array returned by the
2472  * table_order function.
2473  *
2474  * key_buf_p - Pointer which, if not NULL, will be set to the address
2475  * of the storage of this entry that is allocated in the table.  If an
2476  * (int) is stored as this entry (for example) then key_buf_p should
2477  * be (int **) i.e. the address of a (int *).
2478  *
2479  * key_size_p - Pointer to an integer which, if not NULL, will be set
2480  * to the size of the key that is stored in the table.
2481  *
2482  * data_buf_p - Pointer which, if not NULL, will be set to the address
2483  * of the data storage of this entry that is allocated in the table.
2484  * If a (long) is stored as this entry data (for example) then
2485  * data_buf_p should be (long **) i.e. the address of a (long *).
2486  *
2487  * data_size_p - Pointer to an integer which, if not NULL, will be set
2488  * to the size of the data that is stored in the table.
2489  */
2490 int table_entry_info(table_t * table_p, table_entry_t * entry_p,
2491                 void **key_buf_p, int *key_size_p,
2492                 void **data_buf_p, int *data_size_p)
2493 {
2494     if (table_p == NULL)
2495         return TABLE_ERROR_ARG_NULL;
2496     if (table_p->ta_magic != TABLE_MAGIC)
2497         return TABLE_ERROR_PNT;
2498     if (entry_p == NULL)
2499         return TABLE_ERROR_ARG_NULL;
2500     if (key_buf_p != NULL)
2501         *key_buf_p = ENTRY_KEY_BUF(entry_p);
2502     if (key_size_p != NULL)
2503         *key_size_p = entry_p->te_key_size;
2504     if (data_buf_p != NULL) {
2505         if (entry_p->te_data_size == 0)
2506             *data_buf_p = NULL;
2507         else {
2508             if (table_p->ta_data_align == 0)
2509                 *data_buf_p = ENTRY_DATA_BUF(table_p, entry_p);
2510             else
2511                 *data_buf_p = entry_data_buf(table_p, entry_p);
2512         }
2513     }
2514     if (data_size_p != NULL)
2515         *data_size_p = entry_p->te_data_size;
2516     return TABLE_ERROR_NONE;
2517 }
2518