From 96033cd2c45e4ce667a577327abe4a6ad0fb2674 Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Sat, 10 Aug 2024 12:27:59 -0700 Subject: [PATCH] Use concepts in more places --- include/bencode.hpp | 124 +++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 71 deletions(-) diff --git a/include/bencode.hpp b/include/bencode.hpp index 6a00e25..b5f0ac3 100644 --- a/include/bencode.hpp +++ b/include/bencode.hpp @@ -334,7 +334,16 @@ namespace bencode { std::end(t); }; - template + template + concept sequence = iterable && !std::convertible_to; + + template + concept mapping = sequence && requires { + typename T::key_type; + typename T::mapped_type; + }; + + template inline void check_overflow(Integer value, Integer digit) { using limits = std::numeric_limits; // Wrap `max` in parentheses to work around #defining `max`. @@ -343,7 +352,7 @@ namespace bencode { throw std::overflow_error("integer overflow"); } - template + template inline void check_underflow(Integer value, Integer digit) { using limits = std::numeric_limits; // As above, work around #defining `min`. @@ -352,7 +361,7 @@ namespace bencode { throw std::underflow_error("integer underflow"); } - template + template inline void check_over_underflow(Integer value, Integer digit, Integer sgn) { if(sgn == 1) @@ -361,7 +370,7 @@ namespace bencode { check_underflow(value, digit); } - template + template inline Integer decode_digits(Iter &begin, Iter end, [[maybe_unused]] Integer sgn = 1) { assert(sgn == 1 || (std::is_signed_v && @@ -411,7 +420,7 @@ namespace bencode { return value; } - template + template Integer decode_int(Iter &begin, Iter end) { assert(*begin == u8'i'); ++begin; @@ -433,58 +442,43 @@ namespace bencode { return value; } - template - class str_reader { - public: - template - inline String operator ()(Iter &begin, Iter end, Size len) { - return call( - begin, end, len, - typename std::iterator_traits::iterator_category() - ); - } - private: - template - String call(Iter &begin, Iter end, Size len, std::forward_iterator_tag) { - if(std::distance(begin, end) < static_cast(len)) { - begin = end; - throw end_of_input_error(); - } - - auto orig = begin; - std::advance(begin, len); - return String(orig, begin); + template + String decode_chars(Iter &begin, Iter end, std::size_t len) { + if(std::distance(begin, end) < static_cast(len)) { + begin = end; + throw end_of_input_error(); } - template - String call(Iter &begin, Iter end, Size len, std::input_iterator_tag) { - String value(len, 0); - for(Size i = 0; i < len; i++) { - if(begin == end) - throw end_of_input_error(); - value[i] = *begin++; - } - return value; - } - }; + auto orig = begin; + std::advance(begin, len); + return String(orig, begin); + } - template<> - class str_reader { - public: - template - std::string_view operator ()(Iter &begin, Iter end, Size len) { - if(std::distance(begin, end) < static_cast(len)) { - begin = end; + template + inline String decode_chars(Iter &begin, Iter end, std::size_t len) { + String value(len, 0); + for(std::size_t i = 0; i < len; i++) { + if(begin == end) throw end_of_input_error(); - } + value[i] = *begin++; + } + return value; + } - std::string_view value(&*begin, len); - std::advance(begin, len); - return value; + template + requires is_view + String decode_chars(Iter &begin, Iter end, std::size_t len) { + if(std::distance(begin, end) < static_cast(len)) { + begin = end; + throw end_of_input_error(); } - }; - template + std::string_view value(&*begin, len); + std::advance(begin, len); + return value; + } + + template String decode_str(Iter &begin, Iter end) { assert(std::isdigit(*begin)); std::size_t len = decode_digits(begin, end); @@ -494,10 +488,10 @@ namespace bencode { throw syntax_error("expected ':' token"); ++begin; - return str_reader{}(begin, end, len); + return decode_chars(begin, end, len); } - template + template Data do_decode(Iter &begin, Iter end, bool all) { using Traits = variant_traits_for; using Integer = typename Data::integer; @@ -600,7 +594,7 @@ namespace bencode { } - template + template inline Data basic_decode(Iter begin, Iter end) { return detail::do_decode(begin, end, true); } @@ -626,7 +620,7 @@ namespace bencode { return detail::do_decode(s, e, true); } - template + template inline Data basic_decode_some(Iter &begin, Iter end) { return detail::do_decode(begin, end, false); } @@ -755,34 +749,22 @@ namespace bencode { std::copy(value.begin(), value.end(), iter); } - template - void encode(Iter &&iter, const std::vector &value) { + template + void encode(Iter &&iter, const Seq &value) { detail::list_encoder e(iter); for(auto &&i : value) e.add(i); } - template - void encode(Iter &&iter, const std::map &value) { + template + void encode(Iter &&iter, const Map &value) { detail::dict_encoder e(iter); for(auto &&i : value) e.add(i.first, i.second); } - template - void encode(Iter &&iter, const std::map &value) { - detail::dict_encoder e(iter); - for(auto &&i : value) - e.add(i.first, i.second); - } - - template - void encode(Iter &&iter, const map_proxy &value) { - encode(iter, *value); - } - namespace detail { - template + template class encode_visitor { public: inline encode_visitor(Iter &iter) : iter(iter) {}