X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fstrpool.c;h=5e8791830d94457e03b7f62648dbb419059ecae9;hb=e679b515eddb3dd340fb25620de0160211f40fdc;hp=79e450b4e53c0c73a600071b90a53ad311b4d28a;hpb=2d1563de904b41b6ba4ec625db60509a0e276b2e;p=platform%2Fupstream%2Flibsolv.git diff --git a/src/strpool.c b/src/strpool.c index 79e450b..5e87918 100644 --- a/src/strpool.c +++ b/src/strpool.c @@ -19,15 +19,15 @@ stringpool_init(Stringpool *ss, const char *strs[]) unsigned count; memset(ss, 0, sizeof(*ss)); - // count number and total size of predefined strings + /* count number and total size of predefined strings */ for (count = 0; strs[count]; count++) totalsize += strlen(strs[count]) + 1; - // alloc appropriate space - ss->stringspace = sat_extend_resize(0, totalsize, 1, STRINGSPACE_BLOCK); - ss->strings = sat_extend_resize(0, count, sizeof(Offset), STRING_BLOCK); + /* alloc appropriate space */ + ss->stringspace = solv_extend_resize(0, totalsize, 1, STRINGSPACE_BLOCK); + ss->strings = solv_extend_resize(0, count, sizeof(Offset), STRING_BLOCK); - // now copy predefined strings into allocated space + /* now copy predefined strings into allocated space */ ss->sstrings = 0; for (count = 0; strs[count]; count++) { @@ -39,6 +39,21 @@ stringpool_init(Stringpool *ss, const char *strs[]) } void +stringpool_free(Stringpool *ss) +{ + solv_free(ss->strings); + solv_free(ss->stringspace); + solv_free(ss->stringhashtbl); +} + +void +stringpool_freehash(Stringpool *ss) +{ + ss->stringhashtbl = solv_free(ss->stringhashtbl); + ss->stringhashmask = 0; +} + +void stringpool_init_empty(Stringpool *ss) { const char *emptystrs[] = { @@ -53,106 +68,115 @@ void stringpool_clone(Stringpool *ss, Stringpool *from) { memset(ss, 0, sizeof(*ss)); - ss->strings = sat_extend_resize(0, from->nstrings, sizeof(Offset), STRING_BLOCK); + ss->strings = solv_extend_resize(0, from->nstrings, sizeof(Offset), STRING_BLOCK); memcpy(ss->strings, from->strings, from->nstrings * sizeof(Offset)); - ss->stringspace = sat_extend_resize(0, from->sstrings, 1, STRINGSPACE_BLOCK); + ss->stringspace = solv_extend_resize(0, from->sstrings, 1, STRINGSPACE_BLOCK); memcpy(ss->stringspace, from->stringspace, from->sstrings); ss->nstrings = from->nstrings; ss->sstrings = from->sstrings; } +void +stringpool_resize_hash(Stringpool *ss, int numnew) +{ + Hashval h, hh, hashmask; + Hashtable hashtbl; + int i; + + if (numnew <= 0) + return; + hashmask = mkmask(ss->nstrings + numnew); + if (hashmask <= ss->stringhashmask) + return; /* same as before */ + + /* realloc hash table */ + ss->stringhashmask = hashmask; + solv_free(ss->stringhashtbl); + ss->stringhashtbl = hashtbl = (Hashtable)solv_calloc(hashmask + 1, sizeof(Id)); + + /* rehash all strings into new hashtable */ + for (i = 1; i < ss->nstrings; i++) + { + h = strhash(ss->stringspace + ss->strings[i]) & hashmask; + hh = HASHCHAIN_START; + while (hashtbl[h] != 0) + h = HASHCHAIN_NEXT(h, hh, hashmask); + hashtbl[h] = i; + } +} + Id -stringpool_strn2id (Stringpool *ss, const char *str, unsigned len, int create) +stringpool_strn2id(Stringpool *ss, const char *str, unsigned int len, int create) { - Hashval h; - unsigned int hh; - Hashmask hashmask; - int i, space_needed; + Hashval h, hh, hashmask, oldhashmask; Id id; Hashtable hashtbl; - // check string if (!str) return STRID_NULL; - if (!*str) + if (!len) return STRID_EMPTY; - hashmask = ss->stringhashmask; - hashtbl = ss->stringhashtbl; - - // expand hashtable if needed - // - // - if (ss->nstrings * 2 > hashmask) + hashmask = oldhashmask = ss->stringhashmask; + /* expand hashtable if needed */ + if ((Hashval)ss->nstrings * 2 > hashmask) { - sat_free(hashtbl); - - // realloc hash table - ss->stringhashmask = hashmask = mkmask(ss->nstrings + STRING_BLOCK); - ss->stringhashtbl = hashtbl = (Hashtable)sat_calloc(hashmask + 1, sizeof(Id)); - - // rehash all strings into new hashtable - for (i = 1; i < ss->nstrings; i++) - { - h = strhash(ss->stringspace + ss->strings[i]) & hashmask; - hh = HASHCHAIN_START; - while (hashtbl[h] != 0) // follow overflow chain - h = HASHCHAIN_NEXT(h, hh, hashmask); - hashtbl[h] = i; - } + stringpool_resize_hash(ss, STRING_BLOCK); + hashmask = ss->stringhashmask; } + hashtbl = ss->stringhashtbl; - // compute hash and check for match - + /* compute hash and check for match */ h = strnhash(str, len) & hashmask; hh = HASHCHAIN_START; - while ((id = hashtbl[h]) != 0) // follow hash overflow chain + while ((id = hashtbl[h]) != 0) { - // break if string already hashed if(!memcmp(ss->stringspace + ss->strings[id], str, len) && ss->stringspace[ss->strings[id] + len] == 0) break; h = HASHCHAIN_NEXT(h, hh, hashmask); } - if (id || !create) // exit here if string found + if (id || !create) /* exit here if string found */ return id; - // generate next id and save in table + /* this should be a test for a flag that tells us if the + * correct blocking is used, but adding a flag would break + * the ABI. So we use the existance of the hash area as + * indication instead */ + if (!oldhashmask) + { + ss->stringspace = solv_extend_resize(ss->stringspace, ss->sstrings + len + 1, 1, STRINGSPACE_BLOCK); + ss->strings = solv_extend_resize(ss->strings, ss->nstrings + 1, sizeof(Offset), STRING_BLOCK); + } + + /* generate next id and save in table */ id = ss->nstrings++; hashtbl[h] = id; - ss->strings = sat_extend(ss->strings, id, 1, sizeof(Offset), STRING_BLOCK); - // 'pointer' into stringspace is Offset of next free pos: sstrings - ss->strings[id] = ss->sstrings; - - space_needed = len + 1; - // make room in string buffer - ss->stringspace = sat_extend(ss->stringspace, ss->sstrings, space_needed, 1, STRINGSPACE_BLOCK); - // copy new string into buffer - memcpy(ss->stringspace + ss->sstrings, str, space_needed - 1); - // add the sentinel, we can't rely on it being in the source string (in - // case the LEN is not really strlen(str)) - ss->stringspace[ss->sstrings + space_needed - 1] = 0; - // next free pos is behind new string - ss->sstrings += space_needed; + ss->strings = solv_extend(ss->strings, id, 1, sizeof(Offset), STRING_BLOCK); + ss->strings[id] = ss->sstrings; /* we will append to the end */ + /* append string to stringspace */ + ss->stringspace = solv_extend(ss->stringspace, ss->sstrings, len + 1, 1, STRINGSPACE_BLOCK); + memcpy(ss->stringspace + ss->sstrings, str, len); + ss->stringspace[ss->sstrings + len] = 0; + ss->sstrings += len + 1; return id; } Id -stringpool_str2id (Stringpool *ss, const char *str, int create) +stringpool_str2id(Stringpool *ss, const char *str, int create) { - if ( !str ) + if (!str) return STRID_NULL; - if ( !*str ) + if (!*str) return STRID_EMPTY; - unsigned len = strlen (str); - return stringpool_strn2id (ss, str, len, create); + return stringpool_strn2id(ss, str, (unsigned int)strlen(str), create); } void -stringpool_shrink (Stringpool *ss) +stringpool_shrink(Stringpool *ss) { - ss->stringspace = sat_extend_resize(ss->stringspace, ss->sstrings, 1, STRINGSPACE_BLOCK); - ss->strings = sat_extend_resize(ss->strings, ss->nstrings, sizeof(Offset), STRING_BLOCK); + ss->stringspace = solv_extend_resize(ss->stringspace, ss->sstrings, 1, STRINGSPACE_BLOCK); + ss->strings = solv_extend_resize(ss->strings, ss->nstrings, sizeof(Offset), STRING_BLOCK); }