@@ -1197,12 +1197,7 @@ bool basic_scan_file_buffer<FileInterface>::sync(std::ptrdiff_t position)
11971197 static_cast <std::ptrdiff_t >(this ->putback_buffer ().size ())) {
11981198 putback_wrapper wrapper{m_file};
11991199 auto segment = this ->get_segment_starting_at (position);
1200- for (auto it = segment.rbegin (); it != segment.rend (); ++it) {
1201- if (!m_file.putback (*it)) {
1202- return false ;
1203- }
1204- }
1205- return true ;
1200+ return segment.empty ();
12061201 }
12071202
12081203 m_file.unsafe_advance_n (position - static_cast <std::ptrdiff_t >(
@@ -1219,12 +1214,7 @@ bool basic_scan_file_buffer<FileInterface>::sync(std::ptrdiff_t position)
12191214 m_file.putback (m_current_view.front ());
12201215
12211216 auto segment = std::string_view{this ->putback_buffer ()}.substr (position);
1222- for (auto it = segment.rbegin (); it != segment.rend (); ++it) {
1223- if (!m_file.putback (*it)) {
1224- return false ;
1225- }
1226- }
1227- return true ;
1217+ return segment.empty ();
12281218}
12291219
12301220} // namespace detail
@@ -1981,6 +1971,7 @@ auto read_exactly_n_code_units(Range range, std::ptrdiff_t count)
19811971template <typename Iterator, typename CharT>
19821972struct read_code_point_into_result {
19831973 Iterator iterator;
1974+ std::size_t codepoint_length;
19841975 std::basic_string<CharT> codepoint;
19851976
19861977 bool is_valid () const
@@ -1990,7 +1981,7 @@ struct read_code_point_into_result {
19901981};
19911982
19921983template <typename Range>
1993- auto read_code_point_into (Range range)
1984+ auto extract_code_point_into (Range range)
19941985 -> read_code_point_into_result<ranges::const_iterator_t<Range>,
19951986 detail::char_t<Range>>
19961987{
@@ -2001,24 +1992,72 @@ auto read_code_point_into(Range range)
20011992 const auto len = detail::code_point_length_by_starting_code_unit (*it);
20021993
20031994 if (SCN_UNLIKELY (len == 0 )) {
2004- ++it;
2005- it = get_start_for_next_code_point (ranges::subrange{it, range.end ()});
2006- return {it, {}};
1995+ return {it, len, {}};
20071996 }
2008-
20091997 if (len == 1 ) {
1998+ return {it, len, string_type (1 , *it)};
1999+ }
2000+ ranges::advance (it, static_cast <std::ptrdiff_t >(len - 1 ), range.end ());
2001+ const auto real_len = ranges::distance (range.begin (), it) + 1 ;;
2002+ SCN_EXPECT (real_len <= 4 );
2003+ if (SCN_LIKELY (real_len == len && it != range.end ())) {
2004+ auto it2 = range.begin ();
2005+ string_type result (len, *it2);
2006+ for (std::size_t i = 1 ; i < len; ++i) {
2007+ result[i] = *(++it2);
2008+ }
2009+ return {it, len, std::move (result)};
2010+ }
2011+ return {it, len, string_type (range.begin (), it)};
2012+ }
2013+
2014+ template <typename Range>
2015+ auto advance_code_point_into (
2016+ Range range,
2017+ const read_code_point_into_result<ranges::const_iterator_t <Range>,
2018+ detail::char_t <Range>>& result)
2019+ -> ranges::const_iterator_t<Range>
2020+ {
2021+ auto it = result.iterator ;
2022+ const auto & len = result.codepoint_length ;
2023+
2024+ if (SCN_UNLIKELY (len == 0 )) {
2025+ ++it;
2026+ return get_start_for_next_code_point (ranges::subrange{it, range.end ()});
2027+ }
2028+ if (it != range.end ()) {
20102029 ++it;
2011- return {it, string_type (1 , *range.begin ())};
20122030 }
2031+ return it;
2032+ }
20132033
2014- ranges::advance (it, static_cast <std::ptrdiff_t >(len), range.end ());
2015- return {it, string_type{range.begin (), it}};
2034+ template <typename Range>
2035+ auto read_code_point_into (Range range)
2036+ -> read_code_point_into_result<ranges::const_iterator_t<Range>,
2037+ detail::char_t<Range>>
2038+ {
2039+ auto result = extract_code_point_into (range);
2040+ result.iterator = advance_code_point_into (range, result);
2041+ return result;
20162042}
20172043
20182044template <typename Range>
20192045auto read_code_point (Range range) -> ranges::const_iterator_t<Range>
20202046{
2021- return read_code_point_into (range).iterator ;
2047+ SCN_EXPECT (!is_range_eof (range));
2048+
2049+ auto it = range.begin ();
2050+ const auto len = detail::code_point_length_by_starting_code_unit (*it);
2051+
2052+ if (SCN_UNLIKELY (len == 0 )) {
2053+ ++it;
2054+ return get_start_for_next_code_point (ranges::subrange{it, range.end ()});
2055+ }
2056+ if (len == 1 ) {
2057+ return ++it;
2058+ }
2059+ ranges::advance (it, static_cast <std::ptrdiff_t >(len), range.end ());
2060+ return it;
20222061}
20232062
20242063template <typename Range>
@@ -2158,16 +2197,16 @@ auto read_until_code_point(Range range, function_ref<bool(char32_t)> pred)
21582197{
21592198 auto it = range.begin ();
21602199 while (it != range.end ()) {
2161- const auto val =
2162- read_code_point_into (ranges:: subrange{it, range. end ()} );
2200+ auto subrange = ranges::subrange{it, range. end ()};
2201+ const auto val = extract_code_point_into ( subrange);
21632202 if (SCN_LIKELY (val.is_valid ())) {
21642203 const auto cp = detail::decode_code_point_exhaustive (
21652204 std::basic_string_view<detail::char_t <Range>>{val.codepoint });
21662205 if (pred (cp)) {
21672206 return it;
21682207 }
21692208 }
2170- it = val. iterator ;
2209+ it = advance_code_point_into (subrange, val) ;
21712210 }
21722211
21732212 return it;
@@ -2242,32 +2281,31 @@ template <typename Range>
22422281auto read_matching_code_unit (Range range, detail::char_t <Range> ch)
22432282 -> parse_expected<ranges::const_iterator_t<Range>>
22442283{
2245- auto it = read_code_unit (range);
2246- if (SCN_UNLIKELY (!it)) {
2247- return unexpected (make_eof_parse_error (it.error ()));
2284+ if (auto e = eof_check (range); SCN_UNLIKELY (!e)) {
2285+ return unexpected (make_eof_parse_error (e));
22482286 }
22492287
22502288 if (SCN_UNLIKELY (*range.begin () !=
22512289 static_cast <detail::char_t <Range>>(ch))) {
22522290 return unexpected (parse_error::error);
22532291 }
22542292
2255- return *it ;
2293+ return ranges::next (range. begin ()) ;
22562294}
22572295
22582296template <typename Range>
22592297auto read_matching_code_point (Range range, char32_t cp)
22602298 -> parse_expected<ranges::const_iterator_t<Range>>
22612299{
2262- auto val = read_code_point_into (range);
2300+ auto val = extract_code_point_into (range);
22632301 if (!val.is_valid ()) {
22642302 return unexpected (parse_error::error);
22652303 }
22662304 auto decoded_cp = decode_code_point_exhaustive (val.codepoint );
22672305 if (SCN_UNLIKELY (cp != decoded_cp)) {
22682306 return unexpected (parse_error::error);
22692307 }
2270- return val. iterator ;
2308+ return advance_code_point_into (range, val) ;
22712309}
22722310
22732311template <typename Range>
@@ -2286,33 +2324,6 @@ auto read_matching_string(Range range,
22862324 return it;
22872325}
22882326
2289- template <typename Range>
2290- auto read_matching_string_classic (Range range, std::string_view str)
2291- -> parse_expected<ranges::const_iterator_t<Range>>
2292- {
2293- SCN_TRY (it, read_exactly_n_code_units (
2294- range, static_cast <std::ptrdiff_t >(str.size ()))
2295- .transform_error (make_eof_parse_error));
2296-
2297- if constexpr (std::is_same_v<detail::char_t <Range>, char >) {
2298- auto sv = make_contiguous_buffer (ranges::subrange{range.begin (), it});
2299- if (SCN_UNLIKELY (sv.view () != str)) {
2300- return unexpected (parse_error::error);
2301- }
2302- return it;
2303- }
2304- else {
2305- auto range_it = range.begin ();
2306- for (size_t i = 0 ; i < str.size (); ++i, (void )++range_it) {
2307- if (SCN_UNLIKELY (*range_it !=
2308- static_cast <detail::char_t <Range>>(str[i]))) {
2309- return unexpected (parse_error::error);
2310- }
2311- }
2312- return it;
2313- }
2314- }
2315-
23162327// Ripped from fast_float
23172328constexpr bool fast_streq_nocase (const char * a, const char * b, size_t len)
23182329{
@@ -2348,16 +2359,15 @@ auto read_matching_string_classic_nocase(Range range, std::string_view str)
23482359 static_cast <char_type>(' a' - ' A' ));
23492360 };
23502361
2351- SCN_TRY (it, read_exactly_n_code_units (
2352- range, static_cast <std::ptrdiff_t >(str.size ()))
2353- .transform_error (make_eof_parse_error));
2354-
2355- if (SCN_UNLIKELY (!std::equal (
2356- range.begin (), it, str.begin (), [&](auto a, auto b) {
2357- return ascii_tolower (a) ==
2358- static_cast <detail::char_t <Range>>(b);
2359- }))) {
2360- return unexpected (parse_error::error);
2362+ auto it = range.begin ();
2363+ for (std::size_t i = 0 ; i < str.size (); ++i, (void )++it) {
2364+ if (it == range.end ()) {
2365+ return unexpected (make_eof_parse_error (eof_error::eof));
2366+ }
2367+ if (SCN_UNLIKELY (ascii_tolower (*it) !=
2368+ static_cast <detail::char_t <Range>>(str[i]))) {
2369+ return unexpected (parse_error::error);
2370+ }
23612371 }
23622372
23632373 return it;
@@ -2368,14 +2378,13 @@ template <typename Range>
23682378auto read_one_of_code_unit (Range range, std::string_view str)
23692379 -> parse_expected<ranges::const_iterator_t<Range>>
23702380{
2371- auto it = read_code_unit (range);
2372- if (SCN_UNLIKELY (!it)) {
2373- return unexpected (make_eof_parse_error (it.error ()));
2381+ if (auto e = eof_check (range); SCN_UNLIKELY (!e)) {
2382+ return unexpected (make_eof_parse_error (e));
23742383 }
23752384
23762385 for (auto ch : str) {
23772386 if (*range.begin () == static_cast <detail::char_t <Range>>(ch)) {
2378- return *it ;
2387+ return ranges::next (range. begin ()) ;
23792388 }
23802389 }
23812390
@@ -5426,11 +5435,11 @@ struct bool_reader_base {
54265435 auto read_textual_classic (Range range, bool & value) const
54275436 -> scan_expected<ranges::const_iterator_t<Range>>
54285437 {
5429- if (auto r = read_matching_string_classic (range, " true" )) {
5438+ if (auto r = read_matching_string_classic_nocase (range, " true" )) {
54305439 value = true ;
54315440 return *r;
54325441 }
5433- if (auto r = read_matching_string_classic (range, " false" )) {
5442+ if (auto r = read_matching_string_classic_nocase (range, " false" )) {
54345443 value = false ;
54355444 return *r;
54365445 }
@@ -5605,15 +5614,15 @@ class code_point_reader<char32_t> {
56055614 auto read (const SourceRange& range, char32_t & cp)
56065615 -> scan_expected<ranges::const_iterator_t<SourceRange>>
56075616 {
5608- auto result = read_code_point_into (range);
5617+ auto result = extract_code_point_into (range);
56095618 if (SCN_UNLIKELY (!result.is_valid ())) {
56105619 return detail::unexpected_scan_error (
56115620 scan_error::invalid_scanned_value, " Invalid code point" );
56125621 }
56135622 cp = detail::decode_code_point_exhaustive_valid (
56145623 std::basic_string_view<detail::char_t <SourceRange>>{
56155624 result.codepoint });
5616- return result. iterator ;
5625+ return advance_code_point_into (range, result) ;
56175626 }
56185627};
56195628
@@ -5826,6 +5835,16 @@ auto skip_ws_before_if_required(bool is_required, Range range)
58265835 return unexpected (e);
58275836 }
58285837
5838+ if constexpr (std::is_same_v<
5839+ ranges::const_iterator_t <Range>,
5840+ typename detail::basic_scan_buffer<
5841+ detail::char_t <Range>>::forward_iterator>) {
5842+ auto beg = range.begin ();
5843+ if (beg.stores_parent ()) {
5844+ beg.parent ()->set_skip_whitespace (is_required);
5845+ }
5846+ }
5847+
58295848 if (!is_required) {
58305849 return range.begin ();
58315850 }
0 commit comments