epoc32/include/stdapis/boost/multi_index/detail/rnd_index_ops.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:27:01 +0100
branchSymbian2
changeset 3 e1b950c65cb4
permissions -rw-r--r--
Attempt to represent the S^2->S^3 header reorganisation as a series of "hg rename" operations
     1 /* Copyright 2003-2005 Joaquín M López Muñoz.
     2  * Distributed under the Boost Software License, Version 1.0.
     3  * (See accompanying file LICENSE_1_0.txt or copy at
     4  * http://www.boost.org/LICENSE_1_0.txt)
     5  *
     6  * See http://www.boost.org/libs/multi_index for library home page.
     7  */
     8 
     9 #ifndef BOOST_MULTI_INDEX_DETAIL_RND_INDEX_OPS_HPP
    10 #define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_OPS_HPP
    11 
    12 #if defined(_MSC_VER)&&(_MSC_VER>=1200)
    13 #pragma once
    14 #endif
    15 
    16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
    17 #include <algorithm>
    18 #include <boost/multi_index/detail/rnd_index_ptr_array.hpp>
    19 #include <functional>
    20 
    21 namespace boost{
    22 
    23 namespace multi_index{
    24 
    25 namespace detail{
    26 
    27 /* Common code for random_access_index memfuns having templatized and
    28  * non-templatized versions.
    29  */
    30 
    31 template<typename Node,typename Allocator,typename Predicate>
    32 Node* random_access_index_remove(
    33   random_access_index_ptr_array<Allocator>& ptrs,Predicate pred
    34   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
    35 {
    36   typedef typename Node::value_type value_type;
    37 
    38   random_access_index_node_impl** first=ptrs.begin(),
    39                                ** res=first,
    40                                ** last=ptrs.end();
    41   for(;first!=last;++first){
    42     if(!pred(
    43         const_cast<const value_type&>(Node::from_impl(*first)->value()))){
    44       if(first!=res){
    45         std::swap(*first,*res);
    46         (*first)->up()=first;
    47         (*res)->up()=res;
    48       }
    49       ++res;
    50     }
    51   }
    52   return Node::from_impl(*res);
    53 }
    54 
    55 template<typename Node,typename Allocator,class BinaryPredicate>
    56 Node* random_access_index_unique(
    57   random_access_index_ptr_array<Allocator>& ptrs,BinaryPredicate binary_pred
    58   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
    59 {
    60   typedef typename Node::value_type value_type;
    61 
    62   random_access_index_node_impl** first=ptrs.begin(),
    63                                ** res=first,
    64                                ** last=ptrs.end();
    65   if(first!=last){
    66     for(;++first!=last;){
    67       if(!binary_pred(
    68            const_cast<const value_type&>(Node::from_impl(*res)->value()),
    69            const_cast<const value_type&>(Node::from_impl(*first)->value()))){
    70         ++res;
    71         if(first!=res){
    72           std::swap(*first,*res);
    73           (*first)->up()=first;
    74           (*res)->up()=res;
    75         }
    76       }
    77     }
    78     ++res;
    79   }
    80   return Node::from_impl(*res);
    81 }
    82 
    83 template<typename Node,typename Allocator,typename Compare>
    84 void random_access_index_inplace_merge(
    85   const Allocator& al,
    86   random_access_index_ptr_array<Allocator>& ptrs,
    87   random_access_index_node_impl** first1,Compare comp
    88   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
    89 {
    90   typedef typename Node::value_type value_type;
    91 
    92   auto_space<random_access_index_node_impl*,Allocator> spc(al,ptrs.size());
    93 
    94   random_access_index_node_impl** first0=ptrs.begin(),
    95                                ** last0=first1,
    96                                ** last1=ptrs.end(),
    97                                ** out=spc.data();
    98   while(first0!=last0&&first1!=last1){
    99     if(comp(
   100         const_cast<const value_type&>(Node::from_impl(*first1)->value()),
   101         const_cast<const value_type&>(Node::from_impl(*first0)->value()))){
   102       *out++=*first1++;
   103     }
   104     else{
   105       *out++=*first0++;
   106     }
   107   }
   108   std::copy(first0,last0,out);
   109   std::copy(first1,last1,out);
   110 
   111   first1=ptrs.begin();
   112   out=spc.data();
   113   while(first1!=last1){
   114     *first1=*out++;
   115     (*first1)->up()=first1;
   116     ++first1;
   117   }
   118 }
   119 
   120 /* sorting */
   121 
   122 /* auxiliary stuff */
   123 
   124 template<typename Node,typename Compare>
   125 struct random_access_index_sort_compare:
   126   std::binary_function<
   127     const typename Node::value_type*,const typename Node::value_type*,bool>
   128 {
   129   random_access_index_sort_compare(Compare comp_=Compare()):comp(comp_){}
   130 
   131   bool operator()(
   132     random_access_index_node_impl* x,
   133     random_access_index_node_impl* y)const
   134   {
   135     typedef typename Node::value_type value_type;
   136 
   137     return comp(
   138       const_cast<const value_type&>(Node::from_impl(x)->value()),
   139       const_cast<const value_type&>(Node::from_impl(y)->value()));
   140   }
   141 
   142 private:
   143   Compare comp;
   144 };
   145 
   146 template<typename Node,typename Allocator,class Compare>
   147 void random_access_index_sort(
   148   const Allocator& al,
   149   random_access_index_ptr_array<Allocator>& ptrs,
   150   Compare comp
   151   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
   152 {
   153   /* The implementation is extremely simple: an auxiliary
   154    * array of pointers is sorted using stdlib facilities and
   155    * then used to rearrange the index. This is suboptimal
   156    * in space and time, but has some advantages over other
   157    * possible approaches:
   158    *   - Use std::stable_sort() directly on ptrs using some
   159    *     special iterator in charge of maintaining pointers
   160    *     and up() pointers in sync: we cannot guarantee
   161    *     preservation of the container invariants in the face of
   162    *     exceptions, if, for instance, std::stable_sort throws
   163    *     when ptrs transitorily contains duplicate elements.
   164    *   - Rewrite the internal algorithms of std::stable_sort
   165    *     adapted for this case: besides being a fair amount of
   166    *     work, making a stable sort compatible with Boost.MultiIndex
   167    *     invariants (basically, no duplicates or missing elements
   168    *     even if an exception is thrown) is complicated, error-prone
   169    *     and possibly won't perform much better than the
   170    *     solution adopted.
   171    */
   172 
   173   typedef typename Node::value_type         value_type;
   174   typedef random_access_index_sort_compare<
   175     Node,Compare>                           ptr_compare;
   176   
   177   random_access_index_node_impl**   first=ptrs.begin();
   178   random_access_index_node_impl**   last=ptrs.end();
   179   auto_space<
   180     random_access_index_node_impl*,
   181     Allocator>                      spc(al,ptrs.size());
   182   random_access_index_node_impl**   buf=spc.data();
   183 
   184   std::copy(first,last,buf);
   185   std::stable_sort(buf,buf+ptrs.size(),ptr_compare(comp));
   186 
   187   while(first!=last){
   188     *first=*buf++;
   189     (*first)->up()=first;
   190     ++first;
   191   }
   192 }
   193 
   194 } /* namespace multi_index::detail */
   195 
   196 } /* namespace multi_index */
   197 
   198 } /* namespace boost */
   199 
   200 #endif