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// <http://www.gnu.org/licenses/>.
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 pat_trie_/pat_trie_base.hpp
38 * Contains the base class for a patricia tree.
39 */
40
41#ifndef PB_DS_PAT_TRIE_BASE
42#define PB_DS_PAT_TRIE_BASE
43
44#include <debug/debug.h>
45
46namespace __gnu_pbds
47{
48  namespace detail
49  {
50    /// Base type for PATRICIA trees.
51    struct pat_trie_base
52    {
53      /**
54       *  @brief  Three types of nodes.
55       *
56       *  i_node is used by _Inode, leaf_node by _Leaf, and head_node by _Head.
57       */
58      enum node_type
59	{
60	  i_node,
61	  leaf_node,
62	  head_node
63	};
64
65      /// Metadata base primary template.
66      template<typename Metadata, typename _Alloc>
67	struct _Metadata
68	{
69	  typedef Metadata     					metadata_type;
70	  typedef _Alloc     					allocator_type;
71	  typedef typename _Alloc::template rebind<Metadata>	__rebind_m;
72	  typedef typename __rebind_m::other::const_reference  const_reference;
73
74	  const_reference
75	  get_metadata() const
76	  { return m_metadata; }
77
78	  metadata_type 					m_metadata;
79	};
80
81      /// Specialization for null metadata.
82      template<typename _Alloc>
83	struct _Metadata<null_type, _Alloc>
84	{
85	  typedef null_type 					metadata_type;
86	  typedef _Alloc     					allocator_type;
87	};
88
89
90      /// Node base.
91      template<typename _ATraits, typename Metadata>
92      struct _Node_base
93      : public Metadata
94      {
95      private:
96	typedef typename Metadata::allocator_type		_Alloc;
97
98      public:
99	typedef _Alloc						allocator_type;
100	typedef _ATraits					access_traits;
101	typedef typename _ATraits::type_traits			type_traits;
102	typedef typename _Alloc::template rebind<_Node_base>	__rebind_n;
103	typedef typename __rebind_n::other::pointer 		node_pointer;
104
105	node_pointer 						m_p_parent;
106	const node_type 	       				m_type;
107
108	_Node_base(node_type type) : m_type(type)
109	{ }
110
111	typedef typename _Alloc::template rebind<_ATraits>    __rebind_at;
112	typedef typename __rebind_at::other::const_pointer    a_const_pointer;
113	typedef typename _ATraits::const_iterator	      a_const_iterator;
114
115#ifdef _GLIBCXX_DEBUG
116	typedef std::pair<a_const_iterator, a_const_iterator> node_debug_info;
117
118	void
119	assert_valid(a_const_pointer p_traits,
120		     const char* __file, int __line) const
121	{ assert_valid_imp(p_traits, __file, __line); }
122
123	virtual node_debug_info
124	assert_valid_imp(a_const_pointer, const char*, int) const = 0;
125#endif
126      };
127
128
129    /// Head node for PATRICIA tree.
130    template<typename _ATraits, typename Metadata>
131    struct _Head
132    : public _Node_base<_ATraits, Metadata>
133    {
134      typedef _Node_base<_ATraits, Metadata> 			base_type;
135      typedef typename base_type::type_traits			type_traits;
136      typedef typename base_type::node_pointer			node_pointer;
137
138      node_pointer						m_p_min;
139      node_pointer						m_p_max;
140
141      _Head() : base_type(head_node) { }
142
143#ifdef _GLIBCXX_DEBUG
144      typedef typename base_type::node_debug_info      	       node_debug_info;
145      typedef typename base_type::a_const_pointer 	       a_const_pointer;
146
147      virtual node_debug_info
148      assert_valid_imp(a_const_pointer, const char* __file, int __line) const
149      {
150	_GLIBCXX_DEBUG_VERIFY_AT(false,
151				 _M_message("Assertion from %1;:%2;")
152				 ._M_string(__FILE__)._M_integer(__LINE__),
153				 __file, __line);
154	return node_debug_info();
155      }
156#endif
157    };
158
159
160    /// Leaf node for PATRICIA tree.
161    template<typename _ATraits, typename Metadata>
162    struct _Leaf
163    : public _Node_base<_ATraits, Metadata>
164    {
165      typedef _Node_base<_ATraits, Metadata> 	   	    	base_type;
166      typedef typename base_type::type_traits			type_traits;
167      typedef typename type_traits::value_type			value_type;
168      typedef typename type_traits::reference			reference;
169      typedef typename type_traits::const_reference    		const_reference;
170
171    private:
172      value_type						m_value;
173
174      _Leaf(const _Leaf&);
175
176    public:
177      _Leaf(const_reference other)
178      : base_type(leaf_node), m_value(other) { }
179
180      reference
181      value()
182      { return m_value; }
183
184      const_reference
185      value() const
186      { return m_value; }
187
188#ifdef _GLIBCXX_DEBUG
189      typedef typename base_type::node_debug_info      		node_debug_info;
190      typedef typename base_type::a_const_pointer      		a_const_pointer;
191
192      virtual node_debug_info
193      assert_valid_imp(a_const_pointer p_traits,
194		       const char* __file, int __line) const
195      {
196	PB_DS_DEBUG_VERIFY(base_type::m_type == leaf_node);
197	node_debug_info ret;
198	const_reference r_val = value();
199	return std::make_pair(p_traits->begin(p_traits->extract_key(r_val)),
200			      p_traits->end(p_traits->extract_key(r_val)));
201      }
202
203      virtual
204      ~_Leaf() { }
205#endif
206    };
207
208
209    /// Internal node type, PATRICIA tree.
210    template<typename _ATraits, typename Metadata>
211    struct _Inode
212    : public _Node_base<_ATraits, Metadata>
213    {
214      typedef _Node_base<_ATraits, Metadata> 			base_type;
215      typedef typename base_type::type_traits			type_traits;
216      typedef typename base_type::access_traits	       		access_traits;
217      typedef typename type_traits::value_type 			value_type;
218      typedef typename base_type::allocator_type		_Alloc;
219      typedef _Alloc						allocator_type;
220      typedef typename _Alloc::size_type 			size_type;
221
222    private:
223      typedef typename base_type::a_const_pointer      	       a_const_pointer;
224      typedef typename base_type::a_const_iterator     	      a_const_iterator;
225
226      typedef typename base_type::node_pointer			node_pointer;
227      typedef typename _Alloc::template rebind<base_type>	__rebind_n;
228      typedef typename __rebind_n::other::const_pointer      node_const_pointer;
229
230      typedef _Leaf<_ATraits, Metadata>	 			leaf;
231      typedef typename _Alloc::template rebind<leaf>::other 	__rebind_l;
232      typedef typename __rebind_l::pointer 			leaf_pointer;
233      typedef typename __rebind_l::const_pointer 	    leaf_const_pointer;
234
235      typedef typename _Alloc::template rebind<_Inode>::other 	__rebind_in;
236      typedef typename __rebind_in::pointer 			inode_pointer;
237      typedef typename __rebind_in::const_pointer 	    inode_const_pointer;
238
239      inline size_type
240      get_pref_pos(a_const_iterator, a_const_iterator, a_const_pointer) const;
241
242    public:
243      typedef typename _Alloc::template rebind<node_pointer>::other __rebind_np;
244      typedef typename __rebind_np::pointer 		node_pointer_pointer;
245      typedef typename __rebind_np::reference 		node_pointer_reference;
246
247      enum
248	{
249	  arr_size = _ATraits::max_size + 1
250	};
251      PB_DS_STATIC_ASSERT(min_arr_size, arr_size >= 2);
252
253
254      /// Constant child iterator.
255      struct const_iterator
256      {
257	node_pointer_pointer 				m_p_p_cur;
258	node_pointer_pointer 				m_p_p_end;
259
260	typedef std::forward_iterator_tag 		iterator_category;
261	typedef typename _Alloc::difference_type 	difference_type;
262	typedef node_pointer 				value_type;
263	typedef node_pointer_pointer 			pointer;
264	typedef node_pointer_reference 			reference;
265
266	const_iterator(node_pointer_pointer p_p_cur = 0,
267		       node_pointer_pointer p_p_end = 0)
268	: m_p_p_cur(p_p_cur), m_p_p_end(p_p_end)
269	{ }
270
271	bool
272	operator==(const const_iterator& other) const
273	{ return m_p_p_cur == other.m_p_p_cur; }
274
275	bool
276	operator!=(const const_iterator& other) const
277	{ return m_p_p_cur != other.m_p_p_cur; }
278
279	const_iterator&
280	operator++()
281	{
282	  do
283	    ++m_p_p_cur;
284	  while (m_p_p_cur != m_p_p_end && *m_p_p_cur == 0);
285	  return *this;
286	}
287
288	const_iterator
289	operator++(int)
290	{
291	  const_iterator ret_it(*this);
292	  operator++();
293	  return ret_it;
294	}
295
296	const node_pointer_pointer
297	operator->() const
298	{
299	  _GLIBCXX_DEBUG_ONLY(assert_referencible();)
300	  return m_p_p_cur;
301	}
302
303	node_const_pointer
304	operator*() const
305	{
306	  _GLIBCXX_DEBUG_ONLY(assert_referencible();)
307	  return *m_p_p_cur;
308	}
309
310      protected:
311#ifdef _GLIBCXX_DEBUG
312	void
313	assert_referencible() const
314	{ _GLIBCXX_DEBUG_ASSERT(m_p_p_cur != m_p_p_end && *m_p_p_cur != 0); }
315#endif
316      };
317
318
319      /// Child iterator.
320      struct iterator : public const_iterator
321      {
322      public:
323	typedef std::forward_iterator_tag 		iterator_category;
324	typedef typename _Alloc::difference_type 	difference_type;
325	typedef node_pointer 				value_type;
326	typedef node_pointer_pointer 			pointer;
327	typedef node_pointer_reference 			reference;
328
329	inline
330	iterator(node_pointer_pointer p_p_cur = 0,
331		 node_pointer_pointer p_p_end = 0)
332	: const_iterator(p_p_cur, p_p_end) { }
333
334	bool
335	operator==(const iterator& other) const
336	{ return const_iterator::m_p_p_cur == other.m_p_p_cur; }
337
338	bool
339	operator!=(const iterator& other) const
340	{ return const_iterator::m_p_p_cur != other.m_p_p_cur; }
341
342	iterator&
343	operator++()
344	{
345	  const_iterator::operator++();
346	  return *this;
347	}
348
349	iterator
350	operator++(int)
351	{
352	  iterator ret_it(*this);
353	  operator++();
354	  return ret_it;
355	}
356
357	node_pointer_pointer
358	operator->()
359	{
360	  _GLIBCXX_DEBUG_ONLY(const_iterator::assert_referencible();)
361	  return const_iterator::m_p_p_cur;
362	}
363
364	node_pointer
365	operator*()
366	{
367	  _GLIBCXX_DEBUG_ONLY(const_iterator::assert_referencible();)
368	  return *const_iterator::m_p_p_cur;
369	}
370      };
371
372
373      _Inode(size_type, const a_const_iterator);
374
375      void
376      update_prefixes(a_const_pointer);
377
378      const_iterator
379      begin() const;
380
381      iterator
382      begin();
383
384      const_iterator
385      end() const;
386
387      iterator
388      end();
389
390      inline node_pointer
391      get_child_node(a_const_iterator, a_const_iterator, a_const_pointer);
392
393      inline node_const_pointer
394      get_child_node(a_const_iterator, a_const_iterator, a_const_pointer) const;
395
396      inline iterator
397      get_child_it(a_const_iterator, a_const_iterator, a_const_pointer);
398
399      inline node_pointer
400      get_lower_bound_child_node(a_const_iterator, a_const_iterator,
401				 size_type, a_const_pointer);
402
403      inline node_pointer
404      add_child(node_pointer, a_const_iterator, a_const_iterator,
405		a_const_pointer);
406
407      inline node_const_pointer
408      get_join_child(node_const_pointer, a_const_pointer) const;
409
410      inline node_pointer
411      get_join_child(node_pointer, a_const_pointer);
412
413      void
414      remove_child(node_pointer);
415
416      void
417      remove_child(iterator);
418
419      void
420      replace_child(node_pointer, a_const_iterator, a_const_iterator,
421		    a_const_pointer);
422
423      inline a_const_iterator
424      pref_b_it() const;
425
426      inline a_const_iterator
427      pref_e_it() const;
428
429      bool
430      should_be_mine(a_const_iterator, a_const_iterator, size_type,
431		     a_const_pointer) const;
432
433      leaf_pointer
434      leftmost_descendant();
435
436      leaf_const_pointer
437      leftmost_descendant() const;
438
439      leaf_pointer
440      rightmost_descendant();
441
442      leaf_const_pointer
443      rightmost_descendant() const;
444
445#ifdef _GLIBCXX_DEBUG
446      typedef typename base_type::node_debug_info 	       node_debug_info;
447
448      virtual node_debug_info
449      assert_valid_imp(a_const_pointer, const char*, int) const;
450#endif
451
452      size_type
453      get_e_ind() const
454      { return m_e_ind; }
455
456    private:
457      _Inode(const _Inode&);
458
459      size_type
460      get_begin_pos() const;
461
462      static __rebind_l			s_leaf_alloc;
463      static __rebind_in 		s_inode_alloc;
464
465      const size_type 			m_e_ind;
466      a_const_iterator 			m_pref_b_it;
467      a_const_iterator 			m_pref_e_it;
468      node_pointer 			m_a_p_children[arr_size];
469    };
470
471#define PB_DS_CONST_IT_C_DEC \
472    _CIter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
473
474#define PB_DS_CONST_ODIR_IT_C_DEC \
475    _CIter<Node, Leaf, Head, Inode, !Is_Forward_Iterator>
476
477#define PB_DS_IT_C_DEC \
478    _Iter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
479
480#define PB_DS_ODIR_IT_C_DEC \
481    _Iter<Node, Leaf, Head, Inode, !Is_Forward_Iterator>
482
483
484    /// Const iterator.
485    template<typename Node, typename Leaf, typename Head, typename Inode,
486	     bool Is_Forward_Iterator>
487    class _CIter
488    {
489    public:
490      // These types are all the same for the first four template arguments.
491      typedef typename Node::allocator_type		allocator_type;
492      typedef typename Node::type_traits		type_traits;
493
494      typedef std::bidirectional_iterator_tag 		iterator_category;
495      typedef typename allocator_type::difference_type	difference_type;
496      typedef typename type_traits::value_type		value_type;
497      typedef typename type_traits::pointer 		pointer;
498      typedef typename type_traits::reference 		reference;
499      typedef typename type_traits::const_pointer 	const_pointer;
500      typedef typename type_traits::const_reference 	const_reference;
501
502      typedef allocator_type				_Alloc;
503      typedef typename _Alloc::template rebind<Node>	__rebind_n;
504      typedef typename __rebind_n::other::pointer	node_pointer;
505      typedef typename _Alloc::template rebind<Leaf>	__rebind_l;
506      typedef typename __rebind_l::other::pointer	leaf_pointer;
507      typedef typename __rebind_l::other::const_pointer	leaf_const_pointer;
508      typedef typename _Alloc::template rebind<Head>	__rebind_h;
509      typedef typename __rebind_h::other::pointer	head_pointer;
510
511      typedef typename _Alloc::template rebind<Inode> __rebind_in;
512      typedef typename __rebind_in::other::pointer 	inode_pointer;
513      typedef typename Inode::iterator			inode_iterator;
514
515      node_pointer 					m_p_nd;
516
517      _CIter(node_pointer p_nd = 0) : m_p_nd(p_nd)
518      { }
519
520      _CIter(const PB_DS_CONST_ODIR_IT_C_DEC& other)
521      : m_p_nd(other.m_p_nd)
522      { }
523
524      _CIter&
525      operator=(const _CIter& other)
526      {
527	m_p_nd = other.m_p_nd;
528	return *this;
529      }
530
531      _CIter&
532      operator=(const PB_DS_CONST_ODIR_IT_C_DEC& other)
533      {
534	m_p_nd = other.m_p_nd;
535	return *this;
536      }
537
538      const_pointer
539      operator->() const
540      {
541	_GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == leaf_node);
542	return &static_cast<leaf_pointer>(m_p_nd)->value();
543      }
544
545      const_reference
546      operator*() const
547      {
548	_GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == leaf_node);
549	return static_cast<leaf_pointer>(m_p_nd)->value();
550      }
551
552      bool
553      operator==(const _CIter& other) const
554      { return m_p_nd == other.m_p_nd; }
555
556      bool
557      operator==(const PB_DS_CONST_ODIR_IT_C_DEC& other) const
558      { return m_p_nd == other.m_p_nd; }
559
560      bool
561      operator!=(const _CIter& other) const
562      { return m_p_nd != other.m_p_nd; }
563
564      bool
565      operator!=(const PB_DS_CONST_ODIR_IT_C_DEC& other) const
566      { return m_p_nd != other.m_p_nd; }
567
568      _CIter&
569      operator++()
570      {
571	inc(integral_constant<int, Is_Forward_Iterator>());
572	return *this;
573      }
574
575      _CIter
576      operator++(int)
577      {
578	_CIter ret_it(m_p_nd);
579	operator++();
580	return ret_it;
581      }
582
583      _CIter&
584      operator--()
585      {
586	dec(integral_constant<int, Is_Forward_Iterator>());
587	return *this;
588      }
589
590      _CIter
591      operator--(int)
592      {
593	_CIter ret_it(m_p_nd);
594	operator--();
595	return ret_it;
596      }
597
598    protected:
599      void
600      inc(false_type)
601      { dec(true_type()); }
602
603      void
604      inc(true_type)
605      {
606	if (m_p_nd->m_type == head_node)
607	  {
608	    m_p_nd = static_cast<head_pointer>(m_p_nd)->m_p_min;
609	    return;
610	  }
611
612	node_pointer p_y = m_p_nd->m_p_parent;
613	while (p_y->m_type != head_node && get_larger_sibling(m_p_nd) == 0)
614	  {
615	    m_p_nd = p_y;
616	    p_y = p_y->m_p_parent;
617	  }
618
619	if (p_y->m_type == head_node)
620	  {
621	    m_p_nd = p_y;
622	    return;
623	  }
624	m_p_nd = leftmost_descendant(get_larger_sibling(m_p_nd));
625      }
626
627      void
628      dec(false_type)
629      { inc(true_type()); }
630
631      void
632      dec(true_type)
633      {
634	if (m_p_nd->m_type == head_node)
635	  {
636	    m_p_nd = static_cast<head_pointer>(m_p_nd)->m_p_max;
637	    return;
638	  }
639
640	node_pointer p_y = m_p_nd->m_p_parent;
641	while (p_y->m_type != head_node && get_smaller_sibling(m_p_nd) == 0)
642	  {
643	    m_p_nd = p_y;
644	    p_y = p_y->m_p_parent;
645	  }
646
647	if (p_y->m_type == head_node)
648	  {
649	    m_p_nd = p_y;
650	    return;
651	  }
652	m_p_nd = rightmost_descendant(get_smaller_sibling(m_p_nd));
653      }
654
655      static node_pointer
656      get_larger_sibling(node_pointer p_nd)
657      {
658	inode_pointer p_parent = static_cast<inode_pointer>(p_nd->m_p_parent);
659
660	inode_iterator it = p_parent->begin();
661	while (*it != p_nd)
662	  ++it;
663
664	inode_iterator next_it = it;
665	++next_it;
666	return (next_it == p_parent->end())? 0 : *next_it;
667      }
668
669      static node_pointer
670      get_smaller_sibling(node_pointer p_nd)
671      {
672	inode_pointer p_parent = static_cast<inode_pointer>(p_nd->m_p_parent);
673
674	inode_iterator it = p_parent->begin();
675	if (*it == p_nd)
676	  return 0;
677
678	inode_iterator prev_it;
679	do
680	  {
681	    prev_it = it;
682	    ++it;
683	    if (*it == p_nd)
684	      return *prev_it;
685	  }
686	while (true);
687
688	_GLIBCXX_DEBUG_ASSERT(false);
689	return 0;
690      }
691
692      static leaf_pointer
693      leftmost_descendant(node_pointer p_nd)
694      {
695	if (p_nd->m_type == leaf_node)
696	  return static_cast<leaf_pointer>(p_nd);
697	return static_cast<inode_pointer>(p_nd)->leftmost_descendant();
698      }
699
700      static leaf_pointer
701      rightmost_descendant(node_pointer p_nd)
702      {
703	if (p_nd->m_type == leaf_node)
704	  return static_cast<leaf_pointer>(p_nd);
705	return static_cast<inode_pointer>(p_nd)->rightmost_descendant();
706      }
707    };
708
709
710    /// Iterator.
711    template<typename Node, typename Leaf, typename Head, typename Inode,
712	     bool Is_Forward_Iterator>
713    class _Iter
714    : public _CIter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
715    {
716    public:
717      typedef _CIter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
718      							base_type;
719      typedef typename base_type::allocator_type	allocator_type;
720      typedef typename base_type::type_traits		type_traits;
721      typedef typename type_traits::value_type		value_type;
722      typedef typename type_traits::pointer 		pointer;
723      typedef typename type_traits::reference 		reference;
724
725      typedef typename base_type::node_pointer		node_pointer;
726      typedef typename base_type::leaf_pointer		leaf_pointer;
727      typedef typename base_type::leaf_const_pointer	leaf_const_pointer;
728      typedef typename base_type::head_pointer		head_pointer;
729      typedef typename base_type::inode_pointer 	inode_pointer;
730
731      _Iter(node_pointer p_nd = 0)
732      : base_type(p_nd) { }
733
734      _Iter(const PB_DS_ODIR_IT_C_DEC& other)
735      : base_type(other.m_p_nd) { }
736
737      _Iter&
738      operator=(const _Iter& other)
739      {
740	base_type::m_p_nd = other.m_p_nd;
741	return *this;
742      }
743
744      _Iter&
745      operator=(const PB_DS_ODIR_IT_C_DEC& other)
746      {
747	base_type::m_p_nd = other.m_p_nd;
748	return *this;
749      }
750
751      pointer
752      operator->() const
753      {
754	_GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == leaf_node);
755	return &static_cast<leaf_pointer>(base_type::m_p_nd)->value();
756      }
757
758      reference
759      operator*() const
760      {
761	_GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == leaf_node);
762	return static_cast<leaf_pointer>(base_type::m_p_nd)->value();
763      }
764
765      _Iter&
766      operator++()
767      {
768	base_type::operator++();
769	return *this;
770      }
771
772      _Iter
773      operator++(int)
774      {
775	_Iter ret(base_type::m_p_nd);
776	operator++();
777	return ret;
778      }
779
780      _Iter&
781      operator--()
782      {
783	base_type::operator--();
784	return *this;
785      }
786
787      _Iter
788      operator--(int)
789      {
790	_Iter ret(base_type::m_p_nd);
791	operator--();
792	return ret;
793      }
794    };
795
796#undef PB_DS_CONST_ODIR_IT_C_DEC
797#undef PB_DS_ODIR_IT_C_DEC
798
799
800#define PB_DS_PAT_TRIE_NODE_CONST_ITERATOR_C_DEC \
801    _Node_citer<Node, Leaf, Head, Inode, _CIterator, Iterator, _ATraits, _Alloc>
802
803#define PB_DS_PAT_TRIE_NODE_ITERATOR_C_DEC \
804    _Node_iter<Node, Leaf, Head, Inode, _CIterator, Iterator, _ATraits, _Alloc>
805
806    /// Node const iterator.
807    template<typename Node,
808	     typename Leaf,
809	     typename Head,
810	     typename Inode,
811	     typename _CIterator,
812	     typename Iterator,
813	     typename _Alloc>
814    class _Node_citer
815    {
816    protected:
817      typedef typename _Alloc::template rebind<Node>	__rebind_n;
818      typedef typename __rebind_n::other::pointer	node_pointer;
819
820      typedef typename _Alloc::template rebind<Leaf>	__rebind_l;
821      typedef typename __rebind_l::other::pointer	leaf_pointer;
822      typedef typename __rebind_l::other::const_pointer	leaf_const_pointer;
823
824      typedef typename _Alloc::template rebind<Inode> 	__rebind_in;
825      typedef typename __rebind_in::other::pointer 	inode_pointer;
826      typedef typename __rebind_in::other::const_pointer inode_const_pointer;
827
828      typedef typename Node::a_const_pointer		a_const_pointer;
829      typedef typename Node::a_const_iterator		a_const_iterator;
830
831    private:
832      a_const_iterator
833      pref_begin() const
834      {
835	if (m_p_nd->m_type == leaf_node)
836	  {
837	    leaf_const_pointer lcp = static_cast<leaf_const_pointer>(m_p_nd);
838	    return m_p_traits->begin(m_p_traits->extract_key(lcp->value()));
839	  }
840	_GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
841	return static_cast<inode_const_pointer>(m_p_nd)->pref_b_it();
842      }
843
844      a_const_iterator
845      pref_end() const
846      {
847	if (m_p_nd->m_type == leaf_node)
848	  {
849	    leaf_const_pointer lcp = static_cast<leaf_const_pointer>(m_p_nd);
850	    return m_p_traits->end(m_p_traits->extract_key(lcp->value()));
851	  }
852	_GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
853	return static_cast<inode_const_pointer>(m_p_nd)->pref_e_it();
854      }
855
856    public:
857      typedef trivial_iterator_tag 			iterator_category;
858      typedef trivial_iterator_difference_type 		difference_type;
859      typedef typename _Alloc::size_type 		size_type;
860
861      typedef _CIterator 		       		value_type;
862      typedef value_type 				reference;
863      typedef value_type 				const_reference;
864
865      /// Metadata type.
866      typedef typename Node::metadata_type 		metadata_type;
867
868      /// Const metadata reference type.
869      typedef typename _Alloc::template rebind<metadata_type> __rebind_m;
870      typedef typename __rebind_m::other 		__rebind_ma;
871      typedef typename __rebind_ma::const_reference    metadata_const_reference;
872
873      inline
874      _Node_citer(node_pointer p_nd = 0, a_const_pointer p_traits = 0)
875      : m_p_nd(const_cast<node_pointer>(p_nd)), m_p_traits(p_traits)
876      { }
877
878      /// Subtree valid prefix.
879      std::pair<a_const_iterator, a_const_iterator>
880      valid_prefix() const
881      { return std::make_pair(pref_begin(), pref_end()); }
882
883      /// Const access; returns the __const iterator* associated with
884      /// the current leaf.
885      const_reference
886      operator*() const
887      {
888	_GLIBCXX_DEBUG_ASSERT(num_children() == 0);
889	return _CIterator(m_p_nd);
890      }
891
892      /// Metadata access.
893      metadata_const_reference
894      get_metadata() const
895      { return m_p_nd->get_metadata(); }
896
897      /// Returns the number of children in the corresponding node.
898      size_type
899      num_children() const
900      {
901	if (m_p_nd->m_type == leaf_node)
902	  return 0;
903	_GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
904	inode_pointer inp = static_cast<inode_pointer>(m_p_nd);
905	return std::distance(inp->begin(), inp->end());
906      }
907
908      /// Returns a __const node __iterator to the corresponding node's
909      /// i-th child.
910      _Node_citer
911      get_child(size_type i) const
912      {
913	_GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
914	inode_pointer inp = static_cast<inode_pointer>(m_p_nd);
915	typename Inode::iterator it = inp->begin();
916	std::advance(it, i);
917	return _Node_citer(*it, m_p_traits);
918      }
919
920      /// Compares content to a different iterator object.
921      bool
922      operator==(const _Node_citer& other) const
923      { return m_p_nd == other.m_p_nd; }
924
925      /// Compares content (negatively) to a different iterator object.
926      bool
927      operator!=(const _Node_citer& other) const
928      { return m_p_nd != other.m_p_nd; }
929
930      node_pointer 			m_p_nd;
931      a_const_pointer 			m_p_traits;
932    };
933
934
935    /// Node iterator.
936    template<typename Node,
937	     typename Leaf,
938	     typename Head,
939	     typename Inode,
940	     typename _CIterator,
941	     typename Iterator,
942	     typename _Alloc>
943    class _Node_iter
944    : public _Node_citer<Node, Leaf, Head, Inode, _CIterator, Iterator, _Alloc>
945    {
946    private:
947      typedef _Node_citer<Node, Leaf, Head, Inode,
948			  _CIterator, Iterator, _Alloc>	base_type;
949      typedef typename _Alloc::template rebind<Node>	__rebind_n;
950      typedef typename __rebind_n::other::pointer	node_pointer;
951      typedef typename base_type::inode_pointer 	inode_pointer;
952      typedef typename base_type::a_const_pointer 	a_const_pointer;
953      typedef Iterator 					iterator;
954
955    public:
956      typedef typename base_type::size_type 		size_type;
957
958      typedef Iterator 					value_type;
959      typedef value_type 				reference;
960      typedef value_type 				const_reference;
961
962      _Node_iter(node_pointer p_nd = 0, a_const_pointer p_traits = 0)
963      : base_type(p_nd, p_traits)
964      { }
965
966      /// Access; returns the iterator*  associated with the current leaf.
967      reference
968      operator*() const
969      {
970	_GLIBCXX_DEBUG_ASSERT(base_type::num_children() == 0);
971	return iterator(base_type::m_p_nd);
972      }
973
974      /// Returns a node __iterator to the corresponding node's i-th child.
975      _Node_iter
976      get_child(size_type i) const
977      {
978	_GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == i_node);
979
980	typename Inode::iterator it =
981	  static_cast<inode_pointer>(base_type::m_p_nd)->begin();
982
983	std::advance(it, i);
984	return _Node_iter(*it, base_type::m_p_traits);
985      }
986    };
987    };
988
989
990#define PB_DS_CLASS_T_DEC \
991    template<typename _ATraits, typename Metadata>
992
993#define PB_DS_CLASS_C_DEC \
994    pat_trie_base::_Inode<_ATraits, Metadata>
995
996    PB_DS_CLASS_T_DEC
997    typename PB_DS_CLASS_C_DEC::__rebind_l
998    PB_DS_CLASS_C_DEC::s_leaf_alloc;
999
1000    PB_DS_CLASS_T_DEC
1001    typename PB_DS_CLASS_C_DEC::__rebind_in
1002    PB_DS_CLASS_C_DEC::s_inode_alloc;
1003
1004    PB_DS_CLASS_T_DEC
1005    inline typename PB_DS_CLASS_C_DEC::size_type
1006    PB_DS_CLASS_C_DEC::
1007    get_pref_pos(a_const_iterator b_it, a_const_iterator e_it,
1008		 a_const_pointer p_traits) const
1009    {
1010      if (static_cast<std::size_t>(std::distance(b_it, e_it)) <= m_e_ind)
1011	return 0;
1012      std::advance(b_it, m_e_ind);
1013      return 1 + p_traits->e_pos(*b_it);
1014    }
1015
1016    PB_DS_CLASS_T_DEC
1017    PB_DS_CLASS_C_DEC::
1018    _Inode(size_type len, const a_const_iterator it)
1019    : base_type(i_node), m_e_ind(len), m_pref_b_it(it), m_pref_e_it(it)
1020    {
1021      std::advance(m_pref_e_it, m_e_ind);
1022      std::fill(m_a_p_children, m_a_p_children + arr_size,
1023		static_cast<node_pointer>(0));
1024    }
1025
1026    PB_DS_CLASS_T_DEC
1027    void
1028    PB_DS_CLASS_C_DEC::
1029    update_prefixes(a_const_pointer p_traits)
1030    {
1031      node_pointer p_first = *begin();
1032      if (p_first->m_type == leaf_node)
1033	{
1034	  leaf_const_pointer p = static_cast<leaf_const_pointer>(p_first);
1035	  m_pref_b_it = p_traits->begin(access_traits::extract_key(p->value()));
1036	}
1037      else
1038	{
1039	  inode_pointer p = static_cast<inode_pointer>(p_first);
1040	  _GLIBCXX_DEBUG_ASSERT(p_first->m_type == i_node);
1041	  m_pref_b_it = p->pref_b_it();
1042	}
1043      m_pref_e_it = m_pref_b_it;
1044      std::advance(m_pref_e_it, m_e_ind);
1045    }
1046
1047    PB_DS_CLASS_T_DEC
1048    typename PB_DS_CLASS_C_DEC::const_iterator
1049    PB_DS_CLASS_C_DEC::
1050    begin() const
1051    {
1052      typedef node_pointer_pointer pointer_type;
1053      pointer_type p = const_cast<pointer_type>(m_a_p_children);
1054      return const_iterator(p + get_begin_pos(), p + arr_size);
1055    }
1056
1057    PB_DS_CLASS_T_DEC
1058    typename PB_DS_CLASS_C_DEC::iterator
1059    PB_DS_CLASS_C_DEC::
1060    begin()
1061    {
1062      return iterator(m_a_p_children + get_begin_pos(),
1063		      m_a_p_children + arr_size);
1064    }
1065
1066    PB_DS_CLASS_T_DEC
1067    typename PB_DS_CLASS_C_DEC::const_iterator
1068    PB_DS_CLASS_C_DEC::
1069    end() const
1070    {
1071      typedef node_pointer_pointer pointer_type;
1072      pointer_type p = const_cast<pointer_type>(m_a_p_children) + arr_size;
1073      return const_iterator(p, p);
1074    }
1075
1076    PB_DS_CLASS_T_DEC
1077    typename PB_DS_CLASS_C_DEC::iterator
1078    PB_DS_CLASS_C_DEC::
1079    end()
1080    { return iterator(m_a_p_children + arr_size, m_a_p_children + arr_size); }
1081
1082    PB_DS_CLASS_T_DEC
1083    inline typename PB_DS_CLASS_C_DEC::node_pointer
1084    PB_DS_CLASS_C_DEC::
1085    get_child_node(a_const_iterator b_it, a_const_iterator e_it,
1086		   a_const_pointer p_traits)
1087    {
1088      const size_type i = get_pref_pos(b_it, e_it, p_traits);
1089      _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1090      return m_a_p_children[i];
1091    }
1092
1093    PB_DS_CLASS_T_DEC
1094    inline typename PB_DS_CLASS_C_DEC::iterator
1095    PB_DS_CLASS_C_DEC::
1096    get_child_it(a_const_iterator b_it, a_const_iterator e_it,
1097		 a_const_pointer p_traits)
1098    {
1099      const size_type i = get_pref_pos(b_it, e_it, p_traits);
1100      _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1101      _GLIBCXX_DEBUG_ASSERT(m_a_p_children[i] != 0);
1102      return iterator(m_a_p_children + i, m_a_p_children + i);
1103    }
1104
1105    PB_DS_CLASS_T_DEC
1106    inline typename PB_DS_CLASS_C_DEC::node_const_pointer
1107    PB_DS_CLASS_C_DEC::
1108    get_child_node(a_const_iterator b_it, a_const_iterator e_it,
1109		   a_const_pointer p_traits) const
1110    { return const_cast<node_pointer>(get_child_node(b_it, e_it, p_traits)); }
1111
1112    PB_DS_CLASS_T_DEC
1113    typename PB_DS_CLASS_C_DEC::node_pointer
1114    PB_DS_CLASS_C_DEC::
1115    get_lower_bound_child_node(a_const_iterator b_it, a_const_iterator e_it,
1116			       size_type checked_ind,
1117			       a_const_pointer p_traits)
1118    {
1119      if (!should_be_mine(b_it, e_it, checked_ind, p_traits))
1120	{
1121	  if (p_traits->cmp_prefixes(b_it, e_it, m_pref_b_it,
1122				     m_pref_e_it, true))
1123	    return leftmost_descendant();
1124	  return rightmost_descendant();
1125	}
1126
1127      size_type i = get_pref_pos(b_it, e_it, p_traits);
1128      _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1129
1130      if (m_a_p_children[i] != 0)
1131	return m_a_p_children[i];
1132
1133      while (++i < arr_size)
1134	if (m_a_p_children[i] != 0)
1135	  {
1136	    const node_type& __nt = m_a_p_children[i]->m_type;
1137	    node_pointer ret = m_a_p_children[i];
1138
1139	    if (__nt == leaf_node)
1140	      return ret;
1141
1142	    _GLIBCXX_DEBUG_ASSERT(__nt == i_node);
1143	    inode_pointer inp = static_cast<inode_pointer>(ret);
1144	    return inp->leftmost_descendant();
1145	  }
1146
1147      return rightmost_descendant();
1148    }
1149
1150    PB_DS_CLASS_T_DEC
1151    inline typename PB_DS_CLASS_C_DEC::node_pointer
1152    PB_DS_CLASS_C_DEC::
1153    add_child(node_pointer p_nd, a_const_iterator b_it, a_const_iterator e_it,
1154	      a_const_pointer p_traits)
1155    {
1156      const size_type i = get_pref_pos(b_it, e_it, p_traits);
1157      _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1158      if (m_a_p_children[i] == 0)
1159	{
1160	  m_a_p_children[i] = p_nd;
1161	  p_nd->m_p_parent = this;
1162	  return p_nd;
1163	}
1164      return m_a_p_children[i];
1165    }
1166
1167    PB_DS_CLASS_T_DEC
1168    typename PB_DS_CLASS_C_DEC::node_const_pointer
1169    PB_DS_CLASS_C_DEC::
1170    get_join_child(node_const_pointer p_nd,
1171		   a_const_pointer p_tr) const
1172    {
1173      node_pointer p = const_cast<node_pointer>(p_nd);
1174      return const_cast<inode_pointer>(this)->get_join_child(p, p_tr);
1175    }
1176
1177    PB_DS_CLASS_T_DEC
1178    typename PB_DS_CLASS_C_DEC::node_pointer
1179    PB_DS_CLASS_C_DEC::
1180    get_join_child(node_pointer p_nd, a_const_pointer p_traits)
1181    {
1182      size_type i;
1183      a_const_iterator b_it;
1184      a_const_iterator e_it;
1185      if (p_nd->m_type == leaf_node)
1186	{
1187	  leaf_const_pointer p = static_cast<leaf_const_pointer>(p_nd);
1188
1189	  typedef typename type_traits::key_const_reference kcr;
1190	  kcr r_key = access_traits::extract_key(p->value());
1191	  b_it = p_traits->begin(r_key);
1192	  e_it = p_traits->end(r_key);
1193	}
1194      else
1195	{
1196	  b_it = static_cast<inode_pointer>(p_nd)->pref_b_it();
1197	  e_it = static_cast<inode_pointer>(p_nd)->pref_e_it();
1198	}
1199      i = get_pref_pos(b_it, e_it, p_traits);
1200      _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1201      return m_a_p_children[i];
1202    }
1203
1204    PB_DS_CLASS_T_DEC
1205    void
1206    PB_DS_CLASS_C_DEC::
1207    remove_child(node_pointer p_nd)
1208    {
1209      size_type i = 0;
1210      for (; i < arr_size; ++i)
1211	if (m_a_p_children[i] == p_nd)
1212	  {
1213	    m_a_p_children[i] = 0;
1214	    return;
1215	  }
1216      _GLIBCXX_DEBUG_ASSERT(i != arr_size);
1217    }
1218
1219    PB_DS_CLASS_T_DEC
1220    void
1221    PB_DS_CLASS_C_DEC::
1222    remove_child(iterator it)
1223    { *it.m_p_p_cur = 0; }
1224
1225    PB_DS_CLASS_T_DEC
1226    void
1227    PB_DS_CLASS_C_DEC::
1228    replace_child(node_pointer p_nd, a_const_iterator b_it,
1229		  a_const_iterator e_it,
1230		  a_const_pointer p_traits)
1231    {
1232      const size_type i = get_pref_pos(b_it, e_it, p_traits);
1233      _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1234      m_a_p_children[i] = p_nd;
1235      p_nd->m_p_parent = this;
1236    }
1237
1238    PB_DS_CLASS_T_DEC
1239    inline typename PB_DS_CLASS_C_DEC::a_const_iterator
1240    PB_DS_CLASS_C_DEC::
1241    pref_b_it() const
1242    { return m_pref_b_it; }
1243
1244    PB_DS_CLASS_T_DEC
1245    inline typename PB_DS_CLASS_C_DEC::a_const_iterator
1246    PB_DS_CLASS_C_DEC::
1247    pref_e_it() const
1248    { return m_pref_e_it; }
1249
1250    PB_DS_CLASS_T_DEC
1251    bool
1252    PB_DS_CLASS_C_DEC::
1253    should_be_mine(a_const_iterator b_it, a_const_iterator e_it,
1254		   size_type checked_ind,
1255		   a_const_pointer p_traits) const
1256    {
1257      if (m_e_ind == 0)
1258	return true;
1259
1260      const size_type num_es = std::distance(b_it, e_it);
1261      if (num_es < m_e_ind)
1262	return false;
1263
1264      a_const_iterator key_b_it = b_it;
1265      std::advance(key_b_it, checked_ind);
1266      a_const_iterator key_e_it = b_it;
1267      std::advance(key_e_it, m_e_ind);
1268
1269      a_const_iterator value_b_it = m_pref_b_it;
1270      std::advance(value_b_it, checked_ind);
1271      a_const_iterator value_e_it = m_pref_b_it;
1272      std::advance(value_e_it, m_e_ind);
1273
1274      return p_traits->equal_prefixes(key_b_it, key_e_it, value_b_it,
1275				      value_e_it);
1276    }
1277
1278    PB_DS_CLASS_T_DEC
1279    typename PB_DS_CLASS_C_DEC::leaf_pointer
1280    PB_DS_CLASS_C_DEC::
1281    leftmost_descendant()
1282    {
1283      node_pointer p_pot = *begin();
1284      if (p_pot->m_type == leaf_node)
1285	return (static_cast<leaf_pointer>(p_pot));
1286      _GLIBCXX_DEBUG_ASSERT(p_pot->m_type == i_node);
1287      return static_cast<inode_pointer>(p_pot)->leftmost_descendant();
1288    }
1289
1290    PB_DS_CLASS_T_DEC
1291    typename PB_DS_CLASS_C_DEC::leaf_const_pointer
1292    PB_DS_CLASS_C_DEC::
1293    leftmost_descendant() const
1294    { return const_cast<inode_pointer>(this)->leftmost_descendant(); }
1295
1296    PB_DS_CLASS_T_DEC
1297    typename PB_DS_CLASS_C_DEC::leaf_pointer
1298    PB_DS_CLASS_C_DEC::
1299    rightmost_descendant()
1300    {
1301      const size_type num_children = std::distance(begin(), end());
1302      _GLIBCXX_DEBUG_ASSERT(num_children >= 2);
1303
1304      iterator it = begin();
1305      std::advance(it, num_children - 1);
1306      node_pointer p_pot =* it;
1307      if (p_pot->m_type == leaf_node)
1308	return static_cast<leaf_pointer>(p_pot);
1309      _GLIBCXX_DEBUG_ASSERT(p_pot->m_type == i_node);
1310      return static_cast<inode_pointer>(p_pot)->rightmost_descendant();
1311    }
1312
1313    PB_DS_CLASS_T_DEC
1314    typename PB_DS_CLASS_C_DEC::leaf_const_pointer
1315    PB_DS_CLASS_C_DEC::
1316    rightmost_descendant() const
1317    { return const_cast<inode_pointer>(this)->rightmost_descendant(); }
1318
1319    PB_DS_CLASS_T_DEC
1320    typename PB_DS_CLASS_C_DEC::size_type
1321    PB_DS_CLASS_C_DEC::
1322    get_begin_pos() const
1323    {
1324      size_type i = 0;
1325      for (; i < arr_size && m_a_p_children[i] == 0; ++i)
1326	;
1327      return i;
1328    }
1329
1330#ifdef _GLIBCXX_DEBUG
1331    PB_DS_CLASS_T_DEC
1332    typename PB_DS_CLASS_C_DEC::node_debug_info
1333    PB_DS_CLASS_C_DEC::
1334    assert_valid_imp(a_const_pointer p_traits,
1335		     const char* __file, int __line) const
1336    {
1337      PB_DS_DEBUG_VERIFY(base_type::m_type == i_node);
1338      PB_DS_DEBUG_VERIFY(static_cast<size_type>(std::distance(pref_b_it(), pref_e_it())) == m_e_ind);
1339      PB_DS_DEBUG_VERIFY(std::distance(begin(), end()) >= 2);
1340
1341      for (typename _Inode::const_iterator it = begin(); it != end(); ++it)
1342	{
1343	  node_const_pointer p_nd = *it;
1344	  PB_DS_DEBUG_VERIFY(p_nd->m_p_parent == this);
1345	  node_debug_info child_ret = p_nd->assert_valid_imp(p_traits,
1346							     __file, __line);
1347
1348	  PB_DS_DEBUG_VERIFY(static_cast<size_type>(std::distance(child_ret.first, child_ret.second)) >= m_e_ind);
1349	  PB_DS_DEBUG_VERIFY(should_be_mine(child_ret.first, child_ret.second, 0, p_traits));
1350	  PB_DS_DEBUG_VERIFY(get_pref_pos(child_ret.first, child_ret.second, p_traits) == static_cast<size_type>(it.m_p_p_cur - m_a_p_children));
1351	}
1352      return std::make_pair(pref_b_it(), pref_e_it());
1353    }
1354#endif
1355
1356#undef PB_DS_CLASS_T_DEC
1357#undef PB_DS_CLASS_C_DEC
1358  } // namespace detail
1359} // namespace __gnu_pbds
1360
1361#endif
1362