asdf/value.h

Structures and methods pertaining to ASDF tree values

type asdf_value_t

Opaque struct representing a generic value from the ASDF tree

enum asdf_value_type_t

Tags used to identify the type of a value in the ASDF tree

See e.g. asdf_value_get_type to get the known type of an asdf_value_t.

enumerator ASDF_VALUE_UNKNOWN

Unknown type; typically not encountered except in a parsing error

enumerator ASDF_VALUE_SEQUENCE

A YAML sequence (array)

enumerator ASDF_VALUE_MAPPING

A YAML mapping (a.k.a. dict, hash, etc.)

enumerator ASDF_VALUE_SCALAR

A generic scalar before coerced to a more specific type

enumerator ASDF_VALUE_STRING

A string

A scalar is considered a string if it is explicitly quoted with single- or double-quotes, or uses a literal or folded scalar represenation style in the YAML document, or any other scalar that cannot be coecered to one of the other types defined in the YAML Core Schema.

enumerator ASDF_VALUE_BOOL

A bool

Values have this type if they are unquoted scalars true/True/TRUE or false/False/FALSE (case-sensitive).

enumerator ASDF_VALUE_NULL

A null value

Values are null if a key in a mapping is followed by nothing but whitespace (there is no explicit value given) or if it contains the unquoted scalars null/Null/NULL/~ (case-sensitive).

enumerator ASDF_VALUE_INT8

Signed 8-bit integer

enumerator ASDF_VALUE_INT16

Signed 16-bit integer

enumerator ASDF_VALUE_INT32

Signed 32-bit integer

enumerator ASDF_VALUE_INT64

Signed 64-bit integer

enumerator ASDF_VALUE_UINT8

Unsigned 8-bit integer

enumerator ASDF_VALUE_UINT16

Unsigned 16-bit integer

enumerator ASDF_VALUE_UINT32

Unsigned 32-bit integer

enumerator ASDF_VALUE_UINT64

Unsigned 64-bit integer

enumerator ASDF_VALUE_FLOAT

32-bit IEEE float

enumerator ASDF_VALUE_DOUBLE

64-bit IEEE float

enumerator ASDF_VALUE_EXTENSION

Extension type

Recognized if the value has a tag associated with a registered extension.

enum asdf_value_err_t

Return type for many functions that return a value out of the ASDF tree

ASDF_VALUE_OK means that the path to the value exists, and that the value could be read as the type corresponding to the getter (e.g. asdf_get_string returns an existing string). Other values of this enum are all errors, the most common being ASDF_VALUE_ERR_NOT_FOUND or ASDF_VALUE_ERR_TYPE_MISMATCH.

enumerator ASDF_VALUE_ERR_NOT_FOUND = -1

Error when the given YAML Pointer does not correspond to a path in the ASDF tree

enumerator ASDF_VALUE_OK = 0

The value was read successfully

enumerator ASDF_VALUE_ERR_TYPE_MISMATCH

A typed getter like asdf_get_string was called on a path that does not point to a string (but some other type)

enumerator ASDF_VALUE_ERR_PARSE_FAILURE

This error mostly occurs if a value had an explicit tag like !!int but could not be parsed as an int.

enumerator ASDF_VALUE_ERR_EMIT_FAILURE

Error that can be returned when attempting to serialize values that are not in a valid state (e.g. user-defined extension values)

enumerator ASDF_VALUE_ERR_OVERFLOW

Error that occurs mostly in the asdf_get_(u)int<N> such as asdf_get_int8 or asdf_get_float or asdf_get_double functions if the value looks like a numeric value but cannot be represented in the C type returned by the function.

enumerator ASDF_VALUE_ERR_OOM

Error returned when memory could not be allocated for the returned object (typically only if the system is out of memory).

enumerator ASDF_VALUE_ERR_READ_ONLY

Error returned when setting a value on a file or other value set to read-only/immutable.

void asdf_value_destroy(asdf_value_t *value)

Free memory held by an asdf_value_t

Calling this does not destroy any memory allocated for C-native data coerced from the value, including extension types. It just frees up the asdf_value_t that wrapped it.

Parameters:
asdf_value_t *asdf_value_clone(asdf_value_t *value)

Clone an asdf_value_t

This performs a deep-copy of a value and may be used in certain cases (such as container iteration) when the user needs an owned copy of the value.

The new cloned value is not initially attached to the YAML tree, so modification to its underlying value is not reflected in the YAML; it may be inserted elsewhere in the tree later.

