Update doc
This commit is contained in:
1 parent
42f807d64b
commit
8eb95d0cdc
1 file changed
+282
-256
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user