소스 검색

Use unordered_map when available. Changes to stl_hash.m4 provided by Oleg Smolsky.

kenton@google.com 15 년 전
부모
커밋
ee7e9420e3
3개의 변경된 파일40개의 추가작업 그리고 17개의 파일을 삭제
  1. 1 0
      CONTRIBUTORS.txt
  2. 25 14
      m4/stl_hash.m4
  3. 14 3
      src/google/protobuf/stubs/hash.h

+ 1 - 0
CONTRIBUTORS.txt

@@ -58,6 +58,7 @@ Patch contributors:
     * Slicing support for repeated scalar fields for the Python API.
   Oleg Smolsky <oleg.smolsky@gmail.com>
     * MS Visual Studio error format option.
+    * Detect unordered_map in stl_hash.m4.
   Brian Olson <brianolson@google.com>
     * gzip/zlib I/O support.
   Michael Poole <mdpoole@troilus.org>

+ 25 - 14
m4/stl_hash.m4

@@ -14,28 +14,39 @@ AC_DEFUN([AC_CXX_STL_HASH],
   [AC_MSG_CHECKING(the location of hash_map)
   AC_LANG_SAVE
    AC_LANG_CPLUSPLUS
-   ac_cv_cxx_hash_map=""
-   for location in ext/hash_map hash_map; do
-     for namespace in __gnu_cxx "" std stdext; do
-       if test -z "$ac_cv_cxx_hash_map"; then
-         AC_TRY_COMPILE([#include <$location>],
-                        [${namespace}::hash_map<int, int> t],
-                        [ac_cv_cxx_hash_map="<$location>";
-                         ac_cv_cxx_hash_namespace="$namespace";])
-       fi
+   ac_cv_cxx_hash_map_header=""
+   ac_cv_cxx_hash_map_class=""
+   for location in [tr1/unordered_map ext/hash_map hash_map]; do
+     for namespace in [std::tr1 __gnu_cxx "" std stdext]; do
+       for name in [unordered_map hash_map]; do
+
+         if test -z "$ac_cv_cxx_hash_map_header"; then
+
+           AC_TRY_COMPILE([#include <$location>],
+                          [${namespace}::$name<int, int> t],
+                          [ac_cv_cxx_hash_map_header="<$location>";
+                           ac_cv_cxx_hash_namespace="$namespace";
+                           ac_cv_cxx_hash_map_class="$name";])
+         fi
+       done
      done
    done
-   ac_cv_cxx_hash_set=`echo "$ac_cv_cxx_hash_map" | sed s/map/set/`;
-   if test -n "$ac_cv_cxx_hash_map"; then
+   ac_cv_cxx_hash_set_header=`echo "$ac_cv_cxx_hash_map_header" | sed s/map/set/`;
+   ac_cv_cxx_hash_set_class=`echo "$ac_cv_cxx_hash_map_class" | sed s/map/set/`;
+   if test -n "$ac_cv_cxx_hash_map_header"; then
       AC_DEFINE(HAVE_HASH_MAP, 1, [define if the compiler has hash_map])
       AC_DEFINE(HAVE_HASH_SET, 1, [define if the compiler has hash_set])
-      AC_DEFINE_UNQUOTED(HASH_MAP_H,$ac_cv_cxx_hash_map,
+      AC_DEFINE_UNQUOTED(HASH_MAP_H,$ac_cv_cxx_hash_map_header,
                          [the location of <hash_map>])
-      AC_DEFINE_UNQUOTED(HASH_SET_H,$ac_cv_cxx_hash_set,
+      AC_DEFINE_UNQUOTED(HASH_SET_H,$ac_cv_cxx_hash_set_header,
                          [the location of <hash_set>])
+      AC_DEFINE_UNQUOTED(HASH_MAP_CLASS,$ac_cv_cxx_hash_map_class,
+                         [the name of <hash_set>])
+      AC_DEFINE_UNQUOTED(HASH_SET_CLASS,$ac_cv_cxx_hash_set_class,
+                         [the name of <hash_set>])
       AC_DEFINE_UNQUOTED(HASH_NAMESPACE,$ac_cv_cxx_hash_namespace,
                          [the namespace of hash_map/hash_set])
-      AC_MSG_RESULT([$ac_cv_cxx_hash_map])
+      AC_MSG_RESULT([$ac_cv_cxx_hash_map_header])
    else
       AC_MSG_RESULT()
       AC_MSG_WARN([could not find an STL hash_map])

+ 14 - 3
src/google/protobuf/stubs/hash.h

@@ -48,6 +48,8 @@
 #include <set>
 #endif
 
+#include <ext/hash_map>
+
 namespace google {
 namespace protobuf {
 
@@ -145,21 +147,30 @@ struct hash<const Key*> {
   }
 };
 
+// Unlike the old SGI version, the TR1 "hash" does not special-case char*.  So,
+// we go ahead and provide our own implementation.
 template <>
-struct hash<const char*> : public HASH_NAMESPACE::hash<const char*> {
+struct hash<const char*> {
+  inline size_t operator()(const char* str) const {
+    size_t result = 0;
+    for (; *str != '\0'; str++) {
+      result = 5 * result + *str;
+    }
+    return result;
+  }
 };
 
 template <typename Key, typename Data,
           typename HashFcn = hash<Key>,
           typename EqualKey = std::equal_to<Key> >
-class hash_map : public HASH_NAMESPACE::hash_map<
+class hash_map : public HASH_NAMESPACE::HASH_MAP_CLASS<
     Key, Data, HashFcn, EqualKey> {
 };
 
 template <typename Key,
           typename HashFcn = hash<Key>,
           typename EqualKey = std::equal_to<Key> >
-class hash_set : public HASH_NAMESPACE::hash_set<
+class hash_set : public HASH_NAMESPACE::HASH_SET_CLASS<
     Key, HashFcn, EqualKey> {
 };