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