92 #ifndef PSTORE_SERIALIZE_TYPES_HPP 93 #define PSTORE_SERIALIZE_TYPES_HPP 98 #include "pstore/serialize/common.hpp" 99 #include "pstore/support/gsl.hpp" 100 #include "pstore/support/portab.hpp" 103 namespace serialize {
105 template <
typename Archive>
106 using archive_result_type =
typename std::remove_reference<Archive>::type::result_type;
117 template <
typename Ty,
typename Enable =
void>
132 template <
typename Archive>
133 static auto write (Archive && archive, Ty
const & v) -> archive_result_type<Archive> {
134 return v.write (std::forward<Archive> (archive));
152 template <
typename Archive>
153 static void read (Archive && archive, Ty & v) {
154 PSTORE_ASSERT (reinterpret_cast<std::uintptr_t> (&v) %
alignof (Ty) == 0);
155 new (&v) Ty (std::forward<Archive> (archive));
164 template <
typename Archive,
typename Span>
165 static void getn (Archive && archive, Span span) {
166 getn_helper::invoke<Archive, Span> (std::forward<Archive> (archive), span,
173 template <
typename Archive,
typename Span>
174 static void invoke (Archive && archive, Span span, ...) {
175 for (
auto & v : span) {
181 template <
typename Archive,
typename Span>
183 invoke (Archive && archive, Span span,
184 decltype (&std::remove_reference<Archive>::type::template getn<Span>)) {
191 template <
typename Archive,
typename SpanType>
192 static void readn (Archive && archive, SpanType span) {
193 readn_helper::invoke (std::forward<Archive> (archive), span,
nullptr);
199 template <
typename Archive,
typename SpanType>
200 static void invoke (Archive && archive, SpanType span, ...) {
201 for (
auto & v : span) {
203 std::forward<Archive> (archive), v);
210 template <
typename Archive,
typename SpanType>
212 invoke (Archive && archive, SpanType span,
214 typename std::remove_reference<Archive>::type, SpanType>)) {
216 std::forward<Archive> (archive), span);
236 template <
typename Archive,
typename SpanType>
237 static auto writen (Archive && archive, SpanType span)
238 -> archive_result_type<Archive> {
239 return writen_helper::invoke (std::forward<Archive> (archive), span,
nullptr);
243 template <
typename Archive,
typename SpanType>
244 static auto invoke (Archive && archive, SpanType span, ...)
245 -> archive_result_type<Archive> {
249 for (
auto & v : span) {
251 std::forward<Archive> (archive), v);
258 template <
typename Archive,
typename SpanType>
260 invoke (Archive && archive, SpanType span,
262 typename std::remove_reference<Archive>::type, SpanType>))
263 -> archive_result_type<Archive> {
265 std::forward<Archive> (archive), span);
272 template <
typename Ty>
273 struct serializer<Ty, typename
std::enable_if<std::is_trivial<Ty>::value>::type> {
278 template <
typename Archive>
279 static auto write (Archive && archive, Ty
const & v) -> archive_result_type<Archive> {
280 return archive.put (v);
287 template <
typename Archive,
typename SpanType>
288 static auto writen (Archive && archive, SpanType span) -> archive_result_type<Archive> {
289 static_assert (std::is_same<typename SpanType::element_type, Ty>::value,
290 "span type does not match the serializer type");
291 return archive.putn (span);
299 template <
typename Archive>
300 static void read (Archive && archive, Ty & out) {
301 PSTORE_ASSERT (reinterpret_cast<std::uintptr_t> (&out) %
alignof (Ty) == 0);
309 template <
typename Archive,
typename Span>
310 static void readn (Archive && archive, Span span) {
311 static_assert (std::is_same<typename Span::element_type, Ty>::value,
312 "span type does not match the serializer type");
313 details::getn_helper::getn (std::forward<Archive> (archive), span);
320 template <
typename T1,
typename T2>
322 template <
typename T>
325 template <
typename T1,
typename T2>
327 template <
typename T1,
typename T2>
329 template <
typename T1,
typename T2>
337 template <
typename Archive,
typename ElementType>
338 void read_uninit (Archive && archive, ElementType & uninit) {
342 template <
typename Archive,
typename ElementType>
344 static_assert (uninit_span.size () == 1,
"Expected span to be 1 in specialization");
348 template <
typename Archive,
typename ElementType, std::ptrdiff_t Extent>
350 details::readn_helper::readn (std::forward<Archive> (archive), uninit_span);
355 template <std::ptrdiff_t SpanExtent>
357 static std::array<std::uint8_t, 4>
const deadbeef{{0xDE, 0xAD, 0xBE, 0xEF}};
359 auto it = std::begin (sp);
360 auto end = std::end (sp);
362 for (
auto uint32_count = sp.size () / 4U; uint32_count > 0U; --uint32_count) {
363 *(it++) = deadbeef[0];
364 *(it++) = deadbeef[1];
365 *(it++) = deadbeef[2];
366 *(it++) = deadbeef[3];
369 auto index = std::size_t{0};
370 for (; it != end; ++it) {
371 *it = deadbeef.at (index);
372 index = (index + 1) % deadbeef.size ();
376 template <std::ptrdiff_t SpanExtent>
379 template <
typename T>
380 inline void flood (T *
const t) noexcept {
381 flood (gsl::make_span (reinterpret_cast<std::uint8_t *> (t),
sizeof (T)));
392 template <std::
size_t Len, std::
size_t Align>
395 std::uint8_t _[(Len + Align - 1) / Align * Align];
398 PSTORE_STATIC_ASSERT (
alignof (
type) >= Align);
399 PSTORE_STATIC_ASSERT (
sizeof (
type) >= Len);
411 template <
typename Ty,
typename Archive>
413 using T2 =
typename std::remove_const<Ty>::type;
415 flood (&uninit_buffer);
418 auto & t2 =
reinterpret_cast<T2 &
> (uninit_buffer);
419 read_uninit (std::forward<Archive> (archive), t2);
422 auto dtor = [] (T2 * p) { p->~T2 (); };
423 std::unique_ptr<T2, decltype (dtor)> d (&t2, dtor);
424 return std::move (t2);
429 template <
typename Archive,
typename Ty>
431 PSTORE_ASSERT (span.size () == 1U);
432 span[0] = read<Ty> (std::forward<Archive> (archive));
435 template <
typename Archive,
typename ElementType, std::ptrdiff_t Extent>
437 for (
auto & element : span) {
438 element.~ElementType ();
440 read_uninit (std::forward<Archive> (archive), span);
452 template <
typename Archive,
typename Ty>
453 auto write (Archive && archive, Ty
const & ty) -> archive_result_type<Archive> {
458 template <
typename Archive,
typename ElementType, std::ptrdiff_t Extent>
460 -> archive_result_type<Archive> {
461 return details::writen_helper::writen (std::forward<Archive> (archive), sp);
465 template <
typename Archive,
typename ElementType>
467 -> archive_result_type<Archive> {
468 static_assert (sp.size () == 1,
"Expected size to be 1 in specialization");
473 template <
typename Archive,
typename Ty,
typename... Args>
474 auto write (Archive && archive, Ty
const & ty, Args
const &... args)
475 -> archive_result_type<Archive> {
476 auto result =
write (std::forward<Archive> (archive), ty);
477 write (std::forward<Archive> (archive), args...);
491 namespace serialize {
503 template <
typename Archive,
typename InputIterator>
504 void write_range (Archive && archive, InputIterator begin, InputIterator end) {
506 auto const distance = std::distance (begin, end);
507 PSTORE_ASSERT (distance >= 0);
508 write (archive, static_cast<std::size_t> (distance));
510 using value_type =
typename std::iterator_traits<InputIterator>::value_type;
511 std::for_each (begin, end, [&archive] (value_type
const & value) {
512 write (std::forward<Archive> (archive), value);
529 template <
typename Ty,
typename Archive,
typename OutputIterator>
530 OutputIterator
read_range (Archive && archive, OutputIterator output) {
531 auto distance = read<std::size_t> (std::forward<Archive> (archive));
532 while (distance-- > 0) {
533 *output = read<Ty> (std::forward<Archive> (archive));
541 #endif // PSTORE_SERIALIZE_TYPES_HPP static void readn(Archive &&archive, Span span)
Reads a standard-layout value of type Ty from an archive.
Definition: types.hpp:310
A helper class which remembers the first time that it is assigned to.
Definition: common.hpp:46
The primary template for serialization of non standard layout types.
Definition: types.hpp:118
static void read(Archive &&archive, Ty &out)
Reads a standard-layout value of type Ty from an archive.
Definition: types.hpp:300
void write_range(Archive &&archive, InputIterator begin, InputIterator end)
Writes a range of values [first, last) to the supplied archive.
Definition: types.hpp:504
static auto write(Archive &&archive, Ty const &v) -> archive_result_type< Archive >
Writes an single value of type Ty to an archive.
Definition: types.hpp:133
This template class enables us to provide the "writen()" interface on all serialization classes witho...
Definition: types.hpp:234
OutputIterator read_range(Archive &&archive, OutputIterator output)
Reads a sequence of values from the given archive and adds them to an iterator range beginning at 'ou...
Definition: types.hpp:530
Definition: chunked_sequence.hpp:607
Definition: types.hpp:162
static auto writen(Archive &&archive, SpanType span) -> archive_result_type< Archive >
Writes a span of objects to an archive.
Definition: types.hpp:288
static void read(Archive &&archive, Ty &v)
Reads a value of type Ty from an archive.
Definition: types.hpp:153
Definition: nonpod2.cpp:40
Definition: types.hpp:189
Definition: types.hpp:394
If the two types T1 and T2 have a compatible representation when serialized, provides the member cons...
Definition: types.hpp:321
static auto write(Archive &&archive, Ty const &v) -> archive_result_type< Archive >
Writes an individual object to an archive.
Definition: types.hpp:279
Definition: types.hpp:393