Skip to content

Commit

Permalink
Report scan_error::invalid_source_state on failed sync
Browse files Browse the repository at this point in the history
  • Loading branch information
eliaskosunen committed Nov 3, 2024
1 parent d2807c0 commit e1b7fe2
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 45 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
run: |
git fetch origin master:refs/remotes/origin/master --tags --force
git remote set-head origin -a
git checkout ${{ github.ref_name }}
git checkout master
git pull --force
- name: Prepare repository (on workflow_dispatch)
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ return result;
* Deprecate `visit_scan_arg`, add `basic_scan_arg::visit`
* Remove thousands separator checking when scanning localized numbers
* `scan_error::invalid_source_state` is now returned if syncing with the underlying source fails after `scan`
(like for example, `std::ungetc` fails)
## 3.0.2
Expand Down
87 changes: 43 additions & 44 deletions src/scn/impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1822,14 +1822,49 @@ scan_expected<void> vinput(std::string_view format, scan_args args)
auto buffer = detail::make_file_scan_buffer(stdin);
auto n = vscan_internal(buffer, format, args);
if (n) {
buffer.sync(*n);
if (SCN_UNLIKELY(!buffer.sync(*n))) {
return detail::unexpected_scan_error(
scan_error::invalid_source_state,
"Failed to sync with underlying FILE");
}
return {};
}
buffer.sync_all();
if (SCN_UNLIKELY(!buffer.sync_all())) {
return detail::unexpected_scan_error(
scan_error::invalid_source_state,
"Failed to sync with underlying FILE");
}
return unexpected(n.error());
}

namespace detail {

namespace {

template <typename Source>
scan_expected<std::ptrdiff_t> sync_after_vscan(
Source& source,
scan_expected<std::ptrdiff_t> result)
{
if (SCN_LIKELY(result)) {
if (SCN_UNLIKELY(!source.sync(*result))) {
return detail::unexpected_scan_error(
scan_error::invalid_source_state,
"Failed to sync with underlying source");
}
}
else {
if (SCN_UNLIKELY(!source.sync_all())) {
return detail::unexpected_scan_error(
scan_error::invalid_source_state,
"Failed to sync with underlying source");
}
}
return result;
}

} // namespace

scan_expected<std::ptrdiff_t> vscan_impl(std::string_view source,
std::string_view format,
scan_args args)
Expand All @@ -1841,13 +1876,7 @@ scan_expected<std::ptrdiff_t> vscan_impl(scan_buffer& source,
scan_args args)
{
auto n = vscan_internal(source, format, args);
if (SCN_LIKELY(n)) {
source.sync(*n);
}
else {
source.sync_all();
}
return n;
return sync_after_vscan(source, n);
}

scan_expected<std::ptrdiff_t> vscan_impl(std::wstring_view source,
Expand All @@ -1861,13 +1890,7 @@ scan_expected<std::ptrdiff_t> vscan_impl(wscan_buffer& source,
wscan_args args)
{
auto n = vscan_internal(source, format, args);
if (SCN_LIKELY(n)) {
source.sync(*n);
}
else {
source.sync_all();
}
return n;
return sync_after_vscan(source, n);
}

#if !SCN_DISABLE_LOCALE
Expand All @@ -1886,13 +1909,7 @@ scan_expected<std::ptrdiff_t> vscan_localized_impl(const Locale& loc,
scan_args args)
{
auto n = vscan_internal(source, format, args, detail::locale_ref{loc});
if (SCN_LIKELY(n)) {
source.sync(*n);
}
else {
source.sync_all();
}
return n;
return sync_after_vscan(source, n);
}

template <typename Locale>
Expand All @@ -1910,13 +1927,7 @@ scan_expected<std::ptrdiff_t> vscan_localized_impl(const Locale& loc,
wscan_args args)
{
auto n = vscan_internal(source, format, args, detail::locale_ref{loc});
if (SCN_LIKELY(n)) {
source.sync(*n);
}
else {
source.sync_all();
}
return n;
return sync_after_vscan(source, n);
}

template auto vscan_localized_impl<std::locale>(const std::locale&,
Expand Down Expand Up @@ -1950,13 +1961,7 @@ scan_expected<std::ptrdiff_t> vscan_value_impl(scan_buffer& source,
basic_scan_arg<scan_context> arg)
{
auto n = vscan_value_internal(source, arg);
if (SCN_LIKELY(n)) {
source.sync(*n);
}
else {
source.sync_all();
}
return n;
return sync_after_vscan(source, n);
}

scan_expected<std::ptrdiff_t> vscan_value_impl(
Expand All @@ -1970,13 +1975,7 @@ scan_expected<std::ptrdiff_t> vscan_value_impl(
basic_scan_arg<wscan_context> arg)
{
auto n = vscan_value_internal(source, arg);
if (SCN_LIKELY(n)) {
source.sync(*n);
}
else {
source.sync_all();
}
return n;
return sync_after_vscan(source, n);
}

#if !SCN_DISABLE_TYPE_SCHAR
Expand Down

0 comments on commit e1b7fe2

Please sign in to comment.