Annotation of embedaddon/php/ext/mbstring/oniguruma/st.c, revision 1.1.1.1

1.1       misho       1: /* This is a public domain general purpose hash table package written by Peter Moore @ UCB. */
                      2: 
                      3: /* static      char    sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */
                      4: 
                      5: #include "config.h"
                      6: #include <stdio.h>
                      7: #include <stdlib.h>
                      8: #include <string.h>
                      9: 
                     10: #ifdef _WIN32
                     11: #include <malloc.h>
                     12: #endif
                     13: 
                     14: #ifdef NOT_RUBY
                     15: #include "regint.h"
                     16: #else
                     17: #ifdef RUBY_PLATFORM
                     18: #define xmalloc ruby_xmalloc
                     19: #define xcalloc ruby_xcalloc
                     20: #define xrealloc ruby_xrealloc
                     21: #define xfree ruby_xfree
                     22: 
                     23: void *xmalloc(long);
                     24: void *xcalloc(long, long);
                     25: void *xrealloc(void *, long);
                     26: void xfree(void *);
                     27: #endif
                     28: #endif
                     29: 
                     30: #include "st.h"
                     31: 
                     32: typedef struct st_table_entry st_table_entry;
                     33: 
                     34: struct st_table_entry {
                     35:     unsigned int hash;
                     36:     st_data_t key;
                     37:     st_data_t record;
                     38:     st_table_entry *next;
                     39: };
                     40: 
                     41: #define ST_DEFAULT_MAX_DENSITY 5
                     42: #define ST_DEFAULT_INIT_TABLE_SIZE 11
                     43: 
                     44:     /*
                     45:      * DEFAULT_MAX_DENSITY is the default for the largest we allow the
                     46:      * average number of items per bin before increasing the number of
                     47:      * bins
                     48:      *
                     49:      * DEFAULT_INIT_TABLE_SIZE is the default for the number of bins
                     50:      * allocated initially
                     51:      *
                     52:      */
                     53: 
                     54: static int numcmp(long, long);
                     55: static int numhash(long);
                     56: static struct st_hash_type type_numhash = {
                     57:     numcmp,
                     58:     numhash,
                     59: };
                     60: 
                     61: /* extern int strcmp(const char *, const char *); */
                     62: static int strhash(const char *);
                     63: static struct st_hash_type type_strhash = {
                     64:     strcmp,
                     65:     strhash,
                     66: };
                     67: 
                     68: static void rehash(st_table *);
                     69: 
                     70: #define alloc(type) (type*)xmalloc((unsigned)sizeof(type))
                     71: #define Calloc(n,s) (char*)xcalloc((n),(s))
                     72: 
                     73: #define EQUAL(table,x,y) ((x)==(y) || (*table->type->compare)((x),(y)) == 0)
                     74: 
                     75: #define do_hash(key,table) (unsigned int)(*(table)->type->hash)((key))
                     76: #define do_hash_bin(key,table) (do_hash(key, table)%(table)->num_bins)
                     77: 
                     78: /*
                     79:  * MINSIZE is the minimum size of a dictionary.
                     80:  */
                     81: 
                     82: #define MINSIZE 8
                     83: 
                     84: /*
                     85: Table of prime numbers 2^n+a, 2<=n<=30.
                     86: */
                     87: static const long primes[] = {
                     88:        8 + 3,
                     89:        16 + 3,
                     90:        32 + 5,
                     91:        64 + 3,
                     92:        128 + 3,
                     93:        256 + 27,
                     94:        512 + 9,
                     95:        1024 + 9,
                     96:        2048 + 5,
                     97:        4096 + 3,
                     98:        8192 + 27,
                     99:        16384 + 43,
                    100:        32768 + 3,
                    101:        65536 + 45,
                    102:        131072 + 29,
                    103:        262144 + 3,
                    104:        524288 + 21,
                    105:        1048576 + 7,
                    106:        2097152 + 17,
                    107:        4194304 + 15,
                    108:        8388608 + 9,
                    109:        16777216 + 43,
                    110:        33554432 + 35,
                    111:        67108864 + 15,
                    112:        134217728 + 29,
                    113:        268435456 + 3,
                    114:        536870912 + 11,
                    115:        1073741824 + 85,
                    116:        0
                    117: };
                    118: 
                    119: static int
                    120: new_size(size)
                    121:     int size;
                    122: {
                    123:     int i;
                    124: 
                    125: #if 0
                    126:     for (i=3; i<31; i++) {
                    127:        if ((1<<i) > size) return 1<<i;
                    128:     }
                    129:     return -1;
                    130: #else
                    131:     int newsize;
                    132: 
                    133:     for (i = 0, newsize = MINSIZE;
                    134:         i < (int )(sizeof(primes)/sizeof(primes[0]));
                    135:         i++, newsize <<= 1)
                    136:     {
                    137:        if (newsize > size) return primes[i];
                    138:     }
                    139:     /* Ran out of polynomials */
                    140:     return -1;                 /* should raise exception */
                    141: #endif
                    142: }
                    143: 
                    144: #ifdef HASH_LOG
                    145: static int collision = 0;
                    146: static int init_st = 0;
                    147: 
                    148: static void
                    149: stat_col()
                    150: {
                    151:     FILE *f = fopen("/tmp/col", "w");
                    152:     fprintf(f, "collision: %d\n", collision);
                    153:     fclose(f);
                    154: }
                    155: #endif
                    156: 
                    157: st_table*
                    158: st_init_table_with_size(type, size)
                    159:     struct st_hash_type *type;
                    160:     int size;
                    161: {
                    162:     st_table *tbl;
                    163: 
                    164: #ifdef HASH_LOG
                    165:     if (init_st == 0) {
                    166:        init_st = 1;
                    167:        atexit(stat_col);
                    168:     }
                    169: #endif
                    170: 
                    171:     size = new_size(size);     /* round up to prime number */
                    172: 
                    173:     tbl = alloc(st_table);
                    174:     tbl->type = type;
                    175:     tbl->num_entries = 0;
                    176:     tbl->num_bins = size;
                    177:     tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*));
                    178: 
                    179:     return tbl;
                    180: }
                    181: 
                    182: st_table*
                    183: st_init_table(type)
                    184:     struct st_hash_type *type;
                    185: {
                    186:     return st_init_table_with_size(type, 0);
                    187: }
                    188: 
                    189: st_table*
                    190: st_init_numtable(void)
                    191: {
                    192:     return st_init_table(&type_numhash);
                    193: }
                    194: 
                    195: st_table*
                    196: st_init_numtable_with_size(size)
                    197:     int size;
                    198: {
                    199:     return st_init_table_with_size(&type_numhash, size);
                    200: }
                    201: 
                    202: st_table*
                    203: st_init_strtable(void)
                    204: {
                    205:     return st_init_table(&type_strhash);
                    206: }
                    207: 
                    208: st_table*
                    209: st_init_strtable_with_size(size)
                    210:     int size;
                    211: {
                    212:     return st_init_table_with_size(&type_strhash, size);
                    213: }
                    214: 
                    215: void
                    216: st_free_table(table)
                    217:     st_table *table;
                    218: {
                    219:     register st_table_entry *ptr, *next;
                    220:     int i;
                    221: 
                    222:     for(i = 0; i < table->num_bins; i++) {
                    223:        ptr = table->bins[i];
                    224:        while (ptr != 0) {
                    225:            next = ptr->next;
                    226:            free(ptr);
                    227:            ptr = next;
                    228:        }
                    229:     }
                    230:     free(table->bins);
                    231:     free(table);
                    232: }
                    233: 
                    234: #define PTR_NOT_EQUAL(table, ptr, hash_val, key) \
                    235: ((ptr) != 0 && (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key)))
                    236: 
                    237: #ifdef HASH_LOG
                    238: #define COLLISION collision++
                    239: #else
                    240: #define COLLISION
                    241: #endif
                    242: 
                    243: #define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\
                    244:     bin_pos = hash_val%(table)->num_bins;\
                    245:     ptr = (table)->bins[bin_pos];\
                    246:     if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) {\
                    247:        COLLISION;\
                    248:        while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\
                    249:            ptr = ptr->next;\
                    250:        }\
                    251:        ptr = ptr->next;\
                    252:     }\
                    253: } while (0)
                    254: 
                    255: int
                    256: st_lookup(table, key, value)
                    257:     st_table *table;
                    258:     register st_data_t key;
                    259:     st_data_t *value;
                    260: {
                    261:     unsigned int hash_val, bin_pos;
                    262:     register st_table_entry *ptr;
                    263: 
                    264:     hash_val = do_hash(key, table);
                    265:     FIND_ENTRY(table, ptr, hash_val, bin_pos);
                    266: 
                    267:     if (ptr == 0) {
                    268:        return 0;
                    269:     }
                    270:     else {
                    271:        if (value != 0)  *value = ptr->record;
                    272:        return 1;
                    273:     }
                    274: }
                    275: 
                    276: #define ADD_DIRECT(table, key, value, hash_val, bin_pos)\
                    277: do {\
                    278:     st_table_entry *entry;\
                    279:     if (table->num_entries/(table->num_bins) > ST_DEFAULT_MAX_DENSITY) {\
                    280:        rehash(table);\
                    281:         bin_pos = hash_val % table->num_bins;\
                    282:     }\
                    283:     \
                    284:     entry = alloc(st_table_entry);\
                    285:     \
                    286:     entry->hash = hash_val;\
                    287:     entry->key = key;\
                    288:     entry->record = value;\
                    289:     entry->next = table->bins[bin_pos];\
                    290:     table->bins[bin_pos] = entry;\
                    291:     table->num_entries++;\
                    292: } while (0)
                    293: 
                    294: int
                    295: st_insert(table, key, value)
                    296:     register st_table *table;
                    297:     register st_data_t key;
                    298:     st_data_t value;
                    299: {
                    300:     unsigned int hash_val, bin_pos;
                    301:     register st_table_entry *ptr;
                    302: 
                    303:     hash_val = do_hash(key, table);
                    304:     FIND_ENTRY(table, ptr, hash_val, bin_pos);
                    305: 
                    306:     if (ptr == 0) {
                    307:        ADD_DIRECT(table, key, value, hash_val, bin_pos);
                    308:        return 0;
                    309:     }
                    310:     else {
                    311:        ptr->record = value;
                    312:        return 1;
                    313:     }
                    314: }
                    315: 
                    316: void
                    317: st_add_direct(table, key, value)
                    318:     st_table *table;
                    319:     st_data_t key;
                    320:     st_data_t value;
                    321: {
                    322:     unsigned int hash_val, bin_pos;
                    323: 
                    324:     hash_val = do_hash(key, table);
                    325:     bin_pos = hash_val % table->num_bins;
                    326:     ADD_DIRECT(table, key, value, hash_val, bin_pos);
                    327: }
                    328: 
                    329: static void
                    330: rehash(table)
                    331:     register st_table *table;
                    332: {
                    333:     register st_table_entry *ptr, *next, **new_bins;
                    334:     int i, old_num_bins = table->num_bins, new_num_bins;
                    335:     unsigned int hash_val;
                    336: 
                    337:     new_num_bins = new_size(old_num_bins+1);
                    338:     new_bins = (st_table_entry**)Calloc(new_num_bins, sizeof(st_table_entry*));
                    339: 
                    340:     for(i = 0; i < old_num_bins; i++) {
                    341:        ptr = table->bins[i];
                    342:        while (ptr != 0) {
                    343:            next = ptr->next;
                    344:            hash_val = ptr->hash % new_num_bins;
                    345:            ptr->next = new_bins[hash_val];
                    346:            new_bins[hash_val] = ptr;
                    347:            ptr = next;
                    348:        }
                    349:     }
                    350:     free(table->bins);
                    351:     table->num_bins = new_num_bins;
                    352:     table->bins = new_bins;
                    353: }
                    354: 
                    355: st_table*
                    356: st_copy(old_table)
                    357:     st_table *old_table;
                    358: {
                    359:     st_table *new_table;
                    360:     st_table_entry *ptr, *entry;
                    361:     int i, num_bins = old_table->num_bins;
                    362: 
                    363:     new_table = alloc(st_table);
                    364:     if (new_table == 0) {
                    365:        return 0;
                    366:     }
                    367: 
                    368:     *new_table = *old_table;
                    369:     new_table->bins = (st_table_entry**)
                    370:        Calloc((unsigned)num_bins, sizeof(st_table_entry*));
                    371: 
                    372:     if (new_table->bins == 0) {
                    373:        free(new_table);
                    374:        return 0;
                    375:     }
                    376: 
                    377:     for(i = 0; i < num_bins; i++) {
                    378:        new_table->bins[i] = 0;
                    379:        ptr = old_table->bins[i];
                    380:        while (ptr != 0) {
                    381:            entry = alloc(st_table_entry);
                    382:            if (entry == 0) {
                    383:                free(new_table->bins);
                    384:                free(new_table);
                    385:                return 0;
                    386:            }
                    387:            *entry = *ptr;
                    388:            entry->next = new_table->bins[i];
                    389:            new_table->bins[i] = entry;
                    390:            ptr = ptr->next;
                    391:        }
                    392:     }
                    393:     return new_table;
                    394: }
                    395: 
                    396: int
                    397: st_delete(table, key, value)
                    398:     register st_table *table;
                    399:     register st_data_t *key;
                    400:     st_data_t *value;
                    401: {
                    402:     unsigned int hash_val;
                    403:     st_table_entry *tmp;
                    404:     register st_table_entry *ptr;
                    405: 
                    406:     hash_val = do_hash_bin(*key, table);
                    407:     ptr = table->bins[hash_val];
                    408: 
                    409:     if (ptr == 0) {
                    410:        if (value != 0) *value = 0;
                    411:        return 0;
                    412:     }
                    413: 
                    414:     if (EQUAL(table, *key, ptr->key)) {
                    415:        table->bins[hash_val] = ptr->next;
                    416:        table->num_entries--;
                    417:        if (value != 0) *value = ptr->record;
                    418:        *key = ptr->key;
                    419:        free(ptr);
                    420:        return 1;
                    421:     }
                    422: 
                    423:     for(; ptr->next != 0; ptr = ptr->next) {
                    424:        if (EQUAL(table, ptr->next->key, *key)) {
                    425:            tmp = ptr->next;
                    426:            ptr->next = ptr->next->next;
                    427:            table->num_entries--;
                    428:            if (value != 0) *value = tmp->record;
                    429:            *key = tmp->key;
                    430:            free(tmp);
                    431:            return 1;
                    432:        }
                    433:     }
                    434: 
                    435:     return 0;
                    436: }
                    437: 
                    438: int
                    439: st_delete_safe(table, key, value, never)
                    440:     register st_table *table;
                    441:     register st_data_t *key;
                    442:     st_data_t *value;
                    443:     st_data_t never;
                    444: {
                    445:     unsigned int hash_val;
                    446:     register st_table_entry *ptr;
                    447: 
                    448:     hash_val = do_hash_bin(*key, table);
                    449:     ptr = table->bins[hash_val];
                    450: 
                    451:     if (ptr == 0) {
                    452:        if (value != 0) *value = 0;
                    453:        return 0;
                    454:     }
                    455: 
                    456:     for(; ptr != 0; ptr = ptr->next) {
                    457:        if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) {
                    458:            table->num_entries--;
                    459:            *key = ptr->key;
                    460:            if (value != 0) *value = ptr->record;
                    461:            ptr->key = ptr->record = never;
                    462:            return 1;
                    463:        }
                    464:     }
                    465: 
                    466:     return 0;
                    467: }
                    468: 
                    469: static int
                    470: delete_never(key, value, never)
                    471:     st_data_t key, value, never;
                    472: {
                    473:     if (value == never) return ST_DELETE;
                    474:     return ST_CONTINUE;
                    475: }
                    476: 
                    477: void
                    478: st_cleanup_safe(table, never)
                    479:     st_table *table;
                    480:     st_data_t never;
                    481: {
                    482:     int num_entries = table->num_entries;
                    483: 
                    484:     st_foreach(table, delete_never, never);
                    485:     table->num_entries = num_entries;
                    486: }
                    487: 
                    488: int
                    489: st_foreach(table, func, arg)
                    490:     st_table *table;
                    491:     int (*func)();
                    492:     st_data_t arg;
                    493: {
                    494:     st_table_entry *ptr, *last, *tmp;
                    495:     enum st_retval retval;
                    496:     int i;
                    497: 
                    498:     for(i = 0; i < table->num_bins; i++) {
                    499:        last = 0;
                    500:        for(ptr = table->bins[i]; ptr != 0;) {
                    501:            retval = (*func)(ptr->key, ptr->record, arg);
                    502:            switch (retval) {
                    503:            case ST_CHECK:      /* check if hash is modified during iteration */
                    504:                tmp = 0;
                    505:                if (i < table->num_bins) {
                    506:                    for (tmp = table->bins[i]; tmp; tmp=tmp->next) {
                    507:                        if (tmp == ptr) break;
                    508:                    }
                    509:                }
                    510:                if (!tmp) {
                    511:                    /* call func with error notice */
                    512:                    return 1;
                    513:                }
                    514:                /* fall through */
                    515:            case ST_CONTINUE:
                    516:                last = ptr;
                    517:                ptr = ptr->next;
                    518:                break;
                    519:            case ST_STOP:
                    520:                return 0;
                    521:            case ST_DELETE:
                    522:                tmp = ptr;
                    523:                if (last == 0) {
                    524:                    table->bins[i] = ptr->next;
                    525:                }
                    526:                else {
                    527:                    last->next = ptr->next;
                    528:                }
                    529:                ptr = ptr->next;
                    530:                free(tmp);
                    531:                table->num_entries--;
                    532:            }
                    533:        }
                    534:     }
                    535:     return 0;
                    536: }
                    537: 
                    538: static int
                    539: strhash(string)
                    540:     register const char *string;
                    541: {
                    542:     register int c;
                    543: 
                    544: #ifdef HASH_ELFHASH
                    545:     register unsigned int h = 0, g;
                    546: 
                    547:     while ((c = *string++) != '\0') {
                    548:        h = ( h << 4 ) + c;
                    549:        if ( g = h & 0xF0000000 )
                    550:            h ^= g >> 24;
                    551:        h &= ~g;
                    552:     }
                    553:     return h;
                    554: #elif HASH_PERL
                    555:     register int val = 0;
                    556: 
                    557:     while ((c = *string++) != '\0') {
                    558:        val += c;
                    559:        val += (val << 10);
                    560:        val ^= (val >> 6);
                    561:     }
                    562:     val += (val << 3);
                    563:     val ^= (val >> 11);
                    564: 
                    565:     return val + (val << 15);
                    566: #else
                    567:     register int val = 0;
                    568: 
                    569:     while ((c = *string++) != '\0') {
                    570:        val = val*997 + c;
                    571:     }
                    572: 
                    573:     return val + (val>>5);
                    574: #endif
                    575: }
                    576: 
                    577: static int
                    578: numcmp(x, y)
                    579:     long x, y;
                    580: {
                    581:     return x != y;
                    582: }
                    583: 
                    584: static int
                    585: numhash(n)
                    586:     long n;
                    587: {
                    588:     return n;
                    589: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>