X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flibpspp%2Fstring-map.c;h=670154fc5df63cd753d48a1d86d3da217ef89a8d;hb=15d30a4c251fe810f3697bd287afdc8b1699487d;hp=48124797ba570af9cdd70b61230295dc160749ce;hpb=d0b91eae59319ab2756d0d43b9cb15eb9cd3c234;p=pspp diff --git a/src/libpspp/string-map.c b/src/libpspp/string-map.c index 48124797ba..670154fc5d 100644 --- a/src/libpspp/string-map.c +++ b/src/libpspp/string-map.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2009 Free Software Foundation, Inc. + Copyright (C) 2009, 2011 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 @@ -16,18 +16,20 @@ #include -#include +#include "libpspp/string-map.h" #include #include -#include -#include +#include "libpspp/hash-functions.h" +#include "libpspp/string-set.h" #include "gl/xalloc.h" +#include "gl/xmemdup0.h" -static struct string_map_node *string_map_find_node__ ( - const struct string_map *, const char *key, unsigned int hash); +static struct string_map_node *string_map_find_node_with_hash ( + const struct string_map *, const char *key, size_t length, + unsigned int hash); static bool string_map_delete__ (struct string_map *, const char *key, unsigned int hash); static struct string_map_node *string_map_insert__ (struct string_map *, @@ -73,7 +75,7 @@ string_map_node_set_value_nocopy (struct string_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 string_maps, but this function should only be used by a caller that owns NODE, such as one that has called string_map_delete_nofree() for the node. */ @@ -132,6 +134,17 @@ string_map_contains (const struct string_map *map, const char *key) return string_map_find_node (map, key) != NULL; } +/* If MAP contains KEY, which is LENGTH bytes long, as a key, returns the + corresponding value. Otherwise, returns a null pointer. */ +const char * +string_map_find__ (const struct string_map *map, const char *key, + size_t length) +{ + const struct string_map_node *node = string_map_find_node__ (map, key, + length); + return node != NULL ? node->value : NULL; +} + /* If MAP contains KEY as a key, returns the corresponding value. Otherwise, returns a null pointer. */ const char * @@ -141,12 +154,22 @@ string_map_find (const struct string_map *map, const char *key) return node != NULL ? node->value : NULL; } +/* If MAP contains KEY as a key, returns the corresponding node. Otherwise, + returns a null pointer. */ +struct string_map_node * +string_map_find_node__ (const struct string_map *map, const char *key, + size_t length) +{ + return string_map_find_node_with_hash (map, key, length, + hash_bytes (key, length, 0)); +} + /* If MAP contains KEY as a key, returns the corresponding node. Otherwise, returns a null pointer. */ struct string_map_node * string_map_find_node (const struct string_map *map, const char *key) { - return string_map_find_node__ (map, key, hash_string (key, 0)); + return string_map_find_node__ (map, key, strlen (key)); } /* If MAP contains KEY as a key, deletes that key's node and returns its value, @@ -172,10 +195,13 @@ string_map_find_and_delete (struct string_map *map, const char *key) struct string_map_node * string_map_insert (struct string_map *map, const char *key, const char *value) { - unsigned int hash = hash_string (key, 0); - struct string_map_node *node = string_map_find_node__ (map, key, hash); + size_t length = strlen (key); + unsigned int hash = hash_bytes (key, length, 0); + struct string_map_node *node = string_map_find_node_with_hash (map, key, + length, hash); if (node == NULL) - node = string_map_insert__ (map, xstrdup (key), xstrdup (value), hash); + node = string_map_insert__ (map, xmemdup0 (key, length), xstrdup (value), + hash); return node; } @@ -186,8 +212,10 @@ string_map_insert (struct string_map *map, const char *key, const char *value) struct string_map_node * string_map_insert_nocopy (struct string_map *map, char *key, char *value) { - unsigned int hash = hash_string (key, 0); - struct string_map_node *node = string_map_find_node__ (map, key, hash); + size_t length = strlen (key); + unsigned int hash = hash_bytes (key, length, 0); + struct string_map_node *node = string_map_find_node_with_hash (map, key, + length, hash); if (node == NULL) node = string_map_insert__ (map, key, value, hash); else @@ -204,10 +232,13 @@ string_map_insert_nocopy (struct string_map *map, char *key, char *value) struct string_map_node * string_map_replace (struct string_map *map, const char *key, const char *value) { - unsigned int hash = hash_string (key, 0); - struct string_map_node *node = string_map_find_node__ (map, key, hash); + size_t length = strlen (key); + unsigned int hash = hash_bytes (key, length, 0); + struct string_map_node *node = string_map_find_node_with_hash (map, key, + length, hash); if (node == NULL) - node = string_map_insert__ (map, xstrdup (key), xstrdup (value), hash); + node = string_map_insert__ (map, xmemdup0 (key, length), + xstrdup (value), hash); else string_map_node_set_value (node, value); return node; @@ -219,8 +250,10 @@ string_map_replace (struct string_map *map, const char *key, const char *value) struct string_map_node * string_map_replace_nocopy (struct string_map *map, char *key, char *value) { - unsigned int hash = hash_string (key, 0); - struct string_map_node *node = string_map_find_node__ (map, key, hash); + size_t length = strlen (key); + unsigned int hash = hash_bytes (key, length, 0); + struct string_map_node *node = string_map_find_node_with_hash (map, key, + length, hash); if (node == NULL) node = string_map_insert__ (map, key, value, hash); else @@ -275,7 +308,8 @@ string_map_insert_map (struct string_map *dst, const struct string_map *src) STRING_MAP_FOR_EACH_NODE (node, src) { - if (!string_map_find_node__ (dst, node->key, node->hmap_node.hash)) + if (!string_map_find_node_with_hash (dst, node->key, strlen (node->key), + node->hmap_node.hash)) string_map_insert__ (dst, xstrdup (node->key), xstrdup (node->value), node->hmap_node.hash); } @@ -292,7 +326,9 @@ string_map_replace_map (struct string_map *dst, const struct string_map *src) STRING_MAP_FOR_EACH_NODE (snode, src) { struct string_map_node *dnode; - dnode = string_map_find_node__ (dst, snode->key, snode->hmap_node.hash); + dnode = string_map_find_node_with_hash (dst, snode->key, + strlen (snode->key), + snode->hmap_node.hash); if (dnode != NULL) string_map_node_set_value (dnode, snode->value); else @@ -324,16 +360,35 @@ string_map_get_values (const struct string_map *map, struct string_set *values) STRING_MAP_FOR_EACH_VALUE (value, node, map) string_set_insert (values, value); } + +/* Returns true if A and B have the same content, false otherwise. */ +bool +string_map_equals (const struct string_map *a, const struct string_map *b) +{ + if (string_map_count (a) != string_map_count (b)) + return false; + + const struct string_map_node *a_node; + STRING_MAP_FOR_EACH_NODE (a_node, a) + { + const struct string_map_node *b_node = string_map_find_node_with_hash ( + b, a_node->key, strlen (a_node->key), a_node->hmap_node.hash); + if (!b_node || strcmp (a_node->value, b_node->value)) + return false; + } + + return true; +} static struct string_map_node * -string_map_find_node__ (const struct string_map *map, const char *key, - unsigned int hash) +string_map_find_node_with_hash (const struct string_map *map, const char *key, + size_t length, unsigned int hash) { struct string_map_node *node; HMAP_FOR_EACH_WITH_HASH (node, struct string_map_node, hmap_node, hash, &map->hmap) - if (!strcmp (key, node->key)) + if (!strncmp (key, node->key, length) && node->key[length] == '\0') return node; return NULL; @@ -343,7 +398,8 @@ static bool string_map_delete__ (struct string_map *map, const char *key, unsigned int hash) { - struct string_map_node *node = string_map_find_node__ (map, key, hash); + struct string_map_node *node + = string_map_find_node_with_hash (map, key, strlen (key), hash); if (node != NULL) { string_map_delete_node (map, node);