From 07e66f20d308685ef8bd54efb8be4edcb3ead7de Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Sat, 15 Dec 2018 15:34:41 +1100 Subject: [PATCH] view: allow longer words for byte views --- view.hpp | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/view.hpp b/view.hpp index f4ba6668..4833544e 100644 --- a/view.hpp +++ b/view.hpp @@ -575,6 +575,9 @@ namespace cruft { auto make_byte_view (T &t) { + static_assert (std::is_integral_v); + static_assert (sizeof (T) % sizeof (ByteT) == 0); + using cursor_type = std::conditional_t< std::is_const_v, ByteT const*, @@ -582,40 +585,43 @@ namespace cruft { >; return view { - reinterpret_cast (&t), - sizeof (T) + cast::alignment (&t), + sizeof (T) / sizeof (ByteT) }; } /////////////////////////////////////////////////////////////////////////// - /// returns a reference to a value of the designated type at the front of - /// the byte-view. if there is insufficient data for the extraction an + /// Returns a reference to a value of the designated type at the front of + /// the word-view. if there is insufficient data for the extraction an /// exception will be thrown. /// - /// there are no validity or other checks performed on the returned data + /// There are no validity or other checks performed on the returned data /// this is deliberate, so that the function is safe to call on user /// supplied data during parsing routines. it is up to the user to ensure /// the object is valid. /// - /// the buffer object is advanced in place so that it no longer covers + /// The buffer object is advanced in place so that it no longer covers /// the extract value /// - /// it is assumed the user has taken care of alignment concerns + /// It is assumed the user has taken care of alignment concerns template < typename ValueT, - typename ByteT, - typename = std::enable_if_t + typename WordT, + // Only allow calls if the value is a multiple of the word size. It's + // useful to allow non-unit words for areas like TCP/IP which tend to + // operate on u16 words. + typename = std::enable_if_t > ValueT const& - extract (view &buffer) + extract (view &buffer) { - if (unlikely (sizeof (ValueT) > buffer.size ())) + if (unlikely (sizeof (ValueT) > buffer.size () * sizeof (WordT))) throw std::runtime_error ("insufficient data for extraction"); - ValueT const &res = *cast::alignment (buffer.data ()); - buffer = buffer.consume (sizeof (ValueT)); - return res; + auto const ptr = cast::alignment (buffer.data ()); + buffer = buffer.consume (sizeof (ValueT) / sizeof (WordT)); + return *ptr; } @@ -626,11 +632,11 @@ namespace cruft { /// view, making the operation alignment safe. template < typename ValueT, - typename ByteT, - typename = std::enable_if_t + typename WordT, + typename = std::enable_if_t > ValueT - read (view &buffer) + read (view &buffer) { // we disable the class-memaccess warning so that we can memcpy into // types that we know are safe but the compiler will complain about. @@ -640,12 +646,12 @@ namespace cruft { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wclass-memaccess" #endif - if (unlikely (sizeof (ValueT) > buffer.size ())) + if (unlikely (sizeof (ValueT) > buffer.size () * sizeof (WordT))) throw std::runtime_error ("insufficient data for extraction"); ValueT res; memcpy (&res, buffer.data (), sizeof (ValueT)); - buffer = buffer.consume (sizeof (ValueT)); + buffer = buffer.consume (sizeof (ValueT) / sizeof (WordT)); return res; #if defined(COMPILER_GCC) #pragma GCC diagnostic pop