mirror of
https://github.com/boostorg/container.git
synced 2026-08-04 03:34:11 +02:00
Fix destination exhaustion logic as the source must be always consumed
This commit is contained in:
@@ -55,8 +55,15 @@ set_difference_dst_bounded
|
||||
(Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2,
|
||||
DstIter dst_first, DstSent dst_last, Comp comp, DstTag, SrcCat)
|
||||
{
|
||||
while(first1 != last1 && first2 != last2 && dst_first != dst_last) {
|
||||
// The destination-full test guards the write, not the whole iteration: an
|
||||
// element that produces no output still has to be consumed, so stopping
|
||||
// with room left in the sources but none in the destination would leave
|
||||
// the segmented walker unable to tell a full segment from an exhausted
|
||||
// destination. With unreachable_sentinel_t the test folds away as before.
|
||||
while(first1 != last1 && first2 != last2) {
|
||||
if (comp(*first1, *first2)) {
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_first == dst_last))
|
||||
break;
|
||||
*dst_first = *first1;
|
||||
++first1;
|
||||
++dst_first;
|
||||
@@ -139,7 +146,6 @@ segtrio<Iter1, Iter2, DstIter> set_difference_until_exhausts
|
||||
|
||||
template <class Iter1, class Sent1, class Iter2, class Sent2, class SegDstIter,
|
||||
class Comp, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
segtrio<Iter1, Iter2, SegDstIter> set_difference_until_exhausts
|
||||
(Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2, SegDstIter result, Comp comp,
|
||||
const segmented_iterator_tag &, const Cat &src1_cat)
|
||||
@@ -166,9 +172,15 @@ segtrio<Iter1, Iter2, SegDstIter> set_difference_until_exhausts
|
||||
first2 = r.second;
|
||||
dst_local = r.third;
|
||||
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_local != dst_end)) {
|
||||
// Stop on source exhaustion, not on "the segment did not fill": when
|
||||
// the output ends exactly on a segment boundary both hold at once, and
|
||||
// stepping dst_seg then walks off the end of the destination. compose()
|
||||
// normalises a local iterator sitting on the segment end, the same way
|
||||
// segmented_copy_dst_dispatch relies on.
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(first1 == last1 || first2 == last2)) {
|
||||
return result_t(first1, first2, dst_traits::compose(dst_seg, dst_local));
|
||||
}
|
||||
// dst segment full and both sources still live; advance to the next.
|
||||
++dst_seg;
|
||||
dst_local = dst_traits::begin(dst_seg);
|
||||
}
|
||||
@@ -193,7 +205,6 @@ BOOST_CONTAINER_FORCEINLINE segtrio<Iter1, Iter2, OutIter> set_difference_seg2_d
|
||||
}
|
||||
|
||||
template <class Iter1, class Sent1, class SegIter2, class OutIter, class Comp, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
segtrio<Iter1, SegIter2, OutIter> set_difference_seg2_dispatch
|
||||
(Iter1 first1, Sent1 last1, SegIter2 first2, SegIter2 last2, OutIter result, Comp comp,
|
||||
segmented_iterator_tag, const Cat & cat)
|
||||
@@ -213,33 +224,29 @@ segtrio<Iter1, SegIter2, OutIter> set_difference_seg2_dispatch
|
||||
const src2_segment_iterator sl2 = src2_traits::segment(last2);
|
||||
src2_local_iterator lf2 = src2_traits::local(first2);
|
||||
|
||||
if(sf2 == sl2) {
|
||||
local_result_t r = (set_difference_seg2_dispatch)
|
||||
(first1, last1, lf2, src2_traits::local(last2), result, comp,
|
||||
src2_is_local_seg_t(), cat);
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
}
|
||||
else {
|
||||
if(BOOST_CONTAINER_SEG_LIKELY(sf2 != sl2)) {
|
||||
local_result_t r = (set_difference_seg2_dispatch)
|
||||
(first1, last1, lf2, src2_traits::end(sf2), result, comp,
|
||||
src2_is_local_seg_t(), cat);
|
||||
if (BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
|
||||
goto exit;
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
|
||||
for(++sf2; sf2 != sl2; ++sf2) {
|
||||
r = (set_difference_seg2_dispatch)
|
||||
(r.first, last1, src2_traits::begin(sf2), src2_traits::end(sf2),
|
||||
r.third, comp, src2_is_local_seg_t(), cat);
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
|
||||
goto exit;
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
}
|
||||
|
||||
r = (set_difference_seg2_dispatch)
|
||||
(r.first, last1, src2_traits::begin(sf2), src2_traits::local(last2),
|
||||
r.third, comp, src2_is_local_seg_t(), cat);
|
||||
exit:
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
lf2 = src2_traits::begin(sl2);
|
||||
first1 = r.first;
|
||||
result = r.third;
|
||||
}
|
||||
const local_result_t r = (set_difference_seg2_dispatch)
|
||||
(first1, last1, lf2, src2_traits::local(last2), result, comp,
|
||||
src2_is_local_seg_t(), cat);
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -264,7 +271,6 @@ BOOST_CONTAINER_FORCEINLINE segtrio<FwdIt, InIter2, OutIter> set_difference_scan
|
||||
}
|
||||
|
||||
template <class SegIt, class InIter2, class Sent2, class OutIter, class Comp>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
segtrio<SegIt, InIter2, OutIter> set_difference_scan
|
||||
(SegIt first, SegIt last, InIter2 first2, Sent2 last2, OutIter result, Comp comp,
|
||||
segmented_iterator_tag)
|
||||
@@ -284,12 +290,7 @@ segtrio<SegIt, InIter2, OutIter> set_difference_scan
|
||||
segment_iterator const slast = traits::segment(last);
|
||||
local_iterator lcur = traits::local(first);
|
||||
|
||||
if(scur == slast) {
|
||||
local_result_t r = set_difference_scan
|
||||
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
}
|
||||
else {
|
||||
if(BOOST_CONTAINER_SEG_LIKELY(scur != slast)) {
|
||||
local_result_t r = set_difference_scan
|
||||
(lcur, traits::end(scur), first2, last2, result, comp, is_local_seg_t());
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(r.second == last2))
|
||||
@@ -302,10 +303,13 @@ segtrio<SegIt, InIter2, OutIter> set_difference_scan
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
}
|
||||
|
||||
r = set_difference_scan
|
||||
(traits::begin(scur), traits::local(last), r.second, last2, r.third, comp, is_local_seg_t());
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
lcur = traits::begin(slast);
|
||||
first2 = r.second;
|
||||
result = r.third;
|
||||
}
|
||||
const local_result_t r = set_difference_scan
|
||||
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
}
|
||||
|
||||
} // namespace detail_algo
|
||||
|
||||
@@ -52,10 +52,19 @@ set_intersection_dst_bounded
|
||||
(Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2,
|
||||
DstIter dst_first, DstSent dst_last, Comp comp, DstTag, SrcCat)
|
||||
{
|
||||
while(first1 != last1 && first2 != last2 && dst_first != dst_last) {
|
||||
// The destination-full test guards the write, not the whole iteration: an
|
||||
// element that produces no output still has to be consumed, so stopping
|
||||
// with room left in the sources but none in the destination would leave
|
||||
// the segmented walker unable to tell a full segment from an exhausted
|
||||
// destination. With unreachable_sentinel_t the test folds away as before.
|
||||
while(first1 != last1 && first2 != last2) {
|
||||
if (comp(*first1, *first2)) { ++first1; }
|
||||
else if (comp(*first2, *first1)) { ++first2; }
|
||||
else { *dst_first = *first1; ++first1; ++first2; ++dst_first; }
|
||||
else {
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_first == dst_last))
|
||||
break;
|
||||
*dst_first = *first1; ++first1; ++first2; ++dst_first;
|
||||
}
|
||||
}
|
||||
return segtrio<Iter1, Iter2, DstIter>(first1, first2, dst_first);
|
||||
}
|
||||
@@ -150,9 +159,15 @@ segtrio<Iter1, Iter2, SegDstIter> set_intersection_until_exhausts
|
||||
first2 = r.second;
|
||||
dst_local = r.third;
|
||||
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_local != dst_end)) {
|
||||
// Stop on source exhaustion, not on "the segment did not fill": when
|
||||
// the output ends exactly on a segment boundary both hold at once, and
|
||||
// stepping dst_seg then walks off the end of the destination. compose()
|
||||
// normalises a local iterator sitting on the segment end, the same way
|
||||
// segmented_copy_dst_dispatch relies on.
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(first1 == last1 || first2 == last2)) {
|
||||
return result_t(first1, first2, dst_traits::compose(dst_seg, dst_local));
|
||||
}
|
||||
// dst segment full and both sources still live; advance to the next.
|
||||
++dst_seg;
|
||||
dst_local = dst_traits::begin(dst_seg);
|
||||
}
|
||||
@@ -196,33 +211,29 @@ segtrio<Iter1, SegIter2, OutIter> set_intersection_seg2_dispatch
|
||||
const src2_segment_iterator sl2 = src2_traits::segment(last2);
|
||||
src2_local_iterator lf2 = src2_traits::local(first2);
|
||||
|
||||
if(sf2 == sl2) {
|
||||
local_result_t r = (set_intersection_seg2_dispatch)
|
||||
(first1, last1, lf2, src2_traits::local(last2), result, comp,
|
||||
src2_is_local_seg_t(), cat);
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
}
|
||||
else {
|
||||
if(BOOST_CONTAINER_SEG_LIKELY(sf2 != sl2)) {
|
||||
local_result_t r = (set_intersection_seg2_dispatch)
|
||||
(first1, last1, lf2, src2_traits::end(sf2), result, comp,
|
||||
src2_is_local_seg_t(), cat);
|
||||
if (BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
|
||||
goto exit;
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
|
||||
for(++sf2; sf2 != sl2; ++sf2) {
|
||||
r = (set_intersection_seg2_dispatch)
|
||||
(r.first, last1, src2_traits::begin(sf2), src2_traits::end(sf2),
|
||||
r.third, comp, src2_is_local_seg_t(), cat);
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
|
||||
goto exit;
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
}
|
||||
|
||||
r = (set_intersection_seg2_dispatch)
|
||||
(r.first, last1, src2_traits::begin(sf2), src2_traits::local(last2),
|
||||
r.third, comp, src2_is_local_seg_t(), cat);
|
||||
exit:
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
lf2 = src2_traits::begin(sl2);
|
||||
first1 = r.first;
|
||||
result = r.third;
|
||||
}
|
||||
const local_result_t r = (set_intersection_seg2_dispatch)
|
||||
(first1, last1, lf2, src2_traits::local(last2), result, comp,
|
||||
src2_is_local_seg_t(), cat);
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -266,12 +277,7 @@ segtrio<SegIt, InIter2, OutIter> set_intersection_scan
|
||||
segment_iterator const slast = traits::segment(last);
|
||||
local_iterator lcur = traits::local(first);
|
||||
|
||||
if(scur == slast) {
|
||||
local_result_t r = set_intersection_scan
|
||||
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
}
|
||||
else {
|
||||
if(BOOST_CONTAINER_SEG_LIKELY(scur != slast)) {
|
||||
local_result_t r = set_intersection_scan
|
||||
(lcur, traits::end(scur), first2, last2, result, comp, is_local_seg_t());
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(r.second == last2))
|
||||
@@ -284,10 +290,13 @@ segtrio<SegIt, InIter2, OutIter> set_intersection_scan
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
}
|
||||
|
||||
r = set_intersection_scan
|
||||
(traits::begin(scur), traits::local(last), r.second, last2, r.third, comp, is_local_seg_t());
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
lcur = traits::begin(slast);
|
||||
first2 = r.second;
|
||||
result = r.third;
|
||||
}
|
||||
const local_result_t r = set_intersection_scan
|
||||
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
}
|
||||
|
||||
} // namespace detail_algo
|
||||
|
||||
@@ -55,14 +55,23 @@ set_symmetric_difference_dst_bounded
|
||||
(Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2,
|
||||
DstIter dst_first, DstSent dst_last, Comp comp, DstTag, SrcCat)
|
||||
{
|
||||
while(first1 != last1 && first2 != last2 && dst_first != dst_last) {
|
||||
// The destination-full test guards the write, not the whole iteration: an
|
||||
// element that produces no output still has to be consumed, so stopping
|
||||
// with room left in the sources but none in the destination would leave
|
||||
// the segmented walker unable to tell a full segment from an exhausted
|
||||
// destination. With unreachable_sentinel_t the test folds away as before.
|
||||
while(first1 != last1 && first2 != last2) {
|
||||
if (comp(*first1, *first2)) {
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_first == dst_last))
|
||||
break;
|
||||
*dst_first = *first1;
|
||||
++first1;
|
||||
++dst_first;
|
||||
}
|
||||
else {
|
||||
if (comp(*first2, *first1)) {
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_first == dst_last))
|
||||
break;
|
||||
*dst_first = *first2;
|
||||
++dst_first;
|
||||
}
|
||||
@@ -153,7 +162,6 @@ segtrio<Iter1, Iter2, DstIter> set_symmetric_difference_until_exhausts
|
||||
|
||||
template <class Iter1, class Sent1, class Iter2, class Sent2, class SegDstIter,
|
||||
class Comp, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
segtrio<Iter1, Iter2, SegDstIter> set_symmetric_difference_until_exhausts
|
||||
(Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2, SegDstIter result, Comp comp,
|
||||
const segmented_iterator_tag &, const Cat &src1_cat)
|
||||
@@ -180,9 +188,15 @@ segtrio<Iter1, Iter2, SegDstIter> set_symmetric_difference_until_exhausts
|
||||
first2 = r.second;
|
||||
dst_local = r.third;
|
||||
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_local != dst_end)) {
|
||||
// Stop on source exhaustion, not on "the segment did not fill": when
|
||||
// the output ends exactly on a segment boundary both hold at once, and
|
||||
// stepping dst_seg then walks off the end of the destination. compose()
|
||||
// normalises a local iterator sitting on the segment end, the same way
|
||||
// segmented_copy_dst_dispatch relies on.
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(first1 == last1 || first2 == last2)) {
|
||||
return result_t(first1, first2, dst_traits::compose(dst_seg, dst_local));
|
||||
}
|
||||
// dst segment full and both sources still live; advance to the next.
|
||||
++dst_seg;
|
||||
dst_local = dst_traits::begin(dst_seg);
|
||||
}
|
||||
@@ -207,7 +221,6 @@ BOOST_CONTAINER_FORCEINLINE segtrio<Iter1, Iter2, OutIter> set_symmetric_differe
|
||||
}
|
||||
|
||||
template <class Iter1, class Sent1, class SegIter2, class OutIter, class Comp, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
segtrio<Iter1, SegIter2, OutIter> set_symmetric_difference_seg2_dispatch
|
||||
(Iter1 first1, Sent1 last1, SegIter2 first2, SegIter2 last2, OutIter result, Comp comp,
|
||||
segmented_iterator_tag, const Cat & cat)
|
||||
@@ -227,33 +240,29 @@ segtrio<Iter1, SegIter2, OutIter> set_symmetric_difference_seg2_dispatch
|
||||
const src2_segment_iterator sl2 = src2_traits::segment(last2);
|
||||
src2_local_iterator lf2 = src2_traits::local(first2);
|
||||
|
||||
if(sf2 == sl2) {
|
||||
local_result_t r = (set_symmetric_difference_seg2_dispatch)
|
||||
(first1, last1, lf2, src2_traits::local(last2), result, comp,
|
||||
src2_is_local_seg_t(), cat);
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
}
|
||||
else {
|
||||
if(BOOST_CONTAINER_SEG_LIKELY(sf2 != sl2)) {
|
||||
local_result_t r = (set_symmetric_difference_seg2_dispatch)
|
||||
(first1, last1, lf2, src2_traits::end(sf2), result, comp,
|
||||
src2_is_local_seg_t(), cat);
|
||||
if (BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
|
||||
goto exit;
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
|
||||
for(++sf2; sf2 != sl2; ++sf2) {
|
||||
r = (set_symmetric_difference_seg2_dispatch)
|
||||
(r.first, last1, src2_traits::begin(sf2), src2_traits::end(sf2),
|
||||
r.third, comp, src2_is_local_seg_t(), cat);
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
|
||||
goto exit;
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
}
|
||||
|
||||
r = (set_symmetric_difference_seg2_dispatch)
|
||||
(r.first, last1, src2_traits::begin(sf2), src2_traits::local(last2),
|
||||
r.third, comp, src2_is_local_seg_t(), cat);
|
||||
exit:
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
lf2 = src2_traits::begin(sl2);
|
||||
first1 = r.first;
|
||||
result = r.third;
|
||||
}
|
||||
const local_result_t r = (set_symmetric_difference_seg2_dispatch)
|
||||
(first1, last1, lf2, src2_traits::local(last2), result, comp,
|
||||
src2_is_local_seg_t(), cat);
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -278,7 +287,6 @@ BOOST_CONTAINER_FORCEINLINE segtrio<FwdIt, InIter2, OutIter> set_symmetric_diffe
|
||||
}
|
||||
|
||||
template <class SegIt, class InIter2, class Sent2, class OutIter, class Comp>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
segtrio<SegIt, InIter2, OutIter> set_symmetric_difference_scan
|
||||
(SegIt first, SegIt last, InIter2 first2, Sent2 last2, OutIter result, Comp comp,
|
||||
segmented_iterator_tag)
|
||||
@@ -298,12 +306,7 @@ segtrio<SegIt, InIter2, OutIter> set_symmetric_difference_scan
|
||||
segment_iterator const slast = traits::segment(last);
|
||||
local_iterator lcur = traits::local(first);
|
||||
|
||||
if(scur == slast) {
|
||||
local_result_t r = set_symmetric_difference_scan
|
||||
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
}
|
||||
else {
|
||||
if(BOOST_CONTAINER_SEG_LIKELY(scur != slast)) {
|
||||
local_result_t r = set_symmetric_difference_scan
|
||||
(lcur, traits::end(scur), first2, last2, result, comp, is_local_seg_t());
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(r.second == last2))
|
||||
@@ -316,10 +319,13 @@ segtrio<SegIt, InIter2, OutIter> set_symmetric_difference_scan
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
}
|
||||
|
||||
r = set_symmetric_difference_scan
|
||||
(traits::begin(scur), traits::local(last), r.second, last2, r.third, comp, is_local_seg_t());
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
lcur = traits::begin(slast);
|
||||
first2 = r.second;
|
||||
result = r.third;
|
||||
}
|
||||
const local_result_t r = set_symmetric_difference_scan
|
||||
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
}
|
||||
|
||||
} // namespace detail_algo
|
||||
|
||||
@@ -126,7 +126,6 @@ segtrio<Iter1, Iter2, DstIter> set_union_until_exhausts
|
||||
|
||||
template <class Iter1, class Sent1, class Iter2, class Sent2, class SegDstIter,
|
||||
class Comp, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
segtrio<Iter1, Iter2, SegDstIter> set_union_until_exhausts
|
||||
(Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2, SegDstIter result, Comp comp,
|
||||
const segmented_iterator_tag &, const Cat &src1_cat)
|
||||
@@ -153,9 +152,15 @@ segtrio<Iter1, Iter2, SegDstIter> set_union_until_exhausts
|
||||
first2 = r.second;
|
||||
dst_local = r.third;
|
||||
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_local != dst_end)) {
|
||||
// Stop on source exhaustion, not on "the segment did not fill": when
|
||||
// the output ends exactly on a segment boundary both hold at once, and
|
||||
// stepping dst_seg then walks off the end of the destination. compose()
|
||||
// normalises a local iterator sitting on the segment end, the same way
|
||||
// segmented_copy_dst_dispatch relies on.
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(first1 == last1 || first2 == last2)) {
|
||||
return result_t(first1, first2, dst_traits::compose(dst_seg, dst_local));
|
||||
}
|
||||
// dst segment full and both sources still live; advance to the next.
|
||||
++dst_seg;
|
||||
dst_local = dst_traits::begin(dst_seg);
|
||||
}
|
||||
@@ -180,7 +185,6 @@ BOOST_CONTAINER_FORCEINLINE segtrio<Iter1, Iter2, OutIter> set_union_seg2_dispat
|
||||
}
|
||||
|
||||
template <class Iter1, class Sent1, class SegIter2, class OutIter, class Comp, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
segtrio<Iter1, SegIter2, OutIter> set_union_seg2_dispatch
|
||||
(Iter1 first1, Sent1 last1, SegIter2 first2, SegIter2 last2, OutIter result, Comp comp,
|
||||
segmented_iterator_tag, const Cat & cat)
|
||||
@@ -200,33 +204,29 @@ segtrio<Iter1, SegIter2, OutIter> set_union_seg2_dispatch
|
||||
const src2_segment_iterator sl2 = src2_traits::segment(last2);
|
||||
src2_local_iterator lf2 = src2_traits::local(first2);
|
||||
|
||||
if(sf2 == sl2) {
|
||||
local_result_t r = (set_union_seg2_dispatch)
|
||||
(first1, last1, lf2, src2_traits::local(last2), result, comp,
|
||||
src2_is_local_seg_t(), cat);
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
}
|
||||
else {
|
||||
if(BOOST_CONTAINER_SEG_LIKELY(sf2 != sl2)) {
|
||||
local_result_t r = (set_union_seg2_dispatch)
|
||||
(first1, last1, lf2, src2_traits::end(sf2), result, comp,
|
||||
src2_is_local_seg_t(), cat);
|
||||
if (BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
|
||||
goto exit;
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
|
||||
for(++sf2; sf2 != sl2; ++sf2) {
|
||||
r = (set_union_seg2_dispatch)
|
||||
(r.first, last1, src2_traits::begin(sf2), src2_traits::end(sf2),
|
||||
r.third, comp, src2_is_local_seg_t(), cat);
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
|
||||
goto exit;
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
}
|
||||
|
||||
r = (set_union_seg2_dispatch)
|
||||
(r.first, last1, src2_traits::begin(sf2), src2_traits::local(last2),
|
||||
r.third, comp, src2_is_local_seg_t(), cat);
|
||||
exit:
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
lf2 = src2_traits::begin(sl2);
|
||||
first1 = r.first;
|
||||
result = r.third;
|
||||
}
|
||||
const local_result_t r = (set_union_seg2_dispatch)
|
||||
(first1, last1, lf2, src2_traits::local(last2), result, comp,
|
||||
src2_is_local_seg_t(), cat);
|
||||
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -251,7 +251,6 @@ BOOST_CONTAINER_FORCEINLINE segtrio<FwdIt, InIter2, OutIter> set_union_scan
|
||||
}
|
||||
|
||||
template <class SegIt, class InIter2, class Sent2, class OutIter, class Comp>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
segtrio<SegIt, InIter2, OutIter> set_union_scan
|
||||
(SegIt first, SegIt last, InIter2 first2, Sent2 last2, OutIter result, Comp comp,
|
||||
segmented_iterator_tag)
|
||||
@@ -271,12 +270,7 @@ segtrio<SegIt, InIter2, OutIter> set_union_scan
|
||||
segment_iterator const slast = traits::segment(last);
|
||||
local_iterator lcur = traits::local(first);
|
||||
|
||||
if(scur == slast) {
|
||||
local_result_t r = set_union_scan
|
||||
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
}
|
||||
else {
|
||||
if(BOOST_CONTAINER_SEG_LIKELY(scur != slast)) {
|
||||
local_result_t r = set_union_scan
|
||||
(lcur, traits::end(scur), first2, last2, result, comp, is_local_seg_t());
|
||||
if(BOOST_CONTAINER_SEG_UNLIKELY(r.second == last2))
|
||||
@@ -289,10 +283,13 @@ segtrio<SegIt, InIter2, OutIter> set_union_scan
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
}
|
||||
|
||||
r = set_union_scan
|
||||
(traits::begin(scur), traits::local(last), r.second, last2, r.third, comp, is_local_seg_t());
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
lcur = traits::begin(slast);
|
||||
first2 = r.second;
|
||||
result = r.third;
|
||||
}
|
||||
const local_result_t r = set_union_scan
|
||||
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
|
||||
return result_t(traits::compose(scur, r.first), r.second, r.third);
|
||||
}
|
||||
|
||||
} // namespace detail_algo
|
||||
|
||||
Reference in New Issue
Block a user