Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6554 serge 1
// -*- C++ -*-
2
 
3
// Copyright (C) 2005-2015 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 terms
7
// of the GNU General Public License as published by the Free Software
8
// Foundation; either version 3, or (at your option) any later
9
// version.
10
 
11
// This library is distributed in the hope that it will be useful, but
12
// WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
// General Public License for more details.
15
 
16
// Under Section 7 of GPL version 3, you are granted additional
17
// permissions described in the GCC Runtime Library Exception, version
18
// 3.1, as published by the Free Software Foundation.
19
 
20
// You should have received a copy of the GNU General Public License and
21
// a copy of the GCC Runtime Library Exception along with this program;
22
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23
// .
24
 
25
// Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
26
 
27
// Permission to use, copy, modify, sell, and distribute this software
28
// is hereby granted without fee, provided that the above copyright
29
// notice appears in all copies, and that both that copyright notice
30
// and this permission notice appear in supporting documentation. None
31
// of the above authors, nor IBM Haifa Research Laboratories, make any
32
// representation about the suitability of this software for any
33
// purpose. It is provided "as is" without express or implied
34
// warranty.
35
 
36
/**
37
 * @file cc_hash_table_map_/cc_ht_map_.hpp
38
 * Contains an implementation class for cc_ht_map_.
39
 */
40
 
41
#include 
42
#include 
43
#include 
44
#include 
45
#include 
46
#include 
47
#include 
48
#include 
49
#ifdef _GLIBCXX_DEBUG
50
#include 
51
#endif
52
#ifdef PB_DS_HT_MAP_TRACE_
53
#include 
54
#endif
55
#include 
56
 
