pupene  0.2.0
pup-core.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "pup-pupper.h"
4 
5 /** \file
6  * Helpers for writing `pup` functions. pup_object() is the default go-to
7  * for pup() implementations.
8  */
9 namespace pupene::fns {
10 
11  /**
12  * Describes a type by enumerating its members, used in conjunction
13  * with pup() implementations.
14  *
15  *
16  * #### Example: a `pup` for [glm][glm]'s vec2 type
17  *
18  * ```{.cpp}
19  * template<typename P>
20  * void pup(Pupper<P>& p, glm::vec2& v, const Meta& meta) {
21  * pup_object(p, v, meta, [&v](auto&& fpup) {
22  * fpup(v.x, "x");
23  * fpup(v.y, "y");
24  * });
25  * }
26  * ```
27  *
28  * `body_fn` is not invoked if begin() returns PupPolicy::consume_object.
29  *
30  * @tparam Fn has signature `[](auto&&)`
31  * @param body_fn invoked with `[](auto& v, const Meta& meta)`,
32  * where `v` is a member of `object`
33  *
34  * [glm]: https://glm.g-truc.net/
35  */
36  template <typename P,
37  typename T,
38  typename Fn>
39  void pup_object(Pupper<P>& p,
40  T& object,
41  const Meta& meta,
42  Fn&& body_fn) {
43 
44  const auto valid_meta = (Meta::Type::Value != meta.type)
45  ? meta
47 
48  auto policy = begin(p, object, valid_meta);
49  if (policy == PupPolicy::pup_object) {
50  body_fn([&p](auto& v, const Meta& meta) {
51  pup(p, v, meta);
52  });
53  }
54  end(p, valid_meta);
55  }
56 
57  /**
58  * A pup_object() for dealing with iterable types. Encodes
59  * `container` as `size` followed by the contents.
60  *
61  * @tparam BodyFn has signature `[](auto&&, uint32_t size)`
62  * @param body_fn invoked with `[](auto& v, const Meta& meta)`,
63  * where `v` is a member of `object`
64  */
65  template <typename P,
66  typename Iterable,
67  typename BodyFn>
69  Iterable container,
70  const Meta& meta,
71  BodyFn&& body_fn) {
72 
73  auto body = [&p, &vs = container, &body_fn](auto&& fpup) {
74  auto size = static_cast<uint32_t>(vs.size());
75  fpup(size, "size");
76 
77  const Meta data = {"data", Meta::Type::Array};
78  pup_object(p, vs, data, [&body_fn, size](auto&& fpup_data) {
79  body_fn(fpup_data, size);
80  });
81  };
82  pup_object(p, container, meta, body);
83  }
84 
85  /**
86  * Pups most STL-like containers, including strings. This
87  * function should only be called by pupper implementations.
88  *
89  * Puppers commonly deal in formats where strings are considered
90  * fundamental/built-in types - if this is not the case, the pupper
91  * must specialize on `std::string`, and pup to this function, e.g.:
92  *
93  * ```{.cpp}
94  * template <>
95  * void pupene::BinaryReader::pup(std::string& value, const Meta& meta) {
96  * pup_iterable(*this, value, meta);
97  * }
98  * ```
99  *
100  * The `container` object is encoded as `size` (element count) followed by its contents.
101  *
102  * #### Example/layout
103  *
104  * ```{.cpp}
105  * using pupene;
106  * using int_string_pair = std::pair<uint32_t, std::string>;
107  *
108  * std::vector<int_string_pair> pairs =
109  * {{1, "one"}, {2, "two"}, {4, "four"}};
110  *
111  * auto pupper = debug_pupper(std::cout);
112  * pup(pupper, pairs, {});
113  *
114  * // alternatively:
115  * do_pup(NullPupper{}, pairs, true);
116  * ```
117  *
118  * DebugPupper output:
119  *
120  * ```
121  * object()
122  * pup(size, 3)
123  * array(data)
124  * object()
125  * pup(key, 1)
126  * pup(value, one)
127  * ~object()
128  * object()
129  * pup(key, 2)
130  * pup(value, two)
131  * ~object()
132  * object()
133  * pup(key, 4)
134  * pup(value, four)
135  * ~object()
136  * ~array(data)
137  * ~object()
138  * ```
139  *
140  * @see enable_if_pup_iterable
141  */
142  template <typename P,
143  typename Iterable,
144  typename = enable_if_pup_iterable<Iterable>>
145  void pup_iterable(Pupper<P>& p,
146  Iterable& container,
147  const Meta& meta) {
148 
149  auto pup_entries = [&vs = container](auto&& fpup, auto size) {
150  vs.resize(size);
151 
152  for (auto& v : vs)
153  fpup(v, {});
154  };
155 
156  pup_object_container(p, container, meta, pup_entries);
157  }
158 }
pup object using its component pup functions
Definition: debug.cpp:4
const char * name
The name typically matches the name of the represented field.
Definition: traits.h:18
void pup_object_container(Pupper< P > &p, Iterable container, const Meta &meta, BodyFn &&body_fn)
A pup_object() for dealing with iterable types.
Definition: pup-core.h:68
void pup_object(Pupper< P > &p, T &object, const Meta &meta, Fn &&body_fn)
Describes a type by enumerating its members, used in conjunction with pup() implementations.
Definition: pup-core.h:39
Holds name and type of objects.
Definition: traits.h:7
void pup_iterable(Pupper< P > &p, Iterable &container, const Meta &meta)
Pups most STL-like containers, including strings.
Definition: pup-core.h:145
Meta(const char *name, Type type=Type::Value)
Definition: traits.h:13
const Type type
Definition: traits.h:19
PupPolicy
Controls an object&#39;s pup() behavior.
Definition: pupper.h:17
Base class for working with puppable types.
Definition: pupper.h:83