Skip to content

Commit

Permalink
Add and use SCN_TRY
Browse files Browse the repository at this point in the history
  • Loading branch information
eliaskosunen committed Oct 7, 2023
1 parent ae9cd02 commit c6f5df7
Show file tree
Hide file tree
Showing 15 changed files with 332 additions and 391 deletions.
17 changes: 5 additions & 12 deletions include/scn/detail/args.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <scn/detail/input_map.h>
#include <scn/detail/ranges.h>
#include <scn/detail/unicode.h>
#include <scn/util/expected.h>
#include <scn/util/meta.h>

#include <array>
Expand Down Expand Up @@ -163,18 +164,10 @@ namespace scn {
{
auto s = Scanner{};

auto r = s.parse(pctx)
.and_then([&](auto&&) {
return s.scan(*static_cast<T*>(arg), ctx);
})
.transform([&](auto&& it) SCN_NOEXCEPT {
ctx.advance_to(SCN_MOVE(it));
});

if (SCN_UNLIKELY(!r)) {
SCN_UNLIKELY_ATTR
return r.error();
}
SCN_TRY_ERR(_, s.parse(pctx));
SCN_TRY_ERR(it, s.scan(*static_cast<T*>(arg), ctx));
ctx.advance_to(SCN_MOVE(it));

return {};
}
};
Expand Down
21 changes: 4 additions & 17 deletions include/scn/detail/pp.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,19 +207,6 @@
}(x))
#endif

// SCN_TRY and friends
#if SCN_HAS_EXCEPTIONS && SCN_USE_EXCEPTIONS
#define SCN_TRY try
#define SCN_CATCH(x) catch (x)
#define SCN_THROW(x) throw x
#define SCN_RETHROW throw
#else
#define SCN_TRY if (true)
#define SCN_CATCH(x) if (false)
#define SCN_THROW(x) ::std::abort()
#define SCN_RETHROW ::std::abort()
#endif

// clang currently can't process libstdc++ ranges::view_interface
#if SCN_CLANG && SCN_STDLIB_GLIBCXX
#define SCN_ENVIRONMENT_SUPPORTS_RANGES 0
Expand Down Expand Up @@ -255,8 +242,8 @@
#define SCN_MOVE(x) \
static_cast< \
typename ::scn::detail::remove_reference<decltype(x)>::type&&>(x)
#define SCN_FWD(x) static_cast<decltype(x)&&>(x)
#define SCN_DECLVAL(T) static_cast<T (*)()>(nullptr)()
#define SCN_FWD(x) static_cast<decltype(x)&&>(x)
#define SCN_DECLVAL(T) static_cast<T (*)()>(nullptr)()

#define SCN_BEGIN_NAMESPACE inline namespace v2 {
#define SCN_END_NAMESPACE }
#define SCN_BEGIN_NAMESPACE inline namespace v2 {
#define SCN_END_NAMESPACE }
5 changes: 2 additions & 3 deletions include/scn/detail/scan.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,8 @@ namespace scn {
{
auto arg =
detail::make_arg<detail::context_type_for<Source>>(value);
return vscan_value(SCN_FWD(source), arg).transform([&](auto&& it) {
return scan_result{SCN_MOVE(it), std::tuple{SCN_MOVE(value)}};
});
SCN_TRY(it, vscan_value(SCN_FWD(source), arg));
return scan_result{SCN_MOVE(it), std::tuple{SCN_MOVE(value)}};
}
} // namespace detail

Expand Down
109 changes: 46 additions & 63 deletions include/scn/detail/scanner_range.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,18 +166,16 @@ namespace scn {
Source source,
std::basic_string_view<CharT> str_to_read)
{
return internal_skip_classic_whitespace(source, false)
.and_then([&](auto it) -> scan_expected<decltype(it)> {
for (auto ch_to_read : str_to_read) {
if (SCN_UNLIKELY(ch_to_read != *it)) {
return unexpected_scan_error(
scan_error::invalid_scanned_value,
"Invalid range character");
}
++it;
}
return it;
});
SCN_TRY(it, internal_skip_classic_whitespace(source, false));
for (auto ch_to_read : str_to_read) {
if (SCN_UNLIKELY(ch_to_read != *it)) {
return unexpected_scan_error(
scan_error::invalid_scanned_value,
"Invalid range character");
}
++it;
}
return it;
}

template <typename Range, typename Element, typename Enable = void>
Expand All @@ -186,15 +184,15 @@ namespace scn {
struct has_push_back<Range,
Element,
decltype(SCN_DECLVAL(Range&).push_back(
SCN_DECLVAL(Element &&)))> : std::true_type {};
SCN_DECLVAL(Element&&)))> : std::true_type {};

template <typename Range, typename Element, typename Enable = void>
struct has_push : std::false_type {};
template <typename Range, typename Element>
struct has_push<Range,
Element,
decltype(SCN_DECLVAL(Range&).push(
SCN_DECLVAL(Element &&)))> : std::true_type {};
SCN_DECLVAL(Element&&)))> : std::true_type {};

