We have 2 APIs, the C++ and the C API. Both are explained in this page.
C++ API
The C++ API is part of the Generator.hpp
header. Most
functionality is contained under the UTTE::Generator
class,
which is used to parse a document.
Loading a document
To load a document, initialise the UTTE::Generator
class
using the default constructor, then call the loadFromFile
or loadFromString
functions like this:
::Generator generator{};
UTTE.loadFromFile("test.tmpl"); generator
The loadFromFile
and loadFromString
functions both have the same signature. They receive a string which will
be the file location or the buffer to be used.
Both of these functions return an InitialisationResult
struct, which looks like this:
enum InitialisationResult
{
= 0,
UTTE_INITIALISATION_RESULT_SUCCESS = 1,
UTTE_INITIALISATION_RESULT_INVALID_UTF8 = 2,
UTTE_INITIALISATION_RESULT_INVALID_FILE };
It is used to check if there were any errors when trying to initialise the generator.
Parsing a document
Once a document is loaded, you can parse it with the
parse
member function. It returns a struct of type
ParseResult
, which looks like this:
struct ParseResult
{
;
ParseResultStatus statusconst std::string* result;
;
Variable _internalBuffer};
The resulting string is the result
member, which is a
pointer to an std::string
.
The status
member is of type
ParseResultStatus
, which looks like this:
enum ParseResultStatus
{
= 0,
UTTE_PARSE_STATUS_SUCCESS = 1,
UTTE_PARSE_STATUS_OUT_OF_BOUNDS = 2,
UTTE_PARSE_STATUS_EXPECTED_TERMINATION = 3,
UTTE_PARSE_STATUS_INVALID_VALUE = 4,
UTTE_PARSE_STATUS_INVALID_TYPE };
It can be used to do error checking.
Finally, the _internalBuffer
variable contains rubbish
intermediate internal data. You should not use it.
Adding additional variables and functions
You can add additional variables and functions by calling the
pushVariable
and pushFunction
members,
respectively.
Variables
The pushVariable
function takes a constant reference to
a Variable
struct and a name for the variable. The
Variable
struct looks like this:
struct Variable
{
std::string value;
= UTTE_VARIABLE_TYPE_HINT_NORMAL;
VariableTypeHint type = UTTE_PARSE_STATUS_SUCCESS;
ParseResultStatus status
bool _internalBoolComment = false;
};
Its members are the following:
value
- The value of the variableVariableTypeHint
- A hint to the type of the variablestatus
- The status of a variable when returning from a function. Used to tell the parser to shut down on error_internalBoolComment
- Whether to treat the variable like a comment. Do not use
Tip
When returning an error from a function, use the
UTTE_ERROR(x)
macro. It only takes a single argument, which
is the ParseResultStatus
enum.
The VariableTypeHint
enum looks like this:
enum VariableTypeHint
{
= 0,
UTTE_VARIABLE_TYPE_HINT_NORMAL = 1,
UTTE_VARIABLE_TYPE_HINT_ARRAY = 2,
UTTE_VARIABLE_TYPE_HINT_MAP = 3,
UTTE_VARIABLE_TYPE_HINT_FUNCTION };
A variable set to UTTE_VARIABLE_TYPE_HINT_NORMAL
is a
simple string.
The pushVariable
function also returns a reference to a
Function
struct, which was pushed to the function registry,
as variables are treated as functions.
The Function
struct looks like this:
struct Function
{
std::string name;
std::function<Func> function = [](std::vector<Variable>&, UTTE::Generator*) -> Variable{ return {}; };
};
The name
member is the name of the function, while the
function
member is the actual function pointer to be
called. It is of type std::function<Func>
, where
Func
is a type definition of
Variable(std::vector<Variable>&, UTTE::Generator*)
.
Tip
If you want to change the value of a variable from a custom function,
use the UTTE_VARIABLE_SET_NEW_VAL
macro like this:
(key, a, a.first, UTTE_VARIABLE_TYPE_HINT_NORMAL); UTTE_VARIABLE_SET_NEW_VAL
In this example, the arguments are like this:
key
- TheFunction&
returned bypushVariable
a
- A struct to pass to the internal lambda through the capture, in this case anstd::pair
a.first
- The new value of the variableUTTE_VARIABLE_TYPE_HINT_NORMAL
- The new type of the variable
Functions
Functions can be added by calling the pushFunction
function. It takes a constant reference to a Function
struct and returns a reference to itself, but in the function
registry.
Updating arbitrary variables and functions
Generally, it's preferable to keep references to the values returned
by pushVariable
and pushFunction
, but
sometimes it's not possible. The setVariable
and
setFunction
members of Generator
can be used
to update a function or variable from a name.
They both return void and their first argument is the name of the
function or variable as a string. The second argument is a
const Variable&
or a
const std::function<Func>&
, for
setVariable
and setFunction
respectively.
Creating arrays and maps
To push array and map variables to the generator, use the
makeArray
and makeMap
static member functions
of the Generator
class. They take a
const std::vector<std::string>&
and
const std::map<std::string, std::string>&
respectively and both return a Variable
struct that can be
used directly with pushVariable
Returning arrays and maps from custom functions
When in a custom function, it may be convenient to return an array or map. This, however, requires you to store the given map or array beyond the lifetime of the given function. Instead of making you create your own custom registry to store these variables, the parser can create and store them for you automatically.
The UTTE::Generator::requestArrayWithGC
and
UTTE::Generator::requestMapWithGC
functions return a
reference to an array and map, respectively. The underlying variables
have the same lifetime as the generator.
Getting the internal functions registry
Some special functions may need more control over what functions are
part of the registry. For systems that want tighter security, this may
even mean removing components of the standard library. To get full
access to the functions registry call
UTTE::Generator::getFunctionsRegistry
.
It returns a reference to an array of
UTTE::Function
.
C API
The C API has a lot of overlap with the C++ one, therefore, make sure to read through the entire C++ API part of the page, before continuing to read about the C API. This guide will only cover parts of the API that are different from the C++ one.
Most functions that are part of the C API are the same as the one in
the C++ API, except that the ::
operator is replaced by a
_
, making the C++ function
UTTE::Generator::loadFromFile
into the C function
UTTE_CGenerator_loadFromFile
.
Creating the generator
In the C API, the generator is created by calling the
UTTE_CGenerator_Allocate
function. It returns a pointer of
type UTTE_CGenerator
. Since C generators are allocated on
the heap, this handle needs to be freed using the
UTTE_CGeneratorFree
function.
All functions that are related to the generator take a
UTTE_CGenerator*
as their first argument.
The UTTE_CParseResult
struct
The C alternative to the UTTE::ParseResult
struct is
UTTE_CParseReult
. It is returned by
UTTE_Generator_parse
and looks like this:
struct UTTE_CParseResult
{
;
UTTE_ParseResultStatus statusconst char* result;
};
The only significant difference is the replacement of
utte_string
with const char*
for the
result
member
Pushing variables and functions
Variables
To push a variable, call UTTE_CGenerator_pushVariable
.
It takes a pointer to the generator, as well as a pointer to a
UTTE_CVariable
struct and a name as a
const char*
.
The UTTE_CVariable
struct is the alternative of the C++
UTTE::Variable
struct, and looks like this:
struct UTTE_CVariable
{
const char* value;
;
UTTE_VariableTypeHint typebool bDeallocate;
;
UTTE_ParseResultStatus status};
The difference is that value
is now a
const char*
and that a new member called
bDeallocate
is added. If the value
member is
heap-allocated, you can set bDeallocate
to automatically
free it after use when calling the following functions:
UTTE_CGenerator_pushVariable
UTTE_CGenerator_tryFreeCVariable
The pushVariable
functions a
UTTE_CFunctionHandle*
, which is a handle to a
UTTE::Function
in the functions' registry. The following
functions take it:
UTTE_CGenerator_modify
- Given a Function handle and aUTTE_CFunction
struct as arguments, will change the underlying function to the data of theUTTE_CFunction
argument. If thename
field of theUTTE_CFunction
struct is set to an empty string, the name of the function will not be changedUTTE_CGenerator_getName
- Given a Function handle, returns the name of the function
The UTTE_CFunction
struct is the C alternative of the
UTTE::Function
struct and looks like this:
struct UTTE_CFunction
{
const char* name;
;
UTTE_CFunctionCallback functionbool bDeallocate;
};
If name
is set to a heap-allocated value, setting
bDeallocate
to true
will free it in the
following functions:
UTTE_CGenerator_modify
UTTE_CGenerator_pushFunction
The function
field is of type
UTTE_CFunctionCallback
, which has the following signature:
UTTE_CVariable()(UTTE_CVariable*, size_t size, UTTE_CGenerator*)
.
Functions
Functions are pushed using the
UTTE_CGenerator_pushFunction
function. The second argument
needs to be a pointer to a UTTE_CFunction
struct. It
returns a UTTE_CFunctionHandle*
, like
pushVariable
.
Setting variables and functions
The UTTE_CGenerator_setVariable
and
UTTE_CGenerator_setFunction
functions allow the user to
iterate the internal generator registry for a function using a name. If
found, its data is replaced by the given UTTE_CVariable*
and UTTE_CFunctionCallback
arguments, respectively.
Both functions return true
if a function is found and
false
if not.
UTTE_CGenerator_setVariable
will deallocate the
value
field of the UTTE_CVariable
struct if
the bDeallocate
boolean is set to true
.
Generating arrays
To generate an array, call the UTTE_CGenerator_makeArray
function. It takes a char**
for the array and a
size_t
for its size.
It returns a UTTE_CVariable
struct with a heap-allocated
value
. The bDeallocate
member is set to
true
, so passing it to
UTTE_CGenerator_pushVariable
will free the memory
automatically. Alternatively, use
UTTE_CGenerator_tryFreeCVariable
to free it manually.
Generating maps
To generate a map, call the UTTE_CGenerator_makeMap
function. It takes a UTTE_CPair*
for the array and a
size_t
for its size.
The UTTE_CPair
struct stores a key and a value and looks
like this:
struct UTTE_CPair
{
char* key;
char* val;
};
It returns a UTTE_CVariable
struct with a heap-allocated
value
. The bDeallocate
member is set to
true
, so passing it to
UTTE_CGenerator_pushVariable
will free the memory
automatically. Alternatively, use
UTTE_CGenerator_tryFreeCVariable
to free it manually.