blob: b93fb79b142d97423494c48ee49040e6e02c1709 [file] [log] [blame] [view]
# Initialization
Outside of the Wuffs base package, every Wuffs struct has an implicit
`initialize` method, which needs to be called before any other method. In
Wuffs' C language form, the `initialize` function for the `foo` package's `bar`
struct is called `wuffs_foo__bar__initialize`. The function takes four
arguments (or, in C++, the `initialize` method takes three arguments, with the
implicit `this` pointer argument):
- A pointer to the `wuffs_foo__bar` object: the `this` pointer.
- The size (in bytes) of that object. Conceptually, this is
`sizeof(wuffs_foo__bar{})`, but that expression generally won't compile, as
`wuffs_foo__bar` is deliberately an incomplete type. Its size is not part of
the stable ABI. Instead, call the `sizeof__wuffs_foo__bar` *function*, whose
return value can change across Wuffs versions, even across point releases.
For an example, look for `sizeof__wuffs_json__decoder` in the
[example/jsonptr](/example/jsonptr/jsonptr.cc) program.
- The Wuffs library version, `WUFFS_VERSION`.
- Additional flags.
Initialization can fail if the caller and callee disagree on the size or the
Wuffs version, or if unsupported flag bits are passed.
There are no destructor functions. Just free the memory. Wuffs structs don't
store or otherwise own file descriptors, pointers to dynamically allocated
memory or anything else that needs explicit releasing.
As a consequence, to restore a Wuffs object to its initial state (e.g. to
re-use a Wuffs image decoder's memory to decode a different image), just call
the `initialize` function again.
## Flags
The flags are a bitmask of options. Zero (or equivalently,
`WUFFS_INITIALIZE__DEFAULT_OPTIONS`) means that none of the options are set.
- The `WUFFS_INITIALIZE__ALREADY_ZEROED` bit tells the `initialize` function to
assume that the entire struct has already been zero-initialized. This can
make the `initialize` call a little faster.
- The `WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED` bit means to
partially, not fully, zero-initialize the struct. Again, this can make the
call a little faster. See the "Partial Zero-Initialization" section below for
details. This bit is ignored if the `WUFFS_INITIALIZE__ALREADY_ZEROED` bit is
also set.
## Partial Zero-Initialization
Memory-safe programming languages typically initialize their variables and
fields to zero, so that there is no way to read an uninitialized value. By
default, Wuffs does so too, but in Wuffs' C/C++ form, there is the option (the
`WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED` flag bit) to leave
some struct fields uninitialized (although local variables are always
zero-initialized), for performance reasons.
With or without this flag bit set, the Wuffs compiler still enforces bounds and
arithmetic overflow checks. It's just that for potentially-uninitialized struct
fields, the compiler has weaker starting assumptions: their numeric types
cannot be [refined](/doc/glossary.md#refinement-type).
Even with this flag bit set, the Wuffs standard library also considers reading
from an uninitialized buffer to be a bug, and strives to never do so, but
unlike buffer out-of-bounds reads or writes, it is not a bug class that the
Wuffs compiler eliminates.
For those paranoid about security, leave this flag bit unset, so that
`wuffs_foo__bar__initialize` will zero-initialize the entire struct (unless the
`WUFFS_INITIALIZE__ALREADY_ZEROED` flag bit is also set).
Setting this flag bit (avoiding a fixed-size cost) gives a small absolute
improvement on micro-benchmarks, mostly noticeable (in relative terms) only
when the actual work to do (the input) is also small. Look for
`WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED` in the
[benchmarks](/doc/benchmarks.md) for performance numbers.
In Wuffs code, a struct definition has two parts, although the second part's
`()` parentheses may be omitted if empty:
```
pub struct bar?(
// Fields in the first part are always zero-initialized.
x : etc,
y : etc,
)(
// Fields in the second part are optionally uninitialized, but are still
// zero-initialized by default.
//
// Valid types for these fields are either unrefined numerical types, or
// arrays of a valid type.
// - "base.u8" is ok.
// - "array[123] base.u8" is ok.
// - "array[123] base.u8[0 ..= 99]" is not, due to the refinement.
z : etc,
)
```