| 341 | |
| 342 | template<typename Iter> |
| 343 | constexpr Iter decrement(Iter it) |
| 344 | { |
| 345 | Iter retval = it; |
| 346 | |
| 347 | int backup = 0; |
| 348 | while (backup < 4 && boost::parser::detail::text::continuation(*--retval)) { |
| 349 | ++backup; |
| 350 | } |
| 351 | backup = it - retval; |
| 352 | |
| 353 | if (boost::parser::detail::text::continuation(*retval)) |
| 354 | return it - 1; |
| 355 | |
| 356 | optional_iter<Iter> first_invalid = end_of_invalid_utf8(retval); |
| 357 | if (first_invalid == retval) |
| 358 | ++*first_invalid; |
| 359 | while (first_invalid && (*first_invalid - retval) < backup) { |
| 360 | backup -= *first_invalid - retval; |
| 361 | retval = *first_invalid; |
| 362 | first_invalid = end_of_invalid_utf8(retval); |
| 363 | if (first_invalid == retval) |
| 364 | ++*first_invalid; |
| 365 | } |
| 366 | |
| 367 | if (1 < backup) { |
| 368 | int const cp_bytes = boost::parser::detail::text::utf8_code_units(*retval); |
| 369 | if (cp_bytes < backup) |
| 370 | retval = it - 1; |
| 371 | } |
| 372 | |
| 373 | return retval; |
| 374 | } |
| 375 | |
| 376 | template<typename Iter> |
| 377 | constexpr Iter decrement(Iter first, Iter it) |
no test coverage detected