asdf_value_type_t asdf_value_get_type(asdf_value_t *value)

Get the specific asdf_value_type_t of a generic asdf_value_t

Parameters:
Returns:

The asdf_value_type_t enum member representing the value type

asdf_value_t *asdf_value_parent(asdf_value_t *value)

Get the parent value, if any, of the given value

Parameters:
Returns:

An asdf_value_t* of its parent mapping or sequence; if the input value is the root node, or is not an attached value, the parent is NULL

const char *asdf_value_type_string(asdf_value_type_t type)

Returns a human-readable string representation of an asdf_value_type_t; useful for error-reporting

asdf_file_t *asdf_value_file(asdf_value_t *value)

Get the asdf_file_t* handle to the file to which a value belongs

Mappings

type asdf_mapping_t

Opaque struct represening a mapping value

Note

By design, it is safe to cast a an asdf_value_t* to asdf_mapping_t* so long as the value has been checked to be a sequence.

asdf_value_t *asdf_mapping_get(asdf_mapping_t *mapping, const char *key)

Return an asdf_value_t from the given mapping at a given key

If the key does not exist in the mapping, or the first argument is not a mapping at all, returns NULL

Parameters:
  • mapping – An asdf_mapping_t* containing a mapping

  • key – The key into the mapping

Returns:

The asdf_value_t* wrapping the value at that key, if any. Make sure to release it with asdf_value_destroy when no-longer needed.

struct asdf_mapping_iter_t

Iterator handle for traversing a mapping value

Initialize with asdf_mapping_iter_init. After each successful call to asdf_mapping_iter_next, the key and value fields hold the current mapping entry and are valid until the next call to asdf_mapping_iter_next or asdf_mapping_iter_destroy. If the value must outlive the current iteration step, clone it with asdf_value_clone.

Warning

Modifying the mapping while iterating over it results in undefined behavior.

const char *key

Current key

asdf_value_t *value

Current value

asdf_mapping_iter_t *asdf_mapping_iter_init(asdf_mapping_t *mapping)

Create a new iterator over mapping

Parameters:
Returns:

A new asdf_mapping_iter_t* handle, or NULL on allocation failure

bool asdf_mapping_iter_next(asdf_mapping_iter_t **iter)

Advance the iterator to the next mapping entry

On success, asdf_mapping_iter_t.key and asdf_mapping_iter_t.value are updated to the current entry. When iteration is exhausted the iterator is freed automatically and *iter is set to NULL.

Typical usage:

asdf_mapping_iter_t *iter = asdf_mapping_iter_init(mapping);
while (asdf_mapping_iter_next(&iter)) {
    // iter->key and iter->value are valid here
}

For early exit call asdf_mapping_iter_destroy before breaking:

asdf_mapping_iter_t *iter = asdf_mapping_iter_init(mapping);
while (asdf_mapping_iter_next(&iter)) {
    if (done) {
        asdf_mapping_iter_destroy(iter);
        break;
    }
}
Parameters:
  • iter – Pointer to the iterator handle; set to NULL on exhaustion

Returns:

true if an entry was found; false when iteration is done

void asdf_mapping_iter_destroy(asdf_mapping_iter_t *iter)

Release resources held by an in-progress mapping iterator

Call this only when breaking out of iteration early. Safe to call with NULL.

Parameters:
asdf_value_err_t asdf_mapping_update(asdf_mapping_t *mapping, asdf_mapping_t *update)

Update / merge a mapping with key/value pairs from a second mapping

If keys in the RHS mapping already exist in the LHS they are overwritten, otherwise appended.

Values in the RHS mapping are copied during the update process, so the RHS mapping remains valid.

Todo

Finish documenting me.

asdf_value_t *asdf_mapping_pop(asdf_mapping_t *mapping, const char *key)

Remove a value from a mapping and return the removed value

Parameters:
  • mapping – The asdf_mapping_t* handle

  • key – The of the item to remove

Returns:

The generic asdf_value_t* of the removed value if any, or NULL if the key did not exist or on errors

Set values on mappings

Todo

Document the rest of these.

asdf_value_err_t asdf_mapping_set(asdf_mapping_t *mapping, const char *key, asdf_value_t *value)

Set a generic asdf_value_t* on a mapping at the given key

If the key already exists in the mapping its value will be overwritten

Params mapping:

Handle to the asdf_mapping_t to update

Params key:

The key at which to insert the value

Params value:

Generic asdf_value_t* to insert into the mapping

Returns:

ASDF_VALUE_OK on success or another asdf_value_err_t

Sequences

type asdf_sequence_t

Opaque struct representing a sequence value

Note

By design, it is safe to cast a an asdf_value_t* to asdf_sequence_t* so long as the value has been checked to be a sequence.

bool asdf_value_is_sequence(asdf_value_t *value)

Return true if value holds a YAML sequence

int asdf_sequence_size(asdf_sequence_t *sequence)

Return the number of items in sequence

Parameters:
Returns:

The number of items currently in the sequence

asdf_value_t *asdf_sequence_get(asdf_sequence_t *sequence, int index)

Return the value at index in sequence

Negative indices are supported (e.g. -1 for the last item). Returns NULL if index is out of range.

Parameters:
  • sequence – The asdf_sequence_t* to query

  • index – Zero-based index; negative indices count from the end

Returns:

The asdf_value_t* at that position, or NULL

asdf_value_err_t asdf_value_as_sequence(asdf_value_t *value, asdf_sequence_t **out)

Obtain a typed asdf_sequence_t* view of a generic value

On success writes the asdf_sequence_t* into *out and returns ASDF_VALUE_OK. Returns an error code and leaves *out unchanged if value is not a sequence.

Parameters:
Returns:

ASDF_VALUE_OK on success, otherwise an asdf_value_err_t error

asdf_value_t *asdf_value_of_sequence(asdf_sequence_t *sequence)

Return the generic asdf_value_t* view of a sequence

The returned pointer shares ownership with sequence; the caller must not free it independently.

Parameters:
Returns:

The same object as a generic asdf_value_t*

asdf_sequence_t *asdf_sequence_create(asdf_file_t *file)

Create a new, empty sequence attached to file

The caller owns the returned sequence and must eventually release it with asdf_sequence_destroy, or transfer ownership by inserting it into a mapping or parent sequence. Returns NULL on allocation failure.

Parameters:
Returns:

A new asdf_sequence_t*, or NULL on failure

void asdf_sequence_set_style(asdf_sequence_t *sequence, asdf_yaml_node_style_t style)

Set the YAML node style used when serializing sequence

Parameters:
void asdf_sequence_destroy(asdf_sequence_t *sequence)

Free a sequence and all values it contains

Must not be called on a sequence that has been inserted into a mapping or parent sequence – ownership transfers at that point.

Parameters:
struct asdf_sequence_iter_t

Iterator handle for traversing a sequence value

Initialize with asdf_sequence_iter_init. After each successful call to asdf_sequence_iter_next, the index and value fields hold the current element and are valid until the next call to asdf_sequence_iter_next or asdf_sequence_iter_destroy.

Warning

Modifying the sequence while iterating over it results in undefined behavior.

asdf_value_t *value

Current value

int index

Index of the current value

asdf_sequence_iter_t *asdf_sequence_iter_init(asdf_sequence_t *sequence)

Create a new iterator over sequence

Parameters:
Returns:

A new asdf_sequence_iter_t* handle, or NULL on allocation failure

bool asdf_sequence_iter_next(asdf_sequence_iter_t **iter)

Advance the iterator to the next sequence element

Typical usage:

asdf_sequence_iter_t *iter = asdf_sequence_iter_init(sequence);
while (asdf_sequence_iter_next(&iter)) {
    // iter->index and iter->value are valid here
}
Parameters:
  • iter – Pointer to the iterator handle; set to NULL on exhaustion

Returns:

true if an element was found; false when iteration is done

void asdf_sequence_iter_destroy(asdf_sequence_iter_t *iter)

Release resources held by an in-progress sequence iterator

Call this only when breaking out of iteration early. Safe to call with NULL.

Parameters:
asdf_value_err_t asdf_sequence_append(asdf_sequence_t *sequence, asdf_value_t *value)

Append a value to a sequence

asdf_sequence_append appends an existing generic asdf_value_t*. Ownership of value transfers to sequence on success.

The asdf_sequence_append_<type> variants construct a new value from a C scalar and append it in one step. asdf_sequence_append_string takes an explicit byte length; asdf_sequence_append_string0 expects a NUL-terminated string. asdf_sequence_append_null takes no value argument. All other variants accept the corresponding C type directly.

asdf_sequence_append_mapping and asdf_sequence_append_sequence transfer ownership of the supplied container to the parent sequence on success.

All functions return ASDF_VALUE_OK on success or an asdf_value_err_t error code on failure.

asdf_sequence_t *asdf_sequence_of_null(asdf_file_t *file, int size)

