Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:45:58

0001 /* Copyright 2016-2024 Joaquin M Lopez Munoz.
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * See http://www.boost.org/libs/poly_collection for library home page.
0007  */
0008 
0009 #ifndef BOOST_POLY_COLLECTION_DETAIL_SEGMENT_SPLIT_HPP
0010 #define BOOST_POLY_COLLECTION_DETAIL_SEGMENT_SPLIT_HPP
0011 
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015 
0016 #include <boost/config.hpp>
0017 #include <boost/iterator/iterator_facade.hpp>
0018 #include <boost/poly_collection/detail/iterator_traits.hpp>
0019 #include <utility>
0020 
0021 #if defined(BOOST_MSVC)
0022 #pragma warning(push)
0023 #pragma warning(disable:4714) /* marked as __forceinline not inlined */
0024 #endif
0025 
0026 namespace boost{
0027 
0028 namespace poly_collection{
0029 
0030 namespace detail{
0031 
0032 /* breakdown of an iterator range into local_base_iterator segments */
0033 
0034 template<typename PolyCollectionIterator>
0035 class segment_splitter
0036 {
0037   using traits=iterator_traits<PolyCollectionIterator>;
0038   using local_base_iterator=typename traits::local_base_iterator;
0039   using base_segment_info_iterator=typename traits::base_segment_info_iterator;
0040   using type_index=typename traits::type_index;
0041 
0042 public:
0043   struct info
0044   {
0045     const type_index&   type_info()const noexcept{return info_;}
0046     local_base_iterator begin()const noexcept{return begin_;}
0047     local_base_iterator end()const noexcept{return end_;}
0048 
0049     const type_index&   info_;
0050     local_base_iterator begin_,end_;
0051   };
0052 
0053   struct iterator:iterator_facade<iterator,info,std::input_iterator_tag,info>
0054   {
0055     iterator()=default;
0056 
0057   private:
0058     friend class segment_splitter;
0059     friend class boost::iterator_core_access;
0060 
0061     iterator(
0062       base_segment_info_iterator it,
0063       const PolyCollectionIterator& first,const PolyCollectionIterator& last):
0064       it{it},pfirst{&first},plast{&last}{}
0065     iterator(
0066       const PolyCollectionIterator& first,const PolyCollectionIterator& last):
0067       it{traits::base_segment_info_iterator_from(first)},
0068       pfirst{&first},plast{&last}
0069       {}
0070 
0071     info dereference()const noexcept
0072     {
0073       return {
0074         it->type_info(),
0075         it==traits::base_segment_info_iterator_from(*pfirst)?
0076           traits::local_base_iterator_from(*pfirst):it->begin(),
0077         it==traits::base_segment_info_iterator_from(*plast)?
0078           traits::local_base_iterator_from(*plast):it->end()
0079       };
0080     }
0081 
0082     bool equal(const iterator& x)const noexcept{return it==x.it;}
0083     void increment()noexcept{++it;}
0084 
0085     base_segment_info_iterator    it;
0086     const PolyCollectionIterator* pfirst;
0087     const PolyCollectionIterator* plast;
0088   };
0089 
0090   segment_splitter(
0091     const PolyCollectionIterator& first,const PolyCollectionIterator& last):
0092     pfirst{&first},plast{&last}{}
0093 
0094   iterator begin()const noexcept{return {*pfirst,*plast};}
0095 
0096   iterator end()const noexcept
0097   {
0098     auto slast=traits::base_segment_info_iterator_from(*plast);
0099     if(slast!=traits::end_base_segment_info_iterator_from(*plast))++slast;
0100     return {slast,*plast,*plast};
0101   }
0102 
0103 private:
0104   const PolyCollectionIterator* pfirst;
0105   const PolyCollectionIterator* plast;
0106 };
0107 
0108 template<typename PolyCollectionIterator>
0109 segment_splitter<PolyCollectionIterator>
0110 segment_split(
0111   const PolyCollectionIterator& first,const PolyCollectionIterator& last)
0112 {
0113   return {first,last};
0114 }
0115 
0116 #if 1
0117 /* equivalent to for(auto i:segment_split(first,last))f(i) */
0118 
0119 template<typename PolyCollectionIterator,typename F>
0120 BOOST_FORCEINLINE void for_each_segment(
0121   const PolyCollectionIterator& first,const PolyCollectionIterator& last,F&& f)
0122 {
0123   using traits=iterator_traits<PolyCollectionIterator>;
0124   using info=typename segment_splitter<PolyCollectionIterator>::info;
0125 
0126   auto sfirst=traits::base_segment_info_iterator_from(first),
0127        slast=traits::base_segment_info_iterator_from(last),
0128        send=traits::end_base_segment_info_iterator_from(last);
0129   auto lbfirst=traits::local_base_iterator_from(first),
0130        lblast=traits::local_base_iterator_from(last);
0131 
0132   if(sfirst!=slast){
0133     for(;;){
0134       f(info{sfirst->type_info(),lbfirst,sfirst->end()});
0135       ++sfirst;
0136       if(sfirst==slast)break;
0137       lbfirst=sfirst->begin();
0138     }
0139     if(sfirst!=send)f(info{sfirst->type_info(),sfirst->begin(),lblast});
0140   }
0141   else if(sfirst!=send){
0142     f(info{sfirst->type_info(),lbfirst,lblast});
0143   }
0144 }
0145 #else
0146 template<typename PolyCollectionIterator,typename F>
0147 BOOST_FORCEINLINE void for_each_segment(
0148   const PolyCollectionIterator& first,const PolyCollectionIterator& last,F&& f)
0149 {
0150   for(auto i:segment_split(first,last))f(i);  
0151 }
0152 #endif
0153 
0154 } /* namespace poly_collection::detail */
0155 
0156 } /* namespace poly_collection */
0157 
0158 } /* namespace boost */
0159 
0160 #if defined(BOOST_MSVC)
0161 #pragma warning(pop) /* C4714 */
0162 #endif
0163 
0164 #endif