]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - lib/hashtable.c
merged current version of git://git.denx.de/u-boot
[karo-tx-uboot.git] / lib / hashtable.c
index 57802cfb6ded27e14490e601c1cc081d0829a368..abd61c891861ee6c2c011beaac051c645e1222e6 100644 (file)
@@ -32,6 +32,7 @@
 #ifdef USE_HOSTCC              /* HOST build */
 # include <string.h>
 # include <assert.h>
+# include <ctype.h>
 
 # ifndef debug
 #  ifdef DEBUG
@@ -43,6 +44,7 @@
 #else                          /* U-Boot build */
 # include <common.h>
 # include <linux/string.h>
+# include <linux/ctype.h>
 #endif
 
 #ifndef        CONFIG_ENV_MIN_ENTRIES  /* minimum number of entries */
 
 /*
  * [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
- * [Knuth]            The Art of Computer Programming, part 3 (6.4)
+ * [Knuth]           The Art of Computer Programming, part 3 (6.4)
  */
 
-/*
- * The non-reentrant version use a global space for storing the hash table.
- */
-static struct hsearch_data htab;
-
 /*
  * The reentrant version has no static variables to maintain the state.
  * Instead the interface of all functions is extended to take an argument
  * which describes the current status.
  */
 typedef struct _ENTRY {
-       unsigned int used;
+       int used;
        ENTRY entry;
 } _ENTRY;
 
@@ -97,11 +94,6 @@ static int isprime(unsigned int number)
        return number % div != 0;
 }
 
-int hcreate(size_t nel)
-{
-       return hcreate_r(nel, &htab);
-}
-
 /*
  * Before using the hash table we must allocate memory for it.
  * Test for an existing table are done. We allocate one element
@@ -110,6 +102,7 @@ int hcreate(size_t nel)
  * The contents of the table is zeroed, especially the field used
  * becomes zero.
  */
