xref: /aosp_15_r20/external/emboss/doc/cpp-reference.md (revision 99e0aae7469b87d12f0ad23e61142c2d74c1ef70)
1*99e0aae7SDavid Rees# Emboss C++ Generated Code Reference
2*99e0aae7SDavid Rees
3*99e0aae7SDavid Rees## `struct`s
4*99e0aae7SDavid Rees
5*99e0aae7SDavid ReesA `struct` will have a corresponding view class, and functions to create views.
6*99e0aae7SDavid Rees
7*99e0aae7SDavid Rees### <code>Make*Struct*View</code> free function
8*99e0aae7SDavid Rees
9*99e0aae7SDavid Rees```c++
10*99e0aae7SDavid Reestemplate <typename T>
11*99e0aae7SDavid Reesauto MakeStructView(/* view parameters, */ T *data, size_t size);
12*99e0aae7SDavid Rees```
13*99e0aae7SDavid Rees
14*99e0aae7SDavid Rees```c++
15*99e0aae7SDavid Reestemplate <typename T>
16*99e0aae7SDavid Reesauto MakeStructView(/* view parameters, */ T *container);
17*99e0aae7SDavid Rees```
18*99e0aae7SDavid Rees
19*99e0aae7SDavid Rees*`Struct`* will be replaced by the name of the specific `struct` whose view
20*99e0aae7SDavid Reeswill be constructed; for example, to make a view for `struct Message`, call the
21*99e0aae7SDavid Rees`MakeMessageView` function.
22*99e0aae7SDavid Rees
23*99e0aae7SDavid Rees*View parameters* will be replaced by one argument for each parameter attached
24*99e0aae7SDavid Reesto the `struct`.  E.g., for:
25*99e0aae7SDavid Rees
26*99e0aae7SDavid Rees```
27*99e0aae7SDavid Reesstruct Foo(x: UInt:8):
28*99e0aae7SDavid Rees   --
29*99e0aae7SDavid Rees```
30*99e0aae7SDavid Rees
31*99e0aae7SDavid Rees`MakeFooView` will be:
32*99e0aae7SDavid Rees
33*99e0aae7SDavid Rees```c++
34*99e0aae7SDavid Reestemplate <typename T>
35*99e0aae7SDavid Reesauto MakeFooView(std::uint8_t x, T *data, size_t size);
36*99e0aae7SDavid Rees```
37*99e0aae7SDavid Rees
38*99e0aae7SDavid Rees```c++
39*99e0aae7SDavid Reestemplate <typename T>
40*99e0aae7SDavid Reesauto MakeFooView(std::uint8_t x, T *container);
41*99e0aae7SDavid Rees```
42*99e0aae7SDavid Rees
43*99e0aae7SDavid ReesAnd for:
44*99e0aae7SDavid Rees
45*99e0aae7SDavid Rees```
46*99e0aae7SDavid Reesstruct Bar(x: UInt:8, y: Int:32):
47*99e0aae7SDavid Rees  --
48*99e0aae7SDavid Rees```
49*99e0aae7SDavid Rees
50*99e0aae7SDavid Rees`MakeBarView` will be:
51*99e0aae7SDavid Rees
52*99e0aae7SDavid Rees```c++
53*99e0aae7SDavid Reestemplate <typename T>
54*99e0aae7SDavid Reesauto MakeBarView(std::uint8_t x, std::int32_t y, T *data, size_t size);
55*99e0aae7SDavid Rees```
56*99e0aae7SDavid Rees
57*99e0aae7SDavid Rees```c++
58*99e0aae7SDavid Reestemplate <typename T>
59*99e0aae7SDavid Reesauto MakeBarView(std::uint8_t x, std::int32_t y, T *container);
60*99e0aae7SDavid Rees```
61*99e0aae7SDavid Rees
62*99e0aae7SDavid ReesThe <code>Make*Struct*View</code> functions construct a view for *`Struct`*
63*99e0aae7SDavid Reesover the given bytes.  For the data/size form, the type `T` must be a character
64*99e0aae7SDavid Reestype: `char`, `const char`, `unsigned char`, `const unsigned char`, `signed
65*99e0aae7SDavid Reeschar`, or `const signed char`.  For the container form, the container can be a
66*99e0aae7SDavid Rees`std::vector`, `std::array`, or `std::basic_string` of a character type, or any
67*99e0aae7SDavid Reesother type with a `data()` method that returns a possibly-`const` `char *`,
68*99e0aae7SDavid Rees`signed char *`, or `unsigned char *`, and a `size()` method that returns a size
69*99e0aae7SDavid Reesin bytes.  Google's `absl::string_view` is one example of such a type.
70*99e0aae7SDavid Rees
71*99e0aae7SDavid ReesIf given a pointer to a `const` character type or a `const` reference to a
72*99e0aae7SDavid Reescontainer, <code>Make*Struct*View</code> will return a read-only view; otherwise
73*99e0aae7SDavid Reesit will return a read-write view.
74*99e0aae7SDavid Rees
75*99e0aae7SDavid ReesThe result of <code>Make*Struct*View</code> should be stored in an `auto`
76*99e0aae7SDavid Reesvariable:
77*99e0aae7SDavid Rees
78*99e0aae7SDavid Rees```c++
79*99e0aae7SDavid Reesauto view = MakeFooView(byte_buffer, available_byte_count);
80*99e0aae7SDavid Rees```
81*99e0aae7SDavid Rees
82*99e0aae7SDavid ReesThe specific type returned by <code>Make*Struct*View</code> is subject to
83*99e0aae7SDavid Reeschange.
84*99e0aae7SDavid Rees
85*99e0aae7SDavid Rees
86*99e0aae7SDavid Rees### `CopyFrom` method
87*99e0aae7SDavid Rees
88*99e0aae7SDavid Rees```c++
89*99e0aae7SDavid Reestemplate <typename OtherStorage>
90*99e0aae7SDavid Reesvoid CopyFrom(GenericStructView<OtherStorage> other) const;
91*99e0aae7SDavid Rees```
92*99e0aae7SDavid Rees
93*99e0aae7SDavid ReesThe `CopyFrom` method copies data from the view `other` into the current view.
94*99e0aae7SDavid ReesWhen complete, the current view's backing storage will contain the same bytes
95*99e0aae7SDavid Reesas `other`.  This works even if the view's backing storage overlaps, in which
96*99e0aae7SDavid Reescase `other`'s backing storage is modified by the operation.
97*99e0aae7SDavid Rees
98*99e0aae7SDavid Rees### `UncheckedCopyFrom` method
99*99e0aae7SDavid Rees
100*99e0aae7SDavid Rees```c++
101*99e0aae7SDavid Reestemplate <typename OtherStorage>
102*99e0aae7SDavid Reesvoid UncheckedCopyFrom(GenericStructView<OtherStorage> other) const;
103*99e0aae7SDavid Rees```
104*99e0aae7SDavid Rees
105*99e0aae7SDavid ReesThe `UncheckedCopyFrom` method performs the same operation as `CopyFrom` but
106*99e0aae7SDavid Reeswithout any checks on the integrity of or the compatibility of the two views.
107*99e0aae7SDavid Rees
108*99e0aae7SDavid Rees### `TryToCopyFrom` method
109*99e0aae7SDavid Rees
110*99e0aae7SDavid Rees```c++
111*99e0aae7SDavid Reestemplate <typename OtherStorage>
112*99e0aae7SDavid Reesbool TryToCopyFrom(GenericStructView<OtherStorage> other) const;
113*99e0aae7SDavid Rees```
114*99e0aae7SDavid Rees
115*99e0aae7SDavid Rees`TryToCopyFrom` copies data from `other` into the current view, if `other` is
116*99e0aae7SDavid Rees`Ok()` and the current backing storage is large enough to hold `other`'s data.
117*99e0aae7SDavid Rees
118*99e0aae7SDavid Rees### `Equals` method
119*99e0aae7SDavid Rees
120*99e0aae7SDavid Rees```c++
121*99e0aae7SDavid Reestemplate <typename OtherStorage>
122*99e0aae7SDavid Reesbool Equals(GenericStructView<OtherStorage> other);
123*99e0aae7SDavid Rees```
124*99e0aae7SDavid Rees
125*99e0aae7SDavid ReesThe `Equals` method returns `true` if and only if itself and `other` contain the
126*99e0aae7SDavid Reessame fields yielding equivalent values (as measured by the `==` operator).
127*99e0aae7SDavid Rees`Equals()` should only be called if `Ok()` is true on both views.
128*99e0aae7SDavid Rees
129*99e0aae7SDavid Rees### `UncheckedEquals` method
130*99e0aae7SDavid Rees
131*99e0aae7SDavid Rees```c++
132*99e0aae7SDavid Reestemplate <typename OtherStorage>
133*99e0aae7SDavid Reesbool UncheckedEquals(GenericStructView<OtherStorage> other);
134*99e0aae7SDavid Rees```
135*99e0aae7SDavid Rees
136*99e0aae7SDavid ReesThe `UncheckedEquals` method performs the same operation as `Equals`, but
137*99e0aae7SDavid Reeswithout any checks on the integrity of or the compatibility of the two views
138*99e0aae7SDavid Reeswhen reading values.  `UncheckedEquals()` should only be called if `Ok()` is
139*99e0aae7SDavid Reestrue on both views.
140*99e0aae7SDavid Rees
141*99e0aae7SDavid Rees### `Ok` method
142*99e0aae7SDavid Rees
143*99e0aae7SDavid Rees```c++
144*99e0aae7SDavid Reesbool Ok() const;
145*99e0aae7SDavid Rees```
146*99e0aae7SDavid Rees
147*99e0aae7SDavid ReesThe `Ok` method returns `true` if and only if there are enough bytes in the
148*99e0aae7SDavid Reesbacking store, and the `Ok` methods of all active fields return `true`.
149*99e0aae7SDavid Rees
150*99e0aae7SDavid Rees
151*99e0aae7SDavid Rees### `IsComplete` method
152*99e0aae7SDavid Rees
153*99e0aae7SDavid Rees```c++
154*99e0aae7SDavid Reesbool IsComplete() const;
155*99e0aae7SDavid Rees```
156*99e0aae7SDavid Rees
157*99e0aae7SDavid ReesThe `IsComplete` method returns `true` if there are enough bytes in the backing
158*99e0aae7SDavid Reesstore to fully contain the `struct`.  If `IsComplete()` returns `true` but
159*99e0aae7SDavid Rees`Ok()` returns `false`, then the structure is broken in some way that cannot be
160*99e0aae7SDavid Reesfixed by adding more bytes.
161*99e0aae7SDavid Rees
162*99e0aae7SDavid Rees
163*99e0aae7SDavid Rees### `IntrinsicSizeInBytes` method
164*99e0aae7SDavid Rees
165*99e0aae7SDavid Rees```c++
166*99e0aae7SDavid Reesauto IntrinsicSizeInBytes() const;
167*99e0aae7SDavid Rees```
168*99e0aae7SDavid Rees
169*99e0aae7SDavid Reesor
170*99e0aae7SDavid Rees
171*99e0aae7SDavid Rees```c++
172*99e0aae7SDavid Reesstatic constexpr auto IntrinsicSizeInBytes() const;
173*99e0aae7SDavid Rees```
174*99e0aae7SDavid Rees
175*99e0aae7SDavid ReesThe `IntrinsicSizeInBytes` method is the [field method](#struct-field-methods)
176*99e0aae7SDavid Reesfor [`$size_in_bytes`](language-reference.md#size-in-bytes).  The `Read` method
177*99e0aae7SDavid Reesof the result returns the size of the `struct`, and the `Ok` method returns
178*99e0aae7SDavid Rees`true` if the `struct`'s intrinsic size is known; i.e.:
179*99e0aae7SDavid Rees
180*99e0aae7SDavid Rees```c++
181*99e0aae7SDavid Reesif (view.IntrinsicSizeInBytes().Ok()) {
182*99e0aae7SDavid Rees  // The exact return type of view.IntrinsicSizeInBytes().Read() may vary, but
183*99e0aae7SDavid Rees  // it will always be implicitly convertible to std::uint64_t.
184*99e0aae7SDavid Rees  std::uint64_t view_size = view.IntrinsicSizeInBytes().Read();
185*99e0aae7SDavid Rees}
186*99e0aae7SDavid Rees```
187*99e0aae7SDavid Rees
188*99e0aae7SDavid ReesAlternately, if you are sure the size is known:
189*99e0aae7SDavid Rees
190*99e0aae7SDavid Rees```c++
191*99e0aae7SDavid Reesstd::uint64_t view_size = view.IntrinsicSizeInBytes().UncheckedRead();
192*99e0aae7SDavid Rees```
193*99e0aae7SDavid Rees
194*99e0aae7SDavid ReesOr, if the size is a compile-time constant:
195*99e0aae7SDavid Rees
196*99e0aae7SDavid Rees```c++
197*99e0aae7SDavid Reesconstexpr std::uint64_t view_size = StructView::IntrinsicSizeInBytes().Read();
198*99e0aae7SDavid Reesconstexpr std::uint64_t view_size2 = Struct::IntrinsicSizeInBytes();
199*99e0aae7SDavid Rees```
200*99e0aae7SDavid Rees
201*99e0aae7SDavid Rees
202*99e0aae7SDavid Rees### `MaxSizeInBytes` method
203*99e0aae7SDavid Rees
204*99e0aae7SDavid Rees```c++
205*99e0aae7SDavid Reesauto MaxSizeInBytes() const;
206*99e0aae7SDavid Rees```
207*99e0aae7SDavid Rees
208*99e0aae7SDavid Reesor
209*99e0aae7SDavid Rees
210*99e0aae7SDavid Rees```c++
211*99e0aae7SDavid Reesstatic constexpr auto MaxSizeInBytes() const;
212*99e0aae7SDavid Rees```
213*99e0aae7SDavid Rees
214*99e0aae7SDavid ReesThe `MaxSizeInBytes` method is the [field method](#struct-field-methods)
215*99e0aae7SDavid Reesfor [`$max_size_in_bytes`](language-reference.md#max-size-in-bytes).  The `Read`
216*99e0aae7SDavid Reesmethod of the result returns the maximum size of the `struct`, and the `Ok`
217*99e0aae7SDavid Reesalways method returns `true`.
218*99e0aae7SDavid Rees
219*99e0aae7SDavid Rees```c++
220*99e0aae7SDavid Reesassert(view.MaxSizeInBytes().Ok());
221*99e0aae7SDavid Rees// The exact return type of view.MaxSizeInBytes().Read() may vary, but it will
222*99e0aae7SDavid Rees// always be implicitly convertible to std::uint64_t.
223*99e0aae7SDavid Reesstd::uint64_t view_size = view.MaxSizeInBytes().Read();
224*99e0aae7SDavid Rees```
225*99e0aae7SDavid Rees
226*99e0aae7SDavid ReesAlternately:
227*99e0aae7SDavid Rees
228*99e0aae7SDavid Rees```c++
229*99e0aae7SDavid Reesstd::uint64_t view_size = view.MaxSizeInBytes().UncheckedRead();
230*99e0aae7SDavid Rees```
231*99e0aae7SDavid Rees
232*99e0aae7SDavid ReesOr:
233*99e0aae7SDavid Rees
234*99e0aae7SDavid Rees```c++
235*99e0aae7SDavid Reesconstexpr std::uint64_t view_size = StructView::MaxSizeInBytes().Read();
236*99e0aae7SDavid Reesconstexpr std::uint64_t view_size2 = Struct::MaxSizeInBytes();
237*99e0aae7SDavid Rees```
238*99e0aae7SDavid Rees
239*99e0aae7SDavid Rees
240*99e0aae7SDavid Rees### `MinSizeInBytes` method
241*99e0aae7SDavid Rees
242*99e0aae7SDavid Rees```c++
243*99e0aae7SDavid Reesauto MinSizeInBytes() const;
244*99e0aae7SDavid Rees```
245*99e0aae7SDavid Rees
246*99e0aae7SDavid Reesor
247*99e0aae7SDavid Rees
248*99e0aae7SDavid Rees```c++
249*99e0aae7SDavid Reesstatic constexpr auto MinSizeInBytes() const;
250*99e0aae7SDavid Rees```
251*99e0aae7SDavid Rees
252*99e0aae7SDavid ReesThe `MinSizeInBytes` method is the [field method](#struct-field-methods)
253*99e0aae7SDavid Reesfor [`$min_size_in_bytes`](language-reference.md#max-size-in-bytes).  The `Read`
254*99e0aae7SDavid Reesmethod of the result returns the minimum size of the `struct`, and the `Ok`
255*99e0aae7SDavid Reesalways method returns `true`.
256*99e0aae7SDavid Rees
257*99e0aae7SDavid Rees```c++
258*99e0aae7SDavid Reesassert(view.MinSizeInBytes().Ok());
259*99e0aae7SDavid Rees// The exact return type of view.MinSizeInBytes().Read() may vary, but it will
260*99e0aae7SDavid Rees// always be implicitly convertible to std::uint64_t.
261*99e0aae7SDavid Reesstd::uint64_t view_size = view.MinSizeInBytes().Read();
262*99e0aae7SDavid Rees```
263*99e0aae7SDavid Rees
264*99e0aae7SDavid ReesAlternately:
265*99e0aae7SDavid Rees
266*99e0aae7SDavid Rees```c++
267*99e0aae7SDavid Reesstd::uint64_t view_size = view.MinSizeInBytes().UncheckedRead();
268*99e0aae7SDavid Rees```
269*99e0aae7SDavid Rees
270*99e0aae7SDavid ReesOr:
271*99e0aae7SDavid Rees
272*99e0aae7SDavid Rees```c++
273*99e0aae7SDavid Reesconstexpr std::uint64_t view_size = StructView::MinSizeInBytes().Read();
274*99e0aae7SDavid Reesconstexpr std::uint64_t view_size2 = Struct::MinSizeInBytes();
275*99e0aae7SDavid Rees```
276*99e0aae7SDavid Rees
277*99e0aae7SDavid Rees
278*99e0aae7SDavid Rees### `SizeIsKnown` method
279*99e0aae7SDavid Rees
280*99e0aae7SDavid Rees```c++
281*99e0aae7SDavid Reesbool SizeIsKnown() const;
282*99e0aae7SDavid Rees```
283*99e0aae7SDavid Rees
284*99e0aae7SDavid Reesor
285*99e0aae7SDavid Rees
286*99e0aae7SDavid Rees```c++
287*99e0aae7SDavid Reesstatic constexpr bool SizeIsKnown() const;
288*99e0aae7SDavid Rees```
289*99e0aae7SDavid Rees
290*99e0aae7SDavid ReesThe `SizeIsKnown` method is an alias of `IntrinsicSizeInBytes().Ok()`.
291*99e0aae7SDavid Rees
292*99e0aae7SDavid ReesThe `SizeIsKnown` method returns `true` if the size of the `struct` can be
293*99e0aae7SDavid Reesdetermined from the bytes that are available.  For example, consider a `struct`
294*99e0aae7SDavid Reeslike:
295*99e0aae7SDavid Rees
296*99e0aae7SDavid Rees```
297*99e0aae7SDavid Reesstruct Message:
298*99e0aae7SDavid Rees  0 [+4]   UInt        payload_length (pl)
299*99e0aae7SDavid Rees  4 [+pl]  UInt:8[pl]  payload
300*99e0aae7SDavid Rees```
301*99e0aae7SDavid Rees
302*99e0aae7SDavid ReesThe `Message`'s view's `SizeIsKnown` method will return `true` if at least four
303*99e0aae7SDavid Reesbytes are available in the backing store, because it can determine the actual
304*99e0aae7SDavid Reessize of the message if at least four bytes can be read.  If the backing store
305*99e0aae7SDavid Reescontains three or fewer bytes, then `SizeIsKnown` will be false.
306*99e0aae7SDavid Rees
307*99e0aae7SDavid ReesNote that if the `struct` contains no dynamically-sized or dynamically-located
308*99e0aae7SDavid Reesfields, then `SizeIsKnown` will be a `static constexpr` method that always
309*99e0aae7SDavid Reesreturn `true`.
310*99e0aae7SDavid Rees
311*99e0aae7SDavid Rees
312*99e0aae7SDavid Rees### `SizeInBytes` method
313*99e0aae7SDavid Rees
314*99e0aae7SDavid Rees```c++
315*99e0aae7SDavid Reesstd::size_t SizeInBytes() const;
316*99e0aae7SDavid Rees```
317*99e0aae7SDavid Rees
318*99e0aae7SDavid Reesor
319*99e0aae7SDavid Rees
320*99e0aae7SDavid Rees```c++
321*99e0aae7SDavid Reesstatic constexpr std::size_t SizeInBytes() const;
322*99e0aae7SDavid Rees```
323*99e0aae7SDavid Rees
324*99e0aae7SDavid ReesThe `SizeInBytes` method returns
325*99e0aae7SDavid Rees`static_cast<std::size_t>(IntrinsicSizeInBytes().Read())`.
326*99e0aae7SDavid Rees
327*99e0aae7SDavid ReesThe `SizeInBytes` method returns the size of the `struct` in bytes.
328*99e0aae7SDavid Rees`SizeInBytes` asserts that `SizeIsKnown()`, so applications should ensure that
329*99e0aae7SDavid Rees`SizeIsKnown()` before calling `SizeInBytes`.
330*99e0aae7SDavid Rees
331*99e0aae7SDavid ReesIf the `struct` contains no dynamically-sized or dynamically-located fields,
332*99e0aae7SDavid Reesthen `SizeInBytes` will be a `static constexpr` method, and can always be called
333*99e0aae7SDavid Reessafely.
334*99e0aae7SDavid Rees
335*99e0aae7SDavid Rees
336*99e0aae7SDavid Rees### `UpdateFromTextStream` method
337*99e0aae7SDavid Rees
338*99e0aae7SDavid Rees```c++
339*99e0aae7SDavid Reestemplate <class Stream>
340*99e0aae7SDavid Reesbool UpdateFromTextStream(Stream *stream) const;
341*99e0aae7SDavid Rees```
342*99e0aae7SDavid Rees
343*99e0aae7SDavid Rees`UpdateFromTextStream` will read a text-format representation of the structure
344*99e0aae7SDavid Reesfrom the given `stream` and update fields.  Generally, applications would not
345*99e0aae7SDavid Reescall this directly; instead, use the global `UpdateFromText` method, which
346*99e0aae7SDavid Reeshandles setting up a stream from a `std::string`.
347*99e0aae7SDavid Rees
348*99e0aae7SDavid Rees### `WriteToTextStream` method
349*99e0aae7SDavid Rees
350*99e0aae7SDavid Rees```c++
351*99e0aae7SDavid Reestemplate <class Stream>
352*99e0aae7SDavid Reesbool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
353*99e0aae7SDavid Rees```
354*99e0aae7SDavid Rees
355*99e0aae7SDavid Rees`WriteToTextStream` will write a text representation of the current value in a
356*99e0aae7SDavid Reesform that can be decoded by `UpdateFromTextStream`. Generally, applications
357*99e0aae7SDavid Reeswould not call this directly; instead, use the global `WriteToString` method,
358*99e0aae7SDavid Reeswhich handles setting up the stream and returning the resulting string.
359*99e0aae7SDavid Rees
360*99e0aae7SDavid Rees### `BackingStorage` method
361*99e0aae7SDavid Rees
362*99e0aae7SDavid Rees```c++
363*99e0aae7SDavid ReesStorage BackingStorage() const;
364*99e0aae7SDavid Rees```
365*99e0aae7SDavid Rees
366*99e0aae7SDavid ReesReturns the backing storage for the view.  The return type of `BackingStorage()`
367*99e0aae7SDavid Reesis a template parameter on the view.
368*99e0aae7SDavid Rees
369*99e0aae7SDavid Rees
370*99e0aae7SDavid Rees### Field methods {#struct-field-methods}
371*99e0aae7SDavid Rees
372*99e0aae7SDavid ReesEach physical field and virtual field in the `struct` will have a corresponding
373*99e0aae7SDavid Reesmethod in the generated view for that `struct`, which returns a subview of that
374*99e0aae7SDavid Reesfield.  For example, take the `struct` definition:
375*99e0aae7SDavid Rees
376*99e0aae7SDavid Rees```
377*99e0aae7SDavid Reesstruct Foo:
378*99e0aae7SDavid Rees  0 [+4]  UInt  bar
379*99e0aae7SDavid Rees  4 [+4]  Int   baz
380*99e0aae7SDavid Rees  let qux = 2 * bar
381*99e0aae7SDavid Rees  let bar_alias = bar
382*99e0aae7SDavid Rees```
383*99e0aae7SDavid Rees
384*99e0aae7SDavid ReesIn this case, the generated code will have methods
385*99e0aae7SDavid Rees
386*99e0aae7SDavid Rees```c++
387*99e0aae7SDavid Reesauto bar() const;
388*99e0aae7SDavid Reesauto baz() const;
389*99e0aae7SDavid Reesauto qux() const;
390*99e0aae7SDavid Reesauto bar_alias() const;
391*99e0aae7SDavid Rees```
392*99e0aae7SDavid Rees
393*99e0aae7SDavid ReesThe `bar` method will return a `UInt` view, and `baz()` will return an `Int`
394*99e0aae7SDavid Reesview.  The `qux` method will return a pseudo-`UInt` view which can only be read.
395*99e0aae7SDavid ReesThe `bar_alias` method actually forwards to `bar`, and can be both read and
396*99e0aae7SDavid Reeswritten:
397*99e0aae7SDavid Rees
398*99e0aae7SDavid Rees```c++
399*99e0aae7SDavid Reesauto foo_view = MakeFooView(&vector_of_foo_bytes);
400*99e0aae7SDavid Reesuint32_t bar_value = foo_view.bar().Read();
401*99e0aae7SDavid Reesint32_t baz_value = foo_view.baz().Read();
402*99e0aae7SDavid Reesint64_t qux_value = foo_view.qux().Read();
403*99e0aae7SDavid Reesuint32_t bar_alias_value = foo_view.bar_alias().Read();
404*99e0aae7SDavid Reesfoo_view.bar_alias().Write(100);
405*99e0aae7SDavid Reesassert(foo_view.bar().Read() == 100);
406*99e0aae7SDavid Rees```
407*99e0aae7SDavid Rees
408*99e0aae7SDavid ReesAs with <code>Make*Struct*View</code>, the exact return type of field methods is
409*99e0aae7SDavid Reessubject to change; if a field's view must be stored, use an `auto` variable.
410*99e0aae7SDavid Rees
411*99e0aae7SDavid ReesFields in anonymous `bits` are treated as if they were fields of the enclosing
412*99e0aae7SDavid Rees`struct` in the generated code.  Take this `struct`:
413*99e0aae7SDavid Rees
414*99e0aae7SDavid Rees```
415*99e0aae7SDavid Reesstruct Foo:
416*99e0aae7SDavid Rees  0 [+4]  bits:
417*99e0aae7SDavid Rees    5 [+5]  UInt  bar
418*99e0aae7SDavid Rees```
419*99e0aae7SDavid Rees
420*99e0aae7SDavid ReesIn C++, `bar` would be read like so:
421*99e0aae7SDavid Rees
422*99e0aae7SDavid Rees```c++
423*99e0aae7SDavid Reesauto foo_view = MakeFooView(&vector_of_foo_bytes);
424*99e0aae7SDavid Reesuint8_t bar_value = foo_view.bar().Read();
425*99e0aae7SDavid Rees```
426*99e0aae7SDavid Rees
427*99e0aae7SDavid ReesFor each field, there is a <code>has_*field*()</code> method, which returns an
428*99e0aae7SDavid Reesobject.  `has_` methods are typically used for conditional fields.  Suppose you
429*99e0aae7SDavid Reeshave a `struct` like:
430*99e0aae7SDavid Rees
431*99e0aae7SDavid Rees```
432*99e0aae7SDavid Reesstruct Foo:
433*99e0aae7SDavid Rees  0 [+1]  enum  message_type:
434*99e0aae7SDavid Rees    BAR = 1
435*99e0aae7SDavid Rees  if message_type == MessageType.BAR:
436*99e0aae7SDavid Rees    1 [+25]  Bar  bar
437*99e0aae7SDavid Rees```
438*99e0aae7SDavid Rees
439*99e0aae7SDavid ReesWhen you have a view of a `Foo`, you can call `foo_view.has_bar().Known()` to
440*99e0aae7SDavid Reesfind out whether `foo_view` has enough information to determine if the field
441*99e0aae7SDavid Rees`bar` should exist.  If it does `.Known()` returns `true`, you may call
442*99e0aae7SDavid Rees`foo_view.has_bar().Value()` to find out if `bar` should exist.  You can also
443*99e0aae7SDavid Reescall `foo_view.has_bar().ValueOr(false)`, which will return `true` if `bar`'s
444*99e0aae7SDavid Reesstatus is known, and `bar` exists.
445*99e0aae7SDavid Rees
446*99e0aae7SDavid ReesEvery field will have a corresponding `has_` method.  In the example above,
447*99e0aae7SDavid Rees`foo_view.has_message_type().Known()` and `foo_view.has_message_type().Value()`
448*99e0aae7SDavid Reesare both supported calls; both will always return `true`.
449*99e0aae7SDavid Rees
450*99e0aae7SDavid ReesNote that just because a field "exists," that does not mean that it can be read
451*99e0aae7SDavid Reesfrom or written to the current message: the field's bytes might be missing, or
452*99e0aae7SDavid Reespresent but contain a non-`Ok()` value.  You can use `view.field().Ok()` to
453*99e0aae7SDavid Reesdetermine if the field can be *read*, and `view.field().IsComplete()` to
454*99e0aae7SDavid Reesdetermine if the field can be *written*.
455*99e0aae7SDavid Rees
456*99e0aae7SDavid Rees
457*99e0aae7SDavid Rees### Constant Virtual Fields
458*99e0aae7SDavid Rees
459*99e0aae7SDavid ReesVirtual fields whose values are compile-time constants can be read without
460*99e0aae7SDavid Reesinstantiating a view:
461*99e0aae7SDavid Rees
462*99e0aae7SDavid Rees```
463*99e0aae7SDavid Reesstruct Foo:
464*99e0aae7SDavid Rees  let register_number = 0xf8
465*99e0aae7SDavid Rees  0 [+4]  UInt  foo
466*99e0aae7SDavid Rees```
467*99e0aae7SDavid Rees
468*99e0aae7SDavid Rees```
469*99e0aae7SDavid Rees// Foo::register_number() is a constexpr function.
470*99e0aae7SDavid Reesstatic_assert(Foo::register_number() == 0xf8);
471*99e0aae7SDavid Rees```
472*99e0aae7SDavid Rees
473*99e0aae7SDavid Rees
474*99e0aae7SDavid Rees### <code>*field*().Ok()</code> vs <code>*field*().IsComplete()</code> vs <code>has_*field*()</code>
475*99e0aae7SDavid Rees
476*99e0aae7SDavid ReesEmboss provides a number of methods to query different kinds of validity.
477*99e0aae7SDavid Rees
478*99e0aae7SDavid Rees<code>has_*field*()</code> is used for checking the existence condition
479*99e0aae7SDavid Reesspecified in the `.emb` file:
480*99e0aae7SDavid Rees
481*99e0aae7SDavid Rees```
482*99e0aae7SDavid Reesstruct Foo:
483*99e0aae7SDavid Rees  0 [+1]    UInt  x
484*99e0aae7SDavid Rees  if x < 10:
485*99e0aae7SDavid Rees    1 [+1]  UInt  y
486*99e0aae7SDavid Rees```
487*99e0aae7SDavid Rees
488*99e0aae7SDavid ReesIn the .cc file:
489*99e0aae7SDavid Rees
490*99e0aae7SDavid Rees```c++
491*99e0aae7SDavid Rees::std::array<char, 2> bytes = { 5, 7 };
492*99e0aae7SDavid Reesauto foo = MakeFooView(&bytes);
493*99e0aae7SDavid Reesassert(foo.x().Read() == 5);
494*99e0aae7SDavid Rees
495*99e0aae7SDavid Rees// foo.x() is readable, so the existence condition on y is known.
496*99e0aae7SDavid Reesassert(foo.has_y().Known());
497*99e0aae7SDavid Rees
498*99e0aae7SDavid Rees// foo.x().Read() < 10, so y exists in foo.
499*99e0aae7SDavid Reesassert(foo.has_y().Value());
500*99e0aae7SDavid Rees
501*99e0aae7SDavid Reesfoo.x().Write(15);
502*99e0aae7SDavid Rees
503*99e0aae7SDavid Rees// foo.x().Read() >= 10, so y no longer exists in foo.
504*99e0aae7SDavid Reesassert(foo.has_y().Known());
505*99e0aae7SDavid Reesassert(!foo.has_y().Value());
506*99e0aae7SDavid Rees
507*99e0aae7SDavid Rees// foo.has_x() is always true, since x's existence condition is just "true".
508*99e0aae7SDavid Reesassert(foo.has_x().Known());
509*99e0aae7SDavid Reesassert(foo.has_x().Value());
510*99e0aae7SDavid Rees
511*99e0aae7SDavid Rees// incomplete_foo has 0 bytes of backing storage, so x is unreadable.
512*99e0aae7SDavid Reesauto incomplete_foo = MakeFooView(&bytes[0], 0);
513*99e0aae7SDavid Rees
514*99e0aae7SDavid Rees// incomplete_foo.has_x() is known, since it does not depend on anything.
515*99e0aae7SDavid Reesassert(incomplete_foo.has_x().Known());
516*99e0aae7SDavid Reesassert(incomplete_foo.has_x().Value());
517*99e0aae7SDavid Rees
518*99e0aae7SDavid Rees// incomplete_foo.x().Ok() is false, since x cannot be read.
519*99e0aae7SDavid Reesassert(!incomplete_foo.x().Ok());
520*99e0aae7SDavid Rees
521*99e0aae7SDavid Rees// Since x cannot be read, incomplete_foo.has_y().Known() is false.
522*99e0aae7SDavid Reesassert(!incomplete_foo.has_y().Known());
523*99e0aae7SDavid Rees
524*99e0aae7SDavid Rees// Since has_y() is not Known(), calling has_y().Value() will crash if Emboss
525*99e0aae7SDavid Rees// assertions are enabled.
526*99e0aae7SDavid Rees// incomplete_foo.has_y().Value()  // Would crash
527*99e0aae7SDavid Rees
528*99e0aae7SDavid Rees// It is safe to call has_y().ValueOr(false).
529*99e0aae7SDavid Reesassert(!incomplete_foo.has_y().ValueOr(false));
530*99e0aae7SDavid Rees```
531*99e0aae7SDavid Rees
532*99e0aae7SDavid Rees<code>has_*field*()</code> is notional: it queries whether *`field`* *should* be
533*99e0aae7SDavid Reespresent in the view.  Even if <code>has_*field*().Value()</code> is `true`,
534*99e0aae7SDavid Rees<code>*field*().IsComplete()</code> and *field*().Ok() might return `false`.
535*99e0aae7SDavid Rees
536*99e0aae7SDavid Rees<code>*field*().IsComplete()</code> tests if there are enough bytes in the
537*99e0aae7SDavid Reesbacking storage to hold *`field`*.  If <code>*field*().IsComplete()</code>, it
538*99e0aae7SDavid Reesis safe to call `Write()` on the field with a valid value for that field.
539*99e0aae7SDavid Rees<code>*field*().Ok()</code> tests if there are enough bytes in the backing
540*99e0aae7SDavid Reesstorage to hold *`field`*, *and* that those bytes contain a valid value for
541*99e0aae7SDavid Rees*`field`*:
542*99e0aae7SDavid Rees
543*99e0aae7SDavid Rees```
544*99e0aae7SDavid Reesstruct Bar:
545*99e0aae7SDavid Rees  0 [+1]  Bcd  x
546*99e0aae7SDavid Rees  1 [+1]  Bcd  y
547*99e0aae7SDavid Rees```
548*99e0aae7SDavid Rees
549*99e0aae7SDavid Rees```c++
550*99e0aae7SDavid Rees::std::array<char, 1> bytes = { 0xbb };  // Not a valid BCD number.
551*99e0aae7SDavid Reesauto bar = MakeBarView(&bytes);
552*99e0aae7SDavid Rees
553*99e0aae7SDavid Rees// There are enough bytes to read and write x.
554*99e0aae7SDavid Reesassert(bar.x().IsComplete());
555*99e0aae7SDavid Rees
556*99e0aae7SDavid Rees// The value in x is not correct.
557*99e0aae7SDavid Reesassert(!bar.x().Ok());
558*99e0aae7SDavid Rees
559*99e0aae7SDavid Rees// Read() would crash if assertions are enabled.
560*99e0aae7SDavid Rees// bar.x().Read();
561*99e0aae7SDavid Rees
562*99e0aae7SDavid Rees// Writing a valid value is safe.
563*99e0aae7SDavid Reesbar.x().Write(99);
564*99e0aae7SDavid Reesassert(bar.x().Ok());
565*99e0aae7SDavid Rees
566*99e0aae7SDavid Rees// Notionally, bar should have y, even though y's byte is not available:
567*99e0aae7SDavid Reesassert(bar.has_y().Value());
568*99e0aae7SDavid Rees
569*99e0aae7SDavid Rees// Since there is no byte to read y from, y is not complete:
570*99e0aae7SDavid Reesassert(!bar.y().IsComplete());
571*99e0aae7SDavid Rees```
572*99e0aae7SDavid Rees
573*99e0aae7SDavid ReesNote that all views have `Ok()` and `IsComplete()` methods.  A view of a
574*99e0aae7SDavid Reesstructure is `Ok()` if all of its fields are either `Ok()` or not present, and
575*99e0aae7SDavid Rees<code>has_*field*().Known()</code> is `true` for all fields.
576*99e0aae7SDavid Rees
577*99e0aae7SDavid ReesA structure view `IsComplete()` if its `SizeIsKnown()` and its backing storage
578*99e0aae7SDavid Reescontains at least `SizeInBits()` or `SizeInBytes()` bits or bytes.  In other
579*99e0aae7SDavid Reeswords: `IsComplete()` is true if Emboss can determine that (just) adding more
580*99e0aae7SDavid Reesbytes to the view's backing storage won't help.  Note that just because
581*99e0aae7SDavid Rees`IsComplete()` is false, that does not mean that adding more bytes *will* help.
582*99e0aae7SDavid ReesIt is possible to define incoherent structures that will confuse Emboss, such
583*99e0aae7SDavid Reesas:
584*99e0aae7SDavid Rees
585*99e0aae7SDavid Rees```
586*99e0aae7SDavid Reesstruct SizeNeverKnown:
587*99e0aae7SDavid Rees  if false:
588*99e0aae7SDavid Rees    0   [+1]  UInt  x_loc
589*99e0aae7SDavid Rees  x_loc [+1]  UInt  x
590*99e0aae7SDavid Rees```
591*99e0aae7SDavid Rees
592*99e0aae7SDavid Rees<!-- TODO(bolms): Rename "existence condition" to "presence condition." -->
593*99e0aae7SDavid Rees
594*99e0aae7SDavid Rees
595*99e0aae7SDavid Rees## `bits` Views
596*99e0aae7SDavid Rees
597*99e0aae7SDavid ReesThe code generated for a `bits` construct is very similar to the code generated
598*99e0aae7SDavid Reesfor a `struct`.  The primary differences are that there is no
599*99e0aae7SDavid Rees<code>Make*Bits*View</code> function and that `SizeInBytes` is replaced by
600*99e0aae7SDavid Rees`SizeInBits`.
601*99e0aae7SDavid Rees
602*99e0aae7SDavid Rees
603*99e0aae7SDavid Rees### `Ok` method
604*99e0aae7SDavid Rees
605*99e0aae7SDavid Rees```c++
606*99e0aae7SDavid Reesbool Ok() const;
607*99e0aae7SDavid Rees```
608*99e0aae7SDavid Rees
609*99e0aae7SDavid ReesThe `Ok` method returns `true` if and only if there are enough bytes in the
610*99e0aae7SDavid Reesbacking store, and the `Ok` methods of all active fields return `true`.
611*99e0aae7SDavid Rees
612*99e0aae7SDavid Rees
613*99e0aae7SDavid Rees### `IsComplete` method
614*99e0aae7SDavid Rees
615*99e0aae7SDavid Rees```c++
616*99e0aae7SDavid Reesbool IsComplete() const;
617*99e0aae7SDavid Rees```
618*99e0aae7SDavid Rees
619*99e0aae7SDavid ReesThe `IsComplete` method returns `true` if there are enough bytes in the backing
620*99e0aae7SDavid Reesstore to fully contain the `bits`.  If `IsComplete()` returns `true` but
621*99e0aae7SDavid Rees`Ok()` returns `false`, then the structure is broken in some way that cannot be
622*99e0aae7SDavid Reesfixed by adding more bytes.
623*99e0aae7SDavid Rees
624*99e0aae7SDavid Rees
625*99e0aae7SDavid Rees### `IntrinsicSizeInBits` method
626*99e0aae7SDavid Rees
627*99e0aae7SDavid Rees```c++
628*99e0aae7SDavid Reesauto IntrinsicSizeInBits() const;
629*99e0aae7SDavid Rees```
630*99e0aae7SDavid Rees
631*99e0aae7SDavid Reesor
632*99e0aae7SDavid Rees
633*99e0aae7SDavid Rees```c++
634*99e0aae7SDavid Reesstatic constexpr auto IntrinsicSizeInBits() const;
635*99e0aae7SDavid Rees```
636*99e0aae7SDavid Rees
637*99e0aae7SDavid ReesThe `IntrinsicSizeInBits` method is the [field method](#bits-field-methods) for
638*99e0aae7SDavid Rees[`$size_in_bits`](language-reference.md#size-in-bits).  The `Read` method of
639*99e0aae7SDavid Reesthe result returns the size of the `struct`, and the `Ok` method returns `true`
640*99e0aae7SDavid Reesif the `struct`'s intrinsic size is known; i.e.:
641*99e0aae7SDavid Rees
642*99e0aae7SDavid Rees```c++
643*99e0aae7SDavid Reesif (view.IntrinsicSizeInBits().Ok()) {
644*99e0aae7SDavid Rees  std::uint64_t view_size = view.IntrinsicSizeInBits().Read();
645*99e0aae7SDavid Rees}
646*99e0aae7SDavid Rees```
647*99e0aae7SDavid Rees
648*99e0aae7SDavid ReesSince the intrinsic size of a `bits` is always a compile-time constant:
649*99e0aae7SDavid Rees
650*99e0aae7SDavid Rees```c++
651*99e0aae7SDavid Reesconstexpr std::uint64_t view_size = BitsView::IntrinsicSizeInBits().Read();
652*99e0aae7SDavid Reesconstexpr std::uint64_t view_size2 = Bits::IntrinsicSizeInBits();
653*99e0aae7SDavid Rees```
654*99e0aae7SDavid Rees
655*99e0aae7SDavid Rees
656*99e0aae7SDavid Rees### `MaxSizeInBits` method
657*99e0aae7SDavid Rees
658*99e0aae7SDavid Rees```c++
659*99e0aae7SDavid Reesauto MaxSizeInBits() const;
660*99e0aae7SDavid Rees```
661*99e0aae7SDavid Rees
662*99e0aae7SDavid Reesor
663*99e0aae7SDavid Rees
664*99e0aae7SDavid Rees```c++
665*99e0aae7SDavid Reesstatic constexpr auto MaxSizeInBits() const;
666*99e0aae7SDavid Rees```
667*99e0aae7SDavid Rees
668*99e0aae7SDavid ReesThe `MaxSizeInBits` method is the [field method](#struct-field-methods)
669*99e0aae7SDavid Reesfor [`$max_size_in_bits`](language-reference.md#max-size-in-bits).  The `Read`
670*99e0aae7SDavid Reesmethod of the result returns the maximum size of the `bits`, and the `Ok`
671*99e0aae7SDavid Reesalways method returns `true`.
672*99e0aae7SDavid Rees
673*99e0aae7SDavid Rees```c++
674*99e0aae7SDavid Reesassert(view.MaxSizeInBits().Ok());
675*99e0aae7SDavid Rees// The exact return type of view.MaxSizeInBits().Read() may vary, but it will
676*99e0aae7SDavid Rees// always be implicitly convertible to std::uint64_t.
677*99e0aae7SDavid Reesstd::uint64_t view_size = view.MaxSizeInBits().Read();
678*99e0aae7SDavid Rees```
679*99e0aae7SDavid Rees
680*99e0aae7SDavid ReesAlternately:
681*99e0aae7SDavid Rees
682*99e0aae7SDavid Rees```c++
683*99e0aae7SDavid Reesstd::uint64_t view_size = view.MaxSizeInBits().UncheckedRead();
684*99e0aae7SDavid Rees```
685*99e0aae7SDavid Rees
686*99e0aae7SDavid ReesOr:
687*99e0aae7SDavid Rees
688*99e0aae7SDavid Rees```c++
689*99e0aae7SDavid Reesconstexpr std::uint64_t view_size = StructView::MaxSizeInBits().Read();
690*99e0aae7SDavid Reesconstexpr std::uint64_t view_size2 = Struct::MaxSizeInBits();
691*99e0aae7SDavid Rees```
692*99e0aae7SDavid Rees
693*99e0aae7SDavid Rees
694*99e0aae7SDavid Rees### `MinSizeInBits` method
695*99e0aae7SDavid Rees
696*99e0aae7SDavid Rees```c++
697*99e0aae7SDavid Reesauto MinSizeInBits() const;
698*99e0aae7SDavid Rees```
699*99e0aae7SDavid Rees
700*99e0aae7SDavid Reesor
701*99e0aae7SDavid Rees
702*99e0aae7SDavid Rees```c++
703*99e0aae7SDavid Reesstatic constexpr auto MinSizeInBits() const;
704*99e0aae7SDavid Rees```
705*99e0aae7SDavid Rees
706*99e0aae7SDavid ReesThe `MinSizeInBits` method is the [field method](#struct-field-methods)
707*99e0aae7SDavid Reesfor [`$min_size_in_bits`](language-reference.md#min-size-in-bits).  The `Read`
708*99e0aae7SDavid Reesmethod of the result returns the minimum size of the `bits`, and the `Ok`
709*99e0aae7SDavid Reesalways method returns `true`.
710*99e0aae7SDavid Rees
711*99e0aae7SDavid Rees```c++
712*99e0aae7SDavid Reesassert(view.MinSizeInBits().Ok());
713*99e0aae7SDavid Rees// The exact return type of view.MinSizeInBits().Read() may vary, but it will
714*99e0aae7SDavid Rees// always be implicitly convertible to std::uint64_t.
715*99e0aae7SDavid Reesstd::uint64_t view_size = view.MinSizeInBits().Read();
716*99e0aae7SDavid Rees```
717*99e0aae7SDavid Rees
718*99e0aae7SDavid ReesAlternately:
719*99e0aae7SDavid Rees
720*99e0aae7SDavid Rees```c++
721*99e0aae7SDavid Reesstd::uint64_t view_size = view.MinSizeInBits().UncheckedRead();
722*99e0aae7SDavid Rees```
723*99e0aae7SDavid Rees
724*99e0aae7SDavid ReesOr:
725*99e0aae7SDavid Rees
726*99e0aae7SDavid Rees```c++
727*99e0aae7SDavid Reesconstexpr std::uint64_t view_size = StructView::MinSizeInBits().Read();
728*99e0aae7SDavid Reesconstexpr std::uint64_t view_size2 = Struct::MinSizeInBits();
729*99e0aae7SDavid Rees```
730*99e0aae7SDavid Rees
731*99e0aae7SDavid Rees
732*99e0aae7SDavid Rees### `SizeIsKnown` method
733*99e0aae7SDavid Rees
734*99e0aae7SDavid Rees```c++
735*99e0aae7SDavid Reesstatic constexpr bool SizeIsKnown() const;
736*99e0aae7SDavid Rees```
737*99e0aae7SDavid Rees
738*99e0aae7SDavid ReesFor a `bits` construct, `SizeIsKnown()` always returns `true`, because the size
739*99e0aae7SDavid Reesof a `bits` construct is always statically known at compilation time.
740*99e0aae7SDavid Rees
741*99e0aae7SDavid Rees
742*99e0aae7SDavid Rees### `SizeInBits` method
743*99e0aae7SDavid Rees
744*99e0aae7SDavid Rees```c++
745*99e0aae7SDavid Reesstatic constexpr std::size_t SizeInBits() const;
746*99e0aae7SDavid Rees```
747*99e0aae7SDavid Rees
748*99e0aae7SDavid ReesThe `SizeInBits` method returns the size of the `bits` in bits.  It is
749*99e0aae7SDavid Reesequivalent to `static_cast<std::size_t>(IntrinsicSizeInBits().Read())`.
750*99e0aae7SDavid Rees
751*99e0aae7SDavid Rees
752*99e0aae7SDavid Rees### `UpdateFromTextStream` method
753*99e0aae7SDavid Rees
754*99e0aae7SDavid Rees```c++
755*99e0aae7SDavid Reestemplate <class Stream>
756*99e0aae7SDavid Reesbool UpdateFromTextStream(Stream *stream) const;
757*99e0aae7SDavid Rees```
758*99e0aae7SDavid Rees
759*99e0aae7SDavid Rees`UpdateFromTextStream` will read a text-format representation of the structure
760*99e0aae7SDavid Reesfrom the given `stream` and update fields.  Generally, applications would not
761*99e0aae7SDavid Reescall this directly; instead, use the global `UpdateFromText` method, which
762*99e0aae7SDavid Reeshandles setting up a stream from a `std::string`.
763*99e0aae7SDavid Rees
764*99e0aae7SDavid Rees### `WriteToTextStream` method
765*99e0aae7SDavid Rees
766*99e0aae7SDavid Rees```c++
767*99e0aae7SDavid Reestemplate <class Stream>
768*99e0aae7SDavid Reesbool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
769*99e0aae7SDavid Rees```
770*99e0aae7SDavid Rees
771*99e0aae7SDavid Rees`WriteToTextStream` will write a text representation of the current value in a
772*99e0aae7SDavid Reesform that can be decoded by `UpdateFromTextStream`. Generally, applications
773*99e0aae7SDavid Reeswould not call this directly; instead, use the global `WriteToString` method,
774*99e0aae7SDavid Reeswhich handles setting up the stream and returning the resulting string.
775*99e0aae7SDavid Rees
776*99e0aae7SDavid Rees### Field methods {#bits-field-methods}
777*99e0aae7SDavid Rees
778*99e0aae7SDavid ReesAs with `struct`, each field in a `bits` will have a corresponding method of the
779*99e0aae7SDavid Reessame name generated, and each such method will return a view of the given field.
780*99e0aae7SDavid ReesTake the module:
781*99e0aae7SDavid Rees
782*99e0aae7SDavid Rees```
783*99e0aae7SDavid Reesbits Bar:
784*99e0aae7SDavid Rees  0 [+12]  UInt  baz
785*99e0aae7SDavid Rees  31 [+1]  Flag  qux
786*99e0aae7SDavid Rees  let two_baz = baz * 2
787*99e0aae7SDavid Rees
788*99e0aae7SDavid Reesstruct Foo:
789*99e0aae7SDavid Rees  0 [+4]  Bar  bar
790*99e0aae7SDavid Rees```
791*99e0aae7SDavid Rees
792*99e0aae7SDavid ReesIn this case, the generated code in the `Bar` view will have methods
793*99e0aae7SDavid Rees
794*99e0aae7SDavid Rees```c++
795*99e0aae7SDavid Reesauto baz() const;
796*99e0aae7SDavid Reesauto qux() const;
797*99e0aae7SDavid Reesauto two_baz() const;
798*99e0aae7SDavid Rees```
799*99e0aae7SDavid Rees
800*99e0aae7SDavid ReesThe `baz` method will return a `UInt` view, and `qux()` will return a `Flag`
801*99e0aae7SDavid Reesview:
802*99e0aae7SDavid Rees
803*99e0aae7SDavid Rees```c++
804*99e0aae7SDavid Reesauto foo_view = MakeFooView(&vector_of_foo_bytes);
805*99e0aae7SDavid Reesuint16_t baz_value = foo_view.bar().baz().Read();
806*99e0aae7SDavid Reesbool qux_value = foo_view.bar().qux().Read();
807*99e0aae7SDavid Reesuint32_t two_baz_value = foo_view.bar().two_baz().Read();
808*99e0aae7SDavid Rees```
809*99e0aae7SDavid Rees
810*99e0aae7SDavid ReesThe exact return type of field methods is subject to change; if a field's view
811*99e0aae7SDavid Reesmust be stored, use an `auto` variable.
812*99e0aae7SDavid Rees
813*99e0aae7SDavid Rees
814*99e0aae7SDavid Rees## `enum`s
815*99e0aae7SDavid Rees
816*99e0aae7SDavid ReesFor each `enum` in an `.emb`, the Emboss compiler will generate a corresponding
817*99e0aae7SDavid ReesC++11-style `enum class`.  Take the following Emboss `enum`:
818*99e0aae7SDavid Rees
819*99e0aae7SDavid Rees```
820*99e0aae7SDavid Reesenum Foo:
821*99e0aae7SDavid Rees  BAR = 1
822*99e0aae7SDavid Rees  BAZ = 1000
823*99e0aae7SDavid Rees```
824*99e0aae7SDavid Rees
825*99e0aae7SDavid ReesEmboss will generate something equivalent to the following C++:
826*99e0aae7SDavid Rees
827*99e0aae7SDavid Rees```c++
828*99e0aae7SDavid Reesenum class Foo : uint64_t {
829*99e0aae7SDavid Rees  BAR = 1,
830*99e0aae7SDavid Rees  BAZ = 1000,
831*99e0aae7SDavid Rees};
832*99e0aae7SDavid Rees```
833*99e0aae7SDavid Rees
834*99e0aae7SDavid ReesAdditionally, like other Emboss entities, `enum`s have corresponding view
835*99e0aae7SDavid Reesclasses.
836*99e0aae7SDavid Rees
837*99e0aae7SDavid Rees
838*99e0aae7SDavid Rees### `TryToGetEnumFromName` free function
839*99e0aae7SDavid Rees
840*99e0aae7SDavid Rees```c++
841*99e0aae7SDavid Reesstatic inline bool TryToGetEnumFromName(const char *name, EnumType *result);
842*99e0aae7SDavid Rees```
843*99e0aae7SDavid Rees
844*99e0aae7SDavid ReesThe `TryToGetEnumFromName` function will try to match `name` against the names
845*99e0aae7SDavid Reesin the Emboss `enum` definition.  If it finds an exact match, it will return
846*99e0aae7SDavid Rees`true` and update `result` with the corresponding enum value.  If it does not
847*99e0aae7SDavid Reesfind a match, it will return `false` and leave `result` unchanged.
848*99e0aae7SDavid Rees
849*99e0aae7SDavid ReesNote that `TryToGetNameFromEnum` will not match the text of the numeric value of
850*99e0aae7SDavid Reesan enum; given the `Foo` enum above, `TryToGetEnumFromName("1000", &my_foo)`
851*99e0aae7SDavid Reeswould return `false`.
852*99e0aae7SDavid Rees
853*99e0aae7SDavid Rees
854*99e0aae7SDavid Rees### `TryToGetNameFromEnum` free function
855*99e0aae7SDavid Rees
856*99e0aae7SDavid Rees```c++
857*99e0aae7SDavid Reesstatic inline const char *TryToGetNameFromEnum(EnumType value);
858*99e0aae7SDavid Rees```
859*99e0aae7SDavid Rees
860*99e0aae7SDavid Rees`TryToGetNameFromEnum` will attempt to find the textual name for the
861*99e0aae7SDavid Reescorresponding enum value.  If a name is found, it will be returned; otherwise
862*99e0aae7SDavid Rees`TryToGetEnumFromName` will return `nullptr`.  (Note that C++ enums are allowed
863*99e0aae7SDavid Reesto contain numeric values that are not explicitly listed in the enum definition,
864*99e0aae7SDavid Reesas long as they are in range for the underlying integral type.)  If the given
865*99e0aae7SDavid Reesvalue has more than one name, the first name that appears in the Emboss
866*99e0aae7SDavid Reesdefinition will be returned.
867*99e0aae7SDavid Rees
868*99e0aae7SDavid Rees
869*99e0aae7SDavid Rees### `Read` method
870*99e0aae7SDavid Rees
871*99e0aae7SDavid Rees```c++
872*99e0aae7SDavid ReesEnumType Read() const;
873*99e0aae7SDavid Rees```
874*99e0aae7SDavid Rees
875*99e0aae7SDavid ReesThe `Read` method reads the enum from the underlying bytes and returns its
876*99e0aae7SDavid Reesvalue as a C++ enum.  `Read` will assert that there are enough bytes to read.
877*99e0aae7SDavid ReesIf the application cannot tolerate a failed assertion, it should first call
878*99e0aae7SDavid Rees`Ok()` to ensure that it can safely read the enum.  If performance is critical
879*99e0aae7SDavid Reesand the application can assure that there will always be enough bytes to read
880*99e0aae7SDavid Reesthe enum, it can call `UncheckedRead` instead.
881*99e0aae7SDavid Rees
882*99e0aae7SDavid Rees
883*99e0aae7SDavid Rees### `UncheckedRead` method
884*99e0aae7SDavid Rees
885*99e0aae7SDavid Rees```c++
886*99e0aae7SDavid ReesEnumType UncheckedRead() const;
887*99e0aae7SDavid Rees```
888*99e0aae7SDavid Rees
889*99e0aae7SDavid ReesLike `Read`, `UncheckedRead` reads the enum from the underlying bytes and
890*99e0aae7SDavid Reesreturns it value as a C++ enum.  Unlike `Read`, `UncheckedRead` does not attempt
891*99e0aae7SDavid Reesto validate that there are enough bytes in the backing store to actually perform
892*99e0aae7SDavid Reesthe read.  In performance-critical situations, if the application is otherwise
893*99e0aae7SDavid Reesable to ensure that there are sufficient bytes in the backing store to read the
894*99e0aae7SDavid Reesenum, `UncheckedRead` may be used.
895*99e0aae7SDavid Rees
896*99e0aae7SDavid Rees
897*99e0aae7SDavid Rees### `Write` method
898*99e0aae7SDavid Rees
899*99e0aae7SDavid Rees```c++
900*99e0aae7SDavid Reesvoid Write(EnumType value) const;
901*99e0aae7SDavid Rees```
902*99e0aae7SDavid Rees
903*99e0aae7SDavid Rees`Write` writes the `value` into the backing store.  Like `Read`, `Write` asserts
904*99e0aae7SDavid Reesthat there are enough bytes in the backing store to safely write the enum.  If
905*99e0aae7SDavid Reesthe application cannot tolerate an assertion failure, it can use `TryToWrite` or
906*99e0aae7SDavid Reesthe combination of `IsComplete` and `CouldWriteValue`.
907*99e0aae7SDavid Rees
908*99e0aae7SDavid Rees
909*99e0aae7SDavid Rees### `TryToWrite` method
910*99e0aae7SDavid Rees
911*99e0aae7SDavid Rees```c++
912*99e0aae7SDavid Reesbool TryToWrite(EnumType value) const;
913*99e0aae7SDavid Rees```
914*99e0aae7SDavid Rees
915*99e0aae7SDavid Rees`TryToWrite` attempts to write the `value` into the backing store.  If the
916*99e0aae7SDavid Reesbacking store does not have enough bytes to hold the enum field, or `value` is
917*99e0aae7SDavid Reestoo large for the specific enum field, then `TryToWrite` will return `false` and
918*99e0aae7SDavid Reesnot update anything.
919*99e0aae7SDavid Rees
920*99e0aae7SDavid Rees
921*99e0aae7SDavid Rees### `CouldWriteValue` method
922*99e0aae7SDavid Rees
923*99e0aae7SDavid Rees```c++
924*99e0aae7SDavid Reesstatic constexpr bool CouldWriteValue(EnumType value);
925*99e0aae7SDavid Rees```
926*99e0aae7SDavid Rees
927*99e0aae7SDavid Rees`CouldWriteValue` returns `true` if the given `value` could be written into the
928*99e0aae7SDavid Reesenum field, assuming that there were enough bytes in the backing store to cover
929*99e0aae7SDavid Reesthe field.
930*99e0aae7SDavid Rees
931*99e0aae7SDavid ReesAlthough `CouldWriteValue` is `static constexpr`, it is tricky to call
932*99e0aae7SDavid Reesstatically; client code that wishes to call it statically must use `decltype`
933*99e0aae7SDavid Reesand `declval` to get the specific type for the specific enum *field* in
934*99e0aae7SDavid Reesquestion.
935*99e0aae7SDavid Rees
936*99e0aae7SDavid Rees
937*99e0aae7SDavid Rees### `UncheckedWrite` method
938*99e0aae7SDavid Rees
939*99e0aae7SDavid Rees```c++
940*99e0aae7SDavid Reesvoid UncheckedWrite(EnumType value) const;
941*99e0aae7SDavid Rees```
942*99e0aae7SDavid Rees
943*99e0aae7SDavid ReesLike `Write`, `UncheckedWrite` writes the given value to the backing store.
944*99e0aae7SDavid ReesUnlike `Write`, `UncheckedWrite` does not check that there are actually enough
945*99e0aae7SDavid Reesbytes in the backing store to safely write; it should only be used if the
946*99e0aae7SDavid Reesapplication has ensured that there are sufficient bytes in the backing store in
947*99e0aae7SDavid Reessome other way, and performance is a concern.
948*99e0aae7SDavid Rees
949*99e0aae7SDavid Rees
950*99e0aae7SDavid Rees### `Ok` method
951*99e0aae7SDavid Rees
952*99e0aae7SDavid Rees```c++
953*99e0aae7SDavid Reesbool Ok() const;
954*99e0aae7SDavid Rees```
955*99e0aae7SDavid Rees
956*99e0aae7SDavid Rees`Ok` returns `true` if there are enough bytes in the backing store for the enum
957*99e0aae7SDavid Reesfield to be read or written.
958*99e0aae7SDavid Rees
959*99e0aae7SDavid ReesIn the future, Emboss may add a "known values only" annotation to enum fields,
960*99e0aae7SDavid Reesin which case `Ok` would also check that the given field contains a known value.
961*99e0aae7SDavid Rees
962*99e0aae7SDavid Rees
963*99e0aae7SDavid Rees### `IsComplete` method
964*99e0aae7SDavid Rees
965*99e0aae7SDavid Rees```c++
966*99e0aae7SDavid Reesbool IsComplete() const;
967*99e0aae7SDavid Rees```
968*99e0aae7SDavid Rees
969*99e0aae7SDavid Rees`IsComplete` returns `true` if there are enough bytes in the backing store for
970*99e0aae7SDavid Reesthe enum field to be read or written.
971*99e0aae7SDavid Rees
972*99e0aae7SDavid Rees
973*99e0aae7SDavid Rees### `UpdateFromTextStream` method
974*99e0aae7SDavid Rees
975*99e0aae7SDavid Rees```c++
976*99e0aae7SDavid Reestemplate <class Stream>
977*99e0aae7SDavid Reesbool UpdateFromTextStream(Stream *stream) const;
978*99e0aae7SDavid Rees```
979*99e0aae7SDavid Rees
980*99e0aae7SDavid Rees`UpdateFromTextStream` will read a text-format representation of the enum from
981*99e0aae7SDavid Reesthe given `stream` and write it into the backing store.  Generally, applications
982*99e0aae7SDavid Reeswould not call this directly; instead, use the global `UpdateFromText` method,
983*99e0aae7SDavid Reeswhich handles setting up a stream from a `std::string`.
984*99e0aae7SDavid Rees
985*99e0aae7SDavid Rees### `WriteToTextStream` method
986*99e0aae7SDavid Rees
987*99e0aae7SDavid Rees```c++
988*99e0aae7SDavid Reestemplate <class Stream>
989*99e0aae7SDavid Reesbool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
990*99e0aae7SDavid Rees```
991*99e0aae7SDavid Rees
992*99e0aae7SDavid Rees`WriteToTextStream` will write a text representation of the current value in a
993*99e0aae7SDavid Reesform that can be decoded by `UpdateFromTextStream`. Generally, applications
994*99e0aae7SDavid Reeswould not call this directly; instead, use the global `WriteToString` method,
995*99e0aae7SDavid Reeswhich handles setting up the stream and returning the resulting string.
996*99e0aae7SDavid Rees
997*99e0aae7SDavid Rees## Arrays
998*99e0aae7SDavid Rees
999*99e0aae7SDavid Rees### `operator[]` method
1000*99e0aae7SDavid Rees
1001*99e0aae7SDavid Rees```c++
1002*99e0aae7SDavid ReesElementView operator[](size_t index) const;
1003*99e0aae7SDavid Rees```
1004*99e0aae7SDavid Rees
1005*99e0aae7SDavid ReesThe `operator[]` method of an array view returns a view of the array element at
1006*99e0aae7SDavid Rees`index`.
1007*99e0aae7SDavid Rees
1008*99e0aae7SDavid Rees### `begin()`/`rbegin()` and `end()`/`rend()` methods
1009*99e0aae7SDavid Rees
1010*99e0aae7SDavid Rees```c++
1011*99e0aae7SDavid ReesElementViewIterator<> begin();
1012*99e0aae7SDavid ReesElementViewIterator<> end();
1013*99e0aae7SDavid ReesElementViewIterator<> rbegin();
1014*99e0aae7SDavid ReesElementViewIterator<> rend();
1015*99e0aae7SDavid Rees```
1016*99e0aae7SDavid Rees
1017*99e0aae7SDavid ReesThe `begin()` and `end()` methods of an array view returns view iterators to the
1018*99e0aae7SDavid Reesbeginning and past-the-end of the array, respectively. They may be used with
1019*99e0aae7SDavid Reesarrays in range-based for loops, for example:
1020*99e0aae7SDavid Rees
1021*99e0aae7SDavid Rees```c++
1022*99e0aae7SDavid Rees  auto view = MakeArrayView(...);
1023*99e0aae7SDavid Rees  for(auto element : view){
1024*99e0aae7SDavid Rees    int a = view.member().Read();
1025*99e0aae7SDavid Rees    ...
1026*99e0aae7SDavid Rees  }
1027*99e0aae7SDavid Rees```
1028*99e0aae7SDavid Rees
1029*99e0aae7SDavid ReesThe `rbegin()` and `rend()` methods of an array view returns reverse view
1030*99e0aae7SDavid Reesiterators to the end and element preceding the first, respectively.
1031*99e0aae7SDavid Rees
1032*99e0aae7SDavid Rees### `SizeInBytes` or `SizeInBits` method
1033*99e0aae7SDavid Rees
1034*99e0aae7SDavid Rees```c++
1035*99e0aae7SDavid Reessize_t SizeInBytes() const;
1036*99e0aae7SDavid Rees```
1037*99e0aae7SDavid Rees
1038*99e0aae7SDavid Reesor
1039*99e0aae7SDavid Rees
1040*99e0aae7SDavid Rees```c++
1041*99e0aae7SDavid Reessize_t SizeInBits() const;
1042*99e0aae7SDavid Rees```
1043*99e0aae7SDavid Rees
1044*99e0aae7SDavid ReesArrays in `struct`s have the `SizeInBytes` method; arrays in `bits` have the
1045*99e0aae7SDavid Rees`SizeInBits` method.  `SizeInBytes` returns the size of the array in bytes;
1046*99e0aae7SDavid Rees`SizeInBits` returns the size of the array in bits.
1047*99e0aae7SDavid Rees
1048*99e0aae7SDavid Rees
1049*99e0aae7SDavid Rees### `ElementCount` method
1050*99e0aae7SDavid Rees
1051*99e0aae7SDavid Rees```c++
1052*99e0aae7SDavid Reessize_t ElementCount() const;
1053*99e0aae7SDavid Rees```
1054*99e0aae7SDavid Rees
1055*99e0aae7SDavid Rees`ElementCount` returns the number of elements in the array.
1056*99e0aae7SDavid Rees
1057*99e0aae7SDavid Rees
1058*99e0aae7SDavid Rees### `Ok` method
1059*99e0aae7SDavid Rees
1060*99e0aae7SDavid Rees```c++
1061*99e0aae7SDavid Reesbool Ok() const;
1062*99e0aae7SDavid Rees```
1063*99e0aae7SDavid Rees
1064*99e0aae7SDavid Rees`Ok` returns `true` if there are enough bytes in the backing store to hold the
1065*99e0aae7SDavid Reesentire array, and every element's `Ok` method returns `true`.
1066*99e0aae7SDavid Rees
1067*99e0aae7SDavid Rees
1068*99e0aae7SDavid Rees### `IsComplete` method
1069*99e0aae7SDavid Rees
1070*99e0aae7SDavid Rees```c++
1071*99e0aae7SDavid Reesbool IsComplete() const;
1072*99e0aae7SDavid Rees```
1073*99e0aae7SDavid Rees
1074*99e0aae7SDavid Rees`IsComplete` returns `true` if there are sufficient bytes in the backing store
1075*99e0aae7SDavid Reesto hold the entire array.
1076*99e0aae7SDavid Rees
1077*99e0aae7SDavid Rees
1078*99e0aae7SDavid Rees### `ToString` method
1079*99e0aae7SDavid Rees
1080*99e0aae7SDavid Rees```c++
1081*99e0aae7SDavid Reestemplate <class String>
1082*99e0aae7SDavid ReesString ToString() const;
1083*99e0aae7SDavid Rees```
1084*99e0aae7SDavid Rees
1085*99e0aae7SDavid ReesIntended usage:
1086*99e0aae7SDavid Rees
1087*99e0aae7SDavid Rees```c++
1088*99e0aae7SDavid Rees// Makes a copy of view's backing storage.
1089*99e0aae7SDavid Reesauto str = view.ToString<std::string>();
1090*99e0aae7SDavid Rees
1091*99e0aae7SDavid Rees// Points to view's backing storage.
1092*99e0aae7SDavid Reesauto str_view = view.ToString<std::string_view>();
1093*99e0aae7SDavid Rees```
1094*99e0aae7SDavid Rees
1095*99e0aae7SDavid Rees`ToString()` returns a string type constructed from the backing storage of the
1096*99e0aae7SDavid Reesarray.  Note that `ToString()` is only enabled for arrays of 1-byte values,
1097*99e0aae7SDavid Reessuch as `UInt:8[]`, and only when the array view's underlying storage is
1098*99e0aae7SDavid Reescontiguous.
1099*99e0aae7SDavid Rees
1100*99e0aae7SDavid ReesAlthough it is intended for use with `std::string` and `std::string_view`,
1101*99e0aae7SDavid Rees`ToString()` can work with any C++ type that:
1102*99e0aae7SDavid Rees
1103*99e0aae7SDavid Rees1.  Has a `data()` method that returns a pointer to the string's underlying
1104*99e0aae7SDavid Rees    data as a `char` type.
1105*99e0aae7SDavid Rees2.  Has a constructor that accepts a `const declval(data())` pointer and a
1106*99e0aae7SDavid Rees    `size_t` length.
1107*99e0aae7SDavid Rees
1108*99e0aae7SDavid Rees
1109*99e0aae7SDavid Rees### `UpdateFromTextStream` method
1110*99e0aae7SDavid Rees
1111*99e0aae7SDavid Rees```c++
1112*99e0aae7SDavid Reestemplate <class Stream>
1113*99e0aae7SDavid Reesbool UpdateFromTextStream(Stream *stream) const;
1114*99e0aae7SDavid Rees```
1115*99e0aae7SDavid Rees
1116*99e0aae7SDavid Rees`UpdateFromTextStream` will read a text-format representation of the structure
1117*99e0aae7SDavid Reesfrom the given `stream` and update array elements.  Generally, applications
1118*99e0aae7SDavid Reeswould not call this directly; instead, use the global `UpdateFromText` method,
1119*99e0aae7SDavid Reeswhich handles setting up a stream from a `std::string`.
1120*99e0aae7SDavid Rees
1121*99e0aae7SDavid Rees### `WriteToTextStream` method
1122*99e0aae7SDavid Rees
1123*99e0aae7SDavid Rees```c++
1124*99e0aae7SDavid Reestemplate <class Stream>
1125*99e0aae7SDavid Reesbool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
1126*99e0aae7SDavid Rees```
1127*99e0aae7SDavid Rees
1128*99e0aae7SDavid Rees`WriteToTextStream` will write a text representation of the current value in a
1129*99e0aae7SDavid Reesform that can be decoded by `UpdateFromTextStream`. Generally, applications
1130*99e0aae7SDavid Reeswould not call this directly; instead, use the global `WriteToString` method,
1131*99e0aae7SDavid Reeswhich handles setting up the stream and returning the resulting string.
1132*99e0aae7SDavid Rees
1133*99e0aae7SDavid Rees### `BackingStorage` method
1134*99e0aae7SDavid Rees
1135*99e0aae7SDavid Rees```c++
1136*99e0aae7SDavid ReesStorage BackingStorage() const;
1137*99e0aae7SDavid Rees```
1138*99e0aae7SDavid Rees
1139*99e0aae7SDavid ReesReturns the backing storage for the view.  The return type of `BackingStorage()`
1140*99e0aae7SDavid Reesis a template parameter on the view.
1141*99e0aae7SDavid Rees
1142*99e0aae7SDavid Rees## `UInt`
1143*99e0aae7SDavid Rees
1144*99e0aae7SDavid Rees### Type `ValueType`
1145*99e0aae7SDavid Rees
1146*99e0aae7SDavid Rees```c++
1147*99e0aae7SDavid Reesusing ValueType = ...;
1148*99e0aae7SDavid Rees```
1149*99e0aae7SDavid Rees
1150*99e0aae7SDavid ReesThe `ValueType` type alias maps to the least-width C++ unsigned integer type
1151*99e0aae7SDavid Reesthat contains enough bits to hold any value of the given `UInt`.  For example:
1152*99e0aae7SDavid Rees
1153*99e0aae7SDavid Rees*   a `UInt:32`'s `ValueType` would be `uint32_t`
1154*99e0aae7SDavid Rees*   a `UInt:64`'s `ValueType` would be `uint64_t`
1155*99e0aae7SDavid Rees*   a `UInt:12`'s `ValueType` would be `uint16_t`
1156*99e0aae7SDavid Rees*   a `UInt:2`'s `ValueType` would be `uint8_t`
1157*99e0aae7SDavid Rees
1158*99e0aae7SDavid ReesThe `Read` and `Write` families of methods use `ValueType` to return or accept
1159*99e0aae7SDavid Reesvalues, respectively.
1160*99e0aae7SDavid Rees
1161*99e0aae7SDavid Rees
1162*99e0aae7SDavid Rees### `Read` method
1163*99e0aae7SDavid Rees
1164*99e0aae7SDavid Rees```c++
1165*99e0aae7SDavid ReesValueType Read() const;
1166*99e0aae7SDavid Rees```
1167*99e0aae7SDavid Rees
1168*99e0aae7SDavid ReesThe `Read` method reads the `UInt` from the underlying bytes and returns its
1169*99e0aae7SDavid Reesvalue as a C++ unsigned integer type.  `Read` will assert that there are enough
1170*99e0aae7SDavid Reesbytes to read.  If the application cannot tolerate a failed assertion, it should
1171*99e0aae7SDavid Reesfirst call `Ok()` to ensure that it can safely read the `UInt`.  If performance
1172*99e0aae7SDavid Reesis critical and the application can assure that there will always be enough
1173*99e0aae7SDavid Reesbytes to read the `UInt`, it can call `UncheckedRead` instead.
1174*99e0aae7SDavid Rees
1175*99e0aae7SDavid Rees
1176*99e0aae7SDavid Rees### `UncheckedRead` method
1177*99e0aae7SDavid Rees
1178*99e0aae7SDavid Rees```c++
1179*99e0aae7SDavid ReesValueType UncheckedRead();
1180*99e0aae7SDavid Rees```
1181*99e0aae7SDavid Rees
1182*99e0aae7SDavid ReesLike `Read`, `UncheckedRead` reads the `UInt` from the underlying bytes and
1183*99e0aae7SDavid Reesreturns it value as a C++ unsigned integer type.  Unlike `Read`, `UncheckedRead`
1184*99e0aae7SDavid Reesdoes not attempt to validate that there are enough bytes in the backing store to
1185*99e0aae7SDavid Reesactually perform the read.  In performance-critical situations, if the
1186*99e0aae7SDavid Reesapplication is otherwise able to ensure that there are sufficient bytes in the
1187*99e0aae7SDavid Reesbacking store to read the `UInt`, `UncheckedRead` may be used.
1188*99e0aae7SDavid Rees
1189*99e0aae7SDavid Rees
1190*99e0aae7SDavid Rees### `Write` method
1191*99e0aae7SDavid Rees
1192*99e0aae7SDavid Rees```c++
1193*99e0aae7SDavid Reesvoid Write(ValueType value);
1194*99e0aae7SDavid Rees```
1195*99e0aae7SDavid Rees
1196*99e0aae7SDavid Rees`Write` writes the `value` into the backing store.  Like `Read`, `Write` asserts
1197*99e0aae7SDavid Reesthat there are enough bytes in the backing store to safely write the `UInt`.  If
1198*99e0aae7SDavid Reesthe application cannot tolerate an assertion failure, it can use `TryToWrite` or
1199*99e0aae7SDavid Reesthe combination of `IsComplete` and `CouldWriteValue`.
1200*99e0aae7SDavid Rees
1201*99e0aae7SDavid Rees
1202*99e0aae7SDavid Rees### `TryToWrite` method
1203*99e0aae7SDavid Rees
1204*99e0aae7SDavid Rees```c++
1205*99e0aae7SDavid Reesbool TryToWrite(ValueType value);
1206*99e0aae7SDavid Rees```
1207*99e0aae7SDavid Rees
1208*99e0aae7SDavid Rees`TryToWrite` attempts to write the `value` into the backing store.  If the
1209*99e0aae7SDavid Reesbacking store does not have enough bytes to hold the `UInt` field, or `value` is
1210*99e0aae7SDavid Reestoo large for the `UInt` field, then `TryToWrite` will return `false` and not
1211*99e0aae7SDavid Reesupdate anything.
1212*99e0aae7SDavid Rees
1213*99e0aae7SDavid Rees
1214*99e0aae7SDavid Rees### `CouldWriteValue` method
1215*99e0aae7SDavid Rees
1216*99e0aae7SDavid Rees```c++
1217*99e0aae7SDavid Reesstatic constexpr bool CouldWriteValue(ValueType value);
1218*99e0aae7SDavid Rees```
1219*99e0aae7SDavid Rees
1220*99e0aae7SDavid Rees`CouldWriteValue` returns `true` if the given `value` could be written into the
1221*99e0aae7SDavid Rees`UInt` field, assuming that there were enough bytes in the backing store to
1222*99e0aae7SDavid Reescover the field.
1223*99e0aae7SDavid Rees
1224*99e0aae7SDavid ReesAlthough `CouldWriteValue` is `static constexpr`, it is tricky to call
1225*99e0aae7SDavid Reesstatically; client code that wishes to call it statically must use `decltype`
1226*99e0aae7SDavid Reesand `declval` to get the specific type for the specific `UInt` field in
1227*99e0aae7SDavid Reesquestion.
1228*99e0aae7SDavid Rees
1229*99e0aae7SDavid Rees
1230*99e0aae7SDavid Rees### `UncheckedWrite` method
1231*99e0aae7SDavid Rees
1232*99e0aae7SDavid Rees```c++
1233*99e0aae7SDavid Reesvoid UncheckedWrite(ValueType value);
1234*99e0aae7SDavid Rees```
1235*99e0aae7SDavid Rees
1236*99e0aae7SDavid ReesLike `Write`, `UncheckedWrite` writes the given value to the backing store.
1237*99e0aae7SDavid ReesUnlike `Write`, `UncheckedWrite` does not check that there are actually enough
1238*99e0aae7SDavid Reesbytes in the backing store to safely write; it should only be used if the
1239*99e0aae7SDavid Reesapplication has ensured that there are sufficient bytes in the backing store in
1240*99e0aae7SDavid Reessome other way, and performance is a concern.
1241*99e0aae7SDavid Rees
1242*99e0aae7SDavid Rees
1243*99e0aae7SDavid Rees### `Ok` method
1244*99e0aae7SDavid Rees
1245*99e0aae7SDavid Rees```c++
1246*99e0aae7SDavid Reesbool Ok() const;
1247*99e0aae7SDavid Rees```
1248*99e0aae7SDavid Rees
1249*99e0aae7SDavid ReesThe `Ok` method returns `true` if there are enough bytes in the backing store to
1250*99e0aae7SDavid Reeshold the given `UInt` field.
1251*99e0aae7SDavid Rees
1252*99e0aae7SDavid Rees
1253*99e0aae7SDavid Rees### `IsComplete` method
1254*99e0aae7SDavid Rees
1255*99e0aae7SDavid Rees```c++
1256*99e0aae7SDavid Reesbool IsComplete();
1257*99e0aae7SDavid Rees```
1258*99e0aae7SDavid Rees
1259*99e0aae7SDavid ReesThe `IsComplete` method returns `true` if there are enough bytes in the backing
1260*99e0aae7SDavid Reesstore to hold the given `UInt` field.
1261*99e0aae7SDavid Rees
1262*99e0aae7SDavid Rees
1263*99e0aae7SDavid Rees### `UpdateFromTextStream` method
1264*99e0aae7SDavid Rees
1265*99e0aae7SDavid Rees```c++
1266*99e0aae7SDavid Reestemplate <class Stream>
1267*99e0aae7SDavid Reesbool UpdateFromTextStream(Stream *stream) const;
1268*99e0aae7SDavid Rees```
1269*99e0aae7SDavid Rees
1270*99e0aae7SDavid Rees`UpdateFromTextStream` will read a text-format representation of the `UInt` from
1271*99e0aae7SDavid Reesthe given `stream` and update fields.  Generally, applications would not call
1272*99e0aae7SDavid Reesthis directly; instead, use the global `UpdateFromText` method, which handles
1273*99e0aae7SDavid Reessetting up a stream from a `std::string`.
1274*99e0aae7SDavid Rees
1275*99e0aae7SDavid Rees### `WriteToTextStream` method
1276*99e0aae7SDavid Rees
1277*99e0aae7SDavid Rees```c++
1278*99e0aae7SDavid Reestemplate <class Stream>
1279*99e0aae7SDavid Reesbool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
1280*99e0aae7SDavid Rees```
1281*99e0aae7SDavid Rees
1282*99e0aae7SDavid Rees`WriteToTextStream` will write a text representation of the current value in a
1283*99e0aae7SDavid Reesform that can be decoded by `UpdateFromTextStream`. Generally, applications
1284*99e0aae7SDavid Reeswould not call this directly; instead, use the global `WriteToString` method,
1285*99e0aae7SDavid Reeswhich handles setting up the stream and returning the resulting string.
1286*99e0aae7SDavid Rees
1287*99e0aae7SDavid Rees### `SizeInBits` method
1288*99e0aae7SDavid Rees
1289*99e0aae7SDavid Rees```c++
1290*99e0aae7SDavid Reesstatic constexpr int SizeInBits();
1291*99e0aae7SDavid Rees```
1292*99e0aae7SDavid Rees
1293*99e0aae7SDavid ReesThe `SizeInBits` method returns the size of this specific `UInt` field, in bits.
1294*99e0aae7SDavid Rees
1295*99e0aae7SDavid Rees
1296*99e0aae7SDavid Rees## `Int`
1297*99e0aae7SDavid Rees
1298*99e0aae7SDavid Rees### Type `ValueType`
1299*99e0aae7SDavid Rees
1300*99e0aae7SDavid Rees```c++
1301*99e0aae7SDavid Reesusing ValueType = ...;
1302*99e0aae7SDavid Rees```
1303*99e0aae7SDavid Rees
1304*99e0aae7SDavid ReesThe `ValueType` type alias maps to the least-width C++ signed integer type
1305*99e0aae7SDavid Reesthat contains enough bits to hold any value of the given `Int`.  For example:
1306*99e0aae7SDavid Rees
1307*99e0aae7SDavid Rees*   a `Int:32`'s `ValueType` would be `int32_t`
1308*99e0aae7SDavid Rees*   a `Int:64`'s `ValueType` would be `int64_t`
1309*99e0aae7SDavid Rees*   a `Int:12`'s `ValueType` would be `int16_t`
1310*99e0aae7SDavid Rees*   a `Int:2`'s `ValueType` would be `int8_t`
1311*99e0aae7SDavid Rees
1312*99e0aae7SDavid ReesThe `Read` and `Write` families of methods use `ValueType` to return or accept
1313*99e0aae7SDavid Reesvalues, respectively.
1314*99e0aae7SDavid Rees
1315*99e0aae7SDavid Rees
1316*99e0aae7SDavid Rees### `Read` method
1317*99e0aae7SDavid Rees
1318*99e0aae7SDavid Rees```c++
1319*99e0aae7SDavid ReesValueType Read() const;
1320*99e0aae7SDavid Rees```
1321*99e0aae7SDavid Rees
1322*99e0aae7SDavid ReesThe `Read` method reads the `Int` from the underlying bytes and returns its
1323*99e0aae7SDavid Reesvalue as a C++ signed integer type.  `Read` will assert that there are enough
1324*99e0aae7SDavid Reesbytes to read.  If the application cannot tolerate a failed assertion, it should
1325*99e0aae7SDavid Reesfirst call `Ok()` to ensure that it can safely read the `Int`.  If performance
1326*99e0aae7SDavid Reesis critical and the application can assure that there will always be enough
1327*99e0aae7SDavid Reesbytes to read the `Int`, it can call `UncheckedRead` instead.
1328*99e0aae7SDavid Rees
1329*99e0aae7SDavid Rees
1330*99e0aae7SDavid Rees### `UncheckedRead` method
1331*99e0aae7SDavid Rees
1332*99e0aae7SDavid Rees```c++
1333*99e0aae7SDavid ReesValueType UncheckedRead();
1334*99e0aae7SDavid Rees```
1335*99e0aae7SDavid Rees
1336*99e0aae7SDavid ReesLike `Read`, `UncheckedRead` reads the `Int` from the underlying bytes and
1337*99e0aae7SDavid Reesreturns it value as a C++ signed integer type.  Unlike `Read`, `UncheckedRead`
1338*99e0aae7SDavid Reesdoes not attempt to validate that there are enough bytes in the backing store to
1339*99e0aae7SDavid Reesactually perform the read.  In performance-critical situations, if the
1340*99e0aae7SDavid Reesapplication is otherwise able to ensure that there are sufficient bytes in the
1341*99e0aae7SDavid Reesbacking store to read the `Int`, `UncheckedRead` may be used.
1342*99e0aae7SDavid Rees
1343*99e0aae7SDavid Rees
1344*99e0aae7SDavid Rees### `Write` method
1345*99e0aae7SDavid Rees
1346*99e0aae7SDavid Rees```c++
1347*99e0aae7SDavid Reesvoid Write(ValueType value);
1348*99e0aae7SDavid Rees```
1349*99e0aae7SDavid Rees
1350*99e0aae7SDavid Rees`Write` writes the `value` into the backing store.  Like `Read`, `Write` asserts
1351*99e0aae7SDavid Reesthat there are enough bytes in the backing store to safely write the `Int`.  If
1352*99e0aae7SDavid Reesthe application cannot tolerate an assertion failure, it can use `TryToWrite` or
1353*99e0aae7SDavid Reesthe combination of `IsComplete` and `CouldWriteValue`.
1354*99e0aae7SDavid Rees
1355*99e0aae7SDavid Rees
1356*99e0aae7SDavid Rees### `TryToWrite` method
1357*99e0aae7SDavid Rees
1358*99e0aae7SDavid Rees```c++
1359*99e0aae7SDavid Reesbool TryToWrite(ValueType value);
1360*99e0aae7SDavid Rees```
1361*99e0aae7SDavid Rees
1362*99e0aae7SDavid Rees`TryToWrite` attempts to write the `value` into the backing store.  If the
1363*99e0aae7SDavid Reesbacking store does not have enough bytes to hold the `Int` field, or `value` is
1364*99e0aae7SDavid Reestoo large for the `Int` field, then `TryToWrite` will return `false` and not
1365*99e0aae7SDavid Reesupdate anything.
1366*99e0aae7SDavid Rees
1367*99e0aae7SDavid Rees
1368*99e0aae7SDavid Rees### `CouldWriteValue` method
1369*99e0aae7SDavid Rees
1370*99e0aae7SDavid Rees```c++
1371*99e0aae7SDavid Reesstatic constexpr bool CouldWriteValue(ValueType value);
1372*99e0aae7SDavid Rees```
1373*99e0aae7SDavid Rees
1374*99e0aae7SDavid Rees`CouldWriteValue` returns `true` if the given `value` could be written into the
1375*99e0aae7SDavid Rees`Int` field, assuming that there were enough bytes in the backing store to cover
1376*99e0aae7SDavid Reesthe field.
1377*99e0aae7SDavid Rees
1378*99e0aae7SDavid ReesAlthough `CouldWriteValue` is `static constexpr`, it is tricky to call
1379*99e0aae7SDavid Reesstatically; client code that wishes to call it statically must use `decltype`
1380*99e0aae7SDavid Reesand `declval` to get the specific type for the specific `Int` field in question.
1381*99e0aae7SDavid Rees
1382*99e0aae7SDavid Rees
1383*99e0aae7SDavid Rees### `UncheckedWrite` method
1384*99e0aae7SDavid Rees
1385*99e0aae7SDavid Rees```c++
1386*99e0aae7SDavid Reesvoid UncheckedWrite(ValueType value);
1387*99e0aae7SDavid Rees```
1388*99e0aae7SDavid Rees
1389*99e0aae7SDavid ReesLike `Write`, `UncheckedWrite` writes the given value to the backing store.
1390*99e0aae7SDavid ReesUnlike `Write`, `UncheckedWrite` does not check that there are actually enough
1391*99e0aae7SDavid Reesbytes in the backing store to safely write; it should only be used if the
1392*99e0aae7SDavid Reesapplication has ensured that there are sufficient bytes in the backing store in
1393*99e0aae7SDavid Reessome other way, and performance is a concern.
1394*99e0aae7SDavid Rees
1395*99e0aae7SDavid Rees
1396*99e0aae7SDavid Rees### `Ok` method
1397*99e0aae7SDavid Rees
1398*99e0aae7SDavid Rees```c++
1399*99e0aae7SDavid Reesbool Ok() const;
1400*99e0aae7SDavid Rees```
1401*99e0aae7SDavid Rees
1402*99e0aae7SDavid ReesThe `Ok` method returns `true` if there are enough bytes in the backing store to
1403*99e0aae7SDavid Reeshold the given `Int` field.
1404*99e0aae7SDavid Rees
1405*99e0aae7SDavid Rees
1406*99e0aae7SDavid Rees### `IsComplete` method
1407*99e0aae7SDavid Rees
1408*99e0aae7SDavid Rees```c++
1409*99e0aae7SDavid Reesbool IsComplete();
1410*99e0aae7SDavid Rees```
1411*99e0aae7SDavid Rees
1412*99e0aae7SDavid ReesThe `IsComplete` method returns `true` if there are enough bytes in the backing
1413*99e0aae7SDavid Reesstore to hold the given `Int` field.
1414*99e0aae7SDavid Rees
1415*99e0aae7SDavid Rees
1416*99e0aae7SDavid Rees### `UpdateFromTextStream` method
1417*99e0aae7SDavid Rees
1418*99e0aae7SDavid Rees```c++
1419*99e0aae7SDavid Reestemplate <class Stream>
1420*99e0aae7SDavid Reesbool UpdateFromTextStream(Stream *stream) const;
1421*99e0aae7SDavid Rees```
1422*99e0aae7SDavid Rees
1423*99e0aae7SDavid Rees`UpdateFromTextStream` will read a text-format representation of the `Int` from
1424*99e0aae7SDavid Reesthe given `stream` and update fields.  Generally, applications would not call
1425*99e0aae7SDavid Reesthis directly; instead, use the global `UpdateFromText` method, which handles
1426*99e0aae7SDavid Reessetting up a stream from a `std::string`.
1427*99e0aae7SDavid Rees
1428*99e0aae7SDavid Rees### `WriteToTextStream` method
1429*99e0aae7SDavid Rees
1430*99e0aae7SDavid Rees```c++
1431*99e0aae7SDavid Reestemplate <class Stream>
1432*99e0aae7SDavid Reesbool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
1433*99e0aae7SDavid Rees```
1434*99e0aae7SDavid Rees
1435*99e0aae7SDavid Rees`WriteToTextStream` will write a text representation of the current value in a
1436*99e0aae7SDavid Reesform that can be decoded by `UpdateFromTextStream`. Generally, applications
1437*99e0aae7SDavid Reeswould not call this directly; instead, use the global `WriteToString` method,
1438*99e0aae7SDavid Reeswhich handles setting up the stream and returning the resulting string.
1439*99e0aae7SDavid Rees
1440*99e0aae7SDavid Rees### `SizeInBits` method
1441*99e0aae7SDavid Rees
1442*99e0aae7SDavid Rees```c++
1443*99e0aae7SDavid Reesstatic constexpr int SizeInBits();
1444*99e0aae7SDavid Rees```
1445*99e0aae7SDavid Rees
1446*99e0aae7SDavid ReesThe `SizeInBits` method returns the size of this specific `Int` field, in bits.
1447*99e0aae7SDavid Rees
1448*99e0aae7SDavid Rees
1449*99e0aae7SDavid Rees## `Bcd`
1450*99e0aae7SDavid Rees
1451*99e0aae7SDavid Rees### Type `ValueType`
1452*99e0aae7SDavid Rees
1453*99e0aae7SDavid Rees```c++
1454*99e0aae7SDavid Reesusing ValueType = ...;
1455*99e0aae7SDavid Rees```
1456*99e0aae7SDavid Rees
1457*99e0aae7SDavid ReesThe `ValueType` type alias maps to a C++ unsigned integer type that contains
1458*99e0aae7SDavid Reesat least enough bits to hold any value of the given `Bcd`.  For example:
1459*99e0aae7SDavid Rees
1460*99e0aae7SDavid Rees*   a `Bcd:32`'s `ValueType` would be `uint32_t`
1461*99e0aae7SDavid Rees*   a `Bcd:64`'s `ValueType` would be `uint64_t`
1462*99e0aae7SDavid Rees*   a `Bcd:12`'s `ValueType` would be `uint16_t`
1463*99e0aae7SDavid Rees*   a `Bcd:2`'s `ValueType` would be `uint8_t`
1464*99e0aae7SDavid Rees
1465*99e0aae7SDavid ReesThe `Read` and `Write` families of methods use `ValueType` to return or accept
1466*99e0aae7SDavid Reesvalues, respectively.
1467*99e0aae7SDavid Rees
1468*99e0aae7SDavid Rees
1469*99e0aae7SDavid Rees### `Read` method
1470*99e0aae7SDavid Rees
1471*99e0aae7SDavid Rees```c++
1472*99e0aae7SDavid ReesValueType Read() const;
1473*99e0aae7SDavid Rees```
1474*99e0aae7SDavid Rees
1475*99e0aae7SDavid ReesThe `Read` method reads the `Bcd` from the underlying bytes and returns its
1476*99e0aae7SDavid Reesvalue as a C++ unsigned integer type.  `Read` will assert that there are enough
1477*99e0aae7SDavid Reesbytes to read, and that the binary representation is a valid BCD integer.  If
1478*99e0aae7SDavid Reesthe application cannot tolerate a failed assertion, it should first call `Ok()`
1479*99e0aae7SDavid Reesto ensure that it can safely read the `Bcd`.  If performance is critical and the
1480*99e0aae7SDavid Reesapplication can assure that there will always be enough bytes to read the `Bcd`,
1481*99e0aae7SDavid Reesand that the bytes will be a valid BCD value, it can call `UncheckedRead`
1482*99e0aae7SDavid Reesinstead.
1483*99e0aae7SDavid Rees
1484*99e0aae7SDavid Rees
1485*99e0aae7SDavid Rees### `UncheckedRead` method
1486*99e0aae7SDavid Rees
1487*99e0aae7SDavid Rees```c++
1488*99e0aae7SDavid ReesValueType UncheckedRead();
1489*99e0aae7SDavid Rees```
1490*99e0aae7SDavid Rees
1491*99e0aae7SDavid ReesLike `Read`, `UncheckedRead` reads the `Bcd` from the underlying bytes and
1492*99e0aae7SDavid Reesreturns it value as a C++ unsigned integer type.  Unlike `Read`, `UncheckedRead`
1493*99e0aae7SDavid Reesdoes not attempt to validate that there are enough bytes in the backing store to
1494*99e0aae7SDavid Reesactually perform the read, nor that the bytes contain an actual BCD number.  In
1495*99e0aae7SDavid Reesperformance-critical situations, if the application is otherwise able to ensure
1496*99e0aae7SDavid Reesthat there are sufficient bytes in the backing store to read the `Bcd`,
1497*99e0aae7SDavid Rees`UncheckedRead` may be used.
1498*99e0aae7SDavid Rees
1499*99e0aae7SDavid Rees
1500*99e0aae7SDavid Rees### `Write` method
1501*99e0aae7SDavid Rees
1502*99e0aae7SDavid Rees```c++
1503*99e0aae7SDavid Reesvoid Write(ValueType value);
1504*99e0aae7SDavid Rees```
1505*99e0aae7SDavid Rees
1506*99e0aae7SDavid Rees`Write` writes the `value` into the backing store.  Like `Read`, `Write` asserts
1507*99e0aae7SDavid Reesthat there are enough bytes in the backing store to safely write the `Bcd`.  If
1508*99e0aae7SDavid Reesthe application cannot tolerate an assertion failure, it can use `TryToWrite` or
1509*99e0aae7SDavid Reesthe combination of `IsComplete` and `CouldWriteValue`.
1510*99e0aae7SDavid Rees
1511*99e0aae7SDavid Rees
1512*99e0aae7SDavid Rees### `TryToWrite` method
1513*99e0aae7SDavid Rees
1514*99e0aae7SDavid Rees```c++
1515*99e0aae7SDavid Reesbool TryToWrite(ValueType value);
1516*99e0aae7SDavid Rees```
1517*99e0aae7SDavid Rees
1518*99e0aae7SDavid Rees`TryToWrite` attempts to write the `value` into the backing store.  If the
1519*99e0aae7SDavid Reesbacking store does not have enough bytes to hold the `Bcd` field, or `value` is
1520*99e0aae7SDavid Reestoo large for the `Bcd` field, then `TryToWrite` will return `false` and not
1521*99e0aae7SDavid Reesupdate anything.
1522*99e0aae7SDavid Rees
1523*99e0aae7SDavid Rees
1524*99e0aae7SDavid Rees### `CouldWriteValue` method
1525*99e0aae7SDavid Rees
1526*99e0aae7SDavid Rees```c++
1527*99e0aae7SDavid Reesstatic constexpr bool CouldWriteValue(ValueType value);
1528*99e0aae7SDavid Rees```
1529*99e0aae7SDavid Rees
1530*99e0aae7SDavid Rees`CouldWriteValue` returns `true` if the given `value` could be written into the
1531*99e0aae7SDavid Rees`Bcd` field, assuming that there were enough bytes in the backing store to cover
1532*99e0aae7SDavid Reesthe field.
1533*99e0aae7SDavid Rees
1534*99e0aae7SDavid ReesAlthough `CouldWriteValue` is `static constexpr`, it is tricky to call
1535*99e0aae7SDavid Reesstatically; client code that wishes to call it statically must use `decltype`
1536*99e0aae7SDavid Reesand `declval` to get the specific type for the specific `Bcd` field in question.
1537*99e0aae7SDavid Rees
1538*99e0aae7SDavid Rees
1539*99e0aae7SDavid Rees### `UncheckedWrite` method
1540*99e0aae7SDavid Rees
1541*99e0aae7SDavid Rees```c++
1542*99e0aae7SDavid Reesvoid UncheckedWrite(ValueType value);
1543*99e0aae7SDavid Rees```
1544*99e0aae7SDavid Rees
1545*99e0aae7SDavid ReesLike `Write`, `UncheckedWrite` writes the given value to the backing store.
1546*99e0aae7SDavid ReesUnlike `Write`, `UncheckedWrite` does not check that there are actually enough
1547*99e0aae7SDavid Reesbytes in the backing store to safely write; it should only be used if the
1548*99e0aae7SDavid Reesapplication has ensured that there are sufficient bytes in the backing store in
1549*99e0aae7SDavid Reessome other way, and performance is a concern.
1550*99e0aae7SDavid Rees
1551*99e0aae7SDavid Rees
1552*99e0aae7SDavid Rees### `Ok` method
1553*99e0aae7SDavid Rees
1554*99e0aae7SDavid Rees```c++
1555*99e0aae7SDavid Reesbool Ok() const;
1556*99e0aae7SDavid Rees```
1557*99e0aae7SDavid Rees
1558*99e0aae7SDavid ReesThe `Ok` method returns `true` if there are enough bytes in the backing store to
1559*99e0aae7SDavid Reeshold the given `Bcd` field, and the bytes contain a valid BCD number: that is,
1560*99e0aae7SDavid Reesthat every nibble in the backing store contains a value between 0 and 9,
1561*99e0aae7SDavid Reesinclusive.
1562*99e0aae7SDavid Rees
1563*99e0aae7SDavid Rees
1564*99e0aae7SDavid Rees### `IsComplete` method
1565*99e0aae7SDavid Rees
1566*99e0aae7SDavid Rees```c++
1567*99e0aae7SDavid Reesbool IsComplete();
1568*99e0aae7SDavid Rees```
1569*99e0aae7SDavid Rees
1570*99e0aae7SDavid ReesThe `IsComplete` method returns `true` if there are enough bytes in the backing
1571*99e0aae7SDavid Reesstore to hold the given `Bcd` field.
1572*99e0aae7SDavid Rees
1573*99e0aae7SDavid Rees
1574*99e0aae7SDavid Rees### `UpdateFromTextStream` method
1575*99e0aae7SDavid Rees
1576*99e0aae7SDavid Rees```c++
1577*99e0aae7SDavid Reestemplate <class Stream>
1578*99e0aae7SDavid Reesbool UpdateFromTextStream(Stream *stream) const;
1579*99e0aae7SDavid Rees```
1580*99e0aae7SDavid Rees
1581*99e0aae7SDavid Rees`UpdateFromTextStream` will read a text-format representation of the `Bcd` from
1582*99e0aae7SDavid Reesthe given `stream` and update fields.  Generally, applications would not call
1583*99e0aae7SDavid Reesthis directly; instead, use the global `UpdateFromText` method, which handles
1584*99e0aae7SDavid Reessetting up a stream from a `std::string`.
1585*99e0aae7SDavid Rees
1586*99e0aae7SDavid Rees### `WriteToTextStream` method
1587*99e0aae7SDavid Rees
1588*99e0aae7SDavid Rees```c++
1589*99e0aae7SDavid Reestemplate <class Stream>
1590*99e0aae7SDavid Reesbool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
1591*99e0aae7SDavid Rees```
1592*99e0aae7SDavid Rees
1593*99e0aae7SDavid Rees`WriteToTextStream` will write a text representation of the current value in a
1594*99e0aae7SDavid Reesform that can be decoded by `UpdateFromTextStream`. Generally, applications
1595*99e0aae7SDavid Reeswould not call this directly; instead, use the global `WriteToString` method,
1596*99e0aae7SDavid Reeswhich handles setting up the stream and returning the resulting string.
1597*99e0aae7SDavid Rees
1598*99e0aae7SDavid Rees### `SizeInBits` method
1599*99e0aae7SDavid Rees
1600*99e0aae7SDavid Rees```c++
1601*99e0aae7SDavid Reesstatic constexpr int SizeInBits();
1602*99e0aae7SDavid Rees```
1603*99e0aae7SDavid Rees
1604*99e0aae7SDavid ReesThe `SizeInBits` method returns the size of this specific `Bcd` field, in bits.
1605*99e0aae7SDavid Rees
1606*99e0aae7SDavid Rees
1607*99e0aae7SDavid Rees## `Flag`
1608*99e0aae7SDavid Rees
1609*99e0aae7SDavid Rees### `Read` method
1610*99e0aae7SDavid Rees
1611*99e0aae7SDavid Rees```c++
1612*99e0aae7SDavid Reesbool Read() const;
1613*99e0aae7SDavid Rees```
1614*99e0aae7SDavid Rees
1615*99e0aae7SDavid ReesThe `Read` method reads the `Flag` from the underlying bit and returns its
1616*99e0aae7SDavid Reesvalue as a C++ `bool`.  `Read` will assert that the underlying bit is in the
1617*99e0aae7SDavid Reesbacking store.  If the application cannot tolerate a failed assertion, it should
1618*99e0aae7SDavid Reesfirst call `Ok()` to ensure that it can safely read the `Flag`.  If performance
1619*99e0aae7SDavid Reesis critical and the application can assure that there will always be enough
1620*99e0aae7SDavid Reesbytes to read the `Flag`, it can call `UncheckedRead` instead.
1621*99e0aae7SDavid Rees
1622*99e0aae7SDavid Rees
1623*99e0aae7SDavid Rees### `UncheckedRead` method
1624*99e0aae7SDavid Rees
1625*99e0aae7SDavid Rees```c++
1626*99e0aae7SDavid Reesbool UncheckedRead();
1627*99e0aae7SDavid Rees```
1628*99e0aae7SDavid Rees
1629*99e0aae7SDavid ReesLike `Read`, `UncheckedRead` reads the `Flag` from the underlying bit and
1630*99e0aae7SDavid Reesreturns it value as a C++ bool.  Unlike `Read`, `UncheckedRead` does not attempt
1631*99e0aae7SDavid Reesto validate that the backing bit is actually in the backing store.  In
1632*99e0aae7SDavid Reesperformance-critical situations, if the application is otherwise able to ensure
1633*99e0aae7SDavid Reesthat there are sufficient bytes in the backing store to read the `Flag`,
1634*99e0aae7SDavid Rees`UncheckedRead` may be used.
1635*99e0aae7SDavid Rees
1636*99e0aae7SDavid Rees
1637*99e0aae7SDavid Rees### `Write` method
1638*99e0aae7SDavid Rees
1639*99e0aae7SDavid Rees```c++
1640*99e0aae7SDavid Reesvoid Write(bool value);
1641*99e0aae7SDavid Rees```
1642*99e0aae7SDavid Rees
1643*99e0aae7SDavid Rees`Write` writes the `value` into the backing store.  Like `Read`, `Write` asserts
1644*99e0aae7SDavid Reesthat there are enough bytes in the backing store to safely write the `Flag`.  If
1645*99e0aae7SDavid Reesthe application cannot tolerate an assertion failure, it can use `TryToWrite` or
1646*99e0aae7SDavid Reesthe combination of `IsComplete` and `CouldWriteValue`.
1647*99e0aae7SDavid Rees
1648*99e0aae7SDavid Rees
1649*99e0aae7SDavid Rees### `TryToWrite` method
1650*99e0aae7SDavid Rees
1651*99e0aae7SDavid Rees```c++
1652*99e0aae7SDavid Reesbool TryToWrite(bool value);
1653*99e0aae7SDavid Rees```
1654*99e0aae7SDavid Rees
1655*99e0aae7SDavid Rees`TryToWrite` attempts to write the `value` into the backing store.  If the
1656*99e0aae7SDavid Reesbacking store does not contain the `Flag`'s bit, then `TryToWrite` will return
1657*99e0aae7SDavid Rees`false` and not update anything.
1658*99e0aae7SDavid Rees
1659*99e0aae7SDavid Rees
1660*99e0aae7SDavid Rees### `CouldWriteValue` method
1661*99e0aae7SDavid Rees
1662*99e0aae7SDavid Rees```c++
1663*99e0aae7SDavid Reesstatic constexpr bool CouldWriteValue(bool value);
1664*99e0aae7SDavid Rees```
1665*99e0aae7SDavid Rees
1666*99e0aae7SDavid Rees`CouldWriteValue` returns `true`, as both C++ `bool` values can be written to
1667*99e0aae7SDavid Reesany `Flag`.
1668*99e0aae7SDavid Rees
1669*99e0aae7SDavid Rees
1670*99e0aae7SDavid Rees### `UncheckedWrite` method
1671*99e0aae7SDavid Rees
1672*99e0aae7SDavid Rees```c++
1673*99e0aae7SDavid Reesvoid UncheckedWrite(ValueType value);
1674*99e0aae7SDavid Rees```
1675*99e0aae7SDavid Rees
1676*99e0aae7SDavid ReesLike `Write`, `UncheckedWrite` writes the given value to the backing store.
1677*99e0aae7SDavid ReesUnlike `Write`, `UncheckedWrite` does not check that there are actually enough
1678*99e0aae7SDavid Reesbytes in the backing store to safely write; it should only be used if the
1679*99e0aae7SDavid Reesapplication has ensured that there are sufficient bytes in the backing store in
1680*99e0aae7SDavid Reessome other way, and performance is a concern.
1681*99e0aae7SDavid Rees
1682*99e0aae7SDavid Rees
1683*99e0aae7SDavid Rees### `Ok` method
1684*99e0aae7SDavid Rees
1685*99e0aae7SDavid Rees```c++
1686*99e0aae7SDavid Reesbool Ok() const;
1687*99e0aae7SDavid Rees```
1688*99e0aae7SDavid Rees
1689*99e0aae7SDavid ReesThe `Ok` method returns `true` if the backing store contains the `Flag`'s bit.
1690*99e0aae7SDavid Rees
1691*99e0aae7SDavid Rees
1692*99e0aae7SDavid Rees### `IsComplete` method
1693*99e0aae7SDavid Rees
1694*99e0aae7SDavid Rees```c++
1695*99e0aae7SDavid Reesbool IsComplete();
1696*99e0aae7SDavid Rees```
1697*99e0aae7SDavid Rees
1698*99e0aae7SDavid ReesThe `IsComplete` method returns `true` if the backing store contains the
1699*99e0aae7SDavid Rees`Flag`'s bit.
1700*99e0aae7SDavid Rees
1701*99e0aae7SDavid Rees
1702*99e0aae7SDavid Rees### `UpdateFromTextStream` method
1703*99e0aae7SDavid Rees
1704*99e0aae7SDavid Rees```c++
1705*99e0aae7SDavid Reestemplate <class Stream>
1706*99e0aae7SDavid Reesbool UpdateFromTextStream(Stream *stream) const;
1707*99e0aae7SDavid Rees```
1708*99e0aae7SDavid Rees
1709*99e0aae7SDavid Rees`UpdateFromTextStream` will read a text-format representation of the `Flag` from
1710*99e0aae7SDavid Reesthe given `stream` and update fields.  Generally, applications would not call
1711*99e0aae7SDavid Reesthis directly; instead, use the global `UpdateFromText` method, which handles
1712*99e0aae7SDavid Reessetting up a stream from a `std::string`.
1713*99e0aae7SDavid Rees
1714*99e0aae7SDavid Rees### `WriteToTextStream` method
1715*99e0aae7SDavid Rees
1716*99e0aae7SDavid Rees```c++
1717*99e0aae7SDavid Reestemplate <class Stream>
1718*99e0aae7SDavid Reesbool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
1719*99e0aae7SDavid Rees```
1720*99e0aae7SDavid Rees
1721*99e0aae7SDavid Rees`WriteToTextStream` will write a text representation of the current value in a
1722*99e0aae7SDavid Reesform that can be decoded by `UpdateFromTextStream`. Generally, applications
1723*99e0aae7SDavid Reeswould not call this directly; instead, use the global `WriteToString` method,
1724*99e0aae7SDavid Reeswhich handles setting up the stream and returning the resulting string.
1725*99e0aae7SDavid Rees
1726*99e0aae7SDavid Rees## `Float`
1727*99e0aae7SDavid Rees
1728*99e0aae7SDavid Rees### Type `ValueType`
1729*99e0aae7SDavid Rees
1730*99e0aae7SDavid Rees```c++
1731*99e0aae7SDavid Reesusing ValueType = ...;
1732*99e0aae7SDavid Rees```
1733*99e0aae7SDavid Rees
1734*99e0aae7SDavid ReesThe `ValueType` type alias maps to the C++ floating-point type that matches the
1735*99e0aae7SDavid Rees`Float` field's type; generally `float` for 32-bit `Float`s and `double` for
1736*99e0aae7SDavid Rees64-bit `Float`s.
1737*99e0aae7SDavid Rees
1738*99e0aae7SDavid ReesThe `Read` and `Write` families of methods use `ValueType` to return or accept
1739*99e0aae7SDavid Reesvalues, respectively.
1740*99e0aae7SDavid Rees
1741*99e0aae7SDavid Rees
1742*99e0aae7SDavid Rees### `Read` method
1743*99e0aae7SDavid Rees
1744*99e0aae7SDavid Rees```c++
1745*99e0aae7SDavid ReesValueType Read() const;
1746*99e0aae7SDavid Rees```
1747*99e0aae7SDavid Rees
1748*99e0aae7SDavid ReesThe `Read` method reads the `Float` from the underlying bytes and returns its
1749*99e0aae7SDavid Reesvalue as a C++ floating point type.  `Read` will assert that there are enough
1750*99e0aae7SDavid Reesbytes to read.  If the application cannot tolerate a failed assertion, it should
1751*99e0aae7SDavid Reesfirst call `Ok()` to ensure that it can safely read the `Float`.  If performance
1752*99e0aae7SDavid Reesis critical and the application can assure that there will always be enough
1753*99e0aae7SDavid Reesbytes to read the `Float`, it can call `UncheckedRead` instead.
1754*99e0aae7SDavid Rees
1755*99e0aae7SDavid Rees
1756*99e0aae7SDavid Rees### `UncheckedRead` method
1757*99e0aae7SDavid Rees
1758*99e0aae7SDavid Rees```c++
1759*99e0aae7SDavid ReesValueType UncheckedRead();
1760*99e0aae7SDavid Rees```
1761*99e0aae7SDavid Rees
1762*99e0aae7SDavid ReesLike `Read`, `UncheckedRead` reads the `Float` from the underlying bytes and
1763*99e0aae7SDavid Reesreturns it value as a C++ floating point type.  Unlike `Read`, `UncheckedRead`
1764*99e0aae7SDavid Reesdoes not attempt to validate that there are enough bytes in the backing store to
1765*99e0aae7SDavid Reesactually perform the read.  In performance-critical situations, if the
1766*99e0aae7SDavid Reesapplication is otherwise able to ensure that there are sufficient bytes in the
1767*99e0aae7SDavid Reesbacking store to read the `Float`, `UncheckedRead` may be used.
1768*99e0aae7SDavid Rees
1769*99e0aae7SDavid Rees
1770*99e0aae7SDavid Rees### `Write` method
1771*99e0aae7SDavid Rees
1772*99e0aae7SDavid Rees```c++
1773*99e0aae7SDavid Reesvoid Write(ValueType value);
1774*99e0aae7SDavid Rees```
1775*99e0aae7SDavid Rees
1776*99e0aae7SDavid Rees`Write` writes the `value` into the backing store.  Like `Read`, `Write` asserts
1777*99e0aae7SDavid Reesthat there are enough bytes in the backing store to safely write the `Float`.
1778*99e0aae7SDavid ReesIf the application cannot tolerate an assertion failure, it can use `TryToWrite`
1779*99e0aae7SDavid Reesor the combination of `IsComplete` and `CouldWriteValue`.
1780*99e0aae7SDavid Rees
1781*99e0aae7SDavid Rees
1782*99e0aae7SDavid Rees### `TryToWrite` method
1783*99e0aae7SDavid Rees
1784*99e0aae7SDavid Rees```c++
1785*99e0aae7SDavid Reesbool TryToWrite(ValueType value);
1786*99e0aae7SDavid Rees```
1787*99e0aae7SDavid Rees
1788*99e0aae7SDavid Rees`TryToWrite` attempts to write the `value` into the backing store.  If the
1789*99e0aae7SDavid Reesbacking store does not have enough bytes to hold the `Float` field, then
1790*99e0aae7SDavid Rees`TryToWrite` will return `false` and not update anything.
1791*99e0aae7SDavid Rees
1792*99e0aae7SDavid Rees
1793*99e0aae7SDavid Rees### `CouldWriteValue` method
1794*99e0aae7SDavid Rees
1795*99e0aae7SDavid Rees```c++
1796*99e0aae7SDavid Reesstatic constexpr bool CouldWriteValue(ValueType value);
1797*99e0aae7SDavid Rees```
1798*99e0aae7SDavid Rees
1799*99e0aae7SDavid Rees`CouldWriteValue` returns `true`.
1800*99e0aae7SDavid Rees
1801*99e0aae7SDavid Rees
1802*99e0aae7SDavid Rees### `UncheckedWrite` method
1803*99e0aae7SDavid Rees
1804*99e0aae7SDavid Rees```c++
1805*99e0aae7SDavid Reesvoid UncheckedWrite(ValueType value);
1806*99e0aae7SDavid Rees```
1807*99e0aae7SDavid Rees
1808*99e0aae7SDavid ReesLike `Write`, `UncheckedWrite` writes the given value to the backing store.
1809*99e0aae7SDavid ReesUnlike `Write`, `UncheckedWrite` does not check that there are actually enough
1810*99e0aae7SDavid Reesbytes in the backing store to safely write; it should only be used if the
1811*99e0aae7SDavid Reesapplication has ensured that there are sufficient bytes in the backing store in
1812*99e0aae7SDavid Reessome other way, and performance is a concern.
1813*99e0aae7SDavid Rees
1814*99e0aae7SDavid Rees
1815*99e0aae7SDavid Rees### `Ok` method
1816*99e0aae7SDavid Rees
1817*99e0aae7SDavid Rees```c++
1818*99e0aae7SDavid Reesbool Ok() const;
1819*99e0aae7SDavid Rees```
1820*99e0aae7SDavid Rees
1821*99e0aae7SDavid ReesThe `Ok` method returns `true` if there are enough bytes in the backing store to
1822*99e0aae7SDavid Reeshold the given `Float` field.
1823*99e0aae7SDavid Rees
1824*99e0aae7SDavid Rees
1825*99e0aae7SDavid Rees### `IsComplete` method
1826*99e0aae7SDavid Rees
1827*99e0aae7SDavid Rees```c++
1828*99e0aae7SDavid Reesbool IsComplete();
1829*99e0aae7SDavid Rees```
1830*99e0aae7SDavid Rees
1831*99e0aae7SDavid ReesThe `IsComplete` method returns `true` if there are enough bytes in the backing
1832*99e0aae7SDavid Reesstore to hold the given `Float` field.
1833*99e0aae7SDavid Rees
1834*99e0aae7SDavid Rees
1835*99e0aae7SDavid Rees### `UpdateFromTextStream` method
1836*99e0aae7SDavid Rees
1837*99e0aae7SDavid Rees```c++
1838*99e0aae7SDavid Reestemplate <class Stream>
1839*99e0aae7SDavid Reesbool UpdateFromTextStream(Stream *stream) const;
1840*99e0aae7SDavid Rees```
1841*99e0aae7SDavid Rees
1842*99e0aae7SDavid Rees`UpdateFromTextStream` will read a text-format representation of the `Float`
1843*99e0aae7SDavid Reesfrom the given `stream` and update fields.  Generally, applications would not
1844*99e0aae7SDavid Reescall this directly; instead, use the global `UpdateFromText` method, which
1845*99e0aae7SDavid Reeshandles setting up a stream from a `std::string`.
1846*99e0aae7SDavid Rees
1847*99e0aae7SDavid Rees*Note: this method is not yet implemented.*
1848*99e0aae7SDavid Rees
1849*99e0aae7SDavid Rees### `WriteToTextStream` method
1850*99e0aae7SDavid Rees
1851*99e0aae7SDavid Rees```c++
1852*99e0aae7SDavid Reestemplate <class Stream>
1853*99e0aae7SDavid Reesbool WriteToTextStream(Stream *stream, const TextOutputOptions &options) const;
1854*99e0aae7SDavid Rees```
1855*99e0aae7SDavid Rees
1856*99e0aae7SDavid Rees`WriteToTextStream` will write a text representation of the current value in a
1857*99e0aae7SDavid Reesform that can be decoded by `UpdateFromTextStream`. Generally, applications
1858*99e0aae7SDavid Reeswould not call this directly; instead, use the global `WriteToString` method,
1859*99e0aae7SDavid Reeswhich handles setting up the stream and returning the resulting string.
1860*99e0aae7SDavid Rees
1861*99e0aae7SDavid Rees*Note: this method is not yet implemented.*
1862*99e0aae7SDavid Rees
1863*99e0aae7SDavid Rees
1864*99e0aae7SDavid Rees## `::emboss::UpdateFromText` function
1865*99e0aae7SDavid Rees
1866*99e0aae7SDavid Rees```c++
1867*99e0aae7SDavid Reestemplate <typename EmbossViewType>
1868*99e0aae7SDavid Reesbool UpdateFromText(EmbossViewType view, const ::std::string &text) const;
1869*99e0aae7SDavid Rees```
1870*99e0aae7SDavid Rees
1871*99e0aae7SDavid ReesThe `::emboss::UpdateFromText` function constructs an appropriate text strem
1872*99e0aae7SDavid Reesobject from the given `text` and calls `view`'s `UpdateFromTextStream` method.
1873*99e0aae7SDavid ReesThis is the preferred way to read Emboss text format in C++.
1874*99e0aae7SDavid Rees
1875*99e0aae7SDavid Rees## `::emboss::WriteToString` function
1876*99e0aae7SDavid Rees
1877*99e0aae7SDavid Rees```c++
1878*99e0aae7SDavid Reestemplate <typename EmbossViewType>
1879*99e0aae7SDavid Rees::std::string WriteToString(EmbossViewType view);
1880*99e0aae7SDavid Reestemplate <typename EmbossViewType>
1881*99e0aae7SDavid Rees::std::string WriteToString(EmbossViewType view, TextOutputOptions options);
1882*99e0aae7SDavid Rees```
1883*99e0aae7SDavid Rees
1884*99e0aae7SDavid ReesThe `::emboss::WriteToString` function constructs a string stream, passes it
1885*99e0aae7SDavid Reesinto the `view`'s `WriteToTextStream` method, and finally returns the text
1886*99e0aae7SDavid Reesformat of the `view`.
1887*99e0aae7SDavid Rees
1888*99e0aae7SDavid ReesThe single-argument form `WriteToString(view)` will return a single line of
1889*99e0aae7SDavid Reestext. For more readable output, `WriteToString(view, ::emboss::MultilineText())`
1890*99e0aae7SDavid Reesshould help.
1891*99e0aae7SDavid Rees
1892*99e0aae7SDavid Rees## `::emboss::TextOutputOptions` class
1893*99e0aae7SDavid Rees
1894*99e0aae7SDavid ReesThe `TextOutputOptions` is used to set options for text output, such as numeric
1895*99e0aae7SDavid Reesbase, whether or not to use multiple lines, etc.
1896*99e0aae7SDavid Rees
1897*99e0aae7SDavid Rees### `PlusOneIndent` method
1898*99e0aae7SDavid Rees
1899*99e0aae7SDavid Rees```c++
1900*99e0aae7SDavid ReesTextOutputOptions PlusOneIndent() const;
1901*99e0aae7SDavid Rees```
1902*99e0aae7SDavid Rees
1903*99e0aae7SDavid Rees`PlusOneIndent` returns a new `TextOutputOptions` with one more level of
1904*99e0aae7SDavid Reesindentation than the current `TextOutputOptions`. This is primarily intended for
1905*99e0aae7SDavid Reesuse inside of `WriteToTextStream` methods, as a way to get an indented
1906*99e0aae7SDavid Rees`TextOutputOptions` to pass to the `WriteToTextStream` methods of child
1907*99e0aae7SDavid Reesobjects.  However, application callers may use `PlusOneIndent()`, possibly
1908*99e0aae7SDavid Reesmultiple times, to indent the entire output.
1909*99e0aae7SDavid Rees
1910*99e0aae7SDavid Rees### `Multiline` method
1911*99e0aae7SDavid Rees
1912*99e0aae7SDavid Rees```c++
1913*99e0aae7SDavid ReesTextOutputOptions Multiline(bool new_value) const;
1914*99e0aae7SDavid Rees```
1915*99e0aae7SDavid Rees
1916*99e0aae7SDavid ReesReturns a new `TextOutputOptions` with the same options as the current
1917*99e0aae7SDavid Rees`TextOutputOptions`, except for a new value for `multiline()`.
1918*99e0aae7SDavid Rees
1919*99e0aae7SDavid Rees### `WithIndent` method
1920*99e0aae7SDavid Rees
1921*99e0aae7SDavid Rees```c++
1922*99e0aae7SDavid ReesTextOutputOptions WithIndent(::std::string new_value) const;
1923*99e0aae7SDavid Rees```
1924*99e0aae7SDavid Rees
1925*99e0aae7SDavid ReesReturns a new `TextOutputOptions` with the same options as the current
1926*99e0aae7SDavid Rees`TextOutputOptions`, except for a new value for `indent()`.
1927*99e0aae7SDavid Rees
1928*99e0aae7SDavid Rees### `WithComments` method
1929*99e0aae7SDavid Rees
1930*99e0aae7SDavid Rees```c++
1931*99e0aae7SDavid ReesTextOutputOptions WithComments(bool new_value) const;
1932*99e0aae7SDavid Rees```
1933*99e0aae7SDavid Rees
1934*99e0aae7SDavid ReesReturns a new `TextOutputOptions` with the same options as the current
1935*99e0aae7SDavid Rees`TextOutputOptions`, except for a new value for `comments()`.
1936*99e0aae7SDavid Rees
1937*99e0aae7SDavid Rees### `WithDigitGrouping` method
1938*99e0aae7SDavid Rees
1939*99e0aae7SDavid Rees```c++
1940*99e0aae7SDavid ReesTextOutputOptions WithDigitGrouping(bool new_value) const;
1941*99e0aae7SDavid Rees```
1942*99e0aae7SDavid Rees
1943*99e0aae7SDavid ReesReturns a new `TextOutputOptions` with the same options as the current
1944*99e0aae7SDavid Rees`TextOutputOptions`, except for a new value for `digit_grouping()`.
1945*99e0aae7SDavid Rees
1946*99e0aae7SDavid Rees### `WithNumericBase` method
1947*99e0aae7SDavid Rees
1948*99e0aae7SDavid Rees```c++
1949*99e0aae7SDavid ReesTextOutputOptions WithNumericBase(int new_value) const;
1950*99e0aae7SDavid Rees```
1951*99e0aae7SDavid Rees
1952*99e0aae7SDavid ReesReturns a new `TextOutputOptions` with the same options as the current
1953*99e0aae7SDavid Rees`TextOutputOptions`, except for a new value for `digit_grouping()`. The new
1954*99e0aae7SDavid Reesnumeric base should be 2, 10, or 16.
1955*99e0aae7SDavid Rees
1956*99e0aae7SDavid Rees### `WithAllowPartialOutput` method
1957*99e0aae7SDavid Rees
1958*99e0aae7SDavid Rees```c++
1959*99e0aae7SDavid ReesTextOutputOptions WithAllowPartialOutput(bool new_value) const;
1960*99e0aae7SDavid Rees```
1961*99e0aae7SDavid Rees
1962*99e0aae7SDavid ReesReturns a new `TextOutputOptions` with the same options as the current
1963*99e0aae7SDavid Rees`TextOutputOptions`, except for a new value for `allow_partial_output()`.
1964*99e0aae7SDavid Rees
1965*99e0aae7SDavid Rees### `current_indent` method
1966*99e0aae7SDavid Rees
1967*99e0aae7SDavid Rees```c++
1968*99e0aae7SDavid Rees::std::string current_indent() const;  // Default "".
1969*99e0aae7SDavid Rees```
1970*99e0aae7SDavid Rees
1971*99e0aae7SDavid ReesReturns the current indent string.
1972*99e0aae7SDavid Rees
1973*99e0aae7SDavid Rees### `indent` method
1974*99e0aae7SDavid Rees
1975*99e0aae7SDavid Rees```c++
1976*99e0aae7SDavid Rees::std::string indent() const;  // Default "  ".
1977*99e0aae7SDavid Rees```
1978*99e0aae7SDavid Rees
1979*99e0aae7SDavid ReesReturns the indent string.  The indent string is the string used for a *single*
1980*99e0aae7SDavid Reeslevel of indentation.
1981*99e0aae7SDavid Rees
1982*99e0aae7SDavid Rees### `multiline` method
1983*99e0aae7SDavid Rees
1984*99e0aae7SDavid Rees```c++
1985*99e0aae7SDavid Reesbool multiline() const;  // Default false.
1986*99e0aae7SDavid Rees```
1987*99e0aae7SDavid Rees
1988*99e0aae7SDavid ReesReturns `true` if text output should use multiple lines, or `false` if text
1989*99e0aae7SDavid Reesoutput should be single-line only.
1990*99e0aae7SDavid Rees
1991*99e0aae7SDavid Rees### `digit_grouping` method
1992*99e0aae7SDavid Rees
1993*99e0aae7SDavid Rees```c++
1994*99e0aae7SDavid Reesbool digit_grouping() const;  // Default false.
1995*99e0aae7SDavid Rees```
1996*99e0aae7SDavid Rees
1997*99e0aae7SDavid ReesReturns `true` if text output should include digit separators on numbers; i.e.
1998*99e0aae7SDavid Rees`1_000_000` instead of `1000000`.
1999*99e0aae7SDavid Rees
2000*99e0aae7SDavid Rees### `comments` method
2001*99e0aae7SDavid Rees
2002*99e0aae7SDavid Rees```c++
2003*99e0aae7SDavid Reesbool comments() const;  // Default false.
2004*99e0aae7SDavid Rees```
2005*99e0aae7SDavid Rees
2006*99e0aae7SDavid ReesReturns `true` if text output should include comments, e.g., to show numbers in
2007*99e0aae7SDavid Reesmultiple bases.
2008*99e0aae7SDavid Rees
2009*99e0aae7SDavid Rees### `numeric_base` method
2010*99e0aae7SDavid Rees
2011*99e0aae7SDavid Rees```c++
2012*99e0aae7SDavid Reesuint8_t numeric_base() const;  // Default 10.
2013*99e0aae7SDavid Rees```
2014*99e0aae7SDavid Rees
2015*99e0aae7SDavid ReesReturns the numeric base that should be used for formatting numbers. This should
2016*99e0aae7SDavid Reesalways be 2, 10, or 16.
2017*99e0aae7SDavid Rees
2018*99e0aae7SDavid Rees### `allow_partial_output` method
2019*99e0aae7SDavid Rees
2020*99e0aae7SDavid Rees```c++
2021*99e0aae7SDavid Reesbool allow_partial_output() const;  // Default false.
2022*99e0aae7SDavid Rees```
2023*99e0aae7SDavid Rees
2024*99e0aae7SDavid ReesReturns `true` if text output should attempt to extract fields from a view that
2025*99e0aae7SDavid Reesis not `Ok()`.  If so:
2026*99e0aae7SDavid Rees
2027*99e0aae7SDavid Rees*   `WriteToString()` or `WriteToTextStream()` should never `CHECK`-fail.
2028*99e0aae7SDavid Rees*   Atomic fields (e.g., `Int`, `UInt`, `enum`, `Flag`, etc. types) will not be
2029*99e0aae7SDavid Rees    written to the text stream if they cannot be read.
2030*99e0aae7SDavid Rees*   If `comments()` is also `true`, unreadable atomic fields will be commented
2031*99e0aae7SDavid Rees    in the text stream.
2032*99e0aae7SDavid Rees*   Aggregate fields (`struct`, `bits`, or arrays) will be written, but may be
2033*99e0aae7SDavid Rees    missing fields or entirely empty if they have non-`Ok()` members.
2034