X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=lib%2Fhashtable.c;h=b96dbe19be4dd52e0233e9d452f3201f6c57ad69;hb=4ff63383e3497389e66cf70943a83bdb1810462a;hp=93028ed83b2677f9dd83d1f2a16abbcd9f3d2d37;hpb=401c2540445aad08816382c0dc208d2516d90d89;p=oweals%2Fu-boot.git diff --git a/lib/hashtable.c b/lib/hashtable.c index 93028ed83b..b96dbe19be 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -13,7 +13,9 @@ */ #include +#include #include +#include #ifdef USE_HOSTCC /* HOST build */ # include @@ -40,6 +42,9 @@ #define CONFIG_ENV_MAX_ENTRIES 512 #endif +#define USED_FREE 0 +#define USED_DELETED -1 + #include #include #include @@ -56,14 +61,14 @@ * which describes the current status. */ -typedef struct _ENTRY { +struct env_entry_node { int used; - ENTRY entry; -} _ENTRY; + struct env_entry entry; +}; -static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep, - int idx); +static void _hdelete(const char *key, struct hsearch_data *htab, + struct env_entry *ep, int idx); /* * hcreate() @@ -117,7 +122,8 @@ int hcreate_r(size_t nel, struct hsearch_data *htab) htab->filled = 0; /* allocate memory and zero out */ - htab->table = (_ENTRY *) calloc(htab->size + 1, sizeof(_ENTRY)); + htab->table = (struct env_entry_node *)calloc(htab->size + 1, + sizeof(struct env_entry_node)); if (htab->table == NULL) return 0; @@ -148,7 +154,7 @@ void hdestroy_r(struct hsearch_data *htab) /* free used memory */ for (i = 1; i <= htab->size; ++i) { if (htab->table[i].used > 0) { - ENTRY *ep = &htab->table[i].entry; + struct env_entry *ep = &htab->table[i].entry; free((void *)ep->key); free(ep->data); @@ -190,14 +196,14 @@ void hdestroy_r(struct hsearch_data *htab) * data any more. * - The standard implementation does not provide a way to update an * existing entry. This version will create a new entry or update an - * existing one when both "action == ENTER" and "item.data != NULL". + * existing one when both "action == ENV_ENTER" and "item.data != NULL". * - Instead of returning 1 on success, we return the index into the * internal hash table, which is also guaranteed to be positive. * This allows us direct access to the found hash table slot for * example for functions like hdelete(). */ -int hmatch_r(const char *match, int last_idx, ENTRY ** retval, +int hmatch_r(const char *match, int last_idx, struct env_entry **retval, struct hsearch_data *htab) { unsigned int idx; @@ -217,18 +223,30 @@ int hmatch_r(const char *match, int last_idx, ENTRY ** retval, return 0; } +static int +do_callback(const struct env_entry *e, const char *name, const char *value, + enum env_op op, int flags) +{ +#ifndef CONFIG_SPL_BUILD + if (e->callback) + return e->callback(name, value, op, flags); +#endif + return 0; +} + /* * Compare an existing entry with the desired key, and overwrite if the action - * is ENTER. This is simply a helper function for hsearch_r(). + * is ENV_ENTER. This is simply a helper function for hsearch_r(). */ -static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action, - ENTRY **retval, struct hsearch_data *htab, int flag, - unsigned int hval, unsigned int idx) +static inline int _compare_and_overwrite_entry(struct env_entry item, + enum env_action action, struct env_entry **retval, + struct hsearch_data *htab, int flag, unsigned int hval, + unsigned int idx) { if (htab->table[idx].used == hval && strcmp(item.key, htab->table[idx].entry.key) == 0) { /* Overwrite existing value? */ - if ((action == ENTER) && (item.data != NULL)) { + if (action == ENV_ENTER && item.data) { /* check for permission */ if (htab->change_ok != NULL && htab->change_ok( &htab->table[idx].entry, item.data, @@ -241,9 +259,8 @@ static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action, } /* If there is a callback, call it */ - if (htab->table[idx].entry.callback && - htab->table[idx].entry.callback(item.key, - item.data, env_op_overwrite, flag)) { + if (do_callback(&htab->table[idx].entry, item.key, + item.data, env_op_overwrite, flag)) { debug("callback() rejected setting variable " "%s, skipping it!\n", item.key); __set_errno(EINVAL); @@ -267,8 +284,8 @@ static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action, return -1; } -int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval, - struct hsearch_data *htab, int flag) +int hsearch_r(struct env_entry item, enum env_action action, + struct env_entry **retval, struct hsearch_data *htab, int flag) { unsigned int hval; unsigned int count; @@ -303,7 +320,7 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval, */ unsigned hval2; - if (htab->table[idx].used == -1 + if (htab->table[idx].used == USED_DELETED && !first_deleted) first_deleted = idx; @@ -335,17 +352,21 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval, if (idx == hval) break; + if (htab->table[idx].used == USED_DELETED + && !first_deleted) + first_deleted = idx; + /* If entry is found use it. */ ret = _compare_and_overwrite_entry(item, action, retval, htab, flag, hval, idx); if (ret != -1) return ret; } - while (htab->table[idx].used); + while (htab->table[idx].used != USED_FREE); } /* An empty bucket has been found. */ - if (action == ENTER) { + if (action == ENV_ENTER) { /* * If table is full and another entry should be * entered return with error. @@ -392,9 +413,8 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval, } /* If there is a callback, call it */ - if (htab->table[idx].entry.callback && - htab->table[idx].entry.callback(item.key, item.data, - env_op_create, flag)) { + if (do_callback(&htab->table[idx].entry, item.key, item.data, + env_op_create, flag)) { debug("callback() rejected setting variable " "%s, skipping it!\n", item.key); _hdelete(item.key, htab, &htab->table[idx].entry, idx); @@ -424,30 +444,29 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval, * do that. */ -static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep, - int idx) +static void _hdelete(const char *key, struct hsearch_data *htab, + struct env_entry *ep, int idx) { - /* free used ENTRY */ + /* free used entry */ debug("hdelete: DELETING key \"%s\"\n", key); free((void *)ep->key); free(ep->data); - ep->callback = NULL; ep->flags = 0; - htab->table[idx].used = -1; + htab->table[idx].used = USED_DELETED; --htab->filled; } int hdelete_r(const char *key, struct hsearch_data *htab, int flag) { - ENTRY e, *ep; + struct env_entry e, *ep; int idx; debug("hdelete: DELETE key \"%s\"\n", key); e.key = (char *)key; - idx = hsearch_r(e, FIND, &ep, htab, 0); + idx = hsearch_r(e, ENV_FIND, &ep, htab, 0); if (idx == 0) { __set_errno(ESRCH); return 0; /* not found */ @@ -463,8 +482,8 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int flag) } /* If there is a callback, call it */ - if (htab->table[idx].entry.callback && - htab->table[idx].entry.callback(key, NULL, env_op_delete, flag)) { + if (do_callback(&htab->table[idx].entry, key, NULL, + env_op_delete, flag)) { debug("callback() rejected deleting variable " "%s, skipping it!\n", key); __set_errno(EINVAL); @@ -521,8 +540,8 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int flag) static int cmpkey(const void *p1, const void *p2) { - ENTRY *e1 = *(ENTRY **) p1; - ENTRY *e2 = *(ENTRY **) p2; + struct env_entry *e1 = *(struct env_entry **)p1; + struct env_entry *e2 = *(struct env_entry **)p2; return (strcmp(e1->key, e2->key)); } @@ -542,9 +561,8 @@ static int match_string(int flag, const char *str, const char *pat, void *priv) case H_MATCH_REGEX: { struct slre *slrep = (struct slre *)priv; - struct cap caps[slrep->num_caps + 2]; - if (slre_match(slrep, str, strlen(str), caps)) + if (slre_match(slrep, str, strlen(str), NULL)) return 1; } break; @@ -557,8 +575,8 @@ static int match_string(int flag, const char *str, const char *pat, void *priv) return 0; } -static int match_entry(ENTRY *ep, int flag, - int argc, char * const argv[]) +static int match_entry(struct env_entry *ep, int flag, int argc, + char *const argv[]) { int arg; void *priv = NULL; @@ -588,9 +606,9 @@ static int match_entry(ENTRY *ep, int flag, ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag, char **resp, size_t size, - int argc, char * const argv[]) + int argc, char *const argv[]) { - ENTRY *list[htab->size]; + struct env_entry *list[htab->size]; char *res, *p; size_t totlen; int i, n; @@ -611,7 +629,7 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag, for (i = 1, n = 0, totlen = 0; i <= htab->size; ++i) { if (htab->table[i].used > 0) { - ENTRY *ep = &htab->table[i].entry; + struct env_entry *ep = &htab->table[i].entry; int found = match_entry(ep, flag, argc, argv); if ((argc > 0) && (found == 0)) @@ -651,7 +669,7 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag, #endif /* Sort list by keys */ - qsort(list, n, sizeof(ENTRY *), cmpkey); + qsort(list, n, sizeof(struct env_entry *), cmpkey); /* Check if the user supplied buffer size is sufficient */ if (size) { @@ -863,7 +881,7 @@ int himport_r(struct hsearch_data *htab, } /* Parse environment; allow for '\0' and 'sep' as separators */ do { - ENTRY e, *rv; + struct env_entry e, *rv; /* skip leading white space */ while (isblank(*dp)) @@ -923,7 +941,7 @@ int himport_r(struct hsearch_data *htab, e.key = name; e.data = value; - hsearch_r(e, ENTER, &rv, htab, flag); + hsearch_r(e, ENV_ENTER, &rv, htab, flag); if (rv == NULL) printf("himport_r: can't insert \"%s=%s\" into hash table\n", name, value); @@ -970,7 +988,7 @@ end: * Walk all of the entries in the hash, calling the callback for each one. * this allows some generic operation to be performed on each element. */ -int hwalk_r(struct hsearch_data *htab, int (*callback)(ENTRY *)) +int hwalk_r(struct hsearch_data *htab, int (*callback)(struct env_entry *entry)) { int i; int retval;