mesa/glsl: Move string_to_uint_map into the util folder
authorThomas Helland <thomashelland90@gmail.com>
Tue, 16 Aug 2016 20:10:36 +0000 (22:10 +0200)
committerTimothy Arceri <timothy.arceri@collabora.com>
Mon, 12 Sep 2016 00:48:35 +0000 (10:48 +1000)
This clears the last bits of the usecases of the hash table
located in mesa/program, allowing us to remove it.

V2: Rebase on top of changes to Makefile.sources

Signed-off-by: Thomas Helland <thomashelland90@gmail.com>
Reviewed-by: Timothy Arceri <timothy.arceri@collabora.com>
15 files changed:
src/compiler/glsl/link_uniform_initializers.cpp
src/compiler/glsl/link_uniforms.cpp
src/compiler/glsl/linker.cpp
src/compiler/glsl/standalone.cpp
src/compiler/glsl/tests/set_uniform_initializer_tests.cpp
src/mesa/Makefile.sources
src/mesa/main/shader_query.cpp
src/mesa/main/shaderobj.c
src/mesa/program/hash_table.h [deleted file]
src/mesa/program/ir_to_mesa.cpp
src/mesa/program/string_to_uint_map.cpp [deleted file]
src/mesa/state_tracker/st_glsl_to_nir.cpp
src/util/Makefile.sources
src/util/string_to_uint_map.cpp [new file with mode: 0644]
src/util/string_to_uint_map.h [new file with mode: 0644]

index 021e95032f8e150ebaa5a87c72ff6b90f0f167b0..68ba167e4785cd91f0c6e672550d37590b0ff884 100644 (file)
  */
 
 #include "main/core.h"
-#include "program/hash_table.h"
 #include "ir.h"
 #include "linker.h"
 #include "ir_uniform.h"
+#include "util/string_to_uint_map.h"
 
 /* These functions are put in a "private" namespace instead of being marked
  * static so that the unit tests can access them.  See
index 9f8adcc11544ba65b057f804f4f53fc17fb38d79..4d3fc6d9c74b9f078f3287d1da1ccc25f4733a48 100644 (file)
@@ -26,8 +26,8 @@
 #include "linker.h"
 #include "ir_uniform.h"
 #include "glsl_symbol_table.h"
-#include "program/hash_table.h"
 #include "program.h"
+#include "util/string_to_uint_map.h"
 
 /**
  * \file link_uniforms.cpp
index 23e87093d722dc80918a396908fa0e5298e56c19..4440c03267287db442219c7e4d5ba82799b20e3d 100644 (file)
@@ -71,9 +71,9 @@
 #include "glsl_parser_extras.h"
 #include "ir.h"
 #include "program.h"
-#include "program/hash_table.h"
 #include "program/prog_instruction.h"
 #include "util/set.h"
+#include "util/string_to_uint_map.h"
 #include "linker.h"
 #include "link_varyings.h"
 #include "ir_optimization.h"
index 88fe5fde09611a6c8ee0d694522be198ce50c225..d6e68291977bbf702cd2382fde9bf232b340ed1c 100644 (file)
 #include "glsl_parser_extras.h"
 #include "ir_optimization.h"
 #include "program.h"
-#include "program/hash_table.h"
 #include "loop_analysis.h"
 #include "standalone_scaffolding.h"
 #include "standalone.h"
+#include "util/string_to_uint_map.h"
 
 static const struct standalone_options *options;
 
index 9d4101743f9a28af09b0fa9c8afed1721ff08151..245494c739b8affa5cfd7da2c2f2650426e22de5 100644 (file)
@@ -24,8 +24,8 @@
 #include "main/compiler.h"
 #include "main/mtypes.h"
 #include "main/macros.h"
-#include "program/hash_table.h"
 #include "util/ralloc.h"
+#include "util/string_to_uint_map.h"
 #include "uniform_initializer_utils.h"
 
 namespace linker {
index d02695d8782db51a75df0f99ddf03d2409a36081..5d51f16db55f64db1b780da7595c28e507dd7baf 100644 (file)
@@ -519,7 +519,6 @@ STATETRACKER_FILES = \
 PROGRAM_FILES = \
        program/arbprogparse.c \
        program/arbprogparse.h \
-       program/hash_table.h \
        program/ir_to_mesa.cpp \
        program/ir_to_mesa.h \
        program/lex.yy.c \
@@ -550,7 +549,6 @@ PROGRAM_FILES = \
        program/program_parser.h \
        program/prog_statevars.c \
        program/prog_statevars.h \
-       program/string_to_uint_map.cpp \
        program/symbol_table.c \
        program/symbol_table.h
 
index 0eae39a3557255df1238d6ff65a751259b175569..5c42006b5dc69a04cc95606e3f09fb17374b102f 100644 (file)
@@ -37,7 +37,7 @@
 #include "compiler/glsl/glsl_symbol_table.h"
 #include "compiler/glsl/ir.h"
 #include "compiler/glsl/program.h"
-#include "program/hash_table.h"
+#include "util/string_to_uint_map.h"
 #include "util/strndup.h"
 
 
index 0075a6d64293bd1dfe377220153e565bac25e1e5..350b677911ebb37e59f2e0fb870eda401c076899 100644 (file)
@@ -39,8 +39,8 @@
 #include "main/uniforms.h"
 #include "program/program.h"
 #include "program/prog_parameter.h"
-#include "program/hash_table.h"
 #include "util/ralloc.h"
+#include "util/string_to_uint_map.h"
 
 /**********************************************************************/
 /*** Shader object functions                                        ***/
