104 #ifndef PSTORE_SERIALIZE_ARCHIVE_HPP 105 #define PSTORE_SERIALIZE_ARCHIVE_HPP 109 #include "pstore/serialize/common.hpp" 113 namespace serialize {
117 template <
typename T>
118 auto unsigned_cast (T
const & t) ->
typename std::make_unsigned<T>::type {
119 using unsigned_type =
typename std::make_unsigned<T>::type;
120 PSTORE_ASSERT (t >= 0);
121 return static_cast<unsigned_type
> (t);
138 template <
typename WriterPolicy>
141 using policy_type = WriterPolicy;
142 using result_type =
typename policy_type::result_type;
148 no_ex_escape ([
this] () { this->flush (); });
159 template <
typename Ty>
160 auto put (Ty
const & t) -> result_type {
161 static_assert (std::is_standard_layout<Ty>::value,
162 "writer_base can only write standard-layout types!");
163 PSTORE_ASSERT (!flushed_);
164 result_type r = policy_.put (t);
165 bytes_consumed_ +=
sizeof (t);
176 template <
typename Span>
177 auto putn (Span sp) -> result_type {
178 using element_type =
typename Span::element_type;
179 static_assert (std::is_standard_layout<element_type>::value,
180 "writer_base can only write standard-layout types!");
181 PSTORE_ASSERT (!flushed_);
182 auto r = putn_helper::template putn<Span> (policy_, sp);
183 bytes_consumed_ += unsigned_cast (sp.size_bytes ());
202 return bytes_produced_helper (*this).get (policy_,
nullptr);
208 WriterPolicy
const & writer_policy ()
const noexcept {
return policy_; }
212 explicit writer_base (WriterPolicy policy = WriterPolicy ())
213 : policy_{std::move (policy)} {}
218 class bytes_produced_helper {
220 explicit bytes_produced_helper (
writer_base const & writer)
224 template <
typename Policy>
225 std::size_t
get (Policy
const & , ...) {
228 template <
typename Policy>
229 std::size_t
get (Policy
const & policy, decltype (&Policy::bytes_produced)) {
230 return policy.bytes_produced ();
241 template <
typename Span>
242 static auto putn (WriterPolicy & policy, Span span) -> result_type {
243 return invoke (policy, span,
nullptr);
249 template <
typename P,
typename Span>
250 static auto invoke (P & policy, Span span, ...)
253 for (
auto & v : span) {
261 template <
typename P,
typename Span>
262 static auto invoke (P & policy, Span span, decltype (&P::template putn<Span>))
264 return policy.putn (span);
268 WriterPolicy policy_;
269 std::size_t bytes_consumed_ = 0U;
270 bool flushed_{
false};
277 using result_type = std::size_t;
278 using container = std::vector<std::uint8_t>;
279 using const_iterator = container::const_iterator;
284 template <
typename Ty>
285 auto put (Ty
const & t) -> result_type {
286 auto const old_size = bytes_.
size ();
287 auto const *
const first =
reinterpret_cast<std::uint8_t
const *
> (&t);
288 std::copy (first, first +
sizeof (Ty), std::back_inserter (bytes_));
292 template <
typename SpanType>
293 auto putn (SpanType sp) -> result_type {
294 auto const old_size = bytes_.size ();
295 auto const *
const first =
reinterpret_cast<std::uint8_t
const *
> (sp.data ());
296 std::copy (first, first + sp.size_bytes (), std::back_inserter (bytes_));
301 std::size_t
size () const noexcept {
return bytes_.size (); }
303 void flush () noexcept {}
307 container::const_iterator
begin ()
const {
return std::begin (bytes_); }
310 container::const_iterator
end ()
const {
return std::end (bytes_); }
326 explicit vector_writer (std::vector<std::uint8_t> & container)
337 using container = policy_type::container;
338 using const_iterator = policy_type::const_iterator;
342 const_iterator
begin ()
const {
return writer_policy ().begin (); }
344 const_iterator
end ()
const {
return writer_policy ().end (); }
366 using result_type =
void *;
369 : begin_ (static_cast<std::uint8_t *> (first))
371 , end_ (static_cast<std::uint8_t *> (last))
373 , it_ (static_cast<std::uint8_t *> (first)) {
376 PSTORE_ASSERT (end_ >= it_);
381 template <
typename Ty>
382 auto put (Ty
const & v) -> result_type {
383 auto const size =
sizeof (v);
384 PSTORE_ASSERT (it_ + size <= end_);
385 auto const result = it_;
386 std::memcpy (it_, &v, size);
388 PSTORE_ASSERT (it_ <= end_);
393 std::size_t
size () const noexcept {
394 PSTORE_ASSERT (it_ >= begin_);
395 static_assert (
sizeof (std::size_t) >=
sizeof (std::ptrdiff_t),
396 "sizeof size_t should be at least sizeof ptrdiff_t");
397 return static_cast<std::size_t
> (it_ - begin_);
400 void flush () noexcept {}
402 using const_iterator = std::uint8_t
const *;
405 const_iterator
begin () const noexcept {
return begin_; }
407 const_iterator
end () const noexcept {
return it_; }
411 std::uint8_t * begin_;
441 static_cast<
std::uint8_t *> (first) + size) {}
445 template <
typename T>
454 using const_iterator = policy_type::const_iterator;
458 const_iterator
begin ()
const {
return writer_policy ().begin (); }
460 const_iterator
end ()
const {
return writer_policy ().end (); }
483 template <
typename Ty>
487 template <
typename SpanType>
492 void flush () noexcept {}
505 ~
null () noexcept
override;
507 null & operator= (
null const &) =
delete;
508 null & operator= (
null &&) =
delete;
517 template <
typename InputIterator>
519 static_assert (
sizeof (
typename std::iterator_traits<InputIterator>::value_type) ==
521 "archive_reader reads from a byte-wide sequence");
528 InputIterator iterator () {
return first_; }
532 template <
typename Ty>
534 static_assert (std::is_standard_layout<Ty>::value,
535 "range_reader can only read standard-layout types");
536 auto ptr =
reinterpret_cast<std::uint8_t *
> (&v);
537 auto const last = ptr +
sizeof (Ty);
538 while (ptr != last) {
539 *(ptr++) = *(first_++);
543 template <
typename SpanType>
544 void getn (SpanType span) {
545 using element_type =
typename SpanType::element_type;
546 static_assert (std::is_standard_layout<element_type>::value,
547 "range_reader can only read standard-layout types");
548 auto out =
reinterpret_cast<std::uint8_t *
> (span.data ());
549 auto last = out + span.size_bytes ();
550 while (out != last) {
551 *(out++) = *(first_++);
556 InputIterator first_;
565 template <
typename InputIterator>
579 constexpr
buffer_reader (
void const *
const first,
void const *
const last) noexcept
580 : first_ (static_cast<std::uint8_t const *> (first))
581 , last_ (static_cast<std::uint8_t const *> (last)) {}
585 constexpr
buffer_reader (
void const *
const first, std::size_t
const size) noexcept
586 : first_ (static_cast<std::uint8_t const *> (first))
587 , last_ (static_cast<std::uint8_t const *> (first) + size) {}
591 template <
typename SpanType>
593 : first_ (reinterpret_cast<std::uint8_t const *> (span.data ()))
594 , last_ (first_ + span.size_bytes ()) {}
598 template <
typename T>
600 typename std::remove_const<T>::type result;
601 static_assert (std::is_standard_layout<T>::value,
602 "buffer_reader(T&) can only read standard-layout types");
603 if (first_ +
sizeof (T) > last_) {
604 raise (std::errc::no_buffer_space,
605 "Attempted to read past the end of a buffer.");
607 std::memcpy (&result, first_,
sizeof (T));
608 first_ +=
sizeof (T);
613 std::uint8_t
const * first_;
614 std::uint8_t
const * last_;
621 #endif // PSTORE_SERIALIZE_ARCHIVE_HPP std::size_t bytes_consumed() const
Returns the number of bytes that have been written via this archive.
Definition: archive.hpp:197
A helper class which remembers the first time that it is assigned to.
Definition: common.hpp:46
const_iterator begin() const noexcept
Returns a const_iterator for the beginning of the byte range.
Definition: archive.hpp:405
buffer_writer(void *const first, void *const last)
Constructs the writer using the range [first, last).
Definition: archive.hpp:429
auto put(Ty const &t) -> result_type
Writes one or more instances of a standard-layout type Ty to the output. Must not be used once the st...
Definition: archive.hpp:160
Definition: archive.hpp:480
The base class for archive-writer objects.
Definition: archive.hpp:139
const_iterator end() const
Returns a const_iterator for the end of the byte vector managed by the object.
Definition: archive.hpp:460
container::const_iterator begin() const
Returns a const_iterator for the beginning of the byte vector managed by the object.
Definition: archive.hpp:307
std::size_t size() const noexcept
Returns the size of the byte vector managed by the object.
Definition: archive.hpp:301
Definition: chunked_sequence.hpp:607
void flush()
Flushes the stream to the output.
Definition: archive.hpp:189
The archiver put() and [optional] putn() methods can optionally return a value to the caller...
Definition: archive.hpp:130
constexpr buffer_reader(void const *const first, void const *const last) noexcept
Constructs the writer using a pair of pointer to define the range [first, last).
Definition: archive.hpp:579
buffer_writer(T *t)
Constructs a buffer_writer from a pointer to allocated uninitialized storage.
Definition: archive.hpp:446
const_iterator end() const
Returns a const_iterator for the end of the byte vector managed by the object.
Definition: archive.hpp:344
An archive-writer which simply discards any data that it writes.
Definition: archive.hpp:499
Definition: archive.hpp:422
buffer_writer(void *const first, std::size_t const size)
Constructs the writer starting at the address given by 'first' and with a number of bytes 'size'...
Definition: archive.hpp:439
std::ostream & operator<<(std::ostream &os, vector_writer const &writer)
Writes the contents of a vector_writer object to an ostream as a stream of space-separated two-digit ...
Definition: archive.cpp:60
container::const_iterator end() const
Returns a const_iterator for the end of the byte vector managed by the object.
Definition: archive.hpp:310
const_iterator begin() const
Returns a const_iterator for the beginning of the byte vector managed by the object.
Definition: archive.hpp:458
constexpr buffer_reader(void const *const first, std::size_t const size) noexcept
Constructs the writer using a pointer and size to define the range [first, first+size).
Definition: archive.hpp:585
database_reader make_reader(pstore::database const &db, pstore::address const addr) noexcept
A convenience function which provides symmetry with the make_writer() function.
Definition: db_archive.hpp:186
Definition: nonpod2.cpp:40
Definition: archive.hpp:364
buffer_reader(SpanType const span) noexcept
Constructs the writer using a pointer and size to define the range [first, first+size).
Definition: archive.hpp:592
An archive-writer which writes data to a std::vector of std::uint8_t bytes.
Definition: archive.hpp:324
Provides an pstore-specific error codes and a suitable error category for them.
const_iterator begin() const
Returns a const_iterator for the beginning of the byte vector managed by the object.
Definition: archive.hpp:342
An archive-reader which consumes data from an iterator.
Definition: archive.hpp:518
An archive-reader which consumes data from a supplied pointer range.
Definition: archive.hpp:576
Definition: archive.hpp:275
const_iterator end() const noexcept
Returns a const_iterator for the end of byte range written to the buffer.
Definition: archive.hpp:407
WriterPolicy & writer_policy() noexcept
Definition: archive.hpp:207
auto putn(Span sp) -> result_type
Writes a span of values to the output.
Definition: archive.hpp:177
range_reader(InputIterator first)
Constructs the writer using an input iterator.
Definition: archive.hpp:525
std::size_t size() const noexcept
Returns the number of bytes written to the buffer.
Definition: archive.hpp:393
auto put(Ty const &v) -> result_type
Writes an object to the output buffer.
Definition: archive.hpp:382
std::size_t bytes_produced() const
Returns the number of bytes that the policy object wrote to its final destination.
Definition: archive.hpp:201