view: add 'read' operation complementing 'extract'
This commit is contained in:
parent
4b69b7515b
commit
e92f0dc337
41
view.hpp
41
view.hpp
@ -18,6 +18,7 @@
|
||||
#ifndef CRUFT_UTIL_VIEW_HPP
|
||||
#define CRUFT_UTIL_VIEW_HPP
|
||||
|
||||
#include "annotation.hpp"
|
||||
#include "cast.hpp"
|
||||
#include "types/traits.hpp"
|
||||
#include "maths.hpp"
|
||||
@ -609,15 +610,14 @@ namespace util {
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// extract a reference to a known type at the front of a byte-view
|
||||
///
|
||||
/// returns a reference to a value of the designated type at the front of
|
||||
/// the byte-view, or throws an exception if there is insufficient data.
|
||||
/// the byte-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
|
||||
/// (other than memory safety wrt to the view). 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.
|
||||
/// 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 extract value
|
||||
@ -631,10 +631,33 @@ namespace util {
|
||||
ValueT const&
|
||||
extract (util::view<const ByteT*> &buffer)
|
||||
{
|
||||
if (buffer.size () < sizeof (ValueT))
|
||||
throw std::runtime_error ("insufficient data for view shift");
|
||||
if (unlikely (sizeof (ValueT) > buffer.size ()))
|
||||
throw std::runtime_error ("insufficient data for extraction");
|
||||
|
||||
ValueT const &res = *util::cast::ffs<ValueT const*> (buffer.data ());
|
||||
ValueT const &res = *util::cast::alignment<ValueT const*> (buffer.data ());
|
||||
buffer = buffer.consume (sizeof (ValueT));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// extracts an object of a specified type from the front of a byte-view.
|
||||
///
|
||||
/// in contrast to 'extract' this will always copy the bytes out from the
|
||||
/// view, making the operation alignment safe.
|
||||
template <
|
||||
typename ValueT,
|
||||
typename ByteT,
|
||||
typename = std::enable_if_t<sizeof(ByteT) == 1>
|
||||
>
|
||||
ValueT
|
||||
read (util::view<ByteT const*> &buffer)
|
||||
{
|
||||
if (unlikely (sizeof (ValueT) > buffer.size ()))
|
||||
throw std::runtime_error ("insufficient data for extraction");
|
||||
|
||||
ValueT res;
|
||||
memcpy (&res, buffer.data (), sizeof (ValueT));
|
||||
buffer = buffer.consume (sizeof (ValueT));
|
||||
return res;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user