epoc32/include/stdapis/boost/multi_index/detail/seq_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-2006 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_SEQ_INDEX_OPS_HPP
    10 #define BOOST_MULTI_INDEX_DETAIL_SEQ_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 <boost/detail/no_exceptions_support.hpp>
    18 #include <boost/multi_index/detail/seq_index_node.hpp>
    19 #include <boost/limits.hpp>
    20 #include <boost/type_traits/aligned_storage.hpp>
    21 #include <boost/type_traits/alignment_of.hpp> 
    22 #include <cstddef>
    23 
    24 namespace boost{
    25 
    26 namespace multi_index{
    27 
    28 namespace detail{
    29 
    30 /* Common code for sequenced_index memfuns having templatized and
    31  * non-templatized versions.
    32  */
    33 
    34 template <typename SequencedIndex,typename Predicate>
    35 void sequenced_index_remove(SequencedIndex& x,Predicate pred)
    36 {
    37   typedef typename SequencedIndex::iterator iterator;
    38   iterator first=x.begin(),last=x.end();
    39   while(first!=last){
    40     if(pred(*first))x.erase(first++);
    41     else ++first;
    42   }
    43 }
    44 
    45 template <typename SequencedIndex,class BinaryPredicate>
    46 void sequenced_index_unique(SequencedIndex& x,BinaryPredicate binary_pred)
    47 {
    48   typedef typename SequencedIndex::iterator iterator;
    49   iterator first=x.begin();
    50   iterator last=x.end();
    51   if(first!=last){
    52     for(iterator middle=first;++middle!=last;middle=first){
    53       if(binary_pred(*middle,*first))x.erase(middle);
    54       else first=middle;
    55     }
    56   }
    57 }
    58 
    59 template <typename SequencedIndex,typename Compare>
    60 void sequenced_index_merge(SequencedIndex& x,SequencedIndex& y,Compare comp)
    61 {
    62   typedef typename SequencedIndex::iterator iterator;
    63   if(&x!=&y){
    64     iterator first0=x.begin(),last0=x.end();
    65     iterator first1=y.begin(),last1=y.end();
    66     while(first0!=last0&&first1!=last1){
    67       if(comp(*first1,*first0))x.splice(first0,y,first1++);
    68       else ++first0;
    69     }
    70     x.splice(last0,y,first1,last1);
    71   }
    72 }
    73 
    74 /* sorting  */
    75 
    76 /* auxiliary stuff */
    77 
    78 template<typename Node,typename Compare>
    79 void sequenced_index_collate(
    80   sequenced_index_node_impl* x,sequenced_index_node_impl* y,Compare comp
    81   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
    82 {
    83   sequenced_index_node_impl* first0=x->next();
    84   sequenced_index_node_impl* last0=x;
    85   sequenced_index_node_impl* first1=y->next();
    86   sequenced_index_node_impl* last1=y;
    87   while(first0!=last0&&first1!=last1){
    88     if(comp(
    89         Node::from_impl(first1)->value(),Node::from_impl(first0)->value())){
    90       sequenced_index_node_impl* tmp=first1->next();
    91       sequenced_index_node_impl::relink(first0,first1);
    92       first1=tmp;
    93     }
    94     else first0=first0->next();
    95   }
    96   sequenced_index_node_impl::relink(last0,first1,last1);
    97 }
    98 
    99 /* Some versions of CGG require a bogus typename in counter_spc
   100  * inside sequenced_index_sort if the following is defined
   101  * also inside sequenced_index_sort.
   102  */
   103 
   104 BOOST_STATIC_CONSTANT(
   105   std::size_t,
   106   sequenced_index_sort_max_fill=
   107     (std::size_t)std::numeric_limits<std::size_t>::digits+1);
   108 
   109 template<typename Node,typename Compare>
   110 void sequenced_index_sort(Node* header,Compare comp)
   111 {
   112   /* Musser's mergesort, see http://www.cs.rpi.edu/~musser/gp/List/lists1.html.
   113    * The implementation is a little convoluted: in the original code
   114    * counter elements and carry are std::lists: here we do not want
   115    * to use multi_index instead, so we do things at a lower level, managing
   116    * directly the internal node representation.
   117    * Incidentally, the implementations I've seen of this algorithm (SGI,
   118    * Dinkumware, STLPort) are not exception-safe: this is. Moreover, we do not
   119    * use any dynamic storage.
   120    */
   121 
   122   if(header->next()==header->impl()||
   123      header->next()->next()==header->impl())return;
   124 
   125   aligned_storage<
   126     sizeof(sequenced_index_node_impl),
   127     alignment_of<
   128     sequenced_index_node_impl>::value
   129   >::type                                   carry_spc;
   130   sequenced_index_node_impl&                carry=
   131     *static_cast<sequenced_index_node_impl*>(static_cast<void*>(&carry_spc));
   132   aligned_storage<
   133     sizeof(
   134       sequenced_index_node_impl
   135         [sequenced_index_sort_max_fill]),
   136     alignment_of<
   137       sequenced_index_node_impl
   138         [sequenced_index_sort_max_fill]
   139     >::value
   140   >::type                                   counter_spc;
   141   sequenced_index_node_impl*                counter=
   142     static_cast<sequenced_index_node_impl*>(static_cast<void*>(&counter_spc));
   143   std::size_t                               fill=0;
   144 
   145   carry.prior()=carry.next()=&carry;
   146   counter[0].prior()=counter[0].next()=&counter[0];
   147 
   148   BOOST_TRY{
   149     while(header->next()!=header->impl()){
   150       sequenced_index_node_impl::relink(carry.next(),header->next());
   151       std::size_t i=0;
   152       while(i<fill&&counter[i].next()!=&counter[i]){
   153         sequenced_index_collate<Node>(&carry,&counter[i++],comp);
   154       }
   155       sequenced_index_node_impl::swap(&carry,&counter[i]);
   156       if(i==fill){
   157         ++fill;
   158         counter[fill].prior()=counter[fill].next()=&counter[fill];
   159       }
   160     }
   161 
   162     for(std::size_t i=1;i<fill;++i){
   163       sequenced_index_collate<Node>(&counter[i],&counter[i-1],comp);
   164     }
   165     sequenced_index_node_impl::swap(header->impl(),&counter[fill-1]);
   166   }
   167   BOOST_CATCH(...)
   168   {
   169     sequenced_index_node_impl::relink(header->impl(),carry.next(),&carry);
   170     for(std::size_t i=0;i<=fill;++i){
   171       sequenced_index_node_impl::relink(
   172         header->impl(),counter[i].next(),&counter[i]);
   173     }
   174     BOOST_RETHROW;
   175   }
   176   BOOST_CATCH_END
   177 }
   178 
   179 } /* namespace multi_index::detail */
   180 
   181 } /* namespace multi_index */
   182 
   183 } /* namespace boost */
   184 
   185 #endif