Lattice has one main function, and two other functions which call the main function with predefined arguments. The functions are identical aside from their output parameters, which substitute the emission function and context for a different type.
size_t lattice(
const char *template,
const void *root,
lattice_emit emit,
void *ctx,
lattice_iface iface,
lattice_opts opts,
lattice_error **err
);
lattice
is the main function: it is the main entrypoint into the template
processor. It rarely needs to be invoked directly, instead being called via the
other functions.
template
: the template, as a null-terminated ASCII string.root
: the root data object to format the template with.emit
: the output callback - seelattice_emit
.ctx
: the context to pass to the callback along with the data.iface
: the interface - seelattice_iface
.opts
: running options - seelattice_opts
.err
: a pointer to a variable to be set on error if non-null.
When no error occurs, all functions return the number of bytes written out.
size_t lattice_buffer(
const char *template,
const void *root,
char **buffer,
lattice_iface iface,
lattice_opts opts,
lattice_error **err
);
lattice_buffer
outputs the data to a string buffer by using its own emission
function.
buffer
: a pointer to a variable to be set to afree
able null-terminated string containing the output.
size_t lattice_file(
const char *template,
const void *root,
FILE *file,
lattice_iface iface,
lattice_opts opts,
lattice_error **err
);
lattice_file
outputs the data to a file by using its own emission function.
file
: a standard C file pointer to write output to.
The primary functions take an arbitrary void *
and a lattice_iface
in order
to generalise the functions over any JSON type. Considering this is impractical
for most uses, functions are provided for three common C JSON libraries, which
replace the void *
with the JSON type and pass their own implementation of
lattice_iface
. The functions place the name of the library (one of cjson
,
jsonc
, or jansson
) after lattice
(for example lattice_cjson_file
) and
have the same signature and functionality, except for the aforementioned
modifications.
typedef struct lattice_opts {
const char * const *search;
char *(*resolve)(const char *);
char *(*escape)(const char *);
bool ignore_emit_zero;
...
} lattice_opts;
lattice_opts
specifies the options that affect the way the template is
processed. All of the fields are optional, and a zero-filled struct represents
a valid default configuration.
The resolve
and search
fields combine specially to determine the behaviour
of the include resolution system:
search is NULL |
search is non-NULL |
|
---|---|---|
resolve is NULL |
Search CWD to obtain path | Search paths in search to obtain path |
resolve is non-NULL |
Call resolve to obtain path |
Call resolve to obtain contents |
search
: null, or a pointer to a null-terminated array of directories to search to find a requested path.resolve
: null, or a function returning afree
able string equating to either the resolved path or contents of the include passed as the parameter.escape
: null, or a function returning afree
able string which is the escaped version of the data passed as the parameter; by default, uses HTML escaping (replaces'
,"
,<
,>
, and&
).ignore_emit_zero
: if theemit
function returns zero, by default it is interpreted as an error; if this field is set totrue
, it will be ignored.
typedef struct lattice_error {
int line; char *file;
lattice_error_code code;
char *message;
} lattice_error;
lattice_error
describes an error that has occurred. lattice_error
s returned
must not be mutated, and should be freed with lattice_error_free
.
line
: the line on which the error occurred, or a nonsense value below 1.file
: null, or the included file in which the error occurred.code
: the type of error - see the error index.message
: a null-terminated ASCII string describing the error. These are subject to change without notice.
typedef size_t (*lattice_emit)(const char *data, void *ctx);
lattice_emit
is a convenience alias for the function type used for arbitrary
output.
data
: a constant null-terminated ASCII string containing the data to be written.ctx
: a context passed into thelattice
function.
An emission function should return the number of bytes written out. In case of error, it should return zero (the emission function should not be called with an empty string).
typedef enum lattice_type {
LATTICE_TYPE_NULL,
LATTICE_TYPE_BOOLEAN,
LATTICE_TYPE_NUMBER,
LATTICE_TYPE_STRING,
LATTICE_TYPE_ARRAY,
LATTICE_TYPE_OBJECT,
} lattice_type;
typedef union lattice_index {
size_t array;
const char *object;
} lattice_index;
typedef union lattice_value {
bool boolean;
double number;
const char *string;
} lattice_value;
typedef struct lattice_iface {
void *(*parse)(const char *, size_t);
char *(*print)(const void *);
void (*free)(void *);
void *(*create)(lattice_type, lattice_value);
void *(*clone)(const void *);
lattice_type (*type)(const void *);
lattice_value (*value)(const void *);
size_t (*length)(const void *);
void *(*get)(const void *, lattice_index);
void (*add)(void *, const char *, void *);
void (*keys)(const void *, const char *[]);
} lattice_iface;
lattice_iface
(and associated types) is used to define custom JSON types. Most
users do not need to use it.
parse
: returns an allocated JSON object, parsed from the JSON string in the first argument; if the second argument is zero, it is null-terminated, otherwise that long.print
: returns afree
able null-terminated string, representing the JSON string for the passed object.free
: recursively frees the passed JSON object.create
: creates a new JSON object with the given type and value (for primitives; containers are initialised to be empty).clone
: allocates a deep copy of the passed JSON object.type
: returns the type of the passed JSON object.value
: if the passed JSON object is primitive, returns its value.length
: if the passed JSON object is a string, array, or object, returns its length.get
: returns the indexed item from the container. The return value will not be freed.add
: adds an item to the container (for arrays, the key will be null).keys
: initialises the string array passed as the second argument to the keys of the object passed as the first argument.
Errors are defined in the enum lattice_error_code
.
Returned when an emission function returns zero, or an IO error occurs (such as when a filesystem call fails whilst resolving an include).
Returned when options passed to lattice
are invalid.
Returned when an issue occurs with the JSON interface.
Returned when there is invalid syntax in the template, regardless of the context in which it takes place (macro or expression).
Returned when there is an incorrect JSON type for the expected value.
Returned when there is an invalid JSON value for the expected value.
Returned when there is reference to a nonexistent key.
Returned when there is an error whilst trying to resolve or read an include, including if a reoslution function returns null.
Four macro constants are defined:
LATTICE_VERSION_MAJOR
: the major version.LATTICE_VERSION_MINOR
: the minor version.LATTICE_VERSION_PATCH
: the patch version.LATTICE_VERSION_STR
: the full version, represented as a string.