Imported Upstream version 0.6.35
[platform/upstream/libsolv.git] / src / strpool.c
index 79e450b..5e87918 100644 (file)
@@ -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);
 }