diff --git a/README.md b/README.md index a9253849..4bfe985d 100644 --- a/README.md +++ b/README.md @@ -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.