LCOV - code coverage report
Current view: top level - include/crpropa - AssocVector.h (source / functions) Coverage Total Hit
Test: coverage.info.cleaned Lines: 100.0 % 21 21
Test Date: 2026-06-18 09:49:19 Functions: 100.0 % 5 5

            Line data    Source code
       1              : ////////////////////////////////////////////////////////////////////////////////
       2              : // The Loki Library
       3              : // Copyright (c) 2001 by Andrei Alexandrescu
       4              : // This code accompanies the book:
       5              : // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
       6              : //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
       7              : //
       8              : // Permission is hereby granted, free of charge, to any person obtaining a copy
       9              : // of this software and associated documentation files (the "Software"), to deal
      10              : // in the Software without restriction, including without limitation the rights
      11              : // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      12              : // copies of the Software, and to permit persons to whom the Software is
      13              : // furnished to do so, subject to the following conditions:
      14              : //
      15              : // The above copyright notice and this permission notice shall be included in
      16              : // all copies or substantial portions of the Software.
      17              : //
      18              : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      19              : // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      20              : // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      21              : // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      22              : // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      23              : // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      24              : // SOFTWARE.
      25              : ////////////////////////////////////////////////////////////////////////////////
      26              : #ifndef LOKI_ASSOCVECTOR_INC_
      27              : #define LOKI_ASSOCVECTOR_INC_
      28              : 
      29              : // $Id$
      30              : 
      31              : 
      32              : #include <algorithm>
      33              : #include <functional>
      34              : #include <vector>
      35              : #include <utility>
      36              : #include <iterator>
      37              : #include <map>
      38              : 
      39              : 
      40              : namespace Loki
      41              : {
      42              : ////////////////////////////////////////////////////////////////////////////////
      43              : // class template AssocVectorCompare
      44              : // Used by AssocVector
      45              : ////////////////////////////////////////////////////////////////////////////////
      46              : 
      47              :     namespace Private
      48              :     {
      49              :         template <class Value, class C, class K>
      50              :         class AssocVectorCompare : public C
      51              :         {
      52              :             typedef K first_argument_type;
      53              :             typedef std::pair<first_argument_type, Value>
      54              :                 Data;
      55              : 
      56              :         public:
      57              :             AssocVectorCompare()
      58              :             {}
      59              : 
      60              :             AssocVectorCompare(const C& src) : C(src)
      61              :             {}
      62              : 
      63              :             bool operator()(const first_argument_type& lhs,
      64              :                 const first_argument_type& rhs) const
      65              :             { return C::operator()(lhs, rhs); }
      66              : 
      67              :             bool operator()(const Data& lhs, const Data& rhs) const
      68              :             { return operator()(lhs.first, rhs.first); }
      69              : 
      70              :             bool operator()(const Data& lhs,
      71              :                 const first_argument_type& rhs) const
      72           77 :             { return operator()(lhs.first, rhs); }
      73              : 
      74              :             bool operator()(const first_argument_type& lhs,
      75              :                 const Data& rhs) const
      76              :             { return operator()(lhs, rhs.first); }
      77              :         };
      78              :     }
      79              : 
      80              : ////////////////////////////////////////////////////////////////////////////////
      81              : // class template AssocVector
      82              : // An associative vector built as a syntactic drop-in replacement for std::map
      83              : // BEWARE: AssocVector doesn't respect all map's guarantees, the most important
      84              : //     being:
      85              : // * iterators are invalidated by insert and erase operations
      86              : // * the complexity of insert/erase is O(N) not O(log N)
      87              : // * value_type is std::pair<K, V> not std::pair<const K, V>
      88              : // * iterators are random
      89              : ////////////////////////////////////////////////////////////////////////////////
      90              : 
      91              : 
      92              :     template
      93              :     <
      94              :         class K,
      95              :         class V,
      96              :         class C = std::less<K>,
      97              :         class A = std::allocator< std::pair<K, V> >
      98              :     >
      99           30 :     class AssocVector
     100              :         : private std::vector< std::pair<K, V>, A >
     101              :         , private Private::AssocVectorCompare<V, C, K>
     102              :     {
     103              :         typedef std::vector<std::pair<K, V>, A> Base;
     104              :         typedef Private::AssocVectorCompare<V, C, K> MyCompare;
     105              : 
     106              :     public:
     107              :         typedef K key_type;
     108              :         typedef V mapped_type;
     109              :         typedef typename Base::value_type value_type;
     110              : 
     111              :         typedef C key_compare;
     112              :         typedef A allocator_type;
     113              :         typedef typename A::value_type& reference;
     114              :         typedef const typename A::value_type* const_reference;
     115              :         typedef typename Base::iterator iterator;
     116              :         typedef typename Base::const_iterator const_iterator;
     117              :         typedef typename Base::size_type size_type;
     118              :         typedef typename Base::difference_type difference_type;
     119              :         typedef typename A::value_type* pointer;
     120              :         typedef const typename A::value_type* const_pointer;
     121              :         typedef typename Base::reverse_iterator reverse_iterator;
     122              :         typedef typename Base::const_reverse_iterator const_reverse_iterator;
     123              : 
     124              :         class value_compare
     125              :             : private key_compare
     126              :         {
     127              :             friend class AssocVector;
     128              : 
     129              :         protected:
     130              :             value_compare(key_compare pred) : key_compare(pred)
     131              :             {}
     132              : 
     133              :         public:
     134              :             bool operator()(const value_type& lhs, const value_type& rhs) const
     135              :             { return key_compare::operator()(lhs.first, rhs.first); }
     136              :         };
     137              : 
     138              :         // 23.3.1.1 construct/copy/destroy
     139              : 
     140              :         explicit AssocVector(const key_compare& comp = key_compare(),
     141              :             const A& alloc = A())
     142              :         : Base(alloc), MyCompare(comp)
     143              :         {}
     144              : 
     145              :         template <class InputIterator>
     146              :         AssocVector(InputIterator first, InputIterator last,
     147              :             const key_compare& comp = key_compare(),
     148              :             const A& alloc = A())
     149              :         : Base( alloc ), MyCompare( comp )
     150              :         {
     151              :             typedef ::std::vector< ::std::pair< K, V >, A > BaseType;
     152              :             typedef ::std::map< K, V, C, A > TempMap;
     153              :             typedef ::std::back_insert_iterator< Base > MyInserter;
     154              :             MyCompare & me = *this;
     155              :             const A tempAlloc;
     156              :             // Make a temporary map similar to this type to prevent any duplicate elements.
     157              :             TempMap temp( first, last, me, tempAlloc );
     158              :             Base::reserve( temp.size() );
     159              :             BaseType & target = static_cast< BaseType & >( *this );
     160              :             MyInserter myInserter = ::std::back_inserter( target );
     161              :             ::std::copy( temp.begin(), temp.end(), myInserter );
     162              :         }
     163              : 
     164           30 :         AssocVector& operator=(const AssocVector& rhs)
     165              :         {
     166           30 :             AssocVector(rhs).swap(*this);
     167           30 :             return *this;
     168              :         }
     169              : 
     170              :         // iterators:
     171              :         // The following are here because MWCW gets 'using' wrong
     172              :         iterator begin() { return Base::begin(); }
     173              :         const_iterator begin() const { return Base::begin(); }
     174              :         iterator end() { return Base::end(); }
     175              :         const_iterator end() const { return Base::end(); }
     176              :         reverse_iterator rbegin() { return Base::rbegin(); }
     177              :         const_reverse_iterator rbegin() const { return Base::rbegin(); }
     178              :         reverse_iterator rend() { return Base::rend(); }
     179              :         const_reverse_iterator rend() const { return Base::rend(); }
     180              : 
     181              :         // capacity:
     182              :         bool empty() const { return Base::empty(); }
     183              :         size_type size() const { return Base::size(); }
     184              :         size_type max_size() { return Base::max_size(); }
     185              : 
     186              :         // 23.3.1.2 element access:
     187         1145 :         mapped_type& operator[](const key_type& key)
     188         2290 :         { return insert(value_type(key, mapped_type())).first->second; }
     189              : 
     190              :         // modifiers:
     191         1145 :         std::pair<iterator, bool> insert(const value_type& val)
     192              :         {
     193              :             bool found(true);
     194         1145 :             iterator i(lower_bound(val.first));
     195              : 
     196         1145 :             if (i == end() || this->operator()(val.first, i->first))
     197              :             {
     198         1132 :                 i = Base::insert(i, val);
     199              :                 found = false;
     200              :             }
     201         1145 :             return std::make_pair(i, !found);
     202              :         }
     203              :         //Section [23.1.2], Table 69
     204              :         //http://developer.apple.com/documentation/DeveloperTools/gcc-3.3/libstdc++/23_containers/howto.html#4
     205              :         iterator insert(iterator pos, const value_type& val)
     206              :         {
     207              :             if( (pos == begin() || this->operator()(*(pos-1),val)) &&
     208              :                 (pos == end()    || this->operator()(val, *pos)) )
     209              :             {
     210              :                 return Base::insert(pos, val);
     211              :             }
     212              :             return insert(val).first;
     213              :         }
     214              : 
     215              :         template <class InputIterator>
     216              :         void insert(InputIterator first, InputIterator last)
     217              :         { for (; first != last; ++first) insert(*first); }
     218              : 
     219              :         void erase(iterator pos)
     220            3 :         { Base::erase(pos); }
     221              : 
     222              :         size_type erase(const key_type& k)
     223              :         {
     224              :             iterator i(find(k));
     225              :             if (i == end()) return 0;
     226              :             erase(i);
     227              :             return 1;
     228              :         }
     229              : 
     230              :         void erase(iterator first, iterator last)
     231              :         { Base::erase(first, last); }
     232              : 
     233              :         void swap(AssocVector& other)
     234              :         {
     235              :             Base::swap(other);
     236              :             MyCompare& me = *this;
     237              :             MyCompare& rhs = other;
     238              :             std::swap(me, rhs);
     239              :         }
     240              : 
     241              :         void clear()
     242              :         { Base::clear(); }
     243              : 
     244              :         // observers:
     245              :         key_compare key_comp() const
     246              :         { return *this; }
     247              : 
     248              :         value_compare value_comp() const
     249              :         {
     250              :             const key_compare& comp = *this;
     251              :             return value_compare(comp);
     252              :         }
     253              : 
     254              :         // 23.3.1.3 map operations:
     255            3 :         iterator find(const key_type& k)
     256              :         {
     257              :             iterator i(lower_bound(k));
     258            3 :             if (i != end() && this->operator()(k, i->first))
     259              :             {
     260              :                 i = end();
     261              :             }
     262            3 :             return i;
     263              :         }
     264              : 
     265           46 :         const_iterator find(const key_type& k) const
     266              :         {
     267              :             const_iterator i(lower_bound(k));
     268           46 :             if (i != end() && this->operator()(k, i->first))
     269              :             {
     270              :                 i = end();
     271              :             }
     272           46 :             return i;
     273              :         }
     274              : 
     275              :         size_type count(const key_type& k) const
     276              :         { return find(k) != end(); }
     277              : 
     278              :         iterator lower_bound(const key_type& k)
     279              :         {
     280              :             MyCompare& me = *this;
     281         1148 :             return std::lower_bound(begin(), end(), k, me);
     282              :         }
     283              : 
     284              :         const_iterator lower_bound(const key_type& k) const
     285              :         {
     286              :             const MyCompare& me = *this;
     287           46 :             return std::lower_bound(begin(), end(), k, me);
     288              :         }
     289              : 
     290              :         iterator upper_bound(const key_type& k)
     291              :         {
     292              :             MyCompare& me = *this;
     293              :             return std::upper_bound(begin(), end(), k, me);
     294              :         }
     295              : 
     296              :         const_iterator upper_bound(const key_type& k) const
     297              :         {
     298              :             const MyCompare& me = *this;
     299              :             return std::upper_bound(begin(), end(), k, me);
     300              :         }
     301              : 
     302              :         std::pair<iterator, iterator> equal_range(const key_type& k)
     303              :         {
     304              :             MyCompare& me = *this;
     305              :             return std::equal_range(begin(), end(), k, me);
     306              :         }
     307              : 
     308              :         std::pair<const_iterator, const_iterator> equal_range(
     309              :             const key_type& k) const
     310              :         {
     311              :             const MyCompare& me = *this;
     312              :             return std::equal_range(begin(), end(), k, me);
     313              :         }
     314              : 
     315              :         template <class K1, class V1, class C1, class A1>
     316              :         friend bool operator==(const AssocVector<K1, V1, C1, A1>& lhs,
     317              :                         const AssocVector<K1, V1, C1, A1>& rhs);
     318              : 
     319              :         bool operator<(const AssocVector& rhs) const
     320              :         {
     321              :             const Base& me = *this;
     322              :             const Base& yo = rhs;
     323              :             return me < yo;
     324              :         }
     325              : 
     326              :         template <class K1, class V1, class C1, class A1>
     327              :         friend bool operator!=(const AssocVector<K1, V1, C1, A1>& lhs,
     328              :                                const AssocVector<K1, V1, C1, A1>& rhs);
     329              : 
     330              :         template <class K1, class V1, class C1, class A1>
     331              :         friend bool operator>(const AssocVector<K1, V1, C1, A1>& lhs,
     332              :                               const AssocVector<K1, V1, C1, A1>& rhs);
     333              : 
     334              :         template <class K1, class V1, class C1, class A1>
     335              :         friend bool operator>=(const AssocVector<K1, V1, C1, A1>& lhs,
     336              :                                const AssocVector<K1, V1, C1, A1>& rhs);
     337              : 
     338              :         template <class K1, class V1, class C1, class A1>
     339              :         friend bool operator<=(const AssocVector<K1, V1, C1, A1>& lhs,
     340              :                                const AssocVector<K1, V1, C1, A1>& rhs);
     341              :     };
     342              : 
     343              :     template <class K, class V, class C, class A>
     344              :     inline bool operator==(const AssocVector<K, V, C, A>& lhs,
     345              :                            const AssocVector<K, V, C, A>& rhs)
     346              :     {
     347              :       const std::vector<std::pair<K, V>, A>& me = lhs;
     348              :       return me == rhs;
     349              :     }
     350              : 
     351              :     template <class K, class V, class C, class A>
     352              :     inline bool operator!=(const AssocVector<K, V, C, A>& lhs,
     353              :                            const AssocVector<K, V, C, A>& rhs)
     354              :     { return !(lhs == rhs); }
     355              : 
     356              :     template <class K, class V, class C, class A>
     357              :     inline bool operator>(const AssocVector<K, V, C, A>& lhs,
     358              :                           const AssocVector<K, V, C, A>& rhs)
     359              :     { return rhs < lhs; }
     360              : 
     361              :     template <class K, class V, class C, class A>
     362              :     inline bool operator>=(const AssocVector<K, V, C, A>& lhs,
     363              :                            const AssocVector<K, V, C, A>& rhs)
     364              :     { return !(lhs < rhs); }
     365              : 
     366              :     template <class K, class V, class C, class A>
     367              :     inline bool operator<=(const AssocVector<K, V, C, A>& lhs,
     368              :                            const AssocVector<K, V, C, A>& rhs)
     369              :     { return !(rhs < lhs); }
     370              : 
     371              : 
     372              :     // specialized algorithms:
     373              :     template <class K, class V, class C, class A>
     374              :     void swap(AssocVector<K, V, C, A>& lhs, AssocVector<K, V, C, A>& rhs)
     375              :     { lhs.swap(rhs); }
     376              : 
     377              : } // namespace Loki
     378              : 
     379              : #endif // end file guardian
     380              : 
        

Generated by: LCOV version 2.0-1