google_hash 0.8.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. data/ChangeLog.txt +2 -0
  2. data/VERSION +1 -1
  3. data/ext/clean.bat +0 -0
  4. data/ext/clean.sh +4 -0
  5. data/ext/extconf.rb +4 -5
  6. data/ext/go.bat +0 -0
  7. data/ext/sparsehash-2.0.2/AUTHORS +2 -0
  8. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/COPYING +0 -0
  9. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/ChangeLog +60 -0
  10. data/ext/sparsehash-2.0.2/INSTALL +365 -0
  11. data/ext/sparsehash-2.0.2/Makefile +1336 -0
  12. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/Makefile.am +97 -40
  13. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/Makefile.in +538 -256
  14. data/ext/sparsehash-2.0.2/NEWS +188 -0
  15. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/README +4 -10
  16. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/README_windows.txt +3 -3
  17. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/TODO +0 -0
  18. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/aclocal.m4 +266 -166
  19. data/ext/sparsehash-2.0.2/allocator.patch +31 -0
  20. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/config.guess +235 -234
  21. data/ext/sparsehash-2.0.2/config.status +1238 -0
  22. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/config.sub +198 -64
  23. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/configure +1118 -1000
  24. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/configure.ac +4 -5
  25. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/depcomp +136 -36
  26. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/dense_hash_map.html +182 -67
  27. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/dense_hash_set.html +173 -74
  28. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/designstyle.css +0 -6
  29. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/implementation.html +0 -0
  30. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/index.html +4 -5
  31. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/performance.html +1 -1
  32. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/sparse_hash_map.html +190 -58
  33. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/sparse_hash_set.html +180 -65
  34. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/doc/sparsetable.html +1 -1
  35. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/Makefile +0 -0
  36. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/README +0 -0
  37. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/example.c +1 -0
  38. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/libchash.c +1 -0
  39. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/experimental/libchash.h +1 -0
  40. data/ext/sparsehash-2.0.2/install-sh +520 -0
  41. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/acx_pthread.m4 +34 -0
  42. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/google_namespace.m4 +0 -0
  43. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/namespaces.m4 +0 -0
  44. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/stl_hash.m4 +0 -0
  45. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/m4/stl_hash_fun.m4 +0 -0
  46. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/missing +60 -44
  47. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb.sh +0 -0
  48. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/README +0 -0
  49. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/changelog +42 -0
  50. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/compat +0 -0
  51. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/control +1 -1
  52. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/copyright +5 -4
  53. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/docs +0 -0
  54. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/deb/rules +0 -0
  55. data/ext/sparsehash-2.0.2/packages/deb/sparsehash.dirs +5 -0
  56. data/ext/sparsehash-2.0.2/packages/deb/sparsehash.install +6 -0
  57. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/rpm.sh +1 -1
  58. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/packages/rpm/rpm.spec +5 -3
  59. data/ext/{sparsehash-1.8.1/google-sparsehash.sln → sparsehash-2.0.2/sparsehash.sln} +0 -0
  60. data/ext/sparsehash-2.0.2/src/config.h +132 -0
  61. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/config.h.in +0 -3
  62. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/config.h.include +0 -1
  63. data/ext/sparsehash-2.0.2/src/google/dense_hash_map +34 -0
  64. data/ext/sparsehash-2.0.2/src/google/dense_hash_set +34 -0
  65. data/ext/sparsehash-2.0.2/src/google/sparse_hash_map +34 -0
  66. data/ext/sparsehash-2.0.2/src/google/sparse_hash_set +34 -0
  67. data/ext/sparsehash-2.0.2/src/google/sparsehash/densehashtable.h +34 -0
  68. data/ext/sparsehash-2.0.2/src/google/sparsehash/hashtable-common.h +34 -0
  69. data/ext/sparsehash-2.0.2/src/google/sparsehash/libc_allocator_with_realloc.h +34 -0
  70. data/ext/sparsehash-2.0.2/src/google/sparsehash/sparsehashtable.h +34 -0
  71. data/ext/sparsehash-2.0.2/src/google/sparsetable +34 -0
  72. data/ext/sparsehash-2.0.2/src/google/template_util.h +34 -0
  73. data/ext/sparsehash-2.0.2/src/google/type_traits.h +34 -0
  74. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/hash_test_interface.h +64 -37
  75. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/hashtable_test.cc +415 -141
  76. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/libc_allocator_with_realloc_test.cc +16 -23
  77. data/ext/sparsehash-2.0.2/src/simple_compat_test.cc +106 -0
  78. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/simple_test.cc +8 -5
  79. data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/dense_hash_map +80 -37
  80. data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/dense_hash_set +64 -34
  81. data/ext/{sparsehash-1.8.1/src/google/sparsehash → sparsehash-2.0.2/src/sparsehash/internal}/densehashtable.h +247 -173
  82. data/ext/sparsehash-2.0.2/src/sparsehash/internal/hashtable-common.h +381 -0
  83. data/ext/{sparsehash-1.8.1/src/google/sparsehash → sparsehash-2.0.2/src/sparsehash/internal}/libc_allocator_with_realloc.h +5 -7
  84. data/ext/{sparsehash-1.8.1/src/google/sparsehash → sparsehash-2.0.2/src/sparsehash/internal}/sparsehashtable.h +154 -93
  85. data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/sparse_hash_map +96 -36
  86. data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/sparse_hash_set +85 -32
  87. data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/sparsetable +520 -258
  88. data/ext/sparsehash-2.0.2/src/sparsehash/template_util.h +134 -0
  89. data/ext/{sparsehash-1.8.1/src/google → sparsehash-2.0.2/src/sparsehash}/type_traits.h +153 -35
  90. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/sparsetable_unittest.cc +108 -22
  91. data/ext/sparsehash-2.0.2/src/stamp-h1 +1 -0
  92. data/ext/sparsehash-2.0.2/src/template_util_unittest.cc +134 -0
  93. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/testutil.h +16 -1
  94. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/time_hash_map.cc +259 -94
  95. data/ext/sparsehash-2.0.2/src/type_traits_unittest.cc +636 -0
  96. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/windows/config.h +4 -4
  97. data/ext/sparsehash-2.0.2/src/windows/google/sparsehash/sparseconfig.h +49 -0
  98. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/windows/port.cc +1 -0
  99. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/src/windows/port.h +4 -13
  100. data/ext/sparsehash-2.0.2/src/windows/sparsehash/internal/sparseconfig.h +49 -0
  101. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/hashtable_test/hashtable_test.vcproj +11 -11
  102. data/ext/sparsehash-2.0.2/vsprojects/libc_allocator_with_realloc_test/libc_allocator_with_realloc_test.vcproj +161 -0
  103. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/simple_test/simple_test.vcproj +10 -10
  104. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/sparsetable_unittest/sparsetable_unittest.vcproj +4 -4
  105. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/time_hash_map/time_hash_map.vcproj +10 -10
  106. data/ext/{sparsehash-1.8.1 → sparsehash-2.0.2}/vsprojects/type_traits_unittest/type_traits_unittest.vcproj +3 -3
  107. data/ext/spec.bat +0 -0
  108. data/ext/template/google_hash.cpp.erb +6 -5
  109. metadata +106 -86
  110. data/ext/sparsehash-1.8.1/AUTHORS +0 -2
  111. data/ext/sparsehash-1.8.1/INSTALL +0 -236
  112. data/ext/sparsehash-1.8.1/NEWS +0 -71
  113. data/ext/sparsehash-1.8.1/compile +0 -99
  114. data/ext/sparsehash-1.8.1/install-sh +0 -323
  115. data/ext/sparsehash-1.8.1/m4/stl_namespace.m4 +0 -25
  116. data/ext/sparsehash-1.8.1/mkinstalldirs +0 -158
  117. data/ext/sparsehash-1.8.1/packages/deb/sparsehash.dirs +0 -2
  118. data/ext/sparsehash-1.8.1/packages/deb/sparsehash.install +0 -2
  119. data/ext/sparsehash-1.8.1/src/google/sparsehash/hashtable-common.h +0 -178
  120. data/ext/sparsehash-1.8.1/src/type_traits_unittest.cc +0 -502
  121. data/ext/sparsehash-1.8.1/src/windows/google/sparsehash/sparseconfig.h +0 -32
