diff options
Diffstat (limited to 'rfc4251.H')
| -rw-r--r-- | rfc4251.H | 116 |
1 files changed, 67 insertions, 49 deletions
@@ -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<typename Length_Type> + struct variable_length : boost::totally_ordered<variable_length<Length_Type>> { + using length_type = Length_Type; + static_assert(std::is_unsigned_v<length_type>, "negative lengths are not supported"); + + std::vector<char> 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<length_type>{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<length_type>{static_cast<length_type>(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<length_type>::max()) + throw std::length_error{"numeric limit for length field in rfc4251::variable_length type exceeded"}; + } + + }; } using byte = internal::fixed_length<uint8_t>; @@ -92,59 +136,33 @@ using boolean = internal::fixed_length<bool>; using uint32 = internal::fixed_length<uint32_t>; using uint64 = internal::fixed_length<uint64_t>; -struct string : boost::totally_ordered<string> { - std::vector<char> value; - - string () = default; - inline explicit string (char const *, size_t); +struct string : internal::variable_length<uint32_t> { + 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<std::string> 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<uint32_t> { + using variable_length::variable_length; + + explicit name_list (std::vector<std::string> const &); + operator std::vector<std::string> () const; - operator mpz_class () const; }; -inline string::string (char const * s, size_t l) { - if (l > std::numeric_limits<uint32_t>::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<uint32_t>::max()) - throw std::length_error{"32-bit limit for rfc4251::string exceeded"}; - if (os << uint32{static_cast<uint32_t>(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<uint32_t> { + using variable_length::variable_length; + + explicit mpint (mpz_srcptr); + explicit mpint (mpz_class const & x) : mpint{x.get_mpz_t()} {} + + operator mpz_class () const; +}; } |