diff --git a/src/mesa/program/hash_table.h b/src/mesa/program/hash_table.h
deleted file mode 100644 (file)
index d757818..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Copyright © 2008 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file hash_table.h
- * \brief Implementation of a generic, opaque hash table data type.
- *
- * \author Ian Romanick <ian.d.romanick@intel.com>
- */
-
-#ifndef HASH_TABLE_H
-#define HASH_TABLE_H
-
-#include <string.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <limits.h>
-#include <assert.h>
-#include "util/hash_table.h"
-
-struct string_to_uint_map;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef unsigned (*hash_func_t)(const void *key);
-typedef bool (*hash_compare_func_t)(const void *key1, const void *key2);
-
-/**
- * Hash table constructor
- *
- * Creates a hash table with the specified number of buckets.  The supplied
- * \c hash and \c compare routines are used when adding elements to the table
- * and when searching for elements in the table.
- *
- * \param num_buckets  Number of buckets (bins) in the hash table.
- * \param hash         Function used to compute hash value of input keys.
- * \param compare      Function used to compare keys.
- */
-static inline struct hash_table *hash_table_ctor(UNUSED unsigned num_buckets,
-    hash_func_t hash, hash_compare_func_t compare)
-{
-   return _mesa_hash_table_create(NULL, hash, compare);
-}
-
-/**
- * Release all memory associated with a hash table
- *
- * \warning
- * This function does not release memory occupied either by keys or data.
- */
-static inline void hash_table_dtor(struct hash_table *ht)
-{
-   return _mesa_hash_table_destroy(ht, NULL);
-}
-
-/**
- * Flush all entries from a hash table
- *
- * \param ht  Table to be cleared of its entries.
- */
-static inline void hash_table_clear(struct hash_table *ht)
-{
-   return _mesa_hash_table_clear(ht, NULL);
-}
-
-/**
- * Search a hash table for a specific element
- *
- * \param ht   Table to be searched
- * \param key  Key of the desired element
- *
- * \return
- * The \c data value supplied to \c hash_table_insert when the element with
- * the matching key was added.  If no matching key exists in the table,
- * \c NULL is returned.
- */
-static inline void *hash_table_find(struct hash_table *ht, const void *key)
-{
-   struct hash_entry *entry = _mesa_hash_table_search(ht, key);
-   if (!entry)
-      return NULL;
-   return entry->data;
-}
-
-/**
- * Add an element to a hash table
- *
- * \warning
- * The value passed by \c key is kept in the hash table and is used by later
- * calls to \c hash_table_find.
- */
-static inline void hash_table_insert(struct hash_table *ht, void *data,
-                                     const void *key)
-{
-   _mesa_hash_table_insert(ht, key, data);
-}
-
-/**
- * Remove a specific element from a hash table.
- */
-static inline void hash_table_remove(struct hash_table *ht, const void *key)
-{
-   struct hash_entry *entry = _mesa_hash_table_search(ht, key);
-
-   if (entry)
-      _mesa_hash_table_remove(ht, entry);
-}
-
-/**
- * Compute hash value of a string
- *
- * \param key  Pointer to a NUL terminated string to be hashed.
- *
- * \sa hash_table_string_compare
- */
-static unsigned
-hash_table_string_hash(const void *key)
-{
-   const char *str = (const char *) key;
-   uint32_t hash = _mesa_hash_string(str);
-   return hash;
-}
-
-/**
- * Compare two strings used as keys
- *
- * This is just a wrapper around \c strcmp.
- *
- * \sa hash_table_string_hash
- */
-static bool
-hash_table_string_compare(const void *a, const void *b)
-{
-   return _mesa_key_string_equal(a, b);
-}
-
-/**
- * Compute hash value of a pointer
- *
- * \param key  Pointer to be used as a hash key
- *
- * \note
- * The memory pointed to by \c key is \b never accessed.  The value of \c key
- * itself is used as the hash key
- *
- * \sa hash_table_pointer_compare
- */
-static unsigned
-hash_table_pointer_hash(const void *key)
-{
-   return _mesa_hash_pointer(key);
-}
-
-/**
- * Compare two pointers used as keys
- *
- * \sa hash_table_pointer_hash
- */
-static bool
-hash_table_pointer_compare(const void *key1, const void *key2)
-{
-   return _mesa_key_pointer_equal(key1, key2);
-}
-
-struct string_to_uint_map *
-string_to_uint_map_ctor();
-
-void
-string_to_uint_map_dtor(struct string_to_uint_map *);
-
-
-#ifdef __cplusplus
-}
-
-struct string_map_iterate_wrapper_closure {
-   void (*callback)(const char *key, unsigned value, void *closure);
-   void *closure;
-};
-
-/**
- * Map from a string (name) to an unsigned integer value
- *
- * \note
- * Because of the way this class interacts with the \c hash_table
- * implementation, values of \c UINT_MAX cannot be stored in the map.
- */
-struct string_to_uint_map {
-public:
-   string_to_uint_map()
-   {
-      this->ht = _mesa_hash_table_create(NULL, _mesa_key_hash_string,
-                                         _mesa_key_string_equal);
-   }
-
-   ~string_to_uint_map()
-   {
-      hash_table_call_foreach(this->ht, delete_key, NULL);
-      _mesa_hash_table_destroy(this->ht, NULL);
-   }
-
-   /**
-    * Remove all mappings from this map.
-    */
-   void clear()
-   {
-      hash_table_call_foreach(this->ht, delete_key, NULL);
-      _mesa_hash_table_clear(this->ht, NULL);
-   }
-
-   /**
-    * Runs a passed callback for the hash
-    */
-   void iterate(void (*func)(const char *, unsigned, void *), void *closure)
-   {
-      struct string_map_iterate_wrapper_closure *wrapper;
-
-      wrapper = (struct string_map_iterate_wrapper_closure *)
-         malloc(sizeof(struct string_map_iterate_wrapper_closure));
-      if (wrapper == NULL)
-         return;
-
-      wrapper->callback = func;
-      wrapper->closure = closure;
-
-      hash_table_call_foreach(this->ht, subtract_one_wrapper, wrapper);
-      free(wrapper);
-   }
-
-   /**
-    * Get the value associated with a particular key
-    *
-    * \return
-    * If \c key is found in the map, \c true is returned.  Otherwise \c false
-    * is returned.
-    *
-    * \note
-    * If \c key is not found in the table, \c value is not modified.
-    */
-   bool get(unsigned &value, const char *key)
-   {
-      hash_entry *entry = _mesa_hash_table_search(this->ht,
-                                                  (const void *) key);
-
-      if (!entry)
-         return false;
-
-      const intptr_t v = (intptr_t) entry->data;
-      value = (unsigned)(v - 1);
-      return true;
-   }
-
-   void put(unsigned value, const char *key)
-   {
-      /* The low-level hash table structure returns NULL if key is not in the
-       * hash table.  However, users of this map might want to store zero as a
-       * valid value in the table.  Bias the value by +1 so that a
-       * user-specified zero is stored as 1.  This enables ::get to tell the
-       * difference between a user-specified zero (returned as 1 by
-       * _mesa_hash_table_search) and the key not in the table (returned as 0 by
-       * _mesa_hash_table_search).
-       *
-       * The net effect is that we can't store UINT_MAX in the table.  This is
-       * because UINT_MAX+1 = 0.
-       */
-      assert(value != UINT_MAX);
-      char *dup_key = strdup(key);
-
-      struct hash_entry *entry = _mesa_hash_table_search(this->ht, dup_key);
-      if (entry) {
-         entry->data = (void *) (intptr_t) (value + 1);
-      } else {
-         _mesa_hash_table_insert(this->ht, dup_key,
-                                 (void *) (intptr_t) (value + 1));
-      }
-
-      if (entry)
-         free(dup_key);
-   }
-
-private:
-   static void delete_key(const void *key, void *data, void *closure)
-   {
-      (void) data;
-      (void) closure;
-
-      free((char *)key);
-   }
-
-   static void subtract_one_wrapper(const void *key, void *data, void *closure)
-   {
-      struct string_map_iterate_wrapper_closure *wrapper =
-         (struct string_map_iterate_wrapper_closure *) closure;
-      unsigned value = (intptr_t) data;
-
-      value -= 1;
-
-      wrapper->callback((const char *) key, value, wrapper->closure);
-   }
-
-   struct hash_table *ht;
-};
-
-#endif /* __cplusplus */
-#endif /* HASH_TABLE_H */
index e74d94f84f7a35baa3dbd889c43f2ee5776771b4..530c00fa78533d622ca04adb61e0d71cb18a8a2e 100644 (file)
 #include "compiler/glsl_types.h"
 #include "compiler/glsl/linker.h"
 #include "compiler/glsl/program.h"
