Annotation of embedaddon/php/ext/mbstring/oniguruma/st.c, revision 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>