+
 int hcreate_r(size_t nel, struct hsearch_data *htab)
 {
        /* Test for correct arguments.  */
@@ -143,15 +136,12 @@ int hcreate_r(size_t nel, struct hsearch_data *htab)
 /*
  * hdestroy()
  */
-void hdestroy(void)
-{
-       hdestroy_r(&htab);
-}
 
 /*
  * After using the hash table it has to be destroyed. The used memory can
  * be freed and the local static variable can be marked as not used.
  */
+
 void hdestroy_r(struct hsearch_data *htab)
 {
        int i;
@@ -164,10 +154,10 @@ void hdestroy_r(struct hsearch_data *htab)
 
        /* free used memory */
        for (i = 1; i <= htab->size; ++i) {
-               if (htab->table[i].used) {
+               if (htab->table[i].used > 0) {
                        ENTRY *ep = &htab->table[i].entry;
 
-                       free(ep->key);
+                       free((void *)ep->key);
                        free(ep->data);
                }
        }
@@ -214,13 +204,47 @@ void hdestroy_r(struct hsearch_data *htab)
  *   example for functions like hdelete().
  */
 
-ENTRY *hsearch(ENTRY item, ACTION action)
+/*
+ * hstrstr_r - return index to entry whose key and/or data contains match
+ */
+int hstrstr_r(const char *match, int last_idx, ENTRY ** retval,
+             struct hsearch_data *htab)
+{
+       unsigned int idx;
+
+       for (idx = last_idx + 1; idx < htab->size; ++idx) {
+               if (htab->table[idx].used <= 0)
+                       continue;
+               if (strstr(htab->table[idx].entry.key, match) ||
+                   strstr(htab->table[idx].entry.data, match)) {
+                       *retval = &htab->table[idx].entry;
+                       return idx;
+               }
+       }
+
+       __set_errno(ESRCH);
+       *retval = NULL;
+       return 0;
+}
+
+int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
+            struct hsearch_data *htab)
 {
-       ENTRY *result;
+       unsigned int idx;
+       size_t key_len = strlen(match);
 
-       (void) hsearch_r(item, action, &result, &htab);
+       for (idx = last_idx + 1; idx < htab->size; ++idx) {
+               if (htab->table[idx].used <= 0)
+                       continue;
+               if (!strncmp(match, htab->table[idx].entry.key, key_len)) {
+                       *retval = &htab->table[idx].entry;
+                       return idx;
+               }
+       }
 
-       return result;
+       __set_errno(ESRCH);
+       *retval = NULL;
+       return 0;
 }
 
 int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
@@ -230,6 +254,7 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
        unsigned int count;
        unsigned int len = strlen(item.key);
        unsigned int idx;
+       unsigned int first_deleted = 0;
 
        /* Compute an value for the given string. Perhaps use a better method. */
        hval = len;
@@ -252,11 +277,15 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
 
        if (htab->table[idx].used) {
                /*
-                 * Further action might be required according to the
+                * Further action might be required according to the
                 * action value.
                 */
                unsigned hval2;
 
+               if (htab->table[idx].used == -1
+                   && !first_deleted)
+                       first_deleted = idx;
+
                if (htab->table[idx].used == hval
                    && strcmp(item.key, htab->table[idx].entry.key) == 0) {
                        /* Overwrite existing value? */
@@ -283,8 +312,8 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
 
                do {
                        /*
-                         * Because SIZE is prime this guarantees to
-                         * step through all available indices.
+                        * Because SIZE is prime this guarantees to
+                        * step through all available indices.
                         */
                        if (idx <= hval2)
                                idx = htab->size + idx - hval2;
@@ -323,8 +352,8 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
        /* An empty bucket has been found. */
        if (action == ENTER) {
                /*
-                 * If table is full and another entry should be
-                 * entered return with error.
+                * If table is full and another entry should be
+                * entered return with error.
                 */
                if (htab->filled == htab->size) {
                        __set_errno(ENOMEM);
@@ -336,6 +365,9 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
                 * Create new entry;
                 * create copies of item.key and item.data
                 */
+               if (first_deleted)
+                       idx = first_deleted;
+
                htab->table[idx].used = hval;
                htab->table[idx].entry.key = strdup(item.key);
                htab->table[idx].entry.data = strdup(item.data);
@@ -369,11 +401,6 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
  * do that.
  */
 
-int hdelete(const char *key)
-{
-       return hdelete_r(key, &htab);
-}
-
 int hdelete_r(const char *key, struct hsearch_data *htab)
 {
        ENTRY e, *ep;
@@ -391,9 +418,9 @@ int hdelete_r(const char *key, struct hsearch_data *htab)
        /* free used ENTRY */
        debug("hdelete: DELETING key \"%s\"\n", key);
 
-       free(ep->key);
+       free((void *)ep->key);
        free(ep->data);
-       htab->table[idx].used = 0;
+       htab->table[idx].used = -1;
 
        --htab->filled;
 
@@ -442,11 +469,6 @@ int hdelete_r(const char *key, struct hsearch_data *htab)
  *             bytes in the string will be '\0'-padded.
  */
 
-ssize_t hexport(const char sep, char **resp, size_t size)
-{
-       return hexport_r(&htab, sep, resp, size);
-}
-
 static int cmpkey(const void *p1, const void *p2)
 {
        ENTRY *e1 = *(ENTRY **) p1;
@@ -456,7 +478,8 @@ static int cmpkey(const void *p1, const void *p2)
 }
 
 ssize_t hexport_r(struct hsearch_data *htab, const char sep,
-                char **resp, size_t size)
+                char **resp, size_t size,
+                int argc, char * const argv[])
 {
        ENTRY *list[htab->size];
        char *res, *p;
@@ -469,8 +492,8 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
                return (-1);
        }
 
-       debug("EXPORT  table = %p, htab.size = %d, htab.filled = %d, size = %d\n",
-               htab, htab->size, htab->filled, size);
+       debug("EXPORT  table = %p, htab.size = %d, htab.filled = %d, "
+               "size = %zu\n", htab, htab->size, htab->filled, size);
        /*
         * Pass 1:
         * search used entries,
@@ -478,8 +501,18 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
         */
        for (i = 1, n = 0, totlen = 0; i <= htab->size; ++i) {
 
-               if (htab->table[i].used) {
+               if (htab->table[i].used > 0) {
                        ENTRY *ep = &htab->table[i].entry;
+                       int arg, found = 0;
+
+                       for (arg = 0; arg < argc; ++arg) {
+                               if (strcmp(argv[arg], ep->key) == 0) {
+                                       found = 1;
+                                       break;
+                               }
+                       }
+                       if ((argc > 0) && (found == 0))
+                               continue;
 
                        list[n++] = ep;
 
@@ -517,8 +550,8 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
        /* Check if the user supplied buffer size is sufficient */
        if (size) {
                if (size < totlen + 1) {        /* provided buffer too small */
-                       debug("### buffer too small: %d, but need %d\n",
-                               size, totlen + 1);
+                       printf("Env export buffer too small: %zu, "
+                               "but need %zu\n", size, totlen + 1);
                        __set_errno(ENOMEM);
                        return (-1);
                }
@@ -544,7 +577,7 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
         * export sorted list of result data
         */
        for (i = 0, p = res; i < n; ++i) {
-               char *s;
+               const char *s;
 
                s = list[i]->key;
                while (*s)
@@ -605,11 +638,6 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
  * '\0' and '\n' have really been tested.
  */
 
-int himport(const char *env, size_t size, const char sep, int flag)
-{
-       return himport_r(&htab, env, size, sep, flag);
-}
-
 int himport_r(struct hsearch_data *htab,
              const char *env, size_t size, const char sep, int flag)
 {
@@ -623,7 +651,7 @@ int himport_r(struct hsearch_data *htab,
 
        /* we allocate new space to make sure we can write to the array */
        if ((data = malloc(size)) == NULL) {
-               debug("himport_r: can't malloc %d bytes\n", size);
+               debug("himport_r: can't malloc %zu bytes\n", size);
                __set_errno(ENOMEM);
                return 0;
        }
@@ -675,7 +703,7 @@ int himport_r(struct hsearch_data *htab,
                ENTRY e, *rv;
 
                /* skip leading white space */
-               while ((*dp == ' ') || (*dp == '\t'))
+               while (isblank(*dp))
                        ++dp;
 
                /* skip comment lines */