From: Ben Pfaff Date: Sun, 4 Jul 2021 21:13:45 +0000 (-0700) Subject: stringi-map: Add some support for non-null-terminated strings. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b30aadab012dce34c7cacbdbca3f3eab0270d89;p=pspp stringi-map: Add some support for non-null-terminated strings. --- diff --git a/src/libpspp/stringi-map.c b/src/libpspp/stringi-map.c index 7b8d398d03..ba3e41ef78 100644 --- a/src/libpspp/stringi-map.c +++ b/src/libpspp/stringi-map.c @@ -27,11 +27,13 @@ #include "libpspp/stringi-set.h" #include "gl/xalloc.h" +#include "gl/xmemdup0.h" static struct stringi_map_node *stringi_map_find_node__ ( - const struct stringi_map *, const char *key, unsigned int hash); + const struct stringi_map *, const char *key, size_t key_len, + unsigned int hash); static bool stringi_map_delete__ (struct stringi_map *, const char *key, - unsigned int hash); + size_t key_len, unsigned int hash); static struct stringi_map_node *stringi_map_insert__ (struct stringi_map *, char *key, char *value, unsigned int hash); @@ -132,7 +134,7 @@ stringi_map_destroy (struct stringi_map *map) bool stringi_map_contains (const struct stringi_map *map, const char *key) { - return stringi_map_find_node (map, key) != NULL; + return stringi_map_find_node (map, key, strlen (key)) != NULL; } /* If MAP contains KEY (or an equivalent with different case) as a key, returns @@ -140,16 +142,30 @@ stringi_map_contains (const struct stringi_map *map, const char *key) const char * stringi_map_find (const struct stringi_map *map, const char *key) { - const struct stringi_map_node *node = stringi_map_find_node (map, key); + return stringi_map_find__ (map, key, strlen (key)); +} + +/* If MAP contains KEY with the specified KEY_LEN (or an equivalent with + different case) as a key, returns the corresponding value. Otherwise, + returns a null pointer. */ +const char * +stringi_map_find__ (const struct stringi_map *map, const char *key, + size_t key_len) +{ + const struct stringi_map_node *node = stringi_map_find_node (map, key, + key_len); return node != NULL ? node->value : NULL; } -/* If MAP contains KEY (or an equivalent with different case) as a key, returns - the corresponding node. Otherwise, returns a null pointer. */ +/* If MAP contains KEY with the specified KEY_LEN (or an equivalent with + different case) as a key, returns the corresponding node. Otherwise, + returns a null pointer. */ struct stringi_map_node * -stringi_map_find_node (const struct stringi_map *map, const char *key) +stringi_map_find_node (const struct stringi_map *map, const char *key, + size_t key_len) { - return stringi_map_find_node__ (map, key, utf8_hash_case_string (key, 0)); + return stringi_map_find_node__ (map, key, key_len, + utf8_hash_case_bytes (key, key_len, 0)); } /* If MAP contains KEY (or an equivalent with different case) as a key, deletes @@ -158,7 +174,8 @@ stringi_map_find_node (const struct stringi_map *map, const char *key) char * stringi_map_find_and_delete (struct stringi_map *map, const char *key) { - struct stringi_map_node *node = stringi_map_find_node (map, key); + struct stringi_map_node *node = stringi_map_find_node (map, key, + strlen (key)); char *value = NULL; if (node != NULL) { @@ -176,10 +193,13 @@ struct stringi_map_node * stringi_map_insert (struct stringi_map *map, const char *key, const char *value) { - unsigned int hash = utf8_hash_case_string (key, 0); - struct stringi_map_node *node = stringi_map_find_node__ (map, key, hash); + size_t key_len = strlen (key); + unsigned int hash = utf8_hash_case_bytes (key, key_len, 0); + struct stringi_map_node *node = stringi_map_find_node__ (map, key, key_len, + hash); if (node == NULL) - node = stringi_map_insert__ (map, xstrdup (key), xstrdup (value), hash); + node = stringi_map_insert__ (map, xmemdup0 (key, key_len), + xstrdup (value), hash); return node; } @@ -190,8 +210,10 @@ stringi_map_insert (struct stringi_map *map, const char *key, struct stringi_map_node * stringi_map_insert_nocopy (struct stringi_map *map, char *key, char *value) { - unsigned int hash = utf8_hash_case_string (key, 0); - struct stringi_map_node *node = stringi_map_find_node__ (map, key, hash); + size_t key_len = strlen (key); + unsigned int hash = utf8_hash_case_bytes (key, key_len, 0); + struct stringi_map_node *node = stringi_map_find_node__ (map, key, key_len, + hash); if (node == NULL) node = stringi_map_insert__ (map, key, value, hash); else @@ -209,8 +231,10 @@ struct stringi_map_node * stringi_map_replace (struct stringi_map *map, const char *key, const char *value) { - unsigned int hash = utf8_hash_case_string (key, 0); - struct stringi_map_node *node = stringi_map_find_node__ (map, key, hash); + size_t key_len = strlen (key); + unsigned int hash = utf8_hash_case_bytes (key, key_len, 0); + struct stringi_map_node *node = stringi_map_find_node__ (map, key, key_len, + hash); if (node == NULL) node = stringi_map_insert__ (map, xstrdup (key), xstrdup (value), hash); else @@ -225,8 +249,10 @@ stringi_map_replace (struct stringi_map *map, const char *key, struct stringi_map_node * stringi_map_replace_nocopy (struct stringi_map *map, char *key, char *value) { - unsigned int hash = utf8_hash_case_string (key, 0); - struct stringi_map_node *node = stringi_map_find_node__ (map, key, hash); + size_t key_len = strlen (key); + unsigned int hash = utf8_hash_case_bytes (key, key_len, 0); + struct stringi_map_node *node = stringi_map_find_node__ (map, key, key_len, + hash); if (node == NULL) node = stringi_map_insert__ (map, key, value, hash); else @@ -243,7 +269,9 @@ stringi_map_replace_nocopy (struct stringi_map *map, char *key, char *value) bool stringi_map_delete (struct stringi_map *map, const char *key) { - return stringi_map_delete__ (map, key, utf8_hash_case_string (key, 0)); + size_t key_len = strlen (key); + return stringi_map_delete__ (map, key, key_len, + utf8_hash_case_bytes (key, key_len, 0)); } /* Deletes NODE from MAP and destroys the node and its key and value. */ @@ -284,8 +312,11 @@ stringi_map_insert_map (struct stringi_map *dst, const struct stringi_map *src) STRINGI_MAP_FOR_EACH_NODE (node, src) { - if (!stringi_map_find_node__ (dst, node->key, node->hmap_node.hash)) - stringi_map_insert__ (dst, xstrdup (node->key), xstrdup (node->value), + size_t key_len = strlen (node->key); + if (!stringi_map_find_node__ (dst, node->key, key_len, + node->hmap_node.hash)) + stringi_map_insert__ (dst, xmemdup0 (node->key, key_len), + xstrdup (node->value), node->hmap_node.hash); } } @@ -301,13 +332,15 @@ stringi_map_replace_map (struct stringi_map *dst, STRINGI_MAP_FOR_EACH_NODE (snode, src) { + size_t key_len = strlen (snode->key); struct stringi_map_node *dnode; - dnode = stringi_map_find_node__ (dst, snode->key, snode->hmap_node.hash); + dnode = stringi_map_find_node__ (dst, snode->key, key_len, + snode->hmap_node.hash); if (dnode != NULL) stringi_map_node_set_value (dnode, snode->value); else - stringi_map_insert__ (dst, - xstrdup (snode->key), xstrdup (snode->value), + stringi_map_insert__ (dst, xmemdup0 (snode->key, key_len), + xstrdup (snode->value), snode->hmap_node.hash); } } @@ -339,13 +372,13 @@ stringi_map_get_values (const struct stringi_map *map, static struct stringi_map_node * stringi_map_find_node__ (const struct stringi_map *map, const char *key, - unsigned int hash) + size_t key_len, unsigned int hash) { struct stringi_map_node *node; HMAP_FOR_EACH_WITH_HASH (node, struct stringi_map_node, hmap_node, hash, &map->hmap) - if (!utf8_strcasecmp (key, node->key)) + if (!utf8_strncasecmp (key, key_len, node->key, strlen (node->key))) return node; return NULL; @@ -353,9 +386,10 @@ stringi_map_find_node__ (const struct stringi_map *map, const char *key, static bool stringi_map_delete__ (struct stringi_map *map, const char *key, - unsigned int hash) + size_t key_len, unsigned int hash) { - struct stringi_map_node *node = stringi_map_find_node__ (map, key, hash); + struct stringi_map_node *node = stringi_map_find_node__ (map, key, key_len, + hash); if (node != NULL) { stringi_map_delete_node (map, node); diff --git a/src/libpspp/stringi-map.h b/src/libpspp/stringi-map.h index 1c4894b411..5f2ffdc40b 100644 --- a/src/libpspp/stringi-map.h +++ b/src/libpspp/stringi-map.h @@ -90,8 +90,11 @@ static inline bool stringi_map_is_empty (const struct stringi_map *); bool stringi_map_contains (const struct stringi_map *, const char *); const char *stringi_map_find (const struct stringi_map *, const char *); +const char *stringi_map_find__ (const struct stringi_map *, const char *key, + size_t key_len); struct stringi_map_node *stringi_map_find_node (const struct stringi_map *, - const char *); + const char *key, + size_t key_len); char *stringi_map_find_and_delete (struct stringi_map *, const char *key); struct stringi_map_node *stringi_map_insert (struct stringi_map *, diff --git a/tests/libpspp/stringi-map-test.c b/tests/libpspp/stringi-map-test.c index a78fd56557..eaf4102bb1 100644 --- a/tests/libpspp/stringi-map-test.c +++ b/tests/libpspp/stringi-map-test.c @@ -223,7 +223,7 @@ check_map_contains (struct stringi_map *map, check (stringi_map_contains (map, key)); - node = stringi_map_find_node (map, key); + node = stringi_map_find_node (map, key, strlen (key)); check (node != NULL); check (!utf8_strcasecmp (key, stringi_map_node_get_key (node))); check (!strcmp (value, stringi_map_node_get_value (node))); @@ -271,7 +271,7 @@ check_stringi_map (struct stringi_map *map, const int data[], size_t cnt) check (!stringi_map_contains (map, "xxx")); check (stringi_map_find (map, "0") == NULL); - check (stringi_map_find_node (map, "") == NULL); + check (stringi_map_find_node (map, "", 0) == NULL); check (!stringi_map_delete (map, "xyz")); if (cnt == 0) @@ -689,11 +689,12 @@ node_swap_value_cb (struct stringi_map *map, int data[], int n) for (i = 0; i < n; i++) { + const char *key = make_key (data[i]); const char *value = make_value (data[i]); struct stringi_map_node *node; char *old_value; - node = stringi_map_find_node (map, make_key (data[i])); + node = stringi_map_find_node (map, key, strlen (key)); check (node != NULL); check (!strcmp (stringi_map_node_get_value (node), value)); data[i] = (data[i] & KEY_MASK) | random_value (i, 15);