Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/api/asdf/yaml.h.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
asdf/yaml.h
===========

.. autodoc:: include/asdf/yaml.h
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ def read_config_h() -> tuple[str, str, str]:

# libasdf identifiers that should be documented but aren't yet
('c:identifier', 'asdf_emitter_cfg_t'),
('c:identifier', 'asdf_event_t'),
('c:identifier', 'asdf_history_entry_t'),
('c:identifier', 'asdf_parser_cfg_t'),
]
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ headers.
:maxdepth: 2

api/asdf/extension.h
api/asdf/yaml.h


Resources
Expand Down
16 changes: 16 additions & 0 deletions include/asdf/core/ndarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,22 @@ ASDF_EXPORT uint64_t asdf_ndarray_nbytes(const asdf_ndarray_t *ndarray);
ASDF_EXPORT void *asdf_ndarray_data_alloc(asdf_ndarray_t *ndarray);


/**
* Allocate a temporary data buffer for an ndarray to be written to a file,
* with automatic cleanup after the write completes.
*
* Like `asdf_ndarray_data_alloc` but the allocated memory is freed
* automatically after `asdf_write_to` (or `asdf_close`) is called.
* Extension authors should use this instead of `asdf_ndarray_data_alloc`
* when building ndarrays inside a serialize callback.
*
* :param file: The `asdf_file_t *` to register the cleanup with
* :param ndarray: An `asdf_ndarray_t *` whose shape and datatype are already set
* :return: A `void *` to the zero-initialized buffer, or NULL on OOM
*/
ASDF_EXPORT void *asdf_ndarray_data_alloc_temp(asdf_file_t *file, asdf_ndarray_t *ndarray);


/**
* Free ndarray data allocated with `asdf_ndarray_data_alloc`
*
Expand Down
67 changes: 48 additions & 19 deletions include/asdf/file.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,19 +143,19 @@ static asdf_file_t *asdf_open_mem(const void *buf, size_t size);


#define ASDF__OPEN_1(source) \
_Generic((source), \
_Generic( \
(source), \
FILE *: asdf_open_fp(source, NULL), \
const char *: asdf_open_file(source, "r"), \
char *: asdf_open_file(source, "r"), \
void *: asdf_open_mem(NULL, 0) \
)
void *: asdf_open_mem(NULL, 0))
#define ASDF__OPEN_2(source, ...) \
_Generic((source), \
_Generic( \
(source), \
FILE *: asdf_open_fp, \
const char *: asdf_open_file, \
char *: asdf_open_file, \
const void *: asdf_open_mem \
)(source, __VA_ARGS__)
const void *: asdf_open_mem)(source, __VA_ARGS__)


/**
Expand Down Expand Up @@ -193,12 +193,12 @@ static asdf_file_t *asdf_open_mem(const void *buf, size_t size);
* `asdf_open_mem_ex` depending on the argument types
*/
#define asdf_open_ex(source, ...) /* NOLINT(readability-identifier-naming) */ \
_Generic((source), \
_Generic( \
(source), \
const char *: asdf_open_file_ex, \
char *: asdf_open_file_ex, \
FILE *: asdf_open_fp_ex, \
void *: asdf_open_mem_ex \
)(source, __VA_ARGS__)
void *: asdf_open_mem_ex)(source, __VA_ARGS__)

/**
* Opens an ASDF file for reading
Expand Down Expand Up @@ -237,44 +237,73 @@ static inline asdf_file_t *asdf_open_mem(const void *buf, size_t size) {


#define ASDF__WRITE_TO_1(source, dest) \
_Generic((dest), \
_Generic( \
(dest), \
const char *: asdf_write_to_file, \
char *: asdf_write_to_file, \
FILE *: asdf_write_to_fp \
)(file, dest)
FILE *: asdf_write_to_fp)(file, dest)


#define ASDF__WRITE_TO_2(source, dest, ...) asdf_write_to_mem(source, dest, __VA_ARGS__)


/**
* Write the contents of an ``asdf_file_t`` to a destination
*
* This is a type-generic macro that dispatches to one of the following based
* on the type and number of arguments after ``file``:
*
* * ``asdf_write_to(file, filename)`` -- where ``filename`` is a
* ``const char *`` or ``char *``: calls `asdf_write_to_file`
* * ``asdf_write_to(file, fp)`` -- where ``fp`` is a ``FILE *``: calls
* `asdf_write_to_fp`
* * ``asdf_write_to(file, buf, size)`` -- where ``buf`` is a ``void **`` and
* ``size`` is a ``size_t *``: calls `asdf_write_to_mem`
*
* :param file: The `asdf_file_t *` to write
* :param ...: Destination argument(s) -- see above
* :return: 0 on success, non-zero on failure
*/
#define asdf_write_to(file, ...) /* NOLINT(readability-identifier-naming) */ \
ASDF__PP_CAT(ASDF__WRITE_TO_, ASDF__PP_NARGS(__VA_ARGS__))(file, __VA_ARGS__)


