OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libstdc++-v3/] [include/] [tr1/] [hashtable] - Blame information for rev 17

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 17 jlechner
// Internal header for TR1 unordered_set and unordered_map -*- C++ -*-
2
 
3
// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
4
//
5
// This file is part of the GNU ISO C++ Library.  This library is free
6
// software; you can redistribute it and/or modify it under the
7
// terms of the GNU General Public License as published by the
8
// Free Software Foundation; either version 2, or (at your option)
9
// any later version.
10
 
11
// This library is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
// GNU General Public License for more details.
15
 
16
// You should have received a copy of the GNU General Public License along
17
// with this library; see the file COPYING.  If not, write to the Free
18
// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19
// USA.
20
 
21
// As a special exception, you may use this file as part of a free software
22
// library without restriction.  Specifically, if other files instantiate
23
// templates or use macros or inline functions from this file, or you compile
24
// this file and link it with other files to produce an executable, this
25
// file does not by itself cause the resulting executable to be covered by
26
// the GNU General Public License.  This exception does not however
27
// invalidate any other reasons why the executable file might be covered by
28
// the GNU General Public License.
29
 
30
/** @file
31
 *  This is a TR1 C++ Library header.
32
 */
33
 
34
// This header file defines std::tr1::hashtable, which is used to
35
// implement std::tr1::unordered_set, std::tr1::unordered_map,
36
// std::tr1::unordered_multiset, and std::tr1::unordered_multimap.
37
// hashtable has many template parameters, partly to accommodate
38
// the differences between those four classes and partly to
39
// accommodate policy choices that go beyond what TR1 calls for.
40
 
41
// ??? Arguably this should be Internal::hashtable, not std::tr1::hashtable.
42
 
43
// Class template hashtable attempts to encapsulate all reasonable
44
// variation among hash tables that use chaining.  It does not handle
45
// open addressing.
46
 
47
// References:
48
// M. Austern, "A Proposal to Add Hash Tables to the Standard
49
//    Library (revision 4)," WG21 Document N1456=03-0039, 2003.
50
// D. E. Knuth, The Art of Computer Programming, v. 3, Sorting and Searching.
51
// A. Tavori and V. Dreizin, "Generic Associative Containers", 2004.
52
//    ??? Full citation?
53
 
54
#ifndef GNU_LIBSTDCXX_TR1_HASHTABLE_
55
#define GNU_LIBSTDCXX_TR1_HASHTABLE_
56
 
57
#include                // For std::pair
58
#include 
59
#include 
60
#include 
61
#include 
62
#include 
63
#include        // For true_type and false_type
64
 
65
//----------------------------------------------------------------------
66
// General utilities
67
 
68
namespace Internal
69
{
70
  template
71
    struct IF;
72
 
73
  template
74
    struct IF
75
    { typedef IfTrue type; };
76
 
77
  template 
78
    struct IF
79
    { typedef IfFalse type; };
80
 
81
  // Helper function: return distance(first, last) for forward
82
  // iterators, or 0 for input iterators.
83
  template
84
    inline typename std::iterator_traits::difference_type
85
    distance_fw(Iterator first, Iterator last, std::input_iterator_tag)
86
    { return 0; }
87
 
88
  template
89
    inline typename std::iterator_traits::difference_type
90
    distance_fw(Iterator first, Iterator last, std::forward_iterator_tag)
91
    { return std::distance(first, last); }
92
 
93
  template
94
    inline typename std::iterator_traits::difference_type
95
    distance_fw(Iterator first, Iterator last)
96
    {
97
      typedef typename std::iterator_traits::iterator_category tag;
98
      return distance_fw(first, last, tag());
99
    }
100
 
101
} // namespace Internal
102
 
103
//----------------------------------------------------------------------
104
// Auxiliary types used for all instantiations of hashtable: nodes
105
// and iterators.
106
 
107
// Nodes, used to wrap elements stored in the hash table.  A policy
108
// template parameter of class template hashtable controls whether
109
// nodes also store a hash code. In some cases (e.g. strings) this may
110
// be a performance win.
111
 
112
namespace Internal
113
{
114
  template
115
    struct hash_node;
116
 
117
  template
118
    struct hash_node
119
    {
120
      Value m_v;
121
      std::size_t hash_code;
122
      hash_node* m_next;
123
    };
124
 
125
  template
126
    struct hash_node
127
    {
128
      Value m_v;
129
      hash_node* m_next;
130
    };
131
 
132
  // Local iterators, used to iterate within a bucket but not between
133
  // buckets.
134
 
135
  template
136
    struct node_iterator_base
137
    {
138
      node_iterator_base(hash_node* p)
139
      : m_cur(p) { }
140
 
141
      void
142
      incr()
143
      { m_cur = m_cur->m_next; }
144
 
145
      hash_node* m_cur;
146
    };
147
 
148
  template
149
    inline bool
150
    operator==(const node_iterator_base& x,
151
               const node_iterator_base& y)
152
    { return x.m_cur == y.m_cur; }
153
 
154
  template
155
    inline bool
156
    operator!=(const node_iterator_base& x,
157
               const node_iterator_base& y)
158
    { return x.m_cur != y.m_cur; }
159
 
160
  template
161
    struct node_iterator
162
    : public node_iterator_base
163
    {
164
      typedef Value                                    value_type;
165
      typedef typename IF::type
166
                                                       pointer;
167
      typedef typename IF::type
168
                                                       reference;
169
      typedef std::ptrdiff_t                           difference_type;
170
      typedef std::forward_iterator_tag                iterator_category;
171
 
172
      node_iterator()
173
      : node_iterator_base(0) { }
174
 
175
      explicit
176
      node_iterator(hash_node* p)
177
      : node_iterator_base(p) { }
178
 
179
      reference
180
      operator*() const
181
      { return this->m_cur->m_v; }
182
 
183
      pointer
184
      operator->() const
185
      { return &this->m_cur->m_v; }
186
 
187
      node_iterator&
188
      operator++()
189
      {
190
        this->incr();
191
        return *this;
192
      }
193
 
194
      node_iterator
195
      operator++(int)
196
      {
197
        node_iterator tmp(*this);
198
        this->incr();
199
        return tmp;
200
      }
201
    };
202
 
203
  template
204
    struct node_const_iterator
205
    : public node_iterator_base
206
    {
207
      typedef Value                                    value_type;
208
      typedef const Value*                             pointer;
209
      typedef const Value&                             reference;
210
      typedef std::ptrdiff_t                           difference_type;
211
      typedef std::forward_iterator_tag                iterator_category;
212
 
213
      node_const_iterator()
214
      : node_iterator_base(0) { }
215
 
216
      explicit
217
      node_const_iterator(hash_node* p)
218
      : node_iterator_base(p) { }
219
 
220
      node_const_iterator(const node_iterator
221
                          cache>& x)
222
      : node_iterator_base(x.m_cur) { }
223
 
224
      reference
225
      operator*() const
226
      { return this->m_cur->m_v; }
227
 
228
      pointer
229
      operator->() const
230
      { return &this->m_cur->m_v; }
231
 
232
      node_const_iterator&
233
      operator++()
234
      {
235
        this->incr();
236
        return *this;
237
      }
238
 
239
      node_const_iterator
240
      operator++(int)
241
      {
242
        node_const_iterator tmp(*this);
243
        this->incr();
244
        return tmp;
245
      }
246
    };
247
 
248
  template
249
    struct hashtable_iterator_base
250
    {
251
      hashtable_iterator_base(hash_node* node,
252
                              hash_node** bucket)
253
      : m_cur_node(node), m_cur_bucket(bucket) { }
254
 
255
      void
256
      incr()
257
      {
258
        m_cur_node = m_cur_node->m_next;
259
        if (!m_cur_node)
260
          m_incr_bucket();
261
      }
262
 
263
      void
264
      m_incr_bucket();
265
 
266
      hash_node* m_cur_node;
267
      hash_node** m_cur_bucket;
268
    };
269
 
270
  // Global iterators, used for arbitrary iteration within a hash
271
  // table.  Larger and more expensive than local iterators.
272
  template
273
    void
274
    hashtable_iterator_base::
275
    m_incr_bucket()
276
    {
277
      ++m_cur_bucket;
278
 
279
      // This loop requires the bucket array to have a non-null sentinel.
280
      while (!*m_cur_bucket)
281
        ++m_cur_bucket;
282
      m_cur_node = *m_cur_bucket;
283
    }
284
 
285
  template
286
    inline bool
287
    operator==(const hashtable_iterator_base& x,
288
               const hashtable_iterator_base& y)
289
    { return x.m_cur_node == y.m_cur_node; }
290
 
291
  template
292
    inline bool
293
    operator!=(const hashtable_iterator_base& x,
294
               const hashtable_iterator_base& y)
295
    { return x.m_cur_node != y.m_cur_node; }
296
 
297
  template
298
    struct hashtable_iterator
299
    : public hashtable_iterator_base
300
    {
301
      typedef Value                                    value_type;
302
      typedef typename IF::type
303
                                                       pointer;
304
      typedef typename IF::type
305
                                                       reference;
306
      typedef std::ptrdiff_t                           difference_type;
307
      typedef std::forward_iterator_tag                iterator_category;
308
 
309
      hashtable_iterator()
310
      : hashtable_iterator_base(0, 0) { }
311
 
312
      hashtable_iterator(hash_node* p,
313
                         hash_node** b)
314
      : hashtable_iterator_base(p, b) { }
315
 
316
      explicit
317
      hashtable_iterator(hash_node** b)
318
      : hashtable_iterator_base(*b, b) { }
319
 
320
      reference
321
      operator*() const
322
      { return this->m_cur_node->m_v; }
323
 
324
      pointer
325
      operator->() const
326
      { return &this->m_cur_node->m_v; }
327
 
328
      hashtable_iterator&
329
      operator++()
330
      {
331
        this->incr();
332
        return *this;
333
      }
334
 
335
      hashtable_iterator
336
      operator++(int)
337
      {
338
        hashtable_iterator tmp(*this);
339
        this->incr();
340
        return tmp;
341
      }
342
    };
343
 
344
  template
345
    struct hashtable_const_iterator
346
    : public hashtable_iterator_base
347
    {
348
      typedef Value                                    value_type;
349
      typedef const Value*                             pointer;
350
      typedef const Value&                             reference;
351
      typedef std::ptrdiff_t                           difference_type;
352
      typedef std::forward_iterator_tag                iterator_category;
353
 
354
      hashtable_const_iterator()
355
      : hashtable_iterator_base(0, 0) { }
356
 
357
      hashtable_const_iterator(hash_node* p,
358
                               hash_node** b)
359
      : hashtable_iterator_base(p, b) { }
360
 
361
      explicit
362
      hashtable_const_iterator(hash_node** b)
363
      : hashtable_iterator_base(*b, b) { }
364
 
365
      hashtable_const_iterator(const hashtable_iterator
366
                               constant_iterators, cache>& x)
367
      : hashtable_iterator_base(x.m_cur_node, x.m_cur_bucket) { }
368
 
369
      reference
370
      operator*() const
371
      { return this->m_cur_node->m_v; }
372
 
373
      pointer
374
      operator->() const
375
      { return &this->m_cur_node->m_v; }
376
 
377
      hashtable_const_iterator&
378
      operator++()
379
      {
380
        this->incr();
381
        return *this;
382
      }
383
 
384
      hashtable_const_iterator
385
      operator++(int)
386
      {
387
        hashtable_const_iterator tmp(*this);
388
        this->incr();
389
        return tmp;
390
      }
391
    };
392
} // namespace Internal
393
 