@@ -0,0 +1,34 @@
1
+ // Copyright (c) 2012, Google Inc.
2
+ // All rights reserved.
3
+ //
4
+ // Redistribution and use in source and binary forms, with or without
5
+ // modification, are permitted provided that the following conditions are
6
+ // met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright
9
+ // notice, this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above
11
+ // copyright notice, this list of conditions and the following disclaimer
12
+ // in the documentation and/or other materials provided with the
13
+ // distribution.
14
+ // * Neither the name of Google Inc. nor the names of its
15
+ // contributors may be used to endorse or promote products derived from
16
+ // this software without specific prior written permission.
17
+ //
18
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ // Header files have moved from the google directory to the sparsehash
31
+ // directory. This forwarding file is provided only for backwards
32
+ // compatibility. Use <sparsehash/*> in all new code.
33
+
34
+ #include <sparsehash/template_util.h>
@@ -0,0 +1,34 @@
1
+ // Copyright (c) 2012, Google Inc.
2
+ // All rights reserved.
3
+ //
4
+ // Redistribution and use in source and binary forms, with or without
5
+ // modification, are permitted provided that the following conditions are
6
+ // met:
7
+ //
8
+ // * Redistributions of source code must retain the above copyright
9
+ // notice, this list of conditions and the following disclaimer.
10
+ // * Redistributions in binary form must reproduce the above
11
+ // copyright notice, this list of conditions and the following disclaimer
12
+ // in the documentation and/or other materials provided with the
13
+ // distribution.
14
+ // * Neither the name of Google Inc. nor the names of its
15
+ // contributors may be used to endorse or promote products derived from
16
+ // this software without specific prior written permission.
17
+ //
18
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ // Header files have moved from the google directory to the sparsehash
31
+ // directory. This forwarding file is provided only for backwards
32
+ // compatibility. Use <sparsehash/*> in all new code.
33
+
34
+ #include <sparsehash/type_traits.h>
@@ -27,8 +27,7 @@
27
27
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
28
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
29
 
30
- // ----
31
- // Author: Craig Silverstein
30
+ // ---
32
31
  //
33
32
  // This implements a uniform interface for all 6 hash implementations:
34
33
  // dense_hashtable, dense_hash_map, dense_hash_set
@@ -46,15 +45,15 @@
46
45
  #ifndef UTIL_GTL_HASH_TEST_INTERFACE_H_
47
46
  #define UTIL_GTL_HASH_TEST_INTERFACE_H_
48
47
 
49
- #include "config.h"
50
- #include HASH_MAP_H // for hash<>
51
- #include <functional> // for equal_to<>
52
- #include <google/sparsehash/sparsehashtable.h>
53
- #include <google/sparse_hash_map>
54
- #include <google/sparse_hash_set>
55
- #include <google/sparsehash/densehashtable.h>
56
- #include <google/dense_hash_map>
57
- #include <google/dense_hash_set>
48
+ #include <sparsehash/internal/sparseconfig.h>
49
+ #include <functional> // for equal_to<>
50
+ #include <sparsehash/internal/sparsehashtable.h>
51
+ #include <sparsehash/sparse_hash_map>
52
+ #include <sparsehash/sparse_hash_set>
53
+ #include <sparsehash/internal/densehashtable.h>
54
+ #include <sparsehash/dense_hash_map>
55
+ #include <sparsehash/dense_hash_set>
56
+ #include HASH_FUN_H // for hash<>
58
57
 
59
58
  _START_GOOGLE_NAMESPACE_
60
59
 