/**
* Write the contents of the ``asdf_file_t`` to the given filesystem path
*
* :param file: The `asdf_file_t *` to write
* :param filename: Path to the output file; created or truncated as needed
* :return: 0 on success, non-zero on failure
*/
ASDF_EXPORT int asdf_write_to_file(asdf_file_t *file, const char *filename);


/**
* Write the contents of the ``asdf_file_t`` to the given writeable ``FILE *``
* stream
*
* :param file: The `asdf_file_t *` to write
* :param fp: An open, writeable ``FILE *`` stream
* :return: 0 on success, non-zero on failure
*/
ASDF_EXPORT int asdf_write_to_fp(asdf_file_t *file, FILE *fp);


/**
* Write the contents of the ``asdf_file_t`` to a memory buffer
*
* If the value of ``*buf`` is non-NULL then a user-provided buffer is assumed
* and its size is read from ``*size``. If the size is not large enough to
* hold the file, then it is simply truncated and a non-zero return value is
* returned.
* If ``*buf`` is non-NULL, a user-provided buffer is assumed and its size is
* read from ``*size``. If the buffer is not large enough to hold the file,
* the output is truncated and a non-zero value is returned.
*
* If ``*buf`` is NULL, a buffer is allocated with `malloc()` and a pointer to
* it is stored in ``*buf``; the allocated size is written to ``*size``. The
* caller is responsible for freeing the buffer with `free()`.
*
* Otherwise, memory is allocated with `malloc()` and the size of the buffer is
* returned into the ``size`` argument. The user is responsible for freeing
* the buffer with `free()`.
* :param file: The `asdf_file_t *` to write
* :param buf: Address of a ``void *`` buffer pointer (in/out)
* :param size: Address of a ``size_t`` holding the buffer size (in/out)
* :return: 0 on success, non-zero on failure
*/
ASDF_EXPORT int asdf_write_to_mem(asdf_file_t *file, void **buf, size_t *size);

Expand Down
159 changes: 153 additions & 6 deletions include/asdf/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,38 +406,135 @@ ASDF_EXPORT void asdf_mapping_item_destroy(asdf_mapping_item_t *item);
*/
typedef struct asdf_sequence asdf_sequence_t;

/** Return true if ``value`` holds a YAML sequence */
ASDF_EXPORT bool asdf_value_is_sequence(asdf_value_t *value);

/**
* Return the number of items in ``sequence``
*
* :param sequence: The `asdf_sequence_t *` to query
* :return: The number of items currently in the sequence
*/
ASDF_EXPORT int asdf_sequence_size(asdf_sequence_t *sequence);

/**
* 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.
*
* :param sequence: The `asdf_sequence_t *` to query
* :param index: Zero-based index; negative indices count from the end
* :return: The `asdf_value_t *` at that position, or ``NULL``
*/
ASDF_EXPORT asdf_value_t *asdf_sequence_get(asdf_sequence_t *sequence, int index);

/**
* 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.
*
* :param value: The generic `asdf_value_t *` to inspect
* :param out: Receives the `asdf_sequence_t *` on success
* :return: ``ASDF_VALUE_OK`` on success, otherwise an `asdf_value_err_t` error
*/
ASDF_EXPORT asdf_value_err_t asdf_value_as_sequence(asdf_value_t *value, asdf_sequence_t **out);

/**
* Return the generic `asdf_value_t *` view of a sequence
*
* The returned pointer shares ownership with ``sequence``; the caller must
* not free it independently.
*
* :param sequence: The `asdf_sequence_t *` to wrap
* :return: The same object as a generic `asdf_value_t *`
*/
ASDF_EXPORT asdf_value_t *asdf_value_of_sequence(asdf_sequence_t *sequence);

/**
* 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.
*
* :param file: The `asdf_file_t *` that will own the sequence
* :return: A new `asdf_sequence_t *`, or ``NULL`` on failure
*/
ASDF_EXPORT asdf_sequence_t *asdf_sequence_create(asdf_file_t *file);