template <typename Range, typename Element, typename Enable = void>
struct has_element_insert : std::false_type {};
Expand All @@ -203,7 +201,7 @@ namespace scn {
Range,
Element,
std::void_t<decltype(SCN_DECLVAL(Range&).insert(
SCN_DECLVAL(Element &&)))>> : std::true_type {};
SCN_DECLVAL(Element&&)))>> : std::true_type {};

template <typename Range,
typename Element,
Expand Down Expand Up @@ -277,38 +275,30 @@ namespace scn {
scan_expected<typename Context::iterator>
scan_impl(Scan scan_cb, Range& range, Context& ctx) const
{
return detail::scan_str(ctx.range(), this->m_opening_bracket)
.and_then([&](auto it)
-> scan_expected<typename Context::iterator> {
ctx.advance_to(it);

using diff_type = ranges::range_difference_t<Range>;
for (diff_type i = 0; i < detail::range_max_size(range);
++i) {
if (auto e = detail::scan_str(
ctx.range(), this->m_closing_bracket);
e) {
break;
}

T elem{};
if (auto e =
scan_inner_loop(scan_cb, ctx, elem, i == 0);
SCN_LIKELY(e)) {
detail::add_element_to_range(range,
SCN_MOVE(elem));
ctx.advance_to(*e);
}
else {
return e;
}
}
return ctx.range().begin();
})
.and_then([&](auto) {
return detail::scan_str(ctx.range(),
this->m_closing_bracket);
});
SCN_TRY(it,
detail::scan_str(ctx.range(), this->m_opening_bracket));
ctx.advance_to(it);

using diff_type = ranges::range_difference_t<Range>;
for (diff_type i = 0; i < detail::range_max_size(range); ++i) {
if (auto e = detail::scan_str(ctx.range(),
this->m_closing_bracket);
e) {
break;
}

T elem{};
if (auto e = scan_inner_loop(scan_cb, ctx, elem, i == 0);
SCN_LIKELY(e)) {
detail::add_element_to_range(range, SCN_MOVE(elem));
ctx.advance_to(*e);
}
else {
return e;
}
}

return detail::scan_str(ctx.range(), this->m_closing_bracket);
}

private:
Expand All @@ -328,12 +318,11 @@ namespace scn {
return detail::scan_str(src, sep);
};

return skip_separator(ctx.range(), this->m_separator, is_first)
.and_then([&](auto it) {
ctx.advance_to(it);
return scan_cb(detail::range_mapper<CharT>().map(elem),
ctx, is_first);
});
SCN_TRY(it, skip_separator(ctx.range(), this->m_separator,
is_first));
ctx.advance_to(it);
return scan_cb(detail::range_mapper<CharT>().map(elem), ctx,
is_first);
}
};

Expand Down Expand Up @@ -368,16 +357,10 @@ namespace scn {
scan_expected<typename Context::iterator> scan(Tuple& value,
Context& ctx) const
{
return detail::scan_str(ctx.range(), this->m_opening_bracket)
.and_then(
[&](auto it) -> scan_expected<typename Context::iterator> {
ctx.advance_to(it);
return scan_for_each(value, ctx);
})
.and_then([&](auto) {
return detail::scan_str(ctx.range(),
this->m_closing_bracket);
});
SCN_TRY(it, detail::scan_str(ctx.range(), this->m_opening_bracket));
ctx.advance_to(it);
SCN_TRY(_, scan_for_each(value, ctx));
return detail::scan_str(ctx.range(), this->m_closing_bracket);
}

private:
Expand Down
19 changes: 19 additions & 0 deletions include/scn/util/expected.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,22 @@ namespace scn {

SCN_END_NAMESPACE
} // namespace scn

#define SCN_TRY_IMPL_CONCAT(a, b) a##b
#define SCN_TRY_IMPL_CONCAT2(a, b) SCN_TRY_IMPL_CONCAT(a, b)
#define SCN_TRY_TMP SCN_TRY_IMPL_CONCAT2(_scn_try_tmp_, __LINE__)

#define SCN_TRY_ASSIGN(init, x) \
auto&& SCN_TRY_TMP = (x); \
if (SCN_UNLIKELY(!SCN_TRY_TMP)) { \
return ::scn::unexpected(SCN_TRY_TMP.error()); \
} \
init = *SCN_FWD(SCN_TRY_TMP);
#define SCN_TRY(name, x) SCN_TRY_ASSIGN(auto name, x)

#define SCN_TRY_ERR(name, x) \
auto&& SCN_TRY_TMP = (x); \
if (SCN_UNLIKELY(!SCN_TRY_TMP)) { \
return SCN_TRY_TMP.error(); \
} \
auto name = *SCN_FWD(SCN_TRY_TMP);
Loading

0 comments on commit c6f5df7

Please sign in to comment.