-#include "program/hash_table.h"
 #include "program/prog_instruction.h"
 #include "program/prog_optimize.h"
 #include "program/prog_print.h"
 #include "program/program.h"
 #include "program/prog_parameter.h"
+#include "util/string_to_uint_map.h"
 
 
 static int swizzle_for_size(int size);
diff --git a/src/mesa/program/string_to_uint_map.cpp b/src/mesa/program/string_to_uint_map.cpp
deleted file mode 100644 (file)
index cfa73ab..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright © 2011 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file string_to_uint_map.cpp
- * \brief Dumb wrapprs so that C code can create and destroy maps.
- *
- * \author Ian Romanick <ian.d.romanick@intel.com>
- */
-#include "hash_table.h"
-
-extern "C" struct string_to_uint_map *
-string_to_uint_map_ctor()
-{
-   return new string_to_uint_map;
-}
-
-extern "C" void
-string_to_uint_map_dtor(struct string_to_uint_map *map)
-{
-   delete map;
-}
index 307bf3e3a142455df2dac10ef447529bbc737937..e6e6bb953f41dc5fb1114babb4fc178647bfde99 100644 (file)
 #include "program/prog_statevars.h"
 #include "program/prog_parameter.h"
 #include "program/ir_to_mesa.h"
-#include "program/hash_table.h"
 #include "main/mtypes.h"
 #include "main/errors.h"
 #include "main/shaderapi.h"
 #include "main/uniforms.h"
