[U-Boot] [RFC, PATCH v4 01/16] hashtable: extend interfaces to handle entries with context

AKASHI Takahiro takahiro.akashi at linaro.org
Wed Jul 17 08:25:10 UTC 2019


The following interfaces are extended to accept an additional argument,
context:
    hsearch_r() -> hsearch_ext()
    hmatch_r() -> hmatch_ext()
    hdelete_r() -> hdelete_ext()
    hexport_r() -> hexport_ext()
    himport_r() -> himport_ext()

A context of an entry does not have any specific meaning in hash
routines, except that it can be used one of matching parameters.

This feature will be used to add multiple U-Boot environment context
support in successive commits.

Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
---
 include/search.h | 15 +++++++++
 lib/hashtable.c  | 80 +++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 81 insertions(+), 14 deletions(-)

diff --git a/include/search.h b/include/search.h
index 5d07b49073cc..9cece695d726 100644
--- a/include/search.h
+++ b/include/search.h
@@ -31,6 +31,7 @@ typedef enum {
 } ACTION;
 
 typedef struct entry {
+	unsigned int context;	/* opaque data for table operations */
 	const char *key;
 	char *data;
 	int (*callback)(const char *name, const char *value, enum env_op op,
@@ -77,6 +78,8 @@ extern void hdestroy_r(struct hsearch_data *__htab);
  * */
 extern int hsearch_r(ENTRY __item, ACTION __action, ENTRY ** __retval,
 		     struct hsearch_data *__htab, int __flag);
+extern int hsearch_ext(ENTRY __item, ACTION __action, ENTRY ** __retval,
+		       struct hsearch_data *__htab, int __flag);
 
 /*
  * Search for an entry matching "__match".  Otherwise, Same semantics
@@ -84,14 +87,22 @@ extern int hsearch_r(ENTRY __item, ACTION __action, ENTRY ** __retval,
  */
 extern int hmatch_r(const char *__match, int __last_idx, ENTRY ** __retval,
 		    struct hsearch_data *__htab);
+extern int hmatch_ext(const char *__match, int __last_idx, ENTRY ** __retval,
+		      struct hsearch_data *__htab, unsigned int ctx);
 
 /* Search and delete entry matching "__key" in internal hash table. */
 extern int hdelete_r(const char *__key, struct hsearch_data *__htab,
 		     int __flag);
+extern int hdelete_ext(const char *__key, struct hsearch_data *__htab,
+		       unsigned int ctx, int __flag);
 
 extern ssize_t hexport_r(struct hsearch_data *__htab,
 		     const char __sep, int __flag, char **__resp, size_t __size,
 		     int argc, char * const argv[]);
+extern ssize_t hexport_ext(struct hsearch_data *__htab, unsigned int ctx,
+			   const char __sep, int __flag,
+			   char **__resp, size_t __size,
+			   int argc, char * const argv[]);
 
 /*
  * nvars: length of vars array
@@ -101,6 +112,10 @@ extern int himport_r(struct hsearch_data *__htab,
 		     const char *__env, size_t __size, const char __sep,
 		     int __flag, int __crlf_is_lf, int nvars,
 		     char * const vars[]);
+extern int himport_ext(struct hsearch_data *__htab, unsigned int ctx,
+		       const char *__env, size_t __size, const char __sep,
+		       int __flag, int __crlf_is_lf, int nvars,
+		       char * const vars[]);
 
 /* Walk the whole table calling the callback on each element */
 extern int hwalk_r(struct hsearch_data *__htab, int (*callback)(ENTRY *));
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 0d288d12d991..d6975d9cafc6 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -200,8 +200,8 @@ void hdestroy_r(struct hsearch_data *htab)
  *   example for functions like hdelete().
  */
 
-int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
-	     struct hsearch_data *htab)
+int hmatch_ext(const char *match, int last_idx, ENTRY ** retval,
+	       struct hsearch_data *htab, unsigned int ctx)
 {
 	unsigned int idx;
 	size_t key_len = strlen(match);
@@ -209,6 +209,8 @@ int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
 	for (idx = last_idx + 1; idx < htab->size; ++idx) {
 		if (htab->table[idx].used <= 0)
 			continue;
+		if (htab->table[idx].entry.context != ctx)
+			continue;
 		if (!strncmp(match, htab->table[idx].entry.key, key_len)) {
 			*retval = &htab->table[idx].entry;
 			return idx;
@@ -220,6 +222,12 @@ int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
 	return 0;
 }
 
+int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
+	     struct hsearch_data *htab)
+{
+	return hmatch_ext(match, last_idx, retval, htab, 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().
@@ -230,6 +238,14 @@ static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action,
 {
 	if (htab->table[idx].used == hval
 	    && strcmp(item.key, htab->table[idx].entry.key) == 0) {
+		/* No duplicated keys allowed */
+		if (item.context != htab->table[idx].entry.context) {
+			debug("context mismatch %s\n", item.key);
+			__set_errno(EINVAL);
+			*retval = NULL;
+			return 0;
+		}
+
 		/* Overwrite existing value? */
 		if ((action == ENTER) && (item.data != NULL)) {
 			/* check for permission */
@@ -270,8 +286,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_ext(ENTRY item, ACTION action, ENTRY ** retval,
+		struct hsearch_data *htab, int flag)
 {
 	unsigned int hval;
 	unsigned int count;
@@ -371,6 +387,7 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
 			idx = first_deleted;
 
 		htab->table[idx].used = hval;
+		htab->table[idx].entry.context = item.context;
 		htab->table[idx].entry.key = strdup(item.key);
 		htab->table[idx].entry.data = strdup(item.data);
 		if (!htab->table[idx].entry.key ||
@@ -420,6 +437,15 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
 	return 0;
 }
 
+int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
+	      struct hsearch_data *htab, int flag)
+{
+	ENTRY e;
+
+	e = item;
+	e.context = 0;
+	return hsearch_ext(e, action, retval, htab, flag);
+}
 
 /*
  * hdelete()
@@ -445,16 +471,18 @@ static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep,
 	--htab->filled;
 }
 
-int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
+int hdelete_ext(const char *key, struct hsearch_data *htab, unsigned int ctx,
+		int flag)
 {
 	ENTRY e, *ep;
 	int idx;
 
 	debug("hdelete: DELETE key \"%s\"\n", key);
 
+	e.context = ctx;
 	e.key = (char *)key;
 
-	idx = hsearch_r(e, FIND, &ep, htab, 0);
+	idx = hsearch_ext(e, FIND, &ep, htab, 0);
 	if (idx == 0) {
 		__set_errno(ESRCH);
 		return 0;	/* not found */
@@ -483,6 +511,11 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
 	return 1;
 }
 
+int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
+{
+	return hdelete_ext(key, htab, 0, flag);
+}
+
 #if !(defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_SAVEENV))
 /*
  * hexport()
@@ -592,9 +625,9 @@ static int match_entry(ENTRY *ep, int flag,
 	return 0;
 }
 
-ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
-		 char **resp, size_t size,
-		 int argc, char * const argv[])
+ssize_t hexport_ext(struct hsearch_data *htab, unsigned int ctx,
+		    const char sep, int flag, char **resp, size_t size,
+		    int argc, char * const argv[])
 {
 	ENTRY *list[htab->size];
 	char *res, *p;
@@ -618,8 +651,12 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
 
 		if (htab->table[i].used > 0) {
 			ENTRY *ep = &htab->table[i].entry;
-			int found = match_entry(ep, flag, argc, argv);
+			int found;
 
+			if (ep->context != ctx)
+				continue;
+
+			found = match_entry(ep, flag, argc, argv);
 			if ((argc > 0) && (found == 0))
 				continue;
 
@@ -709,8 +746,14 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
 
 	return size;
 }
-#endif
 
+ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
+		  char **resp, size_t size,
+		  int argc, char * const argv[])
+{
+	return hexport_ext(htab, 0, sep, flag, resp, size, argc, argv);
+}
+#endif
 
 /*
  * himport()
@@ -782,7 +825,7 @@ static int drop_var_from_set(const char *name, int nvars, char * vars[])
  * '\0' and '\n' have really been tested.
  */
 
-int himport_r(struct hsearch_data *htab,
+int himport_ext(struct hsearch_data *htab, unsigned int ctx,
 		const char *env, size_t size, const char sep, int flag,
 		int crlf_is_lf, int nvars, char * const vars[])
 {
@@ -898,7 +941,7 @@ int himport_r(struct hsearch_data *htab,
 			if (!drop_var_from_set(name, nvars, localvars))
 				continue;
 
-			if (hdelete_r(name, htab, flag) == 0)
+			if (hdelete_ext(name, htab, ctx, flag) == 0)
 				debug("DELETE ERROR ##############################\n");
 
 			continue;
@@ -926,10 +969,11 @@ int himport_r(struct hsearch_data *htab,
 			continue;
 
 		/* enter into hash table */
+		e.context = ctx;
 		e.key = name;
 		e.data = value;
 
-		hsearch_r(e, ENTER, &rv, htab, flag);
+		hsearch_ext(e, ENTER, &rv, htab, flag);
 		if (rv == NULL)
 			printf("himport_r: can't insert \"%s=%s\" into hash table\n",
 				name, value);
@@ -968,6 +1012,14 @@ end:
 	return 1;		/* everything OK */
 }
 
+int himport_r(struct hsearch_data *htab,
+	      const char *env, size_t size, const char sep, int flag,
+	      int crlf_is_lf, int nvars, char * const vars[])
+{
+	return himport_ext(htab, 0, env, size, sep, flag, crlf_is_lf,
+			   nvars, vars);
+}
+
 /*
  * hwalk_r()
  */
-- 
2.21.0



More information about the U-Boot mailing list