@@ -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,62 @@ 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 }
1997+ if (len == 1 ) {
1998+ return {it, len, string_type (1 , *it)};
1999+ }
2000+ ranges::advance (it, static_cast <std::ptrdiff_t >(len), range.end ());
2001+ return {it, len, string_type (range.begin (), it)};
2002+ }
20082003
2004+ template <typename Range>
2005+ auto advance_code_point_into (
2006+ Range range,
2007+ const read_code_point_into_result<ranges::const_iterator_t <Range>,
2008+ detail::char_t <Range>>& result)
2009+ -> ranges::const_iterator_t<Range>
2010+ {
2011+ auto it = result.iterator ;
2012+ const auto & len = result.codepoint_length ;
2013+
2014+ if (SCN_UNLIKELY (len == 0 )) {
2015+ ++it;
2016+ return get_start_for_next_code_point (ranges::subrange{it, range.end ()});
2017+ }
20092018 if (len == 1 ) {
20102019 ++it;
2011- return {it, string_type (1 , *range.begin ())};
20122020 }
2021+ return it;
2022+ }
20132023
2014- ranges::advance (it, static_cast <std::ptrdiff_t >(len), range.end ());
2015- return {it, string_type{range.begin (), it}};
2024+ template <typename Range>
2025+ auto read_code_point_into (Range range)
2026+ -> read_code_point_into_result<ranges::const_iterator_t<Range>,
2027+ detail::char_t<Range>>
2028+ {
2029+ auto result = extract_code_point_into (range);
2030+ result.iterator = advance_code_point_into (range, result);
2031+ return result;
20162032}
20172033
20182034template <typename Range>
20192035auto read_code_point (Range range) -> ranges::const_iterator_t<Range>
20202036{
2021- return read_code_point_into (range).iterator ;
2037+ SCN_EXPECT (!is_range_eof (range));
2038+
2039+ auto it = range.begin ();
2040+ const auto len = detail::code_point_length_by_starting_code_unit (*it);
2041+
2042+ if (SCN_UNLIKELY (len == 0 )) {
2043+ ++it;
2044+ return get_start_for_next_code_point (ranges::subrange{it, range.end ()});
2045+ }
2046+ if (len == 1 ) {
2047+ return ++it;
2048+ }
2049+ ranges::advance (it, static_cast <std::ptrdiff_t >(len), range.end ());
2050+ return it;
20222051}
20232052
20242053template <typename Range>
@@ -2158,16 +2187,16 @@ auto read_until_code_point(Range range, function_ref<bool(char32_t)> pred)
21582187{
21592188 auto it = range.begin ();
21602189 while (it != range.end ()) {
2161- const auto val =
2162- read_code_point_into (ranges:: subrange{it, range. end ()} );
2190+ auto subrange = ranges::subrange{it, range. end ()};
2191+ const auto val = extract_code_point_into ( subrange);
21632192 if (SCN_LIKELY (val.is_valid ())) {
21642193 const auto cp = detail::decode_code_point_exhaustive (
21652194 std::basic_string_view<detail::char_t <Range>>{val.codepoint });
21662195 if (pred (cp)) {
21672196 return it;
21682197 }
21692198 }
2170- it = val. iterator ;
2199+ it = advance_code_point_into (subrange, val) ;
21712200 }
21722201
21732202 return it;
@@ -2242,32 +2271,31 @@ template <typename Range>
22422271auto read_matching_code_unit (Range range, detail::char_t <Range> ch)
22432272 -> parse_expected<ranges::const_iterator_t<Range>>
22442273{
2245- auto it = read_code_unit (range);
2246- if (SCN_UNLIKELY (!it)) {
2247- return unexpected (make_eof_parse_error (it.error ()));
2274+ if (auto e = eof_check (range); SCN_UNLIKELY (!e)) {
2275+ return unexpected (make_eof_parse_error (e));
22482276 }
22492277
22502278 if (SCN_UNLIKELY (*range.begin () !=
22512279 static_cast <detail::char_t <Range>>(ch))) {
22522280 return unexpected (parse_error::error);
22532281 }
22542282
2255- return *it ;
2283+ return ranges::next (range. begin ()) ;
22562284}
22572285
22582286template <typename Range>
22592287auto read_matching_code_point (Range range, char32_t cp)
22602288 -> parse_expected<ranges::const_iterator_t<Range>>
22612289{
2262- auto val = read_code_point_into (range);
2290+ auto val = extract_code_point_into (range);
22632291 if (!val.is_valid ()) {
22642292 return unexpected (parse_error::error);
22652293 }
22662294 auto decoded_cp = decode_code_point_exhaustive (val.codepoint );
22672295 if (SCN_UNLIKELY (cp != decoded_cp)) {
22682296 return unexpected (parse_error::error);
22692297 }
2270- return val. iterator ;
2298+ return advance_code_point_into (range, val) ;
22712299}
22722300
22732301template <typename Range>
@@ -2286,33 +2314,6 @@ auto read_matching_string(Range range,
22862314 return it;
22872315}
22882316
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-
23162317// Ripped from fast_float
23172318constexpr bool fast_streq_nocase (const char * a, const char * b, size_t len)
23182319{
@@ -2348,16 +2349,15 @@ auto read_matching_string_classic_nocase(Range range, std::string_view str)
23482349 static_cast <char_type>(' a' - ' A' ));
23492350 };
23502351
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);
2352+ auto it = range.begin ();
2353+ for (std::size_t i = 0 ; i < str.size (); ++i, (void )++it) {
2354+ if (it == range.end ()) {
2355+ return unexpected (make_eof_parse_error (eof_error::eof));
2356+ }
2357+ if (SCN_UNLIKELY (ascii_tolower (*it) !=
2358+ static_cast <detail::char_t <Range>>(str[i]))) {
2359+ return unexpected (parse_error::error);
2360+ }
23612361 }
23622362
23632363 return it;
@@ -2368,14 +2368,13 @@ template <typename Range>
23682368auto read_one_of_code_unit (Range range, std::string_view str)
23692369 -> parse_expected<ranges::const_iterator_t<Range>>
23702370{
2371- auto it = read_code_unit (range);
2372- if (SCN_UNLIKELY (!it)) {
2373- return unexpected (make_eof_parse_error (it.error ()));
2371+ if (auto e = eof_check (range); SCN_UNLIKELY (!e)) {
2372+ return unexpected (make_eof_parse_error (e));
23742373 }
23752374
23762375 for (auto ch : str) {
23772376 if (*range.begin () == static_cast <detail::char_t <Range>>(ch)) {
2378- return *it ;
2377+ return ranges::next (range. begin ()) ;
23792378 }
23802379 }
23812380
@@ -5426,11 +5425,11 @@ struct bool_reader_base {
54265425 auto read_textual_classic (Range range, bool & value) const
54275426 -> scan_expected<ranges::const_iterator_t<Range>>
54285427 {
5429- if (auto r = read_matching_string_classic (range, " true" )) {
5428+ if (auto r = read_matching_string_classic_nocase (range, " true" )) {
54305429 value = true ;
54315430 return *r;
54325431 }
5433- if (auto r = read_matching_string_classic (range, " false" )) {
5432+ if (auto r = read_matching_string_classic_nocase (range, " false" )) {
54345433 value = false ;
54355434 return *r;
54365435 }
@@ -5605,15 +5604,15 @@ class code_point_reader<char32_t> {
56055604 auto read (const SourceRange& range, char32_t & cp)
56065605 -> scan_expected<ranges::const_iterator_t<SourceRange>>
56075606 {
5608- auto result = read_code_point_into (range);
5607+ auto result = extract_code_point_into (range);
56095608 if (SCN_UNLIKELY (!result.is_valid ())) {
56105609 return detail::unexpected_scan_error (
56115610 scan_error::invalid_scanned_value, " Invalid code point" );
56125611 }
56135612 cp = detail::decode_code_point_exhaustive_valid (
56145613 std::basic_string_view<detail::char_t <SourceRange>>{
56155614 result.codepoint });
5616- return result. iterator ;
5615+ return advance_code_point_into (range, result) ;
56175616 }
56185617};
56195618
@@ -5826,6 +5825,16 @@ auto skip_ws_before_if_required(bool is_required, Range range)
58265825 return unexpected (e);
58275826 }
58285827
5828+ if constexpr (std::is_same_v<
5829+ ranges::const_iterator_t <Range>,
5830+ typename detail::basic_scan_buffer<
5831+ detail::char_t <Range>>::forward_iterator>) {
5832+ auto beg = range.begin ();
5833+ if (beg.stores_parent ()) {
5834+ beg.parent ()->set_skip_whitespace (is_required);
5835+ }
5836+ }
5837+
58295838 if (!is_required) {
58305839 return range.begin ();
58315840 }
0 commit comments