libmoost
/home/mhx/git/github/libmoost/include/moost/container/multi_map.hpp
Go to the documentation of this file.
00001 /* vim:set ts=3 sw=3 sts=3 et: */
00028 #ifndef MULTI_MAP_CONTAINER_H__
00029 #define MULTI_MAP_CONTAINER_H__
00030 
00031 #include <string>
00032 #include <vector>
00033 #include <algorithm>
00034 #include <map>
00035 
00036 #include "../which.hpp"
00037 #include "policies/dense_hash_map.hpp"
00038 
00039 #include "dense_hash_map.hpp"
00040 
00041 namespace moost { namespace container {
00042 
00043 typedef std::pair<int, int> multimap_value_type;
00044 
00045 // -----------------------------------------------------------------------------
00046 // -----------------------------------------------------------------------------
00047 
00090 template < typename TKey,
00091            typename TVal,
00092            typename TLocMap = moost::container::dense_hash_map<TKey, multimap_value_type >
00093          >
00094 class multi_map
00095 {
00096 private:
00097 
00098    typedef multi_map<TKey, TVal, TLocMap> self_type;
00099 
00100 public:
00101 
00102    typedef TKey first_type;
00103    typedef TVal second_type;
00104 
00105    typedef typename
00106       policies::map_policy_selector
00107             < TKey, multimap_value_type, TLocMap>::policy_type loc_map_policy_type;
00108 
00109    typedef typename std::vector<TVal>::iterator        range_iterator;
00110    typedef typename std::vector<TVal>::const_iterator  const_range_iterator;
00111 
00112    class range
00113    {
00114    public:
00115       range() {}
00116       range( range_iterator f, range_iterator l ) : first(f), last(l) {}
00117 
00118       range_iterator begin() const { return first; }
00119       range_iterator end()   const { return last; }
00120       size_t size() const { return last - first; }
00121       bool empty() const { return (last - first) == 0; }
00122 
00123    private:
00124       range_iterator first;
00125       range_iterator last;
00126    };
00127 
00128    class const_range
00129    {
00130    public:
00131 
00132       const_range() {}
00133       const_range( const_range_iterator f, const_range_iterator l ) : first(f), last(l) {}
00134       const_range( const range& r ) : first(r.begin()), last(r.end()) {}
00135 
00136       void operator=( const range& r )
00137       { first = r.begin(); last = r.end(); }
00138 
00139       const_range_iterator begin() const { return first; }
00140       const_range_iterator end() const { return last; }
00141 
00142       size_t size() const { return last - first; }
00143       bool empty() const { return (last - first) == 0; }
00144 
00145    private:
00146       const_range_iterator first;
00147       const_range_iterator last;
00148    };
00149 
00150 
00151 public:
00152 
00153    class const_iterator;
00154 
00155    class iterator /*: public const_iterator*/
00156    {
00157       friend class const_iterator;
00158 
00159    public:
00160 
00161       iterator() : m_pSelf(NULL) {}
00162       iterator( typename TLocMap::iterator it,
00163                 typename TLocMap::iterator lastIt,
00164                 self_type* pSelf )
00165          : m_loc_map_it(it), m_pSelf(pSelf)
00166       {
00167          if ( it == lastIt )
00168             std::make_pair( -1, range(m_pSelf->m_data.end(), m_pSelf->m_data.end()) );
00169          else
00170             update_iterator();
00171       }
00172 
00173       std::pair<int, range>& operator*()
00174       {
00175          update_iterator();
00176          return m_it;
00177       }
00178       std::pair<int, range>* operator->()
00179       {
00180          update_iterator();
00181          return &m_it;
00182       }
00183 
00184       iterator& operator++()
00185       {  // preincrement
00186          ++m_loc_map_it;
00187          return (*this);
00188       }
00189 
00190       iterator& operator--()
00191       {  // predecrement
00192          --m_loc_map_it;
00193          return (*this);
00194       }
00195 
00196       bool operator!=(const iterator& other) const
00197       {  // test for iterator inequality
00198          return other.m_loc_map_it != m_loc_map_it;
00199       }
00200 
00201    private:
00202 
00203       void update_iterator()
00204       {
00205          m_it.first = m_pSelf->m_locHandlerPolicy.template get_key<int>(m_pSelf->m_locations, m_loc_map_it);
00206          //m_it.first = TLocHandler::get_index(m_pSelf->m_locations, m_loc_map_it); // m_loc_map_it->first
00207          m_it.second = create_range();
00208       }
00209 
00210       range create_range()
00211       {
00212          multimap_value_type loc = m_pSelf->m_locHandlerPolicy.template get_value<multimap_value_type>(m_pSelf->m_locations, m_loc_map_it);
00213 
00214          //multimap_value_t loc = TLocHandler::get_location(m_loc_map_it);
00215          return range( m_pSelf->m_data.begin() +  loc.first, // start
00216                        m_pSelf->m_data.begin() + loc.first + loc.second ); //end
00217       }
00218 
00219       std::pair< int, range >    m_it;
00220       typename TLocMap::iterator m_loc_map_it;
00221       self_type*                 m_pSelf;
00222    };
00223 
00224    class const_iterator
00225    {
00226    public:
00227 
00228       const_iterator() : m_pSelf(NULL) {}
00229       const_iterator(const iterator& i)
00230          : m_it(i.m_it),
00231            m_loc_map_it(i.m_loc_map_it),
00232            m_pSelf(i.m_pSelf) {}
00233 
00234       const_iterator( typename TLocMap::const_iterator it,
00235                       typename TLocMap::const_iterator lastIt,
00236                       const self_type* pSelf )
00237          : m_loc_map_it(it), m_pSelf(pSelf)
00238       {
00239          if ( it == lastIt )
00240             std::make_pair( -1, const_range(m_pSelf->m_data.end(), m_pSelf->m_data.end()) );
00241          else
00242             update_iterator();
00243       }
00244 
00245       void operator=(const iterator& i)
00246       {  m_pSelf = i.m_pSelf; m_it = i.m_it; m_loc_map_it = i.m_loc_map_it; }
00247 
00248       std::pair<int, const_range>& operator*()
00249       {
00250          update_iterator();
00251          return m_it;
00252       }
00253       std::pair<int, const_range>* operator->()
00254       {
00255          update_iterator();
00256          return &m_it;
00257       }
00258 
00259       const_iterator& operator++()
00260       {  // preincrement
00261          ++m_loc_map_it;
00262          return (*this);
00263       }
00264 
00265       const_iterator& operator--()
00266       {  // predecrement
00267          --m_loc_map_it;
00268          return (*this);
00269       }
00270 
00271       bool operator!=(const const_iterator& other) const
00272       {  // test for iterator inequality
00273          return other.m_loc_map_it != m_loc_map_it;
00274       }
00275 
00276    protected:
00277 
00278       void update_iterator()
00279       {
00280          m_it.first = m_pSelf->m_locHandlerPolicy.template get_key<int>(m_pSelf->m_locations, m_loc_map_it); // m_loc_map_it->first
00281          //m_it.first = TLocHandler::get_index(m_pSelf->m_locations, m_loc_map_it); // m_loc_map_it->first
00282          m_it.second = create_range();
00283       }
00284 
00285       const_range create_range()
00286       {
00287          multimap_value_type loc = m_pSelf->m_locHandlerPolicy.template get_value<multimap_value_type>(m_pSelf->m_locations, m_loc_map_it);
00288          //multimap_value_t loc = TLocHandler::get_location(m_loc_map_it);
00289          return const_range( m_pSelf->m_data.begin() + loc.first, // start
00290                              m_pSelf->m_data.begin() + loc.first + loc.second ); //end
00291       }
00292 
00293       std::pair< int, const_range >    m_it;
00294       typename TLocMap::const_iterator m_loc_map_it;
00295       const self_type*                 m_pSelf;
00296       //std::vector<TVal>*         m_pData;
00297    };
00298 
00299 
00301 
00302    iterator       begin()       { return iterator(m_locations.begin(), m_locations.end(), this); }
00303    const_iterator begin() const { return const_iterator(m_locations.begin(), m_locations.end(), this); }
00304 
00305    iterator       end()       { return iterator(m_locations.end(), m_locations.end(), this); }
00306    const_iterator end() const { return const_iterator(m_locations.end(), m_locations.end(), this); }
00307 
00308 public:
00309 
00310    multi_map(const loc_map_policy_type& locHandlerPolicy = loc_map_policy_type() )
00311    : m_locHandlerPolicy(locHandlerPolicy)
00312    { m_locHandlerPolicy.init(m_locations); }
00313 
00321    template <int WhichKey, typename Iterator>
00322    void create_map(Iterator first, Iterator last, size_t suggestedSize = 128);
00323 
00328    template < typename Iterator,
00329               typename GetKeyPolicy, // int operator()( typename const Entry& e )
00330               typename GetValuesPolicy > // void operator()( typename const Entry& e, vector<TVal>& vals)
00331    void create_map( Iterator first, Iterator last,
00332                     const GetKeyPolicy& getKey,
00333                     const GetValuesPolicy& getValues,
00334                     size_t suggestedSize = 128 );
00335 
00343    template <int WhichKey, typename TFirst, typename TSecond>
00344    void create_map( std::vector<TFirst, TSecond>& i2i, bool doSort = true);
00345 
00346    template <int WhichKey, typename TFirst, typename TSecond>
00347    void create_map_compressed(std::vector<TFirst, TSecond>& i2i, bool doSort = true);
00348 
00356    template <int WhichKey, typename Iterator>
00357    void create_map_compressed(Iterator first, Iterator last, size_t suggestedSize = 128);
00358 
00359 
00360    range operator[](const TKey& key);
00361    const_range operator[](const TKey& key) const;
00362 
00364    void clear();
00365 
00367    size_t size() const
00368    { return m_locations.size(); }
00369 
00370    bool empty() const
00371    { return m_locations.empty(); }
00372 
00373 protected:
00374 
00375    TLocMap m_locations;
00376    loc_map_policy_type m_locHandlerPolicy;
00377    //TLocHandler m_locHandler;
00378    std::vector<TVal> m_data;
00379 
00380 };
00381 
00382 // -----------------------------------------------------------------------------
00383 // -----------------------------------------------------------------------------
00384 
00385 template <typename TKey, typename TVal, typename TLocMap>
00386 template <int WhichKey, typename TFirst, typename TSecond>
00387 void multi_map<TKey, TVal, TLocMap>::create_map( std::vector<TFirst, TSecond>& i2i,
00388                                                  bool doSort )
00389 {
00390    if ( i2i.empty() )
00391       return;
00392    if ( doSort )
00393    {
00394       using namespace moost;
00395       typename which<WhichKey>::template comparer<std::less> comparer;
00396       std::stable_sort(i2i.begin(), i2i.end(), comparer );
00397    }
00398 
00399    create_map<WhichKey>( i2i.begin(), i2i.end(), i2i.size() );
00400 }
00401 
00402 // -----------------------------------------------------------------------------
00403 
00404 template <typename TKey, typename TVal, typename TLocMap>
00405 template <int WhichKey, typename Iterator>
00406 void multi_map<TKey, TVal, TLocMap>::create_map( Iterator first, Iterator last,
00407                                                  size_t suggestedSize )
00408 {
00409    if ( first == last )
00410       return;
00411 
00412    int currPos = 0;
00413    int currSize = 0;
00414 
00415    typename moost::which<WhichKey> getKey;
00416    typename moost::which<WhichKey>::other_type getValue;
00417 
00418    TKey currKey = getKey(*first);
00419 
00420    if ( suggestedSize > 0 )
00421       m_data.reserve(suggestedSize);
00422 
00423    Iterator it;
00424    for ( it = first; it != last; ++it )
00425    {
00426       if ( currKey != getKey(*it) )
00427       {
00428          m_locHandlerPolicy.put(m_locations, currKey, std::make_pair(currPos, currSize));
00429          currKey = getKey(*it);
00430          currPos = static_cast<int>(m_data.size());
00431          currSize = 0;
00432       }
00433 
00434       m_data.push_back( getValue(*it) );
00435       ++currSize;
00436    }
00437 
00438    // last one
00439    m_locHandlerPolicy.put(m_locations, currKey, std::make_pair(currPos, currSize));
00440 }
00441 
00442 // -----------------------------------------------------------------------------
00443 
00444 template <typename TKey, typename TVal, typename TLocMap>
00445 template < typename Iterator, typename GetKeyPolicy, typename GetValuesPolicy >
00446 void multi_map<TKey, TVal, TLocMap>::create_map( Iterator first,
00447                                                  Iterator last,
00448                                                  const GetKeyPolicy& getKey,
00449                                                  const GetValuesPolicy& getValues,
00450                                                  size_t suggestedSize /*= 128 */)
00451 {
00452    if ( suggestedSize > 0 )
00453       m_data.reserve(suggestedSize);
00454 
00455    int currKey;
00456    std::vector<TVal> values;
00457 
00458    int entryPos = 0;
00459    int valuesSize;
00460 
00461    for ( Iterator it = first; it != last; ++it )
00462    {
00463       currKey = getKey(*it);
00464       getValues(*it, values);
00465       if ( values.empty() )
00466          continue;
00467 
00468       valuesSize = static_cast<int>(values.size());
00469 
00470       std::copy( values.begin(), values.end(), back_inserter(m_data) );
00471       m_locHandlerPolicy.put(m_locations, currKey, std::make_pair(entryPos, valuesSize));
00472       entryPos += valuesSize;
00473    }
00474 }
00475 
00476 // -----------------------------------------------------------------------------
00477 
00478 template <typename TKey, typename TVal, typename TLocMap>
00479 template <int WhichKey, typename TFirst, typename TSecond>
00480 void multi_map<TKey, TVal, TLocMap>::create_map_compressed( std::vector<TFirst, TSecond>& i2i,
00481                                                           bool doSort )
00482 {
00483    if ( i2i.empty() )
00484       return;
00485    if ( doSort )
00486    {
00487       using namespace moost;
00488       typename which<WhichKey>::template comparer<std::less> comparer;
00489       std::stable_sort(i2i.begin(), i2i.end(), comparer );
00490    }
00491 
00492    create_map_compressed<WhichKey>( i2i.begin(), i2i.end(), i2i.size() );
00493 }
00494 
00495 // -----------------------------------------------------------------------------
00496 
00497 template <typename TKey, typename TVal, typename TLocMap>
00498 template <int WhichKey, typename Iterator>
00499 void multi_map<TKey, TVal, TLocMap>::create_map_compressed( Iterator first, Iterator last,
00500                                                           size_t suggestedSize )
00501 {
00502    if ( first == last )
00503       return;
00504 
00505    int currPos = 0;
00506    int currSize = 0;
00507 
00508    typename moost::which<WhichKey> getKey;
00509    typename moost::which<WhichKey>::other_type getValue;
00510 
00511    TKey currKey = getKey(*first);
00512 
00513    if ( suggestedSize > 0 )
00514       m_data.reserve(suggestedSize);
00515 
00516    std::map<TVal, int> compressedLocsMap;
00517    typename std::map<TVal, int>::iterator clIt;
00518 
00519    Iterator it;
00520    for ( it = first; it != last; ++it )
00521    {
00522       if ( currKey != getKey(*it) )
00523       {
00524          if ( currSize == 1 )
00525          {
00526             // does it have the given value?
00527             clIt = compressedLocsMap.find( m_data.back() );
00528             if ( clIt == compressedLocsMap.end() )
00529             {
00530                // not found! Add it!
00531                compressedLocsMap[m_data.back()] = currPos;
00532             }
00533             else
00534             {
00535                m_data.pop_back();
00536                currPos = clIt->second;
00537             }
00538          }
00539 
00540          m_locHandlerPolicy.put(m_locations, currKey, std::make_pair(currPos, currSize));
00541          currKey = getKey(*it);
00542          currPos = static_cast<int>(m_data.size());
00543          currSize = 0;
00544       }
00545 
00546       m_data.push_back( getValue(*it) );
00547       ++currSize;
00548    }
00549 
00550    // last one
00551    m_locHandlerPolicy.put(m_locations, currKey, std::make_pair(currPos, currSize));
00552 }
00553 
00554 // -----------------------------------------------------------------------------
00555 
00556 template <typename TKey, typename TVal, typename TLocMap>
00557 typename multi_map<TKey, TVal, TLocMap>::range
00558 multi_map<TKey, TVal, TLocMap>::operator[]( const TKey& key )
00559 {
00560    multimap_value_type loc;
00561    if ( m_locHandlerPolicy(m_locations, key, loc) )
00562    {
00563       return range( m_data.begin() + loc.first, // start
00564                     m_data.begin() + loc.first + loc.second  // end
00565                   );
00566    }
00567    else
00568    {
00569       return range(m_data.end(), m_data.end());
00570    }
00571 }
00572 
00573 // -----------------------------------------------------------------------------
00574 
00575 template <typename TKey, typename TVal, typename TLocMap>
00576 typename multi_map<TKey, TVal, TLocMap>::const_range
00577 multi_map<TKey, TVal, TLocMap>::operator[]( const TKey& key ) const
00578 {
00579    multimap_value_type loc;
00580    if ( m_locHandlerPolicy(m_locations, key, loc) )
00581    {
00582       return const_range( m_data.begin() + loc.first, // start
00583                           m_data.begin() + loc.first + loc.second  // end
00584                          );
00585    }
00586    else
00587    {
00588       return const_range(m_data.end(), m_data.end());
00589    }
00590 }
00591 
00592 // -----------------------------------------------------------------------------
00593 
00594 template <typename TKey, typename TVal, typename TLocMap>
00595 void multi_map<TKey, TVal, TLocMap>::clear()
00596 {
00597    m_data.clear();
00598    m_locations.clear();
00599 }
00600 
00601 // -----------------------------------------------------------------------------
00602 
00603 }}
00604 
00605 #endif // MULTI_MAP_CONTAINER_H__
00606 
00607 // -----------------------------------------------------------------------------