57
namespace __gnu_pbds
58
{
59
  namespace detail
60
  {
61
#ifdef PB_DS_DATA_TRUE_INDICATOR
62
#define PB_DS_CC_HASH_NAME cc_ht_map
63
#endif
64
 
65
#ifdef PB_DS_DATA_FALSE_INDICATOR
66
#define PB_DS_CC_HASH_NAME cc_ht_set
67
#endif
68
 
69
#define PB_DS_CLASS_T_DEC \
70
    template
71
	     typename Eq_Fn, typename _Alloc, bool Store_Hash, \
72
	     typename Comb_Hash_Fn, typename Resize_Policy>
73
 
74
#define PB_DS_CLASS_C_DEC \
75
    PB_DS_CC_HASH_NAME
76
		     Store_Hash, Comb_Hash_Fn, Resize_Policy>
77
 
78
#define PB_DS_HASH_EQ_FN_C_DEC \
79
    hash_eq_fn
80
 
81
#define PB_DS_RANGED_HASH_FN_C_DEC \
82
    ranged_hash_fn
83
 
84
#define PB_DS_CC_HASH_TRAITS_BASE \
85
    types_traits
86
 
87
#ifdef _GLIBCXX_DEBUG
88
#define PB_DS_DEBUG_MAP_BASE_C_DEC \
89
    debug_map_base
90
		  typename _Alloc::template rebind::other::const_reference>
91
#endif
92
 
93
 
94
    /**
95
     *  A collision-chaining hash-based container.
96
     *
97
     *
98
     *  @ingroup hash-detail
99
     *
100
     *  @tparam Key 	    	Key type.
101
     *
102
     *  @tparam Mapped 	    	Map type.
103
     *
104
     *  @tparam Hash_Fn	      	Hashing functor.
105
     *                          Default is __gnu_cxx::hash.
106
     *
107
     *  @tparam Eq_Fn	      	Equal functor.
108
     *                          Default std::equal_to
109
     *
110
     *  @tparam _Alloc 	    	Allocator type.
111
     *
112
     *  @tparam Store_Hash    	If key type stores extra metadata.
113
     *                          Defaults to false.
114
     *
115
     *  @tparam Comb_Hash_Fn	Combining hash functor.
116
     *                          If Hash_Fn is not null_type, then this
117
     *                          is the ranged-hash functor; otherwise,
118
     *                          this is the range-hashing functor.
119
     *                    XXX(See Design::Hash-Based Containers::Hash Policies.)
120
     *                          Default direct_mask_range_hashing.
121
     *
122
     *  @tparam Resize_Policy 	Resizes hash.
123
     *                          Defaults to hash_standard_resize_policy,
124
     *                          using hash_exponential_size_policy and
125
     *                          hash_load_check_resize_trigger.
126
     *
127
     *
128
     *  Bases are: detail::hash_eq_fn, Resize_Policy, detail::ranged_hash_fn,
129
     *             detail::types_traits. (Optional: detail::debug_map_base.)
130
     */
131
    template
132
	     typename Mapped,
133
	     typename Hash_Fn,
134
	     typename Eq_Fn,
135
	     typename _Alloc,
136
	     bool Store_Hash,
137
	     typename Comb_Hash_Fn,
138
	     typename Resize_Policy >
139
    class PB_DS_CC_HASH_NAME:
140
#ifdef _GLIBCXX_DEBUG
141
      protected PB_DS_DEBUG_MAP_BASE_C_DEC,
142
#endif
143
      public PB_DS_HASH_EQ_FN_C_DEC,
144
      public Resize_Policy,
145
      public PB_DS_RANGED_HASH_FN_C_DEC,
146
      public PB_DS_CC_HASH_TRAITS_BASE
147
    {
148
    private:
149
      typedef PB_DS_CC_HASH_TRAITS_BASE	       	traits_base;
150
      typedef typename traits_base::comp_hash 	comp_hash;
151
      typedef typename traits_base::value_type 	value_type_;
152
      typedef typename traits_base::pointer 	pointer_;
153
      typedef typename traits_base::const_pointer const_pointer_;
154
      typedef typename traits_base::reference 	reference_;
155
      typedef typename traits_base::const_reference const_reference_;
156
 
157
      struct entry : public traits_base::stored_data_type
158
      {
159
	typename _Alloc::template rebind::other::pointer m_p_next;
160
      };
161
 
162
      typedef cond_dealtor 	cond_dealtor_t;
163
 
164
      typedef typename _Alloc::template rebind::other entry_allocator;
165
      typedef typename entry_allocator::pointer entry_pointer;
166
      typedef typename entry_allocator::const_pointer const_entry_pointer;
167
      typedef typename entry_allocator::reference entry_reference;
168
      typedef typename entry_allocator::const_reference const_entry_reference;
169
 
170
      typedef typename _Alloc::template rebind::other entry_pointer_allocator;
171
      typedef typename entry_pointer_allocator::pointer entry_pointer_array;
172
 
173
      typedef PB_DS_RANGED_HASH_FN_C_DEC ranged_hash_fn_base;
174
      typedef PB_DS_HASH_EQ_FN_C_DEC hash_eq_fn_base;
175
      typedef Resize_Policy resize_base;
176
 
177
#ifdef _GLIBCXX_DEBUG
178
      typedef PB_DS_DEBUG_MAP_BASE_C_DEC 	debug_base;
179
#endif
180
 
181
#define PB_DS_GEN_POS std::pair
182
 
183
#include 
184
#include 
185
#include 
186
#include 
187
 
188
#undef PB_DS_GEN_POS
189
 
190
    public:
191
      typedef _Alloc 				allocator_type;
192
      typedef typename _Alloc::size_type 	size_type;
193
      typedef typename _Alloc::difference_type 	difference_type;
194
      typedef Hash_Fn 				hash_fn;
195
      typedef Eq_Fn 				eq_fn;
196
      typedef Comb_Hash_Fn 			comb_hash_fn;
197
      typedef Resize_Policy 			resize_policy;
198
 
199
      /// Value stores hash, true or false.
200
      enum
201
	{
202
	  store_hash = Store_Hash
203
	};
204
 
205
      typedef typename traits_base::key_type key_type;
206
      typedef typename traits_base::key_pointer key_pointer;
207
      typedef typename traits_base::key_const_pointer key_const_pointer;
208
      typedef typename traits_base::key_reference key_reference;
209
      typedef typename traits_base::key_const_reference key_const_reference;
210
      typedef typename traits_base::mapped_type mapped_type;
211
      typedef typename traits_base::mapped_pointer mapped_pointer;
212
      typedef typename traits_base::mapped_const_pointer mapped_const_pointer;
213
      typedef typename traits_base::mapped_reference mapped_reference;
214
      typedef typename traits_base::mapped_const_reference mapped_const_reference;
215
      typedef typename traits_base::value_type 	value_type;
216
      typedef typename traits_base::pointer 	pointer;
217
      typedef typename traits_base::const_pointer const_pointer;
218
      typedef typename traits_base::reference 	reference;
219
      typedef typename traits_base::const_reference const_reference;
220
 
221
#ifdef PB_DS_DATA_TRUE_INDICATOR
222
      typedef point_iterator_ 			point_iterator;
223
#endif
224
 
225
#ifdef PB_DS_DATA_FALSE_INDICATOR
226
      typedef point_const_iterator_ 		point_iterator;
227
#endif
228
 
229
      typedef point_const_iterator_ 		point_const_iterator;
230
 
231
#ifdef PB_DS_DATA_TRUE_INDICATOR
232
      typedef iterator_ 			iterator;
233
#endif
234
 
235
#ifdef PB_DS_DATA_FALSE_INDICATOR
236
      typedef const_iterator_ 			iterator;
237
#endif
238
 
239
      typedef const_iterator_ 			const_iterator;
240
 
241
      PB_DS_CC_HASH_NAME();
242
 
243
      PB_DS_CC_HASH_NAME(const Hash_Fn&);
244
 
245
      PB_DS_CC_HASH_NAME(const Hash_Fn&, const Eq_Fn&);
246
 
247
      PB_DS_CC_HASH_NAME(const Hash_Fn&, const Eq_Fn&, const Comb_Hash_Fn&);
248
 
249
      PB_DS_CC_HASH_NAME(const Hash_Fn&, const Eq_Fn&, const Comb_Hash_Fn&,
250
		       const Resize_Policy&);
251
 
252
      PB_DS_CC_HASH_NAME(const PB_DS_CLASS_C_DEC&);
253
 
254
      virtual
255
      ~PB_DS_CC_HASH_NAME();
256
 
257
      void
258
      swap(PB_DS_CLASS_C_DEC&);
259
 
260
      template
261
      void
262
      copy_from_range(It, It);
263
 
264
      void
265
      initialize();
266
 
267
      inline size_type
268
      size() const;
269
 
270
      inline size_type
271
      max_size() const;
272
 
273
      /// True if size() == 0.
274
      inline bool
275
      empty() const;
276
 
277
      /// Return current hash_fn.
278
      Hash_Fn&
279
      get_hash_fn();
280
 
281
      /// Return current const hash_fn.
282
      const Hash_Fn&
283
      get_hash_fn() const;
284
 
285
      /// Return current eq_fn.
286
      Eq_Fn&
287
      get_eq_fn();
288
 
289
      /// Return current const eq_fn.
290
      const Eq_Fn&
291
      get_eq_fn() const;
292
 
293
      /// Return current comb_hash_fn.
294
      Comb_Hash_Fn&
295
      get_comb_hash_fn();
296
 
297
      /// Return current const comb_hash_fn.
298
      const Comb_Hash_Fn&
299
      get_comb_hash_fn() const;
300
 
301
      /// Return current resize_policy.
302
      Resize_Policy&
303
      get_resize_policy();
304
 
305
      /// Return current const resize_policy.
306
      const Resize_Policy&
307
      get_resize_policy() const;
308
 
309
      inline std::pair
310
      insert(const_reference r_val)
311
      { return insert_imp(r_val, traits_base::m_store_extra_indicator); }
312
 
313
      inline mapped_reference
314
      operator[](key_const_reference r_key)
315
      {
316
#ifdef PB_DS_DATA_TRUE_INDICATOR
317
	return (subscript_imp(r_key, traits_base::m_store_extra_indicator));
318
#else
319
	insert(r_key);
320
	return traits_base::s_null_type;
321
#endif
322
      }
323
 
324
      inline point_iterator
325
      find(key_const_reference);
326
 
327
      inline point_const_iterator
328
      find(key_const_reference) const;
329
 
330
      inline point_iterator
331
      find_end();
332
 
333
      inline point_const_iterator
334
      find_end() const;
335
 
336
      inline bool
337
      erase(key_const_reference);
338
 
339
      template
340
      inline size_type
341
      erase_if(Pred);
342
 
343
      void
344
      clear();
345
 
346
      inline iterator
347
      begin();
348
 
349
      inline const_iterator
350
      begin() const;
351
 
352
      inline iterator
353
      end();
354
 
355
      inline const_iterator
356
      end() const;
357
 
358
#ifdef _GLIBCXX_DEBUG
359
      void
360
      assert_valid(const char*, int) const;
361
#endif
362
 
363
#ifdef PB_DS_HT_MAP_TRACE_
364
      void
365
      trace() const;
366
#endif
367
 
368
    private:
369
      void
370
      deallocate_all();
371
 
372
      inline bool
373
      do_resize_if_needed();
374
 
375
      inline void
376
      do_resize_if_needed_no_throw();
377
 
378
      void
379
      resize_imp(size_type);
380
 
381
      void
382
      do_resize(size_type);
383
 
384
      void
385
      resize_imp_no_exceptions(size_type, entry_pointer_array, size_type);
386
 
387
      inline entry_pointer
388
      resize_imp_no_exceptions_reassign_pointer(entry_pointer,
389
						entry_pointer_array,
390
						false_type);
391
 
392
      inline entry_pointer
393
      resize_imp_no_exceptions_reassign_pointer(entry_pointer,
394
						entry_pointer_array,
395
						true_type);
396
 
397
      void
398
      deallocate_links_in_list(entry_pointer);
399
 
400
      inline entry_pointer
401
      get_entry(const_reference, false_type);
402
 
403
      inline entry_pointer
404
      get_entry(const_reference, true_type);
405
 
406
      inline void
407
      rels_entry(entry_pointer);
408
 
409
#ifdef PB_DS_DATA_TRUE_INDICATOR
410
      inline mapped_reference
411
      subscript_imp(key_const_reference r_key, false_type)
412
      {
413
	_GLIBCXX_DEBUG_ONLY(assert_valid(__FILE__, __LINE__);)
414
	const size_type pos = ranged_hash_fn_base::operator()(r_key);
415
	entry_pointer p_e = m_entries[pos];
416
	resize_base::notify_insert_search_start();
417
 
418
	while (p_e != 0
419
	       && !hash_eq_fn_base::operator()(p_e->m_value.first, r_key))
420
	  {
421
	    resize_base::notify_insert_search_collision();
422
	    p_e = p_e->m_p_next;
423
	  }
424
 
425
	resize_base::notify_insert_search_end();
426
	if (p_e != 0)
427
	  {
428
	    PB_DS_CHECK_KEY_EXISTS(r_key)
429
	    return (p_e->m_value.second);
430
	  }
431
 
432
	PB_DS_CHECK_KEY_DOES_NOT_EXIST(r_key)
433
	return insert_new_imp(value_type(r_key, mapped_type()), pos)->second;
434
      }
435
 
436
      inline mapped_reference
437
      subscript_imp(key_const_reference r_key, true_type)
438
      {
439
	_GLIBCXX_DEBUG_ONLY(assert_valid(__FILE__, __LINE__);)
440
	comp_hash pos_hash_pair = ranged_hash_fn_base::operator()(r_key);
441
	entry_pointer p_e = m_entries[pos_hash_pair.first];
442
	resize_base::notify_insert_search_start();
443
	while (p_e != 0 &&
444
	       !hash_eq_fn_base::operator()(p_e->m_value.first, p_e->m_hash,
445
					    r_key, pos_hash_pair.second))
446
	  {
447
	    resize_base::notify_insert_search_collision();
448
	    p_e = p_e->m_p_next;
449
	  }
450
 
451
	resize_base::notify_insert_search_end();
452
	if (p_e != 0)
453
	  {
454
	    PB_DS_CHECK_KEY_EXISTS(r_key)
455
	    return p_e->m_value.second;
456
	  }
457
 
458
	PB_DS_CHECK_KEY_DOES_NOT_EXIST(r_key)
459
	return insert_new_imp(value_type(r_key, mapped_type()),
460
			      pos_hash_pair)->second;
461
      }
462
#endif
463
 
464
      inline std::pair
465
      insert_imp(const_reference, false_type);
466
 
467
      inline std::pair
468
      insert_imp(const_reference, true_type);
469
 
470
      inline pointer
471
      insert_new_imp(const_reference r_val, size_type pos)
472
      {
473
	if (do_resize_if_needed())
474
	  pos = ranged_hash_fn_base::operator()(PB_DS_V2F(r_val));
475
 
476
	// Following lines might throw an exception.
477
	entry_pointer p_e = get_entry(r_val,
478
				      traits_base::m_no_throw_copies_indicator);
479
 
480
	// At this point no exceptions can be thrown.
481
	p_e->m_p_next = m_entries[pos];
482
	m_entries[pos] = p_e;
483
	resize_base::notify_inserted(++m_num_used_e);
484
 
485
	_GLIBCXX_DEBUG_ONLY(debug_base::insert_new(PB_DS_V2F(r_val));)
486
	_GLIBCXX_DEBUG_ONLY(assert_valid(__FILE__, __LINE__);)
487
	return &p_e->m_value;
488
      }
489
 
490
      inline pointer
491
      insert_new_imp(const_reference r_val, comp_hash& r_pos_hash_pair)
492
      {
493
	// Following lines might throw an exception.
494
	if (do_resize_if_needed())
495
	  r_pos_hash_pair = ranged_hash_fn_base::operator()(PB_DS_V2F(r_val));
496
 
497
	entry_pointer p_e = get_entry(r_val,
498
				      traits_base::m_no_throw_copies_indicator);
499
 
500
	// At this point no exceptions can be thrown.
501
	p_e->m_hash = r_pos_hash_pair.second;
502
	p_e->m_p_next = m_entries[r_pos_hash_pair.first];
503
	m_entries[r_pos_hash_pair.first] = p_e;
504
	resize_base::notify_inserted(++m_num_used_e);
505
	_GLIBCXX_DEBUG_ONLY(debug_base::insert_new(PB_DS_V2F(r_val));)
506
	_GLIBCXX_DEBUG_ONLY(assert_valid(__FILE__, __LINE__);)
507
	return &p_e->m_value;
508
      }
509
 
510
      inline pointer
511
      find_key_pointer(key_const_reference r_key, false_type)
512
      {
513
	entry_pointer p_e = m_entries[ranged_hash_fn_base::operator()(r_key)];
514
	resize_base::notify_find_search_start();
515
	while (p_e != 0 &&
516
	       !hash_eq_fn_base::operator()(PB_DS_V2F(p_e->m_value), r_key))
517
	  {
518
	    resize_base::notify_find_search_collision();
519
	    p_e = p_e->m_p_next;
520
	  }
521
 
522
	resize_base::notify_find_search_end();
523
 
524
#ifdef _GLIBCXX_DEBUG
525
	if (p_e == 0)
526
	  PB_DS_CHECK_KEY_DOES_NOT_EXIST(r_key)
527
	else
528
	  PB_DS_CHECK_KEY_EXISTS(r_key)
529
#endif
530
	return &p_e->m_value;
531
      }
532
 
533
      inline pointer
534
      find_key_pointer(key_const_reference r_key, true_type)
535
      {
536
	comp_hash pos_hash_pair = ranged_hash_fn_base::operator()(r_key);
537
	entry_pointer p_e = m_entries[pos_hash_pair.first];
538
	resize_base::notify_find_search_start();
539
	while (p_e != 0 &&
540
	       !hash_eq_fn_base::operator()(PB_DS_V2F(p_e->m_value),
541
					    p_e->m_hash,
542
					    r_key, pos_hash_pair.second))
543
	  {
544
	    resize_base::notify_find_search_collision();
545
	    p_e = p_e->m_p_next;
546
	  }
547
 
548
	resize_base::notify_find_search_end();
549
 
550
#ifdef _GLIBCXX_DEBUG
551
	if (p_e == 0)
552
	  PB_DS_CHECK_KEY_DOES_NOT_EXIST(r_key)
553
	else
554
	  PB_DS_CHECK_KEY_EXISTS(r_key)
555
#endif
556
	return &p_e->m_value;
557
      }
558
 
559
      inline bool
560
      erase_in_pos_imp(key_const_reference, size_type);
561
 
562
      inline bool
563
      erase_in_pos_imp(key_const_reference, const comp_hash&);
564
 
565
      inline void
566
      erase_entry_pointer(entry_pointer&);
567
 
568
#ifdef PB_DS_DATA_TRUE_INDICATOR
569
      void
570
      inc_it_state(pointer& r_p_value,
571
		   std::pair& r_pos) const
572
      {
573
	inc_it_state((mapped_const_pointer& )r_p_value, r_pos);
574
      }
575
#endif
576
 
577
      void
578
      inc_it_state(const_pointer& r_p_value,
579
		   std::pair& r_pos) const
580
      {
581
	_GLIBCXX_DEBUG_ASSERT(r_p_value != 0);
582
	r_pos.first = r_pos.first->m_p_next;
583
	if (r_pos.first != 0)
584
	  {
585
	    r_p_value = &r_pos.first->m_value;
586
	    return;
587
	  }
588
 
589
	for (++r_pos.second; r_pos.second < m_num_e; ++r_pos.second)
590
	  if (m_entries[r_pos.second] != 0)
591
	    {
592
	      r_pos.first = m_entries[r_pos.second];
593
	      r_p_value = &r_pos.first->m_value;
594
	      return;
595
	    }
596
	r_p_value = 0;
597
      }
598
 
599
      void
600
      get_start_it_state(pointer& r_p_value,
601
			 std::pair& r_pos) const
602
      {
603
	for (r_pos.second = 0; r_pos.second < m_num_e; ++r_pos.second)
604
	  if (m_entries[r_pos.second] != 0)
605
	    {
606
	      r_pos.first = m_entries[r_pos.second];
607
	      r_p_value = &r_pos.first->m_value;
608
	      return;
609
	    }
610
	r_p_value = 0;
611
      }
612
 
613
#ifdef _GLIBCXX_DEBUG
614
      void
615
      assert_entry_pointer_array_valid(const entry_pointer_array,
616
				       const char*, int) const;
617
 
618
      void
619
      assert_entry_pointer_valid(const entry_pointer, true_type,
620
				 const char*, int) const;
621
 
622
      void
623
      assert_entry_pointer_valid(const entry_pointer, false_type,
624
				 const char*, int) const;
625
#endif
626
 
627
#ifdef PB_DS_HT_MAP_TRACE_
628
      void
629
      trace_list(const_entry_pointer) const;
630
#endif
631
 
632
    private:
633
#ifdef PB_DS_DATA_TRUE_INDICATOR
634
      friend class iterator_;
635
#endif
636
 
637
      friend class const_iterator_;
638
 
639
      static entry_allocator 		s_entry_allocator;
640
      static entry_pointer_allocator 	s_entry_pointer_allocator;
641
      static iterator 			s_end_it;
642
      static const_iterator 		s_const_end_it;
643
      static point_iterator 		s_find_end_it;
644
      static point_const_iterator 	s_const_find_end_it;
645
 
646
      size_type 			m_num_e;
647
      size_type 			m_num_used_e;
648
      entry_pointer_array 		m_entries;
649
 
650
      enum
651
	{
652
	  store_hash_ok = !Store_Hash
653
			  || !is_same::value
654
	};
655
 
656
      PB_DS_STATIC_ASSERT(sth, store_hash_ok);
657
    };
658
 
659
#include 
660
#include 
661
#include 
662
#include 
663
#include 
664
#include 
665
#include 
666
#include 
667
#include 
668
#include 
669
#include 
670
 
671
#undef PB_DS_CLASS_T_DEC
672
#undef PB_DS_CLASS_C_DEC
673
#undef PB_DS_HASH_EQ_FN_C_DEC
674
#undef PB_DS_RANGED_HASH_FN_C_DEC
675
#undef PB_DS_CC_HASH_TRAITS_BASE
676
#undef PB_DS_DEBUG_MAP_BASE_C_DEC
677
#undef PB_DS_CC_HASH_NAME
678
  } // namespace detail
679
} // namespace __gnu_pbds