google_hash 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/README +21 -0
  2. data/Rakefile +11 -0
  3. data/VERSION +1 -0
  4. data/ext/extconf.rb +15 -0
  5. data/ext/go.cpp +109 -0
  6. data/ext/sparsehash-1.5.2/AUTHORS +2 -0
  7. data/ext/sparsehash-1.5.2/COPYING +28 -0
  8. data/ext/sparsehash-1.5.2/ChangeLog +167 -0
  9. data/ext/sparsehash-1.5.2/INSTALL +236 -0
  10. data/ext/sparsehash-1.5.2/Makefile.am +157 -0
  11. data/ext/sparsehash-1.5.2/Makefile.in +1019 -0
  12. data/ext/sparsehash-1.5.2/NEWS +0 -0
  13. data/ext/sparsehash-1.5.2/README +149 -0
  14. data/ext/sparsehash-1.5.2/README.windows +25 -0
  15. data/ext/sparsehash-1.5.2/TODO +28 -0
  16. data/ext/sparsehash-1.5.2/aclocal.m4 +868 -0
  17. data/ext/sparsehash-1.5.2/compile +99 -0
  18. data/ext/sparsehash-1.5.2/config.guess +1516 -0
  19. data/ext/sparsehash-1.5.2/config.sub +1626 -0
  20. data/ext/sparsehash-1.5.2/configure +8054 -0
  21. data/ext/sparsehash-1.5.2/configure.ac +74 -0
  22. data/ext/sparsehash-1.5.2/depcomp +530 -0
  23. data/ext/sparsehash-1.5.2/doc/dense_hash_map.html +1591 -0
  24. data/ext/sparsehash-1.5.2/doc/dense_hash_set.html +1445 -0
  25. data/ext/sparsehash-1.5.2/doc/designstyle.css +115 -0
  26. data/ext/sparsehash-1.5.2/doc/implementation.html +365 -0
  27. data/ext/sparsehash-1.5.2/doc/index.html +69 -0
  28. data/ext/sparsehash-1.5.2/doc/performance.html +96 -0
  29. data/ext/sparsehash-1.5.2/doc/sparse_hash_map.html +1527 -0
  30. data/ext/sparsehash-1.5.2/doc/sparse_hash_set.html +1376 -0
  31. data/ext/sparsehash-1.5.2/doc/sparsetable.html +1393 -0
  32. data/ext/sparsehash-1.5.2/experimental/Makefile +9 -0
  33. data/ext/sparsehash-1.5.2/experimental/README +14 -0
  34. data/ext/sparsehash-1.5.2/experimental/example.c +54 -0
  35. data/ext/sparsehash-1.5.2/experimental/libchash.c +1537 -0
  36. data/ext/sparsehash-1.5.2/experimental/libchash.h +252 -0
  37. data/ext/sparsehash-1.5.2/google-sparsehash.sln +47 -0
  38. data/ext/sparsehash-1.5.2/install-sh +323 -0
  39. data/ext/sparsehash-1.5.2/m4/acx_pthread.m4 +363 -0
  40. data/ext/sparsehash-1.5.2/m4/google_namespace.m4 +42 -0
  41. data/ext/sparsehash-1.5.2/m4/namespaces.m4 +15 -0
  42. data/ext/sparsehash-1.5.2/m4/stl_hash.m4 +70 -0
  43. data/ext/sparsehash-1.5.2/m4/stl_hash_fun.m4 +36 -0
  44. data/ext/sparsehash-1.5.2/m4/stl_namespace.m4 +25 -0
  45. data/ext/sparsehash-1.5.2/missing +360 -0
  46. data/ext/sparsehash-1.5.2/mkinstalldirs +158 -0
  47. data/ext/sparsehash-1.5.2/packages/deb.sh +74 -0
  48. data/ext/sparsehash-1.5.2/packages/deb/README +7 -0
  49. data/ext/sparsehash-1.5.2/packages/deb/changelog +107 -0
  50. data/ext/sparsehash-1.5.2/packages/deb/compat +1 -0
  51. data/ext/sparsehash-1.5.2/packages/deb/control +17 -0
  52. data/ext/sparsehash-1.5.2/packages/deb/copyright +35 -0
  53. data/ext/sparsehash-1.5.2/packages/deb/docs +16 -0
  54. data/ext/sparsehash-1.5.2/packages/deb/rules +117 -0
  55. data/ext/sparsehash-1.5.2/packages/deb/sparsehash.dirs +2 -0
  56. data/ext/sparsehash-1.5.2/packages/deb/sparsehash.install +2 -0
  57. data/ext/sparsehash-1.5.2/packages/rpm.sh +86 -0
  58. data/ext/sparsehash-1.5.2/packages/rpm/rpm.spec +61 -0
  59. data/ext/sparsehash-1.5.2/src/config.h.in +131 -0
  60. data/ext/sparsehash-1.5.2/src/config.h.include +23 -0
  61. data/ext/sparsehash-1.5.2/src/google/dense_hash_map +310 -0
  62. data/ext/sparsehash-1.5.2/src/google/dense_hash_set +287 -0
  63. data/ext/sparsehash-1.5.2/src/google/sparse_hash_map +294 -0
  64. data/ext/sparsehash-1.5.2/src/google/sparse_hash_set +275 -0
  65. data/ext/sparsehash-1.5.2/src/google/sparsehash/densehashtable.h +1062 -0
  66. data/ext/sparsehash-1.5.2/src/google/sparsehash/sparsehashtable.h +1015 -0
  67. data/ext/sparsehash-1.5.2/src/google/sparsetable +1468 -0
  68. data/ext/sparsehash-1.5.2/src/google/type_traits.h +250 -0
  69. data/ext/sparsehash-1.5.2/src/hashtable_unittest.cc +1375 -0
  70. data/ext/sparsehash-1.5.2/src/simple_test.cc +103 -0
  71. data/ext/sparsehash-1.5.2/src/sparsetable_unittest.cc +696 -0
  72. data/ext/sparsehash-1.5.2/src/time_hash_map.cc +488 -0
  73. data/ext/sparsehash-1.5.2/src/type_traits_unittest.cc +492 -0
  74. data/ext/sparsehash-1.5.2/src/windows/config.h +149 -0
  75. data/ext/sparsehash-1.5.2/src/windows/google/sparsehash/sparseconfig.h +32 -0
  76. data/ext/sparsehash-1.5.2/src/windows/port.cc +63 -0
  77. data/ext/sparsehash-1.5.2/src/windows/port.h +81 -0
  78. data/ext/sparsehash-1.5.2/src/words +8944 -0
  79. data/ext/sparsehash-1.5.2/vsprojects/hashtable_unittest/hashtable_unittest.vcproj +187 -0
  80. data/ext/sparsehash-1.5.2/vsprojects/sparsetable_unittest/sparsetable_unittest.vcproj +172 -0
  81. data/ext/sparsehash-1.5.2/vsprojects/time_hash_map/time_hash_map.vcproj +187 -0
  82. data/ext/sparsehash-1.5.2/vsprojects/type_traits_unittest/type_traits_unittest.vcproj +169 -0
  83. data/ext/test.rb +10 -0
  84. data/test/spec.go +70 -0
  85. metadata +147 -0
