google_hash 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
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