27 #ifndef Common_directory_h
28 #define Common_directory_h
39 #include <type_traits>
57 typedef decltype(
swap(std::declval<_Tp&>(), std::declval<_Tp&>()))
type;
65 : public
std::integral_constant<
bool, __detail::__swappable<_Tp>::value>
69 template <
bool,
class _Tp>
71 :
public std::integral_constant<bool, noexcept(swap(std::declval<_Tp&>(),
72 std::declval<_Tp&>()))>
78 :
public std::false_type
92 template <
class _Key,
class _Tp>
97 directory_entry(
int level, _Key key, _Tp
value) : level(level), key(key), value(value), isset_value(true) {}
100 os << std::setw(2) << de.
level <<
" " << de.
key;
102 os <<
"=" << de.
value;
111 template <
class _Key,
class _Tp>
121 template <
class _Key,
class _Tp>
124 return !(lhs == rhs);
127 template <
class _Key,
class _Tp>
128 inline bool operator< (const directory_entry<_Key, _Tp>& lhs,
130 if (lhs.level != rhs.level)
131 return lhs.
level < rhs.level;
132 if (lhs.key != rhs.key)
133 return lhs.key < rhs.key;
134 if (lhs.isset_value != rhs.isset_value)
135 return !lhs.isset_value;
137 return lhs.value < rhs.value;
141 template <
class _Value,
class _Compare,
class _Allocator>
148 typedef typename __alloc_traits::template rebind_alloc<__directory_node_internal>
__node_allocator;
153 :
public std::binary_function<pointer, pointer, bool> {
169 : m_value_allocator(__alloc_traits::select_on_container_copy_construction(other.m_value_allocator)),
170 entry(other.entry), children(other.children.key_comp(), other.m_value_allocator) {}
172 : m_value_allocator(alloc), entry(value), children(
pointer_compare(comp), alloc) {}
175 for (
auto &np : children)
179 std::pair<typename children_set::iterator, bool>
insert_child(pointer child) {
181 return children.insert(child);
186 for (
const auto &child : children)
194 __node_allocator __na(m_value_allocator);
195 __node_traits::destroy(__na, np);
196 __node_traits::deallocate(__na, np, 1);
207 template <
class _Tp,
class _NodePtr,
class _DiffType>
211 typedef typename std::pointer_traits<_NodePtr>::element_type
__node;
218 typedef typename std::pointer_traits<__node_pointer>::template rebind<value_type>
pointer;
229 reference
operator*()
const {
return __iters_.back().np->entry;}
232 return std::pointer_traits<pointer>::pointer_to(__iters_.back().np->entry);
236 if (__iters_.back().iter != __iters_.back().np->children.end()) {
237 __node_pointer np = *__iters_.back().iter;
241 while (!__iters_.empty()) {
242 if (__iters_.back().iter == __iters_.back().np->children.end())
245 ++__iters_.back().iter;
246 if (__iters_.back().iter == __iters_.back().np->children.end())
248 __node_pointer np = *__iters_.back().iter;
262 if (__iters_.empty())
264 else if (__iters_.back().iter == __iters_.back().np->children.begin())
267 if (__iters_.back().iter != __iters_.back().np->children.begin()) {
270 --__iters_.back().iter;
271 np = *__iters_.back().iter;
273 }
while (!np->children.empty());
287 return !(__x == __y);
291 typename __node::children_set::iterator iter) {
296 return __iters_.back().np;
299 operator bool()
const {
300 return !__iters_.empty();
304 os <<
"[directory_iterator]" << std::endl;
306 os << si.np->entry << std::endl;
315 typename __node::children_set::iterator iter)
316 : np(np), iter(iter) {}
318 typename __node::children_set::iterator
iter;
325 return !(__x == __y);
330 __node_pointer __root_ {};
341 template <
class _Key,
class _Tp,
class _Compare = std::less<_Key>,
342 class _Allocator = std::allocator<directory_entry<const _Key, _Tp> > >
364 typedef typename __alloc_traits::pointer
pointer;
378 :
public std::binary_function<value_type, value_type, bool> {
385 bool operator()(
const value_type& __x,
const value_type& __y)
const
386 {
return key_comp(__x.
key, __y.
key);}
405 noexcept(
std::is_nothrow_default_constructible<allocator_type>::
value &&
406 std::is_nothrow_default_constructible<key_compare>::
value &&
407 std::is_nothrow_copy_constructible<key_compare>::
value)
408 : m_value_compare(key_compare()) {
411 explicit directory(
const key_compare& __comp)
412 noexcept(std::is_nothrow_default_constructible<allocator_type>::value &&
413 std::is_nothrow_copy_constructible<key_compare>::value);
415 explicit directory(
const allocator_type& __a);
417 directory(
const key_compare& __comp,
const allocator_type& __a);
419 template <
class _InputIterator>
421 const key_compare& __comp = key_compare())
422 : m_value_compare(__comp) {
426 template <
class _InputIterator>
428 const key_compare& __comp,
const allocator_type& __a)
429 : m_value_allocator(__a), m_value_compare(__comp) {
433 template <
class _InputIterator>
434 directory(_InputIterator __f, _InputIterator __l,
const allocator_type& __a)
435 :
directory(__f, __l, key_compare(), __a) {}
440 noexcept(
std::is_nothrow_move_constructible<allocator_type>::
value &&
441 std::is_nothrow_move_constructible<value_compare>::
value);
444 __destroy_node(m_root);
451 __copy_assign_alloc(__d);
458 noexcept(__node_traits::propagate_on_container_move_assignment::
value &&
460 std::is_nothrow_move_assignable<allocator_type>::
value) {
462 __move_assign(__d, std::integral_constant<
bool,
463 __node_traits::propagate_on_container_move_assignment::value>());
474 return m_value_compare.key_comp;
493 reverse_iterator
rbegin() noexcept {
return reverse_iterator(end());}
494 const_reverse_iterator
rbegin() const noexcept
495 {
return const_reverse_iterator(end());}
496 reverse_iterator
rend() noexcept {
return reverse_iterator(begin());}
497 const_reverse_iterator
rend() const noexcept
498 {
return const_reverse_iterator(begin());}
500 bool empty() const noexcept {
return m_root ==
nullptr; }
502 size_type
size() const noexcept {
503 return m_root ? m_root->size() : 0;
507 {
return __node_traits::max_size(m_value_allocator); }
509 std::pair<iterator, bool>
510 insert(
const std::vector<key_type> &keys,
const mapped_type &val) {
511 assert(!keys.empty());
512 std::pair<iterator, bool> ret;
515 m_root = __create_node();
516 __node *node = m_root;
517 for (
size_t i=0; i<keys.size(); ++i) {
518 __node child(value_type(i+1, keys[i]), m_value_compare, m_value_allocator);
519 auto child_iter = node->
children.find(&child);
520 if (child_iter == node->
children.end()) {
521 if (i == keys.size()-1) {
523 child.
entry.set_value(val);
525 __node *new_node = __create_node(child);
527 ret.first.push(node, node->
insert_child(new_node).first);
531 ret.first.push(node, child_iter);
538 template <
class InputIterator>
539 void insert(const_iterator pos, InputIterator first, InputIterator last);
541 template <
class InputIterator>
542 void insert(InputIterator first, InputIterator last);
546 __destroy_node(m_root);
553 (!__node_traits::propagate_on_container_swap::value ||
557 if (keys.empty() || !m_root)
561 for (
auto key_iter = keys.begin(); key_iter != keys.end(); ++key_iter) {
562 __node child(value_type(0, *key_iter), m_value_compare, m_value_allocator);
563 auto child_iter = np->children.find(&child);
564 if (child_iter == np->children.end())
566 iter.
push(np, child_iter);
569 iter.
push(np, np->children.begin());
574 if (keys.empty() || !m_root)
578 for (
auto key_iter = keys.begin(); key_iter != keys.end(); ++key_iter) {
579 __node child(value_type(0, *key_iter), m_value_compare, m_value_allocator);
580 auto child_iter = np->children.find(&child);
581 if (child_iter == np->children.end())
583 iter.
push(np, child_iter);
586 iter.
push(np, np->children.begin());
598 __node_pointer __create_node();
600 __node_pointer __create_node(__node &other);
602 __node_pointer __create_node(value_type &
value);
604 template <
class ..._Args>
605 __node_pointer __create_node(_Args&& ...__args);
607 void __destroy_node(__node *np);
610 { __copy_assign_alloc(__d, std::integral_constant<
bool,
611 __node_traits::propagate_on_container_copy_assignment::value>());}
618 noexcept(!__node_traits::propagate_on_container_move_assignment::value ||
619 std::is_nothrow_move_assignable<__node_allocator>::value) {
620 __move_assign_alloc(__d, std::integral_constant<
bool,
621 __node_traits::propagate_on_container_move_assignment::value>());
625 noexcept(
std::is_nothrow_move_assignable<allocator_type>::
value)
632 std::is_nothrow_move_assignable<allocator_type>::
value) {
633 __destroy_node(m_root);
635 __move_assign_alloc(__d);
636 m_value_compare = std::move(m_value_compare);
641 __move_assign(__d, std::true_type());
643 m_value_compare = std::move(m_value_compare);
656 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
658 noexcept(std::is_nothrow_default_constructible<allocator_type>::value &&
659 std::is_nothrow_copy_constructible<key_compare>::value)
660 : m_value_compare(__comp) {
663 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
665 : m_value_allocator(__a), m_value_compare(key_compare()) {
668 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
670 const allocator_type& __a)
671 : m_value_allocator(__a), m_value_compare(__comp) {
674 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
676 : m_value_allocator(__alloc_traits::select_on_container_copy_construction(__d.m_value_allocator)),
677 m_value_compare(__d.value_comp()) {
681 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
683 noexcept(
std::is_nothrow_move_constructible<allocator_type>::value &&
685 : m_root(__d.release_root()),
686 m_value_allocator(
std::move(__d.m_value_allocator)),
687 m_value_compare(
std::move(__d.m_value_compare)) {
691 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
692 template <
class _InputIterator>
694 __node_pointer parent;
702 m_root = __create_node();
708 if (__f->level == 0 && parent->entry.level == 0)
711 size_t previous_level = __f->level;
712 __node_pointer previous_node {};
714 for ( ; __f != __l; ++__f) {
716 if (__f->level < previous_level) {
717 parent = parent->parent;
721 else if (__f->level > previous_level && previous_node)
722 parent = previous_node;
724 __node child(*__f, m_value_compare, m_value_allocator);
725 auto child_iter = parent->children.find(&child);
726 if (child_iter == parent->children.end()) {
727 __node *new_node = __create_node(child);
728 new_node->
entry.level = parent->entry.level + 1;
729 parent->insert_child(new_node);
730 previous_node = new_node;
733 (*child_iter)->
entry.value = __f->value;
734 previous_node = *child_iter;
737 previous_level = __f->level;
741 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
744 (!__node_traits::propagate_on_container_swap::value ||
748 swap(m_root, __d.m_root);
749 swap(m_value_compare, __d.m_value_compare);
750 swap(m_value_allocator, __d.m_value_allocator);
754 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
755 template <
class _InputIterator>
764 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
767 __node_allocator __na(m_value_allocator);
769 = __node_traits::allocate(__na, 1);
770 __node_traits::construct(__na, node, m_value_compare, m_value_allocator);
775 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
778 __node_allocator __na(m_value_allocator);
780 = __node_traits::allocate(__na, 1);
781 __node_traits::construct(__na, node, other);
785 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
786 typename directory<_Key, _Tp, _Compare, _Allocator>::__node_pointer
788 __node_allocator __na(m_value_allocator);
789 typename directory<_Key, _Tp, _Compare, _Allocator>::__node_pointer node
790 = __node_traits::allocate(__na, 1);
791 __node_traits::construct(__na, node, value, m_value_compare, m_value_allocator);
795 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
796 template <
class ..._Args>
797 typename directory<_Key, _Tp, _Compare, _Allocator>::__node_pointer
799 __node_allocator __na(m_value_allocator);
801 = __node_traits::allocate(__na, 1);
802 __node_traits::construct(__na, node, std::forward<_Args>(__args)...);
806 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
809 __node_allocator __na(m_value_allocator);
810 __node_traits::destroy(__na, np);
811 __node_traits::deallocate(__na, np, 1);
815 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
823 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
828 return !(__x == __y);
831 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
834 operator< (const directory<_Key, _Tp, _Compare, _Allocator>& __x,
837 auto iter_x = __x.
begin();
838 auto iter_y = __y.begin();
839 while (iter_x != __x.end() && iter_y != __y.end()) {
840 if (*iter_x != *iter_y)
841 return *iter_x < *iter_y;
845 if (iter_x == __x.end())
846 return iter_y != __y.end();
850 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
858 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
866 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
868 bool operator<=(const directory<_Key, _Tp, _Compare, _Allocator>& __x,
874 template <
class _Key,
class _Tp,
class _Compare,
class _Allocator>
878 noexcept(noexcept(__x.swap(__y)))
887 #endif // Common_directory_h
__directory_node_internal(_Compare &comp, _Allocator &alloc)
pointer_compare(_Compare c)
friend bool operator!=(const __directory_iterator &__x, const __directory_iterator &__y)
__node::pointer release_root()
reference operator*() const
friend std::ostream & operator<<(std::ostream &os, const __directory_iterator &di)
directory_entry(int level, _Key key, _Tp value)
directory & operator=(const directory &__d)
void push(__node_pointer np, typename __node::children_set::iterator iter)
__directory_node_internal()
iterator begin() noexcept
__alloc_traits::template rebind_alloc< __directory_node_internal > __node_allocator
value_type & reference
Reference to value type.
__directory_node_internal(const __directory_node_internal &other)
directory(_InputIterator __f, _InputIterator __l, const key_compare &__comp, const allocator_type &__a)
std::allocator_traits< __node_allocator > __node_traits
~__directory_node_internal()
void __destroy_node(__node *np)
bool operator()(const value_type &__x, const value_type &__y) const
void __copy_assign_alloc(const directory &__d, std::false_type)
const_reverse_iterator rend() const noexcept
__directory_iterator & operator++()
_Allocator allocator_type
Memory allocator type.
directory(_InputIterator __f, _InputIterator __l, const key_compare &__comp=key_compare())
__node::children_set::iterator iter
directory_entry< const key_type, mapped_type > value_type
Value type.
std::allocator_traits< allocator_type > __alloc_traits
std::reverse_iterator< const_iterator > const_reverse_iterator
void swap(directory< _Key, _Tp, _Compare, _Allocator > &__x, directory< _Key, _Tp, _Compare, _Allocator > &__y) noexcept(noexcept(__x.swap(__y)))
const value_type & const_reference
Const reference to value type.
std::bidirectional_iterator_tag iterator_category
void __destroy_node(pointer np)
const_iterator find(const std::vector< key_type > &keys) const
std::pair< typename children_set::iterator, bool > insert_child(pointer child)
decltype(swap(std::declval< _Tp & >(), std::declval< _Tp & >())) typedef type
__node_pointer __create_node()
std::pointer_traits< _NodePtr >::element_type __node
key_compare key_comp() const
Returns a copy of the key comparison object from which the container was constructed.
__alloc_traits::template rebind_alloc< __node > __node_allocator
Directory container class.
friend bool operator==(const __directory_iterator &__x, const __directory_iterator &__y)
bool empty() const noexcept
void __move_assign(directory &__d, std::false_type)
__directory_node_internal * pointer
directory_entry(int level, _Key key)
const_iterator end() const noexcept
__alloc_traits::pointer pointer
__alloc_traits::size_type size_type
std::pair< iterator, bool > insert(const std::vector< key_type > &keys, const mapped_type &val)
__directory_iterator(__node_pointer root, __node_pointer np)
void __move_assign(directory &__d, std::true_type) noexcept(std::is_nothrow_move_assignable< value_compare >::value &&std::is_nothrow_move_assignable< allocator_type >::value)
__alloc_traits::const_pointer const_pointer
bool operator==(const directory_entry< _Key, _Tp > &lhs, const directory_entry< _Key, _Tp > &rhs)
__alloc_traits::difference_type difference_type
__directory_iterator() noexcept
reverse_iterator rend() noexcept
bool operator!=(const directory_entry< _Key, _Tp > &lhs, const directory_entry< _Key, _Tp > &rhs)
std::reverse_iterator< iterator > reverse_iterator
friend std::ostream & operator<<(std::ostream &os, const directory_entry &de)
bool operator>=(const directory< _Key, _Tp, _Compare, _Allocator > &__x, const directory< _Key, _Tp, _Compare, _Allocator > &__y)
_Tp mapped_type
Mapped value type.
__node_traits::pointer __node_pointer
_DiffType difference_type
const_iterator begin() const noexcept
value_compare m_value_compare
bool operator()(const pointer __x, const pointer __y) const
void __copy_assign_alloc(const directory &__d)
std::pointer_traits< __node_pointer >::template rebind< value_type > pointer
size_type max_size() const noexcept
iterator find(const std::vector< key_type > &keys)
bool equal(double a, double b)
Compare doubles that may have been serialized and unserialized.
allocator_type m_value_allocator
__subdirectory_iterator(__node_pointer np, typename __node::children_set::iterator iter)
__directory_iterator(__node_pointer root) noexcept
void swap(directory &__d) noexcept(__is_nothrow_swappable< value_compare >::value &&(!__node_traits::propagate_on_container_swap::value||__is_nothrow_swappable< __node_allocator >::value))
value_compare(key_compare c)
__directory_iterator operator++(int)
directory(_InputIterator __f, _InputIterator __l, const allocator_type &__a)
pointer operator->() const
std::allocator_traits< _Allocator > __alloc_traits
std::allocator_traits< __node_allocator > __node_traits
__directory_node_internal(_Value value, _Compare &comp, _Allocator &alloc)
Ordering relation on value_type.
reverse_iterator rbegin() noexcept
void __copy_assign_alloc(const directory &__d, std::true_type)
std::vector< __subdirectory_iterator > __iters_
size_type size() const noexcept
value_compare value_comp() const
Returns an object of type #value_compare constructed from the key comparison object.
std::set< pointer, pointer_compare, _Allocator > children_set
const_reverse_iterator rbegin() const noexcept
void __move_assign_alloc(directory &__d, std::true_type) noexcept(std::is_nothrow_move_assignable< allocator_type >::value)
_Allocator m_value_allocator
void __move_assign_alloc(directory &__d, std::false_type) noexcept
__directory_iterator & operator--()
bool operator>(const directory< _Key, _Tp, _Compare, _Allocator > &__x, const directory< _Key, _Tp, _Compare, _Allocator > &__y)
__node_traits::pointer __node_const_pointer
void __move_assign_alloc(directory &__d) noexcept(!__node_traits::propagate_on_container_move_assignment::value||std::is_nothrow_move_assignable< __node_allocator >::value)
__directory_iterator & operator--(int)
friend bool operator!=(const __subdirectory_iterator &__x, const __subdirectory_iterator &__y)
directory & operator=(directory &&__d) noexcept(__node_traits::propagate_on_container_move_assignment::value &&std::is_nothrow_move_assignable< value_compare >::value &&std::is_nothrow_move_assignable< allocator_type >::value)
__directory_node_internal< value_type, value_compare, allocator_type > __node
friend bool operator==(const __subdirectory_iterator &__x, const __subdirectory_iterator &__y)
directory() noexcept(std::is_nothrow_default_constructible< allocator_type >::value &&std::is_nothrow_default_constructible< key_compare >::value &&std::is_nothrow_copy_constructible< key_compare >::value)
Default constructor.
_Compare key_compare
Key comparison type
size_t size() const noexcept