File indexing completed on 2025-01-18 09:47:50
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/iterator/iterator_facade.hpp>
0017 #include <boost/poly_collection/detail/iterator_traits.hpp>
0018 #include <typeinfo>
0019 #include <utility>
0020
0021 namespace boost{
0022
0023 namespace poly_collection{
0024
0025 namespace detail{
0026
0027
0028
0029 template<typename PolyCollectionIterator>
0030 class segment_splitter
0031 {
0032 using traits=iterator_traits<PolyCollectionIterator>;
0033 using local_base_iterator=typename traits::local_base_iterator;
0034 using base_segment_info_iterator=typename traits::base_segment_info_iterator;
0035
0036 public:
0037 struct info
0038 {
0039 const std::type_info& type_info()const noexcept{return *pinfo_;}
0040 local_base_iterator begin()const noexcept{return begin_;}
0041 local_base_iterator end()const noexcept{return end_;}
0042
0043 const std::type_info* pinfo_;
0044 local_base_iterator begin_,end_;
0045 };
0046
0047 struct iterator:iterator_facade<iterator,info,std::input_iterator_tag,info>
0048 {
0049 iterator()=default;
0050
0051 private:
0052 friend class segment_splitter;
0053 friend class boost::iterator_core_access;
0054
0055 iterator(
0056 base_segment_info_iterator it,
0057 const PolyCollectionIterator& first,const PolyCollectionIterator& last):
0058 it{it},pfirst{&first},plast{&last}{}
0059 iterator(
0060 const PolyCollectionIterator& first,const PolyCollectionIterator& last):
0061 it{traits::base_segment_info_iterator_from(first)},
0062 pfirst{&first},plast{&last}
0063 {}
0064
0065 info dereference()const noexcept
0066 {
0067 return {
0068 &it->type_info(),
0069 it==traits::base_segment_info_iterator_from(*pfirst)?
0070 traits::local_base_iterator_from(*pfirst):it->begin(),
0071 it==traits::base_segment_info_iterator_from(*plast)?
0072 traits::local_base_iterator_from(*plast):it->end()
0073 };
0074 }
0075
0076 bool equal(const iterator& x)const noexcept{return it==x.it;}
0077 void increment()noexcept{++it;}
0078
0079 base_segment_info_iterator it;
0080 const PolyCollectionIterator* pfirst;
0081 const PolyCollectionIterator* plast;
0082 };
0083
0084 segment_splitter(
0085 const PolyCollectionIterator& first,const PolyCollectionIterator& last):
0086 pfirst{&first},plast{&last}{}
0087
0088 iterator begin()const noexcept{return {*pfirst,*plast};}
0089
0090 iterator end()const noexcept
0091 {
0092 auto slast=traits::base_segment_info_iterator_from(*plast);
0093 if(slast!=traits::end_base_segment_info_iterator_from(*plast))++slast;
0094 return {slast,*plast,*plast};
0095 }
0096
0097 private:
0098 const PolyCollectionIterator* pfirst;
0099 const PolyCollectionIterator* plast;
0100 };
0101
0102 template<typename PolyCollectionIterator>
0103 segment_splitter<PolyCollectionIterator>
0104 segment_split(
0105 const PolyCollectionIterator& first,const PolyCollectionIterator& last)
0106 {
0107 return {first,last};
0108 }
0109
0110 #if 1
0111
0112
0113 template<typename PolyCollectionIterator,typename F>
0114 void for_each_segment(
0115 const PolyCollectionIterator& first,const PolyCollectionIterator& last,F&& f)
0116 {
0117 using traits=iterator_traits<PolyCollectionIterator>;
0118 using info=typename segment_splitter<PolyCollectionIterator>::info;
0119
0120 auto sfirst=traits::base_segment_info_iterator_from(first),
0121 slast=traits::base_segment_info_iterator_from(last),
0122 send=traits::end_base_segment_info_iterator_from(last);
0123 auto lbfirst=traits::local_base_iterator_from(first),
0124 lblast=traits::local_base_iterator_from(last);
0125
0126 if(sfirst!=slast){
0127 for(;;){
0128 f(info{&sfirst->type_info(),lbfirst,sfirst->end()});
0129 ++sfirst;
0130 if(sfirst==slast)break;
0131 lbfirst=sfirst->begin();
0132 }
0133 if(sfirst!=send)f(info{&sfirst->type_info(),sfirst->begin(),lblast});
0134 }
0135 else if(sfirst!=send){
0136 f(info{&sfirst->type_info(),lbfirst,lblast});
0137 }
0138 }
0139 #else
0140 template<typename PolyCollectionIterator,typename F>
0141 void for_each_segment(
0142 const PolyCollectionIterator& first,const PolyCollectionIterator& last,F&& f)
0143 {
0144 for(auto i:segment_split(first,last))f(i);
0145 }
0146 #endif
0147
0148 }
0149
0150 }
0151
0152 }
0153
0154 #endif