+#include "util/string_to_uint_map.h"
 
 #include "st_context.h"
 #include "st_program.h"
index c34e27b04690a4a52603cfee311d6b5342a06d32..8b17bcf8143f0fc4f98ad4fe1b75371c21e11b5f 100644 (file)
@@ -27,6 +27,8 @@ MESA_UTIL_FILES :=    \
        simple_list.h \
        slab.c \
        slab.h \
+       string_to_uint_map.h \
+       string_to_uint_map.cpp \
        strndup.c \
        strndup.h \
        strtod.c \
diff --git a/src/util/string_to_uint_map.cpp b/src/util/string_to_uint_map.cpp
new file mode 100644 (file)
index 0000000..35fb76b
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file string_to_uint_map.cpp
+ * \brief Dumb wrapprs so that C code can create and destroy maps.
+ *
+ * \author Ian Romanick <ian.d.romanick@intel.com>
+ */
+#include "string_to_uint_map.h"
+
+extern "C" struct string_to_uint_map *
+string_to_uint_map_ctor()
+{
+   return new string_to_uint_map;
+}
+
+extern "C" void
+string_to_uint_map_dtor(struct string_to_uint_map *map)
+{
+   delete map;
+}
diff --git a/src/util/string_to_uint_map.h b/src/util/string_to_uint_map.h
new file mode 100644 (file)
index 0000000..e0533ec
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef STRING_TO_UINT_MAP_H
+#define STRING_TO_UINT_MAP_H
+
+#include <string.h>
+#include <limits.h>
+#include "util/hash_table.h"
+
+struct string_to_uint_map;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct string_to_uint_map *
+string_to_uint_map_ctor();
+
+void
+string_to_uint_map_dtor(struct string_to_uint_map *);
+
+
+#ifdef __cplusplus
+}
+
+struct string_map_iterate_wrapper_closure {
+   void (*callback)(const char *key, unsigned value, void *closure);
+   void *closure;
+};
+
+/**
+ * Map from a string (name) to an unsigned integer value
+ *
+ * \note
+ * Because of the way this class interacts with the \c hash_table
+ * implementation, values of \c UINT_MAX cannot be stored in the map.
+ */
+struct string_to_uint_map {
+public:
+   string_to_uint_map()
+   {
+      this->ht = _mesa_hash_table_create(NULL, _mesa_key_hash_string,
+                                         _mesa_key_string_equal);
+   }
+
+   ~string_to_uint_map()
+   {
+      hash_table_call_foreach(this->ht, delete_key, NULL);
+      _mesa_hash_table_destroy(this->ht, NULL);
+   }
+
+   /**
+    * Remove all mappings from this map.
+    */
+   void clear()
+   {
+      hash_table_call_foreach(this->ht, delete_key, NULL);
+      _mesa_hash_table_clear(this->ht, NULL);
+   }
+
+   /**
+    * Runs a passed callback for the hash
+    */
+   void iterate(void (*func)(const char *, unsigned, void *), void *closure)
+   {
+      struct string_map_iterate_wrapper_closure *wrapper;
+
+      wrapper = (struct string_map_iterate_wrapper_closure *)
+         malloc(sizeof(struct string_map_iterate_wrapper_closure));
+      if (wrapper == NULL)
+         return;
+
+      wrapper->callback = func;
+      wrapper->closure = closure;
+
+      hash_table_call_foreach(this->ht, subtract_one_wrapper, wrapper);
+      free(wrapper);
+   }
+
+   /**
+    * Get the value associated with a particular key
+    *
+    * \return
+    * If \c key is found in the map, \c true is returned.  Otherwise \c false
+    * is returned.
+    *
+    * \note
+    * If \c key is not found in the table, \c value is not modified.
+    */
+   bool get(unsigned &value, const char *key)
+   {
+      hash_entry *entry = _mesa_hash_table_search(this->ht,
+                                                  (const void *) key);
+
+      if (!entry)
+         return false;
+
+      const intptr_t v = (intptr_t) entry->data;
+      value = (unsigned)(v - 1);
+      return true;
+   }
+
+   void put(unsigned value, const char *key)
+   {
+      /* The low-level hash table structure returns NULL if key is not in the
+       * hash table.  However, users of this map might want to store zero as a
+       * valid value in the table.  Bias the value by +1 so that a
+       * user-specified zero is stored as 1.  This enables ::get to tell the
+       * difference between a user-specified zero (returned as 1 by
+       * _mesa_hash_table_search) and the key not in the table (returned as 0 by
+       * _mesa_hash_table_search).
+       *
+       * The net effect is that we can't store UINT_MAX in the table.  This is
+       * because UINT_MAX+1 = 0.
+       */
+      assert(value != UINT_MAX);
+      char *dup_key = strdup(key);
+
+      struct hash_entry *entry = _mesa_hash_table_search(this->ht, dup_key);
+      if (entry) {
+         entry->data = (void *) (intptr_t) (value + 1);
+      } else {
+         _mesa_hash_table_insert(this->ht, dup_key,
+                                 (void *) (intptr_t) (value + 1));
+      }
+
+      if (entry)
+         free(dup_key);
+   }
+
+private:
+   static void delete_key(const void *key, void *data, void *closure)
+   {
+      (void) data;
+      (void) closure;
+
+      free((char *)key);
+   }
+
+   static void subtract_one_wrapper(const void *key, void *data, void *closure)
+   {
+      struct string_map_iterate_wrapper_closure *wrapper =
+         (struct string_map_iterate_wrapper_closure *) closure;
+      unsigned value = (intptr_t) data;
+
+      value -= 1;
+
+      wrapper->callback((const char *) key, value, wrapper->closure);
+   }
+
+   struct hash_table *ht;
+};
+
+#endif /* __cplusplus */
+#endif /* STRING_TO_UINT_MAP_H */