X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flibpspp%2Fstringi-map.c;h=b47cbd409d0675731eb18ad253578d5f2a3cd4f3;hb=037d8f6e7932459b5d0fb479a2c5030a8088f3d1;hp=d3e5144de7276da98af7f0af99a88c12f8377b1e;hpb=6b1a7420704720085826e2b5f9fedea3ca8239de;p=pspp diff --git a/src/libpspp/stringi-map.c b/src/libpspp/stringi-map.c index d3e5144de7..b47cbd409d 100644 --- a/src/libpspp/stringi-map.c +++ b/src/libpspp/stringi-map.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,15 +22,18 @@ #include #include "libpspp/hash-functions.h" +#include "libpspp/i18n.h" #include "libpspp/string-set.h" #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); @@ -74,7 +77,7 @@ stringi_map_node_set_value_nocopy (struct stringi_map_node *node, char *value) node->value = value; } -/* Frees NODE and and its key and value. Ordinarily nodes are owned by +/* Frees NODE and its key and value. Ordinarily nodes are owned by stringi_maps, but this function should only be used by a caller that owns NODE, such as one that has called stringi_map_delete_nofree() for the node. */ @@ -131,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 @@ -139,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, 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 @@ -157,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) { @@ -175,10 +193,13 @@ struct stringi_map_node * stringi_map_insert (struct stringi_map *map, const char *key, const char *value) { - unsigned int hash = 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; } @@ -189,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 = 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 @@ -208,8 +231,10 @@ struct stringi_map_node * stringi_map_replace (struct stringi_map *map, const char *key, const char *value) { - unsigned int hash = 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 @@ -224,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 = 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 @@ -242,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, 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. */ @@ -283,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); } } @@ -300,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); } } @@ -338,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 (!strcasecmp (key, node->key)) + if (!utf8_strncasecmp (key, key_len, node->key, strlen (node->key))) return node; return NULL; @@ -352,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);