From b929b048a1839c3da1cadf7f116b0f767f40267e Mon Sep 17 00:00:00 2001 From: Timo Weingärtner Date: Thu, 22 Apr 2021 23:29:10 +0200 Subject: implement separate rfc4251::(string|mpint|name_list) types --- rfc4251.H | 116 ++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 67 insertions(+), 49 deletions(-) (limited to 'rfc4251.H') diff --git a/rfc4251.H b/rfc4251.H index fe8ccd4..6647d15 100644 --- a/rfc4251.H +++ b/rfc4251.H @@ -5,7 +5,9 @@ * rfc4251::boolean boolean * rfc4251::uint32 uint32 * rfc4251::uint64 uint64 - * rfc4251::string string, incl. mpint and name-list + * rfc4251::string string + * rfc4251::mpint mpint + * rfc4251::name_list name-list * * those structs contain the objects in their RFC 4251 representation, * conversions are provided via constructors and cast operators @@ -85,6 +87,48 @@ namespace internal { return os.write(x.buf.data(), x.buf.size()); } }; + + template + struct variable_length : boost::totally_ordered> { + using length_type = Length_Type; + static_assert(std::is_unsigned_v, "negative lengths are not supported"); + + std::vector buf; + + variable_length () = default; + explicit variable_length (std::istream & is) { is >> *this; } + + size_t size () const noexcept { return buf.size(); } + char const * data () const noexcept { return buf.data(); } + char * data () noexcept { return buf.data(); } + + friend std::istream & operator>> (std::istream & is, variable_length & v) { + if (length_type const len{fixed_length{is}}; is) { + v.buf.clear(); + v.buf.resize(len); + is.read(v.buf.data(), len); + } + return is; + } + friend std::ostream & operator<< (std::ostream & os, variable_length const & v) { + check_length_against_limit(v.buf.size()); + if (os << fixed_length{static_cast(v.buf.size())}) + os.write(v.buf.data(), v.buf.size()); + return os; + } + friend bool operator== (variable_length const & l, variable_length const & r) { + return l.buf == r.buf; + } + friend bool operator< (variable_length const & l, variable_length const & r) { + return l.buf < r.buf; + } + + constexpr static void check_length_against_limit(size_t const length) { + if (length > std::numeric_limits::max()) + throw std::length_error{"numeric limit for length field in rfc4251::variable_length type exceeded"}; + } + + }; } using byte = internal::fixed_length; @@ -92,59 +136,33 @@ using boolean = internal::fixed_length; using uint32 = internal::fixed_length; using uint64 = internal::fixed_length; -struct string : boost::totally_ordered { - std::vector value; - - string () = default; - inline explicit string (char const *, size_t); +struct string : internal::variable_length { + using variable_length::variable_length; + + inline explicit string (char const * s, size_t l) { + check_length_against_limit(l); + buf.insert(buf.end(), s, s + l); + } explicit string (std::string const & s) : string{s.data(), s.size()} {} - explicit string (std::vector const &); - explicit string (mpz_srcptr); - explicit string (mpz_class const & x) : string{x.get_mpz_t()} {} - inline explicit string (std::istream &); - size_t size () const noexcept { return value.size(); } - char const * data () const noexcept { return value.data(); } - char * data () noexcept { return value.data(); } + operator std::string () const { return {buf.cbegin(), buf.cend()}; } +}; - operator std::string () const { return {value.begin(), value.end()}; } +struct name_list : internal::variable_length { + using variable_length::variable_length; + + explicit name_list (std::vector const &); + operator std::vector () const; - operator mpz_class () const; }; -inline string::string (char const * s, size_t l) { - if (l > std::numeric_limits::max()) - throw std::length_error{"32-bit limit for rfc4251::string exceeded"}; - value.insert(value.end(), s, s + l); -} - -inline std::istream & operator>> (std::istream & is, string & s) { - s.value.clear(); - if (uint32_t const len{uint32{is}}; is) { - s.value.resize(len); - is.read(s.value.data(), len); - } - return is; -} - -inline std::ostream & operator<< (std::ostream & os, string const & s) { - if (s.value.size() > std::numeric_limits::max()) - throw std::length_error{"32-bit limit for rfc4251::string exceeded"}; - if (os << uint32{static_cast(s.value.size())}) - os.write(s.value.data(), s.value.size()); - return os; -} - -inline string::string (std::istream & is) { - is >> *this; -} - -inline bool operator== (string const & l, string const & r) { - return l.value == r.value; -} - -inline bool operator< (string const & l, string const & r) { - return l.value < r.value; -} +struct mpint : internal::variable_length { + using variable_length::variable_length; + + explicit mpint (mpz_srcptr); + explicit mpint (mpz_class const & x) : mpint{x.get_mpz_t()} {} + + operator mpz_class () const; +}; } -- cgit v1.2.3