File indexing completed on 2025-09-17 08:45:58
0001
0002
0003
0004
0005
0006
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)
0024 #endif
0025
0026 namespace boost{
0027
0028 namespace poly_collection{
0029
0030 namespace detail{
0031
0032
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
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 }
0155
0156 }
0157
0158 }
0159
0160 #if defined(BOOST_MSVC)
0161 #pragma warning(pop)
0162 #endif
0163
0164 #endif