394
// ----------------------------------------------------------------------
395
// Many of class template hashtable's template parameters are policy
396
// classes.  These are defaults for the policies.
397
 
398
namespace Internal
399
{
400
  // The two key extraction policies used by the *set and *map variants.
401
  template
402
    struct identity
403
    {
404
      const T&
405
      operator()(const T& t) const
406
      { return t; }
407
    };
408
 
409
  template
410
    struct extract1st
411
    {
412
      const typename Pair::first_type&
413
      operator()(const Pair& p) const
414
      { return p.first; }
415
    };
416
 
417
  // Default range hashing function: use division to fold a large number
418
  // into the range [0, N).
419
  struct mod_range_hashing
420
  {
421
    typedef std::size_t first_argument_type;
422
    typedef std::size_t second_argument_type;
423
    typedef std::size_t result_type;
424
 
425
    result_type
426
    operator() (first_argument_type r, second_argument_type N) const
427
    { return r % N; }
428
  };
429
 
430
  // Default ranged hash function H.  In principle it should be a
431
  // function object composed from objects of type H1 and H2 such that
432
  // h(k, N) = h2(h1(k), N), but that would mean making extra copies of
433
  // h1 and h2.  So instead we'll just use a tag to tell class template
434
  // hashtable to do that composition.
435
  struct default_ranged_hash { };
436
 
437
  // Default value for rehash policy.  Bucket size is (usually) the
438
  // smallest prime that keeps the load factor small enough.
439
  struct prime_rehash_policy
440
  {
441
    prime_rehash_policy(float z = 1.0);
442
 
443
    float
444
    max_load_factor() const;
445
 
446
    // Return a bucket size no smaller than n.
447
    std::size_t
448
    next_bkt(std::size_t n) const;
449
 
450
    // Return a bucket count appropriate for n elements
451
    std::size_t
452
    bkt_for_elements(std::size_t n) const;
453
 
454
    // n_bkt is current bucket count, n_elt is current element count,
455
    // and n_ins is number of elements to be inserted.  Do we need to
456
    // increase bucket count?  If so, return make_pair(true, n), where n
457
    // is the new bucket count.  If not, return make_pair(false, 0).
458
    std::pair
459
    need_rehash(std::size_t n_bkt, std::size_t n_elt, std::size_t n_ins) const;
460
 
461
    float m_max_load_factor;
462
    float m_growth_factor;
463
    mutable std::size_t m_next_resize;
464
  };
465
 
466
  // XXX This is a hack.  prime_rehash_policy's member functions, and
467
  // certainly the list of primes, should be defined in a .cc file.
468
  // We're temporarily putting them in a header because we don't have a
469
  // place to put TR1 .cc files yet.  There's no good reason for any of
470
  // prime_rehash_policy's member functions to be inline, and there's
471
  // certainly no good reason for X<> to exist at all.
472
 
473
  struct lt
474
  {
475
    template
476
      bool
477
      operator()(X x, Y y)
478
      { return x < y; }
479
  };
480
 
481
  template
482
    struct X
483
    {
484
      static const int n_primes = ulongsize != 8 ? 256 : 256 + 48;
485
      static const unsigned long primes[256 + 48 + 1];
486
    };
487
 
488
  template
489
    const int X::n_primes;
490
 
491
  template
492
    const unsigned long X::primes[256 + 48 + 1] =
493
    {
494
      2ul, 3ul, 5ul, 7ul, 11ul, 13ul, 17ul, 19ul, 23ul, 29ul, 31ul,
495
      37ul, 41ul, 43ul, 47ul, 53ul, 59ul, 61ul, 67ul, 71ul, 73ul, 79ul,
496
      83ul, 89ul, 97ul, 103ul, 109ul, 113ul, 127ul, 137ul, 139ul, 149ul,
497
      157ul, 167ul, 179ul, 193ul, 199ul, 211ul, 227ul, 241ul, 257ul,
498
      277ul, 293ul, 313ul, 337ul, 359ul, 383ul, 409ul, 439ul, 467ul,
499
      503ul, 541ul, 577ul, 619ul, 661ul, 709ul, 761ul, 823ul, 887ul,
500
      953ul, 1031ul, 1109ul, 1193ul, 1289ul, 1381ul, 1493ul, 1613ul,
501
      1741ul, 1879ul, 2029ul, 2179ul, 2357ul, 2549ul, 2753ul, 2971ul,
502
      3209ul, 3469ul, 3739ul, 4027ul, 4349ul, 4703ul, 5087ul, 5503ul,
503
      5953ul, 6427ul, 6949ul, 7517ul, 8123ul, 8783ul, 9497ul, 10273ul,
504
      11113ul, 12011ul, 12983ul, 14033ul, 15173ul, 16411ul, 17749ul,
505
      19183ul, 20753ul, 22447ul, 24281ul, 26267ul, 28411ul, 30727ul,
506
      33223ul, 35933ul, 38873ul, 42043ul, 45481ul, 49201ul, 53201ul,
507
      57557ul, 62233ul, 67307ul, 72817ul, 78779ul, 85229ul, 92203ul,
508
      99733ul, 107897ul, 116731ul, 126271ul, 136607ul, 147793ul,
509
      159871ul, 172933ul, 187091ul, 202409ul, 218971ul, 236897ul,
510
      256279ul, 277261ul, 299951ul, 324503ul, 351061ul, 379787ul,
511
      410857ul, 444487ul, 480881ul, 520241ul, 562841ul, 608903ul,
512
      658753ul, 712697ul, 771049ul, 834181ul, 902483ul, 976369ul,
513
      1056323ul, 1142821ul, 1236397ul, 1337629ul, 1447153ul, 1565659ul,
514
      1693859ul, 1832561ul, 1982627ul, 2144977ul, 2320627ul, 2510653ul,
515
      2716249ul, 2938679ul, 3179303ul, 3439651ul, 3721303ul, 4026031ul,
516
      4355707ul, 4712381ul, 5098259ul, 5515729ul, 5967347ul, 6456007ul,
517
      6984629ul, 7556579ul, 8175383ul, 8844859ul, 9569143ul, 10352717ul,
518
      11200489ul, 12117689ul, 13109983ul, 14183539ul, 15345007ul,
519
      16601593ul, 17961079ul, 19431899ul, 21023161ul, 22744717ul,
520
      24607243ul, 26622317ul, 28802401ul, 31160981ul, 33712729ul,
521
      36473443ul, 39460231ul, 42691603ul, 46187573ul, 49969847ul,
522
      54061849ul, 58488943ul, 63278561ul, 68460391ul, 74066549ul,
523
      80131819ul, 86693767ul, 93793069ul, 101473717ul, 109783337ul,
524
      118773397ul, 128499677ul, 139022417ul, 150406843ul, 162723577ul,
525
      176048909ul, 190465427ul, 206062531ul, 222936881ul, 241193053ul,
526
      260944219ul, 282312799ul, 305431229ul, 330442829ul, 357502601ul,
527
      386778277ul, 418451333ul, 452718089ul, 489790921ul, 529899637ul,
528
      573292817ul, 620239453ul, 671030513ul, 725980837ul, 785430967ul,
529
      849749479ul, 919334987ul, 994618837ul, 1076067617ul, 1164186217ul,
530
      1259520799ul, 1362662261ul, 1474249943ul, 1594975441ul,
531
      1725587117ul, 1866894511ul, 2019773507ul, 2185171673ul,
532
      2364114217ul, 2557710269ul, 2767159799ul, 2993761039ul,
533
      3238918481ul, 3504151727ul, 3791104843ul, 4101556399ul,
534
      4294967291ul,
535
      // Sentinel, so we don't have to test the result of lower_bound,
536
      // or, on 64-bit machines, rest of the table.
537
      ulongsize != 8 ? 4294967291ul : (unsigned long)6442450933ull,
538
      (unsigned long)8589934583ull,
539
      (unsigned long)12884901857ull, (unsigned long)17179869143ull,
540
      (unsigned long)25769803693ull, (unsigned long)34359738337ull,
541
      (unsigned long)51539607367ull, (unsigned long)68719476731ull,
542
      (unsigned long)103079215087ull, (unsigned long)137438953447ull,
543
      (unsigned long)206158430123ull, (unsigned long)274877906899ull,
544
      (unsigned long)412316860387ull, (unsigned long)549755813881ull,
545
      (unsigned long)824633720731ull, (unsigned long)1099511627689ull,
546
      (unsigned long)1649267441579ull, (unsigned long)2199023255531ull,
547
      (unsigned long)3298534883309ull, (unsigned long)4398046511093ull,
548
      (unsigned long)6597069766607ull, (unsigned long)8796093022151ull,
549
      (unsigned long)13194139533241ull, (unsigned long)17592186044399ull,
550
      (unsigned long)26388279066581ull, (unsigned long)35184372088777ull,
551
      (unsigned long)52776558133177ull, (unsigned long)70368744177643ull,
552
      (unsigned long)105553116266399ull, (unsigned long)140737488355213ull,
553
      (unsigned long)211106232532861ull, (unsigned long)281474976710597ull,
554
      (unsigned long)562949953421231ull, (unsigned long)1125899906842597ull,
555
      (unsigned long)2251799813685119ull, (unsigned long)4503599627370449ull,
556
      (unsigned long)9007199254740881ull, (unsigned long)18014398509481951ull,
557
      (unsigned long)36028797018963913ull, (unsigned long)72057594037927931ull,
558
      (unsigned long)144115188075855859ull,
559
      (unsigned long)288230376151711717ull,
560
      (unsigned long)576460752303423433ull,
561
      (unsigned long)1152921504606846883ull,
562
      (unsigned long)2305843009213693951ull,
563
      (unsigned long)4611686018427387847ull,
564
      (unsigned long)9223372036854775783ull,
565
      (unsigned long)18446744073709551557ull,
566
      (unsigned long)18446744073709551557ull
567
    };
568
 
569
  inline
570
  prime_rehash_policy::
571
  prime_rehash_policy(float z)
572
  : m_max_load_factor(z), m_growth_factor(2.f), m_next_resize(0)
573
  { }
574
 
575
  inline float
576
  prime_rehash_policy::
577
  max_load_factor() const
578
  { return m_max_load_factor; }
579
 
580
  // Return a prime no smaller than n.
581
  inline std::size_t
582
  prime_rehash_policy::
583
  next_bkt(std::size_t n) const
584
  {
585
    const unsigned long* const last = X<>::primes + X<>::n_primes;
586
    const unsigned long* p = std::lower_bound (X<>::primes, last, n);
587
    m_next_resize = static_cast(std::ceil(*p * m_max_load_factor));
588
    return *p;
589
  }
590
 
591
  // Return the smallest prime p such that alpha p >= n, where alpha
592
  // is the load factor.
593
  inline std::size_t
594
  prime_rehash_policy::
595
  bkt_for_elements(std::size_t n) const
596
  {
597
    const unsigned long* const last = X<>::primes + X<>::n_primes;
598
    const float min_bkts = n / m_max_load_factor;
599
    const unsigned long* p = std::lower_bound (X<>::primes, last,
600
                                               min_bkts, lt());
601
    m_next_resize = static_cast(std::ceil(*p * m_max_load_factor));
602
    return *p;
603
  }
604
 
605
  // Finds the smallest prime p such that alpha p > n_elt + n_ins.
606
  // If p > n_bkt, return make_pair(true, p); otherwise return
607
  // make_pair(false, 0).  In principle this isn't very different from
608
  // bkt_for_elements.
609
 
610
  // The only tricky part is that we're caching the element count at
611
  // which we need to rehash, so we don't have to do a floating-point
612
  // multiply for every insertion.
613
 
614
  inline std::pair
615
  prime_rehash_policy::
616
  need_rehash(std::size_t n_bkt, std::size_t n_elt, std::size_t n_ins) const
617
  {
618
    if (n_elt + n_ins > m_next_resize)
619
      {
620
        float min_bkts = (float(n_ins) + float(n_elt)) / m_max_load_factor;
621
        if (min_bkts > n_bkt)
622
          {
623
            min_bkts = std::max (min_bkts, m_growth_factor * n_bkt);
624
            const unsigned long* const last = X<>::primes + X<>::n_primes;
625
            const unsigned long* p = std::lower_bound (X<>::primes, last,
626
                                                       min_bkts, lt());
627
            m_next_resize =
628
              static_cast(std::ceil(*p * m_max_load_factor));
629
            return std::make_pair(true, *p);
630
          }
631
        else
632
          {
633
            m_next_resize =
634
              static_cast(std::ceil(n_bkt * m_max_load_factor));
635
            return std::make_pair(false, 0);
636
          }
637
      }
638
    else
639
      return std::make_pair(false, 0);
640
  }
641
 
642
} // namespace Internal
643
 