@@ -271,17 +270,18 @@ class BaseHashtableInterface {
271
270
 
272
271
  size_type count(const key_type& key) const { return ht_.count(key); }
273
272
 
274
- pair<iterator, iterator> equal_range(const key_type& key) {
275
- pair<typename HT::iterator, typename HT::iterator> r
273
+ std::pair<iterator, iterator> equal_range(const key_type& key) {
274
+ std::pair<typename HT::iterator, typename HT::iterator> r
276
275
  = ht_.equal_range(key);
277
- return pair<iterator, iterator>(iterator(r.first, this),
276
+ return std::pair<iterator, iterator>(iterator(r.first, this),
278
277
  iterator(r.second, this));
279
278
  }
280
- pair<const_iterator, const_iterator> equal_range(const key_type& key) const {
281
- pair<typename HT::const_iterator, typename HT::const_iterator> r
279
+ std::pair<const_iterator, const_iterator> equal_range(const key_type& key)
280
+ const {
281
+ std::pair<typename HT::const_iterator, typename HT::const_iterator> r
282
282
  = ht_.equal_range(key);
283
- return pair<const_iterator, const_iterator>(const_iterator(r.first, this),
284
- const_iterator(r.second, this));
283
+ return std::pair<const_iterator, const_iterator>(
284
+ const_iterator(r.first, this), const_iterator(r.second, this));
285
285
  }
286
286
 
287
287
  const_iterator random_element(class ACMRandom* r) const {
@@ -291,9 +291,9 @@ class BaseHashtableInterface {
291
291
  return iterator(ht_.random_element(r), this);
292
292
  }
293
293
 
294
- pair<iterator, bool> insert(const value_type& obj) {
295
- pair<typename HT::iterator, bool> r = ht_.insert(obj);
296
- return pair<iterator, bool>(iterator(r.first, this), r.second);
294
+ std::pair<iterator, bool> insert(const value_type& obj) {
295
+ std::pair<typename HT::iterator, bool> r = ht_.insert(obj);
296
+ return std::pair<iterator, bool>(iterator(r.first, this), r.second);
297
297
  }
298
298
  template <class InputIterator>
299
299
  void insert(InputIterator f, InputIterator l) {
@@ -328,6 +328,15 @@ class BaseHashtableInterface {
328
328
  return ht_ != other.ht_;
329
329
  }
330
330
 
331
+ template <typename ValueSerializer, typename OUTPUT>
332
+ bool serialize(ValueSerializer serializer, OUTPUT *fp) {
333
+ return ht_.serialize(serializer, fp);
334
+ }
335
+ template <typename ValueSerializer, typename INPUT>
336
+ bool unserialize(ValueSerializer serializer, INPUT *fp) {
337
+ return ht_.unserialize(serializer, fp);
338
+ }
339
+
331
340
  template <typename OUTPUT>
332
341
  bool write_metadata(OUTPUT *fp) {
333
342
  return ht_.write_metadata(fp);
@@ -364,6 +373,7 @@ class BaseHashtableInterface {
364
373
  virtual bool supports_brackets() const = 0; // has a 'real' operator[]
365
374
  virtual bool supports_readwrite() const = 0;
366
375
  virtual bool supports_num_table_copies() const = 0;
376
+ virtual bool supports_serialization() const = 0;
367
377
 
368
378
  protected:
369
379
  HT ht_;
@@ -378,9 +388,9 @@ class BaseHashtableInterface {
378
388
  // ---------------------------------------------------------------------
379
389
 
380
390
  template <class Key, class T,
381
- class HashFcn = HASH_NAMESPACE::hash<Key>,
382
- class EqualKey = STL_NAMESPACE::equal_to<Key>,
383
- class Alloc = libc_allocator_with_realloc<pair<const Key, T> > >
391
+ class HashFcn = SPARSEHASH_HASH<Key>,
392
+ class EqualKey = std::equal_to<Key>,
393
+ class Alloc = libc_allocator_with_realloc<std::pair<const Key, T> > >
384
394
  class HashtableInterface_SparseHashMap
385
395
  : public BaseHashtableInterface< sparse_hash_map<Key, T, HashFcn,
386
396
  EqualKey, Alloc> > {
@@ -421,12 +431,16 @@ class HashtableInterface_SparseHashMap
421
431
  bool supports_brackets() const { return true; }
422
432
  bool supports_readwrite() const { return true; }
423
433
  bool supports_num_table_copies() const { return false; }
434
+ bool supports_serialization() const { return true; }
424
435
 
425
436
  void set_empty_key(const typename p::key_type& k) { }
426
437
  void clear_empty_key() { }
427
438
  typename p::key_type empty_key() const { return typename p::key_type(); }
439
+
428
440
  int num_table_copies() const { return 0; }
429
441
 
442
+ typedef typename ht::NopointerSerializer NopointerSerializer;
443
+
430
444
  protected:
431
445
  template <class K2, class T2, class H2, class E2, class A2>
432
446
  friend void swap(HashtableInterface_SparseHashMap<K2,T2,H2,E2,A2>& a,
@@ -456,8 +470,8 @@ void swap(HashtableInterface_SparseHashMap<K,T,H,E,A>& a,
456
470
  // ---------------------------------------------------------------------
457
471
 
458
472
  template <class Value,
459
- class HashFcn = HASH_NAMESPACE::hash<Value>,
460
- class EqualKey = STL_NAMESPACE::equal_to<Value>,
473
+ class HashFcn = SPARSEHASH_HASH<Value>,
474
+ class EqualKey = std::equal_to<Value>,
461
475
  class Alloc = libc_allocator_with_realloc<Value> >
462
476
  class HashtableInterface_SparseHashSet
463
477
  : public BaseHashtableInterface< sparse_hash_set<Value, HashFcn,
@@ -524,12 +538,16 @@ class HashtableInterface_SparseHashSet
524
538
  bool supports_brackets() const { return false; }
525
539
  bool supports_readwrite() const { return true; }
526
540
  bool supports_num_table_copies() const { return false; }
541
+ bool supports_serialization() const { return true; }
527
542
 
528
543
  void set_empty_key(const typename p::key_type& k) { }
529
544
  void clear_empty_key() { }
530
545
  typename p::key_type empty_key() const { return typename p::key_type(); }
546
+
531
547
  int num_table_copies() const { return 0; }
532
548
 
549
+ typedef typename ht::NopointerSerializer NopointerSerializer;
550
+
533
551
  protected:
534
552
  template <class K2, class H2, class E2, class A2>
535
553
  friend void swap(HashtableInterface_SparseHashSet<K2,H2,E2,A2>& a,
@@ -636,6 +654,7 @@ class HashtableInterface_SparseHashtable
636
654
  bool supports_brackets() const { return false; }
637
655
  bool supports_readwrite() const { return true; }
638
656
  bool supports_num_table_copies() const { return true; }
657
+ bool supports_serialization() const { return true; }
639
658
 
640
659
  void set_empty_key(const typename p::key_type& k) { }
641
660
  void clear_empty_key() { }
@@ -647,6 +666,8 @@ class HashtableInterface_SparseHashtable
647
666
 
648
667
  // TODO(csilvers): also support/test destructive_begin()/destructive_end()?
649
668
 
669
+ typedef typename ht::NopointerSerializer NopointerSerializer;
670
+
650
671
  protected:
651
672
  template <class V2, class K2, class HF2, class EK2, class SK2, class Eq2,
652
673
  class A2>
@@ -684,9 +705,9 @@ void swap(HashtableInterface_SparseHashtable<V,K,HF,EK,SK,Eq,A>& a,
684
705
  // value saying what the empty key is.
685
706
 
686
707
  template <class Key, class T, const Key& EMPTY_KEY,
687
- class HashFcn = HASH_NAMESPACE::hash<Key>,
688
- class EqualKey = STL_NAMESPACE::equal_to<Key>,
689
- class Alloc = libc_allocator_with_realloc<pair<const Key, T> > >
708
+ class HashFcn = SPARSEHASH_HASH<Key>,
709
+ class EqualKey = std::equal_to<Key>,
710
+ class Alloc = libc_allocator_with_realloc<std::pair<const Key, T> > >
690
711
  class HashtableInterface_DenseHashMap
691
712
  : public BaseHashtableInterface< dense_hash_map<Key, T, HashFcn,
692
713
  EqualKey, Alloc> > {
@@ -733,9 +754,11 @@ class HashtableInterface_DenseHashMap
733
754
  bool supports_brackets() const { return true; }
734
755
  bool supports_readwrite() const { return false; }
735
756
  bool supports_num_table_copies() const { return false; }
757
+ bool supports_serialization() const { return true; }
736
758
 
737
- template <typename OUTPUT> bool write_metadata(OUTPUT *fp) { return false; }
738
- template <typename INPUT> bool read_metadata(INPUT *fp) { return false; }
759
+ typedef typename ht::NopointerSerializer NopointerSerializer;
760
+ template <typename OUTPUT> bool write_metadata(OUTPUT *) { return false; }
761
+ template <typename INPUT> bool read_metadata(INPUT *) { return false; }
739
762
  template <typename OUTPUT> bool write_nopointer_data(OUTPUT *) {
740
763
  return false;
741
764
  }
@@ -776,8 +799,8 @@ void swap(HashtableInterface_DenseHashMap<K,T,Empty,H,E,A>& a,
776
799
  // value saying what the empty key is.
777
800
 
778
801
  template <class Value, const Value& EMPTY_KEY,
779
- class HashFcn = HASH_NAMESPACE::hash<Value>,
780
- class EqualKey = STL_NAMESPACE::equal_to<Value>,
802
+ class HashFcn = SPARSEHASH_HASH<Value>,
803
+ class EqualKey = std::equal_to<Value>,
781
804
  class Alloc = libc_allocator_with_realloc<Value> >
782
805
  class HashtableInterface_DenseHashSet
783
806
  : public BaseHashtableInterface< dense_hash_set<Value, HashFcn,
@@ -835,9 +858,11 @@ class HashtableInterface_DenseHashSet
835
858
  bool supports_brackets() const { return false; }
836
859
  bool supports_readwrite() const { return false; }
837
860
  bool supports_num_table_copies() const { return false; }
861
+ bool supports_serialization() const { return true; }
838
862
 
839
- template <typename OUTPUT> bool write_metadata(OUTPUT *fp) { return false; }
840
- template <typename INPUT> bool read_metadata(INPUT *fp) { return false; }
863
+ typedef typename ht::NopointerSerializer NopointerSerializer;
864
+ template <typename OUTPUT> bool write_metadata(OUTPUT *) { return false; }
865
+ template <typename INPUT> bool read_metadata(INPUT *) { return false; }
841
866
  template <typename OUTPUT> bool write_nopointer_data(OUTPUT *) {
842
867
  return false;
843
868
  }
@@ -960,9 +985,11 @@ class HashtableInterface_DenseHashtable
960
985
  bool supports_brackets() const { return false; }
961
986
  bool supports_readwrite() const { return false; }
962
987
  bool supports_num_table_copies() const { return true; }
988
+ bool supports_serialization() const { return true; }
963
989
 
964
- template <typename OUTPUT> bool write_metadata(OUTPUT *fp) { return false; }
965
- template <typename INPUT> bool read_metadata(INPUT *fp) { return false; }
990
+ typedef typename ht::NopointerSerializer NopointerSerializer;
991
+ template <typename OUTPUT> bool write_metadata(OUTPUT *) { return false; }
992
+ template <typename INPUT> bool read_metadata(INPUT *) { return false; }
966
993
  template <typename OUTPUT> bool write_nopointer_data(OUTPUT *) {
967
994
  return false;
968
995
  }
@@ -27,71 +27,86 @@
27
27
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
28
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
29
 
30
- // ----
31
- // Author: Craig Silverstein
30
+ // ---
32
31
  //
33
- // This tests common/densehashtable.h
34
- // This tests common/dense_hash_set.h
35
- // This tests common/dense_hash_map.h
36
- // This tests common/sparsehashtable.h
37
- // This tests common/sparse_hash_set.h
38
- // This tests common/sparse_hash_map.h
32
+ // This tests densehashtable
33
+ // This tests dense_hash_set
34
+ // This tests dense_hash_map
35
+ // This tests sparsehashtable
36
+ // This tests sparse_hash_set
37
+ // This tests sparse_hash_map
39
38
  //
40
- // This test replacess hashtable_unittest.cc, which was becoming
41
- // unreadable.
39
+ // This test replaces hashtable_unittest.cc, which was becoming
40
+ // unreadable. This file is opaque but hopefully not unreadable -- at
41
+ // least, not the tests!
42
42
  //
43
43
  // Note that since all these classes are templatized, it's important
44
44
  // to call every public method on the class: not just to make sure
45
45
  // they work, but to make sure they even compile.
46
46
 
47
- #ifdef _MSC_VER
48
- // Below, we purposefully test having a very small allocator size.
49
- // This causes some "type conversion too small" errors when using this
50
- // allocator with sparsetable buckets. We're testing to make sure we
51
- // handle that situation ok, so we don't need the compiler warnings.
52
- #pragma warning(disable:4244)
53
- #endif
54
-
55
- #include "config.h"
47
+ #include <sparsehash/internal/sparseconfig.h>
48
+ #include <config.h>
56
49
  #include <math.h>
50
+ #include <stddef.h> // for size_t
57
51
  #include <stdlib.h>
58
52
  #include <string.h>
53
+ #ifdef HAVE_STDINT_H
54
+ # include <stdint.h>
55
+ #endif // for uintptr_t
59
56
  #include <iostream>
60
57
  #include <set>
58
+ #include <sstream>
59
+ #include <typeinfo> // for class typeinfo (returned by typeid)
61
60
  #include <vector>
62
- #include <google/type_traits.h>
63
- #include <google/sparsetable>
61
+ #include <sparsehash/type_traits.h>
62
+ #include <sparsehash/sparsetable>
64
63
  #include "hash_test_interface.h"
65
64
  #include "testutil.h"
65
+ namespace testing = GOOGLE_NAMESPACE::testing;
66
66
 
67
- using GOOGLE_NAMESPACE::sparsetable;
68
- using GOOGLE_NAMESPACE::sparse_hash_map;
69
- using GOOGLE_NAMESPACE::sparse_hash_set;
67
+ using std::cout;
68
+ using std::pair;
69
+ using std::set;
70
+ using std::string;
71
+ using std::vector;
70
72
  using GOOGLE_NAMESPACE::dense_hash_map;
71
73
  using GOOGLE_NAMESPACE::dense_hash_set;
74
+ using GOOGLE_NAMESPACE::sparse_hash_map;
75
+ using GOOGLE_NAMESPACE::sparse_hash_set;
76
+ using GOOGLE_NAMESPACE::sparsetable;
72
77
  using GOOGLE_NAMESPACE::HashtableInterface_SparseHashMap;
73
78
  using GOOGLE_NAMESPACE::HashtableInterface_SparseHashSet;
74
79
  using GOOGLE_NAMESPACE::HashtableInterface_SparseHashtable;
75
80
  using GOOGLE_NAMESPACE::HashtableInterface_DenseHashMap;
76
81
  using GOOGLE_NAMESPACE::HashtableInterface_DenseHashSet;
77
82
  using GOOGLE_NAMESPACE::HashtableInterface_DenseHashtable;
78
- namespace testing = GOOGLE_NAMESPACE::testing;
79
- using STL_NAMESPACE::cout;
80
- using STL_NAMESPACE::pair;
81
- using STL_NAMESPACE::set;
82
- using STL_NAMESPACE::string;
83
- using STL_NAMESPACE::vector;
83
+ namespace sparsehash_internal = GOOGLE_NAMESPACE::sparsehash_internal;
84
+
85
+ typedef unsigned char uint8;
86
+
87
+ #ifdef _MSC_VER
88
+ // Below, we purposefully test having a very small allocator size.
89
+ // This causes some "type conversion too small" errors when using this
90
+ // allocator with sparsetable buckets. We're testing to make sure we
91
+ // handle that situation ok, so we don't need the compiler warnings.
92
+ #pragma warning(disable:4244)
93
+ #endif
84
94
 
85
95
  namespace {
86
96
 
87
97
  #ifndef _MSC_VER // windows defines its own version
98
+ # ifdef __MINGW32__ // mingw has trouble writing to /tmp
99
+ static string TmpFile(const char* basename) {
100
+ return string("./#") + basename;
101
+ }
102
+ # else
88
103
  static string TmpFile(const char* basename) {
89
- return string("/tmp/") + basename;
104
+ string kTmpdir = "/tmp";
105
+ return kTmpdir + "/" + basename;
90
106
  }
107
+ # endif
91
108
  #endif
92
109
 
93
- typedef unsigned char uint8;
94
-
95
110
  // Used as a value in some of the hashtable tests. It's just some
96
111
  // arbitrary user-defined type with non-trivial memory management.
97
112
  struct ValueType {
@@ -161,6 +176,10 @@ struct Hasher {
161
176
  hash = 33 * hash + a[i];
162
177
  return hash;
163
178
  }
179
+ size_t operator()(const int* a) const {
180
+ num_hashes_++;
181
+ return static_cast<size_t>(reinterpret_cast<uintptr_t>(a));
182
+ }
164
183
  bool operator()(int a, int b) const {
165
184
  num_compares_++;
166
185
  return a == b;
@@ -257,11 +276,13 @@ struct Alloc {
257
276
  // be their own inverse: f(f(x)) == x.
258
277
  template<class Value>
259
278
  struct Negation {
279
+ typedef Value result_type;
260
280
  Value operator()(Value& v) { return -v; }
261
281
  const Value operator()(const Value& v) const { return -v; }
262
282
  };
263
283
 
264
284
  struct Capital {
285
+ typedef string result_type;
265
286
  string operator()(string& s) {
266
287
  return string(1, s[0] ^ 32) + s.substr(1);
267
288
  }
@@ -271,6 +292,7 @@ struct Capital {
271
292
  };
272
293
 
273
294
  struct Identity { // lame, I know, but an important case to test.
295
+ typedef const char* result_type;
274
296
  const char* operator()(const char* s) const {
275
297
  return s;
276
298
  }
@@ -328,8 +350,67 @@ template<> pair<const char* const,ValueType> UniqueObjectHelper(int index) {
328
350
  UniqueObjectHelper<char*>(index), UniqueObjectHelper<ValueType>(index+1));
329
351
  }
330
352
 
353
+ class ValueSerializer {
354
+ public:
355
+ bool operator()(FILE* fp, const int& value) {
356
+ return fwrite(&value, sizeof(value), 1, fp) == 1;
357
+ }
358
+ bool operator()(FILE* fp, int* value) {
359
+ return fread(value, sizeof(*value), 1, fp) == 1;
360
+ }
361
+ bool operator()(FILE* fp, const string& value) {
362
+ const int size = value.size();
363
+ return (*this)(fp, size) && fwrite(value.c_str(), size, 1, fp) == 1;
364
+ }
365
+ bool operator()(FILE* fp, string* value) {
366
+ int size;
367
+ if (!(*this)(fp, &size)) return false;
368
+ char* buf = new char[size];
369
+ if (fread(buf, size, 1, fp) != 1) {
370
+ delete[] buf;
371
+ return false;
372
+ }
373
+ new(value) string(buf, size);
374
+ delete[] buf;
375
+ return true;
376
+ }
377
+ template <typename OUTPUT>
378
+ bool operator()(OUTPUT* fp, const ValueType& v) {
379
+ return (*this)(fp, string(v.s()));
380
+ }
381
+ template <typename INPUT>
382
+ bool operator()(INPUT* fp, ValueType* v) {
383
+ string data;
384
+ if (!(*this)(fp, &data)) return false;
385
+ new(v) ValueType(data.c_str());
386
+ return true;
387
+ }
388
+ template <typename OUTPUT>
389
+ bool operator()(OUTPUT* fp, const char* const& value) {
390
+ // Just store the index.
391
+ return (*this)(fp, atoi(value));
392
+ }
393
+ template <typename INPUT>
394
+ bool operator()(INPUT* fp, const char** value) {
395
+ // Look up via index.
396
+ int index;
397
+ if (!(*this)(fp, &index)) return false;
398
+ *value = UniqueObjectHelper<char*>(index);
399
+ return true;
400
+ }
401
+ template <typename OUTPUT, typename First, typename Second>
402
+ bool operator()(OUTPUT* fp, std::pair<const First, Second>* value) {
403
+ return (*this)(fp, const_cast<First*>(&value->first))
404
+ && (*this)(fp, &value->second);
405
+ }
406
+ template <typename INPUT, typename First, typename Second>
407
+ bool operator()(INPUT* fp, const std::pair<const First, Second>& value) {
408
+ return (*this)(fp, value.first) && (*this)(fp, value.second);
409
+ }
410
+ };
411
+
331
412
  template <typename HashtableType>
332
- class HashtableTest {
413
+ class HashtableTest : public ::testing::Test {
333
414
  public:
334
415
  HashtableTest() : ht_() { }
335
416
  // Give syntactically-prettier access to UniqueObjectHelper.
@@ -419,27 +500,58 @@ namespace {
419
500
  // We need to define the same class 4 times due to limitations in the
420
501
  // testing framework. Basically, we associate each class below with
421
502
  // the set of types we want to run tests on it with.
422
- typedef testing::TypeList6<INT_HASHTABLES> IntHashtables;
423
503
  template <typename HashtableType> class HashtableIntTest
424
504
  : public HashtableTest<HashtableType> { };
425
- TYPED_TEST_CASE_6(HashtableIntTest, IntHashtables);
426
-
427
- typedef testing::TypeList6<STRING_HASHTABLES> StringHashtables;
428
505
  template <typename HashtableType> class HashtableStringTest
429
506
  : public HashtableTest<HashtableType> { };
430
- TYPED_TEST_CASE_6(HashtableStringTest, StringHashtables);
431
-
432
- typedef testing::TypeList6<CHARSTAR_HASHTABLES> CharStarHashtables;
433
507
  template <typename HashtableType> class HashtableCharStarTest
434
508
  : public HashtableTest<HashtableType> { };
435
- TYPED_TEST_CASE_6(HashtableCharStarTest, CharStarHashtables);
509
+ template <typename HashtableType> class HashtableAllTest
510
+ : public HashtableTest<HashtableType> { };
436
511
 
512
+ typedef testing::TypeList6<INT_HASHTABLES> IntHashtables;
513
+ typedef testing::TypeList6<STRING_HASHTABLES> StringHashtables;
514
+ typedef testing::TypeList6<CHARSTAR_HASHTABLES> CharStarHashtables;
437
515
  typedef testing::TypeList18<INT_HASHTABLES, STRING_HASHTABLES,
438
516
  CHARSTAR_HASHTABLES> AllHashtables;
439
- template <typename HashtableType> class HashtableAllTest
440
- : public HashtableTest<HashtableType> { };
517
+
518
+ TYPED_TEST_CASE_6(HashtableIntTest, IntHashtables);
519
+ TYPED_TEST_CASE_6(HashtableStringTest, StringHashtables);
520
+ TYPED_TEST_CASE_6(HashtableCharStarTest, CharStarHashtables);
441
521
  TYPED_TEST_CASE_18(HashtableAllTest, AllHashtables);
442
522
 
523
+ // ------------------------------------------------------------------------
524
+ // First, some testing of the underlying infrastructure.
525
+
526
+ TEST(HashtableCommonTest, HashMunging) {
527
+ const Hasher hasher;
528
+
529
+ // We don't munge the hash value on non-pointer template types.
530
+ {
531
+ const sparsehash_internal::sh_hashtable_settings<int, Hasher, size_t, 1>
532
+ settings(hasher, 0.0, 0.0);
533
+ const int v = 1000;
534
+ EXPECT_EQ(hasher(v), settings.hash(v));
535
+ }
536
+
537
+ {
538
+ // We do munge the hash value on pointer template types.
539
+ const sparsehash_internal::sh_hashtable_settings<int*, Hasher, size_t, 1>
540
+ settings(hasher, 0.0, 0.0);
541
+ int* v = NULL;
542
+ v += 0x10000; // get a non-trivial pointer value
543
+ EXPECT_NE(hasher(v), settings.hash(v));
544
+ }
545
+ {
546
+ const sparsehash_internal::sh_hashtable_settings<const int*, Hasher,
547
+ size_t, 1>
548
+ settings(hasher, 0.0, 0.0);
549
+ const int* v = NULL;
550
+ v += 0x10000; // get a non-trivial pointer value
551
+ EXPECT_NE(hasher(v), settings.hash(v));
552
+ }
553
+ }
554
+
443
555
  // ------------------------------------------------------------------------
444
556
  // If the first arg to TYPED_TEST is HashtableIntTest, it will run
445
557
  // this test on all the hashtable types, with key=int and value=int.
@@ -624,18 +736,20 @@ TYPED_TEST(HashtableIntTest, Constructors) {
624
736
  EXPECT_LE(1, alloc_count);
625
737
  int old_alloc_count = alloc_count;
626
738
 
627
- vector<typename TypeParam::value_type> input(4);
628
- // We have to use placement-new because value_type may be const.
629
- new(&input[0]) typename TypeParam::value_type(this->UniqueObject(1));
630
- new(&input[1]) typename TypeParam::value_type(this->UniqueObject(2));
631
- new(&input[2]) typename TypeParam::value_type(this->UniqueObject(4));
632
- new(&input[3]) typename TypeParam::value_type(this->UniqueObject(8));
633
- TypeParam ht_iter_noarg(input.begin(), input.end());
634
- TypeParam ht_iter_onearg(input.begin(), input.end(), 100);
635
- TypeParam ht_iter_twoarg(input.begin(), input.end(), 100, hasher);
636
- TypeParam ht_iter_threearg(input.begin(), input.end(), 100, hasher, hasher);
637
- TypeParam ht_iter_fourarg(input.begin(), input.end(), 100, hasher, hasher,
638
- alloc);
739
+ const typename TypeParam::value_type input[] = {
740
+ this->UniqueObject(1),
741
+ this->UniqueObject(2),
742
+ this->UniqueObject(4),
743
+ this->UniqueObject(8)
744
+ };
745
+ const int num_inputs = sizeof(input) / sizeof(input[0]);
746
+ const typename TypeParam::value_type *begin = &input[0];
747
+ const typename TypeParam::value_type *end = begin + num_inputs;
748
+ TypeParam ht_iter_noarg(begin, end);
749
+ TypeParam ht_iter_onearg(begin, end, 100);
750
+ TypeParam ht_iter_twoarg(begin, end, 100, hasher);
751
+ TypeParam ht_iter_threearg(begin, end, 100, hasher, hasher);
752
+ TypeParam ht_iter_fourarg(begin, end, 100, hasher, hasher, alloc);
639
753
  // Now the allocator should have been called more.
640
754
  EXPECT_GT(alloc_count, old_alloc_count);
641
755
  old_alloc_count = alloc_count;
@@ -781,7 +895,7 @@ TYPED_TEST(HashtableAllTest, Swap) {
781
895
 
782
896
  // We purposefully don't swap allocs -- they're not necessarily swappable.
783
897
 
784
- // Now swap back, using the free-function swap.
898
+ // Now swap back, using the free-function swap
785
899
  // NOTE: MSVC seems to have trouble with this free swap, not quite
786
900
  // sure why. I've given up trying to fix it though.
787
901
  #ifdef _MSC_VER
@@ -798,6 +912,20 @@ TYPED_TEST(HashtableAllTest, Swap) {
798
912
  EXPECT_EQ(1u, other_ht.size());
799
913
  EXPECT_EQ(1u, this->ht_.count(this->UniqueKey(111)));
800
914
  EXPECT_EQ(0u, other_ht.count(this->UniqueKey(111)));
915
+
916
+ // A user reported a crash with this code using swap to clear.
917
+ // We've since fixed the bug; this prevents a regression.
918
+ TypeParam swap_to_clear_ht;
919
+ swap_to_clear_ht.set_deleted_key(this->UniqueKey(1));
920
+ for (int i = 2; i < 10000; ++i) {
921
+ swap_to_clear_ht.insert(this->UniqueObject(i));
922
+ }
923
+ TypeParam empty_ht;
924
+ empty_ht.swap(swap_to_clear_ht);
925
+ swap_to_clear_ht.set_deleted_key(this->UniqueKey(1));
926
+ for (int i = 2; i < 10000; ++i) {
927
+ swap_to_clear_ht.insert(this->UniqueObject(i));
928
+ }
801
929
  }
802
930
 
803
931
  TYPED_TEST(HashtableAllTest, Size) {
@@ -1073,6 +1201,7 @@ TYPED_TEST(HashtableAllTest, BracketInsert) {
1073
1201
  EXPECT_EQ(2, ht.hash_funct().num_hashes());
1074
1202
  }
1075
1203
 
1204
+
1076
1205
  TYPED_TEST(HashtableAllTest, InsertValue) {
1077
1206
  // First, try some straightforward insertions.
1078
1207
  EXPECT_TRUE(this->ht_.empty());
@@ -1111,13 +1240,13 @@ TYPED_TEST(HashtableIntTest, InsertRange) {
1111
1240
  ht_source.insert(this->UniqueObject(100000));
1112
1241
  ht_source.insert(this->UniqueObject(1000000));
1113
1242
 
1114
- vector<typename TypeParam::value_type> input(4);
1115
- // We have to use placement-new because value_type may be const.
1116
- // This is a copy of the first element in ht_source.
1117
- new(&input[0]) typename TypeParam::value_type(*ht_source.begin());
1118
- new(&input[1]) typename TypeParam::value_type(this->UniqueObject(2));
1119
- new(&input[2]) typename TypeParam::value_type(this->UniqueObject(4));
1120
- new(&input[3]) typename TypeParam::value_type(this->UniqueObject(8));
1243
+ const typename TypeParam::value_type input[] = {
1244
+ // This is a copy of the first element in ht_source.
1245
+ *ht_source.begin(),
1246
+ this->UniqueObject(2),
1247
+ this->UniqueObject(4),
1248
+ this->UniqueObject(8)
1249
+ };
1121
1250
 
1122
1251
  set<typename TypeParam::value_type> set_input;
1123
1252
  set_input.insert(this->UniqueObject(1111111));
@@ -1152,7 +1281,7 @@ TYPED_TEST(HashtableIntTest, InsertRange) {
1152
1281
  // Insert from input as well, a separate, random-access iterator.
1153
1282
  // The first element of input overlaps with an existing element
1154
1283
  // of ht_, so this should only up the size by 2.
1155
- this->ht_.insert(input.begin(), input.begin() + 3);
1284
+ this->ht_.insert(&input[0], &input[3]);
1156
1285
  EXPECT_EQ(8u, this->ht_.size());
1157
1286
  }
1158
1287
 
@@ -1298,10 +1427,9 @@ TYPED_TEST(HashtableAllTest, Equals) {
1298
1427
  }
1299
1428
 
1300
1429
  TEST(HashtableTest, IntIO) {
1301
- // Since dense_hash_* doesn't support IO yet, and the set case is
1302
- // just a special (easier) case than the map case, I just test on
1303
- // sparse_hash_map. This handles the easy case where we can use the
1304
- // standard reader and writer.
1430
+ // Since the set case is just a special (easier) case than the map case, I
1431
+ // just test on sparse_hash_map. This handles the easy case where we can
1432
+ // use the standard reader and writer.
1305
1433
  sparse_hash_map<int, int> ht_out;
1306
1434
  ht_out.set_deleted_key(0);
1307
1435
  for (int i = 1; i < 1000; i++) {
@@ -1310,7 +1438,7 @@ TEST(HashtableTest, IntIO) {
1310
1438
  ht_out.erase(563); // just to test having some erased keys when we write.
1311
1439
  ht_out.erase(22);
1312
1440
 
1313
- string file(TmpFile("/intio"));
1441
+ string file(TmpFile("intio"));
1314
1442
  FILE* fp = fopen(file.c_str(), "wb");
1315
1443
  EXPECT_TRUE(fp != NULL);
1316
1444
  EXPECT_TRUE(ht_out.write_metadata(fp));
@@ -1333,10 +1461,9 @@ TEST(HashtableTest, IntIO) {
1333
1461
  }
1334
1462
 
1335
1463
  TEST(HashtableTest, StringIO) {
1336
- // Since dense_hash_* doesn't support IO yet, and the set case is
1337
- // just a special (easier) case than the map case, I just test on
1338
- // sparse_hash_map. This handles the difficult case where we have
1339
- // to write our own custom reader/writer for the data.
1464
+ // Since the set case is just a special (easier) case than the map case,
1465
+ // I just test on sparse_hash_map. This handles the difficult case where
1466
+ // we have to write our own custom reader/writer for the data.
1340
1467
  sparse_hash_map<string, string, Hasher, Hasher> ht_out;
1341
1468
  ht_out.set_deleted_key(string(""));
1342
1469
  for (int i = 32; i < 128; i++) {
@@ -1346,7 +1473,7 @@ TEST(HashtableTest, StringIO) {
1346
1473
  ht_out.erase("c"); // just to test having some erased keys when we write.
1347
1474
  ht_out.erase("y");
1348
1475
 
1349
- string file(TmpFile("/stringio"));
1476
+ string file(TmpFile("stringio"));
1350
1477
  FILE* fp = fopen(file.c_str(), "wb");
1351
1478
  EXPECT_TRUE(fp != NULL);
1352
1479
  EXPECT_TRUE(ht_out.write_metadata(fp));
@@ -1369,14 +1496,14 @@ TEST(HashtableTest, StringIO) {
1369
1496
  for (sparse_hash_map<string, string, Hasher, Hasher>::iterator
1370
1497
  it = ht_in.begin(); it != ht_in.end(); ++it) {
1371
1498
  string::size_type first_size;
1372
- fread(&first_size, sizeof(first_size), 1, fp);
1499
+ EXPECT_EQ(1u, fread(&first_size, sizeof(first_size), 1, fp));
1373
1500
  char* first = new char[first_size];
1374
- fread(first, first_size, 1, fp);
1501
+ EXPECT_EQ(1u, fread(first, first_size, 1, fp));
1375
1502
 
1376
1503
  string::size_type second_size;
1377
- fread(&second_size, sizeof(second_size), 1, fp);
1504
+ EXPECT_EQ(1u, fread(&second_size, sizeof(second_size), 1, fp));
1378
1505
  char* second = new char[second_size];
1379
- fread(second, second_size, 1, fp);
1506
+ EXPECT_EQ(1u, fread(second, second_size, 1, fp));
1380
1507
 
1381
1508
  // it points to garbage, so we have to use placement-new to initialize.
1382
1509
  // We also have to use const-cast since it->first is const.
@@ -1393,6 +1520,195 @@ TEST(HashtableTest, StringIO) {
1393
1520
  EXPECT_EQ(string(""), ht_in["y"]);
1394
1521
  }
1395
1522
 
1523
+ TYPED_TEST(HashtableAllTest, Serialization) {
1524
+ if (!this->ht_.supports_serialization()) return;
1525
+ TypeParam ht_out;
1526
+ ht_out.set_deleted_key(this->UniqueKey(2000));
1527
+ for (int i = 1; i < 100; i++) {
1528
+ ht_out.insert(this->UniqueObject(i));
1529
+ }
1530
+ // just to test having some erased keys when we write.
1531
+ ht_out.erase(this->UniqueKey(56));
1532
+ ht_out.erase(this->UniqueKey(22));
1533
+
1534
+ string file(TmpFile("serialization"));
1535
+ FILE* fp = fopen(file.c_str(), "wb");
1536
+ EXPECT_TRUE(fp != NULL);
1537
+ EXPECT_TRUE(ht_out.serialize(ValueSerializer(), fp));
1538
+ fclose(fp);
1539
+
1540
+ TypeParam ht_in;
1541
+ fp = fopen(file.c_str(), "rb");
1542
+ EXPECT_TRUE(fp != NULL);
1543
+ EXPECT_TRUE(ht_in.unserialize(ValueSerializer(), fp));
1544
+ fclose(fp);
1545
+
1546
+ EXPECT_EQ(this->UniqueObject(1), *ht_in.find(this->UniqueKey(1)));
1547
+ EXPECT_EQ(this->UniqueObject(99), *ht_in.find(this->UniqueKey(99)));
1548
+ EXPECT_FALSE(ht_in.count(this->UniqueKey(100)));
1549
+ EXPECT_EQ(this->UniqueObject(21), *ht_in.find(this->UniqueKey(21)));
1550
+ // should not have been saved
1551
+ EXPECT_FALSE(ht_in.count(this->UniqueKey(22)));
1552
+ EXPECT_FALSE(ht_in.count(this->UniqueKey(56)));
1553
+ }
1554
+
1555
+ TYPED_TEST(HashtableIntTest, NopointerSerialization) {
1556
+ if (!this->ht_.supports_serialization()) return;
1557
+ TypeParam ht_out;
1558
+ ht_out.set_deleted_key(this->UniqueKey(2000));
1559
+ for (int i = 1; i < 100; i++) {
1560
+ ht_out.insert(this->UniqueObject(i));
1561
+ }
1562
+ // just to test having some erased keys when we write.
1563
+ ht_out.erase(this->UniqueKey(56));
1564
+ ht_out.erase(this->UniqueKey(22));
1565
+
1566
+ string file(TmpFile("nopointer_serialization"));
1567
+ FILE* fp = fopen(file.c_str(), "wb");
1568
+ EXPECT_TRUE(fp != NULL);
1569
+ EXPECT_TRUE(ht_out.serialize(typename TypeParam::NopointerSerializer(), fp));
1570
+ fclose(fp);
1571
+
1572
+ TypeParam ht_in;
1573
+ fp = fopen(file.c_str(), "rb");
1574
+ EXPECT_TRUE(fp != NULL);
1575
+ EXPECT_TRUE(ht_in.unserialize(typename TypeParam::NopointerSerializer(), fp));
1576
+ fclose(fp);
1577
+
1578
+ EXPECT_EQ(this->UniqueObject(1), *ht_in.find(this->UniqueKey(1)));
1579
+ EXPECT_EQ(this->UniqueObject(99), *ht_in.find(this->UniqueKey(99)));
1580
+ EXPECT_FALSE(ht_in.count(this->UniqueKey(100)));
1581
+ EXPECT_EQ(this->UniqueObject(21), *ht_in.find(this->UniqueKey(21)));
1582
+ // should not have been saved
1583
+ EXPECT_FALSE(ht_in.count(this->UniqueKey(22)));
1584
+ EXPECT_FALSE(ht_in.count(this->UniqueKey(56)));
1585
+ }
1586
+
1587
+ // We don't support serializing to a string by default, but you can do
1588
+ // it by writing your own custom input/output class.
1589
+ class StringIO {
1590
+ public:
1591
+ explicit StringIO(string* s) : s_(s) {}
1592
+ size_t Write(const void* buf, size_t len) {
1593
+ s_->append(reinterpret_cast<const char*>(buf), len);
1594
+ return len;
1595
+ }
1596
+ size_t Read(void* buf, size_t len) {
1597
+ if (s_->length() < len)
1598
+ len = s_->length();
1599
+ memcpy(reinterpret_cast<char*>(buf), s_->data(), len);
1600
+ s_->erase(0, len);
1601
+ return len;
1602
+ }
1603
+ private:
1604
+ string* const s_;
1605
+ };
1606
+
1607
+ TYPED_TEST(HashtableIntTest, SerializingToString) {
1608
+ if (!this->ht_.supports_serialization()) return;
1609
+ TypeParam ht_out;
1610
+ ht_out.set_deleted_key(this->UniqueKey(2000));
1611
+ for (int i = 1; i < 100; i++) {
1612
+ ht_out.insert(this->UniqueObject(i));
1613
+ }
1614
+ // just to test having some erased keys when we write.
1615
+ ht_out.erase(this->UniqueKey(56));
1616
+ ht_out.erase(this->UniqueKey(22));
1617
+
1618
+ string stringbuf;
1619
+ StringIO stringio(&stringbuf);
1620
+ EXPECT_TRUE(ht_out.serialize(typename TypeParam::NopointerSerializer(),
1621
+ &stringio));
1622
+
1623
+ TypeParam ht_in;
1624
+ EXPECT_TRUE(ht_in.unserialize(typename TypeParam::NopointerSerializer(),
1625
+ &stringio));
1626
+
1627
+ EXPECT_EQ(this->UniqueObject(1), *ht_in.find(this->UniqueKey(1)));
1628
+ EXPECT_EQ(this->UniqueObject(99), *ht_in.find(this->UniqueKey(99)));
1629
+ EXPECT_FALSE(ht_in.count(this->UniqueKey(100)));
1630
+ EXPECT_EQ(this->UniqueObject(21), *ht_in.find(this->UniqueKey(21)));
1631
+ // should not have been saved
1632
+ EXPECT_FALSE(ht_in.count(this->UniqueKey(22)));
1633
+ EXPECT_FALSE(ht_in.count(this->UniqueKey(56)));
1634
+ }
1635
+
1636
+ // An easier way to do the above would be to use the existing stream methods.
1637
+ TYPED_TEST(HashtableIntTest, SerializingToStringStream) {
1638
+ if (!this->ht_.supports_serialization()) return;
1639
+ TypeParam ht_out;
1640
+ ht_out.set_deleted_key(this->UniqueKey(2000));
1641
+ for (int i = 1; i < 100; i++) {
1642
+ ht_out.insert(this->UniqueObject(i));
1643
+ }
1644
+ // just to test having some erased keys when we write.
1645
+ ht_out.erase(this->UniqueKey(56));
1646
+ ht_out.erase(this->UniqueKey(22));
1647
+
1648
+ std::stringstream string_buffer;
1649
+ EXPECT_TRUE(ht_out.serialize(typename TypeParam::NopointerSerializer(),
1650
+ &string_buffer));
1651
+
1652
+ TypeParam ht_in;
1653
+ EXPECT_TRUE(ht_in.unserialize(typename TypeParam::NopointerSerializer(),
1654
+ &string_buffer));
1655
+
1656
+ EXPECT_EQ(this->UniqueObject(1), *ht_in.find(this->UniqueKey(1)));
1657
+ EXPECT_EQ(this->UniqueObject(99), *ht_in.find(this->UniqueKey(99)));
1658
+ EXPECT_FALSE(ht_in.count(this->UniqueKey(100)));
1659
+ EXPECT_EQ(this->UniqueObject(21), *ht_in.find(this->UniqueKey(21)));
1660
+ // should not have been saved
1661
+ EXPECT_FALSE(ht_in.count(this->UniqueKey(22)));
1662
+ EXPECT_FALSE(ht_in.count(this->UniqueKey(56)));
1663
+ }
1664
+
1665
+ // Verify that the metadata serialization is endianness and word size
1666
+ // agnostic.
1667
+ TYPED_TEST(HashtableAllTest, MetadataSerializationAndEndianness) {
1668
+ TypeParam ht_out;
1669
+ string kExpectedDense("\x13W\x86""B\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0",
1670
+ 24);
1671
+ string kExpectedSparse("$hu1\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0", 20);
1672
+
1673
+ if (ht_out.supports_readwrite()) {
1674
+ string file(TmpFile("metadata_serialization"));
1675
+ FILE* fp = fopen(file.c_str(), "wb");
1676
+ EXPECT_TRUE(fp != NULL);
1677
+
1678
+ EXPECT_TRUE(ht_out.write_metadata(fp));
1679
+ EXPECT_TRUE(ht_out.write_nopointer_data(fp));
1680
+
1681
+ const size_t num_bytes = ftell(fp);
1682
+ fclose(fp);
1683
+ fp = fopen(file.c_str(), "rb");
1684
+ EXPECT_LE(num_bytes, static_cast<size_t>(24));
1685
+ char contents[24];
1686
+ EXPECT_EQ(num_bytes, fread(contents, 1, num_bytes, fp));
1687
+ EXPECT_EQ(EOF, fgetc(fp)); // check we're *exactly* the right size
1688
+ fclose(fp);
1689
+ // TODO(csilvers): check type of ht_out instead of looking at the 1st byte.
1690
+ if (contents[0] == kExpectedDense[0]) {
1691
+ EXPECT_EQ(kExpectedDense, string(contents, num_bytes));
1692
+ } else {
1693
+ EXPECT_EQ(kExpectedSparse, string(contents, num_bytes));
1694
+ }
1695
+ }
1696
+
1697
+ // Do it again with new-style serialization. Here we can use StringIO.
1698
+ if (ht_out.supports_serialization()) {
1699
+ string stringbuf;
1700
+ StringIO stringio(&stringbuf);
1701
+ EXPECT_TRUE(ht_out.serialize(typename TypeParam::NopointerSerializer(),
1702
+ &stringio));
1703
+ if (stringbuf[0] == kExpectedDense[0]) {
1704
+ EXPECT_EQ(kExpectedDense, stringbuf);
1705
+ } else {
1706
+ EXPECT_EQ(kExpectedSparse, stringbuf);
1707
+ }
1708
+ }
1709
+ }
1710
+
1711
+
1396
1712
  // ------------------------------------------------------------------------
1397
1713
  // The above tests test the general API for correctness. These tests
1398
1714
  // test a few corner cases that have tripped us up in the past, and
@@ -1594,20 +1910,12 @@ TEST(HashtableTest, NestedHashtables) {
1594
1910
 
1595
1911
  TEST(HashtableDeathTest, ResizeOverflow) {
1596
1912
  dense_hash_map<int, int> ht;
1597
- try {
1598
- ht.resize(static_cast<size_t>(-1));
1599
- EXPECT_TRUE(false && "dense_hash_map reszie should have failed");
1600
- } catch (const STL_NAMESPACE::length_error&) {
1601
- // Good, the resize failed.
1602
- }
1913
+ EXPECT_DEATH(ht.resize(static_cast<size_t>(-1)),
1914
+ "overflows size_type");
1603
1915
 
1604
1916
  sparse_hash_map<int, int> ht2;
1605
- try {
1606
- ht2.resize(static_cast<size_t>(-1));
1607
- EXPECT_TRUE(false && "sparse_hash_map reszie should have failed");
1608
- } catch (const STL_NAMESPACE::length_error&) {
1609
- // Good, the resize failed.
1610
- }
1917
+ EXPECT_DEATH(ht2.resize(static_cast<size_t>(-1)),
1918
+ "overflows size_type");
1611
1919
  }
1612
1920
 
1613
1921
  TEST(HashtableDeathTest, InsertSizeTypeOverflow) {
@@ -1626,18 +1934,10 @@ TEST(HashtableDeathTest, InsertSizeTypeOverflow) {
1626
1934
  EXPECT_TRUE(dhs.get_allocator().is_custom_alloc());
1627
1935
 
1628
1936
  // Test size_type overflow in insert(it, it)
1629
- try {
1630
- dhs.insert(test_data.begin(), test_data.end());
1631
- EXPECT_TRUE(false && "dense_hash_map::insert(it,it) should have overflown");
1632
- } catch (const STL_NAMESPACE::length_error&) {
1633
- // Good, the operation failed.
1634
- }
1635
- try {
1636
- shs.insert(test_data.begin(), test_data.end());
1637
- EXPECT_TRUE(false && "sparse_hash_map::insert(it,it) should have overflown");
1638
- } catch (const STL_NAMESPACE::length_error&) {
1639
- // Good, the operation failed.
1640
- }
1937
+ EXPECT_DEATH(dhs.insert(test_data.begin(), test_data.end()),
1938
+ "overflows size_type");
1939
+ EXPECT_DEATH(shs.insert(test_data.begin(), test_data.end()),
1940
+ "overflows size_type");
1641
1941
  }
1642
1942
 
1643
1943
  TEST(HashtableDeathTest, InsertMaxSizeOverflow) {
@@ -1652,18 +1952,10 @@ TEST(HashtableDeathTest, InsertMaxSizeOverflow) {
1652
1952
  dhs.set_empty_key(-1);
1653
1953
 
1654
1954
  // Test max_size overflow
1655
- try {
1656
- dhs.insert(test_data.begin(), test_data.begin() + 11);
1657
- EXPECT_TRUE(false && "dense_hash_map max_size check should have failed");
1658
- } catch (const STL_NAMESPACE::length_error&) {
1659
- // Good, the operation failed.
1660
- }
1661
- try {
1662
- shs.insert(test_data.begin(), test_data.begin() + 11);
1663
- EXPECT_TRUE(false && "sparse_hash_map max_size check should have failed");
1664
- } catch (const STL_NAMESPACE::length_error&) {
1665
- // Good, the operation failed.
1666
- }
1955
+ EXPECT_DEATH(dhs.insert(test_data.begin(), test_data.begin() + 11),
1956
+ "exceed max_size");
1957
+ EXPECT_DEATH(shs.insert(test_data.begin(), test_data.begin() + 11),
1958
+ "exceed max_size");
1667
1959
  }
1668
1960
 
1669
1961
  TEST(HashtableDeathTest, ResizeSizeTypeOverflow) {
@@ -1672,18 +1964,8 @@ TEST(HashtableDeathTest, ResizeSizeTypeOverflow) {
1672
1964
  dense_hash_set<int, Hasher, Hasher, Alloc<int, uint8, 10> > dhs;
1673
1965
  dhs.set_empty_key(-1);
1674
1966
 
1675
- try {
1676
- dhs.resize(250); // 9+250 > 25
1677
- EXPECT_TRUE(false && "dense_hash_map resize should have seen overflow");
1678
- } catch (const STL_NAMESPACE::length_error&) {
1679
- // Good, the operation failed.
1680
- }
1681
- try {
1682
- shs.resize(250);
1683
- EXPECT_TRUE(false && "sparse_hash_map resize should have seen overflow");
1684
- } catch (const STL_NAMESPACE::length_error&) {
1685
- // Good, the operation failed.
1686
- }
1967
+ EXPECT_DEATH(dhs.resize(250), "overflows size_type"); // 9+250 > 256
1968
+ EXPECT_DEATH(shs.resize(250), "overflows size_type");
1687
1969
  }
1688
1970
 
1689
1971
  TEST(HashtableDeathTest, ResizeDeltaOverflow) {
@@ -1700,18 +1982,10 @@ TEST(HashtableDeathTest, ResizeDeltaOverflow) {
1700
1982
  dhs.insert(i);
1701
1983
  shs.insert(i);
1702
1984
  }
1703
- try {
1704
- dhs.insert(test_data.begin(), test_data.begin() + 250);
1705
- EXPECT_TRUE(false && "dense_hash_map big insert should have overflowed");
1706
- } catch (const STL_NAMESPACE::length_error&) {
1707
- // Good, the operation failed.
1708
- }
1709
- try {
1710
- shs.insert(test_data.begin(), test_data.begin() + 250);
1711
- EXPECT_TRUE(false && "sparse_hash_map big insert should have overflowed");
1712
- } catch (const STL_NAMESPACE::length_error&) {
1713
- // Good, the operation failed.
1714
- }
1985
+ EXPECT_DEATH(dhs.insert(test_data.begin(), test_data.begin() + 250),
1986
+ "overflows size_type"); // 9+250 > 256
1987
+ EXPECT_DEATH(shs.insert(test_data.begin(), test_data.begin() + 250),
1988
+ "overflows size_type");
1715
1989
  }
1716
1990
 
1717
1991
  // ------------------------------------------------------------------------
@@ -1719,8 +1993,8 @@ TEST(HashtableDeathTest, ResizeDeltaOverflow) {
1719
1993
  // Also, benchmarks.
1720
1994
 
1721
1995
  TYPED_TEST(HashtableAllTest, ClassSizes) {
1722
- cout << "sizeof(" << typeid(TypeParam).name() << "): "
1723
- << sizeof(this->ht_) << "\n";
1996
+ std::cout << "sizeof(" << typeid(TypeParam).name() << "): "
1997
+ << sizeof(this->ht_) << "\n";
1724
1998
  }
1725
1999
 
1726
2000
  } // unnamed namespace