template <typename Storage>
class View
Defined at line 99 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
The zbitl::View class provides functionality for processing ZBI items in various
storage formats.
For example, the entries in a ZBI present in memory can be enumerated as follows:
```
void ProcessZbiEntries(std::string_view data) {
// Create the view.
zbitl::View
<std
::string_view> view{data};
// Iterate over entries.
for (const auto
&
entry : view) {
printf("Found entry of type %x with payload size %ld.\n",
entry.header->type, // entry.header has type similar to "zbi_header_t *".
entry.payload.size()); // entry.payload has type "std::string_view".
}
// Callers are required to check for errors (or call "ignore_error")
// prior to object destruction. See "Error checking" below.
if (auto error = view.take_error(); error.is_error()) {
printf("Error encountered!\n");
// ...
}
}
```
zbitl::View satisfies the C++20 std::forward_range concept; it satisfies the
std::view concept if the Storage and Storage::error_type types support
constant-time copy/move/assignment.
## Error checking
The "error-checking view" pattern means that the container/range/view API
of begin() and end() iterators is supported, but when begin() or
iterator::operator++() encounters an error, it simply returns end() so that
loops terminate normally. Thereafter, take_error() must be called to check
whether the loop terminated because it iterated past the last item or
because it encountered an error. Once begin() has been called,
take_error() must be called before the View is destroyed, so no error goes
undetected. Since all use of iterators updates the error state, use of any
zbitl::View object must be serialized and after begin() or operator++()
yields end(), take_error() must be checked before using begin() again.
## Iteration
Each time begin() is called the underlying storage is examined afresh, so
it's safe to reuse a zbitl::View object after changing the data. Reducing
the size of the underlying storage invalidates any iterators that pointed
past the new end of the image. It's simplest just to assume that changing
the underlying storage always invalidates all iterators.
## Storage
The Storage type is some type that can be abstractly considered to have
non-owning "view" semantics: it doesn't hold the storage of the ZBI, it
just refers to it somehow. The zbitl::View:Error type describes errors
encountered while iterating. It uses the Storage::error_type type to
propagate errors caused by access to the underlying storage.
Usually Storage and Storage:error_type types are small and can be copied.
zbitl::View is move-only if Storage is move-only or if Storage::error_type
is move-only. Note that copying zbitl::View copies its error-checking
state exactly, so if the original View needed to be checked for errors
before destruction then both the original and the copy need to be checked
before their respective destructions. A moved-from zbitl::View can always
be destroyed without checking.
Public Methods
void View<Storage> ()
Defined at line 104 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
void View<Storage> (const View<Storage> & )
Defined at line 105 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
View<Storage> & operator= (const View<Storage> & )
Defined at line 106 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
void View<Storage> (View<Storage> && other)
This is almost the same as the default move behavior. But it also
explicitly resets the moved-from error state to kUnused so that the
moved-from View can be destroyed without checking it.
Defined at line 111 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
View<Storage> & operator= (View<Storage> && other)
Defined at line 116 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
void View<Storage> (storage_type storage)
Defined at line 125 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
void ~View<Storage> ()
Defined at line 127 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
fit::result<Error> take_error ()
Check the container for errors after using iterators. When begin() or
iterator::operator++() encounters an error, it simply returns end() so
that loops terminate normally. Thereafter, take_error() must be called
to check whether the loop terminated because it iterated past the last
item or because it encountered an error. Once begin() has been called,
take_error() must be called before the View is destroyed, so no error
goes undetected. After take_error() is called the error state is
consumed and take_error() cannot be called again until another begin() or
iterator::operator++() call has been made.
Defined at line 281 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
bool haz_error ()
Defined at line 292 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
void ignore_error ()
If you explicitly don't care about any error that might have terminated
the last loop early, then call ignore_error() instead of take_error().
Defined at line 296 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
storage_type & storage ()
Trivial accessors for the underlying Storage (view) object.
Defined at line 299 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
const storage_type & storage ()
Defined at line 300 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
fit::result<Error, zbi_header_t> container_header ()
This returns its own error state and does not affect the `take_error()`
state of the View.
Defined at line 466 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
iterator begin ()
After calling begin(), it's mandatory to call take_error() before
destroying the View object. An iteration that encounters an error will
simply end early, i.e. begin() or operator++() will yield an iterator
that equals end(). At the end of a loop, call take_error() to check for
errors. It's also acceptable to call take_error() during an iteration
that hasn't reached end() yet, but it cannot be called again before the
next begin() or operator++() call.
Defined at line 507 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
iterator end ()
Defined at line 520 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
size_t size_bytes ()
Defined at line 522 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
iterator find (uint32_t type)
Looks up an item by type, returning the iterator pointing to the first
match or else end().
Like begin(), find() resets the internal error state and it is the
responsibility of the caller to take or ignore that error before calling
this method.
Defined at line 538 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
fit::result<typename Traits::error_type> EditHeader (const iterator & item, const zbi_header_t & header)
Replace an item's header with a new one, using an iterator into this
view.. This never changes the existing item's length (nor its payload).
So the header can be `{.type = XYZ}` alone or whatever fields and flags
matter. Note this returns only the storage error type, not an Error since
no ZBI format errors are possible here, only a storage failure to update.
This method is not available if zbitl::StorageTraits
<storage
_type>
doesn't support mutation.
Defined at line 552 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
fit::result<typename Traits::error_type> EditHeader (iterator & item, const zbi_header_t & header)
When the iterator is mutable and not a temporary, make the next
operator*() consistent with the new header if it worked. For kReference
storage types, the change is reflected intrinsically.
Defined at line 567 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
fit::result<Error, bool> CheckCrc32 (iterator it)
Verifies that a given View iterator points to an item with a valid CRC32.
Defined at line 584 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
template <typename CopyStorage>
fit::result<CopyError<std::decay_t<CopyStorage>>> Copy (CopyStorage && to, uint32_t offset, uint32_t length, uint32_t to_offset)
Copy a range of the underlying storage into an existing piece of storage,
which can be any mutable type with sufficient capacity. The Error return
value is for a read error. The "success" return value indicates there was
no read error. It's another fit::result
<error
_type> for the writing side
(which may be different than the type used in Error::storage_error). The
optional `to_offset` argument says where in `to` the data is written, as a
byte offset that is zero by default.
Defined at line 630 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
template <typename T = Traits, typename CreateStorage = std::decay_t<typename T::template CreateResult<>>>
fit::result<CopyError<CreateStorage>, CreateStorage> Copy (uint32_t offset, uint32_t length, uint32_t to_offset)
Defined at line 716 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
template <typename CopyStorage>
fit::result<CopyError<std::decay_t<CopyStorage>>> CopyRawItem (CopyStorage && to, const iterator & it)
Copy a single item's payload into supplied storage.
Defined at line 730 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
template <typename T = Traits, typename CreateStorage = std::decay_t<typename T::template CreateResult<>>>
fit::result<CopyError<CreateStorage>, CreateStorage> CopyRawItem (const iterator & it)
Defined at line 739 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
template <typename CopyStorage>
fit::result<CopyError<std::decay_t<CopyStorage>>> CopyRawItemWithHeader (CopyStorage && to, const iterator & it)
Copy a single item's header and payload into supplied storage.
Defined at line 745 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
template <typename T = Traits, typename CreateStorage = std::decay_t<typename T::template CreateResult<>>>
fit::result<CopyError<CreateStorage>, CreateStorage> CopyRawItemWithHeader (const iterator & it)
Defined at line 755 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
template <typename CopyStorage, typename ScratchAllocator>
fit::result<CopyError<std::decay_t<CopyStorage>>> CopyStorageItem (CopyStorage && to, const iterator & it, ScratchAllocator && scratch)
Copy a single item's payload into supplied storage, including
decompressing a ZBI_TYPE_STORAGE_* item if necessary. This statically
determines based on the input and output storage types whether it has to
use streaming decompression or can use the one-shot mode (which is more
efficient and requires less scratch memory). So the unused part of the
decompression library can be elided at link time.
If decompression is necessary, then this calls `scratch(size_t{bytes})` to
allocate scratch memory for the decompression engine. This returns
`fit::result
<std
::string_view, T>` where T is any movable object that has
a `get()` method returning a pointer (of any type implicitly converted to
`void*`) to the scratch memory. The returned object is destroyed after
decompression is finished and the scratch memory is no longer needed.
zbitl::decompress:DefaultAllocator is a default-constructible class that
can serve as `scratch`. The overloads below with fewer arguments use it.
Defined at line 776 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
template <typename ScratchAllocator, typename T = Traits, typename CreateStorage = std::decay_t<typename T::template CreateResult<>>>
fit::result<CopyError<CreateStorage>, CreateStorage> CopyStorageItem (const iterator & it, ScratchAllocator && scratch)
Defined at line 788 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
template <typename CopyStorage>
fit::result<CopyError<std::decay_t<CopyStorage>>> CopyStorageItem (CopyStorage && to, const iterator & it)
These overloads have the effect of default arguments for the allocator
arguments to the general versions above, but template argument deduction
doesn't work with default arguments.
Defined at line 818 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
auto CopyStorageItem (const iterator & it)
Defined at line 823 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
template <typename CopyStorage>
fit::result<CopyError<std::decay_t<CopyStorage>>> Copy (CopyStorage && to, const iterator & first, const iterator & last)
Copy the subrange `[first,last)` of the ZBI into supplied storage.
The storage will contain a new ZBI container with only those items.
Defined at line 832 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
template <typename T = Traits, typename CreateStorage = std::decay_t<typename T::template CreateResult<>>>
fit::result<CopyError<CreateStorage>, CreateStorage> Copy (const iterator & first, const iterator & last)
Copy the subrange `[first,last)` of the ZBI into newly-created storage.
The storage will contain a new ZBI container with only those items.
Defined at line 857 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
template <typename CopyStorage = Storage>
bool CanZeroCopy ()
This is public mostly just for tests to assert on it.
Defined at line 917 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
Protected Methods
fit::result<typename Traits::error_type, typename Traits::template LocalizedReadResult<zbi_header_t>> ReadContainerHeader (Storage & storage)
Fetches the container header.
Defined at line 927 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
fit::result<typename Traits::error_type, typename Traits::template LocalizedReadResult<zbi_header_t>> ReadItemHeader (Storage & storage, uint32_t offset)
Fetches an item header at a given offset.
Defined at line 934 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
fit::result<typename Traits::error_type, zbi_header_t> WriteHeader (zbi_header_t header, uint32_t offset, std::optional<uint32_t> new_length)
WriteHeader sanitizes and optionally updates the length of a provided
header, writes it to the provided offset, and returns the modified header
on success.
Defined at line 943 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
fit::result<typename Traits::error_type, zbi_header_t> WriteHeader (zbi_header_t header, uint32_t offset, std::optional<uint32_t> new_length)
WriteHeader sanitizes and optionally updates the length of a provided
header, writes it to the provided offset, and returns the modified header
on success.
Defined at line 943 of file ../../src/lib/zbitl/include/lib/zbitl/view.h
void set_limit (uint32_t limit)
Defined at line 955 of file ../../src/lib/zbitl/include/lib/zbitl/view.h