@@ -334,7 +334,16 @@ namespace bencode {
334
334
std::end (t);
335
335
};
336
336
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>
338
347
inline void check_overflow (Integer value, Integer digit) {
339
348
using limits = std::numeric_limits<Integer>;
340
349
// Wrap `max` in parentheses to work around <windows.h> #defining `max`.
@@ -343,7 +352,7 @@ namespace bencode {
343
352
throw std::overflow_error (" integer overflow" );
344
353
}
345
354
346
- template <typename Integer>
355
+ template <std::integral Integer>
347
356
inline void check_underflow (Integer value, Integer digit) {
348
357
using limits = std::numeric_limits<Integer>;
349
358
// As above, work around <windows.h> #defining `min`.
@@ -352,7 +361,7 @@ namespace bencode {
352
361
throw std::underflow_error (" integer underflow" );
353
362
}
354
363
355
- template <typename Integer>
364
+ template <std::integral Integer>
356
365
inline void
357
366
check_over_underflow (Integer value, Integer digit, Integer sgn) {
358
367
if (sgn == 1 )
@@ -361,7 +370,7 @@ namespace bencode {
361
370
check_underflow (value, digit);
362
371
}
363
372
364
- template <typename Integer, typename Iter>
373
+ template <std::integral Integer, std::input_iterator Iter>
365
374
inline Integer
366
375
decode_digits (Iter &begin, Iter end, [[maybe_unused]] Integer sgn = 1 ) {
367
376
assert (sgn == 1 || (std::is_signed_v<Integer> &&
@@ -411,7 +420,7 @@ namespace bencode {
411
420
return value;
412
421
}
413
422
414
- template <typename Integer, typename Iter>
423
+ template <std::integral Integer, std::input_iterator Iter>
415
424
Integer decode_int (Iter &begin, Iter end) {
416
425
assert (*begin == u8 ' i' );
417
426
++begin;
@@ -433,58 +442,43 @@ namespace bencode {
433
442
return value;
434
443
}
435
444
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 ();
457
450
}
458
451
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
+ }
470
456
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)
478
462
throw end_of_input_error ();
479
- }
463
+ value[i] = *begin++;
464
+ }
465
+ return value;
466
+ }
480
467
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 ();
484
474
}
485
- };
486
475
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>
488
482
String decode_str (Iter &begin, Iter end) {
489
483
assert (std::isdigit (*begin));
490
484
std::size_t len = decode_digits<std::size_t >(begin, end);
@@ -494,10 +488,10 @@ namespace bencode {
494
488
throw syntax_error (" expected ':' token" );
495
489
++begin;
496
490
497
- return str_reader <String>{} (begin, end, len);
491
+ return decode_chars <String>(begin, end, len);
498
492
}
499
493
500
- template <typename Data, typename Iter>
494
+ template <typename Data, std::input_iterator Iter>
501
495
Data do_decode (Iter &begin, Iter end, bool all) {
502
496
using Traits = variant_traits_for<Data>;
503
497
using Integer = typename Data::integer;
@@ -600,7 +594,7 @@ namespace bencode {
600
594
601
595
}
602
596
603
- template <typename Data, typename Iter>
597
+ template <typename Data, std::input_iterator Iter>
604
598
inline Data basic_decode (Iter begin, Iter end) {
605
599
return detail::do_decode<Data>(begin, end, true );
606
600
}
@@ -626,7 +620,7 @@ namespace bencode {
626
620
return detail::do_decode<Data>(s, e, true );
627
621
}
628
622
629
- template <typename Data, typename Iter>
623
+ template <typename Data, std::input_iterator Iter>
630
624
inline Data basic_decode_some (Iter &begin, Iter end) {
631
625
return detail::do_decode<Data>(begin, end, false );
632
626
}
@@ -755,34 +749,22 @@ namespace bencode {
755
749
std::copy (value.begin (), value.end (), iter);
756
750
}
757
751
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) {
760
754
detail::list_encoder e (iter);
761
755
for (auto &&i : value)
762
756
e.add (i);
763
757
}
764
758
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) {
767
761
detail::dict_encoder e (iter);
768
762
for (auto &&i : value)
769
763
e.add (i.first , i.second );
770
764
}
771
765
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
-
784
766
namespace detail {
785
- template <std::input_or_output_iterator Iter>
767
+ template <detail::output_iterator_ref Iter>
786
768
class encode_visitor {
787
769
public:
788
770
inline encode_visitor (Iter &iter) : iter(iter) {}
0 commit comments