Warning, file /include/boost/parser/detail/text/algorithm.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006 #ifndef BOOST_PARSER_DETAIL_TEXT_ALGORITHM_HPP
0007 #define BOOST_PARSER_DETAIL_TEXT_ALGORITHM_HPP
0008
0009 #include <boost/parser/detail/text/config.hpp>
0010 #include <boost/parser/detail/text/detail/algorithm.hpp>
0011 #include <boost/parser/detail/text/detail/sentinel_tag.hpp>
0012
0013 #include <boost/parser/detail/stl_interfaces/view_interface.hpp>
0014
0015 #include <cstddef>
0016 #include <iterator>
0017 #include <utility>
0018
0019
0020 namespace boost::parser::detail { namespace text {
0021
0022 namespace detail {
0023 template<typename Iter>
0024 std::ptrdiff_t distance(Iter first, Iter last, non_sentinel_tag)
0025 {
0026 return std::distance(first, last);
0027 }
0028
0029 template<typename Iter, typename Sentinel>
0030 std::ptrdiff_t distance(Iter first, Sentinel last, sentinel_tag)
0031 {
0032 std::ptrdiff_t retval = 0;
0033 while (first != last) {
0034 ++retval;
0035 ++first;
0036 }
0037 return retval;
0038 }
0039 }
0040
0041
0042
0043 template<typename Iter, typename Sentinel>
0044 std::ptrdiff_t distance(Iter first, Sentinel last)
0045 {
0046 return detail::distance(
0047 first,
0048 last,
0049 typename std::conditional<
0050 std::is_same<Iter, Sentinel>::value,
0051 detail::non_sentinel_tag,
0052 detail::sentinel_tag>::type());
0053 }
0054
0055
0056
0057 template<typename BidiIter, typename Sentinel, typename T>
0058 BidiIter find(BidiIter first, Sentinel last, T const & x)
0059 {
0060 while (first != last) {
0061 if (*first == x)
0062 return first;
0063 ++first;
0064 }
0065 return first;
0066 }
0067
0068
0069
0070 template<typename BidiIter, typename Sentinel, typename T>
0071 BidiIter find_not(BidiIter first, Sentinel last, T const & x)
0072 {
0073 while (first != last) {
0074 if (*first != x)
0075 return first;
0076 ++first;
0077 }
0078 return first;
0079 }
0080
0081
0082
0083 template<typename BidiIter, typename Sentinel, typename Pred>
0084 BidiIter find_if(BidiIter first, Sentinel last, Pred p)
0085 {
0086 while (first != last) {
0087 if (p(*first))
0088 return first;
0089 ++first;
0090 }
0091 return first;
0092 }
0093
0094
0095
0096 template<typename BidiIter, typename Sentinel, typename Pred>
0097 BidiIter find_if_not(BidiIter first, Sentinel last, Pred p)
0098 {
0099 while (first != last) {
0100 if (!p(*first))
0101 return first;
0102 ++first;
0103 }
0104 return first;
0105 }
0106
0107
0108
0109 template<typename BidiIter, typename T>
0110 BidiIter find_backward(BidiIter first, BidiIter last, T const & x)
0111 {
0112 auto it = last;
0113 while (it != first) {
0114 if (*--it == x)
0115 return it;
0116 }
0117 return last;
0118 }
0119
0120
0121
0122 template<typename BidiIter, typename T>
0123 BidiIter find_not_backward(BidiIter first, BidiIter last, T const & x)
0124 {
0125 auto it = last;
0126 while (it != first) {
0127 if (*--it != x)
0128 return it;
0129 }
0130 return last;
0131 }
0132
0133
0134
0135 template<typename BidiIter, typename Pred>
0136 BidiIter find_if_backward(BidiIter first, BidiIter last, Pred p)
0137 {
0138 auto it = last;
0139 while (it != first) {
0140 if (p(*--it))
0141 return it;
0142 }
0143 return last;
0144 }
0145
0146
0147
0148 template<typename BidiIter, typename Pred>
0149 BidiIter find_if_not_backward(BidiIter first, BidiIter last, Pred p)
0150 {
0151 auto it = last;
0152 while (it != first) {
0153 if (!p(*--it))
0154 return it;
0155 }
0156 return last;
0157 }
0158
0159
0160 template<typename Iter, typename Sentinel = Iter>
0161 using foreach_subrange_range =
0162 BOOST_PARSER_DETAIL_TEXT_SUBRANGE<Iter, Sentinel>;
0163
0164
0165
0166
0167
0168 template<typename FwdIter, typename Sentinel, typename Func>
0169 Func foreach_subrange(FwdIter first, Sentinel last, Func f)
0170 {
0171 while (first != last) {
0172 auto const & x = *first;
0173 auto const next = boost::parser::detail::text::find_not(first, last, x);
0174 if (first != next) {
0175 f(boost::parser::detail::text::foreach_subrange_range<FwdIter, Sentinel>(
0176 first, next));
0177 }
0178 first = next;
0179 }
0180 return f;
0181 }
0182
0183
0184
0185
0186
0187 template<typename FwdIter, typename Sentinel, typename Func, typename Proj>
0188 Func foreach_subrange(FwdIter first, Sentinel last, Func f, Proj proj)
0189 {
0190 using value_type = typename std::iterator_traits<FwdIter>::value_type;
0191 while (first != last) {
0192 auto const & x = proj(*first);
0193 auto const next = boost::parser::detail::text::find_if_not(
0194 first, last, [&x, proj](const value_type & element) {
0195 return proj(element) == x;
0196 });
0197 if (first != next) {
0198 f(boost::parser::detail::text::foreach_subrange_range<FwdIter, Sentinel>(
0199 first, next));
0200 }
0201 first = next;
0202 }
0203 return f;
0204 }
0205
0206
0207
0208
0209 template<typename FwdIter, typename Sentinel, typename T, typename Func>
0210 Func foreach_subrange_of(FwdIter first, Sentinel last, T const & x, Func f)
0211 {
0212 while (first != last) {
0213 first = boost::parser::detail::text::find(first, last, x);
0214 auto const next = boost::parser::detail::text::find_not(first, last, x);
0215 if (first != next) {
0216 f(boost::parser::detail::text::foreach_subrange_range<FwdIter, Sentinel>(
0217 first, next));
0218 }
0219 first = next;
0220 }
0221 return f;
0222 }
0223
0224
0225
0226
0227 template<typename FwdIter, typename Sentinel, typename Pred, typename Func>
0228 Func foreach_subrange_if(FwdIter first, Sentinel last, Pred p, Func f)
0229 {
0230 while (first != last) {
0231 first = boost::parser::detail::text::find_if(first, last, p);
0232 auto const next = boost::parser::detail::text::find_if_not(first, last, p);
0233 if (first != next) {
0234 f(boost::parser::detail::text::foreach_subrange_range<FwdIter, Sentinel>(
0235 first, next));
0236 }
0237 first = next;
0238 }
0239 return f;
0240 }
0241
0242
0243 template<typename Iter, typename Sentinel, typename Pred>
0244 bool all_of(Iter first, Sentinel last, Pred p)
0245 {
0246 for (; first != last; ++first) {
0247 if (!p(*first))
0248 return false;
0249 }
0250 return true;
0251 }
0252
0253
0254 template<
0255 typename Iter1,
0256 typename Sentinel1,
0257 typename Iter2,
0258 typename Sentinel2>
0259 bool equal(Iter1 first1, Sentinel1 last1, Iter2 first2, Sentinel2 last2)
0260 {
0261 for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
0262 if (*first1 != *first2)
0263 return false;
0264 }
0265 return first1 == last1 && first2 == last2;
0266 }
0267
0268
0269 template<
0270 typename Iter1,
0271 typename Sentinel1,
0272 typename Iter2,
0273 typename Sentinel2>
0274 std::pair<Iter1, Iter2>
0275 mismatch(Iter1 first1, Sentinel1 last1, Iter2 first2, Sentinel2 last2)
0276 {
0277 for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
0278 if (*first1 != *first2)
0279 break;
0280 }
0281 return {first1, first2};
0282 }
0283
0284
0285
0286
0287 template<
0288 typename Iter1,
0289 typename Sentinel1,
0290 typename Iter2,
0291 typename Sentinel2>
0292 int lexicographical_compare_three_way(
0293 Iter1 first1, Sentinel1 last1, Iter2 first2, Sentinel2 last2)
0294 {
0295 auto const iters = boost::parser::detail::text::mismatch(first1, last1, first2, last2);
0296 if (iters.first == last1) {
0297 if (iters.second == last2)
0298 return 0;
0299 else
0300 return -1;
0301 } else if (iters.second == last2) {
0302 return 1;
0303 } else if (*iters.first < *iters.second) {
0304 return -1;
0305 } else {
0306 return 1;
0307 }
0308 }
0309
0310
0311 template<typename Iter>
0312 using search_result = BOOST_PARSER_DETAIL_TEXT_SUBRANGE<Iter>;
0313
0314
0315 template<
0316 typename Iter1,
0317 typename Sentinel1,
0318 typename Iter2,
0319 typename Sentinel2>
0320 search_result<Iter1>
0321 search(Iter1 first1, Sentinel1 last1, Iter2 first2, Sentinel2 last2)
0322 {
0323 if (first1 == last1 || first2 == last2)
0324 return {first1, first1};
0325
0326 if (detail::next(first2) == last2) {
0327 auto const it = parser::detail::text::find(first1, last1, *first2);
0328 if (it == last1)
0329 return {it, it};
0330 return {it, detail::next(it)};
0331 }
0332
0333 auto it = first1;
0334 for (;;) {
0335 first1 = parser::detail::text::find(first1, last1, *first2);
0336
0337 if (first1 == last1)
0338 return {first1, first1};
0339
0340 auto it2 = detail::next(first2);
0341 it = first1;
0342 if (++it == last1)
0343 return {it, it};
0344
0345 while (*it == *it2) {
0346 if (++it2 == last2)
0347 return {first1, ++it};
0348 if (++it == last1)
0349 return {it, it};
0350 }
0351
0352 ++first1;
0353 }
0354
0355 return {first1, first1};
0356 }
0357
0358
0359 template<
0360 typename Iter1,
0361 typename Sentinel1,
0362 typename Iter2,
0363 typename Sentinel2,
0364 typename Pred>
0365 Iter1 find_first_of(
0366 Iter1 first1, Sentinel1 last1, Iter2 first2, Sentinel2 last2, Pred pred)
0367 {
0368 for (; first1 != last1; ++first1) {
0369 for (auto it = first2; it != last2; ++it) {
0370 if (pred(*first1, *it))
0371 return first1;
0372 }
0373 }
0374 return first1;
0375 }
0376
0377 }}
0378
0379 #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
0380
0381 namespace std::ranges {
0382 template<typename Iter, typename Sentinel>
0383 inline constexpr bool enable_borrowed_range<
0384 boost::parser::detail::text::foreach_subrange_range<Iter, Sentinel>> = true;
0385 }
0386
0387 #endif
0388
0389 #endif