Update documentation

This commit is contained in:
Patrick Pelissier committed 2020-12-13 00:18:53 +01:00
1 parent 9f780805f0
commit a4ff7c71f2
1 file changed
+46 -48
+46 -48
View File
@@ -1,4 +1,4 @@
M\*LIB: a Generic type-safe Container Library in C language
M\*LIB: Generic type-safe Container Library for C language
==========================================================
Overview
@@ -15,7 +15,7 @@ without erasing type information (typically using void pointers or resorting
to C macro to access the container).
This is an equivalent of the [C++](https://en.wikipedia.org/wiki/C%2B%2B)
[STL](https://en.wikipedia.org/wiki/Standard_Template_Library) but for standard ISO C99.
[Standard Library](https://en.wikipedia.org/wiki/C%2B%2B_Standard_Library) but for standard ISO C99 / C11.
There is not a strict mapping as both the STL and M\*LIB have their exclusive containers:
See [here](https://github.com/P-p-H-d/mlib/wiki/STL-to-M*LIB-mapping) for details.
@@ -30,26 +30,25 @@ There is no dependency (except some other headers of M\*LIB and the LIBC).
One of M\*LIB's design key is to ensure safety. This is done by multiple means:
* in debug mode, defensive programming is extensively used:
the contracts of the function are checked, ensuring
that the data are not corrupted. For example,
[Buffer overflow](https://en.wikipedia.org/wiki/Buffer_overflow) are checked in this mode
through [bound checking](https://en.wikipedia.org/wiki/Bounds_checking)
or the intrinsic properties of a Red-Black tree are verified.
* very few casts are used within the library. Still the library can be used
with the greatest level of warnings by a C compiler without
any aliasing warning.
the contracts of the function are checked, ensuring
that the data are not corrupted. For example,
[Buffer overflow](https://en.wikipedia.org/wiki/Buffer_overflow) are checked in this mode
through [bound checking](https://en.wikipedia.org/wiki/Bounds_checking)
or the intrinsic properties of a Red-Black tree (for example) are verified.
* as few cast as possible are used within the library (as cast are the evil of safety).
Still the library can be used with the greatest level of warnings by a C compiler without
any aliasing warning.
* the genericity is not done directly by macro, but indirectly by making them
define inline functions with the proper prototypes: this enables
the user calls to have proper warning checks.
define inline functions with the proper prototypes: this enables
the user calls to have proper warning checks.
Other key designs are:
* do not rewrite the C library and just wrap around it (for example don't rewrite sort but stable sort),
* do not make users pay the cost of what they don't need.
Due to the [weak](https://en.wikipedia.org/wiki/Strong_and_weak_typing#Pointers) nature of the C language for pointers,
[type safe](https://en.wikipedia.org/wiki/Type_safety)
means that at least a warning
Due to the [weak](https://en.wikipedia.org/wiki/Strong_and_weak_typing#Pointers) nature of the C language for pointers,
[type safe](https://en.wikipedia.org/wiki/Type_safety) means that at least a warning
is generated by the compiler in case of wrong type passed as
container arguments to the functions.
@@ -63,9 +62,8 @@ is one of the fastest generic C library you can find.
M\*LIB uses internally the 'malloc', 'realloc' and 'free' functions to handle
the memory pool. This behavior can be overridden at different level.
M\*LIB default policy is to abort the
program if there is a memory error. However, this behavior
can also be customized.
M\*LIB default policy is to abort the program if there is a memory error.
However, this behavior can also be customized globally.
M\*LIB may use a lot of assertions in its implementation to ensure safety:
it is highly recommended to properly define NDEBUG for released programs.
@@ -470,7 +468,7 @@ to specify that the function accept as its *first* argument a pointer
to the type rather than the type itself
(aka the prototype is init\_func(type `*`) instead of init\_func(type)).
If you use the '[1]' trick (see below), you won't need this.
See also the API\_* transformation call below for further transformation
See also the API\_\* transformation call below for further transformation
means of the calls.
An oplist has no real form from a C language point of view. It is just an abstraction
@@ -572,7 +570,7 @@ Example:
If there is two operations with the same name in an oplist, the left one has the priority. This enables partial overriding.
Oplists can be registered globally by defining, for the type 'type', a macro named
Oplist can be registered globally by defining, for the type 'type', a macro named
M\_OPL\_ ## type () that expands to the oplist of the type.
Only type without space in their name can be registered. A typedef of the type
can be used instead through. This can simplify a lot OPLIST usage.
@@ -611,7 +609,7 @@ An operator OP can be defined, omitted or disabled:
My type is:
* a C boolean: M\_BOOL\_OPLIST (M\_DEFAULT\_OPLIST also works partially),
* a C Boolean: M\_BOOL\_OPLIST (M\_DEFAULT\_OPLIST also works partially),
* a C integer or a C float: M\_DEFAULT\_OPLIST (it can also be omitted),
* a C enumerate: M\_ENUM\_OPLIST,
* a pointer to something (the contained do nothing on the pointed object): M\_PTR\_OPLIST,
@@ -623,7 +621,7 @@ My type is:
* a M\*LIB container: the OPLIST of the used container,
* other things: you need to provide a custom OPLIST to your type.
Note: The precise exported methods of the oplists depend of the version
Note: The precise exported methods of the Oplist depend of the version
of the C language used. Typically, in C11 mode, the M\_DEFAULT\_OPLIST
exports all needed methods to handle generic input/output of int/floats
(using _Generic) whereas it is not possible in C99 mode.
@@ -2198,7 +2196,7 @@ The following methods are automatically and properly created by the previous mac
##### name\_itref\_t
Type of one item referenced in the dictionnary. It is either:
Type of one item referenced in the dictionary. It is either:
* a structure composed of the key (field key) and the value (field value) if the dict is a map
* or the basic type of the container if the dict is a set.
@@ -2365,7 +2363,7 @@ is provided.
#### TUPLE\_OPLIST(name, oplist1[, ...] )
Return the oplist of the tuple defined by calling TUPLE\_DEF2 with the given name & the oplists.
Return the oplist of the tuple defined by calling TUPLE\_DEF2 with the given name & the Oplist.
#### Created methods
@@ -2397,19 +2395,19 @@ Set the tuple 'tuple' to the value of 'ref'.
##### void name\_emplace(name\_t tuple, const type1 element1[, ...])
Set the tuple 'tuple' to the value of the tuple construted with ('element1'[,...]).
Set the tuple 'tuple' to the value of the tuple constructed with ('element1'[,...]).
##### void name\_init\_move(name\_t tuple, name\_t ref)
Initialize the tuple 'tuple' (aka constructor) by stealing as many resources from 'ref' as possible.
After-wise 'ref' is cleared.
This method is created only if all oplists of the tuple define INIT\_MOVE method.
This method is created only if all Oplist of the tuple define INIT\_MOVE method.
##### void name\_move(name\_t tuple, name\_t ref)
Set the tuple 'tuple' by stealing as many resources from 'ref' as possible.
After-wise 'ref' is cleared.
This method is created only if all oplists of the tuple define MOVE method.
This method is created only if all Oplist of the tuple define MOVE method.
##### void name\_clear(name\_t tuple)
@@ -2433,7 +2431,7 @@ There is as many methods as there are elements.
##### int name\_cmp(const name\_t tuple1, const name\_t tuple2)
Compare 'tuple1' to 'tuple2' using lexicographic order.
This method is created only if all oplists of the tuple define CMP method.
This method is created only if all Oplist of the tuple define CMP method.
##### int name\_cmp\_order(const name\_t tuple1, const name\_t tuple2, const int order[])
@@ -2442,7 +2440,7 @@ Compare 'tuple1' to 'tuple2' using the given order.
an order of {1,4,2,0} indicates to compare first the first field,
if it is equal, to compare the fourth and so on. The third field is not
compared. A negative value indicates to revert the comparison.
This method is created only if all oplists of the tuple define CMP method.
This method is created only if all Oplist of the tuple define CMP method.
##### int name\_cmp\_element1(const name\_t tuple1, const name\_t tuple2)
@@ -2452,13 +2450,13 @@ This method is created only if the oplist of element1 defines the CMP method.
##### int name\_equal\_p(const name\_t tuple1, const name\_t tuple2)
Return true if 'tuple1' and 'tuple2' are identical.
This method is created only if all oplists of the tuple define EQUAL method.
This method is created only if all Oplist of the tuple define EQUAL method.
##### void name\_get\_str(string\_t str, const name\_t tuple, bool append)
Generate a string representation of the tuple 'tuple' and set 'str' to this representation
(if 'append' is false) or append 'str' with this representation (if 'append' is true).
This method is only defined if all oplists define a GET\_STR method.
This method is only defined if all Oplist define a GET\_STR method.
##### bool name\_parse\_str(name\_t tuple, const char str[], const char **endp)
@@ -2472,12 +2470,12 @@ decoded by the function.
##### void name\_out\_str(FILE *file, const name\_t tuple)
Generate a string representation of the tuple 'tuple' and outputs it into the FILE 'file'.
This method is only defined if all oplists define a OUT\_STR method.
This method is only defined if all Oplist define a OUT\_STR method.
##### void name\_in\_str(name\_t tuple, FILE *file)
Read from the file 'file' a string representation of a tuple and set 'tuple' to this representation.
This method is only defined if all oplists define a IN\_STR method.
This method is only defined if all Oplist define a IN\_STR method.
@@ -2524,7 +2522,7 @@ is provided.
#### VARIANT\_OPLIST(name, oplist1[, ...] )
Return the oplist of the variant defined by calling VARIANT\_DEF2 with the given name & the oplists.
Return the oplist of the variant defined by calling VARIANT\_DEF2 with the given name & the Oplist.
#### Created methods
@@ -2553,14 +2551,14 @@ Set the variant 'variant' to the value of 'ref'.
Initialize the variant 'variant' (aka constructor) by stealing as many resources from 'ref' as possible.
After-wise 'ref' is cleared.
This method is created only if all oplists of the variant define INIT\_MOVE method.
This method is created only if all Oplist of the variant define INIT\_MOVE method.
##### void name\_move(name\_t variant, name\_t ref)
##### void name\_move\_elementN(name\_t variant, typeN ref)
Set the variant 'variant' by stealing as many resources from 'ref' as possible.
After-wise 'ref' is cleared.
This method is created only if all oplists of the variant define MOVE method.
This method is created only if all Oplist of the variant define MOVE method.
##### void name\_clear(name\_t variant)
@@ -4082,7 +4080,7 @@ freed by DEL.
It can be used for statically allocated entities. However, in this case,
you shall disable the operator NEW & DEL when expanding the oplist
so that the CLEAR method doesn't try to free the objectslike this:
so that the CLEAR method doesn't try to free the objects like this:
(NEW(0), DEL(0))
@@ -4131,7 +4129,7 @@ It initializes the private fields of 'object' handling the shared pointer,
returning a pointer to the object (but initialized).
As a consequence, the shared pointer part of 'object' shall not have been initialized yet.
The other part of 'objec' may or may not be initialized before calling this method.
The other part of 'object' may or may not be initialized before calling this method.
##### name\_t name\_init\_set(name\_t shared)
@@ -5123,7 +5121,7 @@ str1 shall be a non empty string.
##### size\_t string\_replace\_all\_str (string\_t v, const char str1[], const char str2[])
##### size\_t string\_replace\_all (string\_t v, const string\_t str1, const string\_t str2)
Replace in the string 'v' all the occurences of
Replace in the string 'v' all the occurrences of
the string 'str1' by the string 'str2'.
str1 shall be a non empty string.
@@ -5778,7 +5776,7 @@ Return the associated method to the given operator within the given oplist.
##### M\_BOOL\_OPLIST
Default oplist for C standard boolean.
Default oplist for C standard Boolean.
##### M\_DEFAULT\_OPLIST
@@ -6008,8 +6006,8 @@ 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
A generic serialization object is an object that takes a C object (Boolean, integer, float,
structure, union, pointer, array, list, hash-map, ...) 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.
@@ -6037,7 +6035,7 @@ The serialization input object is named as m\_serial\_read\_t, defined in m-core
* m\_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).
* 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
@@ -6545,15 +6543,15 @@ to any C compiler (C11 or C99 compliant) or C++ compiler.
If available, it uses the C11 header stdatomic.h,
otherwise if the compiler is a C++ compiler,
it uses the header 'atomic' and imports all definition
into the global namespace (this is needed because the
into the global name space (this is needed because the
C++ standard doesn't support officially the stdatomic header,
resulting in broken compilation when building C code with
a C++ compiler).
Otherwise it provides a non-thin emulation of atomic
using mutex. This emulation has a known theorical limitation:
using mutex. This emulation has a known theoretical limitation:
the mutex are never cleared. There is nothing to do
to fix this. In practise, it is not a problem.
to fix this. In practice, it is not a problem.
### M-ALGO
@@ -7220,9 +7218,9 @@ Clear the serialization object 'serial'.
# Licence
# License
All files of M\*LIB are distributed under the following licence.
All files of M\*LIB are distributed under the following license.
Copyright (c) 2017-2020, Patrick Pelissier
All rights reserved.