/**
* Set the YAML node style used when serializing ``sequence``
*
* :param sequence: The `asdf_sequence_t *` to modify
* :param style: The desired `asdf_yaml_node_style_t` (e.g. block or flow)
*/
ASDF_EXPORT void asdf_sequence_set_style(asdf_sequence_t *sequence, asdf_yaml_node_style_t style);

/**
* 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.
*
* :param sequence: The `asdf_sequence_t *` to free
*/
ASDF_EXPORT void asdf_sequence_destroy(asdf_sequence_t *sequence);


/** Opaque struct holding sequence iterator state */
typedef void *asdf_sequence_iter_t;

/**
* Initialize an `asdf_sequence_iter_t` to its starting state
*
* Call this once before the first call to `asdf_sequence_iter`.
*
* :return: An initialized `asdf_sequence_iter_t`
*/
ASDF_EXPORT asdf_sequence_iter_t asdf_sequence_iter_init(void);


/**
* Iterate over a sequence value
* Advance a sequence iterator and return the next value
*
* .. todo::
* Typical usage::
*
* Finish documenting me.
* asdf_sequence_iter_t iter = asdf_sequence_iter_init();
* asdf_value_t *val;
* while ((val = asdf_sequence_iter(seq, &iter)) != NULL) {
* // use val ...
* }
*
* Returns ``NULL`` when iteration is exhausted.
*
* :param sequence: The `asdf_sequence_t *` to iterate over
* :param iter: Pointer to the iterator state; updated on each call
* :return: The next `asdf_value_t *` in the sequence, or ``NULL`` when done
*/
ASDF_EXPORT asdf_value_t *asdf_sequence_iter(asdf_sequence_t *sequence, asdf_sequence_iter_t *iter);


/**
* Append values to sequences
* Append a value to a sequence
*
* .. todo::
* ``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.
*
* Document these.
* ``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_EXPORT asdf_value_err_t asdf_sequence_append(asdf_sequence_t *sequence, asdf_value_t *value);
ASDF_EXPORT asdf_value_err_t
Expand Down Expand Up @@ -467,6 +564,56 @@ ASDF_EXPORT asdf_value_err_t
asdf_sequence_append_sequence(asdf_sequence_t *sequence, asdf_sequence_t *value);


/**
* 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_EXPORT asdf_sequence_t *asdf_sequence_of_null(asdf_file_t *file, int size);

ASDF_EXPORT asdf_sequence_t *asdf_sequence_of_string(
asdf_file_t *file, const char *const *arr, const size_t *lens, int size);
ASDF_EXPORT asdf_sequence_t *asdf_sequence_of_string0(
asdf_file_t *file, const char *const *arr, int size);

ASDF_EXPORT asdf_sequence_t *asdf_sequence_of_bool(asdf_file_t *file, const bool *arr, int size);

ASDF_EXPORT asdf_sequence_t *asdf_sequence_of_int8(asdf_file_t *file, const int8_t *arr, int size);
ASDF_EXPORT asdf_sequence_t *asdf_sequence_of_int16(
asdf_file_t *file, const int16_t *arr, int size);
ASDF_EXPORT asdf_sequence_t *asdf_sequence_of_int32(
asdf_file_t *file, const int32_t *arr, int size);
ASDF_EXPORT asdf_sequence_t *asdf_sequence_of_int64(
asdf_file_t *file, const int64_t *arr, int size);

ASDF_EXPORT asdf_sequence_t *asdf_sequence_of_uint8(
asdf_file_t *file, const uint8_t *arr, int size);
ASDF_EXPORT asdf_sequence_t *asdf_sequence_of_uint16(
asdf_file_t *file, const uint16_t *arr, int size);
ASDF_EXPORT asdf_sequence_t *asdf_sequence_of_uint32(
asdf_file_t *file, const uint32_t *arr, int size);
ASDF_EXPORT asdf_sequence_t *asdf_sequence_of_uint64(
asdf_file_t *file, const uint64_t *arr, int size);

ASDF_EXPORT asdf_sequence_t *asdf_sequence_of_float(asdf_file_t *file, const float *arr, int size);
ASDF_EXPORT asdf_sequence_t *asdf_sequence_of_double(
asdf_file_t *file, const double *arr, int size);


/**
* Remove a value from a sequence and return the removed value
*
Expand Down
Loading
Loading