Update doc

This commit is contained in:
Patrick Pelissier committed 2019-06-05 22:05:02 +02:00
1 parent 42f807d64b
commit 8eb95d0cdc
1 file changed
+282 -256
+282 -256
View File
@@ -5140,6 +5140,272 @@ The assertion is kept in programs built in release mode.
The default is to abort the execution.
#### Generic Serialization objects.
A [serialization](https://en.wikipedia.org/wiki/Serialization) is the process of translating
data structures into a format that can be stored or transmitted.
When the resulting format is reread and translated,
it creates a semantically identical clone of the original object.
A generic serialization object is an object that takes a C object (boolean, integer, float,
structure, union, pointer, array, list, hashmap, ...) and outputs it into a serialization way through
the following defined interface that defined the format of the serialization and where it is
physically output.
The M\*LIB containers define the methods \_out\_serial and \_in\_serial
if the underlying types define theses methods over the operators OUT\_SERIAL and IN\_SERIAL.
The methods for the basic C types (int, float, ...) are also defined (but only
in C11 due to technical limitation).
The methods \_out\_serial and \_in\_serial will request the generic serialization object
to serialize their current object:
* calling the interface of the generic serialization object if needed,
* performing recursive call to serialize the contained-objects.
The final output of this serialization can be a FILE or a string.
Two kinds of serialization objects exist: one for input and one
for output. The serialization is fully recursive and can be seen as a collection of token.
The only constraint is that what is output by the output serialization object
shall be able to be parsed by the input serialization object.
The serialization input object is named as m\_serial\_read\_t, defined in m-core.h as a structure
(of array of size 1) with the following fields:
* interface: a pointer to the constant m\_serial\_read\_interface\_s structure that defines all
methods that operate on this object to parse it. The instance has to be customized for the needs of the
wanted serialization.
* data: a table of M\_SERIAL\_MAX\_DATA\_SIZE of C types (boolean, integer, size or pointer).
This data is used to store the needed data for the methods.
This is pretty much like a pure virtual interface object in C++. The interface has to defines
the following fields with the following definition:
* read\_boolean:
Read from the stream 'serial' a boolean.
Set '*b' with the boolean value if it succeeds.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise
* read\_integer:
Read from the stream 'serial' an integer that can be represented with 'size_of_type' bytes.
Set '*i' with the integer value if it succeeds.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise.
* read\_float:
Read from the stream 'serial' a float that can be represented with 'size_of_type' bytes.
Set '*r' with the float value if it succeeds.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise.
* read\_string:
Read from the stream 'serial' a string.
Set 's' with the string if it succeeds.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise
* read\_array\_start:
Start reading from the stream 'serial' an array (which is defined as a sequential collection of object).
Set '*num' with the number of elements, or 0 if it is not known.
Initialize the object 'local' so that it can be used by the serialization object to serialize the array.
('local' is an unique local serialization object of the array).
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the parsing of the array can continue (the array is not empty),
M\_SERIAL\_OK\_DONE if it succeeds and the array ends (the array is empty),
M\_SERIAL\_FAIL otherwise.
* read\_array\_next:
Continue reading from the stream 'serial' an array using 'local' to load / save data if needed.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the array can continue (the array end is still not reached),
M\_SERIAL\_OK\_DONE if it succeeds and the array ends,
M\_SERIAL\_FAIL otherwise.
* read\_map_start:
Start reading from the stream 'serial' a map (an associative array).
Set '*num' with the number of elements, or 0 if it is not known.
Initialize 'local' so that it can be used to serialize the map.
('local' is an unique serialization object of the map).
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the map continue,
M\_SERIAL\_OK\_DONE if it succeeds and the map ends (the map is empty),
M\_SERIAL\_FAIL otherwise
* read\_map\_value:
Continue reading from the stream 'serial' the value separator token (if needed)
using 'local' to load / save data if needed.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the map continue,
M\_SERIAL\_FAIL otherwise
* read\_map_next:
Continue reading from the stream 'serial' a map.
using 'local' to load / save data if needed.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the map continue,
M\_SERIAL\_OK\_DONE if it succeeds and the map ends,
M\_SERIAL\_FAIL otherwise
* read\_tuple\_start:
Start reading a tuple from the stream 'serial'.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the tuple continues,
M\_SERIAL\_FAIL otherwise
* read\_tuple\_id:
Continue reading a tuple (a structure) from the stream 'serial'.
using 'local' to load / save data if needed.
Set '*id' with the corresponding index of the table 'field_name[max]'
associated to the parsed field in the stream.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the tuple continues,
Return M\_SERIAL\_OK\_DONE if it succeeds and the tuple ends,
M\_SERIAL\_FAIL otherwise
* read\_variant\_start:
Start reading a variant (an union) from the stream 'serial'.
Set '*id' with the corresponding index of the table 'field_name[max]'
associated to the parsed field in the stream.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the variant continues,
Return M\_SERIAL\_OK\_DONE if it succeeds and the variant ends(variant is empty),
M\_SERIAL\_FAIL otherwise
* read\_variant\_end:
End reading a variant from the stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds and the variant ends,
M\_SERIAL\_FAIL otherwise
The serialization output object is named as m\_serial\_write\_t, defined in m-core.h as a structure
(of array of size 1) with the following fields:
* interface: a pointer to the constant m\_serial\_write\_interface\_s structure that defines all
methods that operate on this object to output it. The instance has to be customized for the needs of the
wanted serialization.
* data: a table of M\_SERIAL\_MAX\_DATA\_SIZE of C types (boolean, integer, size or pointer).
This data is used to store the needed data for the methods.
This is pretty much like a pure virtual interface object in C++. The interface has to defines
the following fields with the following definition:
* write\_boolean:
Write the boolean 'b' into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write_\integer:
Write the integer 'data' of 'size_of_type' bytes into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_float:
Write the float 'data' of 'size_of_type' bytes into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_string:
Write the null-terminated string 'data'into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_array\_start:
Start writing an array of 'number_of_elements' objects into the serial stream 'serial'.
If 'number_of_elements' is 0, then either the array has no data,
or the number of elements of the array is unkown.
Initialize 'local' so that it can be used to serialize the array
(local is an unique serialization object of the array).
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_array\_next:
Write an array separator between elements of an array into the serial stream 'serial' if needed.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_array\_end:
End the writing of an array into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_map\_start:
Start writing a map of 'number_of_elements' pairs of objects into the serial stream 'serial'.
If 'number_of_elements' is 0, then either the map has no data,
or the number of elements is unkown.
Initialize 'local' so that it can be used to serialize the map
(local is an unique serialization object of the map).
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_map\_value:
Write a value separator between element of the same pair of a map into the serial stream 'serial' if needed.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_map\_next:
Write a map separator between elements of a map into the serial stream 'serial' if needed.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_map\_end:
End the writing of a map into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_tuple\_start:
Start writing a tuple into the serial stream 'serial'.
Initialize 'local' so that it can serial the tuple
(local is an unique serialization object of the tuple).
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_tuple\_id:
Start writing the field named field_name[index] of a tuple into the serial stream 'serial'.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_tuple\_end:
End the write of a tuple into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_variant\_start:
Start writing a variant into the serial stream 'serial'.
If index <= 0, the variant is empty.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise
Otherwise, the field 'field_name[index]' will be filled.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_variant\_end:
End Writing a variant into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
M\_SERIAL\_MAX\_DATA\_SIZE can be overloaded before including any M\*LIB header
to increase the size of the generic object. The maximum default size is 4 fields.
The full C definition are:
// Serial return code
typedef enum m_serial_return_code_e {
M_SERIAL_OK_DONE = 0, M_SERIAL_OK_CONTINUE = 1, M_SERIAL_FAIL = 2
} m_serial_return_code_t;
// Different types of types that can be stored in a serial object to represent it.
typedef union m_serial_ll_u {
bool b;
int i;
size_t s;
void *p;
} m_serial_ll_t;
/* Object to handle the construction of a serial write/read of an object
that needs multiple calls (array, map, ...)
It is common to all calls to the same object */
typedef struct m_serial_local_s {
m_serial_ll_t data[M_SERIAL_MAX_DATA_SIZE];
} m_serial_local_t[1];
// Object to handle the generic serial read of an object.
typedef struct m_serial_read_s {
const struct m_serial_read_interface_s *interface;
m_serial_ll_t data[M_SERIAL_MAX_DATA_SIZE];
} m_serial_read_t[1];
// Interface exported by the serial read object.
typedef struct m_serial_read_interface_s {
m_serial_return_code_t (*read_boolean)(m_serial_read_t serial,bool *b);
m_serial_return_code_t (*read_integer)(m_serial_read_t serial, long long *i, const size_t size_of_type);
m_serial_return_code_t (*read_float)(m_serial_read_t serial, long double *f, const size_t size_of_type);
m_serial_return_code_t (*read_string)(m_serial_read_t serial, struct string_s *s);
m_serial_return_code_t (*read_array_start)(m_serial_local_t local, m_serial_read_t serial, size_t *s);
m_serial_return_code_t (*read_array_next)(m_serial_local_t local, m_serial_read_t serial);
m_serial_return_code_t (*read_map_start)(m_serial_local_t local, m_serial_read_t serial, size_t *);
m_serial_return_code_t (*read_map_value)(m_serial_local_t local, m_serial_read_t serial);
m_serial_return_code_t (*read_map_next)(m_serial_local_t local, m_serial_read_t serial);
m_serial_return_code_t (*read_tuple_start)(m_serial_local_t local, m_serial_read_t serial);
m_serial_return_code_t (*read_tuple_id)(m_serial_local_t local, m_serial_read_t serial, const char *const field_name [], const int max, int *id);
m_serial_return_code_t (*read_variant_start)(m_serial_local_t local, m_serial_read_t serial, const char *const field_name[], const int max, int*id);
m_serial_return_code_t (*read_variant_end)(m_serial_local_t local, m_serial_read_t serial);
} m_serial_read_interface_t;
// Object to handle the generic serial write of an object.
typedef struct m_serial_write_s {
const struct m_serial_write_interface_s *interface;
m_serial_ll_t data[M_SERIAL_MAX_DATA_SIZE];
} m_serial_write_t[1];
// Interface exported by the serial write object.
typedef struct m_serial_write_interface_s {
m_serial_return_code_t (*write_boolean)(m_serial_write_t serial, const bool b);
m_serial_return_code_t (*write_integer)(m_serial_write_t serial, const long long i, const size_t size_of_type);
m_serial_return_code_t (*write_float)(m_serial_write_t serial, const long double f, const size_t size_of_type);
m_serial_return_code_t (*write_string)(m_serial_write_t serial, const char s[]);
m_serial_return_code_t (*write_array_start)(m_serial_local_t local, m_serial_write_t serial, const size_t number_of_elements);
m_serial_return_code_t (*write_array_next)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_array_end)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_map_start)(m_serial_local_t local, m_serial_write_t serial, const size_t number_of_elements);
m_serial_return_code_t (*write_map_value)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_map_next)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_map_end)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_tuple_start)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_tuple_id)(m_serial_local_t local, m_serial_write_t serial, const char * const field_name[], const int max, const int index);
m_serial_return_code_t (*write_tuple_end)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_variant_start)(m_serial_local_t local, m_serial_write_t serial, const char * const field_name[], const int max, const int index);
m_serial_return_code_t (*write_variant_end)(m_serial_local_t local, m_serial_write_t serial);
} m_serial_write_interface_t;
See [m-serial-json.h](#m-serial-json) for example of use.
### M-MUTEX
This header is for providing very thin layer around OS implementation of threads, conditional variables and mutex.
@@ -5777,262 +6043,22 @@ The clear method of the type is not called.
### M-SERIAL-JSON
This header is for defining an instance supporting import (and export) of a container
from (to) to a JSON file.
It uses the generic serialization ability of M\*LIB for this purpose.
from (to) to a file in [JSON](https://en.wikipedia.org/wiki/JSON) format.
It uses the generic serialization ability of M\*LIB for this purpose,
providing a specialization of the serialization for JSON over FILE*.
#### Generic Serialization objects.
Another way of seeing it is that you define your data structure
using M\*LIB containers (building it using basic types, strings,
tuples, variants, array, dictionnaries, ...) and then you
can import / export your data structure for free in JSON format.
A generic serialization object is an object that takes a C object (boolean, integer, float,
structure, union, array, list, hashmap, ...) and outputs it into a serialization way through
a following defined interface that defined the format of the serialization and where it is
physically output. The final output of this serialization can be a FILE or a string.
Two kinds of serialization objects exist: one for input and one
for output. The serialization is fully recursive and can be seen as a collection of token.
The only constraint is that what is output by the output serialization object
shall be able to be parsed by the input serialization object.
If the JSON file cannot be translated into the data structure, a failure
error is reported (M\_SERIAL\_FAIL). For example, if some new fields are present
in the JSON file but not in the data structure.
On contrary, if some fields are missing (or in a different order) in the JSON
file, the parsing will still succeed (object fields are unmodified
execpt for new sub-objects, for which default value are used).
The serialization input object is named as m\_serial\_read\_t, defined in m-core.h as a structure
(of array of size 1) with the following fields:
* interface: a pointer to the constant m\_serial\_read\_interface\_s structure that defines all
methods that operate on this object to parse it. The instance has to be customized for the needs of the
wanted serialization.
* data: a table of M\_SERIAL\_MAX\_DATA\_SIZE of C types (boolean, integer, size or pointer).
This data is used to store the needed data for the methods.
This is pretty much like a pure virtual interface object in C++. The interface has to defines
the following fields with the following definition:
* read\_boolean:
Read from the stream 'serial' a boolean.
Set '*b' with the boolean value if it succeeds.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise
* read\_integer:
Read from the stream 'serial' an integer that can be represented with 'size_of_type' bytes.
Set '*i' with the integer value if it succeeds.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise.
* read\_float:
Read from the stream 'serial' a float that can be represented with 'size_of_type' bytes.
Set '*r' with the float value if it succeeds.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise.
* read\_string:
Read from the stream 'serial' a string.
Set 's' with the string if it succeeds.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise
* read\_array\_start:
Start reading from the stream 'serial' an array (which is defined as a sequential collection of object).
Set '*num' with the number of elements, or 0 if it is not known.
Initialize the object 'local' so that it can be used by the serialization object to serialize the array.
('local' is an unique local serialization object of the array).
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the parsing of the array can continue (the array is not empty),
M\_SERIAL\_OK\_DONE if it succeeds and the array ends (the array is empty),
M\_SERIAL\_FAIL otherwise.
* read\_array\_next:
Continue reading from the stream 'serial' an array using 'local' to load / save data if needed.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the array can continue (the array end is still not reached),
M\_SERIAL\_OK\_DONE if it succeeds and the array ends,
M\_SERIAL\_FAIL otherwise.
* read\_map_start:
Start reading from the stream 'serial' a map (an associative array).
Set '*num' with the number of elements, or 0 if it is not known.
Initialize 'local' so that it can be used to serialize the map.
('local' is an unique serialization object of the map).
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the map continue,
M\_SERIAL\_OK\_DONE if it succeeds and the map ends (the map is empty),
M\_SERIAL\_FAIL otherwise
* read\_map\_value:
Continue reading from the stream 'serial' the value separator token (if needed)
using 'local' to load / save data if needed.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the map continue,
M\_SERIAL\_FAIL otherwise
* read\_map_next:
Continue reading from the stream 'serial' a map.
using 'local' to load / save data if needed.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the map continue,
M\_SERIAL\_OK\_DONE if it succeeds and the map ends,
M\_SERIAL\_FAIL otherwise
* read\_tuple\_start:
Start reading a tuple from the stream 'serial'.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the tuple continues,
M\_SERIAL\_FAIL otherwise
* read\_tuple\_id:
Continue reading a tuple (a structure) from the stream 'serial'.
using 'local' to load / save data if needed.
Set '*id' with the corresponding index of the table 'field_name[max]'
associated to the parsed field in the stream.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the tuple continues,
Return M\_SERIAL\_OK\_DONE if it succeeds and the tuple ends,
M\_SERIAL\_FAIL otherwise
* read\_variant\_start:
Start reading a variant (an union) from the stream 'serial'.
Set '*id' with the corresponding index of the table 'field_name[max]'
associated to the parsed field in the stream.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds and the variant continues,
Return M\_SERIAL\_OK\_DONE if it succeeds and the variant ends(variant is empty),
M\_SERIAL\_FAIL otherwise
* read\_variant\_end:
End reading a variant from the stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds and the variant ends,
M\_SERIAL\_FAIL otherwise
The serialization output object is named as m\_serial\_write\_t, defined in m-core.h as a structure
(of array of size 1) with the following fields:
* interface: a pointer to the constant m\_serial\_write\_interface\_s structure that defines all
methods that operate on this object to output it. The instance has to be customized for the needs of the
wanted serialization.
* data: a table of M\_SERIAL\_MAX\_DATA\_SIZE of C types (boolean, integer, size or pointer).
This data is used to store the needed data for the methods.
This is pretty much like a pure virtual interface object in C++. The interface has to defines
the following fields with the following definition:
* write\_boolean:
Write the boolean 'b' into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write_\integer:
Write the integer 'data' of 'size_of_type' bytes into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_float:
Write the float 'data' of 'size_of_type' bytes into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_string:
Write the null-terminated string 'data'into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_array\_start:
Start writing an array of 'number_of_elements' objects into the serial stream 'serial'.
If 'number_of_elements' is 0, then either the array has no data,
or the number of elements of the array is unkown.
Initialize 'local' so that it can be used to serialize the array
(local is an unique serialization object of the array).
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_array\_next:
Write an array separator between elements of an array into the serial stream 'serial' if needed.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_array\_end:
End the writing of an array into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_map\_start:
Start writing a map of 'number_of_elements' pairs of objects into the serial stream 'serial'.
If 'number_of_elements' is 0, then either the map has no data,
or the number of elements is unkown.
Initialize 'local' so that it can be used to serialize the map
(local is an unique serialization object of the map).
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_map\_value:
Write a value separator between element of the same pair of a map into the serial stream 'serial' if needed.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_map\_next:
Write a map separator between elements of a map into the serial stream 'serial' if needed.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_map\_end:
End the writing of a map into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_tuple\_start:
Start writing a tuple into the serial stream 'serial'.
Initialize 'local' so that it can serial the tuple
(local is an unique serialization object of the tuple).
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_tuple\_id:
Start writing the field named field_name[index] of a tuple into the serial stream 'serial'.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_tuple\_end:
End the write of a tuple into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_variant\_start:
Start writing a variant into the serial stream 'serial'.
If index <= 0, the variant is empty.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise
Otherwise, the field 'field_name[index]' will be filled.
Return M\_SERIAL\_OK\_CONTINUE if it succeeds, M\_SERIAL\_FAIL otherwise */
* write\_variant\_end:
End Writing a variant into the serial stream 'serial'.
Return M\_SERIAL\_OK\_DONE if it succeeds, M\_SERIAL\_FAIL otherwise */
The containers define the methods \_out\_serial and \_in\_serial
if the underlying types define theses methods
over the operators OUT\_SERIAL and IN\_SERIAL.
The methods for the basic C types (int, float, ...) are only
defined in C11 (due to technical limitation).
The full C definition are:
// Serial return code
typedef enum m_serial_return_code_e {
M_SERIAL_OK_DONE = 0, M_SERIAL_OK_CONTINUE = 1, M_SERIAL_FAIL = 2
} m_serial_return_code_t;
// Different types of types that can be stored in a serial object to represent it.
typedef union m_serial_ll_u {
bool b;
int i;
size_t s;
void *p;
} m_serial_ll_t;
/* Object to handle the construction of a serial write/read of an object
that needs multiple calls (array, map, ...)
It is common to all calls to the same object */
typedef struct m_serial_local_s {
m_serial_ll_t data[M_SERIAL_MAX_DATA_SIZE];
} m_serial_local_t[1];
// Object to handle the generic serial read of an object.
typedef struct m_serial_read_s {
const struct m_serial_read_interface_s *interface;
m_serial_ll_t data[M_SERIAL_MAX_DATA_SIZE];
} m_serial_read_t[1];
// Interface exported by the serial read object.
typedef struct m_serial_read_interface_s {
m_serial_return_code_t (*read_boolean)(m_serial_read_t serial,bool *b);
m_serial_return_code_t (*read_integer)(m_serial_read_t serial, long long *i, const size_t size_of_type);
m_serial_return_code_t (*read_float)(m_serial_read_t serial, long double *f, const size_t size_of_type);
m_serial_return_code_t (*read_string)(m_serial_read_t serial, struct string_s *s);
m_serial_return_code_t (*read_array_start)(m_serial_local_t local, m_serial_read_t serial, size_t *s);
m_serial_return_code_t (*read_array_next)(m_serial_local_t local, m_serial_read_t serial);
m_serial_return_code_t (*read_map_start)(m_serial_local_t local, m_serial_read_t serial, size_t *);
m_serial_return_code_t (*read_map_value)(m_serial_local_t local, m_serial_read_t serial);
m_serial_return_code_t (*read_map_next)(m_serial_local_t local, m_serial_read_t serial);
m_serial_return_code_t (*read_tuple_start)(m_serial_local_t local, m_serial_read_t serial);
m_serial_return_code_t (*read_tuple_id)(m_serial_local_t local, m_serial_read_t serial, const char *const field_name [], const int max, int *id);
m_serial_return_code_t (*read_variant_start)(m_serial_local_t local, m_serial_read_t serial, const char *const field_name[], const int max, int*id);
m_serial_return_code_t (*read_variant_end)(m_serial_local_t local, m_serial_read_t serial);
} m_serial_read_interface_t;
// Object to handle the generic serial write of an object.
typedef struct m_serial_write_s {
const struct m_serial_write_interface_s *interface;
m_serial_ll_t data[M_SERIAL_MAX_DATA_SIZE];
} m_serial_write_t[1];
// Interface exported by the serial write object.
typedef struct m_serial_write_interface_s {
m_serial_return_code_t (*write_boolean)(m_serial_write_t serial, const bool b);
m_serial_return_code_t (*write_integer)(m_serial_write_t serial, const long long i, const size_t size_of_type);
m_serial_return_code_t (*write_float)(m_serial_write_t serial, const long double f, const size_t size_of_type);
m_serial_return_code_t (*write_string)(m_serial_write_t serial, const char s[]);
m_serial_return_code_t (*write_array_start)(m_serial_local_t local, m_serial_write_t serial, const size_t number_of_elements);
m_serial_return_code_t (*write_array_next)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_array_end)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_map_start)(m_serial_local_t local, m_serial_write_t serial, const size_t number_of_elements);
m_serial_return_code_t (*write_map_value)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_map_next)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_map_end)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_tuple_start)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_tuple_id)(m_serial_local_t local, m_serial_write_t serial, const char * const field_name[], const int max, const int index);
m_serial_return_code_t (*write_tuple_end)(m_serial_local_t local, m_serial_write_t serial);
m_serial_return_code_t (*write_variant_start)(m_serial_local_t local, m_serial_write_t serial, const char * const field_name[], const int max, const int index);
m_serial_return_code_t (*write_variant_end)(m_serial_local_t local, m_serial_write_t serial);
} m_serial_write_interface_t;
#### JSON Serialization objects.
The header m-serial-json provides a specialization of the serialization for JSON over FILE*.
It is fully working with C11 compilers only.
##### void m\_serial\_json\_write\_init(m\_serial\_write\_t serial, FILE *f)
@@ -6058,10 +6084,10 @@ Cleared the serialization object 'serial'.
Example:
TUPLE_DEF2(my,
(vala, int),
(valb, float)
(value, int),
(name, string_t)
)
#define M_OPL_my_t() TUPLE_OPLIST(my, M_DEFAULT_OPLIST, M_DEFAULT_OPLIST )
#define M_OPL_my_t() TUPLE_OPLIST(my, M_DEFAULT_OPLIST, STRING_OPLIST )
// Output in JSON file the structure my_t
void output(my_t el1)