UJO Data Object Notation  0.9.1
C API
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
Introduction to libUJO-c

All examples in this introduction contain only the code lines to explain a special aspect of the API. Important things like error handling are left out in favor of better readability.

How to use the library

The libUJO-c API is a set of functions operating on handles of objects. In particular these are an UJO Writer, an UJO Reader or an UJO Element. After installing the library you can import ujo into your project.

import "ujo.h"

The library does not need any kind of initialization. You can start creating your first UJO Document.

Create a first UJO Document

To create an UJO document a writer instance is required. It is created with ujo_new_writer(). The first data element in UJO is a container. Trying to add an atomic value at the document root will return an error message. The example uses a list as top level container. Any other container like dictionary or table can be used as well.

ujo_writer* ujow;
ujoByte* data;
size_t datasize;
ujo_new_memory_writer(&ujow); // create the writer
// add a list with some numeric values
ujo_writer_add_int64(ujow, 12345678); // signed int64
ujo_writer_add_float32(ujow, (float32_t)3.14); // single precision float
ujo_writer_add_float64(ujow, 9.81); // double precision float
ujo_writer_list_close(ujow); // closing the list closes the documt
// get the buffer
ujo_writer_get_buffer(ujow, &data, &datasize);
// !!! do something with the data

Closing the top level container finalizes the document. If the top level container is closed, no additional values can be added. The function ujo_writer_get_buffer() returns the document as a buffer, an array of bytes. It does not create a copy of the buffer, but returns a pointer to buffer managed by the writer. You need to make sure that the writer is not deleted with ujo_free_writer()as long as operations are performed on the data.

Currently the UJO_MEMORY option for writing and reading documents is the only available. The implementation of file and stream support is subject to version 1.1 of this library.

Read UJO data

A buffer with UJO data can be traversed using a reader instance. The reader is created with ujo_new_reader(). The example in the previous section shows how to create a buffer with an UJO document. Before it can be traversed by the reader the buffer need sto be passed to the reader using the ujo_reader_set_buffer() function. The reader is creating a copy of the data and the original buffer can be disposed.

ujo_reader* ujor;
ujoByte* data;
size_t datasize;
ujo_element* element;
ujoBool eod;
ujoTypeId type;
// !!! get the UJO document buffer from anywhere
ujo_reader_set_buffer(ujor, data, datasize);
// the first next method
ujo_reader_get_first(ujor, &element, &eod);
// repeat reading elements from the document until eod==ujoTrue
while(!eod) {
ujo_element_get_type(element, &type); //read the element type
switch(type) {
printf("-- container closed\n");
break;
// containers
printf("-- map found\n");
break;
printf("-- list found\n");
break;
// more type containers ...
// atomic types
printf("int64 found\n");
break;
printf("int32 found\n");
break;
// more atomic types ...
}
ujo_free_element(element);
ujo_reader_get_next(ujor, &element, &eod);
}
ujo_free_reader(ujor); // dispose the reader and free the buffer

The example uses the functions ujo_reader_get_first() and ujo_reader_get_next() to traverse through the document. Another method to get the elements from the document is a callback function and a call to ujo_reader_parse().

Traversing a document will result in a sequence of UJO elements. An element can be an atomic value or a marker to indicate the start or end of a container. For example the start of a list is indicated by an element of the type UJO_TYPE_LIST and any container or sequence of values is closed with UJO_TERMINATOR.

Using a callback to read data

A callback function to retreive the elements found in an UJO document is defined according to the specification of ujoOnElementFunc.

typedef ujoError (*ujoOnElementFunc)(ujo_element* element, ujoPointer data);

This example shows a callback that list types and values of each element found in the document.

ujoError myOnElement (ujo_element *element, ujoPointer data){
ujoBool bVal;
int64_t i64Val;
int32_t i32Val;
int16_t i16Val;
int8_t i8Val;
float64_t f64Val;
float32_t f32Val;
char* cstrVal;
uint8_t* bindata;
uint32_t n;
ujoTypeId type;
ujoTypeId stype;
ujoError err = ujo_element_get_type(element, &type);
print_return_ujo_err(err,"ujo_element_get_type");
switch(type)
{
printf("-- container closed\n");
break;
ujo_element_get_int64(element, &i64Val);
printf("int64 \"%lld\"found\n", i64Val);
break;
ujo_element_get_int32(element, &i32Val);
printf("int32 \"%d\"found\n", i32Val);
break;
ujo_element_get_int16(element, &i16Val);
printf("int16 \"%hd\"found\n", i16Val);
break;
ujo_element_get_int8(element, &i8Val);
printf("int8 \"%d\"found\n", i8Val);
break;
printf("None found\n");
break;
ujo_element_get_float32(element, &f32Val);
printf("float32 \"%lf\"found\n", f32Val);
break;
ujo_element_get_float64(element, &f64Val);
printf("float64 \"%lf\"found\n", f64Val);
break;
ujo_element_get_bool(element, &bVal);
printf("bool \"%d\"found\n", bVal == ujoTrue);
break;
ujo_element_get_string_type(element, &stype);
if (stype == UJO_SUB_STRING_C)
{
ujo_element_get_string_c(element, &cstrVal, &n);
printf("string \"%s\"found\n", cstrVal);
} else {
printf("string found\n");
}
break;
ujo_element_get_binary(element, &stype, &bindata, &n);
printf("binary with \"%d\" bytes found\n", n);
break;
printf("List found\n");
break;
printf("Map found\n");
break;
printf("Table found\n");
break;
}
return UJO_SUCCESS;
};

The example from the previous section can be modified to prepare the reader and traverse the document by calling the ujoOnElementFunc function.

ujo_reader* ujor;
ujoByte* data;
size_t datasize;
// !!! get the UJO document buffer from anywhere
ujo_reader_set_buffer(ujor, data, datasize);
ujo_reader_set_on_element(ujor, myOnElement, ujor);
ujo_free_reader(ujor); // dispose the reader and free the buffer

Error Handling

UJO API functions return an error code. If no error was found UJO_SUCCESS is returned. Any value different from UJO_SUCCESS need special attention. The example shows a simple error handling.

ujoError err
err = ujo_new_writer(UJO_MEMORY, &ujow);
if (err != UJO_SUCCESS){
printf(UJO error found":error %i\n", err);
return ujoFalse;
}
return ujoTrue;