644
//----------------------------------------------------------------------
645
// Base classes for std::tr1::hashtable.  We define these base classes
646
// because in some cases we want to do different things depending on
647
// the value of a policy class.  In some cases the policy class affects
648
// which member functions and nested typedefs are defined; we handle that
649
// by specializing base class templates.  Several of the base class templates
650
// need to access other members of class template hashtable, so we use
651
// the "curiously recurring template pattern" for them.
652
 
653
namespace Internal
654
{
655
  // class template map_base.  If the hashtable has a value type of the
656
  // form pair and a key extraction policy that returns the
657
  // first part of the pair, the hashtable gets a mapped_type typedef.
658
  // If it satisfies those criteria and also has unique keys, then it
659
  // also gets an operator[].
660
 
661
  template
662
    struct map_base { };
663
 
664
  template
665
    struct map_base, false, Hashtable>
666
    {
667
      typedef typename Pair::second_type mapped_type;
668
    };
669
 
670
  template
671
    struct map_base, true, Hashtable>
672
    {
673
      typedef typename Pair::second_type mapped_type;
674
 
675
      mapped_type&
676
      operator[](const K& k)
677
      {
678
        Hashtable* h = static_cast(this);
679
        typename Hashtable::iterator it =
680
          h->insert(std::make_pair(k, mapped_type())).first;
681
        return it->second;
682
      }
683
    };
684
 
685
  // class template rehash_base.  Give hashtable the max_load_factor
686
  // functions iff the rehash policy is prime_rehash_policy.
687
  template
688
    struct rehash_base { };
689
 
690
  template
691
    struct rehash_base
692
    {
693
      float
694
      max_load_factor() const
695
      {
696
        const Hashtable* This = static_cast(this);
697
        return This->rehash_policy().max_load_factor();
698
      }
699
 
700
      void
701
      max_load_factor(float z)
702
      {
703
        Hashtable* This = static_cast(this);
704
        This->rehash_policy(prime_rehash_policy(z));
705
      }
706
    };
707
 
708
  // Class template hash_code_base.  Encapsulates two policy issues that
709
  // aren't quite orthogonal.
710
  //   (1) the difference between using a ranged hash function and using
711
  //       the combination of a hash function and a range-hashing function.
712
  //       In the former case we don't have such things as hash codes, so
713
  //       we have a dummy type as placeholder.
714
  //   (2) Whether or not we cache hash codes.  Caching hash codes is
715
  //       meaningless if we have a ranged hash function.
716
  // We also put the key extraction and equality comparison function
717
  // objects here, for convenience.
718
 
719
  // Primary template: unused except as a hook for specializations.
720
 
721
  template
722
           typename ExtractKey, typename Equal,
723
           typename H1, typename H2, typename H,
724
           bool cache_hash_code>
725
    struct hash_code_base;
726
 
727
  // Specialization: ranged hash function, no caching hash codes.  H1
728
  // and H2 are provided but ignored.  We define a dummy hash code type.
729
  template
730
           typename ExtractKey, typename Equal,
731
           typename H1, typename H2, typename H>
732
    struct hash_code_base
733
    {
734
    protected:
735
      hash_code_base(const ExtractKey& ex, const Equal& eq,
736
                     const H1&, const H2&, const H& h)
737
      : m_extract(ex), m_eq(eq), m_ranged_hash(h) { }
738
 
739
      typedef void* hash_code_t;
740
 
741
      hash_code_t
742
      m_hash_code(const Key& k) const
743
      { return 0; }
744
 
745
      std::size_t
746
      bucket_index(const Key& k, hash_code_t, std::size_t N) const
747
      { return m_ranged_hash (k, N); }
748
 
749
      std::size_t
750
      bucket_index(const hash_node* p, std::size_t N) const
751
      { return m_ranged_hash (m_extract (p->m_v), N); }
752
 
753
      bool
754
      compare(const Key& k, hash_code_t, hash_node* n) const
755
      { return m_eq (k, m_extract(n->m_v)); }
756
 
757
      void
758
      store_code(hash_node*, hash_code_t) const
759
      { }
760
 
761
      void
762
      copy_code(hash_node*, const hash_node*) const
763
      { }
764
 
765
      void
766
      m_swap(hash_code_base& x)
767
      {
768
        std::swap(m_extract, x.m_extract);
769
        std::swap(m_eq, x.m_eq);
770
        std::swap(m_ranged_hash, x.m_ranged_hash);
771
      }
772
 
773
    protected:
774
      ExtractKey m_extract;
775
      Equal m_eq;
776
      H m_ranged_hash;
777
    };
778
 
779
 
780
  // No specialization for ranged hash function while caching hash codes.
781
  // That combination is meaningless, and trying to do it is an error.
782
 
783
 
784
  // Specialization: ranged hash function, cache hash codes.  This
785
  // combination is meaningless, so we provide only a declaration
786
  // and no definition.
787
 
788
  template
789
            typename ExtractKey, typename Equal,
790
            typename H1, typename H2, typename H>
791
    struct hash_code_base;
792
 
793
 
794
  // Specialization: hash function and range-hashing function, no
795
  // caching of hash codes.  H is provided but ignored.  Provides
796
  // typedef and accessor required by TR1.
797
 
798
  template
799
           typename ExtractKey, typename Equal,
800
           typename H1, typename H2>
801
    struct hash_code_base
802
                          default_ranged_hash, false>
803
    {
804
      typedef H1 hasher;
805
 
806
      hasher
807
      hash_function() const
808
      { return m_h1; }
809
 
810
    protected:
811
      hash_code_base(const ExtractKey& ex, const Equal& eq,
812
                     const H1& h1, const H2& h2, const default_ranged_hash&)
813
      : m_extract(ex), m_eq(eq), m_h1(h1), m_h2(h2) { }
814
 
815
      typedef std::size_t hash_code_t;
816
 
817
      hash_code_t
818
      m_hash_code(const Key& k) const
819
      { return m_h1(k); }
820
 
821
      std::size_t
822
      bucket_index(const Key&, hash_code_t c, std::size_t N) const
823
      { return m_h2 (c, N); }
824
 
825
      std::size_t
826
      bucket_index(const hash_node* p, std::size_t N) const
827
      { return m_h2 (m_h1 (m_extract (p->m_v)), N); }
828
 
829
      bool
830
      compare(const Key& k, hash_code_t, hash_node* n) const
831
      { return m_eq (k, m_extract(n->m_v)); }
832
 
833
      void
834
      store_code(hash_node*, hash_code_t) const
835
      { }
836
 
837
      void
838
      copy_code(hash_node*, const hash_node*) const
839
      { }
840
 
841
      void
842
      m_swap(hash_code_base& x)
843
      {
844
        std::swap(m_extract, x.m_extract);
845
        std::swap(m_eq, x.m_eq);
846
        std::swap(m_h1, x.m_h1);
847
        std::swap(m_h2, x.m_h2);
848
      }
849
 
850
    protected:
851
      ExtractKey m_extract;
852
      Equal m_eq;
853
      H1 m_h1;
854
      H2 m_h2;
855
    };
856
 
857
  // Specialization: hash function and range-hashing function,
858
  // caching hash codes.  H is provided but ignored.  Provides
859
  // typedef and accessor required by TR1.
860
  template
861
           typename ExtractKey, typename Equal,
862
           typename H1, typename H2>
863
    struct hash_code_base
864
                          default_ranged_hash, true>
865
    {
866
      typedef H1 hasher;
867
 
868
      hasher
869
      hash_function() const
870
      { return m_h1; }
871
 
872
    protected:
873
      hash_code_base(const ExtractKey& ex, const Equal& eq,
874
                     const H1& h1, const H2& h2, const default_ranged_hash&)
875
      : m_extract(ex), m_eq(eq), m_h1(h1), m_h2(h2) { }
876
 
877
      typedef std::size_t hash_code_t;
878
 
879
      hash_code_t
880
      m_hash_code(const Key& k) const
881
      { return m_h1(k); }
882
 
883
      std::size_t
884
      bucket_index(const Key&, hash_code_t c, std::size_t N) const
885
      { return m_h2 (c, N); }
886
 
887
      std::size_t
888
      bucket_index(const hash_node* p, std::size_t N) const
889
      { return m_h2 (p->hash_code, N); }
890
 
891
      bool
892
      compare(const Key& k, hash_code_t c, hash_node* n) const
893
      { return c == n->hash_code && m_eq(k, m_extract(n->m_v)); }
894
 
895
      void
896
      store_code(hash_node* n, hash_code_t c) const
897
      { n->hash_code = c; }
898
 
899
      void
900
      copy_code(hash_node* to,
901
                const hash_node* from) const
902
      { to->hash_code = from->hash_code; }
903
 
904
      void
905
      m_swap(hash_code_base& x)
906
      {
907
        std::swap(m_extract, x.m_extract);
908
        std::swap(m_eq, x.m_eq);
909
        std::swap(m_h1, x.m_h1);
910
        std::swap(m_h2, x.m_h2);
911
      }
912
 
913
    protected:
914
      ExtractKey m_extract;
915
      Equal m_eq;
916
      H1 m_h1;
917
      H2 m_h2;
918
    };
919
 
920
} // namespace internal
921
 