Create a new sequence pre-populated from a C array in a single call

Each asdf_sequence_of_<type> function allocates a new sequence attached to file and appends size elements from arr. On success the caller owns the returned sequence and must eventually release it with asdf_sequence_destroy (or transfer ownership by inserting it into a mapping or parent sequence). Returns NULL on allocation failure.

asdf_sequence_of_null creates a sequence of size null values; it takes no array argument.

asdf_sequence_of_string accepts an array of (str, len) pairs via separate arr and lens pointer arguments. asdf_sequence_of_string0 is the null-terminated-string variant.

All other variants mirror the corresponding asdf_sequence_append_<type> scalar types.

asdf_value_t *asdf_sequence_pop(asdf_sequence_t *sequence, int index)

Remove a value from a sequence and return the removed value

If the index is greater than the size of the sequence, nothing is changed and returns NULL. Items following the removed item in the sequence are shifted down.

Parameters:
  • sequence – The asdf_sequence_t* handle

  • index – The index of the item to remove; negative indices are also supported (e.g. asdf_sequence_pop(sequence, -1) removes the last item

Returns:

The generic asdf_value_t* of the removed value if any, or NULL

struct asdf_container_iter_t

Iterator handle for traversing either a mapping or a sequence

When iterating over a mapping: key holds the current key though index also tracks the position in the mapping (taken as a sequence of key/value pairs). When iterating over a sequence: index holds the position and key is NULL. value is always valid after a successful asdf_container_iter_next.

Warning

Modifying the container while iterating over it results in undefined behavior.

const char *key

Current key (mappings only; NULL for sequences)

int index

Current index

asdf_value_t *value

Current value

asdf_container_iter_t *asdf_container_iter_init(asdf_value_t *container)

Create a new iterator over container (mapping or sequence)

Returns NULL if container is neither a mapping nor a sequence.

Parameters:
Returns:

A new asdf_container_iter_t* handle, or NULL on failure

bool asdf_container_iter_next(asdf_container_iter_t **iter)

Advance the generic container iterator to the next element

In most cases asdf_mapping_iter_next or asdf_sequence_iter_next are preferred, but this is useful when the container type is not known at the call site.

Parameters:
  • iter – Pointer to the iterator handle; set to NULL on exhaustion

Returns:

true if an element was found; false when iteration is done

void asdf_container_iter_destroy(asdf_container_iter_t *iter)

Release resources held by an in-progress container iterator

Call this only when breaking out of iteration early. Safe to call with NULL.

Parameters:
int asdf_container_size(asdf_value_t *container)

Generic container size

Parameters:
  • valueasdf_value_t* containing a mapping or a sequence

Returns:

The size of the mapping or container, or -1 if the value is not a container type

Extension-related functions

bool asdf_value_is_extension_type(asdf_value_t *value, const asdf_extension_t *ext)

Check if an asdf_value_t* has the specified extension type

Note

This is usually wrapped by some helper utility named like asdf_value_is_<extention>, such as asdf_value_is_ndarray.

But that is equivalent to running:

const asdf_extension_t *ext = asdf_extension_get(file, "tag:...");
asdf_value_is_extension_type(value, ext);
asdf_value_err_t asdf_value_as_extension_type(asdf_value_t *value, const asdf_extension_t *ext, void **out)

Cast an asdf_value_t* to the specified extension type

Note

This is usually wrapped by some helper utility named like asdf_value_as_<extention>, such as asdf_value_as_ndarray.

But that is equivalent to running:

asdf_ndarray_t *ndarray = NULL;
const asdf_extension_t *ext = asdf_extension_get(file, "tag:...");
asdf_value_as_extension_type(value, ext, &ndarray);

Generic value functions

bool asdf_value_is_type(asdf_value_t *value, asdf_value_type_t type)

Given an arbitrary asdf_value_type_t enum member, check if the value has that type.

Note

For checking against a specific extension type it’s still necessary to use asdf_value_is_extension_type

asdf_value_err_t asdf_value_as_type(asdf_value_t *value, asdf_value_type_t type, void *out)

Retrieve the underlying value of an arbitrary asdf_value_t as the type associated with an asdf_value_type_t

The output address is passed in as a void*. In the case of ASDF_VALUE_STRING the value is always returned as a 0-terminated string.

Note

For getting the value of a specific extension type it’s still necessary to use asdf_value_as_extension_type

Tree traversal functions

typedef _Bool (*asdf_value_pred_t)(asdf_value_t *value)

Type definition for predicate functions used in asdf_value_find and friends

Simply takes an arbitrary value as asdf_value_t* and returns true if the predicate matches the value.

struct asdf_find_iter_t

Iterator handle for depth/breadth-first tree search

After each successful call to asdf_value_find_iter_next, the value field holds the matching value and is valid until the next call to asdf_value_find_iter_next or asdf_find_iter_destroy. If the value must persist further, clone it with asdf_value_clone.

asdf_value_t *value

Current matching value

asdf_value_t *asdf_value_find(asdf_value_t *root, asdf_value_pred_t pred)

Traverse the tree breadth-first starting from root and return the first value matching pred

The caller owns the returned asdf_value_t* and must eventually destroy it with asdf_value_destroy. Returns NULL if no matching value was found.

Parameters:
  • rootasdf_value_t* handle for the root node to search from

  • pred – A predicate function to match the value to return; see asdf_value_pred_t

Returns:

The first matching asdf_value_t*, or NULL if not found

ASDF_DEPTH_FIRST

Alias for true for use with asdf_value_find_ex and asdf_find_iter_init_ex for added clarity

ASDF_BREADTH_FIRST

Alias for false for use with asdf_value_find_ex and asdf_find_iter_init_ex for added clarity

asdf_value_t *asdf_value_find_ex(asdf_value_t *root, asdf_value_pred_t pred, bool depth_first, asdf_value_pred_t descend_pred, ssize_t max_depth)

Extended version of asdf_value_find with additional traversal options

Like asdf_value_find but allows controlling traversal order, which container types to descend into, and the maximum search depth.

Parameters:
  • rootasdf_value_t* handle for the root node to search from

  • pred – A predicate function to match the value to return; see asdf_value_pred_t

  • depth_first – If true descend the tree in depth-first order; otherwise the tree is traversed breadth-first

  • descend_pred – Optional predicate (NULL means descend into all containers) controlling which containers are descended into

  • max_depth – Maximum depth to descend; -1 means no limit

Returns:

The first matching asdf_value_t*, or NULL if not found

static inline bool asdf_find_descend_mapping_only(asdf_value_t *value)

For use as the descend_pred argument to asdf_value_find_ex and asdf_find_iter_init_ex

Only descend into mappings (don’t iterate over sequences).

static inline bool asdf_find_descend_sequence_only(asdf_value_t *value)

For use as the descend_pred argument to asdf_value_find_ex and asdf_find_iter_init_ex

Only iterate over sequences and nested sequences (don’t descend into nested mappings).

asdf_find_descend_all

For use as the descend_pred argument to asdf_value_find_ex and asdf_find_iter_init_ex

Equivalent to passing NULL, meaning always descend into nested mappings and sequences.

asdf_find_iter_t *asdf_find_iter_init(asdf_value_t *root, asdf_value_pred_t pred)

Create an iterator that traverses the tree from root breadth-first, yielding values matching pred

The root must be a mapping or sequence; for scalar values use asdf_value_find directly.

Parameters:
Returns:

A new asdf_find_iter_t*, or NULL on failure

asdf_find_iter_t *asdf_find_iter_init_ex(asdf_value_t *root, asdf_value_pred_t pred, bool depth_first, asdf_value_pred_t descend_pred, ssize_t max_depth)

Like asdf_find_iter_init with additional traversal options

Parameters:
  • root – Container asdf_value_t* to search from

  • pred – Predicate selecting which values to yield

  • depth_first – If true traverse depth-first; otherwise breadth-first

  • descend_pred – Optional predicate controlling which containers to descend

  • max_depth – Maximum search depth; -1 means no limit

Returns:

A new asdf_find_iter_t*, or NULL on failure

bool asdf_value_find_iter_next(asdf_find_iter_t **iter)

Advance the find iterator to the next matching value

On success, asdf_find_iter_t.value is updated. When iteration is exhausted the iterator is freed and *iter is set to NULL.

Typical usage:

asdf_find_iter_t *iter = asdf_find_iter_init(root, pred);
while (asdf_value_find_iter_next(&iter)) {
    // iter->value is valid here; use asdf_value_clone if it must persist
}
Parameters:
  • iter – Pointer to the iterator handle; set to NULL on exhaustion

Returns:

true if a matching value was found; false when done

void asdf_find_iter_destroy(asdf_find_iter_t *iter)

Release resources held by an in-progress find iterator

Call this only when breaking out of iteration early. Safe to call with NULL.

Parameters: