Skip to content

Commit 96033cd

Browse files
committed
Use concepts in more places
1 parent 36dea3e commit 96033cd

File tree

1 file changed

+53
-71
lines changed

1 file changed

+53
-71
lines changed

include/bencode.hpp

Lines changed: 53 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,16 @@ namespace bencode {
334334
std::end(t);
335335
};
336336

337-
template<typename Integer>
337+
template<typename T>
338+
concept sequence = iterable<T> && !std::convertible_to<T, std::string_view>;
339+
340+
template<typename T>
341+
concept mapping = sequence<T> && requires {
342+
typename T::key_type;
343+
typename T::mapped_type;
344+
};
345+
346+
template<std::integral Integer>
338347
inline void check_overflow(Integer value, Integer digit) {
339348
using limits = std::numeric_limits<Integer>;
340349
// Wrap `max` in parentheses to work around <windows.h> #defining `max`.
@@ -343,7 +352,7 @@ namespace bencode {
343352
throw std::overflow_error("integer overflow");
344353
}
345354

346-
template<typename Integer>
355+
template<std::integral Integer>
347356
inline void check_underflow(Integer value, Integer digit) {
348357
using limits = std::numeric_limits<Integer>;
349358
// As above, work around <windows.h> #defining `min`.
@@ -352,7 +361,7 @@ namespace bencode {
352361
throw std::underflow_error("integer underflow");
353362
}
354363

355-
template<typename Integer>
364+
template<std::integral Integer>
356365
inline void
357366
check_over_underflow(Integer value, Integer digit, Integer sgn) {
358367
if(sgn == 1)
@@ -361,7 +370,7 @@ namespace bencode {
361370
check_underflow(value, digit);
362371
}
363372

364-
template<typename Integer, typename Iter>
373+
template<std::integral Integer, std::input_iterator Iter>
365374
inline Integer
366375
decode_digits(Iter &begin, Iter end, [[maybe_unused]] Integer sgn = 1) {
367376
assert(sgn == 1 || (std::is_signed_v<Integer> &&
@@ -411,7 +420,7 @@ namespace bencode {
411420
return value;
412421
}
413422

414-
template<typename Integer, typename Iter>
423+
template<std::integral Integer, std::input_iterator Iter>
415424
Integer decode_int(Iter &begin, Iter end) {
416425
assert(*begin == u8'i');
417426
++begin;
@@ -433,58 +442,43 @@ namespace bencode {
433442
return value;
434443
}
435444

436-
template<typename String>
437-
class str_reader {
438-
public:
439-
template<typename Iter, typename Size>
440-
inline String operator ()(Iter &begin, Iter end, Size len) {
441-
return call(
442-
begin, end, len,
443-
typename std::iterator_traits<Iter>::iterator_category()
444-
);
445-
}
446-
private:
447-
template<typename Iter, typename Size>
448-
String call(Iter &begin, Iter end, Size len, std::forward_iterator_tag) {
449-
if(std::distance(begin, end) < static_cast<std::ptrdiff_t>(len)) {
450-
begin = end;
451-
throw end_of_input_error();
452-
}
453-
454-
auto orig = begin;
455-
std::advance(begin, len);
456-
return String(orig, begin);
445+
template<typename String, std::forward_iterator Iter>
446+
String decode_chars(Iter &begin, Iter end, std::size_t len) {
447+
if(std::distance(begin, end) < static_cast<std::ptrdiff_t>(len)) {
448+
begin = end;
449+
throw end_of_input_error();
457450
}
458451

459-
template<typename Iter, typename Size>
460-
String call(Iter &begin, Iter end, Size len, std::input_iterator_tag) {
461-
String value(len, 0);
462-
for(Size i = 0; i < len; i++) {
463-
if(begin == end)
464-
throw end_of_input_error();
465-
value[i] = *begin++;
466-
}
467-
return value;
468-
}
469-
};
452+
auto orig = begin;
453+
std::advance(begin, len);
454+
return String(orig, begin);
455+
}
470456

471-
template<>
472-
class str_reader<std::string_view> {
473-
public:
474-
template<typename Iter, typename Size>
475-
std::string_view operator ()(Iter &begin, Iter end, Size len) {
476-
if(std::distance(begin, end) < static_cast<std::ptrdiff_t>(len)) {
477-
begin = end;
457+
template<typename String, std::input_iterator Iter>
458+
inline String decode_chars(Iter &begin, Iter end, std::size_t len) {
459+
String value(len, 0);
460+
for(std::size_t i = 0; i < len; i++) {
461+
if(begin == end)
478462
throw end_of_input_error();
479-
}
463+
value[i] = *begin++;
464+
}
465+
return value;
466+
}
480467

481-
std::string_view value(&*begin, len);
482-
std::advance(begin, len);
483-
return value;
468+
template<typename String, std::contiguous_iterator Iter>
469+
requires is_view<String>
470+
String decode_chars(Iter &begin, Iter end, std::size_t len) {
471+
if(std::distance(begin, end) < static_cast<std::ptrdiff_t>(len)) {
472+
begin = end;
473+
throw end_of_input_error();
484474
}
485-
};
486475

487-
template<typename String, typename Iter>
476+
std::string_view value(&*begin, len);
477+
std::advance(begin, len);
478+
return value;
479+
}
480+
481+
template<typename String, std::input_iterator Iter>
488482
String decode_str(Iter &begin, Iter end) {
489483
assert(std::isdigit(*begin));
490484
std::size_t len = decode_digits<std::size_t>(begin, end);
@@ -494,10 +488,10 @@ namespace bencode {
494488
throw syntax_error("expected ':' token");
495489
++begin;
496490

497-
return str_reader<String>{}(begin, end, len);
491+
return decode_chars<String>(begin, end, len);
498492
}
499493

500-
template<typename Data, typename Iter>
494+
template<typename Data, std::input_iterator Iter>
501495
Data do_decode(Iter &begin, Iter end, bool all) {
502496
using Traits = variant_traits_for<Data>;
503497
using Integer = typename Data::integer;
@@ -600,7 +594,7 @@ namespace bencode {
600594

601595
}
602596

603-
template<typename Data, typename Iter>
597+
template<typename Data, std::input_iterator Iter>
604598
inline Data basic_decode(Iter begin, Iter end) {
605599
return detail::do_decode<Data>(begin, end, true);
606600
}
@@ -626,7 +620,7 @@ namespace bencode {
626620
return detail::do_decode<Data>(s, e, true);
627621
}
628622

629-
template<typename Data, typename Iter>
623+
template<typename Data, std::input_iterator Iter>
630624
inline Data basic_decode_some(Iter &begin, Iter end) {
631625
return detail::do_decode<Data>(begin, end, false);
632626
}
@@ -755,34 +749,22 @@ namespace bencode {
755749
std::copy(value.begin(), value.end(), iter);
756750
}
757751

758-
template<detail::output_iterator_ref Iter, typename T>
759-
void encode(Iter &&iter, const std::vector<T> &value) {
752+
template<detail::output_iterator_ref Iter, detail::sequence Seq>
753+
void encode(Iter &&iter, const Seq &value) {
760754
detail::list_encoder e(iter);
761755
for(auto &&i : value)
762756
e.add(i);
763757
}
764758

765-
template<detail::output_iterator_ref Iter, typename T>
766-
void encode(Iter &&iter, const std::map<string, T> &value) {
759+
template<detail::output_iterator_ref Iter, detail::mapping Map>
760+
void encode(Iter &&iter, const Map &value) {
767761
detail::dict_encoder e(iter);
768762
for(auto &&i : value)
769763
e.add(i.first, i.second);
770764
}
771765

772-
template<detail::output_iterator_ref Iter, typename T>
773-
void encode(Iter &&iter, const std::map<string_view, T> &value) {
774-
detail::dict_encoder e(iter);
775-
for(auto &&i : value)
776-
e.add(i.first, i.second);
777-
}
778-
779-
template<detail::output_iterator_ref Iter, typename K, typename V>
780-
void encode(Iter &&iter, const map_proxy<K, V> &value) {
781-
encode(iter, *value);
782-
}
783-
784766
namespace detail {
785-
template<std::input_or_output_iterator Iter>
767+
template<detail::output_iterator_ref Iter>
786768
class encode_visitor {
787769
public:
788770
inline encode_visitor(Iter &iter) : iter(iter) {}

0 commit comments

Comments
 (0)