@@ -0,0 +1,1468 @@
1
+ // Copyright (c) 2005, 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
+ // ---
31
+ // Author: Craig Silverstein
32
+ //
33
+ // A sparsetable is a random container that implements a sparse array,
34
+ // that is, an array that uses very little memory to store unassigned
35
+ // indices (in this case, between 1-2 bits per unassigned index). For
36
+ // instance, if you allocate an array of size 5 and assign a[2] = <big
37
+ // struct>, then a[2] will take up a lot of memory but a[0], a[1],
38
+ // a[3], and a[4] will not. Array elements that have a value are
39
+ // called "assigned". Array elements that have no value yet, or have
40
+ // had their value cleared using erase() or clear(), are called
41
+ // "unassigned".
42
+ //
43
+ // Unassigned values seem to have the default value of T (see below).
44
+ // Nevertheless, there is a difference between an unassigned index and
45
+ // one explicitly assigned the value of T(). The latter is considered
46
+ // assigned.
47
+ //
48
+ // Access to an array element is constant time, as is insertion and
49
+ // deletion. Insertion and deletion may be fairly slow, however:
50
+ // because of this container's memory economy, each insert and delete
51
+ // causes a memory reallocation.
52
+ //
53
+ // See /usr/(local/)?doc/sparsehash-0.1/sparsetable.html
54
+ // for information about how to use this class.
55
+
56
+ #ifndef _SPARSETABLE_H_
57
+ #define _SPARSETABLE_H_
58
+
59
+ #include <google/sparsehash/sparseconfig.h>
60
+ #include <stdlib.h> // for malloc/free
61
+ #include <stdio.h> // to read/write tables
62
+ #ifdef HAVE_STDINT_H
63
+ #include <stdint.h> // the normal place uint16_t is defined
64
+ #endif
65
+ #ifdef HAVE_SYS_TYPES_H
66
+ #include <sys/types.h> // the normal place u_int16_t is defined
67
+ #endif
68
+ #ifdef HAVE_INTTYPES_H
69
+ #include <inttypes.h> // a third place for uint16_t or u_int16_t
70
+ #endif
71
+ #include <assert.h> // for bounds checking
72
+ #include <iterator> // to define reverse_iterator for me
73
+ #include <algorithm> // equal, lexicographical_compare, swap,...
74
+ #include <memory> // uninitialized_copy
75
+ #include <vector> // a sparsetable is a vector of groups
76
+ #include <google/type_traits.h> // for true_type, integral_constant, etc.
77
+
78
+ #if STDC_HEADERS
79
+ #include <string.h> // for memcpy
80
+ #else
81
+ #if !HAVE_MEMCPY
82
+ #define memcpy(d, s, n) bcopy ((s), (d), (n))
83
+ #endif
84
+ #endif
85
+
86
+ _START_GOOGLE_NAMESPACE_
87
+
88
+ #ifndef HAVE_U_INT16_T
89
+ # if defined HAVE_UINT16_T
90
+ typedef uint16_t u_int16_t; // true on solaris, possibly other C99 libc's
91
+ # elif defined HAVE___UINT16
92
+ typedef __int16 int16_t; // true on vc++7
93
+ typedef unsigned __int16 u_int16_t;
94
+ # else
95
+ // Cannot find a 16-bit integer type. Hoping for the best with "short"...
96
+ typedef short int int16_t;
97
+ typedef unsigned short int u_int16_t;
98
+ # endif
99
+ #endif
100
+
101
+ using STL_NAMESPACE::vector;
102
+ using STL_NAMESPACE::uninitialized_copy;
103
+
104
+ // The smaller this is, the faster lookup is (because the group bitmap is
105
+ // smaller) and the faster insert is, because there's less to move.
106
+ // On the other hand, there are more groups. Since group::size_type is
107
+ // a short, this number should be of the form 32*x + 16 to avoid waste.
108
+ static const u_int16_t DEFAULT_SPARSEGROUP_SIZE = 48; // fits in 1.5 words
109
+
110
+
111
+ // A NOTE ON ASSIGNING:
112
+ // A sparse table does not actually allocate memory for entries
113
+ // that are not filled. Because of this, it becomes complicated
114
+ // to have a non-const iterator: we don't know, if the iterator points
115
+ // to a not-filled bucket, whether you plan to fill it with something
116
+ // or whether you plan to read its value (in which case you'll get
117
+ // the default bucket value). Therefore, while we can define const
118
+ // operations in a pretty 'normal' way, for non-const operations, we
119
+ // define something that returns a helper object with operator= and
120
+ // operator& that allocate a bucket lazily. We use this for table[]
121
+ // and also for regular table iterators.
122
+
123
+ template <class tabletype>
124
+ class table_element_adaptor {
125
+ public:
126
+ typedef typename tabletype::value_type value_type;
127
+ typedef typename tabletype::size_type size_type;
128
+ typedef typename tabletype::reference reference;
129
+ typedef typename tabletype::pointer pointer;
130
+
131
+ table_element_adaptor(tabletype *tbl, size_type p)
132
+ : table(tbl), pos(p) { }
133
+ table_element_adaptor& operator= (const value_type &val) {
134
+ table->set(pos, val);
135
+ return *this;
136
+ }
137
+ operator value_type() { return table->get(pos); } // we look like a value
138
+ pointer operator& () { return &table->mutating_get(pos); }
139
+
140
+ private:
141
+ tabletype* table;
142
+ size_type pos;
143
+ };
144
+
145
+ // Our iterator as simple as iterators can be: basically it's just
146
+ // the index into our table. Dereference, the only complicated
147
+ // thing, we punt to the table class. This just goes to show how
148
+ // much machinery STL requires to do even the most trivial tasks.
149
+ //
150
+ // By templatizing over tabletype, we have one iterator type which
151
+ // we can use for both sparsetables and sparsebins. In fact it
152
+ // works on any class that allows size() and operator[] (eg vector),
153
+ // as long as it does the standard STL typedefs too (eg value_type).
154
+
155
+ template <class tabletype>
156
+ class table_iterator {
157
+ public:
158
+ typedef table_iterator iterator;
159
+
160
+ typedef STL_NAMESPACE::random_access_iterator_tag iterator_category;
161
+ typedef typename tabletype::value_type value_type;
162
+ typedef typename tabletype::difference_type difference_type;
163
+ typedef typename tabletype::size_type size_type;
164
+ typedef table_element_adaptor<tabletype> reference;
165
+ typedef table_element_adaptor<tabletype>* pointer;
166
+
167
+ // The "real" constructor
168
+ table_iterator(tabletype *tbl, size_type p)
169
+ : table(tbl), pos(p) { }
170
+ // The default constructor, used when I define vars of type table::iterator
171
+ table_iterator() : table(NULL), pos(0) { }
172
+ // The copy constructor, for when I say table::iterator foo = tbl.begin()
173
+ // The default destructor is fine; we don't define one
174
+ // The default operator= is fine; we don't define one
175
+
176
+ // The main thing our iterator does is dereference. If the table entry
177
+ // we point to is empty, we return the default value type.
178
+ // This is the big different function from the const iterator.
179
+ reference operator*() {
180
+ return table_element_adaptor<tabletype>(table, pos);
181
+ }
182
+ pointer operator->() { return &(operator*()); }
183
+
184
+ // Helper function to assert things are ok; eg pos is still in range
185
+ void check() const {
186
+ assert(table);
187
+ assert(pos <= table->size());
188
+ }
189
+
190
+ // Arithmetic: we just do arithmetic on pos. We don't even need to
191
+ // do bounds checking, since STL doesn't consider that it's job. :-)
192
+ iterator& operator+=(size_type t) { pos += t; check(); return *this; }
193
+ iterator& operator-=(size_type t) { pos -= t; check(); return *this; }
194
+ iterator& operator++() { ++pos; check(); return *this; }
195
+ iterator& operator--() { --pos; check(); return *this; }
196
+ iterator operator++(int) { iterator tmp(*this); // for x++
197
+ ++pos; check(); return tmp; }
198
+ iterator operator--(int) { iterator tmp(*this); // for x--
199
+ --pos; check(); return tmp; }
200
+ iterator operator+(difference_type i) const { iterator tmp(*this);
201
+ tmp += i; return tmp; }
202
+ iterator operator-(difference_type i) const { iterator tmp(*this);
203
+ tmp -= i; return tmp; }
204
+ difference_type operator-(iterator it) const { // for "x = it2 - it"
205
+ assert(table == it.table);
206
+ return pos - it.pos;
207
+ }
208
+ reference operator[](difference_type n) const {
209
+ return *(*this + n); // simple though not totally efficient
210
+ }
211
+
212
+ // Comparisons.
213
+ bool operator==(const iterator& it) const {
214
+ return table == it.table && pos == it.pos;
215
+ }
216
+ bool operator<(const iterator& it) const {
217
+ assert(table == it.table); // life is bad bad bad otherwise
218
+ return pos < it.pos;
219
+ }
220
+ bool operator!=(const iterator& it) const { return !(*this == it); }
221
+ bool operator<=(const iterator& it) const { return !(it < *this); }
222
+ bool operator>(const iterator& it) const { return it < *this; }
223
+ bool operator>=(const iterator& it) const { return !(*this < it); }
224
+
225
+ // Here's the info we actually need to be an iterator
226
+ tabletype *table; // so we can dereference and bounds-check
227
+ size_type pos; // index into the table
228
+ };
229
+
230
+ // support for "3 + iterator" has to be defined outside the class, alas
231
+ template<class T>
232
+ table_iterator<T> operator+(typename table_iterator<T>::difference_type i,
233
+ table_iterator<T> it) {
234
+ return it + i; // so people can say it2 = 3 + it
235
+ }
236
+
237
+ template <class tabletype>
238
+ class const_table_iterator {
239
+ public:
240
+ typedef table_iterator<tabletype> iterator;
241
+ typedef const_table_iterator const_iterator;
242
+
243
+ typedef STL_NAMESPACE::random_access_iterator_tag iterator_category;
244
+ typedef typename tabletype::value_type value_type;
245
+ typedef typename tabletype::difference_type difference_type;
246
+ typedef typename tabletype::size_type size_type;
247
+ typedef typename tabletype::const_reference reference; // we're const-only
248
+ typedef typename tabletype::const_pointer pointer;
249
+
250
+ // The "real" constructor
251
+ const_table_iterator(const tabletype *tbl, size_type p)
252
+ : table(tbl), pos(p) { }
253
+ // The default constructor, used when I define vars of type table::iterator
254
+ const_table_iterator() : table(NULL), pos(0) { }
255
+ // The copy constructor, for when I say table::iterator foo = tbl.begin()
256
+ // Also converts normal iterators to const iterators
257
+ const_table_iterator(const iterator &from)
258
+ : table(from.table), pos(from.pos) { }
259
+ // The default destructor is fine; we don't define one
260
+ // The default operator= is fine; we don't define one
261
+
262
+ // The main thing our iterator does is dereference. If the table entry
263
+ // we point to is empty, we return the default value type.
264
+ reference operator*() const { return (*table)[pos]; }
265
+ pointer operator->() const { return &(operator*()); }
266
+
267
+ // Helper function to assert things are ok; eg pos is still in range
268
+ void check() const {
269
+ assert(table);
270
+ assert(pos <= table->size());
271
+ }
272
+
273
+ // Arithmetic: we just do arithmetic on pos. We don't even need to
274
+ // do bounds checking, since STL doesn't consider that it's job. :-)
275
+ const_iterator& operator+=(size_type t) { pos += t; check(); return *this; }
276
+ const_iterator& operator-=(size_type t) { pos -= t; check(); return *this; }
277
+ const_iterator& operator++() { ++pos; check(); return *this; }
278
+ const_iterator& operator--() { --pos; check(); return *this; }
279
+ const_iterator operator++(int) { const_iterator tmp(*this); // for x++
280
+ ++pos; check(); return tmp; }
281
+ const_iterator operator--(int) { const_iterator tmp(*this); // for x--
282
+ --pos; check(); return tmp; }
283
+ const_iterator operator+(difference_type i) const { const_iterator tmp(*this);
284
+ tmp += i; return tmp; }
285
+ const_iterator operator-(difference_type i) const { const_iterator tmp(*this);
286
+ tmp -= i; return tmp; }
287
+ difference_type operator-(const_iterator it) const { // for "x = it2 - it"
288
+ assert(table == it.table);
289
+ return pos - it.pos;
290
+ }
291
+ reference operator[](difference_type n) const {
292
+ return *(*this + n); // simple though not totally efficient
293
+ }
294
+
295
+ // Comparisons.
296
+ bool operator==(const const_iterator& it) const {
297
+ return table == it.table && pos == it.pos;
298
+ }
299
+ bool operator<(const const_iterator& it) const {
300
+ assert(table == it.table); // life is bad bad bad otherwise
301
+ return pos < it.pos;
302
+ }
303
+ bool operator!=(const const_iterator& it) const { return !(*this == it); }
304
+ bool operator<=(const const_iterator& it) const { return !(it < *this); }
305
+ bool operator>(const const_iterator& it) const { return it < *this; }
306
+ bool operator>=(const const_iterator& it) const { return !(*this < it); }
307
+
308
+ // Here's the info we actually need to be an iterator
309
+ const tabletype *table; // so we can dereference and bounds-check
310
+ size_type pos; // index into the table
311
+ };
312
+
313
+ // support for "3 + iterator" has to be defined outside the class, alas
314
+ template<class T>
315
+ const_table_iterator<T> operator+(typename
316
+ const_table_iterator<T>::difference_type i,
317
+ const_table_iterator<T> it) {
318
+ return it + i; // so people can say it2 = 3 + it
319
+ }
320
+
321
+
322
+ // ---------------------------------------------------------------------------
323
+
324
+
325
+ /*
326
+ // This is a 2-D iterator. You specify a begin and end over a list
327
+ // of *containers*. We iterate over each container by iterating over
328
+ // it. It's actually simple:
329
+ // VECTOR.begin() VECTOR[0].begin() --------> VECTOR[0].end() ---,
330
+ // | ________________________________________________/
331
+ // | \_> VECTOR[1].begin() --------> VECTOR[1].end() -,
332
+ // | ___________________________________________________/
333
+ // v \_> ......
334
+ // VECTOR.end()
335
+ //
336
+ // It's impossible to do random access on one of these things in constant
337
+ // time, so it's just a bidirectional iterator.
338
+ //
339
+ // Unfortunately, because we need to use this for a non-empty iterator,
340
+ // we use nonempty_begin() and nonempty_end() instead of begin() and end()
341
+ // (though only going across, not down).
342
+ */
343
+
344
+ #define TWOD_BEGIN_ nonempty_begin
345
+ #define TWOD_END_ nonempty_end
346
+ #define TWOD_ITER_ nonempty_iterator
347
+ #define TWOD_CONST_ITER_ const_nonempty_iterator
348
+
349
+ template <class containertype>
350
+ class two_d_iterator {
351
+ public:
352
+ typedef two_d_iterator iterator;
353
+
354
+ typedef STL_NAMESPACE::bidirectional_iterator_tag iterator_category;
355
+ // apparently some versions of VC++ have trouble with two ::'s in a typename
356
+ typedef typename containertype::value_type _tmp_vt;
357
+ typedef typename _tmp_vt::value_type value_type;
358
+ typedef typename _tmp_vt::difference_type difference_type;
359
+ typedef typename _tmp_vt::reference reference;
360
+ typedef typename _tmp_vt::pointer pointer;
361
+
362
+ // The "real" constructor. begin and end specify how many rows we have
363
+ // (in the diagram above); we always iterate over each row completely.
364
+ two_d_iterator(typename containertype::iterator begin,
365
+ typename containertype::iterator end,
366
+ typename containertype::iterator curr)
367
+ : row_begin(begin), row_end(end), row_current(curr), col_current() {
368
+ if ( row_current != row_end ) {
369
+ col_current = row_current->TWOD_BEGIN_();
370
+ advance_past_end(); // in case cur->begin() == cur->end()
371
+ }
372
+ }
373
+ // If you want to start at an arbitrary place, you can, I guess
374
+ two_d_iterator(typename containertype::iterator begin,
375
+ typename containertype::iterator end,
376
+ typename containertype::iterator curr,
377
+ typename containertype::value_type::TWOD_ITER_ col)
378
+ : row_begin(begin), row_end(end), row_current(curr), col_current(col) {
379
+ advance_past_end(); // in case cur->begin() == cur->end()
380
+ }
381
+ // The default constructor, used when I define vars of type table::iterator
382
+ two_d_iterator() : row_begin(), row_end(), row_current(), col_current() { }
383
+ // The default destructor is fine; we don't define one
384
+ // The default operator= is fine; we don't define one
385
+
386
+ // Happy dereferencer
387
+ reference operator*() const { return *col_current; }
388
+ pointer operator->() const { return &(operator*()); }
389
+
390
+ // Arithmetic: we just do arithmetic on pos. We don't even need to
391
+ // do bounds checking, since STL doesn't consider that it's job. :-)
392
+ // NOTE: this is not amortized constant time! What do we do about it?
393
+ void advance_past_end() { // used when col_current points to end()
394
+ while ( col_current == row_current->TWOD_END_() ) { // end of current row
395
+ ++row_current; // go to beginning of next
396
+ if ( row_current != row_end ) // col is irrelevant at end
397
+ col_current = row_current->TWOD_BEGIN_();
398
+ else
399
+ break; // don't go past row_end
400
+ }
401
+ }
402
+
403
+ iterator& operator++() {
404
+ assert(row_current != row_end); // how to ++ from there?
405
+ ++col_current;
406
+ advance_past_end(); // in case col_current is at end()
407
+ return *this;
408
+ }
409
+ iterator& operator--() {
410
+ while ( row_current == row_end ||
411
+ col_current == row_current->TWOD_BEGIN_() ) {
412
+ assert(row_current != row_begin);
413
+ --row_current;
414
+ col_current = row_current->TWOD_END_(); // this is 1 too far
415
+ }
416
+ --col_current;
417
+ return *this;
418
+ }
419
+ iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; }
420
+ iterator operator--(int) { iterator tmp(*this); --*this; return tmp; }
421
+
422
+
423
+ // Comparisons.
424
+ bool operator==(const iterator& it) const {
425
+ return ( row_begin == it.row_begin &&
426
+ row_end == it.row_end &&
427
+ row_current == it.row_current &&
428
+ (row_current == row_end || col_current == it.col_current) );
429
+ }
430
+ bool operator!=(const iterator& it) const { return !(*this == it); }
431
+
432
+
433
+ // Here's the info we actually need to be an iterator
434
+ // These need to be public so we convert from iterator to const_iterator
435
+ typename containertype::iterator row_begin, row_end, row_current;
436
+ typename containertype::value_type::TWOD_ITER_ col_current;
437
+ };
438
+
439
+ // The same thing again, but this time const. :-(
440
+ template <class containertype>
441
+ class const_two_d_iterator {
442
+ public:
443
+ typedef const_two_d_iterator iterator;
444
+
445
+ typedef STL_NAMESPACE::bidirectional_iterator_tag iterator_category;
446
+ // apparently some versions of VC++ have trouble with two ::'s in a typename
447
+ typedef typename containertype::value_type _tmp_vt;
448
+ typedef typename _tmp_vt::value_type value_type;
449
+ typedef typename _tmp_vt::difference_type difference_type;
450
+ typedef typename _tmp_vt::const_reference reference;
451
+ typedef typename _tmp_vt::const_pointer pointer;
452
+
453
+ const_two_d_iterator(typename containertype::const_iterator begin,
454
+ typename containertype::const_iterator end,
455
+ typename containertype::const_iterator curr)
456
+ : row_begin(begin), row_end(end), row_current(curr), col_current() {
457
+ if ( curr != end ) {
458
+ col_current = curr->TWOD_BEGIN_();
459
+ advance_past_end(); // in case cur->begin() == cur->end()
460
+ }
461
+ }
462
+ const_two_d_iterator(typename containertype::const_iterator begin,
463
+ typename containertype::const_iterator end,
464
+ typename containertype::const_iterator curr,
465
+ typename containertype::value_type::TWOD_CONST_ITER_ col)
466
+ : row_begin(begin), row_end(end), row_current(curr), col_current(col) {
467
+ advance_past_end(); // in case cur->begin() == cur->end()
468
+ }
469
+ const_two_d_iterator()
470
+ : row_begin(), row_end(), row_current(), col_current() {
471
+ }
472
+ // Need this explicitly so we can convert normal iterators to const iterators
473
+ const_two_d_iterator(const two_d_iterator<containertype>& it) :
474
+ row_begin(it.row_begin), row_end(it.row_end), row_current(it.row_current),
475
+ col_current(it.col_current) { }
476
+
477
+ typename containertype::const_iterator row_begin, row_end, row_current;
478
+ typename containertype::value_type::TWOD_CONST_ITER_ col_current;
479
+
480
+
481
+ // EVERYTHING FROM HERE DOWN IS THE SAME AS THE NON-CONST ITERATOR
482
+ reference operator*() const { return *col_current; }
483
+ pointer operator->() const { return &(operator*()); }
484
+
485
+ void advance_past_end() { // used when col_current points to end()
486
+ while ( col_current == row_current->TWOD_END_() ) { // end of current row
487
+ ++row_current; // go to beginning of next
488
+ if ( row_current != row_end ) // col is irrelevant at end
489
+ col_current = row_current->TWOD_BEGIN_();
490
+ else
491
+ break; // don't go past row_end
492
+ }
493
+ }
494
+ iterator& operator++() {
495
+ assert(row_current != row_end); // how to ++ from there?
496
+ ++col_current;
497
+ advance_past_end(); // in case col_current is at end()
498
+ return *this;
499
+ }
500
+ iterator& operator--() {
501
+ while ( row_current == row_end ||
502
+ col_current == row_current->TWOD_BEGIN_() ) {
503
+ assert(row_current != row_begin);
504
+ --row_current;
505
+ col_current = row_current->TWOD_END_(); // this is 1 too far
506
+ }
507
+ --col_current;
508
+ return *this;
509
+ }
510
+ iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; }
511
+ iterator operator--(int) { iterator tmp(*this); --*this; return tmp; }
512
+
513
+ bool operator==(const iterator& it) const {
514
+ return ( row_begin == it.row_begin &&
515
+ row_end == it.row_end &&
516
+ row_current == it.row_current &&
517
+ (row_current == row_end || col_current == it.col_current) );
518
+ }
519
+ bool operator!=(const iterator& it) const { return !(*this == it); }
520
+ };
521
+
522
+ // We provide yet another version, to be as frugal with memory as
523
+ // possible. This one frees each block of memory as it finishes
524
+ // iterating over it. By the end, the entire table is freed.
525
+ // For understandable reasons, you can only iterate over it once,
526
+ // which is why it's an input iterator
527
+ template <class containertype>
528
+ class destructive_two_d_iterator {
529
+ public:
530
+ typedef destructive_two_d_iterator iterator;
531
+
532
+ typedef STL_NAMESPACE::input_iterator_tag iterator_category;
533
+ // apparently some versions of VC++ have trouble with two ::'s in a typename
534
+ typedef typename containertype::value_type _tmp_vt;
535
+ typedef typename _tmp_vt::value_type value_type;
536
+ typedef typename _tmp_vt::difference_type difference_type;
537
+ typedef typename _tmp_vt::reference reference;
538
+ typedef typename _tmp_vt::pointer pointer;
539
+
540
+ destructive_two_d_iterator(typename containertype::iterator begin,
541
+ typename containertype::iterator end,
542
+ typename containertype::iterator curr)
543
+ : row_begin(begin), row_end(end), row_current(curr), col_current() {
544
+ if ( curr != end ) {
545
+ col_current = curr->TWOD_BEGIN_();
546
+ advance_past_end(); // in case cur->begin() == cur->end()
547
+ }
548
+ }
549
+ destructive_two_d_iterator(typename containertype::iterator begin,
550
+ typename containertype::iterator end,
551
+ typename containertype::iterator curr,
552
+ typename containertype::value_type::TWOD_ITER_ col)
553
+ : row_begin(begin), row_end(end), row_current(curr), col_current(col) {
554
+ advance_past_end(); // in case cur->begin() == cur->end()
555
+ }
556
+ destructive_two_d_iterator()
557
+ : row_begin(), row_end(), row_current(), col_current() {
558
+ }
559
+
560
+ typename containertype::iterator row_begin, row_end, row_current;
561
+ typename containertype::value_type::TWOD_ITER_ col_current;
562
+
563
+ // This is the part that destroys
564
+ void advance_past_end() { // used when col_current points to end()
565
+ while ( col_current == row_current->TWOD_END_() ) { // end of current row
566
+ row_current->clear(); // the destructive part
567
+ // It would be nice if we could decrement sparsetable->num_buckets here
568
+ ++row_current; // go to beginning of next
569
+ if ( row_current != row_end ) // col is irrelevant at end
570
+ col_current = row_current->TWOD_BEGIN_();
571
+ else
572
+ break; // don't go past row_end
573
+ }
574
+ }
575
+
576
+ // EVERYTHING FROM HERE DOWN IS THE SAME AS THE REGULAR ITERATOR
577
+ reference operator*() const { return *col_current; }
578
+ pointer operator->() const { return &(operator*()); }
579
+
580
+ iterator& operator++() {
581
+ assert(row_current != row_end); // how to ++ from there?
582
+ ++col_current;
583
+ advance_past_end(); // in case col_current is at end()
584
+ return *this;
585
+ }
586
+ iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; }
587
+
588
+ bool operator==(const iterator& it) const {
589
+ return ( row_begin == it.row_begin &&
590
+ row_end == it.row_end &&
591
+ row_current == it.row_current &&
592
+ (row_current == row_end || col_current == it.col_current) );
593
+ }
594
+ bool operator!=(const iterator& it) const { return !(*this == it); }
595
+ };
596
+
597
+ #undef TWOD_BEGIN_
598
+ #undef TWOD_END_
599
+ #undef TWOD_ITER_
600
+ #undef TWOD_CONST_ITER_
601
+
602
+
603
+
604
+
605
+ // SPARSE-TABLE
606
+ // ------------
607
+ // The idea is that a table with (logically) t buckets is divided
608
+ // into t/M *groups* of M buckets each. (M is a constant set in
609
+ // GROUP_SIZE for efficiency.) Each group is stored sparsely.
610
+ // Thus, inserting into the table causes some array to grow, which is
611
+ // slow but still constant time. Lookup involves doing a
612
+ // logical-position-to-sparse-position lookup, which is also slow but
613
+ // constant time. The larger M is, the slower these operations are
614
+ // but the less overhead (slightly).
615
+ //
616
+ // To store the sparse array, we store a bitmap B, where B[i] = 1 iff
617
+ // bucket i is non-empty. Then to look up bucket i we really look up
618
+ // array[# of 1s before i in B]. This is constant time for fixed M.
619
+ //
620
+ // Terminology: the position of an item in the overall table (from
621
+ // 1 .. t) is called its "location." The logical position in a group
622
+ // (from 1 .. M ) is called its "position." The actual location in
623
+ // the array (from 1 .. # of non-empty buckets in the group) is
624
+ // called its "offset."
625
+
626
+ // The weird mod in the offset is entirely to quiet compiler warnings
627
+ // as is the cast to int after doing the "x mod 256"
628
+ #define PUT_(take_from, offset) do { \
629
+ if (putc(static_cast<int>(((take_from) >> ((offset) % (sizeof(take_from)*8)))\
630
+ % 256), fp) \
631
+ == EOF) \
632
+ return false; \
633
+ } while (0)
634
+
635
+ #define GET_(add_to, offset) do { \
636
+ if ((x=getc(fp)) == EOF) \
637
+ return false; \
638
+ else \
639
+ add_to |= (static_cast<size_type>(x) << ((offset) % (sizeof(add_to)*8))); \
640
+ } while (0)
641
+
642
+ template <class T, u_int16_t GROUP_SIZE>
643
+ class sparsegroup {
644
+ public:
645
+ // Basic types
646
+ typedef T value_type;
647
+ typedef value_type* pointer;
648
+ typedef const value_type* const_pointer;
649
+ typedef table_iterator<sparsegroup<T, GROUP_SIZE> > iterator;
650
+ typedef const_table_iterator<sparsegroup<T, GROUP_SIZE> > const_iterator;
651
+ typedef table_element_adaptor<sparsegroup<T, GROUP_SIZE> > element_adaptor;
652
+ typedef value_type &reference;
653
+ typedef const value_type &const_reference;
654
+ typedef u_int16_t size_type; // max # of buckets
655
+ typedef int16_t difference_type;
656
+ typedef STL_NAMESPACE::reverse_iterator<const_iterator> const_reverse_iterator;
657
+ typedef STL_NAMESPACE::reverse_iterator<iterator> reverse_iterator;
658
+
659
+ // These are our special iterators, that go over non-empty buckets in a
660
+ // group. These aren't const-only because you can change non-empty bcks.
661
+ typedef pointer nonempty_iterator;
662
+ typedef const_pointer const_nonempty_iterator;
663
+ typedef STL_NAMESPACE::reverse_iterator<nonempty_iterator> reverse_nonempty_iterator;
664
+ typedef STL_NAMESPACE::reverse_iterator<const_nonempty_iterator> const_reverse_nonempty_iterator;
665
+
666
+ // Iterator functions
667
+ iterator begin() { return iterator(this, 0); }
668
+ const_iterator begin() const { return const_iterator(this, 0); }
669
+ iterator end() { return iterator(this, size()); }
670
+ const_iterator end() const { return const_iterator(this, size()); }
671
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
672
+ const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
673
+ reverse_iterator rend() { return reverse_iterator(begin()); }
674
+ const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
675
+
676
+ // We'll have versions for our special non-empty iterator too
677
+ nonempty_iterator nonempty_begin() { return group; }
678
+ const_nonempty_iterator nonempty_begin() const { return group; }
679
+ nonempty_iterator nonempty_end() { return group + num_buckets; }
680
+ const_nonempty_iterator nonempty_end() const { return group + num_buckets; }
681
+ reverse_nonempty_iterator nonempty_rbegin() {
682
+ return reverse_nonempty_iterator(nonempty_end());
683
+ }
684
+ const_reverse_nonempty_iterator nonempty_rbegin() const {
685
+ return const_reverse_nonempty_iterator(nonempty_end());
686
+ }
687
+ reverse_nonempty_iterator nonempty_rend() {
688
+ return reverse_nonempty_iterator(nonempty_begin());
689
+ }
690
+ const_reverse_nonempty_iterator nonempty_rend() const {
691
+ return const_reverse_nonempty_iterator(nonempty_begin());
692
+ }
693
+
694
+
695
+ // This gives us the "default" value to return for an empty bucket.
696
+ // We just use the default constructor on T, the template type
697
+ const_reference default_value() const {
698
+ static value_type defaultval = value_type();
699
+ return defaultval;
700
+ }
701
+
702
+
703
+ private:
704
+ // We need to do all this bit manipulation, of course. ick
705
+ static size_type charbit(size_type i) { return i >> 3; }
706
+ static size_type modbit(size_type i) { return 1 << (i&7); }
707
+ int bmtest(size_type i) const { return bitmap[charbit(i)] & modbit(i); }
708
+ void bmset(size_type i) { bitmap[charbit(i)] |= modbit(i); }
709
+ void bmclear(size_type i) { bitmap[charbit(i)] &= ~modbit(i); }
710
+
711
+ void* realloc_or_die(void* ptr, size_t num_bytes) {
712
+ void* retval = realloc(ptr, num_bytes);
713
+ if (retval == NULL) {
714
+ // We really should use PRIuS here, but I don't want to have to add
715
+ // a whole new configure option, with concomitant macro namespace
716
+ // pollution, just to print this (unlikely) error message. So I cast.
717
+ fprintf(stderr, "FATAL ERROR: failed to allocate %lu bytes for ptr %p",
718
+ static_cast<unsigned long>(num_bytes), ptr);
719
+ exit(1);
720
+ }
721
+ return retval;
722
+ }
723
+
724
+ value_type* allocate_group(size_t n) {
725
+ return static_cast<value_type*>(realloc_or_die(NULL,
726
+ n * sizeof(value_type)));
727
+ }
728
+
729
+ void free_group() {
730
+ // Valid even for empty group, because NULL+0 is defined to be NULL
731
+ value_type* end_it = group + num_buckets;
732
+ for (value_type* p = group; p != end_it; ++p)
733
+ p->~value_type();
734
+ free(group);
735
+ group = NULL;
736
+ }
737
+
738
+ public: // get_iter() in sparsetable needs it
739
+ // We need a small function that tells us how many set bits there are
740
+ // in positions 0..i-1 of the bitmap. It uses a big table.
741
+ // We make it static so templates don't allocate lots of these tables
742
+ static size_type pos_to_offset(const unsigned char *bm, size_type pos) {
743
+ // We could make these ints. The tradeoff is size (eg does it overwhelm
744
+ // the cache?) vs efficiency in referencing sub-word-sized array elements
745
+ static const char bits_in[256] = { // # of bits set in one char
746
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
747
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
748
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
749
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
750
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
751
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
752
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
753
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
754
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
755
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
756
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
757
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
758
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
759
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
760
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
761
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
762
+ };
763
+ size_type retval = 0;
764
+
765
+ // [Note: condition pos > 8 is an optimization; convince yourself we
766
+ // give exactly the same result as if we had pos >= 8 here instead.]
767
+ for ( ; pos > 8; pos -= 8 ) // bm[0..pos/8-1]
768
+ retval += bits_in[*bm++]; // chars we want *all* bits in
769
+ return retval + bits_in[*bm & ((1 << pos)-1)]; // the char that includes pos
770
+ }
771
+
772
+ size_type pos_to_offset(size_type pos) const { // not static but still const
773
+ return pos_to_offset(bitmap, pos);
774
+ }
775
+
776
+
777
+ public:
778
+ // Constructors -- default and copy -- and destructor
779
+ sparsegroup() : group(0), num_buckets(0) { memset(bitmap, 0, sizeof(bitmap)); }
780
+ sparsegroup(const sparsegroup& x) : group(0), num_buckets(x.num_buckets) {
781
+ if ( num_buckets ) {
782
+ group = allocate_group(x.num_buckets);
783
+ uninitialized_copy(x.group, x.group + x.num_buckets, group);
784
+ }
785
+ memcpy(bitmap, x.bitmap, sizeof(bitmap));
786
+ }
787
+ ~sparsegroup() { free_group(); }
788
+
789
+ // Operator= is just like the copy constructor, I guess
790
+ // TODO(austern): Make this exception safe. Handle exceptions in value_type's
791
+ // copy constructor.
792
+ sparsegroup &operator=(const sparsegroup& x) {
793
+ if ( &x == this ) return *this; // x = x
794
+ if ( x.num_buckets == 0 ) {
795
+ free_group();
796
+ } else {
797
+ value_type* p = allocate_group(x.num_buckets);
798
+ uninitialized_copy(x.group, x.group + x.num_buckets, p);
799
+ free_group();
800
+ group = p;
801
+ }
802
+ memcpy(bitmap, x.bitmap, sizeof(bitmap));
803
+ num_buckets = x.num_buckets;
804
+ return *this;
805
+ }
806
+
807
+ // Many STL algorithms use swap instead of copy constructors
808
+ void swap(sparsegroup& x) {
809
+ STL_NAMESPACE::swap(group, x.group);
810
+ for ( int i = 0; i < sizeof(bitmap) / sizeof(*bitmap); ++i )
811
+ STL_NAMESPACE::swap(bitmap[i], x.bitmap[i]); // swap not defined on arrays
812
+ STL_NAMESPACE::swap(num_buckets, x.num_buckets);
813
+ }
814
+
815
+ // It's always nice to be able to clear a table without deallocating it
816
+ void clear() {
817
+ free_group();
818
+ memset(bitmap, 0, sizeof(bitmap));
819
+ num_buckets = 0;
820
+ }
821
+
822
+ // Functions that tell you about size. Alas, these aren't so useful
823
+ // because our table is always fixed size.
824
+ size_type size() const { return GROUP_SIZE; }
825
+ size_type max_size() const { return GROUP_SIZE; }
826
+ bool empty() const { return false; }
827
+ // We also may want to know how many *used* buckets there are
828
+ size_type num_nonempty() const { return num_buckets; }
829
+
830
+
831
+ // get()/set() are explicitly const/non-const. You can use [] if
832
+ // you want something that can be either (potentially more expensive).
833
+ const_reference get(size_type i) const {
834
+ if ( bmtest(i) ) // bucket i is occupied
835
+ return group[pos_to_offset(bitmap, i)];
836
+ else
837
+ return default_value(); // return the default reference
838
+ }
839
+
840
+ // TODO(csilvers): make protected + friend
841
+ // This is used by sparse_hashtable to get an element from the table
842
+ // when we know it exists.
843
+ const_reference unsafe_get(size_type i) const {
844
+ assert(bmtest(i));
845
+ return group[pos_to_offset(bitmap, i)];
846
+ }
847
+
848
+ // TODO(csilvers): make protected + friend
849
+ reference mutating_get(size_type i) { // fills bucket i before getting
850
+ if ( !bmtest(i) )
851
+ set(i, default_value());
852
+ return group[pos_to_offset(bitmap, i)];
853
+ }
854
+
855
+ // Syntactic sugar. It's easy to return a const reference. To
856
+ // return a non-const reference, we need to use the assigner adaptor.
857
+ const_reference operator[](size_type i) const {
858
+ return get(i);
859
+ }
860
+
861
+ element_adaptor operator[](size_type i) {
862
+ return element_adaptor(this, i);
863
+ }
864
+
865
+ private:
866
+ // Create space at group[offset], assuming value_type has trivial
867
+ // copy constructor and destructor. (Really, we want it to have
868
+ // "trivial move", because that's what realloc and memmove both do.
869
+ // But there's no way to capture that using type_traits, so we
870
+ // pretend that move(x, y) is equivalent to "x.~T(); new(x) T(y);"
871
+ // which is pretty much correct, if a bit conservative.)
872
+ void set_aux(size_type offset, true_type) {
873
+ group = (value_type *)
874
+ realloc_or_die(group, sizeof(*group) * (num_buckets+1));
875
+ // This is equivalent to memmove(), but faster on my Intel P4,
876
+ // at least with gcc4.1 -O2 / glibc 2.3.6.
877
+ for (size_type i = num_buckets; i > offset; --i)
878
+ memcpy(group + i, group + i-1, sizeof(*group));
879
+ }
880
+
881
+ // Create space at group[offset], without special assumptions about value_type
882
+ void set_aux(size_type offset, false_type) {
883
+ // This is valid because 0 <= offset <= num_buckets
884
+ value_type* p = allocate_group(num_buckets + 1);
885
+ uninitialized_copy(group, group + offset, p);
886
+ uninitialized_copy(group + offset, group + num_buckets, p + offset + 1);
887
+ free_group();
888
+ group = p;
889
+ }
890
+
891
+ public:
892
+ // This returns a reference to the inserted item (which is a copy of val).
893
+ // TODO(austern): Make this exception safe: handle exceptions from
894
+ // value_type's copy constructor.
895
+ reference set(size_type i, const_reference val) {
896
+ size_type offset = pos_to_offset(bitmap, i); // where we'll find (or insert)
897
+ if ( bmtest(i) ) {
898
+ // Delete the old value, which we're replacing with the new one
899
+ group[offset].~value_type();
900
+ } else {
901
+ typedef integral_constant<bool,
902
+ (has_trivial_copy<value_type>::value &&
903
+ has_trivial_destructor<value_type>::value)>
904
+ realloc_and_memmove_ok; // we pretend mv(x,y) == "x.~T(); new(x) T(y)"
905
+ set_aux(offset, realloc_and_memmove_ok());
906
+ ++num_buckets;
907
+ bmset(i);
908
+ }
909
+ // This does the actual inserting. Since we made the array using
910
+ // malloc, we use "placement new" to just call the constructor.
911
+ new(&group[offset]) value_type(val);
912
+ return group[offset];
913
+ }
914
+
915
+ // We let you see if a bucket is non-empty without retrieving it
916
+ bool test(size_type i) const {
917
+ return bmtest(i) ? true : false; // cast an int to a bool
918
+ }
919
+ bool test(iterator pos) const {
920
+ return bmtest(pos.pos) ? true : false;
921
+ }
922
+
923
+ private:
924
+ // Shrink the array, assuming value_type has trivial copy
925
+ // constructor and destructor. (Really, we want it to have "trivial
926
+ // move", because that's what realloc and memmove both do. But
927
+ // there's no way to capture that using type_traits, so we pretend
928
+ // that move(x, y) is equivalent to ""x.~T(); new(x) T(y);"
929
+ // which is pretty much correct, if a bit conservative.)
930
+ void erase_aux(size_type offset, true_type) {
931
+ // This isn't technically necessary, since we know we have a
932
+ // trivial destructor, but is a cheap way to get a bit more safety.
933
+ group[offset].~value_type();
934
+ // This is equivalent to memmove(), but faster on my Intel P4,
935
+ // at lesat with gcc4.1 -O2 / glibc 2.3.6.
936
+ assert(num_buckets > 0);
937
+ for (size_type i = offset; i < num_buckets-1; ++i)
938
+ memcpy(group + i, group + i+1, sizeof(*group)); // hopefully inlined!
939
+ group = (value_type *)
940
+ realloc_or_die(group, sizeof(*group) * (num_buckets-1));
941
+ }
942
+
943
+ // Shrink the array, without any special assumptions about value_type.
944
+ void erase_aux(size_type offset, false_type) {
945
+ // This is valid because 0 <= offset < num_buckets. Note the inequality.
946
+ value_type* p = allocate_group(num_buckets - 1);
947
+ uninitialized_copy(group, group + offset, p);
948
+ uninitialized_copy(group + offset + 1, group + num_buckets, p + offset);
949
+ free_group();
950
+ group = p;
951
+ }
952
+
953
+ public:
954
+ // This takes the specified elements out of the group. This is
955
+ // "undefining", rather than "clearing".
956
+ // TODO(austern): Make this exception safe: handle exceptions from
957
+ // value_type's copy constructor.
958
+ void erase(size_type i) {
959
+ if ( bmtest(i) ) { // trivial to erase empty bucket
960
+ size_type offset = pos_to_offset(bitmap,i); // where we'll find (or insert)
961
+ if ( num_buckets == 1 ) {
962
+ free_group();
963
+ group = NULL;
964
+ } else {
965
+ typedef integral_constant<bool,
966
+ (has_trivial_copy<value_type>::value &&
967
+ has_trivial_destructor<value_type>::value)>
968
+ realloc_and_memmove_ok; // pretend mv(x,y) == "x.~T(); new(x) T(y)"
969
+ erase_aux(offset, realloc_and_memmove_ok());
970
+ }
971
+ --num_buckets;
972
+ bmclear(i);
973
+ }
974
+ }
975
+
976
+ void erase(iterator pos) {
977
+ erase(pos.pos);
978
+ }
979
+
980
+ void erase(iterator start_it, iterator end_it) {
981
+ // This could be more efficient, but to do so we'd need to make
982
+ // bmclear() clear a range of indices. Doesn't seem worth it.
983
+ for ( ; start_it != end_it; ++start_it )
984
+ erase(start_it);
985
+ }
986
+
987
+
988
+ // I/O
989
+ // We support reading and writing groups to disk. We don't store
990
+ // the actual array contents (which we don't know how to store),
991
+ // just the bitmap and size. Meant to be used with table I/O.
992
+ // Returns true if all was ok
993
+ bool write_metadata(FILE *fp) const {
994
+ assert(sizeof(num_buckets) == 2); // we explicitly set to u_int16_t
995
+ PUT_(num_buckets, 8);
996
+ PUT_(num_buckets, 0);
997
+ if ( !fwrite(bitmap, sizeof(bitmap), 1, fp) ) return false;
998
+ return true;
999
+ }
1000
+
1001
+ // Reading destroys the old group contents! Returns true if all was ok
1002
+ bool read_metadata(FILE *fp) {
1003
+ clear();
1004
+
1005
+ int x; // the GET_ macro requires an 'int x' to be defined
1006
+ GET_(num_buckets, 8);
1007
+ GET_(num_buckets, 0);
1008
+
1009
+ if ( !fread(bitmap, sizeof(bitmap), 1, fp) ) return false;
1010
+
1011
+ // We'll allocate the space, but we won't fill it: it will be
1012
+ // left as uninitialized raw memory.
1013
+ group = allocate_group(num_buckets);
1014
+ return true;
1015
+ }
1016
+
1017
+ // If your keys and values are simple enough, we can write them
1018
+ // to disk for you. "simple enough" means POD and no pointers.
1019
+ // However, we don't try to normalize endianness
1020
+ bool write_nopointer_data(FILE *fp) const {
1021
+ for ( const_nonempty_iterator it = nonempty_begin();
1022
+ it != nonempty_end(); ++it ) {
1023
+ if ( !fwrite(&*it, sizeof(*it), 1, fp) ) return false;
1024
+ }
1025
+ return true;
1026
+ }
1027
+
1028
+ // When reading, we have to override the potential const-ness of *it.
1029
+ // Again, only meaningful if value_type is a POD.
1030
+ bool read_nopointer_data(FILE *fp) {
1031
+ for ( nonempty_iterator it = nonempty_begin();
1032
+ it != nonempty_end(); ++it ) {
1033
+ if ( !fread(reinterpret_cast<void*>(&(*it)), sizeof(*it), 1, fp) )
1034
+ return false;
1035
+ }
1036
+ return true;
1037
+ }
1038
+
1039
+ // Comparisons. Note the comparisons are pretty arbitrary: we
1040
+ // compare values of the first index that isn't equal (using default
1041
+ // value for empty buckets).
1042
+ bool operator==(const sparsegroup& x) const {
1043
+ return ( num_buckets == x.num_buckets &&
1044
+ memcmp(bitmap, x.bitmap, sizeof(bitmap)) == 0 &&
1045
+ STL_NAMESPACE::equal(begin(), end(), x.begin()) ); // from algorithm
1046
+ }
1047
+ bool operator<(const sparsegroup& x) const { // also from algorithm
1048
+ return STL_NAMESPACE::lexicographical_compare(begin(), end(),
1049
+ x.begin(), x.end());
1050
+ }
1051
+ bool operator!=(const sparsegroup& x) const { return !(*this == x); }
1052
+ bool operator<=(const sparsegroup& x) const { return !(x < *this); }
1053
+ bool operator>(const sparsegroup& x) const { return x < *this; }
1054
+ bool operator>=(const sparsegroup& x) const { return !(*this < x); }
1055
+
1056
+ private:
1057
+ // The actual data
1058
+ value_type *group; // (small) array of T's
1059
+ unsigned char bitmap[(GROUP_SIZE-1)/8 + 1]; // fancy math is so we round up
1060
+ size_type num_buckets; // limits GROUP_SIZE to 64K
1061
+ };
1062
+
1063
+ // We need a global swap as well
1064
+ template <class T, u_int16_t GROUP_SIZE>
1065
+ inline void swap(sparsegroup<T,GROUP_SIZE> &x, sparsegroup<T,GROUP_SIZE> &y) {
1066
+ x.swap(y);
1067
+ }
1068
+
1069
+ // ---------------------------------------------------------------------------
1070
+
1071
+
1072
+ template <class T, u_int16_t GROUP_SIZE = DEFAULT_SPARSEGROUP_SIZE>
1073
+ class sparsetable {
1074
+ public:
1075
+ // Basic types
1076
+ typedef T value_type; // stolen from stl_vector.h
1077
+ typedef value_type* pointer;
1078
+ typedef const value_type* const_pointer;
1079
+ typedef table_iterator<sparsetable<T, GROUP_SIZE> > iterator;
1080
+ typedef const_table_iterator<sparsetable<T, GROUP_SIZE> > const_iterator;
1081
+ typedef table_element_adaptor<sparsetable<T, GROUP_SIZE> > element_adaptor;
1082
+ typedef value_type &reference;
1083
+ typedef const value_type &const_reference;
1084
+ typedef size_t size_type;
1085
+ typedef ptrdiff_t difference_type;
1086
+ typedef STL_NAMESPACE::reverse_iterator<const_iterator> const_reverse_iterator;
1087
+ typedef STL_NAMESPACE::reverse_iterator<iterator> reverse_iterator;
1088
+
1089
+ // These are our special iterators, that go over non-empty buckets in a
1090
+ // table. These aren't const only because you can change non-empty bcks.
1091
+ typedef two_d_iterator< vector< sparsegroup<value_type, GROUP_SIZE> > >
1092
+ nonempty_iterator;
1093
+ typedef const_two_d_iterator< vector< sparsegroup<value_type, GROUP_SIZE> > >
1094
+ const_nonempty_iterator;
1095
+ typedef STL_NAMESPACE::reverse_iterator<nonempty_iterator> reverse_nonempty_iterator;
1096
+ typedef STL_NAMESPACE::reverse_iterator<const_nonempty_iterator> const_reverse_nonempty_iterator;
1097
+ // Another special iterator: it frees memory as it iterates (used to resize)
1098
+ typedef destructive_two_d_iterator< vector< sparsegroup<value_type, GROUP_SIZE> > >
1099
+ destructive_iterator;
1100
+
1101
+ // Iterator functions
1102
+ iterator begin() { return iterator(this, 0); }
1103
+ const_iterator begin() const { return const_iterator(this, 0); }
1104
+ iterator end() { return iterator(this, size()); }
1105
+ const_iterator end() const { return const_iterator(this, size()); }
1106
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
1107
+ const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
1108
+ reverse_iterator rend() { return reverse_iterator(begin()); }
1109
+ const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
1110
+
1111
+ // Versions for our special non-empty iterator
1112
+ nonempty_iterator nonempty_begin() {
1113
+ return nonempty_iterator(groups.begin(), groups.end(), groups.begin());
1114
+ }
1115
+ const_nonempty_iterator nonempty_begin() const {
1116
+ return const_nonempty_iterator(groups.begin(),groups.end(), groups.begin());
1117
+ }
1118
+ nonempty_iterator nonempty_end() {
1119
+ return nonempty_iterator(groups.begin(), groups.end(), groups.end());
1120
+ }
1121
+ const_nonempty_iterator nonempty_end() const {
1122
+ return const_nonempty_iterator(groups.begin(), groups.end(), groups.end());
1123
+ }
1124
+ reverse_nonempty_iterator nonempty_rbegin() {
1125
+ return reverse_nonempty_iterator(nonempty_end());
1126
+ }
1127
+ const_reverse_nonempty_iterator nonempty_rbegin() const {
1128
+ return const_reverse_nonempty_iterator(nonempty_end());
1129
+ }
1130
+ reverse_nonempty_iterator nonempty_rend() {
1131
+ return reverse_nonempty_iterator(nonempty_begin());
1132
+ }
1133
+ const_reverse_nonempty_iterator nonempty_rend() const {
1134
+ return const_reverse_nonempty_iterator(nonempty_begin());
1135
+ }
1136
+ destructive_iterator destructive_begin() {
1137
+ return destructive_iterator(groups.begin(), groups.end(), groups.begin());
1138
+ }
1139
+ destructive_iterator destructive_end() {
1140
+ return destructive_iterator(groups.begin(), groups.end(), groups.end());
1141
+ }
1142
+
1143
+ private:
1144
+ typedef typename vector< sparsegroup<value_type, GROUP_SIZE> >::reference
1145
+ GroupsReference;
1146
+ typedef typename
1147
+ vector< sparsegroup<value_type, GROUP_SIZE> >::const_reference
1148
+ GroupsConstReference;
1149
+ typedef typename vector< sparsegroup<value_type, GROUP_SIZE> >::iterator
1150
+ GroupsIterator;
1151
+ typedef typename vector< sparsegroup<value_type, GROUP_SIZE> >::const_iterator
1152
+ GroupsConstIterator;
1153
+
1154
+ // How to deal with the proper group
1155
+ static size_type num_groups(size_type num) { // how many to hold num buckets
1156
+ return num == 0 ? 0 : ((num-1) / GROUP_SIZE) + 1;
1157
+ }
1158
+
1159
+ u_int16_t pos_in_group(size_type i) const {
1160
+ return static_cast<u_int16_t>(i % GROUP_SIZE);
1161
+ }
1162
+ size_type group_num(size_type i) const {
1163
+ return i / GROUP_SIZE;
1164
+ }
1165
+ GroupsReference which_group(size_type i) {
1166
+ return groups[group_num(i)];
1167
+ }
1168
+ GroupsConstReference which_group(size_type i) const {
1169
+ return groups[group_num(i)];
1170
+ }
1171
+
1172
+ public:
1173
+ // Constructors -- default, normal (when you specify size), and copy
1174
+ sparsetable(size_type sz = 0)
1175
+ : groups(num_groups(sz)), table_size(sz), num_buckets(0) { }
1176
+ // We'll can get away with using the default copy constructor,
1177
+ // and default destructor, and hence the default operator=. Huzzah!
1178
+
1179
+ // Many STL algorithms use swap instead of copy constructors
1180
+ void swap(sparsetable& x) {
1181
+ STL_NAMESPACE::swap(groups, x.groups);
1182
+ STL_NAMESPACE::swap(table_size, x.table_size);
1183
+ STL_NAMESPACE::swap(num_buckets, x.num_buckets);
1184
+ }
1185
+
1186
+ // It's always nice to be able to clear a table without deallocating it
1187
+ void clear() {
1188
+ GroupsIterator group;
1189
+ for ( group = groups.begin(); group != groups.end(); ++group ) {
1190
+ group->clear();
1191
+ }
1192
+ num_buckets = 0;
1193
+ }
1194
+
1195
+ // Functions that tell you about size.
1196
+ // NOTE: empty() is non-intuitive! It does not tell you the number
1197
+ // of not-empty buckets (use num_nonempty() for that). Instead
1198
+ // it says whether you've allocated any buckets or not.
1199
+ size_type size() const { return table_size; }
1200
+ size_type max_size() const { return size_type(-1); }
1201
+ bool empty() const { return table_size == 0; }
1202
+ // We also may want to know how many *used* buckets there are
1203
+ size_type num_nonempty() const { return num_buckets; }
1204
+
1205
+ // OK, we'll let you resize one of these puppies
1206
+ void resize(size_type new_size) {
1207
+ groups.resize(num_groups(new_size));
1208
+ if ( new_size < table_size) { // lower num_buckets, clear last group
1209
+ if ( pos_in_group(new_size) > 0 ) // need to clear inside last group
1210
+ groups.back().erase(groups.back().begin() + pos_in_group(new_size),
1211
+ groups.back().end());
1212
+ num_buckets = 0; // refigure # of used buckets
1213
+ GroupsConstIterator group;
1214
+ for ( group = groups.begin(); group != groups.end(); ++group )
1215
+ num_buckets += group->num_nonempty();
1216
+ }
1217
+ table_size = new_size;
1218
+ }
1219
+
1220
+
1221
+ // We let you see if a bucket is non-empty without retrieving it
1222
+ bool test(size_type i) const {
1223
+ return which_group(i).test(pos_in_group(i));
1224
+ }
1225
+ bool test(iterator pos) const {
1226
+ return which_group(pos.pos).test(pos_in_group(pos.pos));
1227
+ }
1228
+ bool test(const_iterator pos) const {
1229
+ return which_group(pos.pos).test(pos_in_group(pos.pos));
1230
+ }
1231
+
1232
+ // We only return const_references because it's really hard to
1233
+ // return something settable for empty buckets. Use set() instead.
1234
+ const_reference get(size_type i) const {
1235
+ assert(i < table_size);
1236
+ return which_group(i).get(pos_in_group(i));
1237
+ }
1238
+
1239
+ // TODO(csilvers): make protected + friend
1240
+ // This is used by sparse_hashtable to get an element from the table
1241
+ // when we know it exists (because the caller has called test(i)).
1242
+ const_reference unsafe_get(size_type i) const {
1243
+ assert(i < table_size);
1244
+ assert(test(i));
1245
+ return which_group(i).unsafe_get(pos_in_group(i));
1246
+ }
1247
+
1248
+ // TODO(csilvers): make protected + friend element_adaptor
1249
+ reference mutating_get(size_type i) { // fills bucket i before getting
1250
+ assert(i < table_size);
1251
+ size_type old_numbuckets = which_group(i).num_nonempty();
1252
+ reference retval = which_group(i).mutating_get(pos_in_group(i));
1253
+ num_buckets += which_group(i).num_nonempty() - old_numbuckets;
1254
+ return retval;
1255
+ }
1256
+
1257
+ // Syntactic sugar. As in sparsegroup, the non-const version is harder
1258
+ const_reference operator[](size_type i) const {
1259
+ return get(i);
1260
+ }
1261
+
1262
+ element_adaptor operator[](size_type i) {
1263
+ return element_adaptor(this, i);
1264
+ }
1265
+
1266
+ // Needed for hashtables, gets as a nonempty_iterator. Crashes for empty bcks
1267
+ const_nonempty_iterator get_iter(size_type i) const {
1268
+ assert(test(i)); // how can a nonempty_iterator point to an empty bucket?
1269
+ return const_nonempty_iterator(
1270
+ groups.begin(), groups.end(),
1271
+ groups.begin() + group_num(i),
1272
+ (groups[group_num(i)].nonempty_begin() +
1273
+ groups[group_num(i)].pos_to_offset(pos_in_group(i))));
1274
+ }
1275
+ // For nonempty we can return a non-const version
1276
+ nonempty_iterator get_iter(size_type i) {
1277
+ assert(test(i)); // how can a nonempty_iterator point to an empty bucket?
1278
+ return nonempty_iterator(
1279
+ groups.begin(), groups.end(),
1280
+ groups.begin() + group_num(i),
1281
+ (groups[group_num(i)].nonempty_begin() +
1282
+ groups[group_num(i)].pos_to_offset(pos_in_group(i))));
1283
+ }
1284
+
1285
+
1286
+ // This returns a reference to the inserted item (which is a copy of val)
1287
+ // The trick is to figure out whether we're replacing or inserting anew
1288
+ reference set(size_type i, const_reference val) {
1289
+ assert(i < table_size);
1290
+ size_type old_numbuckets = which_group(i).num_nonempty();
1291
+ reference retval = which_group(i).set(pos_in_group(i), val);
1292
+ num_buckets += which_group(i).num_nonempty() - old_numbuckets;
1293
+ return retval;
1294
+ }
1295
+
1296
+ // This takes the specified elements out of the table. This is
1297
+ // "undefining", rather than "clearing".
1298
+ void erase(size_type i) {
1299
+ assert(i < table_size);
1300
+ size_type old_numbuckets = which_group(i).num_nonempty();
1301
+ which_group(i).erase(pos_in_group(i));
1302
+ num_buckets += which_group(i).num_nonempty() - old_numbuckets;
1303
+ }
1304
+
1305
+ void erase(iterator pos) {
1306
+ erase(pos.pos);
1307
+ }
1308
+
1309
+ void erase(iterator start_it, iterator end_it) {
1310
+ // This could be more efficient, but then we'd need to figure
1311
+ // out if we spanned groups or not. Doesn't seem worth it.
1312
+ for ( ; start_it != end_it; ++start_it )
1313
+ erase(start_it);
1314
+ }
1315
+
1316
+
1317
+ // We support reading and writing tables to disk. We don't store
1318
+ // the actual array contents (which we don't know how to store),
1319
+ // just the groups and sizes. Returns true if all went ok.
1320
+
1321
+ private:
1322
+ // Every time the disk format changes, this should probably change too
1323
+ static const unsigned long MAGIC_NUMBER = 0x24687531;
1324
+
1325
+ // Old versions of this code write all data in 32 bits. We need to
1326
+ // support these files as well as having support for 64-bit systems.
1327
+ // So we use the following encoding scheme: for values < 2^32-1, we
1328
+ // store in 4 bytes in big-endian order. For values > 2^32, we
1329
+ // store 0xFFFFFFF followed by 8 bytes in big-endian order. This
1330
+ // causes us to mis-read old-version code that stores exactly
1331
+ // 0xFFFFFFF, but I don't think that is likely to have happened for
1332
+ // these particular values.
1333
+ static bool write_32_or_64(FILE* fp, size_type value) {
1334
+ if ( value < 0xFFFFFFFFULL ) { // fits in 4 bytes
1335
+ PUT_(value, 24);
1336
+ PUT_(value, 16);
1337
+ PUT_(value, 8);
1338
+ PUT_(value, 0);
1339
+ } else if ( value == 0xFFFFFFFFUL ) { // special case in 32bit systems
1340
+ PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); // marker
1341
+ PUT_(0, 0); PUT_(0, 0); PUT_(0, 0); PUT_(0, 0);
1342
+ PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0);
1343
+ } else {
1344
+ PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); // marker
1345
+ PUT_(value, 56);
1346
+ PUT_(value, 48);
1347
+ PUT_(value, 40);
1348
+ PUT_(value, 32);
1349
+ PUT_(value, 24);
1350
+ PUT_(value, 16);
1351
+ PUT_(value, 8);
1352
+ PUT_(value, 0);
1353
+ }
1354
+ return true;
1355
+ }
1356
+
1357
+ static bool read_32_or_64(FILE* fp, size_type *value) { // reads into value
1358
+ size_type first4 = 0;
1359
+ int x;
1360
+ GET_(first4, 24);
1361
+ GET_(first4, 16);
1362
+ GET_(first4, 8);
1363
+ GET_(first4, 0);
1364
+ if ( first4 < 0xFFFFFFFFULL ) {
1365
+ *value = first4;
1366
+ } else {
1367
+ GET_(*value, 56);
1368
+ GET_(*value, 48);
1369
+ GET_(*value, 40);
1370
+ GET_(*value, 32);
1371
+ GET_(*value, 24);
1372
+ GET_(*value, 16);
1373
+ GET_(*value, 8);
1374
+ GET_(*value, 0);
1375
+ }
1376
+ return true;
1377
+ }
1378
+
1379
+ public:
1380
+ bool write_metadata(FILE *fp) const {
1381
+ if ( !write_32_or_64(fp, MAGIC_NUMBER) ) return false;
1382
+ if ( !write_32_or_64(fp, table_size) ) return false;
1383
+ if ( !write_32_or_64(fp, num_buckets) ) return false;
1384
+
1385
+ GroupsConstIterator group;
1386
+ for ( group = groups.begin(); group != groups.end(); ++group )
1387
+ if ( group->write_metadata(fp) == false ) return false;
1388
+ return true;
1389
+ }
1390
+
1391
+ // Reading destroys the old table contents! Returns true if read ok.
1392
+ bool read_metadata(FILE *fp) {
1393
+ size_type magic_read = 0;
1394
+ if ( !read_32_or_64(fp, &magic_read) ) return false;
1395
+ if ( magic_read != MAGIC_NUMBER ) {
1396
+ clear(); // just to be consistent
1397
+ return false;
1398
+ }
1399
+
1400
+ if ( !read_32_or_64(fp, &table_size) ) return false;
1401
+ if ( !read_32_or_64(fp, &num_buckets) ) return false;
1402
+
1403
+ resize(table_size); // so the vector's sized ok
1404
+ GroupsIterator group;
1405
+ for ( group = groups.begin(); group != groups.end(); ++group )
1406
+ if ( group->read_metadata(fp) == false ) return false;
1407
+ return true;
1408
+ }
1409
+
1410
+ // This code is identical to that for SparseGroup
1411
+ // If your keys and values are simple enough, we can write them
1412
+ // to disk for you. "simple enough" means no pointers.
1413
+ // However, we don't try to normalize endianness
1414
+ bool write_nopointer_data(FILE *fp) const {
1415
+ for ( const_nonempty_iterator it = nonempty_begin();
1416
+ it != nonempty_end(); ++it ) {
1417
+ if ( !fwrite(&*it, sizeof(*it), 1, fp) ) return false;
1418
+ }
1419
+ return true;
1420
+ }
1421
+
1422
+ // When reading, we have to override the potential const-ness of *it
1423
+ bool read_nopointer_data(FILE *fp) {
1424
+ for ( nonempty_iterator it = nonempty_begin();
1425
+ it != nonempty_end(); ++it ) {
1426
+ if ( !fread(reinterpret_cast<void*>(&(*it)), sizeof(*it), 1, fp) )
1427
+ return false;
1428
+ }
1429
+ return true;
1430
+ }
1431
+
1432
+ // Comparisons. Note the comparisons are pretty arbitrary: we
1433
+ // compare values of the first index that isn't equal (using default
1434
+ // value for empty buckets).
1435
+ bool operator==(const sparsetable& x) const {
1436
+ return ( table_size == x.table_size &&
1437
+ num_buckets == x.num_buckets &&
1438
+ groups == x.groups );
1439
+ }
1440
+ bool operator<(const sparsetable& x) const { // also from algobase.h
1441
+ return STL_NAMESPACE::lexicographical_compare(begin(), end(),
1442
+ x.begin(), x.end());
1443
+ }
1444
+ bool operator!=(const sparsetable& x) const { return !(*this == x); }
1445
+ bool operator<=(const sparsetable& x) const { return !(x < *this); }
1446
+ bool operator>(const sparsetable& x) const { return x < *this; }
1447
+ bool operator>=(const sparsetable& x) const { return !(*this < x); }
1448
+
1449
+
1450
+ private:
1451
+ // The actual data
1452
+ vector< sparsegroup<value_type, GROUP_SIZE> > groups; // our list of groups
1453
+ size_type table_size; // how many buckets they want
1454
+ size_type num_buckets; // number of non-empty buckets
1455
+ };
1456
+
1457
+ // We need a global swap as well
1458
+ template <class T, u_int16_t GROUP_SIZE>
1459
+ inline void swap(sparsetable<T,GROUP_SIZE> &x, sparsetable<T,GROUP_SIZE> &y) {
1460
+ x.swap(y);
1461
+ }
1462
+
1463
+ #undef GET_
1464
+ #undef PUT_
1465
+
1466
+ _END_GOOGLE_NAMESPACE_
1467
+
1468
+ #endif