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

Records