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
|
#ifndef CRUFT_UTIL_VIEW_HPP
|
||||||
#define CRUFT_UTIL_VIEW_HPP
|
#define CRUFT_UTIL_VIEW_HPP
|
||||||
|
|
||||||
|
#include "annotation.hpp"
|
||||||
#include "cast.hpp"
|
#include "cast.hpp"
|
||||||
#include "types/traits.hpp"
|
#include "types/traits.hpp"
|
||||||
#include "maths.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
|
/// 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
|
/// there are no validity or other checks performed on the returned data
|
||||||
/// (other than memory safety wrt to the view). this is deliberate, so
|
/// this is deliberate, so that the function is safe to call on user
|
||||||
/// that the function is safe to call on user supplied data during
|
/// supplied data during parsing routines. it is up to the user to ensure
|
||||||
/// parsing routines. it is up to the user to ensure the object is valid.
|
/// 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
|
/// the extract value
|
||||||
@ -631,10 +631,33 @@ namespace util {
|
|||||||
ValueT const&
|
ValueT const&
|
||||||
extract (util::view<const ByteT*> &buffer)
|
extract (util::view<const ByteT*> &buffer)
|
||||||
{
|
{
|
||||||
if (buffer.size () < sizeof (ValueT))
|
if (unlikely (sizeof (ValueT) > buffer.size ()))
|
||||||
throw std::runtime_error ("insufficient data for view shift");
|
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));
|
buffer = buffer.consume (sizeof (ValueT));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user