922
namespace std
923
{
924
namespace tr1
925
{
926
  //----------------------------------------------------------------------
927
  // Class template hashtable, class definition.
928
 
929
  // Meaning of class template hashtable's template parameters
930
 
931
  // Key and Value: arbitrary CopyConstructible types.
932
 
933
  // Allocator: an allocator type ([lib.allocator.requirements]) whose
934
  // value type is Value.
935
 
936
  // ExtractKey: function object that takes a object of type Value
937
  // and returns a value of type Key.
938
 
939
  // Equal: function object that takes two objects of type k and returns
940
  // a bool-like value that is true if the two objects are considered equal.
941
 
942
  // H1: the hash function.  A unary function object with argument type
943
  // Key and result type size_t.  Return values should be distributed
944
  // over the entire range [0, numeric_limits:::max()].
945
 
946
  // H2: the range-hashing function (in the terminology of Tavori and
947
  // Dreizin).  A binary function object whose argument types and result
948
  // type are all size_t.  Given arguments r and N, the return value is
949
  // in the range [0, N).
950
 
951
  // H: the ranged hash function (Tavori and Dreizin). A binary function
952
  // whose argument types are Key and size_t and whose result type is
953
  // size_t.  Given arguments k and N, the return value is in the range
954
  // [0, N).  Default: h(k, N) = h2(h1(k), N).  If H is anything other
955
  // than the default, H1 and H2 are ignored.
956
 
957
  // RehashPolicy: Policy class with three members, all of which govern
958
  // the bucket count. n_bkt(n) returns a bucket count no smaller
959
  // than n.  bkt_for_elements(n) returns a bucket count appropriate
960
  // for an element count of n.  need_rehash(n_bkt, n_elt, n_ins)
961
  // determines whether, if the current bucket count is n_bkt and the
962
  // current element count is n_elt, we need to increase the bucket
963
  // count.  If so, returns make_pair(true, n), where n is the new
964
  // bucket count.  If not, returns make_pair(false, ).
965
 
966
  // ??? Right now it is hard-wired that the number of buckets never
967
  // shrinks.  Should we allow RehashPolicy to change that?
968
 
969
  // cache_hash_code: bool.  true if we store the value of the hash
970
  // function along with the value.  This is a time-space tradeoff.
971
  // Storing it may improve lookup speed by reducing the number of times
972
  // we need to call the Equal function.
973
 
974
  // constant_iterators: bool.  true if iterator and const_iterator are
975
  // both constant iterator types.  This is true for unordered_set and
976
  // unordered_multiset, false for unordered_map and unordered_multimap.
977
 
978
  // unique_keys: bool.  true if the return value of hashtable::count(k)
979
  // is always at most one, false if it may be an arbitrary number.  This
980
  // true for unordered_set and unordered_map, false for unordered_multiset
981
  // and unordered_multimap.
982
 
983
  template
984
           typename Allocator,
985
           typename ExtractKey, typename Equal,
986
           typename H1, typename H2,
987
           typename H, typename RehashPolicy,
988
           bool cache_hash_code,
989
           bool constant_iterators,
990
           bool unique_keys>
991
    class hashtable
992
    : public Internal::rehash_base
993
                                   hashtable
994
                                             Equal, H1, H2, H, RehashPolicy,
995
                                             cache_hash_code, constant_iterators,
996
                                             unique_keys> >,
997
      public Internal::hash_code_base
998
                                      cache_hash_code>,
999
      public Internal::map_base
1000
                                hashtable
1001
                                          Equal, H1, H2, H, RehashPolicy,
1002
                                          cache_hash_code, constant_iterators,
1003
                                          unique_keys> >
1004
    {
1005
    public:
1006
      typedef Allocator                                      allocator_type;
1007
      typedef Value                                          value_type;
1008
      typedef Key                                            key_type;
1009
      typedef Equal                                          key_equal;
1010
      // mapped_type, if present, comes from map_base.
1011
      // hasher, if present, comes from hash_code_base.
1012
      typedef typename Allocator::difference_type            difference_type;
1013
      typedef typename Allocator::size_type                  size_type;
1014
      typedef typename Allocator::reference                  reference;
1015
      typedef typename Allocator::const_reference            const_reference;
1016
 
1017
      typedef Internal::node_iterator
1018
                                      cache_hash_code>
1019
        local_iterator;
1020
      typedef Internal::node_const_iterator
1021
                                            cache_hash_code>
1022
        const_local_iterator;
1023
 
1024
      typedef Internal::hashtable_iterator
1025
                                           cache_hash_code>
1026
        iterator;
1027
      typedef Internal::hashtable_const_iterator
1028
                                                 cache_hash_code>
1029
        const_iterator;
1030
 
1031
    private:
1032
      typedef Internal::hash_node    node;
1033
      typedef typename Allocator::template rebind::other
1034
        node_allocator_t;
1035
      typedef typename Allocator::template rebind::other
1036
        bucket_allocator_t;
1037
 
1038
    private:
1039
      node_allocator_t m_node_allocator;
1040
      node** m_buckets;
1041
      size_type m_bucket_count;
1042
      size_type m_element_count;
1043
      RehashPolicy m_rehash_policy;
1044
 
1045
      node*
1046
      m_allocate_node(const value_type& v);
1047
 
1048
      void
1049
      m_deallocate_node(node* n);
1050
 
1051
      void
1052
      m_deallocate_nodes(node**, size_type);
1053
 
1054
      node**
1055
      m_allocate_buckets(size_type n);
1056
 
1057
      void
1058
      m_deallocate_buckets(node**, size_type n);
1059
 
1060
    public:                         // Constructor, destructor, assignment, swap
1061
      hashtable(size_type bucket_hint,
1062
                const H1&, const H2&, const H&,
1063
                const Equal&, const ExtractKey&,
1064
                const allocator_type&);
1065
 
1066
      template
1067
        hashtable(InIter first, InIter last,
1068
                  size_type bucket_hint,
1069
                  const H1&, const H2&, const H&,
1070
                  const Equal&, const ExtractKey&,
1071
                  const allocator_type&);
1072
 
1073
      hashtable(const hashtable&);
1074
 
1075
      hashtable&
1076
      operator=(const hashtable&);
1077
 
1078
      ~hashtable();
1079
 
1080
      void swap(hashtable&);
1081
 
1082
    public:                             // Basic container operations
1083
      iterator
1084
      begin()
1085
      {
1086
        iterator i(m_buckets);
1087
        if (!i.m_cur_node)
1088
          i.m_incr_bucket();
1089
        return i;
1090
      }
1091
 
1092
      const_iterator
1093
      begin() const
1094
      {
1095
        const_iterator i(m_buckets);
1096
        if (!i.m_cur_node)
1097
          i.m_incr_bucket();
1098
        return i;
1099
      }
1100
 
1101
      iterator
1102
      end()
1103
      { return iterator(m_buckets + m_bucket_count); }
1104
 
1105
      const_iterator
1106
      end() const
1107
      { return const_iterator(m_buckets + m_bucket_count); }
1108
 
1109
      size_type
1110
      size() const
1111
      { return m_element_count; }
1112
 
1113
      bool
1114
      empty() const
1115
      { return size() == 0; }
1116
 
1117
      allocator_type
1118
      get_allocator() const
1119
      { return m_node_allocator; }
1120
 
1121
      size_type
1122
      max_size() const
1123
      { return m_node_allocator.max_size(); }
1124
 
1125
    public:                             // Observers
1126
      key_equal
1127
      key_eq() const
1128
      { return this->m_eq; }
1129
 
1130
      // hash_function, if present, comes from hash_code_base.
1131
 
1132
    public:                             // Bucket operations
1133
      size_type
1134
      bucket_count() const
1135
      { return m_bucket_count; }
1136
 
1137
      size_type
1138
      max_bucket_count() const
1139
      { return max_size(); }
1140
 
1141
      size_type
1142
      bucket_size(size_type n) const
1143
      { return std::distance(begin(n), end(n)); }
1144
 
1145
      size_type
1146
      bucket(const key_type& k) const
1147
      {
1148
        return this->bucket_index(k, this->m_hash_code(k),
1149
                                  this->m_bucket_count);
1150
      }
1151
 
1152
      local_iterator
1153
      begin(size_type n)
1154
      { return local_iterator(m_buckets[n]); }
1155
 
1156
      local_iterator
1157
      end(size_type)
1158
      { return local_iterator(0); }
1159
 
1160
      const_local_iterator
1161
      begin(size_type n) const
1162
      { return const_local_iterator(m_buckets[n]); }
1163
 
1164
      const_local_iterator
1165
      end(size_type) const
1166
      { return const_local_iterator(0); }
1167
 
1168
      float
1169
      load_factor() const
1170
      {
1171
        return static_cast(size()) / static_cast(bucket_count());
1172
      }
1173
      // max_load_factor, if present, comes from rehash_base.
1174
 
1175
      // Generalization of max_load_factor.  Extension, not found in TR1.  Only
1176
      // useful if RehashPolicy is something other than the default.
1177
      const RehashPolicy&
1178
      rehash_policy() const
1179
      { return m_rehash_policy; }
1180
 
1181
      void
1182
      rehash_policy(const RehashPolicy&);
1183
 
1184
    public:                             // lookup
1185
      iterator
1186
      find(const key_type&);
1187
 
1188
      const_iterator
1189
      find(const key_type& k) const;
1190
 
1191
      size_type
1192
      count(const key_type& k) const;
1193
 
1194
      std::pair
1195
      equal_range(const key_type& k);
1196
 
1197
      std::pair
1198
      equal_range(const key_type& k) const;
1199
 
1200
    private:                    // Insert and erase helper functions
1201
      // ??? This dispatching is a workaround for the fact that we don't
1202
      // have partial specialization of member templates; it would be
1203
      // better to just specialize insert on unique_keys.  There may be a
1204
      // cleaner workaround.
1205
      typedef typename Internal::IF
1206
                                    std::pair, iterator>::type
1207
        Insert_Return_Type;
1208
 
1209
      typedef typename Internal::IF
1210
                                    Internal::extract1st,
1211
                                    Internal::identity
1212
                                   >::type
1213
        Insert_Conv_Type;
1214
 
1215
      node*
1216
      find_node(node* p, const key_type& k,
1217
                typename hashtable::hash_code_t c) const;
1218
 
1219
      std::pair
1220
      insert(const value_type&, std::tr1::true_type);
1221
 
1222
      iterator
1223
      insert(const value_type&, std::tr1::false_type);
1224
 
1225
      void
1226
      erase_node(node*, node**);
1227
 
1228
    public:                             // Insert and erase
1229
      Insert_Return_Type
1230
      insert(const value_type& v)
1231
      {
1232
        return this->insert(v, std::tr1::integral_constant
1233
                            unique_keys>());
1234
      }
1235
 
1236
      iterator
1237
      insert(iterator, const value_type& v)
1238
      { return iterator(Insert_Conv_Type()(this->insert(v))); }
1239
 
1240
      const_iterator
1241
      insert(const_iterator, const value_type& v)
1242
      { return const_iterator(Insert_Conv_Type()(this->insert(v))); }
1243
 
1244
      template
1245
        void
1246
        insert(InIter first, InIter last);
1247
 
1248
      iterator
1249
      erase(iterator);
1250
 
1251
      const_iterator
1252
      erase(const_iterator);
1253
 
1254
      size_type
1255
      erase(const key_type&);
1256
 
1257
      iterator
1258
      erase(iterator, iterator);
1259
 
1260
      const_iterator
1261
      erase(const_iterator, const_iterator);
1262
 
1263
      void
1264
      clear();
1265
 
1266
    public:
1267
      // Set number of buckets to be appropriate for container of n element.
1268
      void rehash(size_type n);
1269
 
1270
    private:
1271
      // Unconditionally change size of bucket array to n.
1272
      void m_rehash(size_type n);
1273
    };
1274
 
1275
  //----------------------------------------------------------------------
1276
  // Definitions of class template hashtable's out-of-line member functions.
1277
 
1278
  template
1279
           typename A, typename Ex, typename Eq,
1280
           typename H1, typename H2, typename H, typename RP,
1281
           bool c, bool ci, bool u>
1282
    typename hashtable::node*
1283
    hashtable::
1284
    m_allocate_node(const value_type& v)
1285
    {
1286
      node* n = m_node_allocator.allocate(1);
1287
      try
1288
        {
1289
          get_allocator().construct(&n->m_v, v);
1290
          n->m_next = 0;
1291
          return n;
1292
        }
1293
      catch(...)
1294
        {
1295
          m_node_allocator.deallocate(n, 1);
1296
          __throw_exception_again;
1297
        }
1298
    }
1299
 
1300
  template
1301
           typename A, typename Ex, typename Eq,
1302
           typename H1, typename H2, typename H, typename RP,
1303
           bool c, bool ci, bool u>
1304
    void
1305
    hashtable::
1306
    m_deallocate_node(node* n)
1307
    {
1308
      get_allocator().destroy(&n->m_v);
1309
      m_node_allocator.deallocate(n, 1);
1310
    }
1311
 
1312
  template
1313
           typename A, typename Ex, typename Eq,
1314
           typename H1, typename H2, typename H, typename RP,
1315
           bool c, bool ci, bool u>
1316
    void
1317
    hashtable::
1318
    m_deallocate_nodes(node** array, size_type n)
1319
    {
1320
      for (size_type i = 0; i < n; ++i)
1321
        {
1322
          node* p = array[i];
1323
          while (p)
1324
            {
1325
              node* tmp = p;
1326
              p = p->m_next;
1327
              m_deallocate_node (tmp);
1328
            }
1329
          array[i] = 0;
1330
        }
1331
    }
1332
 
1333
  template
1334
           typename A, typename Ex, typename Eq,
1335
           typename H1, typename H2, typename H, typename RP,
1336
           bool c, bool ci, bool u>
1337
    typename hashtable::node**
1338
    hashtable::
1339
    m_allocate_buckets(size_type n)
1340
    {
1341
      bucket_allocator_t alloc(m_node_allocator);
1342
 
1343
      // We allocate one extra bucket to hold a sentinel, an arbitrary
1344
      // non-null pointer.  Iterator increment relies on this.
1345
      node** p = alloc.allocate(n+1);
1346
      std::fill(p, p+n, (node*) 0);
1347
      p[n] = reinterpret_cast(0x1000);
1348
      return p;
1349
    }
1350
 
1351
  template
1352
           typename A, typename Ex, typename Eq,
1353
           typename H1, typename H2, typename H, typename RP,
1354
           bool c, bool ci, bool u>
1355
    void
1356
    hashtable::
1357
    m_deallocate_buckets(node** p, size_type n)
1358
    {
1359
      bucket_allocator_t alloc(m_node_allocator);
1360
      alloc.deallocate(p, n+1);
1361
    }
1362
 
1363
  template
1364
           typename A, typename Ex, typename Eq,
1365
           typename H1, typename H2, typename H, typename RP,
1366
           bool c, bool ci, bool u>
1367
    hashtable::
1368
    hashtable(size_type bucket_hint,
1369
              const H1& h1, const H2& h2, const H& h,
1370
              const Eq& eq, const Ex& exk,
1371
              const allocator_type& a)
1372
    : Internal::rehash_base(),
1373
      Internal::hash_code_base(exk, eq, h1, h2, h),
1374
      Internal::map_base(),
1375
      m_node_allocator(a),
1376
      m_bucket_count(0),
1377
      m_element_count(0),
1378
      m_rehash_policy()
1379
    {
1380
      m_bucket_count = m_rehash_policy.next_bkt(bucket_hint);
1381
      m_buckets = m_allocate_buckets(m_bucket_count);
1382
    }
1383
 
1384
  template
1385
           typename A, typename Ex, typename Eq,
1386
           typename H1, typename H2, typename H, typename RP,
1387
           bool c, bool ci, bool u>
1388
    template
1389
      hashtable::
1390
      hashtable(InIter f, InIter l,
1391
                size_type bucket_hint,
1392
                const H1& h1, const H2& h2, const H& h,
1393
                const Eq& eq, const Ex& exk,
1394
                const allocator_type& a)
1395
      : Internal::rehash_base(),
1396
        Internal::hash_code_base (exk, eq,
1397
                                                              h1, h2, h),
1398
        Internal::map_base(),
1399
        m_node_allocator(a),
1400
        m_bucket_count (0),
1401
        m_element_count(0),
1402
        m_rehash_policy()
1403
      {
1404
        m_bucket_count = std::max(m_rehash_policy.next_bkt(bucket_hint),
1405
                                  m_rehash_policy.
1406
                                  bkt_for_elements(Internal::
1407
                                                   distance_fw(f, l)));
1408
        m_buckets = m_allocate_buckets(m_bucket_count);
1409
        try
1410
          {
1411
            for (; f != l; ++f)
1412
              this->insert(*f);
1413
          }
1414
        catch(...)
1415
          {
1416
            clear();
1417
            m_deallocate_buckets(m_buckets, m_bucket_count);
1418
            __throw_exception_again;
1419
          }
1420
      }
1421
 
1422
  template
1423
           typename A, typename Ex, typename Eq,
1424
           typename H1, typename H2, typename H, typename RP,
1425
           bool c, bool ci, bool u>
1426
    hashtable::
1427
    hashtable(const hashtable& ht)
1428
    : Internal::rehash_base(ht),
1429
      Internal::hash_code_base(ht),
1430
      Internal::map_base(ht),
1431
      m_node_allocator(ht.get_allocator()),
1432
      m_bucket_count(ht.m_bucket_count),
1433
      m_element_count(ht.m_element_count),
1434
      m_rehash_policy(ht.m_rehash_policy)
1435
    {
1436
      m_buckets = m_allocate_buckets (m_bucket_count);
1437
      try
1438
        {
1439
          for (size_t i = 0; i < ht.m_bucket_count; ++i)
1440
            {
1441
              node* n = ht.m_buckets[i];
1442
              node** tail = m_buckets + i;
1443
              while (n)
1444
                {
1445
                  *tail = m_allocate_node(n->m_v);
1446
                  this->copy_code(*tail, n);
1447
                  tail = &((*tail)->m_next);
1448
                  n = n->m_next;
1449
                }
1450
            }
1451
        }
1452
      catch (...)
1453
        {
1454
          clear();
1455
          m_deallocate_buckets (m_buckets, m_bucket_count);
1456
          __throw_exception_again;
1457
        }
1458
    }
1459
 
1460
  template
1461
           typename A, typename Ex, typename Eq,
1462
           typename H1, typename H2, typename H, typename RP,
1463
           bool c, bool ci, bool u>
1464
    hashtable&
1465
    hashtable::
1466
    operator=(const hashtable& ht)
1467
    {
1468
      hashtable tmp(ht);
1469
      this->swap(tmp);
1470
      return *this;
1471
    }
1472
 
1473
  template
1474
           typename A, typename Ex, typename Eq,
1475
           typename H1, typename H2, typename H, typename RP,
1476
           bool c, bool ci, bool u>
1477
    hashtable::
1478
    ~hashtable()
1479
    {
1480
      clear();
1481
      m_deallocate_buckets(m_buckets, m_bucket_count);
1482
    }
1483
 
1484
  template
1485
           typename A, typename Ex, typename Eq,
1486
           typename H1, typename H2, typename H, typename RP,
1487
           bool c, bool ci, bool u>
1488
    void
1489
    hashtable::
1490
    swap(hashtable& x)
1491
    {
1492
      // The only base class with member variables is hash_code_base.  We
1493
      // define hash_code_base::m_swap because different specializations
1494
      // have different members.
1495
      Internal::hash_code_base::m_swap(x);
1496
 
1497
      // open LWG issue 431
1498
      // std::swap(m_node_allocator, x.m_node_allocator);
1499
      std::swap(m_rehash_policy, x.m_rehash_policy);
1500
      std::swap(m_buckets, x.m_buckets);
1501
      std::swap(m_bucket_count, x.m_bucket_count);
1502
      std::swap(m_element_count, x.m_element_count);
1503
    }
1504
 
1505
  template
1506
           typename A, typename Ex, typename Eq,
1507
           typename H1, typename H2, typename H, typename RP,
1508
           bool c, bool ci, bool u>
1509
    void
1510
    hashtable::
1511
    rehash_policy(const RP& pol)
1512
    {
1513
      m_rehash_policy = pol;
1514
      size_type n_bkt = pol.bkt_for_elements(m_element_count);
1515
      if (n_bkt > m_bucket_count)
1516
        m_rehash (n_bkt);
1517
    }
1518
 
1519
  template
1520
           typename A, typename Ex, typename Eq,
1521
           typename H1, typename H2, typename H, typename RP,
1522
           bool c, bool ci, bool u>
1523
    typename hashtable::iterator
1524
    hashtable::
1525
    find(const key_type& k)
1526
    {
1527
      typename hashtable::hash_code_t code = this->m_hash_code(k);
1528
      std::size_t n = this->bucket_index(k, code, this->bucket_count());
1529
      node* p = find_node(m_buckets[n], k, code);
1530
      return p ? iterator(p, m_buckets + n) : this->end();
1531
    }
1532
 
1533
  template
1534
           typename A, typename Ex, typename Eq,
1535
           typename H1, typename H2, typename H, typename RP,
1536
           bool c, bool ci, bool u>
1537
    typename hashtable::const_iterator
1538
    hashtable::
1539
    find(const key_type& k) const
1540
    {
1541
      typename hashtable::hash_code_t code = this->m_hash_code(k);
1542
      std::size_t n = this->bucket_index(k, code, this->bucket_count());
1543
      node* p = find_node(m_buckets[n], k, code);
1544
      return p ? const_iterator(p, m_buckets + n) : this->end();
1545
    }
1546
 
1547
  template
1548
           typename A, typename Ex, typename Eq,
1549
           typename H1, typename H2, typename H, typename RP,
1550
           bool c, bool ci, bool u>
1551
    typename hashtable::size_type
1552
    hashtable::
1553
    count(const key_type& k) const
1554
    {
1555
      typename hashtable::hash_code_t code = this->m_hash_code(k);
1556
      std::size_t n = this->bucket_index(k, code, this->bucket_count());
1557
      size_t result = 0;
1558
      for (node* p = m_buckets[n]; p ; p = p->m_next)
1559
        if (this->compare(k, code, p))
1560
          ++result;
1561
      return result;
1562
    }
1563
 
1564
  template
1565
           typename A, typename Ex, typename Eq,
1566
           typename H1, typename H2, typename H, typename RP,
1567
           bool c, bool ci, bool u>
1568
    std::pair
1569
                                 H2, H, RP, c, ci, u>::iterator,
1570
              typename hashtable
1571
                                 H2, H, RP, c, ci, u>::iterator>
1572
    hashtable::
1573
    equal_range(const key_type& k)
1574
    {
1575
      typename hashtable::hash_code_t code = this->m_hash_code(k);
1576
      std::size_t n = this->bucket_index(k, code, this->bucket_count());
1577
      node** head = m_buckets + n;
1578
      node* p = find_node (*head, k, code);
1579
 
1580
      if (p)
1581
        {
1582
          node* p1 = p->m_next;
1583
          for (; p1 ; p1 = p1->m_next)
1584
            if (!this->compare (k, code, p1))
1585
              break;
1586
 
1587
          iterator first(p, head);
1588
          iterator last(p1, head);
1589
          if (!p1)
1590
            last.m_incr_bucket();
1591
          return std::make_pair(first, last);
1592
        }
1593
      else
1594
        return std::make_pair(this->end(), this->end());
1595
    }
1596
 
1597
  template
1598
           typename A, typename Ex, typename Eq,
1599
           typename H1, typename H2, typename H, typename RP,
1600
           bool c, bool ci, bool u>
1601
    std::pair
1602
                                 H2, H, RP, c, ci, u>::const_iterator,
1603
              typename hashtable
1604
                                 H2, H, RP, c, ci, u>::const_iterator>
1605
    hashtable::
1606
    equal_range(const key_type& k) const
1607
    {
1608
      typename hashtable::hash_code_t code = this->m_hash_code(k);
1609
      std::size_t n = this->bucket_index(k, code, this->bucket_count());
1610
      node** head = m_buckets + n;
1611
      node* p = find_node(*head, k, code);
1612
 
1613
      if (p)
1614
        {
1615
          node* p1 = p->m_next;
1616
          for (; p1 ; p1 = p1->m_next)
1617
            if (!this->compare(k, code, p1))
1618
              break;
1619
 
1620
          const_iterator first(p, head);
1621
          const_iterator last(p1, head);
1622
          if (!p1)
1623
            last.m_incr_bucket();
1624
          return std::make_pair(first, last);
1625
        }
1626
      else
1627
        return std::make_pair(this->end(), this->end());
1628
    }
1629
 
1630
  // Find the node whose key compares equal to k, beginning the search
1631
  // at p (usually the head of a bucket).  Return nil if no node is found.
1632
  template
1633
           typename A, typename Ex, typename Eq,
1634
           typename H1, typename H2, typename H, typename RP,
1635
           bool c, bool ci, bool u>
1636
    typename hashtable::node*
1637
    hashtable::
1638
    find_node(node* p, const key_type& k,
1639
              typename hashtable::hash_code_t code) const
1640
    {
1641
      for ( ; p ; p = p->m_next)
1642
        if (this->compare (k, code, p))
1643
          return p;
1644
      return false;
1645
    }
1646
 
1647
  // Insert v if no element with its key is already present.
1648
  template
1649
           typename A, typename Ex, typename Eq,
1650
           typename H1, typename H2, typename H, typename RP,
1651
           bool c, bool ci, bool u>
1652
    std::pair
1653
                                 H2, H, RP, c, ci, u>::iterator, bool>
1654
    hashtable::
1655
    insert(const value_type& v, std::tr1::true_type)
1656
    {
1657
      const key_type& k = this->m_extract(v);
1658
      typename hashtable::hash_code_t code = this->m_hash_code(k);
1659
      size_type n = this->bucket_index(k, code, m_bucket_count);
1660
 
1661
      if (node* p = find_node(m_buckets[n], k, code))
1662
        return std::make_pair(iterator(p, m_buckets + n), false);
1663
 
1664
      std::pair do_rehash
1665
        = m_rehash_policy.need_rehash(m_bucket_count, m_element_count, 1);
1666
 
1667
      // Allocate the new node before doing the rehash so that we don't
1668
      // do a rehash if the allocation throws.
1669
      node* new_node = m_allocate_node (v);
1670
 
1671
      try
1672
        {
1673
          if (do_rehash.first)
1674
            {
1675
              n = this->bucket_index(k, code, do_rehash.second);
1676
              m_rehash(do_rehash.second);
1677
            }
1678
 
1679
          new_node->m_next = m_buckets[n];
1680
          this->store_code(new_node, code);
1681
          m_buckets[n] = new_node;
1682
          ++m_element_count;
1683
          return std::make_pair(iterator(new_node, m_buckets + n), true);
1684
        }
1685
      catch (...)
1686
        {
1687
          m_deallocate_node (new_node);
1688
          __throw_exception_again;
1689
        }
1690
    }
1691
 
1692
  // Insert v unconditionally.
1693
  template
1694
           typename A, typename Ex, typename Eq,
1695
           typename H1, typename H2, typename H, typename RP,
1696
           bool c, bool ci, bool u>
1697
    typename hashtable::iterator
1698
    hashtable::
1699
    insert(const value_type& v, std::tr1::false_type)
1700
    {
1701
      std::pair do_rehash
1702
        = m_rehash_policy.need_rehash(m_bucket_count, m_element_count, 1);
1703
      if (do_rehash.first)
1704
        m_rehash(do_rehash.second);
1705
 
1706
      const key_type& k = this->m_extract(v);
1707
      typename hashtable::hash_code_t code = this->m_hash_code(k);
1708
      size_type n = this->bucket_index(k, code, m_bucket_count);
1709
 
1710
      node* new_node = m_allocate_node (v);
1711
      node* prev = find_node(m_buckets[n], k, code);
1712
      if (prev)
1713
        {
1714
          new_node->m_next = prev->m_next;
1715
          prev->m_next = new_node;
1716
        }
1717
      else
1718
        {
1719
          new_node->m_next = m_buckets[n];
1720
          m_buckets[n] = new_node;
1721
        }
1722
      this->store_code(new_node, code);
1723
 
1724
      ++m_element_count;
1725
      return iterator(new_node, m_buckets + n);
1726
    }
1727
 
1728
  // For erase(iterator) and erase(const_iterator).
1729
  template
1730
           typename A, typename Ex, typename Eq,
1731
           typename H1, typename H2, typename H, typename RP,
1732
           bool c, bool ci, bool u>
1733
    void
1734
    hashtable::
1735
    erase_node(node* p, node** b)
1736
    {
1737
      node* cur = *b;
1738
      if (cur == p)
1739
        *b = cur->m_next;
1740
      else
1741
        {
1742
          node* next = cur->m_next;
1743
          while (next != p)
1744
            {
1745
              cur = next;
1746
              next = cur->m_next;
1747
            }
1748
          cur->m_next = next->m_next;
1749
        }
1750
 
1751
      m_deallocate_node (p);
1752
      --m_element_count;
1753
    }
1754
 
1755
  template
1756
           typename A, typename Ex, typename Eq,
1757
           typename H1, typename H2, typename H, typename RP,
1758
           bool c, bool ci, bool u>
1759
    template
1760
      void
1761
      hashtable::
1762
      insert(InIter first, InIter last)
1763
      {
1764
        size_type n_elt = Internal::distance_fw (first, last);
1765
        std::pair do_rehash
1766
          = m_rehash_policy.need_rehash(m_bucket_count, m_element_count, n_elt);
1767
        if (do_rehash.first)
1768
          m_rehash(do_rehash.second);
1769
 
1770
        for (; first != last; ++first)
1771
          this->insert (*first);
1772
      }
1773
 
1774
  template
1775
           typename A, typename Ex, typename Eq,
1776
           typename H1, typename H2, typename H, typename RP,
1777
           bool c, bool ci, bool u>
1778
    typename hashtable::iterator
1779
    hashtable::
1780
    erase(iterator i)
1781
    {
1782
      iterator result = i;
1783
      ++result;
1784
      erase_node(i.m_cur_node, i.m_cur_bucket);
1785
      return result;
1786
    }
1787
 
1788
  template
1789
           typename A, typename Ex, typename Eq,
1790
           typename H1, typename H2, typename H, typename RP,
1791
           bool c, bool ci, bool u>
1792
    typename hashtable::const_iterator
1793
    hashtable::
1794
    erase(const_iterator i)
1795
    {
1796
      const_iterator result = i;
1797
      ++result;
1798
      erase_node(i.m_cur_node, i.m_cur_bucket);
1799
      return result;
1800
    }
1801
 
1802
  template
1803
           typename A, typename Ex, typename Eq,
1804
           typename H1, typename H2, typename H, typename RP,
1805
           bool c, bool ci, bool u>
1806
    typename hashtable::size_type
1807
    hashtable::
1808
    erase(const key_type& k)
1809
    {
1810
      typename hashtable::hash_code_t code = this->m_hash_code(k);
1811
      size_type n = this->bucket_index(k, code, m_bucket_count);
1812
      size_type result = 0;
1813
 
1814
      node** slot = m_buckets + n;
1815
      while (*slot && ! this->compare(k, code, *slot))
1816
        slot = &((*slot)->m_next);
1817
 
1818
      while (*slot && this->compare(k, code, *slot))
1819
        {
1820
          node* n = *slot;
1821
          *slot = n->m_next;
1822
          m_deallocate_node (n);
1823
          --m_element_count;
1824
          ++result;
1825
        }
1826
 
1827
      return result;
1828
    }
1829
 
1830
  // ??? This could be optimized by taking advantage of the bucket
1831
  // structure, but it's not clear that it's worth doing.  It probably
1832
  // wouldn't even be an optimization unless the load factor is large.
1833
  template
1834
           typename A, typename Ex, typename Eq,
1835
           typename H1, typename H2, typename H, typename RP,
1836
           bool c, bool ci, bool u>
1837
    typename hashtable::iterator
1838
    hashtable::
1839
    erase(iterator first, iterator last)
1840
    {
1841
      while (first != last)
1842
        first = this->erase(first);
1843
      return last;
1844
    }
1845
 
1846
  template
1847
           typename A, typename Ex, typename Eq,
1848
           typename H1, typename H2, typename H, typename RP,
1849
           bool c, bool ci, bool u>
1850
    typename hashtable::const_iterator
1851
    hashtable::
1852
    erase(const_iterator first, const_iterator last)
1853
    {
1854
      while (first != last)
1855
        first = this->erase(first);
1856
      return last;
1857
    }
1858
 
1859
  template
1860
           typename A, typename Ex, typename Eq,
1861
           typename H1, typename H2, typename H, typename RP,
1862
           bool c, bool ci, bool u>
1863
    void
1864
    hashtable::
1865
    clear()
1866
    {
1867
      m_deallocate_nodes(m_buckets, m_bucket_count);
1868
      m_element_count = 0;
1869
    }
1870
 
1871
  template
1872
           typename A, typename Ex, typename Eq,
1873
           typename H1, typename H2, typename H, typename RP,
1874
           bool c, bool ci, bool u>
1875
    void
1876
    hashtable::
1877
    rehash(size_type n)
1878
    {
1879
      m_rehash(std::max(m_rehash_policy.next_bkt(n),
1880
                        m_rehash_policy.bkt_for_elements(m_element_count
1881
                                                         + 1)));
1882
    }
1883
 
1884
  template
1885
           typename A, typename Ex, typename Eq,
1886
           typename H1, typename H2, typename H, typename RP,
1887
           bool c, bool ci, bool u>
1888
    void
1889
    hashtable::
1890
    m_rehash(size_type N)
1891
    {
1892
      node** new_array = m_allocate_buckets (N);
1893
      try
1894
        {
1895
          for (size_type i = 0; i < m_bucket_count; ++i)
1896
            while (node* p = m_buckets[i])
1897
              {
1898
                size_type new_index = this->bucket_index (p, N);
1899
                m_buckets[i] = p->m_next;
1900
                p->m_next = new_array[new_index];
1901
                new_array[new_index] = p;
1902
              }
1903
          m_deallocate_buckets(m_buckets, m_bucket_count);
1904
          m_bucket_count = N;
1905
          m_buckets = new_array;
1906
        }
1907
      catch (...)
1908
        {
1909
          // A failure here means that a hash function threw an exception.
1910
          // We can't restore the previous state without calling the hash
1911
          // function again, so the only sensible recovery is to delete
1912
          // everything.
1913
          m_deallocate_nodes(new_array, N);
1914
          m_deallocate_buckets(new_array, N);
1915
          m_deallocate_nodes(m_buckets, m_bucket_count);
1916
          m_element_count = 0;
1917
          __throw_exception_again;
1918
        }
1919
    }
1920
}
1921
}                               // Namespace std::tr1
1922
 
1923
#endif /* GNU_LIBSTDCXX_TR1_HASHTABLE_ */
1924
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.