Advertisement
sp2danny

StringMap.hpp

Nov 26th, 2015
209
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 21.47 KB | None | 0 0
  1.  
  2. #ifndef LIB_STRING_MAP_H
  3. #define LIB_STRING_MAP_H
  4.  
  5. #include <string>
  6. #include <utility>
  7. #include <iterator>
  8. #include <cassert>
  9. #include <algorithm>
  10. #include <functional>
  11. #include <utility>
  12. #include <limits>
  13. #include <stdexcept>
  14.  
  15. namespace lib
  16. {
  17.  
  18.     namespace detail
  19.     {
  20.         struct range
  21.         {
  22.             constexpr range(std::size_t sz) : b(0), e(sz) {}
  23.             constexpr range(std::size_t b, std::size_t e) : b(b), e(e) {}
  24.             struct iterator
  25.             {
  26.                 iterator& operator++() { ++i; return *this; }
  27.                 iterator operator++(int) { auto tmp = *this; ++i; return tmp; }
  28.                 iterator& operator--() { --i; return *this; }
  29.                 iterator operator--(int) { auto tmp = *this; --i; return tmp; }
  30.                 bool operator==(iterator other) const { return i==other.i; }
  31.                 bool operator!=(iterator other) const { return i!=other.i; }
  32.                 std::size_t operator*() const { return i; };
  33.                 std::size_t i;
  34.             };
  35.             std::size_t b, e;
  36.             iterator begin() const { return {b}; }
  37.             iterator end()   const { return {e}; }
  38.         };
  39.         static int ival(char c)
  40.         {
  41.             union X {
  42.                 unsigned char uc;
  43.                 char c;
  44.             } x;
  45.             x.c = c;
  46.             return x.uc;
  47.         }
  48.     }
  49.  
  50.     static constexpr detail::range knodes = detail::range(1,256); // key nodes
  51.     static constexpr detail::range anodes = detail::range(0,256); // all nodes
  52.  
  53.     template<
  54.         typename T,                               // this is the mapped type
  55.         typename Alloc = std::allocator<T>        // allocator, need to implement rebind
  56.     >
  57.     class StringMap
  58.     {
  59.         struct TreeElem;
  60.     public:
  61.         StringMap() noexcept;
  62.         StringMap(const StringMap&);
  63.         StringMap(StringMap&&) noexcept;
  64.         StringMap& operator=(const StringMap&);
  65.         StringMap& operator=(StringMap&&) noexcept;
  66.         ~StringMap();
  67.  
  68.         void swap(StringMap&) noexcept;
  69.         void swap(StringMap&&) noexcept;
  70.  
  71.         struct iterator;
  72.         struct const_iterator;
  73.  
  74.         typedef std::string key_type;
  75.         typedef T mapped_type;
  76.         typedef T& reference;
  77.         typedef T* pointer;
  78.  
  79.     private:
  80.         struct iter_core
  81.         {
  82.             std::string key() const;
  83.             void nxt();
  84.             TreeElem* node;
  85.             bool eq(const iter_core& other) const;
  86.         };
  87.  
  88.     public:
  89.  
  90.         struct const_iterator :
  91.             std::iterator<std::forward_iterator_tag,const_iterator>,
  92.             private iter_core
  93.         {
  94.             std::string key() const; // O(log(n))
  95.             const T& value() const; // O(1)
  96.             const_iterator() { this->node = nullptr; }
  97.             const_iterator& operator++() { this->nxt(); return *this; }
  98.             const const_iterator operator*() { return *this; }
  99.             const const_iterator* operator->() { return this; }
  100.             const_iterator operator++(int) { const_iterator tmp = *this; this->nxt(); return tmp; }
  101.             bool operator==(const const_iterator& other) const { return this->eq(other); }
  102.             bool operator!=(const const_iterator& other) const { return ! this->eq(other); }
  103.         private:
  104.             const_iterator(TreeElem* p) { this->node = p; }
  105.         friend
  106.             class StringMap;
  107.         friend
  108.             struct iterator;
  109.         };
  110.  
  111.         struct iterator :
  112.             std::iterator<std::forward_iterator_tag,iterator>,
  113.             private iter_core
  114.         {
  115.             std::string key() const; // O(log(n))
  116.             T& value() const; // O(1)
  117.             iterator() { this->node = nullptr; }
  118.             iterator& operator++() { this->nxt(); return *this; }
  119.             iterator operator*() { return *this; }
  120.             iterator* operator->() { return this; }
  121.             iterator operator++(int) { iterator tmp = *this; this->nxt(); return tmp; }
  122.             bool operator==(const iterator& other) const { return this->eq(other); }
  123.             bool operator!=(const iterator& other) const { return ! this->eq(other); }
  124.             operator const_iterator() { return {this->node}; }
  125.         private:
  126.             iterator(TreeElem* p) { this->node = p; }
  127.         friend
  128.             class StringMap;
  129.         };
  130.  
  131.         typedef iterator value_type;
  132.         typedef const_iterator const_value_type;
  133.  
  134.         iterator begin();
  135.         iterator end();
  136.  
  137.         const_iterator begin() const;
  138.         const_iterator end() const;
  139.         const_iterator cbegin() const { return begin(); }
  140.         const_iterator cend() const { return end(); }
  141.  
  142.         T& operator[](const std::string&);
  143.  
  144.         T& at(const std::string&);
  145.         const T& at(const std::string&) const;
  146.  
  147.         iterator find(const std::string&);
  148.         const_iterator find(const std::string&) const;
  149.  
  150.         std::size_t count(const std::string&) const;
  151.  
  152.         iterator lower_bound(const std::string& key);
  153.         const_iterator lower_bound(const std::string& key) const;
  154.  
  155.         iterator upper_bound(const std::string& key);
  156.         const_iterator upper_bound(const std::string& key) const;
  157.  
  158.         std::pair< iterator, iterator > equal_range( const std::string& key );
  159.         std::pair< const_iterator, const_iterator > equal_range( const std::string& key ) const;
  160.  
  161.         std::size_t size() const { return sz; }
  162.         bool empty() const { return !sz; }
  163.  
  164.         static std::size_t max_size() noexcept { return std::numeric_limits<std::size_t>::max(); }
  165.  
  166.         typedef std::pair<iterator,bool> insert_result_type;
  167.  
  168.         insert_result_type insert(const std::string&, const T&);
  169.         insert_result_type insert(const std::string&, T&&);
  170.  
  171.         template<typename... Args>
  172.         insert_result_type emplace(const std::string&, Args&&...);
  173.  
  174.         template<typename... Args>
  175.         insert_result_type try_emplace(const std::string& key, Args&&... args)
  176.             { return emplace(key,std::forward<Args>(args)...); } // emplace already works like that for StringMap
  177.  
  178.         insert_result_type insert_or_assign(const std::string&, const T&);
  179.         insert_result_type insert_or_assign(const std::string&, T&&);
  180.  
  181.         iterator erase(iterator);
  182.         bool erase(const std::string&);
  183.         iterator erase(iterator,iterator);
  184.  
  185.         void clear();
  186.  
  187.         void debugprint(std::ostream&) const;
  188.  
  189.         int compare(const StringMap&) const;
  190.  
  191.     private:
  192.  
  193.         struct TreeElem
  194.         {
  195.             T* leaf;
  196.             TreeElem* nodes[256];
  197.             TreeElem* nxt();
  198.         };
  199.  
  200.         Alloc val_alloc;
  201.         mutable typename Alloc::template rebind<TreeElem>::other node_alloc;
  202.  
  203.         std::size_t sz;
  204.  
  205.         mutable TreeElem sentinel;
  206.  
  207.         void recursive_clear_nodes( TreeElem* );
  208.  
  209.         TreeElem* make_node( bool clear=true ) const;
  210.         template<typename... Args>
  211.         void make_val( TreeElem*, Args&&... );
  212.         void del_val( TreeElem* );
  213.         void del_node( TreeElem* );
  214.  
  215.         TreeElem* lookup(const std::string&) const;
  216.         TreeElem* create(const std::string&) const;
  217.  
  218.     };
  219.  
  220.     template<typename T,typename Alloc>
  221.     StringMap<T,Alloc>::StringMap() noexcept
  222.     {
  223.         for( auto i : anodes )
  224.             sentinel.nodes[i] = nullptr;
  225.         sentinel.leaf = nullptr;
  226.         sz = 0;
  227.     }
  228.  
  229.     template<typename T,typename Alloc>
  230.     StringMap<T,Alloc>::StringMap(const StringMap& other)
  231.         : StringMap()
  232.     {
  233.         (*this) = other;
  234.     }
  235.  
  236.     template<typename T,typename Alloc>
  237.     StringMap<T,Alloc>::StringMap(StringMap&& other) noexcept
  238.         : StringMap()
  239.     {
  240.         swap(other);
  241.     }
  242.  
  243.     template<typename T,typename Alloc>
  244.     auto StringMap<T,Alloc>::operator=(const StringMap& other) -> StringMap&
  245.     {
  246.         clear();
  247.  
  248.         std::function<void(const TreeElem*,TreeElem*)> cpy = [&](const TreeElem* src, TreeElem* dst) -> void
  249.         {
  250.             if( src->leaf )
  251.             {
  252.                 make_val( dst, *src->leaf );
  253.                 ++sz;
  254.             } else {
  255.                 dst->leaf = nullptr;
  256.             }
  257.             for( auto i : knodes )
  258.             {
  259.                 if( src->nodes[i] )
  260.                 {
  261.                     dst->nodes[i] = make_node(false);
  262.                     dst->nodes[i]->nodes[0] = dst;
  263.                     cpy( src->nodes[i], dst->nodes[i] );
  264.                 } else {
  265.                     dst->nodes[i] = nullptr;
  266.                 }
  267.             }
  268.         };
  269.  
  270.         cpy( &other.sentinel, &sentinel );
  271.         return *this;
  272.     }
  273.  
  274.     template<typename T,typename Alloc>
  275.     auto StringMap<T,Alloc>::operator=(StringMap&& other) noexcept -> StringMap&
  276.     {
  277.         swap(other);
  278.         return *this;
  279.     }
  280.  
  281.     template<typename T,typename Alloc>
  282.     void StringMap<T,Alloc>::swap(StringMap& other) noexcept
  283.     {
  284.         using std::swap;
  285.         swap( sentinel.leaf, other.sentinel.leaf );
  286.         for( auto i : knodes )
  287.         {
  288.             swap( sentinel.nodes[i], other.sentinel.nodes[i] );
  289.             if( sentinel.nodes[i] )
  290.                 sentinel.nodes[i]->nodes[0] = &sentinel;
  291.             if( other.sentinel.nodes[i] )
  292.                 other.sentinel.nodes[i]->nodes[0] = &other.sentinel;
  293.         }
  294.         swap( val_alloc, other.val_alloc );
  295.         swap( node_alloc, other.node_alloc );
  296.     }
  297.  
  298.     template<typename T,typename Alloc>
  299.     void StringMap<T,Alloc>::swap(StringMap&& other) noexcept
  300.     {
  301.         swap(other);
  302.     }
  303.  
  304.     template<typename T,typename Alloc>
  305.     StringMap<T,Alloc>::~StringMap()
  306.     {
  307.         clear();
  308.     }
  309.  
  310.     template<typename T,typename Alloc>
  311.     auto StringMap<T,Alloc>::iter_core::key() const -> std::string
  312.     {
  313.         std::string res;
  314.         TreeElem* p = node;
  315.         while( true )
  316.         {
  317.             TreeElem* par = p->nodes[0];
  318.             if(!par) break;
  319.             for( auto i : knodes )
  320.             {
  321.                 if( par->nodes[i] == p )
  322.                 {
  323.                     res += (char) i;
  324.                     break;
  325.                 }
  326.             }
  327.             p = par;
  328.         }
  329.         std::reverse( res.begin(), res.end() );
  330.         return res;
  331.     }
  332.  
  333.     template<typename T,typename Alloc>
  334.     auto StringMap<T,Alloc>::iterator::key() const -> std::string
  335.     {
  336.         return iter_core::key();
  337.     }
  338.  
  339.     template<typename T,typename Alloc>
  340.     auto StringMap<T,Alloc>::iterator::value() const -> T&
  341.     {
  342.         assert(this->node && this->node->leaf);
  343.         return *this->node->leaf;
  344.     }
  345.  
  346.     template<typename T,typename Alloc>
  347.     auto StringMap<T,Alloc>::const_iterator::key() const -> std::string
  348.     {
  349.         return iter_core::key();
  350.     }
  351.  
  352.     template<typename T,typename Alloc>
  353.     auto StringMap<T,Alloc>::const_iterator::value() const -> const T&
  354.     {
  355.         assert(this->node && this->node->leaf);
  356.         return *this->node->leaf;
  357.     }
  358.  
  359.     template<typename T,typename Alloc>
  360.     auto StringMap<T,Alloc>::TreeElem::nxt() -> TreeElem*
  361.     {
  362.         for( auto i : knodes )
  363.         {
  364.             if( nodes[i] )
  365.                 return nodes[i];
  366.         }
  367.         TreeElem* from = this;
  368.         TreeElem* node = nodes[0];
  369.         while(true)
  370.         {
  371.             if(!node) return nullptr;
  372.             size_t i;
  373.             for( i=knodes.b; i<knodes.e; ++i )
  374.             {
  375.                 if( node->nodes[i] == from )
  376.                     break;
  377.             }
  378.             if( i<256 )
  379.             {
  380.                 for( ++i; i<knodes.e; ++i )
  381.                 {
  382.                     if( node->nodes[i] )
  383.                         return node->nodes[i];
  384.                 }
  385.             }
  386.             from = node;
  387.             node = node->nodes[0];
  388.         }
  389.     }
  390.  
  391.     template<typename T,typename Alloc>
  392.     auto StringMap<T,Alloc>::iter_core::nxt() -> void
  393.     {
  394.         if(node) while(true)
  395.         {
  396.             node = node->nxt();
  397.             if(!node) break;
  398.             if(node->leaf) break;
  399.         }
  400.     }
  401.  
  402.     template<typename T,typename Alloc>
  403.     bool StringMap<T,Alloc>::iter_core::eq(const iter_core& other) const
  404.     {
  405.         return node == other.node;
  406.     }
  407.  
  408.     template<typename T,typename Alloc>
  409.     auto StringMap<T,Alloc>::begin() -> iterator
  410.     {
  411.         TreeElem* p = &sentinel;
  412.         while(true)
  413.         {
  414.             if(!p) break;
  415.             if(p->leaf) break;
  416.             p = p->nxt();
  417.         }
  418.         return {p};
  419.     }
  420.  
  421.     template<typename T,typename Alloc>
  422.     auto StringMap<T,Alloc>::end() -> iterator
  423.     {
  424.         return {nullptr};
  425.     }
  426.  
  427.     template<typename T,typename Alloc>
  428.     auto StringMap<T,Alloc>::begin() const -> const_iterator
  429.     {
  430.         TreeElem* p = (TreeElem*)&sentinel;
  431.         while(true)
  432.         {
  433.             if(!p) break;
  434.             if(p->leaf) break;
  435.             p = p->nxt();
  436.         }
  437.         return {p};
  438.     }
  439.  
  440.     template<typename T,typename Alloc>
  441.     auto StringMap<T,Alloc>::end() const -> const_iterator
  442.     {
  443.         return {nullptr};
  444.     }
  445.  
  446.     template<typename T,typename Alloc>
  447.     auto StringMap<T,Alloc>::lookup(const std::string& key) const -> TreeElem*
  448.     {
  449.         int i,n = key.size();
  450.         assert(n);
  451.         const TreeElem* p = &sentinel;
  452.         for(i=0;i<n;++i)
  453.         {
  454.             int c = detail::ival(key[i]);
  455.             assert(c);
  456.             if( p->nodes[c] )
  457.             {
  458.                 p = p->nodes[c];
  459.             } else {
  460.                 return nullptr;
  461.             }
  462.         }
  463.         return (TreeElem*)p;
  464.     }
  465.  
  466.     template<typename T,typename Alloc>
  467.     auto StringMap<T,Alloc>::create(const std::string& key) const -> TreeElem*
  468.     {
  469.         int i,n = key.size();
  470.         assert(n);
  471.         TreeElem* p = &sentinel;
  472.         for(i=0;i<n;++i)
  473.         {
  474.             int c = detail::ival(key[i]);
  475.             assert(c);
  476.             if( p->nodes[c] )
  477.             {
  478.                 p = p->nodes[c];
  479.             } else {
  480.                 TreeElem* nn = make_node();
  481.                 nn->nodes[0] = p;
  482.                 p->nodes[c] = nn;
  483.                 p = nn;
  484.             }
  485.         }
  486.         return p;
  487.     }
  488.  
  489.     template<typename T,typename Alloc>
  490.     T& StringMap<T,Alloc>::operator[](const std::string& key)
  491.     {
  492.         TreeElem* p = create(key);
  493.         if( ! p->leaf )
  494.         {
  495.             make_val( p );
  496.             ++sz;
  497.         }
  498.         return *p->leaf;
  499.     }
  500.  
  501.     template<typename T,typename Alloc>
  502.     auto StringMap<T,Alloc>::at(const std::string& key) -> T&
  503.     {
  504.         TreeElem* p = lookup(key);
  505.         if( p && p->leaf )
  506.             return *p->leaf;
  507.         else
  508.             throw std::out_of_range("key not found");
  509.     }
  510.  
  511.     template<typename T,typename Alloc>
  512.     auto StringMap<T,Alloc>::at(const std::string& key) const -> const T&
  513.     {
  514.         TreeElem* p = lookup(key);
  515.         if( p && p->leaf )
  516.             return *p->leaf;
  517.         else
  518.             throw std::out_of_range("key not found");
  519.     }
  520.  
  521.     template<typename T,typename Alloc>
  522.     auto StringMap<T,Alloc>::find(const std::string& key) -> iterator
  523.     {
  524.         TreeElem* p = lookup(key);
  525.         if( p && p->leaf )
  526.             return {p};
  527.         else
  528.             return {nullptr};
  529.     }
  530.  
  531.     template<typename T,typename Alloc>
  532.     auto StringMap<T,Alloc>::find(const std::string& key) const -> const_iterator
  533.     {
  534.         TreeElem* p = lookup(key);
  535.         if( p && p->leaf )
  536.             return {p};
  537.         else
  538.             return {nullptr};
  539.     }
  540.  
  541.     template<typename T,typename Alloc>
  542.     std::size_t StringMap<T,Alloc>::count(const std::string& key) const
  543.     {
  544.         TreeElem* p = lookup(key);
  545.         if( p && p->leaf )
  546.             return 1;
  547.         else
  548.             return 0;
  549.     }
  550.  
  551.     template<typename T,typename Alloc>
  552.     auto StringMap<T,Alloc>::lower_bound(const std::string& key) -> iterator
  553.     {
  554.         TreeElem* p = create(key);
  555.         iterator i = {p};
  556.         if(!p->leaf)
  557.             ++i;
  558.         return i;
  559.     }
  560.  
  561.     template<typename T,typename Alloc>
  562.     auto StringMap<T,Alloc>::lower_bound(const std::string& key) const -> const_iterator
  563.     {
  564.         TreeElem* p = create(key);
  565.         const_iterator i = {p};
  566.         if(!p->leaf)
  567.             ++i;
  568.         return i;
  569.     }
  570.  
  571.     template<typename T,typename Alloc>
  572.     auto StringMap<T,Alloc>::upper_bound(const std::string& key) -> iterator
  573.     {
  574.         TreeElem* p = create(key);
  575.         iterator i = {p};
  576.         ++i;
  577.         return i;
  578.     }
  579.  
  580.     template<typename T,typename Alloc>
  581.     auto StringMap<T,Alloc>::upper_bound(const std::string& key) const -> const_iterator
  582.     {
  583.         TreeElem* p = create(key);
  584.         const_iterator i = {p};
  585.         ++i;
  586.         return i;
  587.     }
  588.  
  589.     template<typename T,typename Alloc>
  590.     auto StringMap<T,Alloc>::equal_range( const std::string& key ) -> std::pair< iterator, iterator >
  591.     {
  592.         std::pair< iterator, iterator > result;
  593.         TreeElem* p = create(key);
  594.         iterator i = {p};
  595.         if(p->leaf)
  596.         {
  597.             result.first  = i;
  598.             result.second = ++i;
  599.         } else {
  600.             result.first  = ++i;
  601.             result.second = i;
  602.         }
  603.         return result;
  604.     }
  605.  
  606.     template<typename T,typename Alloc>
  607.     auto StringMap<T,Alloc>::equal_range( const std::string& key ) const
  608.         -> std::pair< const_iterator, const_iterator >
  609.     {
  610.         std::pair< const_iterator, const_iterator > result;
  611.         TreeElem* p = create(key);
  612.         const_iterator i = {p};
  613.         if(p->leaf)
  614.         {
  615.             result.first  = i;
  616.             result.second = ++i;
  617.         } else {
  618.             result.first  = ++i;
  619.             result.second = i;
  620.         }
  621.         return result;
  622.     }
  623.  
  624.  
  625.     template<typename T,typename Alloc>
  626.     auto StringMap<T,Alloc>::insert(const std::string& key,const T& val) -> insert_result_type
  627.     {
  628.         TreeElem* p = create(key);
  629.         if( p->leaf )
  630.         {
  631.             return make_pair( iterator{p}, false );
  632.         } else {
  633.             make_val( p, val );
  634.             ++sz;
  635.             return make_pair( iterator{p}, true );
  636.         }
  637.     }
  638.  
  639.     template<typename T,typename Alloc>
  640.     auto StringMap<T,Alloc>::insert(const std::string& key,T&& val) -> insert_result_type
  641.     {
  642.         TreeElem* p = create(key);
  643.         if( p->leaf )
  644.         {
  645.             return make_pair( iterator{p}, false );
  646.         } else {
  647.             make_val( p, std::move(val) );
  648.             ++sz;
  649.             return make_pair( iterator{p}, true );
  650.         }
  651.     }
  652.  
  653.     template<typename T,typename Alloc>
  654.     template <class... Args>
  655.     auto StringMap<T,Alloc>::emplace(const std::string& key,Args&&... args) -> insert_result_type
  656.     {
  657.         TreeElem* p = create(key);
  658.         if( p->leaf )
  659.         {
  660.             return make_pair( iterator{p}, false );
  661.         } else {
  662.             make_val( p, std::forward<Args>(args)... );
  663.             ++sz;
  664.             return make_pair( iterator{p}, true );
  665.         }
  666.     }
  667.  
  668.     template<typename T,typename Alloc>
  669.     auto StringMap<T,Alloc>::insert_or_assign(const std::string& key, const T& val) -> insert_result_type
  670.     {
  671.         TreeElem* p = create(key);
  672.         if( p->leaf )
  673.         {
  674.             (*p->leaf) = val;
  675.             return make_pair( iterator{p}, false );
  676.         } else {
  677.             make_val( p, val );
  678.             ++sz;
  679.             return make_pair( iterator{p}, true );
  680.         }
  681.     }
  682.  
  683.     template<typename T,typename Alloc>
  684.     auto StringMap<T,Alloc>::insert_or_assign(const std::string& key, T&& val) -> insert_result_type
  685.     {
  686.         TreeElem* p = create(key);
  687.         if( p->leaf )
  688.         {
  689.             (*p->leaf) = std::move(val);
  690.             return make_pair( iterator{p}, false );
  691.         } else {
  692.             make_val( p, std::move(val) );
  693.             ++sz;
  694.             return make_pair( iterator{p}, true );
  695.         }
  696.     }
  697.  
  698.     template<typename T,typename Alloc>
  699.     auto StringMap<T,Alloc>::erase(iterator iter) -> iterator
  700.     {
  701.         auto n = iter.node;
  702.         if( n && n->leaf )
  703.         {
  704.             del_val( n );
  705.             --sz;
  706.         }
  707.         return ++iter;
  708.     }
  709.  
  710.     template<typename T,typename Alloc>
  711.     bool StringMap<T,Alloc>::erase(const std::string& key)
  712.     {
  713.         auto i = find(key);
  714.         if(i==end()) return false;
  715.         erase(i);
  716.         return true;
  717.     }
  718.  
  719.     template<typename T,typename Alloc>
  720.     auto StringMap<T,Alloc>::erase(iterator b,iterator e) -> iterator
  721.     {
  722.         iterator i = b;
  723.         while( i != e )
  724.             i = erase(i);
  725.         return i;
  726.     }
  727.  
  728.     template<typename T,typename Alloc>
  729.     void StringMap<T,Alloc>::recursive_clear_nodes( TreeElem* p )
  730.     {
  731.         if(!p) return;
  732.         if(p->leaf)
  733.         {
  734.             del_val(p);
  735.         }
  736.         for( auto i : knodes )
  737.             recursive_clear_nodes(p->nodes[i]);
  738.         del_node(p);
  739.     }
  740.  
  741.     template<typename T,typename Alloc>
  742.     void StringMap<T,Alloc>::clear()
  743.     {
  744.         for( auto i : knodes )
  745.         {
  746.             auto& tep = sentinel.nodes[i];
  747.             recursive_clear_nodes( tep );
  748.             tep = nullptr;
  749.         }
  750.         if(sentinel.leaf)
  751.         {
  752.             del_val(&sentinel);
  753.         }
  754.         sz = 0;
  755.     }
  756.  
  757.     template<typename T,typename Alloc>
  758.     auto StringMap<T,Alloc>::make_node( bool clear ) const -> TreeElem*
  759.     {
  760.         TreeElem* tep = node_alloc.allocate(1);
  761.         if(clear)
  762.         {
  763.             for( auto i : anodes )
  764.                 tep->nodes[i]=nullptr;
  765.             tep->leaf = nullptr;
  766.         }
  767.         return tep;
  768.     }
  769.  
  770.     template<typename T,typename Alloc>
  771.     template<typename... Args>
  772.     void StringMap<T,Alloc>::make_val( TreeElem* tep, Args&&... args )
  773.     {
  774.         tep->leaf = val_alloc.allocate(1);
  775.         new (tep->leaf) T( std::forward<Args>(args)... );
  776.     }
  777.  
  778.     template<typename T,typename Alloc>
  779.     void StringMap<T,Alloc>::del_val( TreeElem* tep )
  780.     {
  781.         if( tep->leaf )
  782.         {
  783.             tep->leaf->~T();
  784.             val_alloc.deallocate(tep->leaf,1);
  785.             tep->leaf = nullptr;
  786.         }
  787.     }
  788.  
  789.     template<typename T,typename Alloc>
  790.     void StringMap<T,Alloc>::del_node( TreeElem* tep )
  791.     {
  792.         node_alloc.deallocate(tep,1);
  793.     }
  794.  
  795.     template<typename T,typename Alloc>
  796.     void StringMap<T,Alloc>::debugprint(std::ostream& out) const
  797.     {
  798.         std::function<void(int,int,const TreeElem*)> rp;
  799.         rp = [&](int ind, int c, const TreeElem* p) -> void
  800.         {
  801.             assert(p);
  802.             for(int i=0;i<ind;++i)
  803.                 out << ' ';
  804.             if(c) out << (char)c;
  805.             if(p->leaf)
  806.                 out << " (" << *p->leaf << ")";
  807.             out << "\n";
  808.             for(auto i : knodes)
  809.             {
  810.                 const TreeElem* pp = p->nodes[i];
  811.                 if(!pp) continue;
  812.                 assert( pp->nodes[0] == p );
  813.                 rp(ind+2,i,pp);
  814.             }
  815.         };
  816.  
  817.         rp( 0, 0, &sentinel );
  818.     }
  819.  
  820.     namespace detail
  821.     {
  822.  
  823.         template<typename T>
  824.         struct has_compare_standalone
  825.         {
  826.             typedef char yes_type;
  827.             typedef long no_type;
  828.  
  829.             template<typename U>
  830.             static yes_type test( decltype( int{compare( std::declval<U>(), std::declval<U>() )} , void() )* );
  831.             static no_type test(...);
  832.  
  833.             static const bool value = sizeof(test(0)) == sizeof(yes_type);
  834.         };
  835.  
  836.         template<typename T>
  837.         std::enable_if_t<has_compare_standalone<T>::value,int>
  838.           cmp( const T& t1, const T& t2 )
  839.         {
  840.             return compare(t1,t2);
  841.         }
  842.  
  843.         template<typename T>
  844.         struct has_compare_member
  845.         {
  846.             typedef char yes_type;
  847.             typedef long no_type;
  848.  
  849.             template<typename U>
  850.             static yes_type test( decltype( int{ std::declval<const U&>().compare( std::declval<U>() )} , void() )* );
  851.             static no_type test(...);
  852.  
  853.             static const bool value = sizeof(test(0)) == sizeof(yes_type);
  854.         };
  855.  
  856.         template<typename T>
  857.         std::enable_if_t<has_compare_member<T>::value && ! has_compare_standalone<T>::value,int>
  858.           cmp( const T& t1, const T& t2 )
  859.         {
  860.             return t1.compare(t2);
  861.         }
  862.  
  863.         template<typename T>
  864.         std::enable_if_t< ! has_compare_member<T>::value && ! has_compare_standalone<T>::value,int>
  865.           cmp( const T& t1, const T& t2 )
  866.         {
  867.             using std::less;
  868.             if( less<T>()( t1, t2 ) )
  869.                 return -1;
  870.             if( less<T>()( t2, t1 ) )
  871.                 return +1;
  872.             return 0;
  873.         }
  874.     } // namespace detail
  875.  
  876.     template<typename T,typename Alloc>
  877.     int StringMap<T,Alloc>::compare(const StringMap& other) const
  878.     {
  879.         auto mi = begin();
  880.         auto oi = other.begin();
  881.         while(true)
  882.         {
  883.             bool me = ( mi == end() );
  884.             bool oe = ( oi == other.end() );
  885.             if(me&&oe) return 0;
  886.             if(me) return -1;
  887.             if(oe) return +1;
  888.             int i = detail::cmp<T>( mi->value(), oi->value() );
  889.             if(i) return i;
  890.             ++mi; ++oi;
  891.         }
  892.     }
  893.  
  894.     template<typename T,typename Alloc>
  895.     bool operator < ( const StringMap<T,Alloc>& lhs, const StringMap<T,Alloc>& rhs )
  896.     {
  897.         return lhs.compare(rhs) < 0;
  898.     }
  899.  
  900.     template<typename T,typename Alloc>
  901.     bool operator <= ( const StringMap<T,Alloc>& lhs, const StringMap<T,Alloc>& rhs )
  902.     {
  903.         return lhs.compare(rhs) <= 0;
  904.     }
  905.  
  906.     template<typename T,typename Alloc>
  907.     bool operator == ( const StringMap<T,Alloc>& lhs, const StringMap<T,Alloc>& rhs )
  908.     {
  909.         return lhs.compare(rhs) == 0;
  910.     }
  911.  
  912.     template<typename T,typename Alloc>
  913.     bool operator > ( const StringMap<T,Alloc>& lhs, const StringMap<T,Alloc>& rhs )
  914.     {
  915.         return lhs.compare(rhs) > 0;
  916.     }
  917.  
  918.     template<typename T,typename Alloc>
  919.     bool operator >= ( const StringMap<T,Alloc>& lhs, const StringMap<T,Alloc>& rhs )
  920.     {
  921.         return lhs.compare(rhs) >= 0;
  922.     }
  923.  
  924.     template<typename T,typename Alloc>
  925.     bool operator != ( const StringMap<T,Alloc>& lhs, const StringMap<T,Alloc>& rhs )
  926.     {
  927.         return lhs.compare(rhs) != 0;
  928.     }
  929.  
  930. } // namespace lib
  931.  
  932. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement