Author SHA1 Message Date
Patrick Pelissier 4a96845fac Improve error messages by the compiler
if the number of arguments doesn't match what is expected.
2023-11-01 11:14:27 +01:00
Patrick Pelissier b742881ebc WIP interface 2023-11-01 11:14:27 +01:00
Patrick Pelissier f7f5db61d3 Fix formatting 2023-11-01 11:13:54 +01:00
Patrick Pelissier 32b00eb433 Add new operator GENTYPE 2023-10-21 19:05:08 +02:00
Patrick Pelissier 796f2619e5 Change M_BY_NARGS semantics:
simplify suffix by __ # NARGS
instead of __NARGS_ # NARGS

Driver: reduce macro name length.
2023-10-20 00:02:38 +02:00
Patrick Pelissier 268192138a WIP M_ON_EXCEPTION 2023-10-19 22:54:51 +02:00
Patrick Pelissier 0671a2ea41 Update doc 2023-10-15 22:21:12 +02:00
Patrick Pelissier 07dce84e51 Tuple init: handle case of exception
during construction of tuple
2023-10-14 20:15:14 +02:00
Patrick Pelissier 5f4303624f Adding macro M_CHAIN_OBJ 2023-10-14 15:55:59 +02:00
Patrick Pelissier 19e61467d5 Adding tuple generation
for analysis of generated code.
2023-10-14 15:31:37 +02:00
Patrick Pelissier 1454bcebe4 Add unique name identifier
in order to avoid Wshadow warning
in generated code.
2023-10-14 15:30:57 +02:00
Patrick Pelissier d48f2ff84d Update comment 2023-10-06 22:38:36 +02:00
Patrick Pelissier 269636b4d8 Update doc with new macro M_CHAIN_INIT 2023-09-09 18:40:59 +02:00
Patrick Pelissier bf68340106 Add macro M_CHAIN_INIT for support of partially constructed object. 2023-09-09 18:40:32 +02:00
Patrick Pelissier 5dba526e29 Update ISSUES 2023-09-08 22:12:16 +02:00
Patrick Pelissier 469239adcd Update comments 2023-08-24 23:32:47 +02:00
Patrick Pelissier 589abda0c2 Fix bug in list insertion:
The output iterator has its previous field incorrect.
2023-08-13 23:27:12 +02:00
Patrick Pelissier 8f141896ba Clarify operators for memory allocation 2023-08-02 23:20:02 +02:00
Patrick Pelissier a0cbec4329 Support of output failure for serialization of strings 2023-08-02 23:20:02 +02:00
Patrick Pelissier df66db562d Add comments 2023-08-01 00:33:43 +02:00
Patrick Pelissier 1829a70601 Update documentation 2023-07-20 23:42:15 +02:00
Patrick Pelissier e9b25f2414 Rename internal field size to capacity
to match what it is used for.
2023-07-13 21:48:33 +02:00
Patrick Pelissier c9bb739f24 Fix format 2023-07-10 00:59:18 +02:00
Patrick Pelissier e049b83a9e Rename M_SUFFIX_FUNCTION_BY_NARGS in M_BY_NARGS
and updates suffix with __NARGS_
in order to be more explicit.
2023-07-10 00:58:31 +02:00
Patrick Pelissier 31ac3999a1 Add new operators 2023-07-07 22:17:39 +02:00
Patrick Pelissier a0818419ab Fix format 2023-07-04 01:08:40 +02:00
Patrick Pelissier 496f885a84 Add threads backend for FreeRTOS tasks. 2023-07-04 01:07:59 +02:00
Patrick Pelissier d5d9a4bd5c Update documentation of threads 2023-07-04 00:46:32 +02:00
Patrick Pelissier ca9571a110 Fix no stdio:
M_CSTR macro cannot be available if there is no stdio
2023-06-29 21:26:22 +02:00
Patrick Pelissier 4497214b9c Fix spelling 2023-06-29 00:32:23 +02:00
PpHd ccb1658afd Provide way of avoiding code duplication for multiple source C files
Use of compiler extension for that, only compatible for GCC /CLANG.
This provides easy and total customization (for example non template functions like strings can also avoid code duplication).
2023-06-13 23:46:58 +02:00
Patrick Pelissier eaf2783f1a Synchro with master branch 2023-06-11 23:32:42 +02:00
Patrick Pelissier 5705819814 Update doc 2023-06-11 23:32:02 +02:00
Patrick Pelissier 91f5f513c4 Update macro names
Make global logic easier.
2023-06-11 23:32:02 +02:00
Patrick Pelissier 3dec4e2cbe Fix example 2023-06-11 23:32:02 +02:00
Patrick Pelissier e70766beaa Update list of ignored file 2023-06-11 23:32:02 +02:00
Patrick Pelissier d7639f0ae0 Update example to match new semantic 2023-06-11 23:32:02 +02:00
Patrick Pelissier c63ce84e45 Update logic to select which linkage to use
so that user code can be written easily
M_USE_EXTERN_DECL / M_USE_DECL activates functions that are not inlined.
If M_USE_EXTERN_DEF / M_USE_DEF is also defined, then the definition is emitted instead of the declaration.
2023-06-11 23:32:02 +02:00
Patrick Pelissier a043c379c0 Update user code as per new liberty 2023-06-11 23:32:02 +02:00
Patrick Pelissier 92bb380117 Rewrite order in preprocessing if to simplify user code 2023-06-11 23:32:02 +02:00
Patrick Pelissier 6bb7a184db Fix compil rules 2023-06-11 23:32:02 +02:00
Patrick Pelissier fa9163be9d Make linker options optional 2023-06-11 23:32:02 +02:00
Patrick Pelissier 0bade1563c Also build exn.exe by default 2023-06-11 23:32:02 +02:00
Patrick Pelissier 1278d2f8a0 Implement noinline another way 2023-06-11 23:32:02 +02:00
Patrick Pelissier 53af2aae68 Add example of separating inline & function code 2023-06-11 23:32:02 +02:00
Patrick Pelissier 17ded6fcc8 Update M_USE_EXTERN_FINE_GRAINED to avoid warnings 2023-06-11 23:32:02 +02:00
Patrick Pelissier 19ce371533 Add support for M_USE_EXTERN_FINE_GRAINED to enable / disable inline semantics alongside the translation unit by redefining it when needed 2023-06-11 23:32:02 +02:00
Patrick Pelissier 0bd1bcb68e Another way to request the desired semantics, compatible with clang 2023-06-11 23:32:02 +02:00
Patrick Pelissier b50813713a Define internal M_INLINE:
it is used to control the inline semantics.
By combining it with optimize option "-fno-inline"
for the internal M*LIB function (using _Pragma optimize)
we can control easily if we want to use an inline version
or call of an external function.

Define new user API:
* M_USE_EXTERN_DECL : define it before including any MLIB header to requests to call the M*LIB functions and don't inline then.
* M_USE_EXTERN_DEF  : define it once in a translation unit to define the M*LIB functions. This translation unit shall contain all templated macro too.
If you use one option, you need to use the other one too for another translation unit.
2023-06-11 23:32:02 +02:00
Patrick Pelissier 2628536d20 Add +m_string_it_set_ref 2023-06-10 01:50:14 +02:00
Patrick Pelissier ecfa4a9152 Add new function string_pop_u
to pop the last unicode code point
of a string.
2023-06-03 00:59:34 +02:00
Patrick Pelissier dafe4bcec5 Add basic test for M_DEFAULT_ARGS
Print hint to developper in case of incorrect usage
2023-06-03 00:56:13 +02:00
Patrick Pelissier 8544a7f289 Update example 2023-05-30 14:01:30 +02:00
Patrick Pelissier aa18915d61 Fix overflow computation 2023-05-21 00:15:58 +02:00
Patrick Pelissier df4bc0a56c Remove alloc warning for analyzer:
it is not able to track allocations correctly and only give false warnings.
valgraind or memory sanitizer are much more reliable to track memory errors.
2023-05-13 00:52:06 +02:00
Patrick Pelissier b6046e5e23 Fix new warnings with GCC13 2023-05-13 00:52:06 +02:00
Patrick Pelissier b487bfe5ad Adding missing inline 2023-05-08 23:54:16 +02:00
PpHd 408272c810 Merge pull request
Add m_string_cat_vprintf
2023-05-08 23:35:54 +02:00
kitterion 6a9ee17eca Add tests 2023-05-08 23:17:19 +03:00
kitterion 05c5a94634 Add m_string_cat_vprintf 2023-05-08 20:52:47 +03:00
Patrick Pelissier b1b0927e9f Update examples 2023-05-06 21:54:08 +02:00
Patrick Pelissier 37770365a1 Fix several bugs:
* in case of some invalid format starting with ']' directly it wrongly assume that the parsing was valid.
* incase of exception handling, and an exception was raised during the internal parsing, some destructors wern't called.
2023-05-05 22:16:39 +02:00
Patrick Pelissier 82bdcc685a Add internal macro MQLET for internal M_LET use 2023-05-05 22:15:13 +02:00
Patrick Pelissier 26fa733f70 Fix format 2023-05-05 22:14:41 +02:00
Patrick Pelissier cd2fc05573 Add FIXED_SIZE property 2023-05-05 21:41:05 +02:00
Patrick Pelissier 33430d4359 Update 2023-04-29 18:46:09 +02:00
Patrick Pelissier dc95b49f05 Update 2023-04-29 12:07:10 +02:00
Patrick Pelissier 3ec24cfa40 Update 2023-04-29 11:41:08 +02:00
Patrick Pelissier 12b099dcf8 Update 2023-04-29 11:25:56 +02:00
Patrick Pelissier b885d6136c Update 2023-04-29 11:20:00 +02:00
Patrick Pelissier b51c4bea2b Update 2023-04-29 11:19:54 +02:00
Patrick Pelissier 302c5eb300 Remove export passthrough of NEW/DEL/REALLOC/FREE interface
from the container oplist.
It has no real practical purpose.
NEW/DEL/REALLOC/FREE shall be a property of the container
to be defined, and not a property for an already defined container.
2023-04-29 10:50:04 +02:00
Patrick Pelissier 6d2900a2bd Improve coverage of test suite. 2023-04-27 00:04:44 +02:00
Patrick Pelissier 573e09c56e Remove variable number of elements support which was not working.
Request an explicit number of elements.
2023-04-27 00:04:03 +02:00
Patrick Pelissier 0a39a17d36 The undefined number of element value of serial _array_start
is now (size_t)-1 and no longer 0.
Moreoever, a serialization interface may refuse outputting data
if it doesn't know the number of elements.
In which case, the container shall explictly compute the number
of elements and recall the serial object _array_start method.
2023-04-27 00:01:50 +02:00
Patrick Pelissier a913d0947c Rewrite code to fix coverage 2023-04-26 23:34:13 +02:00
Patrick Pelissier abbd8ad6ce Update 2023-04-26 22:56:23 +02:00
Patrick Pelissier a09c9fe1c3 Update 2023-04-26 22:56:23 +02:00
53 changed files with 3260 additions and 1820 deletions

No files matched your search

+1
View File
@@ -38,6 +38,7 @@ depend
other/
a*.dat
config
config.link
*.log
.vscode
.vs
+314 -70
View File
@@ -26,9 +26,9 @@ M\*LIB: Generic type-safe Container Library for C language
12. [Fixed buffer queue](#m-buffer)
13. [Atomic Shared Register](#m-snapshot)
14. [Shared pointers](#m-shared)
15. [Intrusie Shared Pointers](#m-i-shared)
15. [Intrusive Shared Pointers](#m-i-shared)
16. [Intrusive list](#m-i-list)
17. [Concurrent adaptator](#m-concurrent)
17. [Concurrent adapter](#m-concurrent)
18. [Bitset](#m-bitset)
19. [String](#m-string)
20. [Core preprocessing](#m-core)
@@ -42,28 +42,29 @@ M\*LIB: Generic type-safe Container Library for C language
28. [JSON Serialization](#m-serial-json)
29. [Binary Serialization](#m-serial-bin)
12. [Global User Customization](#global-user-customization)
13. [Licence](#license)
13. [License](#license)
## Overview
M\*LIB (M star lib) is a C library enabling to define and use **generic and
type safe container**, aka handling generic
M\*LIB (M star lib) is a C library enabling to define and to use **generic and
type safe container** in C, aka handling generic
[containers](https://en.wikipedia.org/wiki/Container_%28abstract_data_type%29) in in pure C language.
The objects within the containers can be trivial or very complex:
they can have their own constructor, destructor, operators
or can be basic C type like the C type 'int'.
The encapsulated objects can have their own constructor, destructor, operators
or can be basic C type like the C type 'int': both are fully supported.
This makes it possible to construct fully
recursive objects (container-of[...]-container-of-type-T),
without erasing type information (typically using void pointers or resorting
to C macro to access the container).
recursive container objects (container-of[...]-container-of-type-T)
while keeping compile time type checking.
This is an equivalent of the [C++](https://en.wikipedia.org/wiki/C%2B%2B)
[Standard Library](https://en.wikipedia.org/wiki/C%2B%2B_Standard_Library)
but for standard ISO C99 / C11.
[Standard Library](https://en.wikipedia.org/wiki/C%2B%2B_Standard_Library),
providing vector, deque, forward_list, set, map, multiset, multimap,
unordered_set, unordered_map, stack, queue, shared_ptr, string, variant, option
to 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.
M\*LIB provides also additional concurrent containers to design properly
multi-threaded programs: shared register, communication queue, ...
M\*LIB is portable to any systems that support [ISO C99](https://en.wikipedia.org/wiki/C99).
Some optional features need at least [ISO C11](https://en.wikipedia.org/wiki/C11_(C_standard_revision)).
@@ -78,7 +79,7 @@ One of M\*LIB 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,
that the data are not corrupted. For example, strict
[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.
@@ -86,12 +87,12 @@ One of M\*LIB design key is to ensure safety. This is done by multiple means:
* as few cast as possible are used within the library (casts 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
* the genericity is not done directly by macro (which usually prevent type safety), but indirectly by making them
define inline functions with the proper prototypes: this enables
the user calls to have proper warning checks.
* extensive testing: the library is tested on the main targets using Continuous Integration with a coverage of the test suite of nearly 99%.
the user calls to have proper error and warning checks.
* extensive testing: the library is tested on the main targets using Continuous Integration with a coverage of the test suite of more than 99%.
The test suite itself is run through the multiple sanitizers defined by GCC/CLANG (Address, undefined, leak, thread).
The test suite also includes a comparison of equivalent behaviors of M\*LIB with the C++ STL using random genetic algorithms.
The test suite also includes a comparison of equivalent behaviors of M\*LIB with the C++ STL using random testing or fuzzer testing.
* static analysis: multiple static analyzer (like scan-build or GCC fanalyzer or CodeQL) are run on the generated code, and the results analyzed.
Other key designs are:
@@ -114,12 +115,18 @@ is one of the fastest generic C/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.
Its default policy is to abort the program if there is a memory error.
However, this behavior can also be customized globally.
M\*LIB supports also the exception error model by providing its own implementation of the try / catch mechanism.
This mechanism is compatible with [RAII programming](https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization):
when an exception is thrown, the destructors of the constructed objects are called (See [m-try](#m-try) for more details).
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.
M\*LIB provides automatically several [serialization](https://en.wikipedia.org/wiki/Serialization) methods for each containers.
You can read or write your full and complex data structure into [JSON](https://en.wikipedia.org/wiki/JSON) format in a few lines.
M\*LIB is distributed under BSD-2 simplified license.
It is strongly advised not to read the source to know how to use the library
@@ -141,8 +148,8 @@ The following headers define containers that don't require the user structure to
* [m-list.h](#m-list): header for creating singly-linked list of generic type,
* [m-deque.h](#m-deque): header for creating dynamic double-ended queue of generic type,
* [m-dict.h](#m-dict): header for creating unordered associative array (through hashmap) or unordered set of generic type,
* [m-rbtree.h](#m-rbtree): header for creating ordered set (through binary sorted tree) of generic type,
* [m-bptree.h](#m-bptree): header for creating ordered map/set/multimap/multiset (through B+TREE) of generic type,
* [m-rbtree.h](#m-rbtree): header for creating ordered set (through Red/Black binary sorted tree) of generic type,
* [m-bptree.h](#m-bptree): header for creating ordered map/set/multimap/multiset (through sorted B+TREE) of generic type,
* [m-tree.h](#m-tree): header for creating arbitrary tree of generic type,
* [m-tuple.h](#m-tuple): header for creating arbitrary tuple of generic types,
* [m-variant.h](#m-variant): header for creating arbitrary variant of generic type,
@@ -180,7 +187,7 @@ Finally headers for compatibility with non C11 compilers:
* [m-atomic.h](#m-atomic): header for ensuring compatibility between C's stdatomic.h and C++'s atomic header (provide also its own implementation if nothing is available),
* [m-thread.h](#m-thread): header for providing a very thin layer across multiple implementation of mutex/threads (C11/PTHREAD/WIN32).
Each containers define their iterators (if it is meaningfull).
Each containers define their iterators (if it is meaningful).
All containers try to expose the same common interface:
if the method name is the same, then it does the same thing
@@ -604,6 +611,7 @@ Other documented operators are:
* NAME() --> prefix: Return the base name (prefix) used to construct the container.
* TYPE() --> type: Return the base type associated to this oplist.
* SUBTYPE() --> type: Return the type of the element stored in the container (used to iterate over the container).
* GENTYPE() --> type: Return the type representing TYPE suitable for a _Generic statement.
* OPLIST() --> oplist: Return the oplist of the type of the elements stored in the container.
* KEY\_TYPE() --> key\_t: Return the key type for associative containers.
* VALUE\_TYPE() --> value\_t: Return the value type for associative containers.
@@ -614,7 +622,7 @@ Other documented operators are:
* REALLOC(type, type pointer, number) --> type pointer: realloc the given array referenced by type pointer (either a NULL pointer or a pointer returned by the associated REALLOC method itself) to an array of the number of objects of this type and return a pointer to this new array. Previously objects pointed by the pointer are kept up to the minimum of the new size and old one. New objects are not initialized (a constructor operator shall be called afterward). Freed objects are not cleared (A destructor operator shall be called before). The default is M\_MEMORY\_REALLOC (that allocates from the heap). It returns NULL in case of failure in which case the original array is not modified.
* FREE (&obj) : free the allocated uninitialized array object 'obj'. The objects are not cleared before being free (CLEAR operator has to be called before). The object shall have been allocated by the associated REALLOC method. The default is M\_MEMORY\_FREE (that frees to the heap).
* INC\_ALLOC(size\_t s) -> size\_t: Define the growing policy of an array (or equivalent structure). It returns a new allocation size based on the old allocation size ('s'). Default policy is to get the maximum between '2*s' and 16. NOTE: It doesn't check for overflow: if the returned value is lower than the old one, the user shall raise an overflow error.
* INIT\_MOVE(objd, objc): Initialize 'objd' to the same state than 'objc' by stealing as much resources as possible from 'objc', and then clear 'objc' (constructor of objd + destructor of objc). It is semantically equivalent to calling INIT\_SET(objd,objc) then CLEAR(objc) but is usually way faster. Contrary to the C++ choice of using "conservative move" semantic (you still need to call the destructor of a moved object in C++) M\*LIB implements a "destructive move" semantic (this enables better optimization). By default, all objects are assumed to be **trivially movable** (i.e. using memcpy to move an object is safe). Most C objects (even complex structure) are trivially movable and it is a very nice property to have (enabling better optimization). A notable exception are intrusive objects. If an object is not trivially movable, it shall provide an INIT\_MOVE method or disable the INIT\_MOVE method entirely (NOTE: Some containers may assume that the objects are trivially movable). An INIT\_MOVE operator shall not fail. Moved objects shall use the same memory allocator.
* INIT\_MOVE(objd, objc): Initialize 'objd' to the same state than 'objc' by stealing as much resources as possible from 'objc', and then clear 'objc' (constructor of objd + destructor of objc). It is semantically equivalent to calling INIT\_SET(objd,objc) then CLEAR(objc) but is usually way faster. Contrary to the C++ choice of using "conservative move" semantic (you still need to call the destructor of a moved object in C++) M\*LIB implements a "destructive move" semantic (this enables better optimization). By default, all objects are assumed to be **trivially movable** (i.e. using memcpy to move an object is safe). Most C objects (even complex structure) are trivially movable and it is a very nice property to have (enabling better optimization). A notable exception are intrusive objects. If an object is not trivially movable, it shall provide an INIT\_MOVE method or disable the INIT\_MOVE method entirely (NOTE: Some containers may assume that the objects are trivially movable). An INIT\_MOVE operator shall not fail (and therefore no exception can be throw). Moved objects shall use the same memory allocator.
* MOVE(objd, objc): Set 'objd' to the same state than 'objc' by stealing as resources as possible from 'objc' and then clear 'objc' (destructor of 'objc'). It is equivalent to calling SET(objd,objc) then CLEAR(objc) or CLEAR(objd) and then INIT\_MOVE(objd, objc). See INIT\_MOVE for details and constraints. TBC if this operator is really needed as calling CLEAR then INIT\_MOVE is what do all known implementation, and is efficient.
* INIT\_WITH(obj, ...): Initialize the object 'obj' with the given variable set of arguments (constructor). The arguments can be of different types. It is up to the method of the object to decide how to initialize the object based on this initialization array. This operator is used by the M\_LET macro to initialize objects with their given values and this operator defines what the M\_LET macro supports. In C11, you can use API\_1(M\_INIT\_WITH\_THROUGH\_EMPLACE\_TYPE) as method to automatically use the different emplace functions defined in EMPLACE\_TYPE through a _Generic switch case. The EMPLACE\_TYPE shall use the LIST format. See emplace chapter.
* SWAP(objd, objc): Swap the states of the object 'objc' and the object 'objd'. The objects shall use the same allocator.
@@ -684,7 +692,7 @@ Properties can be stored in a sub-oplist format in the PROPERTIES operator.
The following properties are defined:
* LET\_AS\_INIT\_WITH(1): Defined if the macro M\_LET shall always initialize the object with INIT\_WITH regardless of the given input. The value of the property is 1 (enabled) or 0 (disabled/default).
* NOCLEAR(1): Defined if the object CLEAR operator can be ommited (like for basic types or POD data). The value of the property is 1 (enabled) or 0 (disabled/default).
* NOCLEAR(1): Defined if the object CLEAR operator can be omitted (like for basic types or POD data). The value of the property is 1 (enabled) or 0 (disabled/default).
More properties are expected.
@@ -771,7 +779,7 @@ Let's take the interface of a pseudo library:
```
The library returns a pointer to the object, so we need API_4 for these methods.
There is no method for the SET operator available. However, we can use the macro M_SET_THROUGH_INIT_SET
to emulate a SET semantics by using a combinaison of CLEAR+INIT_SET. This enables to support
to emulate a SET semantics by using a combination of CLEAR+INIT_SET. This enables to support
the type for array containers in particular. Or we can avoid this definition if we don't need it.
A basic oplist will be:
@@ -837,7 +845,7 @@ An operator OP can be defined, omitted or disabled:
* ( ): the operator OP is omitted, and the default global operation for OP is used (if it exists).
* ( OP(0) ): the operator OP is disabled, and it can never be used.
This can be usefull to disable an operator in an inherited oplist.
This can be useful to disable an operator in an inherited oplist.
### Which OPLIST to use?
@@ -876,7 +884,7 @@ For example, internally M\_BOOL\_OPLIST inherits from M\_BASIC\_OPLIST.
A typical example is if you want to provide the OOR\_SET and OOR\_EQUAL operators to a type
so that it can be used in an OA dict.
To do it, you use the M\_OPEXTEND macro. It takes as first argument the oplist you want to inherit with,
and then you provide the additionals associations between operators to methods you want to add
and then you provide the additional associations between operators to methods you want to add
or override in the inherited oplist. For example:
```C
@@ -910,7 +918,7 @@ Let's take a look at the interface of the FILE interface:
FILE *fopen(const char *filename, const char *mode);
fclose(FILE *f);
```
There is no INIT operator (an argument is mandatary), no INIT\_SET operator.
There is no INIT operator (an argument is mandatory), no INIT\_SET operator.
It is only possible to open a file from a filename.
'FILE *' contains some space, so an alias is needed.
There is an optional mode argument, which is a constant string, and isn't a valid preprocessing token.
@@ -940,9 +948,9 @@ In which case, this enables you to close the file even if an exception is thrown
Memory Allocation functions can be globally set by overriding the following macros before using the definition \_DEF macros:
* M\_MEMORY\_ALLOC (type): return a pointer to a new object of type 'type'.
* M\_MEMORY\_ALLOC (type) --> ptr: return a pointer to a new object of type 'type'.
* M\_MEMORY\_DEL (ptr): free the single object pointed by 'ptr'.
* M\_MEMORY\_REALLOC (type, ptr, number): return a pointer to an array of 'number' objects of type 'type', reusing the old array pointed by 'ptr'. 'ptr' can be NULL, in that case the array will be created.
* M\_MEMORY\_REALLOC (type, ptr, number) --> ptr: return a pointer to an array of 'number' objects of type 'type', reusing the old array pointed by 'ptr'. 'ptr' can be NULL, in which case the array will be created.
* M\_MEMORY\_FREE (ptr): free the array of objects pointed by 'ptr'.
ALLOC & DEL operators are supposed to allocate fixed size single element object (no array).
@@ -5702,6 +5710,14 @@ It returns -1 in case of error in decoding the UTF8 string.
Return the position in the stream of the iterator 'it'.
##### void string\_it\_set\_ref(string\_it\_t it, string\_t str, string\_unicode\_t u)
Replace the unicode code point referenced by 'it' to the unicode code point 'u'
in the string 'str'.
If 'u' is 0, then it will resize the string to the size of the referenced iterator
only keeping the unicode code points before the iterator.
'it' shall be a valid iterator of 'str'.
##### bool string\_it\_equal\_p (const string\_it\_t it1, const string\_it\_t it2)
Return true if both iterators reference the same position, false otherwise.
@@ -5711,6 +5727,13 @@ Return true if both iterators reference the same position, false otherwise.
Push the unicode code point 'u' into the string 'str'
encoding it as a variable UTF8 encoded code point.
##### bool string\_pop\_u (string\_unicode\_t *u, string\_t str)
Pop the last unicode code point from the string 'str'
encoded as a variable UTF8 encoded code point
and store in '*u' the popped unicode code point if 'u' is not NULL.
It returns true in case of success or false otherwise (no character to pop or no valid UTF8).
##### size\_t string\_length\_u(string\_t str)
Return the number of UTF8 encoded code point in the string.
@@ -5731,8 +5754,107 @@ The oplist of a string\_t
##### BOUNDED\_STRING\_DEF(name, size)
aka char[size+1]
TODO: Document the API.
Define a bounded string of size 'size', aka char[size+1] (including the final nul char).
###### Created types
The following types are automatically defined by the previous definition macro if not provided by the user:
####### name\_t
Type of the concurrent container of 'type'.
####### Generic methods
The following methods of the generic interface are defined (See generic interface for details):
* void name\_init(name\_t bounded\_string)
* void name\_init\_set(name\_t bounded\_string, const name\_t src)
* void name\_set(name\_t bounded\_string, const name\_t src)
* void name\_reset(name\_t bounded\_string)
* void name\_clear(name\_t bounded\_string)
* size\_t name\_size(const name\_t bounded\_string)
* size\_t name\_capacity(const name\_t bounded\_string)
* bool name\_empty\_p(const name\_t bounded\_string)
* void name\_get\_str(string\_t str, name\_t bounded\_string, bool append)
* void name\_out\_str(FILE *file, name\_t bounded\_string)
* bool name\_parse\_str(name\_t bounded\_string, const char str[], const char **end)
* bool name\_in\_str(name\_t bounded\_string, FILE *file)
* m\_serial\_return\_code\_t name\_out\_serial(m\_serial\_write\_t serial, const name\_t bounded\_string)
* m\_serial\_return\_code\_t name\_in\_str(name\_t bounded\_string, m\_serial\_read\_t serial)
* bool name\_equal\_p(name\_t bounded\_string1, name\_t bounded\_string2)
* int name\_cmp(const name\_t bounded\_string1, const name\_t bounded\_string2)
* size\_t name\_hash(name\_t bounded\_string)
####### Specialized methods
The following specialized methods are automatically created by the previous definition macro:
####### void name\_init\_set\_cstr)(bounded\_t string, const char str[])
Initialize the bounded string to the given C string 'str', truncating if needed.
####### void name\_set\_cstr)(bounded\_t string, const char str[])
Set the bounded string 'string' to the given C string 'str', truncating if needed.
####### void name\_set\_cstrn)(bounded\_t string, const char str[], size\_t n)
Set the bounded string 'string' to the 'n' first byte characters of the given C string 'str', truncating if needed.
####### void name\_set\_n)(bounded\_t string, const bounded\_t string, size\_t offset, size\_t length)
Set the bounded string 'string' to the 'length' first byte characters from the offset 'offset'
of the bounded given C string 'str', truncating if needed.
####### const char *name\_get\_cstr)(const bounded\_t string)
Return the C string representation of the bounded string.
####### char name\_get\_char(const bounded\_t string, size\_t index)
Return the byte character at the given index of the string.
index shall be within the size of the string.
####### void name\_cat)(bounded\_t string, const bounded_t str)
####### void name\_cat\_cstr)(bounded\_t string, const char str[])
Concat the given C string to the bounded string.
####### int name\_cmp\_cstr)(const bounded\_t string, const char str[])
Compared the bounded string to the given C string:
return a negative integer if the bounded string is before the C string,
0 if there are equals,
a positive integer otherwise.
####### bool name\_equal\_cstr\_p)(const bounded\_t string, const char str[])
Return true if the bounded string is equal to the given C string.*
####### int name\_printf)(bounded\_t string, const char format[], ...)
Set the bounded string to the format C string.
####### int name\_cat\_printf)(bounded\_t string, const char format[], ...)
Concat to the bounded string the format C string.
####### bool name\_fgets)(bounded\_t string, FILE *f, string\_fgets\_t arg)
Read at most 'max\_size+1' bytes from the file 'f' and set the bounded string to it.
####### bool name\_fputs)(FILE *f, const bounded\_t string)
Put the bounded string to the file 'f'.
####### bool name\_oor\_equal\_p)(const bounded\_t string, unsigned char n)
Provide the OOR\_EQUAL\_P method of a string.
####### void name\_oor\_set)(bounded\_t string, unsigned char n)
Provide the OOR\_SET method of a string.
### M-CORE
@@ -6542,12 +6664,12 @@ right initialization function in function of the type of argument.
The EMPLACE\_TYPE shall use a LIST based format for listing the different emplace types.
This method is compatible with C11 or above.
This method shall be used with API\_1 adaptator.
This method shall be used with API\_1 adapter.
##### M\_SET\_THROUGH\_INIT\_SET(oplist, dest, src)
Emulate the SET semantics using a combinaison of CLEAR and INIT\_SET of the given oplist.
This method shall be used with API\_1 adaptator.
Emulate the SET semantics using a combination of CLEAR and INIT\_SET of the given oplist.
This method shall be used with API\_1 adapter.
##### M\_GLOBAL\_OPLIST(a)
@@ -6683,7 +6805,7 @@ You can chain the M\_LET\_IF macro to create several different variables.
This macro registers the execution of 'clear\_code' when reaching
the further closing brace of the next block of instruction.
clear_code shall be a valid expression.
clear\_code shall be a valid expression.
There shall be at most one M\_DEFER macro per line of source code.
@@ -6702,6 +6824,77 @@ You can use the break instruction to quit the block
(the clear\_code will be executed) or you can use exception.
##### M\_CHAIN\_INIT(name, init\_code, clear\_code)
This macro executes 'init\_code' then
registers the execution of 'clear\_code' if an exception is triggered
until the further closing brace of the next block of instruction.
init\_code and clear\_code shall be a valid expression.
If exception are not enabled, it simply executes 'init\_code'.
name shall a unique identifier in the current block.
It can be chained multiple times to register multiple registrations.
Therefore it enables support for chaining
initialization at the begining of a constructor for the fields of the constructed
object so that even if the constructor failed and throw an exception,
the fields of the constructed object are properly cleared.
This is equivalent to C++ construct:
void type() : field1(), field2() { rest of constructor }
M_CHAIN_INIT / M_CHAIN_OBJ shall be the first instructions of the constructor function.
Example:
void struct_init_set(struct_t d, struct_t s)
{
M_CHAIN_INIT(s1, string_init_set(d->s1, s->s1), string_clear(d->s1) )
M_CHAIN_INIT(s2, string_init_set(d->s2, s->s2), string_clear(d->s2) ) {
d->num = s->num;
}
}
##### M\_CHAIN\_OBJ(name, oplist, var [, value])
This macro executes the initialization method if 'var' to initialize it then
registers the execution of its CLEAR method if an exception is triggered
(and if the property NOCLEAR of the oplist is not defined)
until the further closing brace of the next block of instruction.
If exception are not enabled, it simply executes the initialization method.
The initialization method being used is :
* INIT method if there is no value
* INIT\_SET method if there is a value which is not between parenthesis
* INIT\_WITH method if there is a value which is between parenthesis.
name shall a unique identifier in the current block.
It can be chained multiple times to register multiple registrations.
Therefore it enables support for chaining
initialization at the begining of a constructor for the fields of the constructed
object so that even if the constructor failed and throw an exception,
the fields of the constructed object are properly cleared.
This is equivalent to C++ construct:
void type() : field1(), field2() { rest of constructor }
M_CHAIN_INIT / M_CHAIN_OBJ shall be the first instructions of the constructor function.
Example:
void struct_init_set(struct_t d, struct_t s)
{
M_CHAIN_OBJ(s1, STRING_OPLIST, d->s1, s->s1)
M_CHAIN_OBJ(s2, STRING_OPLIST, d->s2, s->s2)
M_CHAIN_OBJ(nu, M_BASIC_OPLIST, d->num, s->num) { }
}
#### Memory / Error macros
All these macro can be overridden before including the header m-core.h
@@ -6851,7 +7044,7 @@ 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
This is pretty much like a pure virtual interface object in C++. The interface has to define
the following fields with the following definition:
* read\_boolean:
@@ -6872,11 +7065,12 @@ the following fields with the following definition:
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.
Set '*num' with the number of elements, or (size\_t)-1 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\_RETRY if it doesn't support unknown number of elements,
M\_SERIAL\_FAIL otherwise.
* read\_array\_next:
Continue reading from the stream 'serial' an array using 'local' to load / save data if needed.
@@ -7081,11 +7275,12 @@ See [m-serial-json.h](#m-serial-json) for example of use.
### M-THREAD
This header is for providing very thin layer around OS implementation of threads, conditional variables and mutex.
It has back-ends for WIN32, POSIX thread or C11 thread.
It has back-ends for WIN32, POSIX thread, FreeRTOS tasks or C11 thread.
It was needed due to the low adoption rate of the C11 equivalent layer.
It uses the C11 threads.h if possible.
It uses the FreeRTOS tasks is it detects FreeRTOS.
Otherwise it uses the C11 threads.h if possible.
If the C11 implementation does not respect the C standard
(i.e. the compiler targets C11 mode,
the \_\_STDC\_NO\_THREADS\_\_ macro is not defined
@@ -7096,6 +7291,12 @@ macro to select the back end to use:
* 1: for C11
* 2: for WINDOWS
* 3: for PTHREAD
* 4: for FreeRTOS
The FreeRTOS backend uses two additional global configuration constants:
* M\_USE\_TASK\_STACK\_SIZE to define the stack size of a thread (default is the minimal)
* M\_USE\_TASK\_PRIORITY to define the priority of a thread (default is lowest).
Example:
@@ -7126,64 +7327,63 @@ The following methods are available:
A type representing a mutex.
##### void m\_mutex\_init(mutex)
##### void m\_mutex\_init(m\_mutex\_t mutex)
Initialize the variable mutex of type m\_mutex\_t.
Initialize the variable mutex and sets it to the unlocked position.
If the initialization fails, the program aborts.
Only one thread shall initialize the mutex.
##### void m\_mutex\_clear(mutex)
##### void m\_mutex\_clear(m\_mutex\_t mutex)
Clear the variable mutex of type m\_mutex\_t.
If the variable is not initialized, the behavior is undefined.
Clear the variable mutex.
Only one thread shall clear the mutex.
##### void m\_mutex\_lock(mutex)
##### void m\_mutex\_lock(m\_mutex\_t mutex)
Lock the variable mutex of type m\_mutex\_t for exclusive use.
If the variable is not free, it will wait indefinitely until it is.
If the variable is not initialized, the behavior is undefined.
Lock the variable mutex for exclusive use.
If the mutex is not unlocked, it will wait indefinitely until it is.
The mutex shall not be already locked.
##### void m\_mutex\_unlock(mutex)
##### void m\_mutex\_unlock(m\_mutex\_t mutex)
Unlock the variable mutex of type m\_mutex\_t for exclusive use.
If the variable is not locked, the behavior is undefined.
If the variable is not initialized, the behavior is undefined.
Unlock the variable mutex for exclusive use.
The mutex shall not be already unlocked.
#### m\_cond\_t
A type representing a conditional variable, used within a mutex section.
A type representing a conditional variable, which shall be used within a mutex section.
##### void m\_cond\_init(m\_cond\_t cond)
Initialize the conditional variable cond of type m\_cond\_t.
Initialize the conditional variable cond.
If the initialization failed, the program aborts.
Only one thread shall init the conditional variable.
##### void m\_cond\_clear(m\_cond\_t cond)
Clear the variable cond of type m\_cond\_t.
Clear the variable cond.
If the variable is not initialized, the behavior is undefined.
Only one thread shall clear the conditional variable.
##### void m\_cond\_signal(m\_cond\_t cond)
Within a mutex exclusive section,
signal that the event associated to the variable cond of type m\_cond\_t
Signal that the event associated to the variable cond
has occurred to at least a single thread.
If the variable is not initialized, the behavior is undefined.
All usage of this conditional variable shall be done within the same mutex exclusve section.
##### void m\_cond\_broadcast(m\_cond\_t cond)
Within a mutex exclusive section,
signal that the event associated to the variable cond of type m\_cond\_t
Signal that the event associated to the variable cond
has occurred to all waiting threads.
If the variable is not initialized, the behavior is undefined.
All usage of this conditional variable shall be done within the same mutex exclusve section.
##### void m\_cond\_wait(m\_cond\_t cond, m\_mutex\_t mutex)
Within a mutex exclusive section defined by mutex,
wait indefinitely for the event associated to the variable cond of type m\_cond\_t
Wait indefinitely for the event associated to the variable cond
to occur.
IF multiple threads wait for the same event, which thread to awoken
is not specified.
If any variable is not initialized, the behavior is undefined.
All usage of this conditional variable shall be done within the mutex exclusve section.
#### m\_thread\_t
@@ -7890,16 +8090,16 @@ that accept the generic interface (mainly \_call).
### M-TRY
This header is for [exception handling](https://en.wikipedia.org/wiki/Exception_handling).
It provides basic functionnality for throwing exception and catching then.
It provides basic functionality for throwing exception and catching then.
The setjmp and longjmp standard library functions (or some variants) are used to implement the try / catch / throw macro keywords.
It doesn't support the finaly keyword.
It doesn't support the finally keyword.
When building with a C++ compiler, theses macro keywords simply use the original C++ keyword in a way to match
the specification below.
The whole program shall be compiled with the same exact compiler and the same target architecture.
Only one type of data is supported as exception. This is done to simplify the design and to force using exception
as a general purpose error handlings. It should only be used for rare case of errors which cannot be dealt locally
Only one type of data is supported as exception. This is done to simplify the design and to avoid using exception
as a general purpose error mecanism. It should only be used for rare case of errors which cannot be dealt locally
in the program being executed.
In order to support [Resource Acquisition Is Initialization](https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization)
@@ -7937,6 +8137,11 @@ otherwise it will compile in degraded mode:
-fblocks -lBlocksRuntime
When writing your own constructor, you should consider M\_CHAIN\_INIT
to support partially constructed object
if there are more than two source of throwing in your object
(any memory allocation is a source of throwing).
#### struct m\_exception\_s
This is the exception type. It is composed of the following fields:
@@ -8319,6 +8524,45 @@ Use fast integer conversion algorithms instead of using the LIBC.
Default value: 1 (because it also generates smaller code).
#### M\_USE\_DECL
If M\_USE\_FINE\_GRAINED\_LINKAGE is not defined,
it will request M\*LIB to change the linkage of its symbols globally:
instead of inlining the functions, it will emit weak symbols
for the functions that are not inlined.
And in exactly one translation unit, the macro M\_USE\_DEF
should also be defined so that it emits the normal definition
of the functions. In which case, it should contain all symbols
used by all other translation units.
You should compile your program with
-ffunction-sections -fdata-sections
and link with
-Wl,--gc-sections
in order to remove unused code and to merge identical code
otherwise it is likely to generate even bigger code than using the inlining linkage.
This works for GCC / CLANG in C mode.
#### M\_USE\_FINE\_GRAINED\_LINKAGE
It will request M\*LIB to change the linkage of its symbols dynamically at compile time:
in which case
M\_USE\_DECL / M\_USE\_DEF can be defined / undefined several times in a translation unit
and M\*LIB will emit the change the linkage of the symbols being declared accordingly:
* definition like if M\_USE\_DECL and M\_USE\_DEF are defined
* declaration like if M\_USE\_DECL is defined
* inline like otherwise
This enables to inline some functions and not others.
M\_USE\_DECL / M\_USE\_DEF shall be defined without effective value.
See M\_USE\_DECL for more details.
#### M\_MEMORY\_ALLOC
See [m-core.h](#m-core)
+251 -32
View File
@@ -1,5 +1,206 @@
*Long term issues*
------------------
==========================================================
* TODO #33 : Handling of partially constructed object :ANOMALY:
** State
Support of partially constructed object needs special code to handle it
correctly (register a correct cleanup function in case of exception).
Current containers don't support such features.
** Actions
Add such support in M*LIB containers.
It can be difficult. For example, for array _init_set
function due to the copy of the object one per one. Each copied sub object
may throw an exception, so we always need to have the container in a correct
state so that it can be cleanup.
* TODO #32 : User specialization fields in the container :ENHANCEMENT:
** State
Some methods of a contained object may need to have some options that
are neither constant nor global, but are specialized in function of the container.
For example, a memory handler may need a parameter which is needed to identify
which pool of memory has to be used.
** Plan:
Add a new operator "CONTEXT" which is a type to be added in the
defined container. Then it can be accessed by the operator through an extension
of the GAIA by adding support for identification of specialization like this:
( CONTEXT( memory_pool_ref ),
NEW( API(NONE, memory_pool_alloc, CONTEXT, ARG1)),
DEL( API(NONE, memory_pool_free, CONTEXT, ARG1)) )
** Open points:
- How to get access to the specialization field of the container? ==> Define the "self" name as the name of the container for all methods? What to do when there are several containers for a method?
- How to initialize the specialization field of the container? provide custom initialization functions? It seems to be the hard point.
* TODO #31 : Uniformize parametrisation options of containers :ENHANCEMENT:
** State
Currently in order to pass some parametrization of the containers,
the parameters are passed to the generation macros through:
- extra parameters of the macros,
- special operators of the contained object oplist.
The extra parameters of some generation macros break the uniformity
of the interface.
It is conceptually wrong to put some special operators of the contained object
that have only meanings for the container object.
In case of adding new options, it break the existing interface or put another
operator in the contained object oplist.
The following parameters are used:
- Fixed size of a queue (buffer / B+Tree),
- Policy of a queue (buffer),
- Type of the container, IT type of the container, Ref type of the iterator
The following operators are used:
- NEW / DEL / REALLOC / FREE
- MEMPOOL / MEMPOOL_LINKAGE
The following new options is planned:
- Interface (See #28)
- Extra parameter for memory allocation function
** Plan
The M\_*\_DEF\_AS macros shall be changed like this:
M_*_DEF_AS(name, cont_oplist, type[, type_oplist])
with cont\_oplist being the container oplist that gives parametrization to the container definition.
The following operators are planned:
- TYPE: to define the type of the container,
- IT\_TYPE: to define the IT type of the container,
- SUBTYPE: to define the type pointed by the iterator,
- FIXED\_SIZE: to define the fixed size of a container,
- POLICY: to define the policy of a container,
- NEW / DEL / REALLOC / FREE: to define the memory interface,
- MEMPOOL / MEMPOOL_LINKAGE: to request a definition of a specialized memory interface,
- INTERFACE: to request a pure header definition, an implementation or both (see #28),
- CONTEXT: to request an extra context parameter to add in the container.
All operators should be optional.
The NEW / DEL / REALLOC / FREE / MEMPOOL / MEMPOOL_LINKAGE won't have any effects anymore if defined in the contained object oplist.
** Pro:
- Uniformize interface
** Con:
- API breakage. It can be mitigated by providing an adaptating layer by prividing the new interface for M\_*\_DEF\_AS only
and *\_DEF\_AS will provide a translation layer.
* TODO #30 : Serialization rework :ENHANCEMENT:
** State
Currently, each container supports 3 serialization methods:
- old format to FILE
- old format to string
- generic serialization
Generic serialiation connect the container format to the serialization object constraints.
It is done through a vtable. As such there is a performance penality and it avoids proper inlining.
** Evolution
Old format should be deprecated and shall use the generic serialization interface.
Serialization object shall provide an OPLIST of serialization.
For example CORE will provide OLD Format oplist and serial-json will provide JSON format oplist.
Each oplist will provide the suffix needed for the serialization, and the interface
(see already existing interface).
Then a container will generate specialized serialization methods for each provided oplist.
Pros:
- Faster
- In the M*LIB philosphy: much like other oplist usage.
Cons:
- compatibility breakage.
Open point:
- how can a user add a new serialization object?
- Can we make a generic serialization object to support migration path?
** Example
serial-json provides
#define M_SERIAL_1() (NAME(_json), READ_INT(...), WRITE_INT(...) )
containers provides
For i in 1 100 ; do
if do exist M_SERIAL_ ## i ()
expand(SERIAL_METHOD with M_SERIAL_1())
SERIAL_METHOD(name, ....)
static inline m_serial_return_code_t \
M_C(M_F(name, _out_serial),M_GET_NAME(serial_op) )(M_GET_TYPE(serial_op) f, const list_t list) \
* DONE #29 : Support of partial initialized object :ANOMALY:
** State
In case of exception during the construction of an object,
if the object is partially constructed, there is no destructor to call.
Therefore if there is some partially constructed object
(with some fields already fully constructed), there will be some links.
This is the same problem with C++
** Proposition
Provide new macros to perform the partial initialization before doing the remaining taf.
Something like:
M_CHAIN_INIT( init_code, clear_code)
or
x is { string_t s; string_t d; int num; }
void struct_init_set(struct_t x, const struct_t y)
{
// First thing is Chained Initialization
M_CHAIN_INIT( string_init_set(x->s, y->s), string_clear(x->s) );
M_CHAIN_INIT( string_init_set(x->d, y->d), string_clear(x->d) );
// End of chain init
x->num = y->num;
}
M_CHAIN_INIT will push the clean code pretty much like M_LET.
Everything else is done in M_LET: when the constructor fully returns,
the index of the clean code to call is reset to its value before calling
the constructor. It means that the partially initialized code will be removed
from this stack before the clean method of the structure itself is pushed.
If an exception is raised after a M_CHAIN_INIT, only the clean methods
of the M_CHAIN_INIT are called.
* TODO #28 : Separate generation of interface to implementation :ENHANCEMENT:
@@ -9,9 +210,32 @@ and an implementation only for the source code.
Try to keep API compatibility
==> Only modify renamed macro with M_ prefix by giving a new mandatory
argument for such generation.
This argument is a generation parametric argument.
oplist is a parameter that define the property of the contained type.
It could be used to pass this information but it will be an abuse of interface.
Another argument is needed.
Used arguments to parameter generation not related to the contained type:
- memory interface (NEW / DEL / ...)
- queue policy
- fixed size for queue
- fixed node size for B+Tree
- generate static inline, public (extern) or private (define) functions.
- name of the type.
- name of the iterator
- name of the iterated element.
- ...
Use another oplist as argument for M_.._DEF_AS (See #31)
M_BUFFER_DEF_AS(name, (TYPE(toto), FIXED_SIZE(10), POLICY(STACK), INTERFACE(header)), int, M_BASIC_OPLIST)
* TODO #27 : Uniformization of m-buffer interface :ENHANCEMENT:
** State
The m-buffer interface requires special argument to work:
- size & policy for BUFFER,
- policy only for the others.
@@ -19,8 +243,10 @@ This is not uniform with the others generation macros and not uniform with each
Moreover the others are the only one which can be used in a shared memory, so
a fixed size will be good to have too for such interface.
==> Uniformize the interface. How?
==> Provide static size for all QUEUE.
** Plan
- Uniformization of the interface (See #31)
- Provide static size for all QUEUE.
* TODO #26 : Hash-Map for huge objects :ENHANCEMENT:
@@ -60,7 +286,7 @@ unsigned get_small_hash(int64_t x) {
Find a way to support error return code for the API in case of allocation
failure.
Any service that returns void shall return a "int".
Any service that returns void shall return a "int" (or another type).
In case of allocation failure, it shall return an error.
M_CALL macro shall stop its execution if the service returns an error code
and the error code represents an error (avoid rewritting everything)
@@ -119,19 +345,20 @@ RETCODE/RETCODE
If really needed, the macro can be avoided and code can be hand written.
Open points:
- How to handle warnings on unused labels?
- What about M_LET/ M_EACH?
- What about M_LET / M_EACH? Maybe only supports those.
* TODO #24 : New: Add MIN-MAX-HEAP container :ENHANCEMENT:
* TODO #24 : New MIN-MAX-HEAP container :ENHANCEMENT:
See https://en.wikipedia.org/wiki/Min-max_heap
as DPRIORITY_QUEUE_DEF ?
NOTE: Needs for such container?
* TODO #23 : Strict MOVE semantic to clarify :ENHANCEMENT:
* TODO #23: Strict MOVE semantic to clarify :ENHANCEMENT:
** State
Some type may need to have a force MOVE semantic (for example, they can store
pointer to themselves). Currently the INIT_MOVE & MOVE operators are more
@@ -146,7 +373,7 @@ moving the data before they can be moved using MOVE. Two solutions:
- New operator MOVE_SELF to fix a type after it has been moved.
- If MOVE defined, force another table and then copy by hand the type. This will be slower and consumme more memory.
** MOVE in OPLIST :ENHANCEMENT:
** MOVE in OPLIST
Proposal: do not export INIT_MOVE / MOVE operator in OPLIST if the MOVE operator is
compatible with a pure COPY semantic. An exported MOVE operator will tell
@@ -165,7 +392,6 @@ defined with [1] tricks but without an explicit INIT_MOVE / MOVE
operators as it uses MOVE_DEFAULT which is not (fully compatible).
==> Analyse limitation and possible constraint usages.
Being able to define a correct default for INIT_MOVE will be really good
(compatible with trivial move copy).
In such case, all INIT_MOVE & MOVE operators can be removed from oplist
@@ -176,12 +402,12 @@ If the type is typedef T t[1] then passing such an argument to a function,
will transform the argument to T*, and the type of the argument doesn't match
what is expecting resulting in a move of the pointers, not a move of the design data.
Defining a TYPE to this macro seems mandatory, but within restricting to C11
(by using _Generic to detect such case),
I don't see any way to define the macro.
Defining this type seems possible with C11 _Generic and a TYPE in the oplist,
but without C11 _Generic I don't see any way to define such macro.
Without a way to write such a macro, the ticket seems pretty much a dead end.
* TODO #20: New: Bucket priority queue :ENHANCEMENT:
* TODO #20 : New: Bucket priority queue :ENHANCEMENT:
Add a new kind of priority queue.
See https://en.wikipedia.org/wiki/Bucket_queue
@@ -197,21 +423,18 @@ except that we can scan 64 entries at a time).
Check if we can use BITSET, or introduce fixed size BITSET or use ad-hock
implementation.
* TODO #19: New: Intrusive Red Black Tree :ENHANCEMENT:
* TODO #19 : New: Intrusive Red Black Tree :ENHANCEMENT:
Add intrusive red black tree.
Look also for AVL tree (NOTE: Is there a performance difference between the two?)
* TODO #18: Missing methods :ENHANCEMENT:
* TODO #18 : Missing methods :ENHANCEMENT:
Some containers don't have all the methods they should.
See the cells in yellow here:
http://htmlpreview.github.io/?https://github.com/P-p-H-d/mlib/blob/master/doc/Container.html
* TODO #17: New: Ressource handler :ENHANCEMENT:
* TODO #17 : New: Ressource handler :ENHANCEMENT:
A global 'ressouce handler' which shall associated a unique handle to a ressource.
The handle shall be unique for the ressource and shall not be reused.
@@ -238,11 +461,10 @@ http://htmlpreview.github.io/?https://github.com/P-p-H-d/mlib/blob/master/doc/Co
How to handle multiple resource ?
* variant: works fine. Memory usage can be (much) higher than needed if there is a lot of dissimilarity between the size of the objects.
* embedded the type in the ressource handler: more work, API more complex. Memory usage seems better.
* variant: Pro : easy. Con: Memory usage can be (much) higher than needed if there is a lot of dissimilarity between the size of the objects.
* embedded the type in the ressource handler: Con: more work, API more complex. Pro: Memory usage seems better.
* TODO #16: New: Lock Free List :ENHANCEMENT:
* TODO #16 : New: Lock Free List :ENHANCEMENT:
Implement a lock free list. Most of the difficulty is the memory reclamation part.
Typically this lock free list shall be compatible with RCU method.
@@ -265,8 +487,7 @@ http://htmlpreview.github.io/?https://github.com/P-p-H-d/mlib/blob/master/doc/Co
- needs to be logically deleted : needs a previous field
(NULL if not logically deleted) ? TBC
* TODO #14: Memory allocation enhancement :ENHANCEMENT:
* DONE #14 : Memory allocation enhancement :ENHANCEMENT:
Enhancement of the memory allocation scheme to find way to deal properly with advanced allocators:
@@ -300,8 +521,9 @@ Needs some formal operator in the oplist to support it fully and an example.
It is a kind of object inheritance where the container inherits some extra data from its base.
Duplicate with #32 which is more generic ==> Closed
* TODO #12: New: Atomic shared pointer :ENHANCEMENT:
* TODO #12 : New: Atomic shared pointer :ENHANCEMENT:
Add an extension to the SHARED_PTR API:
@@ -375,9 +597,7 @@ Other alternative solution is to use the bit 0 to mark the pointer as being upda
Other implementation seems to have it hard to be lock-free: cf. https://github.com/llvm-mirror/libcxx/commit/5fec82dc0db3623546038e4a86baa44f749e554f
* TODO #5: New: Concurrent dictionary Container :ENHANCEMENT:
* TODO #5 : New: Concurrent dictionary Container :ENHANCEMENT:
Implement a more efficient dictionary than lock + std dictionary for all operations when dealing with threads.
See https://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx
@@ -423,7 +643,6 @@ It needs before lock-free list: http://www.cse.yorku.ca/~ruppert/papers/lfll.pdf
Atomic update is done by allocating a new node, update it, and atomicaly store it in the dict, putting the old one as logically deleted and to reclaim later.
(Other threads may still read its data so we cannot free immediatly).
* DONE #22: Enhanced services for SPSC Queue :ENHANCEMENT:
Add services:
+15 -2
View File
@@ -21,7 +21,7 @@
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
CC=cc -std=c99
CFLAGS=-Wall -W -pedantic -Wshadow -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wswitch-default -Wswitch-enum -Wcast-align -Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 -Wstrict-prototypes -Winline -Wundef -Wnested-externs -Wcast-qual -Wshadow -Wunreachable-code -Wlogical-op -Wstrict-aliasing=2 -Wredundant-decls -Wold-style-definition -Wno-unused-function -g
CFLAGS=-Wall -W -pedantic -Wshadow -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wswitch-default -Wswitch-enum -Wcast-align -Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 -Wstrict-prototypes -Wundef -Wnested-externs -Wcast-qual -Wshadow -Wunreachable-code -Wlogical-op -Wstrict-aliasing=2 -Wredundant-decls -Wold-style-definition -Wno-unused-function -g
GMP_DIR=
MPFR_DIR=$(GMP_DIR)
CPPFLAGS=-I..
@@ -33,18 +33,31 @@ RM=rm -f
.c.exe:
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@ `cat config` $(LDFLAGS)
.c.o:
@$(MAKE) config
$(CC) $(CFLAGS) $(CPPFLAGS) -O2 `cat config.link` -DNDEBUG -g $< -c -o $@
all: config
$(MAKE) `ls ex-*.c|sed -e 's/\.c/\.exe/g'`
if test "$(CC)" = "cc -std=c99" ; then $(MAKE) `ls ex11-*.c|sed -e 's/\.c/\.exe/g'` CC="cc -std=c11" ; fi
$(MAKE) exm.exe exn.exe
exm.exe: exm-lib.o exm-main.o
$(CC) `cat config.link` -g $^ -o $@
exn.exe: exn-lib.o exn-main.o
$(CC) `cat config.link` -g $^ -o $@
config:
printf "#include <gmp.h>\nint main(void){mpz_t z; mpz_init(z); return 0;}\n" > config-test.c
$(CC) $(CFLAGS) $(CPPFLAGS) -I$(GMP_DIR)/include -L$(GMP_DIR)/lib config-test.c -lgmp -o config-test.exe $(LDFLAGS) 2> /dev/null && echo "-DHAVE_GMP=1 -DHAVE_MPFR=0 -I$(GMP_DIR)/include -L$(GMP_DIR)/lib -lgmp" > config || echo "-DHAVE_GMP=0 -DHAVE_MPFR=0 " > config
printf "#include <mpfr.h>\nint main(void){mpfr_t z; mpfr_init(z); return 0;}\n" > config-test.c
$(CC) $(CFLAGS) $(CPPFLAGS) -I$(GMP_DIR)/include -I$(MPFR_DIR)/include -L$(GMP_DIR)/lib -L$(MPFR_DIR)/lib config-test.c -lmpfr -lgmp -o config-test.exe $(LDFLAGS) 2> /dev/null && echo "-DHAVE_GMP=1 -DHAVE_MPFR=1 -I$(GMP_DIR)/include -L$(GMP_DIR)/lib -I$(MPFR_DIR)/include -L$(MPFR_DIR)/lib -lmpfr -lgmp" > config || echo "MPFR not available"
printf "#include <stdio.h>\nint main(void){printf(\"Ok\"); return 0;}\n" > config-test.c
$(CC) $(CFLAGS) $(CPPFLAGS) config-test.c -ffunction-sections -fdata-sections -Wl,--gc-sections 2> /dev/null && echo "-ffunction-sections -fdata-sections -Wl,--gc-sections" > config.link || echo "" > config.link
$(RM) config-test.c config-test.exe
clean:
$(RM) *.exe *.s *~ *.o ./a.dat config
$(RM) *.exe *.s *~ *.o ./a.dat config config.link
+7 -7
View File
@@ -4,16 +4,16 @@
/* Define a dynamic array of int */
ARRAY_DEF(vector_int, int)
/* Register the oplist of this dynamic array globally */
/* Register the oplist of this dynamic array globally (using implicitely M_BASIC_OPLIST) */
#define M_OPL_vector_int_t() ARRAY_OPLIST(vector_int)
/* Define some standards algorithms on this dynamic array */
/* Define some standards algorithms on this dynamic array. We can reuse the prefix of the dynamic array */
ALGO_DEF(vector_int, vector_int_t)
/* Define a dynamic array of bool */
ARRAY_DEF(vector_bool, bool)
/* Register the oplist of this dynamic array globally */
#define M_OPL_vector_bool_t() ARRAY_OPLIST(vector_bool, M_BOOL_OPLIST)
/* Define some standards algorithms on this dynamic array */
/* Define some standards algorithms on this dynamic array. We can reuse the prefix of the dynamic array */
ALGO_DEF(vector_bool, vector_bool_t)
/* ID function */
@@ -41,10 +41,10 @@ int main(void)
#else
for M_EACH(it, myvector, vector_int_t) {
printf(" %d", *it);
}
}
#endif
printf("\n");
}
} /* End of M_LET: myvector & tmp are automaticly cleared */
// Same thing but with booleans
M_LET(myvector, tmp, vector_bool_t) {
@@ -56,13 +56,13 @@ int main(void)
printf("myvector contains:");
for M_EACH(it, myvector, vector_bool_t) {
printf(" %d", (int)*it);
}
}
printf("\n");
printf ("ALL: %d ANY: %d NONE: %d\n",
vector_bool_all_of_p(myvector, id),
vector_bool_any_of_p(myvector, id),
vector_bool_none_of_p(myvector, id) );
}
} /* End of M_LET: myvector & tmp are automaticly cleared */
return 0;
}
+5 -6
View File
@@ -14,7 +14,7 @@ ARRAY_DEF(vector_int, int)
/* Register the oplist of this array of integer globally */
#define M_OPL_vector_int_t() ARRAY_OPLIST(vector_int)
/* Micro macro to detect if a string starts with the given pattern */
/* Micro macro to detect if the key string starts with the given pattern */
#define start_with(pattern, item) \
string_start_with_str_p((item).key, (pattern))
@@ -26,11 +26,10 @@ int main(void)
int s = 0;
// Init keys as a vector_int_t, initialize it (and prepare its destruction)
M_LET(keys, vector_int_t)
// Initialize m as a dictionnary and initialize it with the given database
// Initialize tmp as a dictionanry
M_LET( (m, (STRING_CTE("foo"), 1), (STRING_CTE("bar"), 42), (STRING_CTE("bluez"), 7), (STRING_CTE("stop"), 789) ), tmp, dict_t) {
/* Extract all elements of 'm' that starts with 'b' */
// Initialize m as a dictionnary and initialize it with the given database
// Initialize tmp as a dictionnary
M_LET( (m, (STRING_CTE("foo"), 1), (STRING_CTE("bar"), 42), (STRING_CTE("bluez"), 7), (STRING_CTE("stop"), 789) ), tmp, dict_t) {
/* Extract all elements of 'm' that starts with 'b' and fills tmp with it */
ALGO_EXTRACT(tmp, dict_t, m, dict_t, start_with, "b");
/* Extract the values of theses elements */
ALGO_TRANSFORM(keys, vector_int_t, tmp, dict_t, get_value);
+2 -2
View File
@@ -14,8 +14,8 @@ int main(void)
{
// Let 's' be a string_t and initialize it.
M_LET(s, string_t)
// Let 'v' be a vector of integer and initialize it.
M_LET( (v, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10), vector_int_t) {
// Let 'v' be a vector of integer and initialize it.
M_LET( (v, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10), vector_int_t) {
int sum = 0, product = 0;
// Compute the sum of theses integers.
+22 -1
View File
@@ -8,13 +8,17 @@
#include "m-string.h"
#include "m-algo.h"
// Let's create a list of string by using the M*LIB dynamic string.
// Let's create a list of string by using the M*LIB dynamic string 'string_t'
// The prefix used for generating functions will be 'list_string'
LIST_DEF(list_string, string_t)
// Let's register the oplist globally so that other M*LIB macros
// can get the oplist without us giving it explictly to them.
// An oplist is the association of operators to the provided methods
// so that generic code can use correctly an object of such type.
// LIST_OPLIST is a macro used to generate the oplist associated to the
// list itself. It needs the prefix used for generating the list (aka list_string here)
// and the oplist of the item in the list (aka the string oplist)
#define M_OPL_list_string_t() LIST_OPLIST(list_string, STRING_OPLIST)
// Let's define some basic algorithms over this list of string.
@@ -95,6 +99,23 @@ int main(void)
}
} // Everything is cleared after this point.
// Let's create another list of string and init it.
list_string_t list;
list_string_init(list);
// Let's put some elements in it:
list_string_emplace_back (list, "A");
list_string_emplace_back (list, "B");
list_string_emplace_back (list, "C");
list_string_emplace_back (list, "D");
// Reverse it
list_string_reverse(list);
// Let's display the string by serializing the elements of the list:
printf ("List of string = ");
list_string_out_str(stdout, list);
printf ("\n");
// Don't forget to clear the list before leaving
list_string_clear(list);
return 0;
}
+28 -2
View File
@@ -14,32 +14,50 @@ RBTREE_DEF(tree_cstr, const char *, M_CSTR_OPLIST)
// It is probably the best for beginner in M*LIB to start like this.
static void classic1(void)
{
// Let's declare a tree on the stack.
// Even if the tree itself is allocated on the stack,
// the nodes will be allocated on the heap.
tree_cstr_t tree;
// Initialize the tree using the provided constructor
tree_cstr_init(tree);
// Let's fill in the tree
// Note that the object of the tree are pointer
// to array of char. Therefore the strings themselves
// are not stored in the tree but only a reference to then
// As such, the pointed objects shall not moved nor being
// destroyed, which is the case for const C string.
tree_cstr_push (tree, "Hello");
tree_cstr_push (tree, "World");
tree_cstr_push (tree, "How");
tree_cstr_push (tree, "Are");
tree_cstr_push (tree, "You");
// Let's print the tree.
// We'll use the OUT_STR method to display the tree
// without iterating ourself in the tree.
printf("\nUsing C string, the generated (sorted) tree is ");
tree_cstr_out_str(stdout, tree);
printf ("\n");
// Let's search for the key "How" in the tree.
// If it is not found a NULL pointer is returned.
// Otherwise a pointer to the key within the tree is returned.
// This pointer is valid until a modification operation on the tree is done.
const char *present = tree_cstr_get(tree, "How") == NULL ? "not " : "";
printf("The word 'How' is %spresent\n", present);
present = tree_cstr_get(tree, "Not") == NULL ? "not " : "";
printf("The word 'Not' is %spresent\n", present);
// Destroy the tree by calling the destructor.
tree_cstr_clear(tree);
}
// Let's define another Red Black Tree over the M*LIB strings
// Notice that we don't need to specify the oplist for this case.
// since the oplist of a string_t is registered globally.
RBTREE_DEF(tree_str, string_t)
// The classic C way
@@ -52,16 +70,24 @@ static void classic2(void)
// STRING_CTE enables to construct a temporary const string_t from a const char *
// usable for function call.
// Note that this time the full string is stored within the tree,
// and not only a pointer to it.
tree_str_push (tree, STRING_CTE("Hello"));
tree_str_push (tree, STRING_CTE("World"));
tree_str_push (tree, STRING_CTE("How"));
tree_str_push (tree, STRING_CTE("Are"));
tree_str_push (tree, STRING_CTE("You"));
// We may also push a const C string into a string_t by calling the emplace function
tree_str_emplace (tree, "You");
// Let's print the tree
printf("\nUsing M*LIB string_t, the generated (sorted) tree is ");
tree_str_out_str(stdout, tree);
printf ("\n");
// Let's search for the string "How"
// We convert it to a temporary string_t, and let's test
// if it is found or not by testing if the returned pointer to string_t
// is null or not.
const char *present = tree_str_get(tree, STRING_CTE("How")) == NULL ? "not " : "";
printf("The word 'How' is %spresent\n", present);
+12
View File
@@ -0,0 +1,12 @@
#ifndef MY_HEADER
#define MY_HEADER
// Request M*LIB to not inline functions if not the library source
#define M_USE_DECL
#include "m-string.h"
#include "m-array.h"
ARRAY_DEF(array_str, string_t)
#endif
+5
View File
@@ -0,0 +1,5 @@
// Request M*LIB to define functions
// This include both m-string functions and array_str templated functions
// Defining M_USE_EXTERN_DEF override M_USE_EXTERN_DECL definition
#define M_USE_DEF
#include "exm-header.h"
+14
View File
@@ -0,0 +1,14 @@
#include "exm-header.h"
int main(void)
{
array_str_t a;
array_str_init(a);
array_str_emplace_back(a, "Hello");
array_str_emplace_back(a, "World");
printf("a=");
array_str_out_str(stdout, a);
printf("\n");
array_str_clear(a);
return 0;
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef MY_HEADER
#define MY_HEADER
// Request M*LIB to not always inline functions
#define M_USE_FINE_GRAINED_LINKAGE
#include "m-string.h"
#include "m-array.h"
// The following functions will not be inlined:
#define M_USE_DECL
ARRAY_DEF(array_str, string_t)
#undef M_USE_DECL
#endif
+4
View File
@@ -0,0 +1,4 @@
// Request M*LIB to define functions for functions defined within M_USE_DECL.
#define M_USE_DEF
#include "exn-header.h"
+19
View File
@@ -0,0 +1,19 @@
#include "exn-header.h"
int main(void)
{
string_t s;
string_init_set_str(s, "a=");
string_fputs(stdout, s);
string_clear(s);
array_str_t a;
array_str_init(a);
array_str_emplace_back(a, "Hello");
array_str_emplace_back(a, "World");
//printf("a=");
array_str_out_str(stdout, a);
printf("\n");
array_str_clear(a);
//main2();
return 0;
}
+45 -45
View File
@@ -28,7 +28,7 @@
#include "m-core.h"
/* Define different kind of basic algorithms named 'name' over the container
which oplist is 'cont_oplist', as static inline functions.
which oplist is 'cont_oplist'.
USAGE:
ALGO_DEF(algogName, containerOplist|type if oplist has been registered) */
#define M_ALGO_DEF(name, cont_oplist) \
@@ -189,7 +189,7 @@
#define M_ALG0_DEF_SORT(name, container_t, cont_oplist, type_t, type_oplist, it_t, order, sort_name) \
\
/* Define the encapsulation function that perform the selected order */ \
static inline int M_C3(name,sort_name,_cmp)(type_t const*a,type_t const*b) \
M_INLINE int M_C3(name,sort_name,_cmp)(type_t const*a,type_t const*b) \
{ \
return order M_CALL_CMP(type_oplist, *a, *b); \
} \
@@ -225,7 +225,7 @@
#define M_ALG0_DEF_SORT_AUX(name, container_t, cont_oplist, type_t, type_oplist, it_t, sort_name, cmp_func, cmp_param, cmp_arg) \
\
/* Test if the container is sorted */ \
static inline bool \
M_INLINE bool \
M_C3(name,sort_name,_p)(const container_t l cmp_param(name)) \
{ \
it_t it1; \
@@ -253,7 +253,7 @@
/* - a selection sort */ \
M_IF(M_AND(M_TEST_METHOD_P(SORT, cont_oplist), M_EMPTY_P(cmp_arg)))( \
/******** OPTIMIZED SORT FOR CONTAINER *********/ \
static inline void M_F(name,sort_name)(container_t l) \
M_INLINE void M_F(name,sort_name)(container_t l) \
{ \
M_CALL_SORT(cont_oplist, l, M_C3(name, sort_name,_cmp)); \
} \
@@ -265,7 +265,7 @@
\
/* Split the container 'l' into near even size l1 and l2 * \
using odd/even splitting */ \
static inline void \
M_INLINE void \
M_C3(name,sort_name,_split)(container_t l1, container_t l2, container_t l) \
{ \
it_t it; \
@@ -280,7 +280,7 @@
} \
\
/* Merge in empty 'l' the sorted container 'l1' and 'l2' */ \
static inline void \
M_INLINE void \
M_C3(name,sort_name,_merge)(container_t l, container_t l1, container_t l2 cmp_param(name)) \
{ \
/* M_ASSERT(M_CALL_EMPTY_P (cont_oplist, l)); */ \
@@ -320,7 +320,7 @@
} \
\
/* Sort the container 'l' */ \
static inline void \
M_INLINE void \
M_F(name,sort_name)(container_t l cmp_param(name)) \
{ \
container_t l1; \
@@ -363,7 +363,7 @@
, \
M_IF_METHOD(IT_PREVIOUS, cont_oplist)( \
/******** GENERIC INSERTION SORT *********/ \
static inline void M_F(name,sort_name)(container_t l cmp_param(name)) \
M_INLINE void M_F(name,sort_name)(container_t l cmp_param(name)) \
{ \
it_t it1; \
it_t it2; \
@@ -400,7 +400,7 @@
\
, \
/********** GENERIC SELECTION SORT ************/ \
static inline void M_F(name,sort_name)(container_t l cmp_param(name)) \
M_INLINE void M_F(name,sort_name)(container_t l cmp_param(name)) \
{ \
it_t it1; \
it_t it2; \
@@ -433,7 +433,7 @@
) /* IF SORT METHOD */ \
/* Compute the union of two ***sorted*** containers */ \
M_IF_METHOD(IT_INSERT, cont_oplist)( \
static inline void \
M_INLINE void \
M_C3(name,sort_name,_union)(container_t dst, const container_t src cmp_param(name)) \
{ \
it_t itSrc; \
@@ -478,7 +478,7 @@
\
/* Compute the intersection of two ***sorted*** containers */ \
M_IF_METHOD(IT_REMOVE, cont_oplist)( \
static inline void \
M_INLINE void \
M_C3(name,sort_name,_intersect)(container_t dst, const container_t src cmp_param(name)) \
{ \
it_t itSrc; \
@@ -517,7 +517,7 @@
#define M_ALG0_DEF_FIND(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
/* It supposes that the container is not sorted */ \
/* Find the next occurrence from it (included) of data */ \
static inline void \
M_INLINE void \
M_F(name, _find_again) (it_t it, type_t const data) \
{ \
for ( /*nothing*/ ; !M_CALL_IT_END_P(cont_oplist, it) ; \
@@ -528,7 +528,7 @@
} \
\
/* Find the first occurrence of data */ \
static inline void \
M_INLINE void \
M_F(name, _find) (it_t it, container_t const l, type_t const data) \
{ \
M_CALL_IT_FIRST(cont_oplist, it, l); \
@@ -536,7 +536,7 @@
} \
\
/* Test if data is within the container */ \
static inline bool \
M_INLINE bool \
M_F(name, _contain_p) (container_t const l, type_t const data) \
{ \
it_t it; \
@@ -549,7 +549,7 @@
PREVIOUS & IT_LAST are defined, then search backwards */ \
M_IF_METHOD2(PREVIOUS, IT_LAST, cont_oplist) \
( \
static inline void \
M_INLINE void \
M_F(name, _find_last) (it_t it, container_t const l, type_t const data) \
{ \
for (M_CALL_IT_LAST(cont_oplist, it, l); \
@@ -562,7 +562,7 @@
} \
, \
/* Otherwise search forward, but don't stop on the first occurrence */ \
static inline void \
M_INLINE void \
M_F(name, _find_last) (it_t it, container_t const l, type_t const data) \
{ \
M_CALL_IT_END(cont_oplist, it, l); \
@@ -578,7 +578,7 @@
) /* End of alternative of _find_last */ \
\
/* Count the number of occurrence of data in the container */ \
static inline size_t \
M_INLINE size_t \
M_F(name, _count) (container_t const l, type_t const data) \
{ \
it_t it; \
@@ -594,7 +594,7 @@
\
\
/* Find the next mismatch between the containers */ \
static inline void \
M_INLINE void \
M_F(name, _mismatch_again) (it_t it1, it_t it2) \
{ \
for (/* nothing */ ; !M_CALL_IT_END_P(cont_oplist, it1) && \
@@ -608,7 +608,7 @@
} \
\
/* Find the first mismatch between the containers */ \
static inline void \
M_INLINE void \
M_F(name, _mismatch) (it_t it1, it_t it2, container_t const l1, container_t const l2 ) \
{ \
M_CALL_IT_FIRST(cont_oplist, it1, l1); \
@@ -625,7 +625,7 @@
#define M_ALG0_DEF_FIND_IF(name, container_t, cont_oplist, type_t, type_oplist, it_t, suffix, test_t, eq_t, call_test, call_eq) \
\
/* Find the next occurrence that matches the condition */ \
static inline void \
M_INLINE void \
M_C3(name, _find_again_, suffix) (it_t it, test_t func) \
{ \
for (/*nothing */ ; !M_CALL_IT_END_P(cont_oplist, it) ; \
@@ -636,7 +636,7 @@
} \
\
/* Find the first occurrence that matches the condition */ \
static inline void \
M_INLINE void \
M_C3(name, _find_, suffix) (it_t it, container_t l, test_t func) \
{ \
M_CALL_IT_FIRST(cont_oplist, it, l); \
@@ -644,7 +644,7 @@
} \
\
/* Count the number of occurrence that matches the condition */ \
static inline size_t \
M_INLINE size_t \
M_C3(name, _count_, suffix) (container_t const l, test_t func) \
{ \
it_t it; \
@@ -660,7 +660,7 @@
} \
\
/* Find the next mismatch between the containers according to the condition */ \
static inline void \
M_INLINE void \
M_C3(name, _mismatch_again_, suffix) (it_t it1, it_t it2, eq_t func) \
{ \
for (/*nothing */ ; !M_CALL_IT_END_P(cont_oplist, it1) && \
@@ -674,7 +674,7 @@
} \
\
/* Find the first mismatch between the containers according to the condition */ \
static inline void \
M_INLINE void \
M_C3(name, _mismatch_, suffix) (it_t it1, it_t it2, container_t const l1, \
container_t l2, eq_t func) \
{ \
@@ -688,7 +688,7 @@
#define M_ALG0_DEF_FILL(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\
/* Fill all the container with value (overwritten) */ \
static inline void \
M_INLINE void \
M_F(name, _fill) (container_t l, type_t const value) \
{ \
for M_EACH(item, l, cont_oplist) { \
@@ -698,7 +698,7 @@
\
/* Fill the container with exactly 'n' occurrence of 'value' */ \
M_IF_METHOD(PUSH, cont_oplist)( \
static inline void \
M_INLINE void \
M_F(name, _fill_n) (container_t l, size_t n, type_t const value) \
{ \
M_CALL_RESET(cont_oplist, l); \
@@ -710,7 +710,7 @@
\
/* Fill the container with FOR('value'; 'value'+'inc') */ \
M_IF_METHOD(ADD, type_oplist)( \
static inline void \
M_INLINE void \
M_F(name, _fill_a) (container_t l, type_t const value, type_t const inc) \
{ \
type_t tmp; \
@@ -724,7 +724,7 @@
\
/* Fill the container with n occurences of FOR('value'; 'value'+'inc') */ \
M_IF_METHOD(PUSH, cont_oplist)( \
static inline void \
M_INLINE void \
M_F(name, _fill_an) (container_t l, size_t n, type_t const value, type_t const inc) \
{ \
type_t tmp; \
@@ -744,7 +744,7 @@
#define M_ALG0_DEF_MAP(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\
/* Apply func for all elements of the container */ \
static inline void \
M_INLINE void \
M_F(name, _for_each) (container_t l, M_F(name, _apply_cb_ct) func) \
{ \
for M_EACH(item, l, cont_oplist) { \
@@ -756,7 +756,7 @@
M_IF_METHOD(PUSH_MOVE, cont_oplist)( \
\
/* Apply func for all elements of the container src and push the result in dst */ \
static inline void \
M_INLINE void \
M_F(name, _transform) (container_t dst, \
container_t src, \
M_F(name, _transform_cb_ct) func) \
@@ -775,7 +775,7 @@
\
/* Reduce all elements of the container in dst in function of func */ \
M_IF_METHOD(SET, type_oplist)( \
static inline void \
M_INLINE void \
M_F(name, _reduce) (type_t *dest, container_t const l, \
M_F(name, _transform_cb_ct) func) \
{ \
@@ -793,7 +793,7 @@
\
/* Reduce all transformed elements of the container in dst in function of func */ \
M_IF_METHOD(INIT, type_oplist)( \
static inline \
M_INLINE \
void M_F(name, _map_reduce) (type_t *dest, \
const container_t l, \
M_F(name, _transform_cb_ct) redFunc, \
@@ -819,7 +819,7 @@
/* Define ALL_OF algorithms */
#define M_ALG0_DEF_ALL_OF(name, container_t, cont_oplist, type_t, type_oplist, it_t, suffix, func_t, call) \
\
static inline bool \
M_INLINE bool \
M_C4(name, _any_of, suffix, p) (container_t const l, \
func_t func ) \
{ \
@@ -830,7 +830,7 @@
return false; \
} \
\
static inline bool \
M_INLINE bool \
M_C4(name, _all_of, suffix, p) (container_t const l, \
func_t func ) \
{ \
@@ -841,7 +841,7 @@
return true; \
} \
\
static inline bool \
M_INLINE bool \
M_C4(name, _none_of, suffix, p) (container_t l, \
func_t func ) \
{ \
@@ -856,7 +856,7 @@
/* Define MIN / MAX algorithms */
#define M_ALG0_DEF_MINMAX(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\
static inline type_t * \
M_INLINE type_t * \
M_F(name, _min) (const container_t l) \
{ \
type_t *min = NULL; \
@@ -869,7 +869,7 @@
return min; \
} \
\
static inline type_t * \
M_INLINE type_t * \
M_F(name, _max) (const container_t l) \
{ \
type_t *max = NULL; \
@@ -882,7 +882,7 @@
return max; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _minmax) (type_t **min_p, type_t **max_p, \
const container_t l) \
{ \
@@ -905,7 +905,7 @@
/* Define functions based on remove method */
#define M_ALG0_DEF_REMOVE(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\
static inline void \
M_INLINE void \
M_F(name, _uniq)(container_t l) \
{ \
it_t it1; \
@@ -927,7 +927,7 @@
} \
} \
\
static inline void \
M_INLINE void \
M_F(name, _remove_val)(container_t l, type_t const val) \
{ \
it_t it1; \
@@ -942,7 +942,7 @@
} \
} \
\
static inline void \
M_INLINE void \
M_F(name, _remove_if)(container_t l, M_F(name, _test_cb_ct) func) \
{ \
it_t it1; \
@@ -961,7 +961,7 @@
#define M_ALG0_DEF_VECTOR(name, container_t, cont_oplist, type_t, type_oplist, it_t) \
\
M_IF_METHOD(ADD, type_oplist)( \
static inline void M_F(name, _add) (container_t dst, const container_t src) \
M_INLINE void M_F(name, _add) (container_t dst, const container_t src) \
{ \
it_t itSrc; \
it_t itDst; \
@@ -979,7 +979,7 @@
, /* NO_ADD METHOD */ ) \
\
M_IF_METHOD(SUB, type_oplist)( \
static inline void M_F(name, _sub) (container_t dst, const container_t src) \
M_INLINE void M_F(name, _sub) (container_t dst, const container_t src) \
{ \
it_t itSrc; \
it_t itDst; \
@@ -997,7 +997,7 @@
, /* NO_SUB METHOD */ ) \
\
M_IF_METHOD(MUL, type_oplist)( \
static inline void M_F(name, _mul) (container_t dst, const container_t src) \
M_INLINE void M_F(name, _mul) (container_t dst, const container_t src) \
{ \
it_t itSrc; \
it_t itDst; \
@@ -1015,7 +1015,7 @@
, /* NO_MUL METHOD */ ) \
\
M_IF_METHOD(DIV, type_oplist)( \
static inline void M_F(name, _div) (container_t dst, const container_t src) \
M_INLINE void M_F(name, _div) (container_t dst, const container_t src) \
{ \
it_t itSrc; \
it_t itDst; \
+88 -100
View File
@@ -131,9 +131,6 @@
,M_IF_METHOD(IN_SERIAL, oplist)(IN_SERIAL(M_F(name, _in_serial)),) \
,M_IF_METHOD(EQUAL, oplist)(EQUAL(M_F(name, _equal_p)),) \
,M_IF_METHOD(HASH, oplist)(HASH(M_F(name, _hash)),) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
)
@@ -204,7 +201,7 @@
/* Define the core functions */
#define M_ARRA4_DEF_CORE(name, type, oplist, array_t, it_t) \
\
static inline void \
M_INLINE void \
M_F(name, _init)(array_t v) \
{ \
M_ASSERT (v != NULL); \
@@ -215,7 +212,7 @@
M_ARRA4_CONTRACT(v); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _reset)(array_t v) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -225,7 +222,7 @@
M_ARRA4_CONTRACT(v); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(array_t v) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -237,7 +234,7 @@
} \
\
M_IF_METHOD2(INIT_SET, SET, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _set)(array_t d, const array_t s) \
{ \
M_ARRA4_CONTRACT(d); \
@@ -265,7 +262,7 @@
M_ARRA4_CONTRACT(d); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_set)(array_t d, const array_t s) \
{ \
M_ASSERT (d != s); \
@@ -274,7 +271,7 @@
} \
, /* No SET & INIT_SET */) \
\
static inline void \
M_INLINE void \
M_F(name, _init_move)(array_t d, array_t s) \
{ \
M_ASSERT (d != s); \
@@ -288,7 +285,7 @@
M_ARRA4_CONTRACT(d); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _move)(array_t d, array_t s) \
{ \
M_ASSERT (d != s); \
@@ -297,7 +294,7 @@
} \
\
M_IF_METHOD(SET, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _set_at)(array_t v, size_t i, type const x) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -307,7 +304,7 @@
} \
, /* No SET */) \
\
static inline type * \
M_INLINE type * \
M_F(name, _back)(array_t v) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -316,7 +313,7 @@
return &v->ptr[v->size-1]; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _push_raw)(array_t v) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -345,7 +342,7 @@
} \
\
M_IF_METHOD(INIT_SET, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _push_back)(array_t v, type const x) \
{ \
type *data = M_F(name, _push_raw)(v); \
@@ -356,7 +353,7 @@
, /* No INIT_SET */ ) \
\
M_IF_METHOD(INIT, oplist)( \
static inline type * \
M_INLINE type * \
M_F(name, _push_new)(array_t v) \
{ \
type *data = M_F(name, _push_raw)(v); \
@@ -368,7 +365,7 @@
, /* No INIT */ ) \
\
M_IF_AT_LEAST_METHOD(INIT_SET, INIT_MOVE, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _push_move)(array_t v, type *x) \
{ \
M_ASSERT (x != NULL); \
@@ -380,7 +377,7 @@
, /* INIT_SET | INIT_MOVE */ ) \
\
M_IF_METHOD(INIT_SET, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _push_at)(array_t v, size_t key, type const x) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -410,7 +407,7 @@
, /* No INIT_SET */ ) \
\
M_IF_METHOD(INIT, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _resize)(array_t v, size_t size) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -439,7 +436,7 @@
} \
, /* No INIT */ ) \
\
static inline void \
M_INLINE void \
M_F(name, _reserve)(array_t v, size_t alloc) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -464,7 +461,7 @@
} \
\
M_IF_METHOD(INIT, oplist)( \
static inline type * \
M_INLINE type * \
M_F(name, _safe_get)(array_t v, size_t idx) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -498,7 +495,7 @@
, /* No INIT */) \
\
M_IF_AT_LEAST_METHOD(SET, INIT_MOVE, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _pop_back)(type *dest, array_t v) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -515,7 +512,7 @@
, /* SET | INIT_MOVE */ ) \
\
M_IF_AT_LEAST_METHOD(INIT_SET, INIT_MOVE, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _pop_move)(type *dest, array_t v) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -529,7 +526,7 @@
, /* INIT_SET | INIT_MOVE */ ) \
\
M_IF_METHOD(INIT, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _pop_until)(array_t v, it_t pos) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -539,21 +536,21 @@
} \
, /* No INIT */ ) \
\
static inline bool \
M_INLINE bool \
M_F(name, _empty_p)(const array_t v) \
{ \
M_ARRA4_CONTRACT(v); \
return v->size == 0; \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _size)(const array_t v) \
{ \
M_ARRA4_CONTRACT(v); \
return v->size; \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _capacity)(const array_t v) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -561,7 +558,7 @@
} \
\
M_IF_AT_LEAST_METHOD(SET, INIT_MOVE, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _pop_at)(type *dest, array_t v, size_t i) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -576,7 +573,7 @@
M_ARRA4_CONTRACT(v); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _erase)(array_t a, size_t i) \
{ \
M_ARRA4_CONTRACT(a); \
@@ -587,7 +584,7 @@
, /* SET | INIT_MOVE */ ) \
\
M_IF_METHOD(INIT, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _insert_v)(array_t v, size_t i, size_t num) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -623,7 +620,7 @@
} \
, /* No INIT */) \
\
static inline void \
M_INLINE void \
M_F(name, _remove_v)(array_t v, size_t i, size_t j) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -637,7 +634,7 @@
M_ARRA4_CONTRACT(v); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _swap)(array_t v1, array_t v2) \
{ \
M_ARRA4_CONTRACT(v1); \
@@ -650,7 +647,7 @@
} \
\
M_IF_AT_LEAST_METHOD(INIT_SET,INIT_MOVE,oplist) ( \
static inline void \
M_INLINE void \
M_F(name, _swap_at)(array_t v, size_t i, size_t j) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -665,7 +662,7 @@
} \
, /* INIT_SET | INIT_MOVE */ ) \
\
static inline type * \
M_INLINE type * \
M_F(name, _get)(const array_t v, size_t i) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -674,7 +671,7 @@
return &v->ptr[i]; \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _cget)(const array_t v, size_t i) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -683,7 +680,7 @@
return M_CONST_CAST(type, &v->ptr[i]); \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _front)(const array_t v) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -691,7 +688,7 @@
return M_F(name, _get)(v, 0); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it)(it_t it, const array_t v) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -700,7 +697,7 @@
it->array = v; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_last)(it_t it, const array_t v) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -710,7 +707,7 @@
it->array = v; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_end)(it_t it, const array_t v) \
{ \
M_ARRA4_CONTRACT(v); \
@@ -719,7 +716,7 @@
it->array = v; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_set)(it_t it, const it_t org) \
{ \
M_ASSERT (it != NULL && org != NULL); \
@@ -728,14 +725,14 @@
M_ARRA4_CONTRACT(it->array); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _end_p)(const it_t it) \
{ \
M_ASSERT(it != NULL && it->array != NULL); \
return it->index >= it->array->size; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _last_p)(const it_t it) \
{ \
M_ASSERT(it != NULL && it->array != NULL); \
@@ -744,7 +741,7 @@
return it->index + 1 >= it->array->size; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_equal_p)(const it_t it1, \
const it_t it2) \
{ \
@@ -752,14 +749,14 @@
return it1->array == it2->array && it1->index == it2->index; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _next)(it_t it) \
{ \
M_ASSERT(it != NULL && it->array != NULL); \
it->index ++; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _previous)(it_t it) \
{ \
M_ASSERT(it != NULL && it->array != NULL); \
@@ -768,14 +765,14 @@
it->index --; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _ref)(const it_t it) \
{ \
M_ASSERT(it != NULL); \
return M_F(name, _get)(it->array, it->index); \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _cref)(const it_t it) \
{ \
M_ASSERT(it != NULL); \
@@ -783,7 +780,7 @@
} \
\
M_IF_METHOD(INIT_SET, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _insert)(array_t a, it_t it, type const x) \
{ \
M_ASSERT (it != NULL && a == it->array); \
@@ -794,7 +791,7 @@
, /* End of INIT_SET */ ) \
\
M_IF_AT_LEAST_METHOD(SET, INIT_MOVE, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _remove)(array_t a, it_t it) \
{ \
M_ASSERT (it != NULL && a == it->array); \
@@ -805,7 +802,7 @@
\
M_IF_METHOD(CMP, oplist) \
( \
static inline void M_F(name, _special_sort)(array_t l, \
M_INLINE void M_F(name, _special_sort)(array_t l, \
int (*func_type) (type const *a, type const *b)) \
{ \
/* Using qsort is more compact but slower than a full templated \
@@ -817,7 +814,7 @@
} \
\
M_IF_METHOD2(SWAP, SET, oplist)( \
static inline void \
M_INLINE void \
M_C3(m_arra4_,name,_stable_sort_noalloc)(type tab[], size_t size, type tmp[]) \
{ \
size_t th = 4; \
@@ -888,7 +885,7 @@
M_ASSERT (org_tab == tab); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _special_stable_sort)(array_t l) \
{ \
if (M_UNLIKELY (l->size < 2)) \
@@ -907,7 +904,7 @@
,) /* IF CMP oplist */ \
\
M_IF_METHOD(EQUAL, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _equal_p)(const array_t array1, \
const array_t array2) \
{ \
@@ -926,7 +923,7 @@
, /* no EQUAL */ ) \
\
M_IF_METHOD(HASH, oplist)( \
static inline size_t \
M_INLINE size_t \
M_F(name, _hash)(const array_t array) \
{ \
M_ARRA4_CONTRACT(array); \
@@ -939,7 +936,7 @@
} \
, /* no HASH */ ) \
\
static inline void \
M_INLINE void \
M_F(name, _splice)(array_t a1, array_t a2) \
{ \
M_ARRA4_CONTRACT(a1); \
@@ -972,7 +969,7 @@
#define M_ARRA4_DEF_IO(name, type, oplist, array_t, it_t) \
\
M_IF_METHOD(GET_STR, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _get_str)(m_string_t str, array_t const array, \
bool append) \
{ \
@@ -992,7 +989,7 @@
, /* no GET_STR */ ) \
\
M_IF_METHOD(OUT_STR, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _out_str)(FILE *file, const array_t array) \
{ \
M_ARRA4_CONTRACT(array); \
@@ -1009,39 +1006,35 @@
, /* no OUT_STR */ ) \
\
M_IF_METHOD2(PARSE_STR, INIT, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _parse_str)(array_t array, const char str[], const char**endp) \
{ \
M_ARRA4_CONTRACT(array); \
M_ASSERT (str != NULL); \
M_F(name,_reset)(array); \
bool success = false; \
int c = *str++; \
if (M_UNLIKELY (c != '[')) goto exit; \
c = *str++; \
if (M_UNLIKELY (c == ']')) { success = true; goto exit; } \
if (M_UNLIKELY (c == 0)) goto exit; \
if (M_UNLIKELY (c != '[')) { c = 0; goto exit; } \
c = m_core_str_nospace(&str); \
if (M_UNLIKELY (c == ']')) { goto exit; } \
if (M_UNLIKELY (c == 0)) { goto exit; } \
str--; \
type item; \
M_CALL_INIT(oplist, item); \
do { \
bool b = M_CALL_PARSE_STR(oplist, item, str, &str); \
do { c = *str++; } while (isspace(c)); \
if (b == false || c == 0) { goto exit_clear; } \
M_F(name, _push_back)(array, item); \
} while (c == M_GET_SEPARATOR oplist); \
M_ARRA4_CONTRACT(array); \
success = (c == ']'); \
exit_clear: \
M_CALL_CLEAR(oplist, item); \
M_QLET(item, type, oplist) { \
do { \
bool b = M_CALL_PARSE_STR(oplist, item, str, &str); \
c = m_core_str_nospace(&str); \
if (b == false || c == 0) { c = 0; break; } \
M_F(name, _push_back)(array, item); \
} while (c == M_GET_SEPARATOR oplist); \
} \
exit: \
M_ARRA4_CONTRACT(array); \
if (endp) *endp = str; \
return success; \
return c == ']'; \
} \
, /* no PARSE_STR & INIT */ ) \
\
M_IF_METHOD2(IN_STR, INIT, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _in_str)(array_t array, FILE *file) \
{ \
M_ARRA4_CONTRACT(array); \
@@ -1053,22 +1046,21 @@
if (M_UNLIKELY (c == ']')) return true; \
if (M_UNLIKELY (c == EOF)) return false; \
ungetc(c, file); \
type item; \
M_CALL_INIT(oplist, item); \
do { \
bool b = M_CALL_IN_STR(oplist, item, file); \
do { c = fgetc(file); } while (isspace(c)); \
if (b == false || c == EOF) { break; } \
M_F(name, _push_back)(array, item); \
} while (c == M_GET_SEPARATOR oplist); \
M_CALL_CLEAR(oplist, item); \
M_QLET(item, type, oplist) { \
do { \
bool b = M_CALL_IN_STR(oplist, item, file); \
c = m_core_fgetc_nospace(file); \
if (b == false || c == EOF) { c = 0; break; } \
M_F(name, _push_back)(array, item); \
} while (c == M_GET_SEPARATOR oplist); \
} \
M_ARRA4_CONTRACT(array); \
return c == ']'; \
} \
, /* no IN_STR & INIT */ ) \
\
M_IF_METHOD(OUT_SERIAL, oplist)( \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _out_serial)(m_serial_write_t f, const array_t array) \
{ \
M_ARRA4_CONTRACT(array); \
@@ -1089,7 +1081,7 @@
, /* no OUT_SERIAL */ ) \
\
M_IF_METHOD2(IN_SERIAL, INIT, oplist)( \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _in_serial)(array_t array, m_serial_read_t f) \
{ \
M_ARRA4_CONTRACT(array); \
@@ -1102,19 +1094,15 @@
if (M_UNLIKELY (ret != M_SERIAL_OK_CONTINUE)) { \
return ret; \
} \
if (estimated_size != 0) { \
/* The format has given an estimation of the array size */ \
M_F(name, _reserve)(array, estimated_size); \
M_F(name, _reserve)(array, estimated_size); \
M_QLET(item, type, oplist) { \
do { \
ret = M_CALL_IN_SERIAL(oplist, item, f); \
if (ret != M_SERIAL_OK_DONE) { break; } \
M_F(name, _push_back)(array, item); \
ret = f->m_interface->read_array_next(local, f); \
} while (ret == M_SERIAL_OK_CONTINUE); \
} \
type item; \
M_CALL_INIT(oplist, item); \
do { \
ret = M_CALL_IN_SERIAL(oplist, item, f); \
if (ret != M_SERIAL_OK_DONE) { break; } \
M_F(name, _push_back)(array, item); \
ret = f->m_interface->read_array_next(local, f); \
} while (ret == M_SERIAL_OK_CONTINUE); \
M_CALL_CLEAR(oplist, item); \
M_ARRA4_CONTRACT(array); \
return ret; \
} \
@@ -1122,7 +1110,7 @@
/* Definition of the emplace_back function for arrays */
#define M_ARRA4_EMPLACE_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
static inline void \
M_INLINE void \
function_name(name_t v \
M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \
{ \
+1 -1
View File
@@ -226,7 +226,7 @@ typedef _Atomic(uintmax_t) atomic_uintmax_t;
#endif
/* (INTERNAL) Unlock the mutex and return the given value */
static inline long long atomic_fetch_unlock (m_mutex_t *lock, long long val)
M_INLINE long long atomic_fetch_unlock (m_mutex_t *lock, long long val)
{
m_mutex_unlock (*lock);
return val;
+51 -51
View File
@@ -81,7 +81,7 @@ typedef struct m_bitset_it_s {
} m_bitset_it_t[1];
/* Initialize a bitset (CONSTRUCTOR) */
static inline void
M_INLINE void
m_bitset_init(m_bitset_t t)
{
M_ASSERT (t != NULL);
@@ -93,7 +93,7 @@ m_bitset_init(m_bitset_t t)
}
/* Clean a bitset */
static inline void
M_INLINE void
m_bitset_reset(m_bitset_t t)
{
M_B1TSET_CONTRACT(t);
@@ -101,7 +101,7 @@ m_bitset_reset(m_bitset_t t)
}
/* Clear a bitset (DESTRUCTOR) */
static inline void
M_INLINE void
m_bitset_clear(m_bitset_t t)
{
m_bitset_reset(t);
@@ -114,7 +114,7 @@ m_bitset_clear(m_bitset_t t)
}
/* Set a bitset to another one */
static inline void
M_INLINE void
m_bitset_set(m_bitset_t d, const m_bitset_t s)
{
M_B1TSET_CONTRACT(d);
@@ -141,7 +141,7 @@ m_bitset_set(m_bitset_t d, const m_bitset_t s)
}
/* Initialize & set a bitset to another one (CONSTRUCTOR) */
static inline void
M_INLINE void
m_bitset_init_set(m_bitset_t d, const m_bitset_t s)
{
M_ASSERT (d != s);
@@ -150,7 +150,7 @@ m_bitset_init_set(m_bitset_t d, const m_bitset_t s)
}
/* Initialize & move a bitset (CONSTRUCTOR) from another one (DESTRUCTOR) */
static inline void
M_INLINE void
m_bitset_init_move(m_bitset_t d, m_bitset_t s)
{
M_B1TSET_CONTRACT(s);
@@ -164,7 +164,7 @@ m_bitset_init_move(m_bitset_t d, m_bitset_t s)
}
/* Move a bitset from another one (DESTRUCTOR) */
static inline void
M_INLINE void
m_bitset_move(m_bitset_t d, m_bitset_t s)
{
m_bitset_clear(d);
@@ -172,7 +172,7 @@ m_bitset_move(m_bitset_t d, m_bitset_t s)
}
/* Set the bit 'i' in the bitset to the value 'x' */
static inline void
M_INLINE void
m_bitset_set_at(m_bitset_t v, size_t i, bool x)
{
M_B1TSET_CONTRACT(v);
@@ -187,7 +187,7 @@ m_bitset_set_at(m_bitset_t v, size_t i, bool x)
}
/* Flip the bit 'i' in the bitset */
static inline void
M_INLINE void
m_bitset_flip_at(m_bitset_t v, size_t i)
{
M_B1TSET_CONTRACT(v);
@@ -200,7 +200,7 @@ m_bitset_flip_at(m_bitset_t v, size_t i)
}
/* Push back the boolean 'x' in the bitset (increasing the bitset) */
static inline void
M_INLINE void
m_bitset_push_back (m_bitset_t v, bool x)
{
M_B1TSET_CONTRACT (v);
@@ -239,7 +239,7 @@ m_bitset_push_back (m_bitset_t v, bool x)
}
/* Resize the bitset to have exactly 'size' bits */
static inline void
M_INLINE void
m_bitset_resize (m_bitset_t v, size_t size)
{
M_B1TSET_CONTRACT (v);
@@ -287,7 +287,7 @@ m_bitset_resize (m_bitset_t v, size_t size)
}
/* Reserve allocation in the bitset to accomodate at least 'size' bits without reallocation */
static inline void
M_INLINE void
m_bitset_reserve (m_bitset_t v, size_t alloc)
{
M_B1TSET_CONTRACT (v);
@@ -319,7 +319,7 @@ m_bitset_reserve (m_bitset_t v, size_t alloc)
* NOTE: Interface is a little bit different:
* It doesn't return a pointer to the data, but the data itself.
*/
static inline bool
M_INLINE bool
m_bitset_get(const m_bitset_t v, size_t i)
{
M_B1TSET_CONTRACT(v);
@@ -334,7 +334,7 @@ m_bitset_get(const m_bitset_t v, size_t i)
#define m_bitset_cget m_bitset_get
/* Pop back the last bit in the bitset */
static inline void
M_INLINE void
m_bitset_pop_back(bool *dest, m_bitset_t v)
{
M_B1TSET_CONTRACT (v);
@@ -354,7 +354,7 @@ m_bitset_pop_back(bool *dest, m_bitset_t v)
}
/* Return the front bit value in the bitset */
static inline bool
M_INLINE bool
m_bitset_front(m_bitset_t v)
{
M_B1TSET_CONTRACT (v);
@@ -363,7 +363,7 @@ m_bitset_front(m_bitset_t v)
}
/* Return the back bit value in the bitset */
static inline bool
M_INLINE bool
m_bitset_back(m_bitset_t v)
{
M_B1TSET_CONTRACT (v);
@@ -372,7 +372,7 @@ m_bitset_back(m_bitset_t v)
}
/* Test if the bitset is empty (no bits stored)*/
static inline bool
M_INLINE bool
m_bitset_empty_p(m_bitset_t v)
{
M_B1TSET_CONTRACT (v);
@@ -380,7 +380,7 @@ m_bitset_empty_p(m_bitset_t v)
}
/* Return the number of bits of the bitset */
static inline size_t
M_INLINE size_t
m_bitset_size(m_bitset_t v)
{
M_B1TSET_CONTRACT (v);
@@ -388,7 +388,7 @@ m_bitset_size(m_bitset_t v)
}
/* Return the capacity in limbs of the bitset */
static inline size_t
M_INLINE size_t
m_bitset_capacity(m_bitset_t v)
{
M_B1TSET_CONTRACT (v);
@@ -396,7 +396,7 @@ m_bitset_capacity(m_bitset_t v)
}
/* Swap the bit at index i and j of the bitset */
static inline void
M_INLINE void
m_bitset_swap_at (m_bitset_t v, size_t i, size_t j)
{
M_ASSERT_INDEX(i, v->size);
@@ -409,7 +409,7 @@ m_bitset_swap_at (m_bitset_t v, size_t i, size_t j)
}
/* Swap the bitsets */
static inline void
M_INLINE void
m_bitset_swap (m_bitset_t v1, m_bitset_t v2)
{
M_B1TSET_CONTRACT (v1);
@@ -425,7 +425,7 @@ m_bitset_swap (m_bitset_t v1, m_bitset_t v2)
* integrating the carry in the lowest position.
* Return the new carry.
*/
static inline m_b1tset_limb_ct
M_INLINE m_b1tset_limb_ct
m_b1tset_lshift(m_b1tset_limb_ct ptr[], size_t n, m_b1tset_limb_ct carry)
{
for(size_t i = 0; i < n; i++) {
@@ -440,7 +440,7 @@ m_b1tset_lshift(m_b1tset_limb_ct ptr[], size_t n, m_b1tset_limb_ct carry)
* integrating the carry in the lowest position.
* Return the new carry.
*/
static inline m_b1tset_limb_ct
M_INLINE m_b1tset_limb_ct
m_b1tset_rshift(m_b1tset_limb_ct ptr[], size_t n, m_b1tset_limb_ct carry)
{
for(size_t i = n - 1; i < n; i--) {
@@ -453,7 +453,7 @@ m_b1tset_rshift(m_b1tset_limb_ct ptr[], size_t n, m_b1tset_limb_ct carry)
/* Insert a new bit at position 'key' of value 'value' in the bitset 'set'
shifting the set accordingly */
static inline void
M_INLINE void
m_bitset_push_at(m_bitset_t set, size_t key, bool value)
{
M_B1TSET_CONTRACT (set);
@@ -481,7 +481,7 @@ m_bitset_push_at(m_bitset_t set, size_t key, bool value)
/* Pop a new bit at position 'key' in the bitset
* and return in *dest its value if *dest exists */
static inline void
M_INLINE void
m_bitset_pop_at(bool *dest, m_bitset_t set, size_t key)
{
M_B1TSET_CONTRACT (set);
@@ -507,7 +507,7 @@ m_bitset_pop_at(bool *dest, m_bitset_t set, size_t key)
}
/* Test if two bitsets are equal */
static inline bool
M_INLINE bool
m_bitset_equal_p (const m_bitset_t set1, const m_bitset_t set2)
{
M_B1TSET_CONTRACT (set1);
@@ -524,7 +524,7 @@ m_bitset_equal_p (const m_bitset_t set1, const m_bitset_t set2)
}
/* Initialize an iterator to the first bit of the biset */
static inline void
M_INLINE void
m_bitset_it(m_bitset_it_t it, m_bitset_t set)
{
M_B1TSET_CONTRACT (set);
@@ -533,7 +533,7 @@ m_bitset_it(m_bitset_it_t it, m_bitset_t set)
}
/* Initialize an iterator to reference the same bit as the given one*/
static inline void
M_INLINE void
m_bitset_it_set(m_bitset_it_t it, const m_bitset_it_t itorg)
{
M_ASSERT (it != NULL && itorg != NULL);
@@ -542,7 +542,7 @@ m_bitset_it_set(m_bitset_it_t it, const m_bitset_it_t itorg)
}
/* Initialize an iterator to reference the last bit of the bitset*/
static inline void
M_INLINE void
m_bitset_it_last(m_bitset_it_t it, m_bitset_t set)
{
M_B1TSET_CONTRACT (set);
@@ -551,7 +551,7 @@ m_bitset_it_last(m_bitset_it_t it, m_bitset_t set)
}
/* Initialize an iterator to reference no valid bit of the bitset*/
static inline void
M_INLINE void
m_bitset_it_end(m_bitset_it_t it, m_bitset_t set)
{
M_B1TSET_CONTRACT (set);
@@ -560,7 +560,7 @@ m_bitset_it_end(m_bitset_it_t it, m_bitset_t set)
}
/* Test if an iterator references no valid bit of the bitset anymore */
static inline bool
M_INLINE bool
m_bitset_end_p(const m_bitset_it_t it)
{
M_ASSERT (it != NULL && it->set != NULL);
@@ -568,7 +568,7 @@ m_bitset_end_p(const m_bitset_it_t it)
}
/* Test if an iterator references the last (or end) bit of the bitset anymore */
static inline bool
M_INLINE bool
m_bitset_last_p(const m_bitset_it_t it)
{
M_ASSERT (it != NULL && it->set != NULL);
@@ -578,7 +578,7 @@ m_bitset_last_p(const m_bitset_it_t it)
}
/* Test if both iterators reference the same bit */
static inline bool
M_INLINE bool
m_bitset_it_equal_p(const m_bitset_it_t it1, const m_bitset_it_t it2)
{
M_ASSERT (it1 != NULL && it2 != NULL);
@@ -586,7 +586,7 @@ m_bitset_it_equal_p(const m_bitset_it_t it1, const m_bitset_it_t it2)
}
/* Move the iterator to the next bit */
static inline void
M_INLINE void
m_bitset_next(m_bitset_it_t it)
{
M_ASSERT (it != NULL && it->set != NULL);
@@ -594,7 +594,7 @@ m_bitset_next(m_bitset_it_t it)
}
/* Move the iterator to the previous bit */
static inline void
M_INLINE void
m_bitset_previous(m_bitset_it_t it)
{
M_ASSERT (it != NULL && it->set != NULL);
@@ -605,7 +605,7 @@ m_bitset_previous(m_bitset_it_t it)
/* Return a pointer to the bit referenced by the iterator
* Only one reference is possible at a time per iterator */
static inline const bool *
M_INLINE const bool *
m_bitset_cref(m_bitset_it_t it)
{
M_ASSERT (it != NULL && it->set != NULL);
@@ -614,7 +614,7 @@ m_bitset_cref(m_bitset_it_t it)
}
/* Output the bitset as a formatted text in a FILE */
static inline void
M_INLINE void
m_bitset_out_str(FILE *file, const m_bitset_t set)
{
M_B1TSET_CONTRACT (set);
@@ -629,7 +629,7 @@ m_bitset_out_str(FILE *file, const m_bitset_t set)
}
/* Input the bitset from a formatted text in a FILE */
static inline bool
M_INLINE bool
m_bitset_in_str(m_bitset_t set, FILE *file)
{
M_B1TSET_CONTRACT (set);
@@ -648,7 +648,7 @@ m_bitset_in_str(m_bitset_t set, FILE *file)
}
/* Parse the bitset from a formatted text in a C string */
static inline bool
M_INLINE bool
m_bitset_parse_str(m_bitset_t set, const char str[], const char **endptr)
{
M_B1TSET_CONTRACT (set);
@@ -672,7 +672,7 @@ m_bitset_parse_str(m_bitset_t set, const char str[], const char **endptr)
}
/* Set the bitset from a formatted text in a C string */
static inline bool
M_INLINE bool
m_bitset_set_str(m_bitset_t dest, const char str[])
{
return m_bitset_parse_str(dest, str, NULL);
@@ -680,7 +680,7 @@ m_bitset_set_str(m_bitset_t dest, const char str[])
/* Perform an AND operation between the bitsets,
* up to the minimum size of both bitsets */
static inline void
M_INLINE void
m_bitset_and(m_bitset_t dest, const m_bitset_t src)
{
M_B1TSET_CONTRACT(dest);
@@ -696,7 +696,7 @@ m_bitset_and(m_bitset_t dest, const m_bitset_t src)
/* Perform an OR operation between the bitsets,
* up to the minimum size of both bitsets */
static inline void
M_INLINE void
m_bitset_or(m_bitset_t dest, const m_bitset_t src)
{
M_B1TSET_CONTRACT(dest);
@@ -712,7 +712,7 @@ m_bitset_or(m_bitset_t dest, const m_bitset_t src)
/* Perform an XOR operation between the bitsets,
* up to the minimum size of both bitsets */
static inline void
M_INLINE void
m_bitset_xor(m_bitset_t dest, const m_bitset_t src)
{
M_B1TSET_CONTRACT(dest);
@@ -733,7 +733,7 @@ m_bitset_xor(m_bitset_t dest, const m_bitset_t src)
}
/* Perform a NOT operation of the bitset */
static inline void
M_INLINE void
m_bitset_not(m_bitset_t dest)
{
M_B1TSET_CONTRACT(dest);
@@ -751,7 +751,7 @@ m_bitset_not(m_bitset_t dest)
}
/* Copute a hash of the bitset */
static inline size_t
M_INLINE size_t
m_bitset_hash(const m_bitset_t set)
{
M_B1TSET_CONTRACT(set);
@@ -764,7 +764,7 @@ m_bitset_hash(const m_bitset_t set)
}
/* Count the number of leading zero */
static inline size_t
M_INLINE size_t
m_bitset_clz(const m_bitset_t set)
{
M_B1TSET_CONTRACT(set);
@@ -792,7 +792,7 @@ m_bitset_clz(const m_bitset_t set)
}
/* Count the number of trailing zero */
static inline size_t
M_INLINE size_t
m_bitset_ctz(const m_bitset_t set)
{
M_B1TSET_CONTRACT(set);
@@ -819,14 +819,14 @@ m_bitset_ctz(const m_bitset_t set)
// For GCC or CLANG or ICC
#if defined(__GNUC__)
static inline size_t m_b1tset_popcount64(m_b1tset_limb_ct limb)
M_INLINE size_t m_b1tset_popcount64(m_b1tset_limb_ct limb)
{
return (size_t) __builtin_popcountll(limb);
}
#else
// MSVC __popcnt64 may not exist on the target architecture (no emulation layer)
// Use emulation layer: https://en.wikipedia.org/wiki/Hamming_weight
static inline size_t m_b1tset_popcount64(m_b1tset_limb_ct limb)
M_INLINE size_t m_b1tset_popcount64(m_b1tset_limb_ct limb)
{
limb = limb - ((limb >> 1) & 0x5555555555555555ULL);
limb = (limb & 0x3333333333333333ULL) + ((limb >> 2) & 0x3333333333333333ULL);
@@ -836,7 +836,7 @@ static inline size_t m_b1tset_popcount64(m_b1tset_limb_ct limb)
#endif
/* Count the number of 1 */
static inline size_t
M_INLINE size_t
m_bitset_popcount(const m_bitset_t set)
{
M_B1TSET_CONTRACT(set);
@@ -962,7 +962,7 @@ M_BEGIN_PROTECTED_CODE
/* Output to a m_string_t 'str' the formatted text representation of the bitset 'set'
or append it to the strinf (append=true) */
static inline void
M_INLINE void
m_bitset_get_str(m_string_t str, const m_bitset_t set, bool append)
{
M_B1TSET_CONTRACT (set);
+51 -57
View File
@@ -188,9 +188,6 @@
M_IF_METHOD(IN_SERIAL, oplist)(IN_SERIAL(M_F(name, _in_serial)),), \
M_IF_METHOD(EQUAL, oplist)(EQUAL(M_F(name, _equal_p)),), \
M_IF_METHOD(HASH, oplist)(HASH(M_F(name, _hash)),) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
)
@@ -247,9 +244,6 @@
M_IF_METHOD_BOTH(IN_SERIAL, key_oplist, value_oplist)(IN_SERIAL(M_F(name, _in_serial)),), \
M_IF_METHOD_BOTH(EQUAL, key_oplist, value_oplist)(EQUAL(M_F(name, _equal_p)),), \
M_IF_METHOD_BOTH(HASH, key_oplist, value_oplist)(HASH(M_F(name, _hash)),) \
,M_IF_METHOD(NEW, key_oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, key_oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, key_oplist)(DEL(M_GET_DEL oplist),) \
)
@@ -412,7 +406,7 @@
\
/* Allocate a new node */ \
/* TODO: Can be specialized to alloc for leaf or for non leaf */ \
static inline node_t M_F(name, _new_node)(void) \
M_INLINE node_t M_F(name, _new_node)(void) \
{ \
M_STATIC_ASSERT(N >= 2, M_LIB_ILLEGAL_PARAM, \
"Number of items per node shall be >= 2."); \
@@ -426,14 +420,14 @@
return n; \
} \
\
static inline void M_F(name, _init)(tree_t b) \
M_INLINE void M_F(name, _init)(tree_t b) \
{ \
b->root = M_F(name, _new_node)(); \
b->size = 0; \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
} \
\
static inline bool M_F(name, _is_leaf)(const node_t n) \
M_INLINE bool M_F(name, _is_leaf)(const node_t n) \
{ \
/* We consider the empty node as a leaf */ \
/* Only the root node can be empty */ \
@@ -441,7 +435,7 @@
} \
\
/* Return the number of keys of the node */ \
static inline int M_F(name, _get_num)(const node_t n) \
M_INLINE int M_F(name, _get_num)(const node_t n) \
{ \
int num = n->num; \
num = num < 0 ? -num : num; \
@@ -449,7 +443,7 @@
return num; \
} \
\
static inline void M_F(name, _reset)(tree_t b) \
M_INLINE void M_F(name, _reset)(tree_t b) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
node_t next, n = b->root; \
@@ -492,7 +486,7 @@
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
} \
\
static inline void M_F(name, _clear)(tree_t b) \
M_INLINE void M_F(name, _clear)(tree_t b) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
M_F(name, _reset)(b); \
@@ -502,7 +496,7 @@
} \
\
/* Copy recursively the node 'o' of root node 'root' */ \
static inline node_t M_F(name, _copy_node)(const node_t o, const node_t root) \
M_INLINE node_t M_F(name, _copy_node)(const node_t o, const node_t root) \
{ \
node_t n = M_F(name, _new_node)(); \
/* Set default number of keys and type to copy */ \
@@ -548,7 +542,7 @@
return n; \
} \
\
static inline void M_F(name, _init_set)(tree_t b, const tree_t o) \
M_INLINE void M_F(name, _init_set)(tree_t b, const tree_t o) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, o); \
M_ASSERT (b != NULL); \
@@ -558,7 +552,7 @@
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
} \
\
static inline void M_F(name, _set)(tree_t b, const tree_t o) \
M_INLINE void M_F(name, _set)(tree_t b, const tree_t o) \
{ \
/* NOTE: We could reuse the already allocated nodes of 'b'. \
Not sure if it worth the effort */ \
@@ -566,20 +560,20 @@
M_F(name, _init_set)(b, o); \
} \
\
static inline bool M_F(name, _empty_p)(const tree_t b) \
M_INLINE bool M_F(name, _empty_p)(const tree_t b) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
/* root shall be an empty leaf */ \
return b->size == 0; \
} \
\
static inline size_t M_F(name, _size)(const tree_t b) \
M_INLINE size_t M_F(name, _size)(const tree_t b) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
return b->size; \
} \
\
static inline node_t M_F(name, _search_for_leaf)(pit_t pit, const tree_t b, key_t const key) \
M_INLINE node_t M_F(name, _search_for_leaf)(pit_t pit, const tree_t b, key_t const key) \
{ \
node_t n = b->root; \
int np = 0; \
@@ -608,7 +602,7 @@
return n; \
} \
\
static inline value_t *M_F(name, _get)(const tree_t b, key_t const key) \
M_INLINE value_t *M_F(name, _get)(const tree_t b, key_t const key) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
pit_t pit; \
@@ -628,12 +622,12 @@
return NULL; \
} \
\
static inline value_t const *M_F(name, _cget)(const tree_t b, key_t const key) \
M_INLINE value_t const *M_F(name, _cget)(const tree_t b, key_t const key) \
{ \
return M_CONST_CAST(value_t, M_F(name, _get)(b, key)); \
} \
\
static inline int \
M_INLINE int \
M_F(name, _search_and_insert_in_leaf)(node_t n, key_t const key \
M_IF(isMap)( M_DEFERRED_COMMA value_t const value,) ) \
{ \
@@ -665,7 +659,7 @@
return i; \
} \
\
static inline int \
M_INLINE int \
M_F(name, _search_and_insert_in_node)(node_t n, node_t l, key_t key) \
{ \
M_ASSERT (!M_F(name, _is_leaf)(n)); \
@@ -688,7 +682,7 @@
return i; \
} \
\
static inline void \
M_INLINE void \
M_IF(isMap)(M_F(name, _set_at),M_F(name,_push))(tree_t b, key_t const key \
M_IF(isMap)(M_DEFERRED_COMMA value_t const value,)) \
{ \
@@ -778,7 +772,7 @@
} \
} \
\
static inline value_t *M_F(name, _safe_get)(tree_t b, key_t const key) \
M_INLINE value_t *M_F(name, _safe_get)(tree_t b, key_t const key) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
/* Not optimized implementation */ \
@@ -797,7 +791,7 @@
return ret; \
} \
\
static inline int \
M_INLINE int \
M_F(name, _search_and_remove_in_leaf)(node_t n, key_t const key) \
{ \
M_ASSERT(M_F(name, _is_leaf)(n)); \
@@ -817,7 +811,7 @@
return -1; /* Not found */ \
} \
\
static inline void M_F(name, _left_shift)(node_t parent, int k) \
M_INLINE void M_F(name, _left_shift)(node_t parent, int k) \
{ \
M_ASSERT (parent != NULL && !M_F(name, _is_leaf)(parent)); \
M_ASSERT (0 <= k && k < M_F(name, _get_num)(parent)); \
@@ -852,7 +846,7 @@
M_ASSERT (left->num != 0); \
} \
\
static inline void M_F(name, _right_shift)(node_t parent, int k) \
M_INLINE void M_F(name, _right_shift)(node_t parent, int k) \
{ \
M_ASSERT (parent != NULL && !M_F(name, _is_leaf)(parent)); \
M_ASSERT (0 <= k && k < M_F(name, _get_num)(parent)); \
@@ -886,7 +880,7 @@
M_ASSERT (left->num != 0); \
} \
\
static inline void M_F(name, _merge_node)(node_t parent, int k, bool leaf) \
M_INLINE void M_F(name, _merge_node)(node_t parent, int k, bool leaf) \
{ \
M_ASSERT (parent != NULL && !M_F(name, _is_leaf)(parent)); \
M_ASSERT (0 <= k && k < M_F(name, _get_num(parent))); \
@@ -921,7 +915,7 @@
\
/* We can also cache the index when we descend the tree. \
TODO: Bench if this is worth the effort.*/ \
static inline int \
M_INLINE int \
M_F(name, _search_for_node)(node_t parent, node_t child) \
{ \
M_ASSERT (!M_F(name, _is_leaf)(parent)); \
@@ -934,7 +928,7 @@
} \
} \
\
static inline bool M_F(name, _erase)(tree_t b, key_t const key) \
M_INLINE bool M_F(name, _erase)(tree_t b, key_t const key) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
pit_t pit; \
@@ -990,7 +984,7 @@
} \
} \
\
static inline bool M_F(name, _pop_at)(value_t *ptr, tree_t b, key_t const key) \
M_INLINE bool M_F(name, _pop_at)(value_t *ptr, tree_t b, key_t const key) \
{ \
if (ptr != NULL) { \
value_t *ref = M_F(name, _get)(b, key); \
@@ -1002,7 +996,7 @@
return M_F(name, _erase)(b, key); \
} \
\
static inline value_t * \
M_INLINE value_t * \
M_F(name, _min)(const tree_t b) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
@@ -1015,7 +1009,7 @@
return &n->M_IF(isMap)(kind.value, key)[0]; \
} \
\
static inline value_t * \
M_INLINE value_t * \
M_F(name, _max)(const tree_t b) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
@@ -1028,19 +1022,19 @@
return &n->M_IF(isMap)(kind.value, key)[-n->num-1]; \
} \
\
static inline value_t const * \
M_INLINE value_t const * \
M_F(name, _cmin)(const tree_t tree) \
{ \
return M_CONST_CAST(value_t, M_F(name, _min)(tree)); \
} \
\
static inline value_t const * \
M_INLINE value_t const * \
M_F(name, _cmax)(const tree_t tree) \
{ \
return M_CONST_CAST(value_t, M_F(name, _max)(tree)); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_move)(tree_t b, tree_t ref) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, ref); \
@@ -1051,7 +1045,7 @@
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _move)(tree_t b, tree_t ref) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
@@ -1062,7 +1056,7 @@
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _swap)(tree_t tree1, tree_t tree2) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, tree1); \
@@ -1076,7 +1070,7 @@
/* Define iterator functions. */
#define M_BPTR33_DEF_IT(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
\
static inline void \
M_INLINE void \
M_F(name, _it)(it_t it, const tree_t b) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
@@ -1090,7 +1084,7 @@
it->idx = 0; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_end)(it_t it, const tree_t b) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
@@ -1104,7 +1098,7 @@
it->idx = -n->num; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_set)(it_t itd, const it_t its) \
{ \
M_ASSERT (itd != NULL && its != NULL); \
@@ -1112,7 +1106,7 @@
itd->idx = its->idx; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _end_p)(it_t it) \
{ \
M_ASSERT (it != NULL && it->node != NULL); \
@@ -1120,13 +1114,13 @@
return it->node->next ==NULL && it->idx >= -it->node->num; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_equal_p)(const it_t it1, const it_t it2) \
{ \
return it1->node == it2->node && it1->idx == it2->idx; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _next)(it_t it) \
{ \
M_ASSERT (it != NULL && it->node != NULL); \
@@ -1138,7 +1132,7 @@
} \
} \
\
static inline subtype_t * \
M_INLINE subtype_t * \
M_F(name, _ref)(it_t it) \
{ \
M_ASSERT (it != NULL && it->node != NULL); \
@@ -1153,14 +1147,14 @@
); \
} \
\
static inline subtype_t const * \
M_INLINE subtype_t const * \
M_F(name, _cref)(it_t it) \
{ \
return M_CONST_CAST(subtype_t, M_F(name, _ref)(it)); \
} \
\
\
static inline void \
M_INLINE void \
M_F(name, _it_from)(it_t it, const tree_t b, key_t const key) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, b); \
@@ -1181,7 +1175,7 @@
it->idx = i; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_until_p)(it_t it, key_t const key) \
{ \
M_ASSERT (it != NULL); \
@@ -1191,7 +1185,7 @@
return (cmp >= 0); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_while_p)(it_t it, key_t const key) \
{ \
M_ASSERT (it != NULL); \
@@ -1206,7 +1200,7 @@
#define M_BPTR33_DEF_EXT(name, N, key_t, key_oplist, value_t, value_oplist, isMap, isMulti, tree_t, node_t, pit_t, it_t, subtype_t) \
\
M_IF_METHOD_BOTH(EQUAL, key_oplist, value_oplist)( \
static inline bool M_F(name,_equal_p)(const tree_t t1, const tree_t t2) { \
M_INLINE bool M_F(name,_equal_p)(const tree_t t1, const tree_t t2) { \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t2); \
if (t1->size != t2->size) return false; \
@@ -1242,7 +1236,7 @@
, /* NO EQUAL METHOD */ ) \
\
M_IF_METHOD_BOTH(HASH, key_oplist, value_oplist)( \
static inline size_t M_F(name,_hash)(const tree_t t1) { \
M_INLINE size_t M_F(name,_hash)(const tree_t t1) { \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
M_HASH_DECL(hash); \
/* NOTE: We can't compute the hash directly for the same reason \
@@ -1264,7 +1258,7 @@
, /* NO HASH METHOD */ ) \
\
M_IF_METHOD_BOTH(GET_STR, key_oplist, value_oplist)( \
static inline void M_F(name, _get_str)(m_string_t str, \
M_INLINE void M_F(name, _get_str)(m_string_t str, \
const tree_t t1, bool append) { \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
M_ASSERT(str != NULL); \
@@ -1292,7 +1286,7 @@
, /* NO GET_STR */ ) \
\
M_IF_METHOD_BOTH(OUT_STR, key_oplist, value_oplist)( \
static inline void \
M_INLINE void \
M_F(name, _out_str)(FILE *file, tree_t const t1) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
@@ -1320,7 +1314,7 @@
, /* no out_str */ ) \
\
M_IF_METHOD_BOTH(PARSE_STR, key_oplist, value_oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _parse_str)(tree_t t1, const char str[], const char **endp) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
@@ -1362,7 +1356,7 @@
, /* no parse_str */ ) \
\
M_IF_METHOD_BOTH(IN_STR, key_oplist, value_oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _in_str)(tree_t t1, FILE *file) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
@@ -1400,7 +1394,7 @@
, /* no in_str */ ) \
\
M_IF_METHOD_BOTH(OUT_SERIAL, key_oplist, value_oplist)( \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _out_serial)(m_serial_write_t f, tree_t const t1) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
@@ -1444,7 +1438,7 @@
, /* no OUT_SERIAL */ ) \
\
M_IF_METHOD_BOTH(IN_SERIAL, key_oplist, value_oplist)( \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _in_serial)(tree_t t1, m_serial_read_t f) \
{ \
M_BPTR33_CONTRACT(N, isMulti, key_oplist, t1); \
+92 -60
View File
@@ -51,23 +51,53 @@ typedef enum {
} m_buffer_policy_e;
// TOMOVE to m-core
#define M_DEF_AS(macro, ...) \
M_BEGIN_PROTECTED_CODE \
M_BY_NARGS(macro, __VA_ARGS__)(__VA_ARGS__) \
M_END_PROTECTED_CODE
#define M_SIZE_AS(oplist, default) M_GET_METHOD(SIZE, default, M_OPFLAT oplist)
#define M_POLICY_AS(oplist, default) M_GET_METHOD(POLICY, default, M_OPFLAT oplist)
#define M_TYPE_AS(oplist, default) M_GET_METHOD(TYPE, default, M_OPFLAT oplist)
#define M_TYPE2OPL(type) M_GLOBAL_OPLIST_OR_DEF(type)()
/* Define a lock based buffer.
If size is 0, then the size will only be defined at run-time when initializing the buffer,
otherwise the size will be a compile time constant.
USAGE: BUFFER_DEF(name, type, size_of_buffer_or_0, policy[, oplist]) */
#define M_BUFFER_DEF(name, type, m_size, ... ) \
M_BUFFER_DEF_AS(name, M_F(name, _t), type, m_size, __VA_ARGS__)
#define M_BUFFER_DEF(a, b, c, ... ) M_DEF_AS(M_BUFF3R_DEF, a, b, c, __VA_ARGS__)
#define M_BUFF3R_DEF__4(n, t, s, p) M_BUFF3R_DEF_P1((n, t, s, p, M_TYPE2OPL(t), M_F(n, _t)))
#define M_BUFF3R_DEF__5(n, t, s, p, o) M_BUFF3R_DEF_P1((n, t, s, p, o, M_F(n, _t)))
#define M_BUFF3R_DEF__6(n, t, s, p, o)
#define M_BUFF3R_DEF__7(n, t, s, p, o)
#define M_BUFF3R_DEF__8(n, t, s, p, o)
#define M_BUFF3R_DEF__9(n, t, s, p, o)
/* Define a lock based buffer
as the provided type name_t.
USAGE: BUFFER_DEF_AS(name, name_t, type, size_of_buffer_or_0, policy[, oplist of type]) */
#define M_BUFFER_DEF_AS(name, name_t, type, m_size, ... ) \
M_BEGIN_PROTECTED_CODE \
M_BUFF3R_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
((name, type, m_size,__VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(type)(), name_t ), \
(name, type, m_size,__VA_ARGS__, name_t ))) \
M_END_PROTECTED_CODE
USAGE: BUFFER_DEF_AS(name, config_opl, type[, oplist of type]) */
#define M_BUFFER_DEF_AS(a, b, ...) M_DEF_AS(M_BUFF3R_DEF_AS, a, b, __VA_ARGS__)
#define M_BUFF3R_DEF_AS__3(n, c, t) M_BUFF3R_DEF_P1(M_BUFF3R_CONFIG(n, c, t, M_TYPE2OPL(t)))
#define M_BUFF3R_DEF_AS__4(n, c, t, o) M_BUFF3R_DEF_P1(M_BUFF3R_CONFIG(n, c, t, o))
#define M_BUFF3R_DEF_AS__5(n, c, t, o)
#define M_BUFF3R_DEF_AS__6(n, c, t, o)
#define M_BUFF3R_DEF_AS__7(n, c, t, o)
#define M_BUFF3R_DEF_AS__8(n, c, t, o)
#define M_BUFF3R_DEF_AS__9(n, c, t, o)
// Extract the optional customization attributes from name_opl
#define M_BUFF3R_CONFIG(n, c, t, o) \
(n, t, M_SIZE_AS(c, 0), M_POLICY_AS(c, M_BUFFER_QUEUE), o, M_TYPE_AS(c, M_C(n, _t)))
// Old call: (name, name_t, type, syze, policy [, oplist] )
#define BUFFER_DEF_AS(a, b, c, d, ...) M_DEF_AS(M_BUFF3R_D3F_AS, a, b, c ,d, __VA_ARGS__)
#define M_BUFF3R_D3F_AS__5(n, n_t, t, s, p) M_BUFF3R_DEF_P1((n, t, s, p, M_TYPE2OPL(type), n_t))
#define M_BUFF3R_D3F_AS__6(n, n_t, t, s, p, o) M_BUFF3R_DEF_P1((n, t, s, p, o, n_t))
#define M_BUFF3R_D3F_AS__7(n, n_t, t, s, p, o)
#define M_BUFF3R_D3F_AS__8(n, n_t, t, s, p, o)
#define M_BUFF3R_D3F_AS__9(n, n_t, t, s, p, o)
/* Define the oplist of a lock based buffer given its name and its oplist.
@@ -152,7 +182,7 @@ typedef union m_buff3r_number_s {
#endif
} m_buff3r_number_ct[1];
static inline void
M_INLINE void
m_buff3r_number_init(m_buff3r_number_ct n, unsigned int policy)
{
if (!M_BUFF3R_POLICY_P(policy, M_BUFFER_THREAD_UNSAFE))
@@ -161,7 +191,7 @@ m_buff3r_number_init(m_buff3r_number_ct n, unsigned int policy)
n->u = 0UL;
}
static inline unsigned int
M_INLINE unsigned int
m_buff3r_number_load(m_buff3r_number_ct n, unsigned int policy)
{
if (!M_BUFF3R_POLICY_P(policy, M_BUFFER_THREAD_UNSAFE))
@@ -172,7 +202,7 @@ m_buff3r_number_load(m_buff3r_number_ct n, unsigned int policy)
return n->u;
}
static inline void
M_INLINE void
m_buff3r_number_store(m_buff3r_number_ct n, unsigned int v, unsigned int policy)
{
if (!M_BUFF3R_POLICY_P(policy, M_BUFFER_THREAD_UNSAFE))
@@ -182,7 +212,7 @@ m_buff3r_number_store(m_buff3r_number_ct n, unsigned int v, unsigned int policy)
n->u = v;
}
static inline void
M_INLINE void
m_buff3r_number_set(m_buff3r_number_ct n, m_buff3r_number_ct v, unsigned int policy)
{
if (!M_BUFF3R_POLICY_P(policy, M_BUFFER_THREAD_UNSAFE))
@@ -192,7 +222,7 @@ m_buff3r_number_set(m_buff3r_number_ct n, m_buff3r_number_ct v, unsigned int pol
n->u = v->u;
}
static inline unsigned int
M_INLINE unsigned int
m_buff3r_number_inc(m_buff3r_number_ct n, unsigned int policy)
{
if (!M_BUFF3R_POLICY_P(policy, M_BUFFER_THREAD_UNSAFE))
@@ -201,7 +231,7 @@ m_buff3r_number_inc(m_buff3r_number_ct n, unsigned int policy)
return n->u ++;
}
static inline unsigned int
M_INLINE unsigned int
m_buff3r_number_dec(m_buff3r_number_ct n, unsigned int policy)
{
if (!M_BUFF3R_POLICY_P(policy, M_BUFFER_THREAD_UNSAFE))
@@ -218,7 +248,7 @@ m_buff3r_number_dec(m_buff3r_number_ct n, unsigned int policy)
/* Return the size (run time or build time).
NOTE: It assumed that the buffer variable name is 'v' */
#define M_BUFF3R_SIZE(m_size) \
M_BUFF3R_IF_CTE_SIZE(m_size) (m_size, v->size)
M_BUFF3R_IF_CTE_SIZE(m_size) (m_size, v->capacity)
/* Contract of a buffer.
Nothing particular since we cannot test much without locking it.
@@ -235,7 +265,9 @@ m_buff3r_number_dec(m_buff3r_number_ct n, unsigned int policy)
/* Deferred evaluation for the definition,
so that all arguments are evaluated before further expansion */
so that all arguments are evaluated before further expansion
USAGE: M_BUFF3R_DEF_P1 ( (name, type, m_size, policy, oplist, buffer_t) )
*/
#define M_BUFF3R_DEF_P1(arg) M_ID( M_BUFF3R_DEF_P2 arg )
/* Validate the value oplist before going further */
@@ -277,7 +309,7 @@ m_buff3r_number_dec(m_buff3r_number_ct n, unsigned int policy)
size_t overwrite; /* Number of overwritten values */ \
m_cond_t there_is_data; /* condition raised when there is data */ \
/* Read only Data */ \
M_BUFF3R_IF_CTE_SIZE(m_size)( ,size_t size;) /* Size of the buffer */ \
M_BUFF3R_IF_CTE_SIZE(m_size)( ,size_t capacity;) /* Capacity of the buffer */ \
/* Data for a consummer */ \
m_cond_t there_is_room_for_data; /* Cond. raised when there is room */ \
m_mutex_t mutexPop; /* MUTEX used for popping elements */ \
@@ -300,11 +332,11 @@ m_buff3r_number_dec(m_buff3r_number_ct n, unsigned int policy)
/* Define the core functionnalities of a buffer */
#define M_BUFF3R_DEF_CORE(name, type, m_size, policy, oplist, buffer_t) \
\
static inline void \
M_INLINE void \
M_F(name, _init)(buffer_t v, size_t size) \
{ \
M_BUFF3R_IF_CTE_SIZE(m_size)(M_ASSERT(size == m_size), v->size = size); \
M_ASSERT(size <= UINT_MAX); \
M_BUFF3R_IF_CTE_SIZE(m_size)(M_ASSERT(size == m_size), v->capacity = size); \
v->idx_prod = v->idx_cons = v->overwrite = 0; \
m_buff3r_number_init (v->number[0], policy); \
if (M_BUFF3R_POLICY_P(policy, M_BUFFER_DEFERRED_POP)) \
@@ -320,7 +352,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
\
M_BUFF3R_IF_CTE_SIZE(m_size)( /* Statically allocated */ , \
v->data = M_CALL_REALLOC(oplist, M_F(name, _el_ct), NULL, M_BUFF3R_SIZE(m_size)); \
if (M_UNLIKELY_NOMEM (v->data == NULL)) { \
if (M_UNLIKELY_NOMEM (v->data == NULL)) { \
M_MEMORY_FULL (M_BUFF3R_SIZE(m_size)*sizeof(M_F(name, _el_ct))); \
return; \
} \
@@ -334,14 +366,14 @@ M_F(name, _init)(buffer_t v, size_t size) \
} \
\
M_BUFF3R_IF_CTE_SIZE(m_size)( \
static inline void \
M_INLINE void \
M_C3(m_buff3r_,name,_init)(buffer_t v) \
{ \
M_F(name, _init)(v, m_size); \
} \
, ) \
\
static inline void \
M_INLINE void \
M_C3(m_buff3r_,name,_clear_obj)(buffer_t v) \
{ \
M_BUFF3R_CONTRACT(v,m_size); \
@@ -365,7 +397,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
M_BUFF3R_CONTRACT(v,m_size); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(buffer_t v) \
{ \
M_BUFF3R_CONTRACT(v,m_size); \
@@ -383,7 +415,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
} \
} \
\
static inline void \
M_INLINE void \
M_F(name, _reset)(buffer_t v) \
{ \
M_BUFF3R_CONTRACT(v,m_size); \
@@ -406,13 +438,13 @@ M_F(name, _init)(buffer_t v, size_t size) \
M_BUFF3R_CONTRACT(v,m_size); \
} \
\
static inline void M_ATTR_DEPRECATED \
M_INLINE void M_ATTR_DEPRECATED \
M_F(name, _clean)(buffer_t v) \
{ \
M_F(name,_reset)(v); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_set)(buffer_t dest, const buffer_t src) \
{ \
/* unconst 'src', so that we can lock it (semantically it is const) */ \
@@ -456,7 +488,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
M_BUFF3R_CONTRACT(dest, m_size); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _set)(buffer_t dest, const buffer_t src) \
{ \
/* unconst 'src', so that we can lock it (semantically it is const) */ \
@@ -526,7 +558,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
M_BUFF3R_CONTRACT(dest, m_size); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _empty_p)(buffer_t v) \
{ \
M_BUFF3R_CONTRACT(v,m_size); \
@@ -540,7 +572,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
return m_buff3r_number_load (v->number[0], policy) == 0; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _full_p)(buffer_t v) \
{ \
M_BUFF3R_CONTRACT(v,m_size); \
@@ -548,14 +580,14 @@ M_F(name, _init)(buffer_t v, size_t size) \
== M_BUFF3R_SIZE(m_size); \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _size)(buffer_t v) \
{ \
M_BUFF3R_CONTRACT(v,m_size); \
return m_buff3r_number_load (v->number[0], policy); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _push_blocking)(buffer_t v, type const data, bool blocking) \
{ \
M_BUFF3R_CONTRACT(v,m_size); \
@@ -635,7 +667,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
return true; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _pop_blocking)(type *data, buffer_t v, bool blocking) \
{ \
M_BUFF3R_CONTRACT(v,m_size); \
@@ -706,34 +738,34 @@ M_F(name, _init)(buffer_t v, size_t size) \
} \
\
\
static inline bool \
M_INLINE bool \
M_F(name, _push)(buffer_t v, type const data) \
{ \
return M_F(name, _push_blocking)(v, data, \
!M_BUFF3R_POLICY_P((policy), M_BUFFER_UNBLOCKING_PUSH)); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _pop)(type *data, buffer_t v) \
{ \
return M_F(name, _pop_blocking)(data, v, \
!M_BUFF3R_POLICY_P((policy), M_BUFFER_UNBLOCKING_POP)); \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _overwrite)(const buffer_t v) \
{ \
return v->overwrite; \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _capacity)(const buffer_t v) \
{ \
(void) v; /* may be unused */ \
return M_BUFF3R_SIZE(m_size); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _pop_release)(buffer_t v) \
{ \
/* Decrement the effective number of elements in the buffer */ \
@@ -833,7 +865,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
/* Define the core functionnalities of a MPMC queue */
#define M_QU3UE_MPMC_DEF_CORE(name, type, policy, oplist, buffer_t) \
static inline bool \
M_INLINE bool \
M_F(name, _push)(buffer_t table, type const x) \
{ \
M_QU3UE_MPMC_CONTRACT(table); \
@@ -867,7 +899,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
return true; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _pop)(type *ptr, buffer_t table) \
{ \
M_QU3UE_MPMC_CONTRACT(table); \
@@ -896,7 +928,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
return true; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init)(buffer_t buffer, size_t size) \
{ \
M_ASSERT (buffer != NULL); \
@@ -920,7 +952,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
M_QU3UE_MPMC_CONTRACT(buffer); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(buffer_t buffer) \
{ \
M_QU3UE_MPMC_CONTRACT(buffer); \
@@ -945,7 +977,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
buffer->size = 3; \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _size)(buffer_t table) \
{ \
M_QU3UE_MPMC_CONTRACT(table); \
@@ -964,20 +996,20 @@ M_F(name, _init)(buffer_t v, size_t size) \
return iP-iC; \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _capacity)(buffer_t v) \
{ \
M_QU3UE_MPMC_CONTRACT(v); \
return v->size; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _empty_p)(buffer_t v) \
{ \
return M_F(name, _size) (v) == 0; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _full_p)(buffer_t v) \
{ \
return M_F(name, _size)(v) >= v->size; \
@@ -1060,7 +1092,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
/* Define the core functionnalities of a SPSC queue */
#define M_QU3UE_SPSC_DEF_CORE(name, type, policy, oplist, buffer_t) \
\
static inline bool \
M_INLINE bool \
M_F(name, _push)(buffer_t table, type const x) \
{ \
M_QU3UE_SPSC_CONTRACT(table); \
@@ -1081,7 +1113,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
return true; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _push_move)(buffer_t table, type *x) \
{ \
M_QU3UE_SPSC_CONTRACT(table); \
@@ -1102,7 +1134,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
return true; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _pop)(type *ptr, buffer_t table) \
{ \
M_QU3UE_SPSC_CONTRACT(table); \
@@ -1124,7 +1156,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
return true; \
} \
\
static inline unsigned \
M_INLINE unsigned \
M_F(name, _push_bulk)(buffer_t table, unsigned n, type const x[]) \
{ \
M_QU3UE_SPSC_CONTRACT(table); \
@@ -1150,7 +1182,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
return max; \
} \
\
static inline unsigned \
M_INLINE unsigned \
M_F(name, _pop_bulk)(unsigned int n, type ptr[], buffer_t table) \
{ \
M_QU3UE_SPSC_CONTRACT(table); \
@@ -1176,7 +1208,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
return max; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _push_force)(buffer_t table, type const x) \
{ \
M_QU3UE_SPSC_CONTRACT(table); \
@@ -1199,7 +1231,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
M_QU3UE_SPSC_CONTRACT(table); \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _size)(buffer_t table) \
{ \
M_QU3UE_SPSC_CONTRACT(table); \
@@ -1220,25 +1252,25 @@ M_F(name, _init)(buffer_t v, size_t size) \
return w-r; \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _capacity)(buffer_t v) \
{ \
return v->size; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _empty_p)(buffer_t v) \
{ \
return M_F(name, _size) (v) == 0; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _full_p)(buffer_t v) \
{ \
return M_F(name, _size)(v) >= v->size; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init)(buffer_t buffer, size_t size) \
{ \
M_ASSERT (buffer != NULL); \
@@ -1261,7 +1293,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
M_QU3UE_SPSC_CONTRACT(buffer); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(buffer_t buffer) \
{ \
M_QU3UE_SPSC_CONTRACT(buffer); \
@@ -1323,7 +1355,7 @@ M_F(name, _init)(buffer_t v, size_t size) \
#if M_USE_SMALL_NAME
#define BUFFER_DEF M_BUFFER_DEF
#define BUFFER_DEF_AS M_BUFFER_DEF_AS
//#define BUFFER_DEF_AS M_BUFFER_DEF_AS
#define BUFFER_OPLIST M_BUFFER_OPLIST
#define QUEUE_MPMC_DEF M_QUEUE_MPMC_DEF
#define QUEUE_MPMC_DEF_AS M_QUEUE_MPMC_DEF_AS
+34 -34
View File
@@ -53,13 +53,13 @@ M_BEGIN_PROTECTED_CODE
\
typedef struct M_F(name, _slist_node_s) *M_F(name, _slist_ct)[1]; \
\
static inline void \
M_INLINE void \
M_F(name, _slist_init)(M_F(name, _slist_ct) list) \
{ \
*list = NULL; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _slist_push)(M_F(name, _slist_ct) list, \
M_F(name, _slist_node_ct) *node) \
{ \
@@ -67,7 +67,7 @@ M_BEGIN_PROTECTED_CODE
*list = node; \
} \
\
static inline M_F(name, _slist_node_ct) * \
M_INLINE M_F(name, _slist_node_ct) * \
M_F(name, _slist_pop)(M_F(name, _slist_ct) list) \
{ \
M_ASSERT (*list != NULL); \
@@ -77,13 +77,13 @@ M_BEGIN_PROTECTED_CODE
return node; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _slist_empty_p)(M_F(name, _slist_ct) list) \
{ \
return *list == NULL; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _slist_move)(M_F(name, _slist_ct) list, \
M_F(name, _slist_ct) src) \
{ \
@@ -91,7 +91,7 @@ M_BEGIN_PROTECTED_CODE
*src = NULL; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _slist_clear)(M_F(name, _slist_ct) list) \
{ \
M_F(name, _slist_node_ct) *it = *list, *next; \
@@ -139,7 +139,7 @@ M_BEGIN_PROTECTED_CODE
M_F(name, _lf_node_t) nil; \
} M_F(name, _lflist_ct)[1]; \
\
static inline void \
M_INLINE void \
M_F(name, _lflist_init)(M_F(name, _lflist_ct) list, \
M_F(name, _lf_node_t) *node) \
{ \
@@ -148,13 +148,13 @@ M_BEGIN_PROTECTED_CODE
atomic_store_explicit(&node->next, &list->nil, memory_order_relaxed); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _lflist_empty_p)(M_F(name, _lflist_ct) list) \
{ \
return atomic_load(&list->tail) == atomic_load(&list->head); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _lflist_push)(M_F(name, _lflist_ct) list, \
M_F(name, _lf_node_t) *node, m_core_backoff_ct bkoff) \
{ \
@@ -190,7 +190,7 @@ M_BEGIN_PROTECTED_CODE
memory_order_relaxed); \
} \
\
static inline M_F(name, _lf_node_t) * \
M_INLINE M_F(name, _lf_node_t) * \
M_F(name, _lflist_pop)(M_F(name, _lflist_ct) list, m_core_backoff_ct bkoff) \
{ \
M_F(name, _lf_node_t) *head; \
@@ -241,7 +241,7 @@ M_BEGIN_PROTECTED_CODE
} \
\
/* Dequeue a node if the node is old enough */ \
static inline M_F(name, _lf_node_t) * \
M_INLINE M_F(name, _lf_node_t) * \
M_F(name, _lflist_pop_if)(M_F(name, _lflist_ct) list, \
m_gc_ticket_ct age, m_core_backoff_ct bkoff) \
{ \
@@ -281,7 +281,7 @@ M_BEGIN_PROTECTED_CODE
return head; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _lflist_clear)(M_F(name, _lflist_ct) list) \
{ \
m_core_backoff_ct bkoff; \
@@ -306,7 +306,7 @@ M_BEGIN_PROTECTED_CODE
As such it is a non Lock-Free path. */
#define M_CMEMP00L_DEF_SYSTEM_ALLOC(name, type_t) \
\
static inline M_F(name, _lf_node_t) * \
M_INLINE M_F(name, _lf_node_t) * \
M_F(name, _alloc_node)(unsigned int initial) \
{ \
M_F(name, _lf_node_t) * node; \
@@ -394,14 +394,14 @@ M_BEGIN_PROTECTED_CODE
M_CACHELINE_ALIGN(align1, M_F(name, _slist_ct), M_F(name, _slist_ct)); \
} M_F(name, _lfmp_thread_ct); \
\
static inline void \
M_INLINE void \
M_F(name, _lfmp_thread_init)(M_F(name, _lfmp_thread_ct) *t) \
{ \
M_F(name, _slist_init)(t->free); \
M_F(name, _slist_init)(t->to_be_reclaimed); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _lfmp_thread_clear)(M_F(name, _lfmp_thread_ct) *t) \
{ \
M_ASSERT(M_F(name, _slist_empty_p)(t->to_be_reclaimed)); \
@@ -423,7 +423,7 @@ M_BEGIN_PROTECTED_CODE
} M_F(name, _t)[1]; \
\
/* Garbage collect of the nodes of the mempool on sleep */ \
static inline void \
M_INLINE void \
M_C3(m_cmemp00l_,name,_gc_on_sleep)(m_gc_t gc_mem, m_cmemp00l_list_ct *data, \
m_gc_tid_t id, m_gc_ticket_ct ticket, m_gc_ticket_ct min_ticket) \
{ \
@@ -458,7 +458,7 @@ M_BEGIN_PROTECTED_CODE
} \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init)(M_F(name, _t) mem, m_gc_t gc_mem, \
unsigned init_node_count, unsigned init_group_count) \
{ \
@@ -490,7 +490,7 @@ M_BEGIN_PROTECTED_CODE
mem->gc_mem = gc_mem; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(M_F(name, _t) mem) \
{ \
const unsigned max_thread = mem->gc_mem->max_thread; \
@@ -506,7 +506,7 @@ M_BEGIN_PROTECTED_CODE
/* TODO: Unregister from the GC? */ \
} \
\
static inline type_t * \
M_INLINE type_t * \
M_F(name, _new)(M_F(name, _t) mem, m_gc_tid_t id) \
{ \
M_F(name, _slist_node_ct) *snode; \
@@ -533,7 +533,7 @@ M_BEGIN_PROTECTED_CODE
} \
} \
\
static inline void \
M_INLINE void \
M_F(name, _del)(M_F(name, _t) mem, type_t *d, m_gc_tid_t id) \
{ \
M_F(name, _slist_node_ct) *snode; \
@@ -579,7 +579,7 @@ typedef struct m_gc_s {
m_cmemp00l_list_ct *mempool_list;
} m_gc_t[1];
static inline void
M_INLINE void
m_gc_init(m_gc_t gc_mem, size_t max_thread)
{
M_ASSERT(gc_mem != NULL);
@@ -600,7 +600,7 @@ m_gc_init(m_gc_t gc_mem, size_t max_thread)
gc_mem->mempool_list = NULL;
}
static inline void
M_INLINE void
m_gc_clear(m_gc_t gc_mem)
{
M_ASSERT(gc_mem != NULL && gc_mem->max_thread > 0);
@@ -613,7 +613,7 @@ m_gc_clear(m_gc_t gc_mem)
m_genint_clear(gc_mem->thread_alloc);
}
static inline m_gc_tid_t
M_INLINE m_gc_tid_t
m_gc_attach_thread(m_gc_t gc_mem)
{
M_ASSERT(gc_mem != NULL && gc_mem->max_thread > 0);
@@ -622,7 +622,7 @@ m_gc_attach_thread(m_gc_t gc_mem)
return M_ASSIGN_CAST(m_gc_tid_t, id);
}
static inline void
M_INLINE void
m_gc_detach_thread(m_gc_t gc_mem, m_gc_tid_t id)
{
M_ASSERT(gc_mem != NULL && gc_mem->max_thread > 0);
@@ -632,7 +632,7 @@ m_gc_detach_thread(m_gc_t gc_mem, m_gc_tid_t id)
m_genint_push(gc_mem->thread_alloc, id);
}
static inline void
M_INLINE void
m_gc_awake(m_gc_t gc_mem, m_gc_tid_t id)
{
M_ASSERT(gc_mem != NULL && gc_mem->max_thread > 0);
@@ -643,7 +643,7 @@ m_gc_awake(m_gc_t gc_mem, m_gc_tid_t id)
atomic_store(&gc_mem->thread_data[id].ticket, t);
}
static inline m_gc_ticket_ct
M_INLINE m_gc_ticket_ct
m_cmemp00l_gc_min_ticket(m_gc_t gc_mem)
{
m_gc_ticket_ct min = atomic_load(&gc_mem->thread_data[0].ticket);
@@ -654,7 +654,7 @@ m_cmemp00l_gc_min_ticket(m_gc_t gc_mem)
return min;
}
static inline void
M_INLINE void
m_gc_sleep(m_gc_t gc_mem, m_gc_tid_t id)
{
/* Increase life time of the thread */
@@ -690,13 +690,13 @@ typedef struct m_vlapool_lfmp_thread_s {
M_CACHELINE_ALIGN(align1, m_vlapool_slist_ct);
} m_vlapool_lfmp_thread_ct;
static inline void
M_INLINE void
m_vlapool_lfmp_thread_init(m_vlapool_lfmp_thread_ct *t)
{
m_vlapool_slist_init(t->to_be_reclaimed);
}
static inline void
M_INLINE void
m_vlapool_lfmp_thread_clear(m_vlapool_lfmp_thread_ct *t)
{
M_ASSERT(m_vlapool_slist_empty_p(t->to_be_reclaimed));
@@ -712,7 +712,7 @@ typedef struct m_vlapool_s {
} m_vlapool_t[1];
/* Garbage collect of the nodes of the vla mempool on sleep */
static inline void
M_INLINE void
m_cmemp00l_vlapool_on_sleep(m_gc_t gc_mem, m_cmemp00l_list_ct *data,
m_gc_tid_t id, m_gc_ticket_ct ticket, m_gc_ticket_ct min_ticket)
{
@@ -751,7 +751,7 @@ m_cmemp00l_vlapool_on_sleep(m_gc_t gc_mem, m_cmemp00l_list_ct *data,
}
}
static inline void
M_INLINE void
m_vlapool_init(m_vlapool_t mem, m_gc_t gc_mem)
{
const size_t max_thread = gc_mem->max_thread;
@@ -777,7 +777,7 @@ m_vlapool_init(m_vlapool_t mem, m_gc_t gc_mem)
mem->gc_mem = gc_mem;
}
static inline void
M_INLINE void
m_vlapool_clear(m_vlapool_t mem)
{
const unsigned max_thread = mem->gc_mem->max_thread;
@@ -792,7 +792,7 @@ m_vlapool_clear(m_vlapool_t mem)
/* TODO: Unregister from the GC? */
}
static inline void *
M_INLINE void *
m_vlapool_new(m_vlapool_t mem, m_gc_tid_t id, size_t size)
{
M_ASSERT(mem != NULL && mem->gc_mem != NULL);
@@ -811,7 +811,7 @@ m_vlapool_new(m_vlapool_t mem, m_gc_tid_t id, size_t size)
return (ptr == NULL) ? NULL : M_ASSIGN_CAST(void *, ptr + offsetof(struct m_vlapool_slist_node_s, data));
}
static inline void
M_INLINE void
m_vlapool_del(m_vlapool_t mem, void *d, m_gc_tid_t id)
{
M_ASSERT(mem != NULL && mem->gc_mem != NULL);
+47 -50
View File
@@ -130,9 +130,6 @@
,M_IF_METHOD(IN_SERIAL, oplist)(IN_SERIAL(M_F(name, _in_serial)),) \
,M_IF_METHOD(EQUAL, oplist)(EQUAL(M_F(name, _equal_p)),) \
,M_IF_METHOD(HASH, oplist)(HASH(M_F(name, _hash)),) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
)
@@ -196,7 +193,7 @@
\
/* Initial the fields of the concurrent object not associated to the \
sub-container. */ \
static inline void \
M_INLINE void \
M_F(name, _internal_init)(concurrent_t out) \
{ \
m_mutex_init(out->lock); \
@@ -207,7 +204,7 @@
\
/* Clear the fields of the concurrent object not associated to the \
sub-container. */ \
static inline void \
M_INLINE void \
M_F(name, _internal_clear)(concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -220,7 +217,7 @@
write lock is exclusive. \
NOTE: This instance doesn't implement the read/write strategy, \
and only get the lock */ \
static inline void \
M_INLINE void \
M_F(name, _read_lock)(const concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -230,7 +227,7 @@
/* Free the read lock. See above. \
NOTE: This instance doesn't implement the read/write strategy, \
and only get the lock */ \
static inline void \
M_INLINE void \
M_F(name, _read_unlock)(const concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -239,7 +236,7 @@
\
/* Wait for a thread pushing some data in the container. \
CONSTRAINT: the read lock shall be get before calling this service */ \
static inline void \
M_INLINE void \
M_F(name, _read_wait)(const concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -250,7 +247,7 @@
can get the read lock too. \
NOTE: This instance doesn't implement the read/write strategy, \
and only get the lock */ \
static inline void \
M_INLINE void \
M_F(name, _write_lock)(concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -260,7 +257,7 @@
/* Free the write lock. \
NOTE: This instance doesn't implement the read/write strategy, \
and only get the lock */ \
static inline void \
M_INLINE void \
M_F(name, _write_unlock)(concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -269,7 +266,7 @@
\
/* Wait for a thread pushing some data in the container. \
CONSTRAINT: the write lock shall be get before calling this service */ \
static inline void \
M_INLINE void \
M_F(name, _write_wait)(const concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -278,7 +275,7 @@
\
/* Wait to all threads that some data are available in the container. \
CONSTRAINT: the write lock shall be get before calling this service */ \
static inline void \
M_INLINE void \
M_F(name, _write_signal)(concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -298,7 +295,7 @@
#define M_C0NCURRENT_DEF_COMMON(name, type, oplist, concurrent_t) \
\
M_IF_METHOD(INIT, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _init)(concurrent_t out) \
{ \
M_F(name, _internal_init)(out); \
@@ -308,7 +305,7 @@
,) \
\
M_IF_METHOD(INIT_SET, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _init_set)(concurrent_t out, concurrent_t const src) \
{ \
M_C0NCURRENT_CONTRACT(src); \
@@ -322,7 +319,7 @@
,) \
\
M_IF_METHOD(SET, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _set)(concurrent_t out, concurrent_t const src) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -357,7 +354,7 @@
,) \
\
M_IF_METHOD(CLEAR, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _clear)(concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -369,7 +366,7 @@
,) \
\
M_IF_METHOD(INIT_MOVE, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _init_move)(concurrent_t out, concurrent_t src) \
{ \
M_C0NCURRENT_CONTRACT(src); \
@@ -383,7 +380,7 @@
,) \
\
M_IF_METHOD(MOVE, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _move)(concurrent_t out, concurrent_t src) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -398,7 +395,7 @@
,) \
\
M_IF_METHOD(SWAP, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _swap)(concurrent_t out, concurrent_t src) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -424,7 +421,7 @@
,) \
\
M_IF_METHOD(RESET, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _reset)(concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -435,7 +432,7 @@
,) \
\
M_IF_METHOD(EMPTY_P, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _empty_p)(concurrent_t const out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -447,7 +444,7 @@
,) \
\
M_IF_METHOD(GET_SIZE, oplist)( \
static inline size_t \
M_INLINE size_t \
M_F(name, _size)(concurrent_t const out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -459,7 +456,7 @@
,) \
\
M_IF_METHOD(SET_KEY, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _set_at)(concurrent_t out, M_GET_KEY_TYPE oplist const key, M_GET_VALUE_TYPE oplist const data) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -471,7 +468,7 @@
,) \
\
M_IF_METHOD(GET_KEY, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _get_copy)(M_GET_VALUE_TYPE oplist *out_data, const concurrent_t out, M_GET_KEY_TYPE oplist const key) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -487,7 +484,7 @@
,) \
\
M_IF_METHOD(SAFE_GET_KEY, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _safe_get_copy)(M_GET_VALUE_TYPE oplist *out_data, concurrent_t out, M_GET_KEY_TYPE oplist const key) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -501,7 +498,7 @@
,) \
\
M_IF_METHOD(ERASE_KEY, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _erase)(concurrent_t out, M_GET_KEY_TYPE oplist const key) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -515,7 +512,7 @@
,) \
\
M_IF_METHOD(PUSH, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _push)(concurrent_t out, M_GET_SUBTYPE oplist const data) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -529,7 +526,7 @@
,) \
\
M_IF_METHOD(POP, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _pop)(M_GET_SUBTYPE oplist *p, concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -541,7 +538,7 @@
,) \
\
M_IF_METHOD(PUSH_MOVE, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _push_move)(concurrent_t out, M_GET_SUBTYPE oplist *data) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -553,7 +550,7 @@
,) \
\
M_IF_METHOD(POP_MOVE, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _pop_move)(M_GET_SUBTYPE oplist *p, concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -565,7 +562,7 @@
,) \
\
M_IF_METHOD(GET_STR, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _get_str)(m_string_t str, concurrent_t const out, bool a) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -576,7 +573,7 @@
,) \
\
M_IF_METHOD(OUT_STR, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _out_str)(FILE *f, concurrent_t const out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -587,7 +584,7 @@
,) \
\
M_IF_METHOD(PARSE_STR, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _parse_str)(concurrent_t out, const char str[], const char **e) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -600,7 +597,7 @@
,) \
\
M_IF_METHOD(IN_STR, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _in_str)(concurrent_t out, FILE *f) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -613,7 +610,7 @@
,) \
\
M_IF_METHOD(OUT_SERIAL, oplist)( \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _out_serial)(m_serial_write_t f, concurrent_t const out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -625,7 +622,7 @@
,) \
\
M_IF_METHOD(IN_SERIAL, oplist)( \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _in_serial)(concurrent_t out, m_serial_read_t f) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -638,7 +635,7 @@
,) \
\
M_IF_METHOD(EQUAL, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _equal_p)(concurrent_t const out1, concurrent_t const out2) \
{ \
M_C0NCURRENT_CONTRACT(out1); \
@@ -665,7 +662,7 @@
,) \
\
M_IF_METHOD(GET_KEY, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _get_blocking)(M_GET_VALUE_TYPE oplist *out_data, const concurrent_t out, M_GET_KEY_TYPE oplist const key, bool blocking) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -689,7 +686,7 @@
,) \
\
M_IF_METHOD2(POP, EMPTY_P, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _pop_blocking)(M_GET_SUBTYPE oplist *p, concurrent_t out, bool blocking) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -712,7 +709,7 @@
,) \
\
M_IF_METHOD2(POP_MOVE, EMPTY_P, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _pop_move_blocking)(M_GET_SUBTYPE oplist *p, concurrent_t out, bool blocking) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -735,7 +732,7 @@
,) \
\
M_IF_METHOD(HASH, oplist)( \
static inline size_t \
M_INLINE size_t \
M_F(name, _hash)(concurrent_t const out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -795,7 +792,7 @@
/* Define the internal services for the lock strategy of a RP container */
#define M_C0NCURRENT_RP_DEF_CORE(name, type, oplist, concurrent_t) \
\
static inline void \
M_INLINE void \
M_F(name, _internal_init)(concurrent_t out) \
{ \
m_mutex_init(out->lock); \
@@ -807,7 +804,7 @@
M_C0NCURRENT_CONTRACT(out); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _internal_clear)(concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -817,7 +814,7 @@
out->self = NULL; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _read_lock)(const concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -830,7 +827,7 @@
m_mutex_unlock (self->lock); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _read_unlock)(const concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -843,7 +840,7 @@
m_mutex_unlock (self->lock); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _write_lock)(concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -858,7 +855,7 @@
m_mutex_unlock (out->lock); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _write_unlock)(concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -868,7 +865,7 @@
m_mutex_unlock (out->lock); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _read_wait)(const concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -887,7 +884,7 @@
m_mutex_unlock (out->self->lock); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _write_wait)(concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
@@ -905,7 +902,7 @@
m_mutex_unlock (out->lock); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _write_signal)(concurrent_t out) \
{ \
M_C0NCURRENT_CONTRACT(out); \
+250 -122
View File
@@ -264,6 +264,50 @@
M_BEGIN_PROTECTED_CODE
/************************************************************/
/************************* LINKAGE **************************/
/************************************************************/
/* The following semantics apply to inline in C99:
- inline: No generation of an extern visible function. May inline or may call the external function.
- extern inline: externally visible code is emitted, so at most one translation unit can use this.
- static inline: No generation of an extern visible function. May inline or may call one static function.
*/
/* If the user requests to use only declaration for all M*LIB functions globally (M_USE_DECL),
it requests no inlining to the compiler and emits code as weak symbol.
Then at most one translation unit should request the definition of all functions (M_USE_DEF).
This is only supported by GCC and CLANG. You should also use the options -ffunction-sections -fdata-sections -Wl,--gc-sections
Otherwise it would increase the size of the executable.
If M_USE_FINE_GRAINED_LINKAGE, then the mechanism can be turn on / off dynamically in compilation time
to decl or def the functions in function of M_USE_DECL / M_USE_DEF
Otherwise uses the classic "M_INLINE" (inline for C++ or static inline for C)
inline in C++ as a weak definition by default, which may reduce code size in executable.
*/
#if !defined(__cplusplus) && defined(__GNUC__)
# define M_INLINE_PRAGMA _Pragma("GCC diagnostic ignored \"-Wmissing-prototypes\"")
#else
# define M_INLINE_PRAGMA
#endif
#if defined(__GNUC__) && defined(M_USE_FINE_GRAINED_LINKAGE)
#define M_INLINE \
M_IF_EMPTY(M_USE_DECL)( \
M_IF_EMPTY(M_USE_DEF)(M_INLINE_PRAGMA __attribute__((noinline)) extern, \
M_INLINE_PRAGMA __attribute__((weak, noinline)) extern), \
static inline)
#elif defined(__GNUC__) && defined(M_USE_DECL)
# ifdef M_USE_DEF
# define M_INLINE M_INLINE_PRAGMA __attribute__((noinline)) extern
# else
# define M_INLINE M_INLINE_PRAGMA __attribute__((weak, noinline)) extern
#endif
#elif defined(__cplusplus)
#define M_INLINE inline
#else
#define M_INLINE static inline
#endif
/************************************************************/
/********************* MEMORY handling **********************/
/************************************************************/
@@ -449,48 +493,6 @@ M_BEGIN_PROTECTED_CODE
#define M_UNLIKELY_NOMEM(cond) M_UNLIKELY(cond)
/***************************************************************/
/****************** Function Generation Macro ******************/
/***************************************************************/
/*
* Define the expansion logic to define a public / private / type function
* for inline expansion
*/
#define M_EXPAND_FUNC_INLINE(proto, ...) \
static inline proto __VA_ARGS__
#define M_EXPAND_FUNC_INLINE_PRIVATE(...) \
__VA_ARGS__
#define M_EXPAND_FUNC_INLINE_TYPE(...) \
__VA_ARGS__
/*
* Define the expansion logic to define a public / private / type function
* for inline expansion
*/
#define M_EXPAND_FUNC_DECL(proto, ...) \
extern proto;
#define M_EXPAND_FUNC_DECL_PRIVATE(...)
#define M_EXPAND_FUNC_DECL_TYPE(...) \
__VA_ARGS__
/*
* Define the expansion logic to define a public / private / type function
* for inline expansion
*/
#define M_EXPAND_FUNC_BODY(proto, ...) \
proto __VA_ARGS__
#define M_EXPAND_FUNC_BODY_PRIVATE(...) \
__VA_ARGS__
#define M_EXPAND_FUNC_BODY_TYPE(...)
/***************************************************************/
/****************** Preprocessing Times Macro ******************/
/***************************************************************/
@@ -2495,7 +2497,7 @@ done
#define M_DEFAULTI_ARGS2(numArgs, numExpected, value, ...) \
__VA_ARGS__ \
M_IF(M_NOTEQUAL(numArgs, numExpected))(M_DEFERRED_COMMA, ) \
M_REVERSE(M_KEEP_ARGS(M_SUB(numExpected, numArgs), M_REVERSE value, nothing))
M_REVERSE(M_KEEP_ARGS(M_SUB(numExpected, numArgs), M_REVERSE value, M_LIB_ERROR_MISSING_MANDATORY_ARGUMENT))
#define M_DEFAULTI_ARGS_EVAL(...) __VA_ARGS__
#define M_DEFAULT_ARGS(expected, value, ...) \
M_DEFAULTI_ARGS_EVAL(M_DEFAULTI_ARGS2(M_NARGS(__VA_ARGS__), expected, value, __VA_ARGS__))
@@ -2574,7 +2576,7 @@ done
#if defined(_MSC_VER) && defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__
/* Wrapper around fopen_s */
static inline FILE *
M_INLINE FILE *
m_core_fopen(const char filename[], const char opt[])
{
FILE *f;
@@ -2663,7 +2665,7 @@ m_core_fopen(const char filename[], const char opt[])
void *: false /* unsupported */)
/* Internal wrappers used by M_FSCAN_ARG : */
static inline bool
M_INLINE bool
m_core_fscan_bool (bool *ptr, FILE *f)
{
int c = fgetc(f);
@@ -2671,7 +2673,7 @@ m_core_fscan_bool (bool *ptr, FILE *f)
return (c == '0' || c == '1');
}
static inline bool
M_INLINE bool
m_core_fscan_char (char *ptr, FILE *f)
{
int c = fgetc(f);
@@ -2680,7 +2682,7 @@ m_core_fscan_char (char *ptr, FILE *f)
}
#define M_FSCAN_DEFAULT_TYPE_DEF(name, type, format) \
static inline bool \
M_INLINE bool \
name (type *ptr, FILE *f) \
{ \
return m_core_fscanf(f, format, ptr) == 1; \
@@ -2701,7 +2703,7 @@ M_FSCAN_DEFAULT_TYPE_DEF(m_core_fscan_ldouble, long double, "%Lf")
/* Return the next character (like fgetc) which is not a space character
and advance the FILE stream accordingly */
static inline int m_core_fgetc_nospace(FILE *f)
M_INLINE int m_core_fgetc_nospace(FILE *f)
{
int c;
do {
@@ -2714,7 +2716,7 @@ static inline int m_core_fgetc_nospace(FILE *f)
/* Return the next character (like fgetc) which is not a space character
and advance the string stream accordingly */
static inline char m_core_str_nospace(const char **str)
M_INLINE char m_core_str_nospace(const char **str)
{
char c;
do {
@@ -2754,7 +2756,7 @@ static inline char m_core_str_nospace(const char **str)
void *: false /* not supported */)
/* Internal wrappers used by M_PARSE_DEFAULT_TYPE : */
static inline bool
M_INLINE bool
m_core_parse_char (char *ptr, const char str[], const char **endptr)
{
*ptr = *str++;
@@ -2762,7 +2764,7 @@ m_core_parse_char (char *ptr, const char str[], const char **endptr)
return true;
}
static inline bool
M_INLINE bool
m_core_parse_bool (bool *ptr, const char str[], const char **endptr)
{
char c = *str++;
@@ -2772,7 +2774,7 @@ m_core_parse_bool (bool *ptr, const char str[], const char **endptr)
}
#define M_PARSE_DEFAULT_TYPE_DEF(name, type, parse_func, extra_arg) \
static inline bool \
M_INLINE bool \
name (type *ptr, const char str[], const char **endptr) \
{ \
char *end; \
@@ -2908,7 +2910,7 @@ M_PARSE_DEFAULT_TYPE_DEF(m_core_parse_ldouble, long double, strtold, )
# define M_MIN_FLEX_ARRAY_SIZE
#endif
#if M_USE_STDARG
#if M_USE_STDARG && M_USE_STDIO
/* Define the allocation of the temporary string used by M_CSTR
Default is 256 bytes (so 255 characters excluding the final null char).
@@ -2981,7 +2983,7 @@ namespace m_lib {
#else
// Encapsulate snprintf to return the input buffer as argument (needed for M_CSTR)
static inline const char *
M_INLINE const char *
m_core_snprintf(char *str, size_t size, const char *format, ...)
{
va_list args;
@@ -3059,12 +3061,12 @@ m_core_snprintf(char *str, size_t size, const char *format, ...)
return (x<<n) | (x>>(-n&31));
but compilers are less likely to generate a roll instruction.
*/
static inline uint32_t m_core_rotl32a (uint32_t x, uint32_t n)
M_INLINE uint32_t m_core_rotl32a (uint32_t x, uint32_t n)
{
M_ASSERT (n > 0 && n<32);
return (x<<n) | (x>>(32-n));
}
static inline uint64_t m_core_rotl64a (uint64_t x, uint32_t n)
M_INLINE uint64_t m_core_rotl64a (uint64_t x, uint32_t n)
{
M_ASSERT (n > 0 && n<64);
return (x<<n) | (x>>(64-n));
@@ -3073,7 +3075,7 @@ static inline uint64_t m_core_rotl64a (uint64_t x, uint32_t n)
/* Round to the next highest power of 2.
See https://web.archive.org/web/20160703165415/https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
*/
static inline uint64_t m_core_roundpow2(uint64_t v)
M_INLINE uint64_t m_core_roundpow2(uint64_t v)
{
v--;
v |= v >> 1;
@@ -3088,20 +3090,20 @@ static inline uint64_t m_core_roundpow2(uint64_t v)
/* Return the count leading zero of the argument */
#if defined(__GNUC__) && (__GNUC__*100 + __GNUC_MINOR__) >= 304
static inline unsigned int m_core_clz32(uint32_t limb)
M_INLINE unsigned int m_core_clz32(uint32_t limb)
{
return (unsigned int) (M_UNLIKELY (limb == 0) ? sizeof(uint32_t)*CHAR_BIT : (size_t) __builtin_clzl(limb) - (sizeof(unsigned long) - sizeof(uint32_t)) * CHAR_BIT);
}
static inline unsigned int m_core_clz64(uint64_t limb)
M_INLINE unsigned int m_core_clz64(uint64_t limb)
{
return (unsigned int) (M_UNLIKELY (limb == 0ULL) ? sizeof (uint64_t)*CHAR_BIT : (size_t) __builtin_clzll(limb) - (sizeof (unsigned long long) - sizeof (uint64_t)) * CHAR_BIT);
}
static inline unsigned int m_core_ctz32(uint32_t limb)
M_INLINE unsigned int m_core_ctz32(uint32_t limb)
{
return (unsigned int) (M_UNLIKELY (limb == 0) ? sizeof(uint32_t)*CHAR_BIT : (size_t) __builtin_ctzl(limb));
}
static inline unsigned int m_core_ctz64(uint64_t limb)
M_INLINE unsigned int m_core_ctz64(uint64_t limb)
{
return (unsigned int) (M_UNLIKELY (limb == 0ULL) ? sizeof (uint64_t)*CHAR_BIT : (size_t) __builtin_ctzll(limb));
}
@@ -3109,7 +3111,7 @@ static inline unsigned int m_core_ctz64(uint64_t limb)
#elif defined(_MSC_VER) && (defined(_M_AMD64) || defined(_M_ARM64))
// NOTE: _BitScanReverse64 is 64-bits only (not compatible 32 bits).
#include <intrin.h>
static inline unsigned int m_core_clz32(uint32_t limb)
M_INLINE unsigned int m_core_clz32(uint32_t limb)
{
unsigned long bit = 0;
if (_BitScanReverse( &bit, limb ) != 0) {
@@ -3118,7 +3120,7 @@ static inline unsigned int m_core_clz32(uint32_t limb)
return 32;
}
}
static inline unsigned int m_core_clz64(uint64_t limb)
M_INLINE unsigned int m_core_clz64(uint64_t limb)
{
unsigned long bit = 0;
if (_BitScanReverse64( &bit, limb ) != 0) {
@@ -3128,7 +3130,7 @@ static inline unsigned int m_core_clz64(uint64_t limb)
}
}
static inline unsigned int m_core_ctz32(uint32_t limb)
M_INLINE unsigned int m_core_ctz32(uint32_t limb)
{
unsigned long bit = 0;
if (_BitScanForward( &bit, limb ) != 0) {
@@ -3137,7 +3139,7 @@ static inline unsigned int m_core_ctz32(uint32_t limb)
return 32;
}
}
static inline unsigned int m_core_ctz64(uint64_t limb)
M_INLINE unsigned int m_core_ctz64(uint64_t limb)
{
unsigned long bit = 0;
if (_BitScanForward64( &bit, limb ) != 0) {
@@ -3151,7 +3153,7 @@ static inline unsigned int m_core_ctz64(uint64_t limb)
// Emulation layer
#define M_CORE_CLZ_TAB "\010\07\06\06\05\05\05\05\04\04\04\04\04\04\04\04\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00"
static inline unsigned int m_core_clz32(uint32_t limb)
M_INLINE unsigned int m_core_clz32(uint32_t limb)
{
unsigned int shift = 0;
/* This code should be branchless on most targets */
@@ -3168,7 +3170,7 @@ static inline unsigned int m_core_clz32(uint32_t limb)
return shift;
}
static inline unsigned int m_core_clz64(uint64_t limb)
M_INLINE unsigned int m_core_clz64(uint64_t limb)
{
unsigned int shift = 0;
/* This code should be branchless on most targets */
@@ -3196,13 +3198,13 @@ static inline unsigned int m_core_clz64(uint64_t limb)
/* See algorithm ctz5 that uses de Bruijn sequences to construct a minimal perfect hash function (32 bits) */
#define M_CORE_CTZ_TAB "\000\001\034\002\035\016\030\003\036\026\024\017\031\021\004\010\037\033\015\027\025\023\020\007\032\014\022\006\013\005\012\011"
static inline unsigned int m_core_ctz32(uint32_t limb)
M_INLINE unsigned int m_core_ctz32(uint32_t limb)
{
if (limb == 0) { return 32; }
return (unsigned int) M_CORE_CTZ_TAB[ ( (uint32_t) (limb & -limb) * 0x077CB531) >> 27];
}
static inline unsigned int m_core_ctz64(uint64_t limb)
M_INLINE unsigned int m_core_ctz64(uint64_t limb)
{
unsigned int shift = 0;
if ((limb & 0x0FFFFFFFFull) == 0) { shift = 32; limb >>= 32; }
@@ -3224,7 +3226,7 @@ static inline unsigned int m_core_ctz64(uint64_t limb)
*/
#if SIZE_MAX <= 4294967295U
/* 32 bits variant with an average measured avalanche effect of 16.056 bits */
static inline uint32_t
M_INLINE uint32_t
m_core_hash (const void *str, size_t length)
{
const uint32_t prime = 709607U;
@@ -3259,7 +3261,7 @@ m_core_hash (const void *str, size_t length)
}
#else
/* 64 bits variant with an average measured avalanche effect of 31.862 bits */
static inline uint64_t
M_INLINE uint64_t
m_core_hash (const void *str, size_t length)
{
const uint64_t prime = 1099511628211ULL;
@@ -3305,7 +3307,7 @@ m_core_hash (const void *str, size_t length)
* We cannot use m_core_hash due to the alignment constraint,
* and it avoids computing the size before computing the hash.
*/
static inline size_t m_core_cstr_hash(const char str[])
M_INLINE size_t m_core_cstr_hash(const char str[])
{
M_HASH_DECL(hash);
while (*str) {
@@ -3352,17 +3354,12 @@ static inline size_t m_core_cstr_hash(const char str[])
#define M_SET_SET(a) ,a,
#define M_MOVE_MOVE(a) ,a,
#define M_CLEAR_CLEAR(a) ,a,
#define M_NEW_NEW(a) ,a,
#define M_DEL_DEL(a) ,a,
#define M_REALLOC_REALLOC(a) ,a,
#define M_FREE_FREE(a) ,a,
#define M_MEMPOOL_MEMPOOL(a) ,a,
#define M_MEMPOOL_LINKAGE_MEMPOOL_LINKAGE(a) ,a,
#define M_HASH_HASH(a) ,a,
#define M_EQUAL_EQUAL(a) ,a,
#define M_CMP_CMP(a) ,a,
#define M_TYPE_TYPE(a) ,a,
#define M_SUBTYPE_SUBTYPE(a) ,a,
#define M_GENTYPE_GENTYPE(a) ,a,
#define M_NAME_NAME(a) ,a,
#define M_OPLIST_OPLIST(a) ,a,
#define M_SORT_SORT(a) ,a,
@@ -3416,10 +3413,19 @@ static inline size_t m_core_cstr_hash(const char str[])
#define M_LIMITS_LIMITS(a) ,a,
#define M_PROPERTIES_PROPERTIES(a) ,a,
#define M_EMPLACE_TYPE_EMPLACE_TYPE(a) ,a,
// Properties only
// As attribute customization
#define M_NEW_NEW(a) ,a,
#define M_DEL_DEL(a) ,a,
#define M_REALLOC_REALLOC(a) ,a,
#define M_FREE_FREE(a) ,a,
#define M_MEMPOOL_MEMPOOL(a) ,a,
#define M_MEMPOOL_LINKAGE_MEMPOOL_LINKAGE(a) ,a,
#define M_SIZE_SIZE(a) ,a,
#define M_CONTEXT_CONTEXT(a) ,a,
#define M_POLICY_POLICY(a) ,a,
// As properties only
#define M_LET_AS_INIT_WITH_LET_AS_INIT_WITH(a) ,a,
#define M_NOCLEAR_NOCLEAR(a) ,a,
#define M_NOCLEAR_NOCLEAR(a) ,a,
/* From an oplist - an unorded list of methods : like "INIT(mpz_init),CLEAR(mpz_clear),SET(mpz_set)" -
Return the given method in the oplist or the default method.
@@ -3438,17 +3444,12 @@ static inline size_t m_core_cstr_hash(const char str[])
#define M_GET_MOVE(...) M_GET_METHOD(MOVE, M_NO_DEFAULT, __VA_ARGS__)
#define M_GET_SWAP(...) M_GET_METHOD(SWAP, M_NO_DEFAULT, __VA_ARGS__)
#define M_GET_CLEAR(...) M_GET_METHOD(CLEAR, M_NOTHING_DEFAULT, __VA_ARGS__)
#define M_GET_NEW(...) M_GET_METHOD(NEW, M_NEW_DEFAULT, __VA_ARGS__)
#define M_GET_DEL(...) M_GET_METHOD(DEL, M_DEL_DEFAULT, __VA_ARGS__)
#define M_GET_REALLOC(...) M_GET_METHOD(REALLOC, M_REALLOC_DEFAULT, __VA_ARGS__)
#define M_GET_FREE(...) M_GET_METHOD(FREE, M_FREE_DEFAULT, __VA_ARGS__)
#define M_GET_MEMPOOL(...) M_GET_METHOD(MEMPOOL, M_NO_DEFAULT, __VA_ARGS__)
#define M_GET_MEMPOOL_LINKAGE(...) M_GET_METHOD(MEMPOOL_LINKAGE, , __VA_ARGS__)
#define M_GET_HASH(...) M_GET_METHOD(HASH, M_NO_DEFAULT, __VA_ARGS__)
#define M_GET_EQUAL(...) M_GET_METHOD(EQUAL, M_EQUAL_DEFAULT, __VA_ARGS__)
#define M_GET_CMP(...) M_GET_METHOD(CMP, M_CMP_DEFAULT, __VA_ARGS__)
#define M_GET_TYPE(...) M_GET_METHOD(TYPE, M_NO_DEF_TYPE, __VA_ARGS__)
#define M_GET_SUBTYPE(...) M_GET_METHOD(SUBTYPE, M_NO_DEF_TYPE, __VA_ARGS__)
#define M_GET_GENTYPE(...) M_GET_METHOD(GENTYPE, M_NO_DEF_TYPE, __VA_ARGS__)
#define M_GET_NAME(...) M_GET_METHOD(NAME, M_NO_DEF_TYPE, __VA_ARGS__)
#define M_GET_OPLIST(...) M_GET_METHOD(OPLIST, (), __VA_ARGS__)
#define M_GET_SORT(...) M_GET_METHOD(SORT, M_NO_DEFAULT, __VA_ARGS__)
@@ -3502,6 +3503,16 @@ static inline size_t m_core_cstr_hash(const char str[])
#define M_GET_LIMITS(...) M_GET_METHOD(LIMITS, M_LIMITS_DEFAULT, __VA_ARGS__)
#define M_GET_PROPERTIES(...) M_GET_METHOD(PROPERTIES, (), __VA_ARGS__)
#define M_GET_EMPLACE_TYPE(...) M_GET_METHOD(EMPLACE_TYPE, M_NO_DEFAULT, __VA_ARGS__)
// As sttribute customization
#define M_GET_NEW(...) M_GET_METHOD(NEW, M_NEW_DEFAULT, __VA_ARGS__)
#define M_GET_DEL(...) M_GET_METHOD(DEL, M_DEL_DEFAULT, __VA_ARGS__)
#define M_GET_REALLOC(...) M_GET_METHOD(REALLOC, M_REALLOC_DEFAULT, __VA_ARGS__)
#define M_GET_FREE(...) M_GET_METHOD(FREE, M_FREE_DEFAULT, __VA_ARGS__)
#define M_GET_MEMPOOL(...) M_GET_METHOD(MEMPOOL, M_NO_DEFAULT, __VA_ARGS__)
#define M_GET_MEMPOOL_LINKAGE(...) M_GET_METHOD(MEMPOOL_LINKAGE, , __VA_ARGS__)
#define M_GET_SIZE(...) M_GET_METHOD(SIZE, 0, __VA_ARGS__)
#define M_GET_CONTEXT(...) M_GET_METHOD(CONTEXT, 0, __VA_ARGS__)
#define M_GET_POLICY(...) M_GET_METHOD(POLICY, 0, __VA_ARGS__)
// Calling method with support of defined transformation API
// operators that are not methods are commented
@@ -3514,16 +3525,12 @@ static inline size_t m_core_cstr_hash(const char str[])
#define M_CALL_SWAP(oplist, ...) M_APPLY_API(M_GET_SWAP oplist, oplist, __VA_ARGS__)
#define M_CALL_CLEAR(oplist, ...) M_APPLY_API(M_GET_CLEAR oplist, oplist, __VA_ARGS__)
#define M_CALL_NEW(oplist, ...) M_APPLY_API(M_GET_NEW oplist, oplist, __VA_ARGS__)
#define M_CALL_DEL(oplist, ...) M_APPLY_API(M_GET_DEL oplist, oplist, __VA_ARGS__)
#define M_CALL_REALLOC(oplist, ...) M_APPLY_API(M_GET_REALLOC oplist, oplist, __VA_ARGS__)
#define M_CALL_FREE(oplist, ...) M_APPLY_API(M_GET_FREE oplist, oplist, __VA_ARGS__)
#define M_CALL_MEMPOOL(oplist, ...) M_APPLY_API(M_GET_MEMPOOL oplist, oplist, __VA_ARGS__)
#define M_CALL_MEMPOOL_LINKAGE(oplist, ...) M_APPLY_API(M_GET_MEMPOOL_LINKAGE oplist, oplist, __VA_ARGS__)
#define M_CALL_HASH(oplist, ...) M_APPLY_API(M_GET_HASH oplist, oplist, __VA_ARGS__)
#define M_CALL_EQUAL(oplist, ...) M_APPLY_API(M_GET_EQUAL oplist, oplist, __VA_ARGS__)
#define M_CALL_CMP(oplist, ...) M_APPLY_API(M_GET_CMP oplist, oplist, __VA_ARGS__)
//#define M_CALL_TYPE(oplist, ...) M_APPLY_API(M_GET_TYPE oplist, oplist, __VA_ARGS__)
//#define M_CALL_SUBTYPE(oplist, ...) M_APPLY_API(M_GET_SUBTYPE oplist, oplist, __VA_ARGS__)
//#define M_CALL_GENTYPE(oplist, ...) M_APPLY_API(M_GET_GENTYPE oplist, oplist, __VA_ARGS__)
//#define M_CALL_NAME(oplist, ...) M_APPLY_API(M_GET_NAME oplist, oplist, __VA_ARGS__)
//#define M_CALL_OPLIST(oplist, ...) M_APPLY_API(M_GET_OPLIST oplist, oplist, __VA_ARGS__)
#define M_CALL_SORT(oplist, ...) M_APPLY_API(M_GET_SORT oplist, oplist, __VA_ARGS__)
@@ -3573,6 +3580,15 @@ static inline size_t m_core_cstr_hash(const char str[])
//#define M_CALL_LIMITS(oplist, ...) M_APPLY_API(M_GET_LIMITS oplist, oplist, __VA_ARGS__)
//#define M_CALL_PROPERTIES(oplist, ...) M_APPLY_API(M_GET_PROPERTIES oplist, oplist, __VA_ARGS__)
//#define M_CALL_EMPLACE_TYPE(oplist, ...) M_APPLY_API(M_GET_EMPLACE_TYPE oplist, oplist, __VA_ARGS__)
// As attribute customization
#define M_CALL_DEL(oplist, ...) M_APPLY_API(M_GET_DEL oplist, oplist, __VA_ARGS__)
#define M_CALL_REALLOC(oplist, ...) M_APPLY_API(M_GET_REALLOC oplist, oplist, __VA_ARGS__)
#define M_CALL_FREE(oplist, ...) M_APPLY_API(M_GET_FREE oplist, oplist, __VA_ARGS__)
#define M_CALL_MEMPOOL(oplist, ...) M_APPLY_API(M_GET_MEMPOOL oplist, oplist, __VA_ARGS__)
#define M_CALL_MEMPOOL_LINKAGE(oplist, ...) M_APPLY_API(M_GET_MEMPOOL_LINKAGE oplist, oplist, __VA_ARGS__)
//#define M_CALL_SIZE(oplist, ...) M_APPLY_API(M_GET_SIZE oplist, oplist, __VA_ARGS__)
//#define M_CALL_CONTEXT(oplist, ...) M_APPLY_API(M_GET_CONTEXT oplist, oplist, __VA_ARGS__)
//#define M_CALL_POLICY(oplist, ...) M_APPLY_API(M_GET_POLICY oplist, oplist, __VA_ARGS__)
/* API transformation support:
@@ -3774,7 +3790,7 @@ static inline size_t m_core_cstr_hash(const char str[])
#define M_CHECK_COMPATIBLE_OPLIST(name, inst, type, oplist) \
M_IF_METHOD(TYPE, oplist) \
( \
static inline void M_C3(m_c0re_ctype_, name, inst)(void) \
M_INLINE void M_C3(m_c0re_ctype_, name, inst)(void) \
{ \
type x; \
/* Proper check using _Generic */ \
@@ -3791,7 +3807,7 @@ static inline size_t m_core_cstr_hash(const char str[])
#define M_CHECK_COMPATIBLE_OPLIST(name, inst, type, oplist) \
M_IF_METHOD(TYPE, oplist) \
( \
static inline void M_C3(m_c0re_ctype_, name, inst)(void) \
M_INLINE void M_C3(m_c0re_ctype_, name, inst)(void) \
{ \
/* Imperfect check using size of type */ \
M_STATIC_ASSERT(sizeof (type) == sizeof (M_GET_TYPE oplist), \
@@ -3986,7 +4002,7 @@ static inline size_t m_core_cstr_hash(const char str[])
/* Input/Output an enumerate.
It is stored as a long long integer for best compatibility. */
#if M_USE_STDIO
static inline long long
M_INLINE long long
m_core_fscan_enum (FILE *f)
{
long long ret;
@@ -4003,12 +4019,12 @@ m_core_fscan_enum (FILE *f)
/* HACK: Parse two times to convert and then compute
if the conversion succeeds for PARSE */
static inline long long
M_INLINE long long
m_core_parse1_enum (const char str[])
{
return strtoll(str, NULL, 10);
}
static inline bool
M_INLINE bool
m_core_parse2_enum (const char str[], const char **endptr)
{
char *end;
@@ -4332,6 +4348,12 @@ m_core_parse2_enum (const char str[], const char **endptr)
#define M_LET_TRY_INJECT_PRE(cont, oplist, name)
#define M_LET_TRY_INJECT_POST(cont, oplist, name)
/*
Internal M_LET for use for withing container.
*/
#define M_QLET(x, type, oplist) \
M_LET(x, M_OPEXTEND(oplist, TYPE(type)))
/* Transform the va list by adding their number as the first argument of
the list.
Example: M_VA(a,b,c,d,e) ==> 5,a,b,c,d,e
@@ -4362,6 +4384,112 @@ m_core_parse2_enum (const char str[], const char **endptr)
#define M_DEFER_TRY_INJECT_POST(cont, clear) /* Nothing */
/* If exceptions are activated, M_CHAIN_INIT enables support for chaining
initialization at the begining of a constructor for the fields of the constructed
object so that even if the constructor failed and throw an exception,
the fields of the constructed object are properly cleared.
This is equivalent to C++ construct: void type() : field1(), field2() { rest of constructor }
M_CHAIN_INIT shall be the first instruction of the init function.
Second argument is the initialization code.
Third argument is the clear code.
The clear code is *only* executed on exception.
USAGE:
void init_function(struct_t s) {
M_CHAIN_INIT(name, string_init(s->str), string_clear(s->str)) {
// Rest of initialization code
}
}
*/
#define M_CHAIN_INIT(name, init, clear) \
M_CHAIN_INIT_INTERNAL(M_C(m_var_, name), init, clear)
#define M_CHAIN_INIT_INTERNAL(cont, init, clear) \
for(bool cont = true; cont; cont = false) \
M_DEFER_TRY_INJECT_PRE(cont, clear) \
for( init; cont ; cont = false) \
M_DEFER_TRY_INJECT_POST(cont, clear) \
for( (void) 0; cont; cont = false)
/* If exceptions are activated, M_CHAIN_OBJ enables support for chaining
initialization at the begining of a constructor for the fields of the constructed
object so that even if the constructor failed and throw an exception,
the fields of the constructed object are properly cleared.
This is equivalent to M_CHAIN_INIT except it takes an oplist.
This is equivalent to C++ construct: void type() : field1(), field2() { rest of constructor }
M_CHAIN_OBJ shall be the first instruction of the init function except
it can be freely mixed with M_CHAIN_INIT
First argument is a name identifier.
Second argument is the oplist of the variable to initialize.
Third argument is the variable to initialize.
Optional fourth argument is the value to use for initialization.
If there is no value, it will initialize using the INIT method.
Otherwise, if there is no parenthesis around the value, it will use the INIT_SET method.
Otherwise the INIT_WITH method.
The clear code is *only* executed on exception.
If the property NOCLEAR is defined for the object,
it won't generate an exception handler at all even if exceptions are activated,
and will only initialize the object.
USAGE:
void init_function(struct_t s) {
M_CHAIN_OBJ(name, STRING_OPLIST, s->str ) {
// Rest of initialization code
}
}
*/
#define M_CHAIN_OBJ(name, oplist, ...) \
M_BY_NARGS( M_IF(M_GET_PROPERTY(oplist, NOCLEAR))(M_CHAIN_OBJ_A, M_CHAIN_OBJ_B), __VA_ARGS__) \
(name, oplist, __VA_ARGS__)
// Need to define an exception handler. Use of M_CHAIN_INIT
#define M_CHAIN_OBJ_B__1(name, oplist, var) \
M_CHAIN_INIT( name, M_CALL_INIT(oplist, var), M_CALL_CLEAR(oplist, var) )
#define M_CHAIN_OBJ_B__2(name, oplist, var, value) \
M_IF(M_PARENTHESIS_P(value))(M_CHAIN_OBJ_B__2_WITH, M_CHAIN_OBJ_B__2_SET) \
(name, oplist, var, value)
#define M_CHAIN_OBJ_B__2_WITH(name, oplist, var, value) \
M_CHAIN_INIT( name, M_CALL_INIT_WITH(oplist, var, value), M_CALL_CLEAR(oplist, var) )
#define M_CHAIN_OBJ_B__2_SET(name, oplist, var, value) \
M_CHAIN_INIT( name, M_CALL_INIT_SET(oplist, var, value), M_CALL_CLEAR(oplist, var) )
// No need to define an exception handler. Just call the INIT function.
#define M_CHAIN_OBJ_A__1(name, oplist, var) \
M_CHAIN_FOR(name, M_CALL_INIT(oplist, var) )
#define M_CHAIN_OBJ_A__2(name, oplist, var, value) \
M_CHAIN_FOR(name, \
M_IF(M_PARENTHESIS_P(value))(M_CALL_INIT_WITH, M_CALL_INIT_SET) \
(oplist, var, value) )
// Execute the 'init' function in a for loop construct
#define M_CHAIN_FOR(name, init ) \
M_CHAIN_FOR_B(M_C(m_var_, name), init)
#define M_CHAIN_FOR_B(cont, init) \
for(bool cont = true; cont; cont = false) \
for( init; cont ; cont = false) \
for( (void) 0; cont; cont = false)
/* If exceptions are activated, M_ON_EXCEPTION enables support for fixing
the data structure when an exception is throw,
so that the data structure is proper for the CLEAR method.
The fix code is *only* executed on exception.
USAGE:
void init_function(struct_t s) {
M_ON_EXCEPTION(name, OPLIST, s->size = i ) {
// Rest of initialization code
}
}
*/
#define M_ON_EXCEPTION(name, oplist, fix) \
M_IF(M_GET_PROPERTY(oplist, NOCLEAR))(M_EAT, M_ON_EXCEPTION_B) \
(M_C(m_var_, name), fix)
#define M_ON_EXCEPTION_B(cont, fix) \
for(bool cont = true; cont; cont = false) \
M_DEFER_TRY_INJECT_PRE(cont, clear) \
for( ; cont ; cont = false) \
M_DEFER_TRY_INJECT_POST(cont, clear) \
for( ; cont; cont = false)
/* Declare a variable, initialize it, continue if the initialization succeeds,
and clears the variable afterwards.
Otherwise, stop the execution and execute else_code if defined.
@@ -4389,18 +4517,21 @@ m_core_parse2_enum (const char str[], const char **endptr)
/******************* INIT_WITH Enhancing ********************/
/************************************************************/
/* Add as suffix for the given function the number of arguments of the calls.
Can be used to call different function in function of the number of arguments. */
#define M_SUFFIX_FUNCTION_BY_NARGS(function, ...) M_C3(function, _, M_NARGS(__VA_ARGS__))
/* Add as suffix for the given function the number of arguments of the calls
equal to __ # NARGS(...)
Can be used to call different function in function of the number of arguments.
It doesn't call the function with the argument in order to be able to chain the
macro */
#define M_BY_NARGS(function, ...) M_C3(function, __, M_NARGS(__VA_ARGS__))
/* Call different INIT_WITH method in function of the number of arguments of the call,
* to be used in an OPLIST.
/* Call different methods in function of the number of arguments of the call,
* to be used in an OPLIST for the INIT_WITH operator.
* Shall be used with API_1 call (example INIT_WITH(API_1(M_INIT_WITH_NVAR)) )
* Shall define a NAME base method
* All INIT_WITH methods shall be named as name ## _init_with_ ## NARGS
* All INIT_WITH methods shall be named as name ## _init_with__ ## NARGS
*/
#define M_INIT_WITH_NVAR(oplist, ...) \
M_SUFFIX_FUNCTION_BY_NARGS(M_C(M_GET_NAME oplist, _init_with), __VA_ARGS__)(__VA_ARGS__)
M_BY_NARGS(M_C(M_GET_NAME oplist, _init_with), __VA_ARGS__)(__VA_ARGS__)
/* Initialize the container 'dest' as per 'oplist' INIT operator
@@ -4464,10 +4595,6 @@ m_core_parse2_enum (const char str[], const char **endptr)
)
#define M_INIT_EMPLACE_VAI2_FUNC(pair, a) \
M_INIT_EMPLACE_VAI3_FUNC(M_PAIR_1 pair, M_PAIR_2 pair, a)
/* We first push a raw new item, and then we get back its pointer using _back.
_back (contrary to _push_raw) has no side effect, and so is safe to be used
in a macro */
#define M_INIT_EMPLACE_VAI3_FUNC(d, op, a) \
( \
M_IF(M_PARENTHESIS_P(a)) \
@@ -4772,7 +4899,7 @@ m_core_parse2_enum (const char str[], const char **endptr)
one for value only.
*/
#define M_EMPLACE_ASS_ARRA1_BOTH_GENE(name, name_t, function_name, key_oplist, val_oplist, key_init_func, val_init_func, key_emplace_type, val_emplace_type) \
static inline void \
M_INLINE void \
function_name(name_t v \
M_EMPLACE_LIST_TYPE_VAR(akey, key_emplace_type) \
M_EMPLACE_LIST_TYPE_VAR(aval, val_emplace_type) \
@@ -4787,7 +4914,7 @@ m_core_parse2_enum (const char str[], const char **endptr)
} \
#define M_EMPLACE_ASS_ARRA1_KEY_GENE(name, name_t, function_name, key_oplist, val_oplist, key_init_func, val_init_func, key_emplace_type, val_emplace_type) \
static inline void \
M_INLINE void \
function_name(name_t v \
M_EMPLACE_LIST_TYPE_VAR(akey, key_emplace_type) \
, M_F(name, _value_ct) const val \
@@ -4799,7 +4926,7 @@ m_core_parse2_enum (const char str[], const char **endptr)
} \
#define M_EMPLACE_ASS_ARRA1_VAL_GENE(name, name_t, function_name, key_oplist, val_oplist, key_init_func, val_init_func, key_emplace_type, val_emplace_type) \
static inline void \
M_INLINE void \
function_name(name_t v, M_F(name, _key_ct) const key \
M_EMPLACE_LIST_TYPE_VAR(aval, val_emplace_type) \
){ \
@@ -4815,7 +4942,7 @@ m_core_parse2_enum (const char str[], const char **endptr)
This definition is far from being efficient but works for the current interface.
*/
#define M_EMPLACE_QUEUE_GENE(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
static inline void \
M_INLINE void \
function_name(name_t v \
M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \
{ \
@@ -4831,7 +4958,7 @@ m_core_parse2_enum (const char str[], const char **endptr)
This definition is far from being efficient but works for the current interface.
*/
#define M_EMPLACE_GET_GENE(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
static inline M_F(name, _value_ct) * \
M_INLINE M_F(name, _value_ct) * \
function_name(name_t const v \
M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \
{ \
@@ -4867,7 +4994,7 @@ typedef struct m_core_backoff_s {
/* Initialize a backoff object.
* Use the C function rand to initialize its internal seed.
* It should be good enough for the purpose of the backoff */
static inline void
M_INLINE void
m_core_backoff_init(m_core_backoff_ct backoff)
{
backoff->count = 0;
@@ -4875,7 +5002,7 @@ m_core_backoff_init(m_core_backoff_ct backoff)
}
/* Reset the count of the backoff object */
static inline void
M_INLINE void
m_core_backoff_reset(m_core_backoff_ct backoff)
{
backoff->count = 0;
@@ -4884,7 +5011,7 @@ m_core_backoff_reset(m_core_backoff_ct backoff)
/* Wait a few nanoseconds using an active loop,
* generating a random number of nanosecond to wait,
* and increment the number of times wait has been called */
static inline void
M_INLINE void
m_core_backoff_wait(m_core_backoff_ct backoff)
{
/* x is qualified as volatile to avoid being optimized away
@@ -4903,7 +5030,7 @@ m_core_backoff_wait(m_core_backoff_ct backoff)
}
/* Clear the backoff object */
static inline void
M_INLINE void
m_core_backoff_clear(m_core_backoff_ct backoff)
{
// Nothing to do
@@ -4923,9 +5050,10 @@ struct m_string_s;
* - OK & done (object is fully parsed),
* - OK & continue parsing (object is partially parsed)
* - Fail parsing
* - Fail parsing with given arguments (give explicit size)
*/
typedef enum m_serial_return_code_e {
M_SERIAL_OK_DONE = 0, M_SERIAL_OK_CONTINUE = 1, M_SERIAL_FAIL = 2
M_SERIAL_OK_DONE = 0, M_SERIAL_OK_CONTINUE = 1, M_SERIAL_FAIL = 2, M_SERIAL_FAIL_RETRY = 4
} m_serial_return_code_t;
#if defined(__cplusplus)
@@ -5106,7 +5234,7 @@ typedef struct m_serial_write_interface_s {
/* Helper functions for M_IN_SERIAL_DEFAULT_ARG
as we need to define a function per supported type in the generic expression */
#define M_IN_SERIAL_DEFAULT_TYPE_DEF(name, type, func, promoted_type) \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
name (m_serial_read_t serial, type *ptr) \
{ \
promoted_type i; \
@@ -5132,7 +5260,7 @@ M_IN_SERIAL_DEFAULT_TYPE_DEF(m_core_in_serial_double, double, read_float, long d
M_IN_SERIAL_DEFAULT_TYPE_DEF(m_core_in_serial_ldouble, long double, read_float, long double)
/* Helper function for M_ENUM_IN_SERIAL */
static inline long long
M_INLINE long long
m_core_in_serial_enum(m_serial_read_t serial)
{
long long i;
@@ -5145,7 +5273,7 @@ m_core_in_serial_enum(m_serial_read_t serial)
* because of expanded code will call strlen with NULL (which is illegal)
* However, the branch where it is called is unreachable, so the warning
* is not justified. */
static inline size_t
M_INLINE size_t
m_core_out_serial_strlen(const char s[])
{
M_ASSERT(s != NULL);
@@ -5157,7 +5285,7 @@ m_core_out_serial_strlen(const char s[])
* M_SERIAL_FAIL
* so that a breakpoint can be put on this function for debugging purpose.
*/
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_core_serial_fail(void)
{
return M_SERIAL_FAIL;
+55 -58
View File
@@ -170,7 +170,7 @@
#define M_D3QU3_DEF_CORE(name, type, oplist, deque_t, it_t, node_t) \
\
/* Allocate a new node for a deque */ \
static inline node_t* \
M_INLINE node_t* \
M_C3(m_d3qu3_,name,_new_node)(deque_t d) \
{ \
size_t def = d->default_size; \
@@ -198,7 +198,7 @@
return n; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init)(deque_t d) \
{ \
M_F(name, _node_list_init)(d->list); \
@@ -214,7 +214,7 @@
M_D3QU3_CONTRACT(d); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _reset)(deque_t d) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -239,7 +239,7 @@
M_D3QU3_CONTRACT(d); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(deque_t d) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -252,7 +252,7 @@
d->count = 0; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _push_back_raw)(deque_t d) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -279,13 +279,13 @@
} \
\
/* Internal, for INIT_WITH */ \
static inline type * \
M_INLINE type * \
M_F(name, _push_raw)(deque_t d) \
{ \
return M_F(name, _push_back_raw)(d); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _push_back)(deque_t d, type const x) \
{ \
type *p = M_F(name, _push_back_raw)(d); \
@@ -295,7 +295,7 @@
} \
\
M_IF_METHOD(INIT, oplist)( \
static inline type * \
M_INLINE type * \
M_F(name, _push_back_new)(deque_t d) \
{ \
type *p = M_F(name, _push_back_raw)(d); \
@@ -306,7 +306,7 @@
} \
, ) \
\
static inline void \
M_INLINE void \
M_F(name, _push_back_move)(deque_t d, type *x) \
{ \
M_ASSERT (x != NULL); \
@@ -316,7 +316,7 @@
M_DO_INIT_MOVE (oplist, *p, *x); \
} \
\
static inline type* \
M_INLINE type* \
M_F(name, _push_front_raw)(deque_t d) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -341,7 +341,7 @@
return ret; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _push_front)(deque_t d, type const x) \
{ \
type *p = M_F(name, _push_front_raw)(d); \
@@ -351,7 +351,7 @@
} \
\
M_IF_METHOD(INIT, oplist)( \
static inline type * \
M_INLINE type * \
M_F(name, _push_front_new)(deque_t d) \
{ \
type *p = M_F(name, _push_front_raw)(d); \
@@ -362,7 +362,7 @@
} \
,) \
\
static inline void \
M_INLINE void \
M_F(name, _push_front_move)(deque_t d, type *x) \
{ \
M_ASSERT (x != NULL); \
@@ -372,7 +372,7 @@
M_DO_INIT_MOVE (oplist, *p, *x); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _pop_back)(type *ptr, deque_t d) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -408,7 +408,7 @@
} \
\
M_IF_METHOD(INIT, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _pop_back_move)(type *ptr, deque_t d) \
{ \
M_ASSERT(ptr != NULL); \
@@ -418,7 +418,7 @@
} \
, ) \
\
static inline void \
M_INLINE void \
M_F(name, _pop_front)(type *ptr, deque_t d) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -464,7 +464,7 @@
} \
\
M_IF_METHOD(INIT, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _pop_front_move)(type *ptr, deque_t d) \
{ \
M_ASSERT(ptr != NULL); \
@@ -474,7 +474,7 @@
} \
,) \
\
static inline type * \
M_INLINE type * \
M_F(name, _back)(const deque_t d) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -489,7 +489,7 @@
return &n->data[i-1]; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _front)(const deque_t d) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -499,14 +499,14 @@
return &n->data[i]; \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _size)(const deque_t d) \
{ \
M_D3QU3_CONTRACT(d); \
return d->count; \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _capacity_back)(const deque_t v) \
{ \
M_D3QU3_CONTRACT(v); \
@@ -520,7 +520,7 @@
return s; \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _capacity_front)(const deque_t v) \
{ \
M_D3QU3_CONTRACT(v); \
@@ -534,20 +534,20 @@
return s; \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _capacity)(const deque_t v) \
{ \
return M_F(name, _capacity_back)(v)+M_F(name, _capacity_front)(v); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _empty_p)(const deque_t d) \
{ \
M_D3QU3_CONTRACT(d); \
return d->count == 0; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it)(it_t it, const deque_t d) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -557,7 +557,7 @@
it->deque = d; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_last)(it_t it, const deque_t d) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -572,7 +572,7 @@
} \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_end)(it_t it, const deque_t d) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -582,7 +582,7 @@
it->deque = d; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_set)(it_t it1, const it_t it2) \
{ \
M_ASSERT (it1 != NULL); \
@@ -592,7 +592,7 @@
it1->deque = it2->deque; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _end_p)(it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -602,7 +602,7 @@
&& it->index < it->deque->front->index); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _next)(it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -621,7 +621,7 @@
} \
} \
\
static inline void \
M_INLINE void \
M_F(name, _previous)(it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -640,7 +640,7 @@
} \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _last_p)(it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -650,7 +650,7 @@
return M_F(name, _end_p)(it2); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_equal_p)(it_t it1, const it_t it2) \
{ \
M_ASSERT (it1 != NULL); \
@@ -660,7 +660,7 @@
&& it1->index == it2->index; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _ref)(it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -668,7 +668,7 @@
return &it->node->data[it->index]; \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _cref)(it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -676,7 +676,7 @@
return M_CONST_CAST(type, &it->node->data[it->index]); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _remove)(deque_t d, it_t it) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -739,7 +739,7 @@
M_D3QU3_CONTRACT(d); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_set)(deque_t d, const deque_t src) \
{ \
M_D3QU3_CONTRACT(src); \
@@ -766,7 +766,7 @@
M_D3QU3_CONTRACT(d); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _set)(deque_t d, deque_t const src) \
{ \
if (M_UNLIKELY (src == d)) \
@@ -776,7 +776,7 @@
M_F(name, _init_set)(d, src); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_move)(deque_t d, deque_t src) \
{ \
M_D3QU3_CONTRACT(src); \
@@ -792,7 +792,7 @@
M_D3QU3_CONTRACT(d); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _move)(deque_t d, deque_t src) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -802,7 +802,7 @@
M_D3QU3_CONTRACT(d); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _swap)(deque_t d, deque_t e) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -818,7 +818,7 @@
M_D3QU3_CONTRACT(e); \
} \
\
static inline type* \
M_INLINE type* \
M_F(name, _get)(deque_t d, size_t key) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -837,13 +837,13 @@
} \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _cget)(deque_t d, size_t key) \
{ \
return M_CONST_CAST(type, M_F(name, _get)(d, key)); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _set_at)(deque_t d, size_t key, type const x) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -854,7 +854,7 @@
} \
\
M_IF_METHOD(EQUAL, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _equal_p)(const deque_t d1, const deque_t d2) \
{ \
M_D3QU3_CONTRACT(d1); \
@@ -877,7 +877,7 @@
, /* NO EQUAL */) \
\
M_IF_METHOD(HASH, oplist)( \
static inline size_t \
M_INLINE size_t \
M_F(name, _hash)(const deque_t d) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -892,7 +892,7 @@
, /* NO HASH */) \
\
M_IF_METHOD(SWAP, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _swap_at)(deque_t d, size_t i, size_t j) \
{ \
M_D3QU3_CONTRACT(d); \
@@ -906,7 +906,7 @@
, /* NO SWAP */) \
\
M_IF_METHOD(GET_STR, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _get_str)(m_string_t str, deque_t const deque, bool append) \
{ \
M_D3QU3_CONTRACT(deque); \
@@ -925,7 +925,7 @@
, /* no GET_STR */ ) \
\
M_IF_METHOD(OUT_STR, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _out_str)(FILE *file, const deque_t deque) \
{ \
M_D3QU3_CONTRACT(deque); \
@@ -945,7 +945,7 @@
, /* no OUT_STR */ ) \
\
M_IF_METHOD2(PARSE_STR, INIT, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _parse_str)(deque_t deque, const char str[], const char **endp) \
{ \
M_D3QU3_CONTRACT(deque); \
@@ -977,7 +977,7 @@
, /* no PARSE_STR */ ) \
\
M_IF_METHOD2(IN_STR, INIT, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _in_str)(deque_t deque, FILE *file) \
{ \
M_D3QU3_CONTRACT(deque); \
@@ -1004,7 +1004,7 @@
, /* no IN_STR */ ) \
\
M_IF_METHOD(OUT_SERIAL, oplist)( \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _out_serial)(m_serial_write_t f, const deque_t deque) \
{ \
M_D3QU3_CONTRACT(deque); \
@@ -1029,7 +1029,7 @@
, /* no OUT_SERIAL */ ) \
\
M_IF_METHOD2(IN_SERIAL, INIT, oplist)( \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _in_serial)(deque_t deque, m_serial_read_t f) \
{ \
M_D3QU3_CONTRACT(deque); \
@@ -1055,7 +1055,7 @@
/* Definition of the emplace_back function for deque */
#define M_D3QUE_EMPLACE_BACK_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
static inline void \
M_INLINE void \
function_name(name_t v \
M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \
{ \
@@ -1068,7 +1068,7 @@
/* Definition of the emplace_front function for deque */
#define M_D3QUE_EMPLACE_FRONT_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
static inline void \
M_INLINE void \
function_name(name_t v \
M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \
{ \
@@ -1133,9 +1133,6 @@
,M_IF_METHOD(IN_SERIAL, oplist)(IN_SERIAL(M_F(name, _in_serial)),) \
,M_IF_METHOD(EQUAL, oplist)(EQUAL(M_F(name, _equal_p)),) \
,M_IF_METHOD(HASH, oplist)(HASH(M_F(name, _hash)),) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
)
+66 -72
View File
@@ -333,7 +333,7 @@
typedef value_type M_F(name, _value_ct); \
typedef dict_it_t M_F(name, _it_ct); \
\
static inline void \
M_INLINE void \
M_F(name, _init)(dict_t map) \
{ \
M_ASSERT (map != NULL); \
@@ -345,7 +345,7 @@
M_D1CT_CONTRACT(name, map); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_set)(dict_t map, const dict_t org) \
{ \
M_D1CT_CONTRACT(name, org); \
@@ -357,7 +357,7 @@
M_D1CT_CONTRACT(name, map); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _set)(dict_t map, const dict_t org) \
{ \
M_D1CT_CONTRACT(name, map); \
@@ -369,14 +369,14 @@
M_D1CT_CONTRACT(name, map); \
} \
\
static inline void \
M_INLINE void \
M_F(name,_clear)(dict_t map) \
{ \
M_D1CT_CONTRACT(name, map); \
M_F(name, _array_list_pair_clear)(map->table); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_move)(dict_t map, dict_t org) \
{ \
M_D1CT_CONTRACT(name, org); \
@@ -387,7 +387,7 @@
M_D1CT_CONTRACT(name, map); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _swap)(dict_t d1, dict_t d2) \
{ \
M_D1CT_CONTRACT(name, d1); \
@@ -400,7 +400,7 @@
M_D1CT_CONTRACT(name, d2); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _move)(dict_t map, dict_t org) \
{ \
M_D1CT_CONTRACT(name, map); \
@@ -411,7 +411,7 @@
M_D1CT_CONTRACT(name, map); \
} \
\
static inline void \
M_INLINE void \
M_F(name,_reset)(dict_t map) \
{ \
M_F(name, _array_list_pair_reset)(map->table); \
@@ -422,7 +422,7 @@
M_D1CT_CONTRACT(name, map); \
} \
\
static inline value_type * \
M_INLINE value_type * \
M_F(name, _get)(const dict_t map, key_type const key) \
{ \
M_D1CT_CONTRACT(name, map); \
@@ -442,13 +442,13 @@
return NULL; \
} \
\
static inline value_type const * \
M_INLINE value_type const * \
M_F(name, _cget)(const dict_t map, key_type const key) \
{ \
return M_CONST_CAST(value_type, M_F(name,_get)(map,key)); \
} \
\
static inline void \
M_INLINE void \
M_C3(m_d1ct_,name,_resize_up)(dict_t map) \
{ \
/* NOTE: Contract may not be fulfilled here */ \
@@ -488,7 +488,7 @@
map->lower_limit = M_D1CT_LOWER_BOUND(new_size); \
} \
\
static inline void \
M_INLINE void \
M_C3(m_d1ct_,name,_resize_down)(dict_t map) \
{ \
/* NOTE: Contract may not be fulfilled here */ \
@@ -513,7 +513,7 @@
map->lower_limit = M_D1CT_LOWER_BOUND(new_size); \
} \
\
static inline void \
M_INLINE void \
M_IF(isSet)(M_F(name, _push), M_F(name, _set_at)) \
(dict_t map, key_type const key \
M_IF(isSet)(, M_DEFERRED_COMMA value_type const value)) \
@@ -545,7 +545,7 @@
M_D1CT_CONTRACT(name, map); \
} \
\
static inline value_type * \
M_INLINE value_type * \
M_F(name, _safe_get)(dict_t map, key_type const key) \
{ \
M_D1CT_CONTRACT(name, map); \
@@ -578,7 +578,7 @@
return &(*ref)->M_IF(isSet)(key, value); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _erase)(dict_t map, key_type const key) \
{ \
M_D1CT_CONTRACT(name, map); \
@@ -606,7 +606,7 @@
return ret; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it)(dict_it_t it, const dict_t d) \
{ \
M_D1CT_CONTRACT(name, d); \
@@ -623,7 +623,7 @@
} \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_set)(dict_it_t it, const dict_it_t ref) \
{ \
M_ASSERT (it != NULL && ref != NULL); \
@@ -632,21 +632,21 @@
M_F(name, _list_pair_it_set)(it->list_it, ref->list_it); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_end)(dict_it_t it, const dict_t d) \
{ \
M_D1CT_CONTRACT(name, d); \
M_F(name, _array_list_pair_it_end)(it->array_it, d->table); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _end_p)(const dict_it_t it) \
{ \
M_ASSERT (it != NULL); \
return M_F(name, _list_pair_end_p)(it->list_it); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _next)(dict_it_t it) \
{ \
M_ASSERT(it != NULL); \
@@ -661,7 +661,7 @@
} \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _last_p)(const dict_it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -671,7 +671,7 @@
return M_F(name, _end_p)(it2); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_equal_p)(const dict_it_t it1, const dict_it_t it2) \
{ \
M_ASSERT (it1 != NULL && it2 != NULL); \
@@ -679,7 +679,7 @@
it2->list_it); \
} \
\
static inline it_deref_t * \
M_INLINE it_deref_t * \
M_F(name, _ref)(const dict_it_t it) \
{ \
M_ASSERT(it != NULL); \
@@ -692,7 +692,7 @@
) \
} \
\
static inline const it_deref_t * \
M_INLINE const it_deref_t * \
M_F(name, _cref)(const dict_it_t it) \
{ \
M_ASSERT(it != NULL); \
@@ -733,14 +733,14 @@
*/
#define M_D1CT_FUNC_ADDITIONAL_DEF2(name, key_type, key_oplist, value_type, value_oplist, isSet, dict_t, dict_it_t, it_deref_t) \
\
static inline bool \
M_INLINE bool \
M_F(name,_empty_p)(const dict_t map) \
{ \
M_ASSERT(map != NULL); \
return map->count == 0; \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name,_size)(const dict_t map) \
{ \
M_ASSERT(map != NULL); \
@@ -748,7 +748,7 @@
} \
\
M_IF_METHOD(EQUAL, value_oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _equal_p)(const dict_t dict1, const dict_t dict2) \
{ \
M_ASSERT (dict1 != NULL && dict2 != NULL); \
@@ -778,7 +778,7 @@
, /* no value equal */ ) \
\
M_IF_METHOD_BOTH(GET_STR, key_oplist, value_oplist)( \
static inline void \
M_INLINE void \
M_F(name, _get_str)(m_string_t str, const dict_t dict, const bool append) \
{ \
(append ? m_string_cat_cstr : m_string_set_cstr) (str, "{"); \
@@ -804,7 +804,7 @@
, /* no GET_STR */ ) \
\
M_IF_METHOD_BOTH(OUT_STR, key_oplist, value_oplist)( \
static inline void \
M_INLINE void \
M_F(name, _out_str)(FILE *file, const dict_t dict) \
{ \
M_ASSERT (file != NULL); \
@@ -831,7 +831,7 @@
, /* no OUT_STR */ ) \
\
M_IF_METHOD_BOTH(PARSE_STR, key_oplist, value_oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _parse_str)(dict_t dict, const char str[], const char **endp) \
{ \
M_ASSERT (str != NULL); \
@@ -876,7 +876,7 @@
, /* no PARSE_STR */ ) \
\
M_IF_METHOD_BOTH(IN_STR, key_oplist, value_oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _in_str)(dict_t dict, FILE *file) \
{ \
M_ASSERT (file != NULL); \
@@ -918,7 +918,7 @@
, /* no IN_STR */ ) \
\
M_IF_METHOD_BOTH(OUT_SERIAL, key_oplist, value_oplist)( \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _out_serial)(m_serial_write_t f, dict_t const t1) \
{ \
M_ASSERT (f != NULL && f->m_interface != NULL); \
@@ -961,7 +961,7 @@
, /* no OUT_SERIAL */ ) \
\
M_IF_METHOD_BOTH(IN_SERIAL, key_oplist, value_oplist)( \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _in_serial)(dict_t t1, m_serial_read_t f) \
{ \
M_ASSERT (f != NULL && f->m_interface != NULL); \
@@ -1003,7 +1003,7 @@
, /* no in_serial */ ) \
\
M_IF(isSet)( \
static inline void \
M_INLINE void \
M_F(name, _splice)(dict_t d1, dict_t d2) \
{ \
dict_it_t it; \
@@ -1018,7 +1018,7 @@
} \
, \
M_IF_METHOD(ADD, value_oplist)( \
static inline void \
M_INLINE void \
M_F(name, _splice)(dict_t d1, dict_t d2) \
{ \
dict_it_t it; \
@@ -1098,9 +1098,6 @@
,M_IF_METHOD_BOTH(OUT_SERIAL, key_oplist, value_oplist)(OUT_SERIAL(M_F(name, _out_serial)),) \
,M_IF_METHOD_BOTH(IN_SERIAL, key_oplist, value_oplist)(IN_SERIAL(M_F(name, _in_serial)),) \
,M_IF_METHOD(EQUAL, value_oplist)(EQUAL(M_F(name, _equal_p)),) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW key_oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC key_oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL key_oplist),) \
)
/* Deferred evaluation for the definition,
@@ -1157,9 +1154,6 @@
,M_IF_METHOD(OUT_SERIAL, oplist)(OUT_SERIAL(M_F(name, _out_serial)),) \
,M_IF_METHOD(IN_SERIAL, oplist)(IN_SERIAL(M_F(name, _in_serial)),) \
,EQUAL(M_F(name, _equal_p)), \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
)
/* Define Lower Bound for hash table (TODO: Common macro for both implementation) */
@@ -1297,7 +1291,7 @@ enum m_d1ct_oa_element_e {
typedef value_type M_F(name, _value_ct); \
typedef dict_it_t M_F(name, _it_ct); \
\
static inline void \
M_INLINE void \
M_C3(m_d1ct_,name,_update_limit)(dict_t dict, size_t size) \
{ \
/* FIXME: Overflow not handled. What to do in case of it? */ \
@@ -1305,7 +1299,7 @@ enum m_d1ct_oa_element_e {
dict->lower_limit = (size <= M_D1CT_INITIAL_SIZE) ? 0 : (size_t) ((double) size * coeff_down) ; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init)(dict_t dict) \
{ \
M_ASSERT(0 <= (coeff_down) && (coeff_down)*2 < (coeff_up) && (coeff_up) < 1); \
@@ -1326,7 +1320,7 @@ enum m_d1ct_oa_element_e {
M_D1CT_OA_CONTRACT(dict); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(dict_t dict) \
{ \
M_D1CT_OA_CONTRACT(dict); \
@@ -1343,7 +1337,7 @@ enum m_d1ct_oa_element_e {
dict->data = NULL; \
} \
\
static inline value_type * \
M_INLINE value_type * \
M_F(name, _get)(const dict_t dict, key_type const key) \
{ \
M_D1CT_OA_CONTRACT(dict); \
@@ -1374,14 +1368,14 @@ enum m_d1ct_oa_element_e {
return NULL; \
} \
\
static inline value_type const * \
M_INLINE value_type const * \
M_F(name, _cget)(const dict_t map, key_type const key) \
{ \
return M_CONST_CAST(value_type, M_F(name,_get)(map,key)); \
} \
\
M_IF_DEBUG( \
static inline bool \
M_INLINE bool \
M_C3(m_d1ct_,name,_control_after_resize)(const dict_t h) \
{ \
/* This function checks if the reshashing of the dict is ok */ \
@@ -1399,7 +1393,7 @@ enum m_d1ct_oa_element_e {
} \
) \
\
static inline void \
M_INLINE void \
M_C3(m_d1ct_,name,_resize_up)(dict_t h, size_t newSize, bool updateLimit) \
{ \
size_t oldSize = h->mask+1; \
@@ -1477,7 +1471,7 @@ enum m_d1ct_oa_element_e {
M_D1CT_OA_CONTRACT(h); \
} \
\
static inline void \
M_INLINE void \
M_IF(isSet)(M_F(name, _push), M_F(name,_set_at)) \
(dict_t dict, key_type const key \
M_IF(isSet)(, M_DEFERRED_COMMA value_type const value) ) \
@@ -1537,7 +1531,7 @@ enum m_d1ct_oa_element_e {
M_D1CT_OA_CONTRACT(dict); \
} \
\
static inline value_type * \
M_INLINE value_type * \
M_F(name,_safe_get)(dict_t dict, key_type const key) \
{ \
M_D1CT_OA_CONTRACT(dict); \
@@ -1593,13 +1587,13 @@ enum m_d1ct_oa_element_e {
M_D1CT_OA_CONTRACT(dict); \
return &data[p].M_IF(isSet)(key, value); \
} \
static inline M_ATTR_DEPRECATED value_type * \
M_INLINE M_ATTR_DEPRECATED value_type * \
M_F(name,_get_at)(dict_t dict, key_type const key) \
{ \
return M_F(name,_safe_get)(dict, key); \
} \
\
static inline void \
M_INLINE void \
M_C3(m_d1ct_,name,_resize_down)(dict_t h, size_t newSize) \
{ \
size_t oldSize = h->mask+1; \
@@ -1677,7 +1671,7 @@ enum m_d1ct_oa_element_e {
M_D1CT_OA_CONTRACT(h); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name,_erase)(dict_t dict, key_type const key) \
{ \
M_D1CT_OA_CONTRACT(dict); \
@@ -1713,7 +1707,7 @@ enum m_d1ct_oa_element_e {
return true; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_set)(dict_t map, const dict_t org) \
{ \
M_D1CT_OA_CONTRACT(org); \
@@ -1741,7 +1735,7 @@ enum m_d1ct_oa_element_e {
M_D1CT_OA_CONTRACT(map); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _set)(dict_t map, const dict_t org) \
{ \
M_D1CT_OA_CONTRACT(map); \
@@ -1753,7 +1747,7 @@ enum m_d1ct_oa_element_e {
M_D1CT_OA_CONTRACT(map); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_move)(dict_t map, dict_t org) \
{ \
M_D1CT_OA_CONTRACT(org); \
@@ -1770,7 +1764,7 @@ enum m_d1ct_oa_element_e {
M_D1CT_OA_CONTRACT(map); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _move)(dict_t map, dict_t org) \
{ \
M_D1CT_OA_CONTRACT(map); \
@@ -1782,7 +1776,7 @@ enum m_d1ct_oa_element_e {
M_D1CT_OA_CONTRACT(map); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _swap)(dict_t d1, dict_t d2) \
{ \
M_D1CT_OA_CONTRACT(d1); \
@@ -1797,7 +1791,7 @@ enum m_d1ct_oa_element_e {
M_D1CT_OA_CONTRACT(d2); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _reset)(dict_t d) \
{ \
M_D1CT_OA_CONTRACT(d); \
@@ -1821,13 +1815,13 @@ enum m_d1ct_oa_element_e {
M_D1CT_OA_CONTRACT(d); \
} \
\
static inline void M_ATTR_DEPRECATED \
M_INLINE void M_ATTR_DEPRECATED \
M_F(name, _clean)(dict_t d) \
{ \
M_F(name, _reset)(d); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it)(dict_it_t it, const dict_t d) \
{ \
M_D1CT_OA_CONTRACT(d); \
@@ -1842,7 +1836,7 @@ enum m_d1ct_oa_element_e {
it->index = i; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_set)(dict_it_t it, const dict_it_t ref) \
{ \
M_ASSERT (it != NULL); \
@@ -1852,7 +1846,7 @@ enum m_d1ct_oa_element_e {
M_D1CT_OA_CONTRACT (it->dict); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_last)(dict_it_t it, const dict_t d) \
{ \
M_D1CT_OA_CONTRACT(d); \
@@ -1867,7 +1861,7 @@ enum m_d1ct_oa_element_e {
it->index = i; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_end)(dict_it_t it, const dict_t d) \
{ \
M_D1CT_OA_CONTRACT(d); \
@@ -1876,7 +1870,7 @@ enum m_d1ct_oa_element_e {
it->index = d->mask+1; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _end_p)(const dict_it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -1884,7 +1878,7 @@ enum m_d1ct_oa_element_e {
return it->index > it->dict->mask; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _next)(dict_it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -1898,7 +1892,7 @@ enum m_d1ct_oa_element_e {
it->index = i; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _previous)(dict_it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -1913,7 +1907,7 @@ enum m_d1ct_oa_element_e {
it->index = i; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _last_p)(const dict_it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -1923,7 +1917,7 @@ enum m_d1ct_oa_element_e {
return M_F(name, _end_p)(it2); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_equal_p)(const dict_it_t it1,const dict_it_t it2) \
{ \
M_ASSERT (it1 != NULL && it2 != NULL); \
@@ -1932,7 +1926,7 @@ enum m_d1ct_oa_element_e {
return it1->dict == it2->dict && it1->index == it2->index; \
} \
\
static inline it_deref_t * \
M_INLINE it_deref_t * \
M_F(name, _ref)(const dict_it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -1944,13 +1938,13 @@ enum m_d1ct_oa_element_e {
return &it->dict->data[i] M_IF(isSet)(.key, ); \
} \
\
static inline const it_deref_t * \
M_INLINE const it_deref_t * \
M_F(name, _cref)(const dict_it_t it) \
{ \
return M_CONST_CAST(it_deref_t, M_F(name, _ref)(it)); \
} \
\
static inline void \
M_INLINE void \
M_F(name,_reserve)(dict_t dict, size_t capacity) \
{ \
M_D1CT_OA_CONTRACT(dict); \
+12 -12
View File
@@ -161,7 +161,7 @@
/* Internal type for oplist & instance */ \
typedef interface_t M_F(name, _ct); \
\
static inline retcode \
M_INLINE retcode \
M_F(name, _call)(interface_t funcobj) \
{ \
M_IF(M_KEYWORD_P(void, retcode)) ( /* nothing */,return) \
@@ -197,7 +197,7 @@
/* Internal type for oplist & instance */ \
typedef interface_t M_F(name, _ct); \
\
static inline retcode \
M_INLINE retcode \
M_F(name, _call)(interface_t funcobj \
M_MAP3(M_FUNC0BJ_BASE_ARGLIST, name, __VA_ARGS__) ) \
{ \
@@ -220,7 +220,7 @@
/* Internal type for oplist */ \
typedef instance_t M_F(name, _ct); \
\
static inline M_C(base_name, _retcode_ct) \
M_INLINE M_C(base_name, _retcode_ct) \
M_F(name, _callback)(M_C(base_name, _ct) _self \
M_IF_EMPTY(M_OPFLAT param_list)( \
/* No param */, \
@@ -233,25 +233,25 @@
callback_core; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_with)(instance_t obj) \
{ \
obj->callback = M_F(name, _callback); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(instance_t obj) \
{ \
(void) obj; /* nothing to do */ \
} \
\
static inline struct M_C(base_name, _s) * \
M_INLINE struct M_C(base_name, _s) * \
M_F(name, _as_interface)(instance_t obj) \
{ \
return (struct M_C(base_name, _s) *) obj; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init)(instance_t obj) \
{ \
obj->callback = M_F(name, _callback); \
@@ -306,7 +306,7 @@
\
M_FUNC0BJ_CONTROL_ALL_OPLIST(name, __VA_ARGS__) \
\
static inline M_C(base_name, _retcode_ct) \
M_INLINE M_C(base_name, _retcode_ct) \
M_F(name, _callback)(M_C(base_name, _ct) _self \
M_IF_EMPTY(M_OPFLAT param_list)( \
/* No param */, \
@@ -321,20 +321,20 @@
callback_core; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_with)(instance_t obj M_MAP(M_FUNC0BJ_INS_ATTR_LIST, __VA_ARGS__)) \
{ \
obj->callback = M_F(name, _callback); \
M_MAP(M_FUNC0BJ_INS_ATTR_INIT_SET, __VA_ARGS__); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(instance_t obj) \
{ \
M_MAP(M_FUNC0BJ_INS_ATTR_CLEAR, __VA_ARGS__); \
} \
\
static inline struct M_C(base_name, _s) * \
M_INLINE struct M_C(base_name, _s) * \
M_F(name, _as_interface)(instance_t obj) \
{ \
return (struct M_C(base_name, _s) *) obj; \
@@ -342,7 +342,7 @@
\
M_IF(M_FUNC0BJ_TEST_METHOD_P(INIT, __VA_ARGS)) \
( \
static inline void \
M_INLINE void \
M_F(name, _init)(instance_t obj) \
{ \
obj->callback = M_F(name, _callback); \
+5 -5
View File
@@ -103,7 +103,7 @@ typedef struct m_genint_s {
* meaning it can be used to index global unique resources shared
* for all threads.
*/
static inline void
M_INLINE void
m_genint_init(m_genint_t s, unsigned int n)
{
M_ASSERT (s != NULL && n > 0 && n <= M_GENINT_MAX_ALLOC);
@@ -126,7 +126,7 @@ m_genint_init(m_genint_t s, unsigned int n)
}
/* Clear an integer generator (Destructor) */
static inline void
M_INLINE void
m_genint_clear(m_genint_t s)
{
M_GEN1NT_CONTRACT(s);
@@ -135,7 +135,7 @@ m_genint_clear(m_genint_t s)
}
/* Return the maximum integer that the generator will provide */
static inline size_t
M_INLINE size_t
m_genint_size(m_genint_t s)
{
M_GEN1NT_CONTRACT(s);
@@ -144,7 +144,7 @@ m_genint_size(m_genint_t s)
/* Get an unique integer from the integer generator.
* NOTE: For a typical case, the amortized cost is one CAS per pop. */
static inline unsigned int
M_INLINE unsigned int
m_genint_pop(m_genint_t s)
{
M_GEN1NT_CONTRACT(s);
@@ -204,7 +204,7 @@ m_genint_pop(m_genint_t s)
/* Restore a used integer in the integer generator.
* NOTE: For a typical case, the amortized cost is one CAS per pop */
static inline void
M_INLINE void
m_genint_push(m_genint_t s, unsigned int n)
{
M_GEN1NT_CONTRACT(s);
+38 -40
View File
@@ -26,7 +26,7 @@
#define MSTARLIB_I_LIST_H
#include "m-core.h"
#include "m-list.h" // For M_L1ST_DEF_ITBASE
#include "m-list.h" // For M_L1ST_ITBASE_DEF
/* Interface to add to a structure to enable intrusive doubly-linked support.
name: name of the intrusive list.
@@ -120,8 +120,6 @@ typedef struct m_il1st_head_s {
M_IF_METHOD(NEW, oplist)(IT_INSERT(M_F(name,_insert)),), \
OPLIST(oplist), \
SPLICE_BACK(M_F(name,_splice_back)) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
)
@@ -169,7 +167,7 @@ typedef struct m_il1st_head_s {
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
M_IL1ST_DEF_CORE(name, type, oplist, list_t, it_t) \
/* Used of internal macro from m-list */ \
M_L1ST_DEF_ITBASE(M_EXPAND_FUNC_INLINE, name, type, oplist, list_t, it_t)
M_L1ST_ITBASE_DEF(name, type, oplist, list_t, it_t)
/* Define the type of an intrusive list */
#define M_IL1ST_DEF_TYPE(name, type, oplist, list_t, it_t) \
@@ -200,7 +198,7 @@ typedef struct m_il1st_head_s {
/* Define core functions for intrusive lists */
#define M_IL1ST_DEF_CORE(name, type, oplist, list_t, it_t) \
\
static inline void \
M_INLINE void \
M_F(name, _init)(list_t list) \
{ \
M_ASSERT (list != NULL); \
@@ -209,7 +207,7 @@ typedef struct m_il1st_head_s {
M_IL1ST_CONTRACT(name, list); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _reset)(list_t list) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -231,7 +229,7 @@ typedef struct m_il1st_head_s {
M_IL1ST_CONTRACT(name, list); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(list_t list) \
{ \
/* Nothing to do more than clean the list itself */ \
@@ -241,7 +239,7 @@ typedef struct m_il1st_head_s {
list->name.prev = NULL; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _empty_p)(const list_t list) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -249,7 +247,7 @@ typedef struct m_il1st_head_s {
} \
\
\
static inline void \
M_INLINE void \
M_F(name, _init_move)(list_t list, list_t ref) \
{ \
M_IL1ST_CONTRACT(name, ref); \
@@ -266,14 +264,14 @@ typedef struct m_il1st_head_s {
M_IL1ST_CONTRACT(name, list); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _move)(list_t list, list_t ref) \
{ \
M_F(name, _clear)(list); \
M_F(name, _init_move)(list, ref); \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _size)(const list_t list) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -287,7 +285,7 @@ typedef struct m_il1st_head_s {
return s; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _push_back)(list_t list, type *obj) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -300,7 +298,7 @@ typedef struct m_il1st_head_s {
M_IL1ST_CONTRACT(name, list); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _push_front)(list_t list, type *obj) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -313,7 +311,7 @@ typedef struct m_il1st_head_s {
M_IL1ST_CONTRACT(name, list); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _push_after)(type *obj_pos, type *obj) \
{ \
M_ASSERT (obj_pos != NULL && obj != NULL); \
@@ -326,7 +324,7 @@ typedef struct m_il1st_head_s {
next->prev = &obj->name; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_field)(type *obj) \
{ \
M_ASSERT (obj != NULL); \
@@ -335,7 +333,7 @@ typedef struct m_il1st_head_s {
obj->name.prev = NULL; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _unlink)(type *obj) \
{ \
M_ASSERT (obj != NULL); \
@@ -350,7 +348,7 @@ typedef struct m_il1st_head_s {
obj->name.prev = NULL; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _back)(const list_t list) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -359,7 +357,7 @@ typedef struct m_il1st_head_s {
struct m_il1st_head_s, name); \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _front)(const list_t list) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -368,7 +366,7 @@ typedef struct m_il1st_head_s {
struct m_il1st_head_s, name); \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _next_obj)(const list_t list, type const *obj) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -379,7 +377,7 @@ typedef struct m_il1st_head_s {
struct m_il1st_head_s, name); \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _previous_obj)(const list_t list, type const *obj) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -390,7 +388,7 @@ typedef struct m_il1st_head_s {
struct m_il1st_head_s, name); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it)(it_t it, const list_t list) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -402,7 +400,7 @@ typedef struct m_il1st_head_s {
M_IL1ST_NODE_CONTRACT(it->current); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_set)(it_t it, const it_t cit) \
{ \
M_ASSERT (it != NULL && cit != NULL); \
@@ -413,7 +411,7 @@ typedef struct m_il1st_head_s {
M_IL1ST_NODE_CONTRACT(it->current); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_last)(it_t it, list_t const list) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -425,7 +423,7 @@ typedef struct m_il1st_head_s {
M_IL1ST_NODE_CONTRACT(it->current); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_end)(it_t it, list_t const list) \
{ \
M_ASSERT (it != NULL && list != NULL); \
@@ -436,7 +434,7 @@ typedef struct m_il1st_head_s {
M_IL1ST_NODE_CONTRACT(it->current); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _end_p)(const it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -444,7 +442,7 @@ typedef struct m_il1st_head_s {
return it->current == it->head; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _last_p)(const it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -452,7 +450,7 @@ typedef struct m_il1st_head_s {
return it->next == it->head || it->current == it->head; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _next)(it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -467,7 +465,7 @@ typedef struct m_il1st_head_s {
M_IL1ST_NODE_CONTRACT(it->current); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _previous)(it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -482,7 +480,7 @@ typedef struct m_il1st_head_s {
M_IL1ST_NODE_CONTRACT(it->current); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_equal_p)(const it_t it1, const it_t it2 ) \
{ \
M_ASSERT (it1 != NULL && it2 != NULL); \
@@ -490,7 +488,7 @@ typedef struct m_il1st_head_s {
return it1->head == it2->head && it1->current == it2->current; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _ref)(const it_t it) \
{ \
M_ASSERT (it != NULL && it->current != NULL); \
@@ -503,14 +501,14 @@ typedef struct m_il1st_head_s {
struct m_il1st_head_s, name); \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _cref)(const it_t it) \
{ \
type *ptr = M_F(name, _ref)(it); \
return M_CONST_CAST(type, ptr); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _remove)(list_t list, it_t it) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -525,7 +523,7 @@ typedef struct m_il1st_head_s {
} \
\
M_IF_METHOD2(NEW, INIT_SET, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _insert)(list_t list, it_t it, type x) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -544,7 +542,7 @@ typedef struct m_il1st_head_s {
} \
, /* NEW & INIT_SET not defined */) \
\
static inline type * \
M_INLINE type * \
M_F(name, _pop_back)(list_t list) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -555,7 +553,7 @@ typedef struct m_il1st_head_s {
return obj; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _pop_front)(list_t list) \
{ \
M_IL1ST_CONTRACT(name, list); \
@@ -566,7 +564,7 @@ typedef struct m_il1st_head_s {
return obj; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _splice)(list_t list1, list_t list2) \
{ \
M_IL1ST_CONTRACT(name, list1); \
@@ -583,7 +581,7 @@ typedef struct m_il1st_head_s {
M_IL1ST_CONTRACT(name, list2); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _splice_back)(list_t nv, list_t ov, it_t it) \
{ \
M_IL1ST_CONTRACT(name, nv); \
@@ -599,7 +597,7 @@ typedef struct m_il1st_head_s {
M_IL1ST_CONTRACT(name, ov); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _splice_at)(list_t nlist, it_t npos, \
list_t olist, it_t opos) \
{ \
@@ -629,7 +627,7 @@ typedef struct m_il1st_head_s {
M_IL1ST_CONTRACT(name, olist); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _swap)(list_t d, list_t e) \
{ \
M_IL1ST_CONTRACT(name, d); \
@@ -652,7 +650,7 @@ typedef struct m_il1st_head_s {
M_IL1ST_CONTRACT(name, e); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _reverse)(list_t list) \
{ \
M_IL1ST_CONTRACT(name, list); \
+10 -13
View File
@@ -55,13 +55,13 @@ M_BEGIN_PROTECTED_CODE
ATOMIC_VAR_INIT(0)
/* Define the intrusive shared pointer type and its static inline functions.
/* Define the intrusive shared pointer type and its M_INLINE functions.
USAGE: ISHARED_PTR_DEF(name, type, [, oplist]) */
#define M_ISHARED_PTR_DEF(name, ...) \
M_ISHARED_PTR_DEF_AS(name, M_F(name,_t), __VA_ARGS__)
/* Define the intrusive shared pointer type and its static inline functions
/* Define the intrusive shared pointer type and its M_INLINE functions
as the name name_t
USAGE: ISHARED_PTR_DEF_AS(name, name_t, type, [, oplist]) */
#define M_ISHARED_PTR_DEF_AS(name, name_t, ...) \
@@ -98,9 +98,6 @@ M_BEGIN_PROTECTED_CODE
TYPE(M_F(name, _ct)), \
OPLIST(oplist), \
SUBTYPE(M_F(name, _subtype_ct)) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
)
@@ -135,7 +132,7 @@ M_BEGIN_PROTECTED_CODE
/* Define the core functions */
#define M_ISHAR3D_PTR_DEF_CORE(name, type, oplist, shared_t) \
\
static inline shared_t \
M_INLINE shared_t \
M_F(name, _init)(type *ptr) \
{ \
/* Initialize the type referenced by the pointer */ \
@@ -145,7 +142,7 @@ M_BEGIN_PROTECTED_CODE
return ptr; \
} \
\
static inline shared_t \
M_INLINE shared_t \
M_F(name, _init_set)(shared_t shared) \
{ \
if (M_LIKELY (shared != NULL)) { \
@@ -159,7 +156,7 @@ M_BEGIN_PROTECTED_CODE
M_IF_DISABLED_METHOD(NEW, oplist) \
( \
/* This function is only for static object */ \
static inline shared_t \
M_INLINE shared_t \
M_F(name, _init_once)(type *shared) \
{ \
if (M_LIKELY (shared != NULL)) { \
@@ -190,7 +187,7 @@ M_BEGIN_PROTECTED_CODE
} \
, \
/* This function is only for dynamic object */ \
static inline shared_t \
M_INLINE shared_t \
M_F(name, _init_new)(void) \
{ \
type *ptr = M_CALL_NEW(oplist, type); \
@@ -205,7 +202,7 @@ M_BEGIN_PROTECTED_CODE
/* End of NEW */) \
, /* End of INIT */) \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(shared_t shared) \
{ \
if (shared != NULL) { \
@@ -216,7 +213,7 @@ M_BEGIN_PROTECTED_CODE
} \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear_ptr)(shared_t *shared) \
{ \
M_ASSERT(shared != NULL); \
@@ -224,14 +221,14 @@ M_BEGIN_PROTECTED_CODE
*shared = NULL; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _reset)(shared_t *shared) \
{ \
M_F(name, _clear)(*shared); \
*shared = NULL; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _set)(shared_t *ptr, shared_t shared) \
{ \
M_ASSERT (ptr != NULL); \
+332 -248
View File
File diff suppressed because it is too large. Load diff
+4 -4
View File
@@ -109,7 +109,7 @@
/* Define the core functions of the mempool */
#define M_M3MPOOL_DEF_CORE(name, type, name_t) \
\
static inline void \
M_INLINE void \
M_F(name,_init)(name_t mem) \
{ \
mem->free_list = NULL; \
@@ -123,7 +123,7 @@
M_M3MPOOL_CONTRACT(mem, type); \
} \
\
static inline void \
M_INLINE void \
M_F(name,_clear)(name_t mem) \
{ \
M_M3MPOOL_CONTRACT(mem, type); \
@@ -138,7 +138,7 @@
mem->current_segment = NULL; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name,_alloc)(name_t mem) \
{ \
M_M3MPOOL_CONTRACT(mem, type); \
@@ -173,7 +173,7 @@
return &ret->t; \
} \
\
static inline void \
M_INLINE void \
M_F(name,_free)(name_t mem, type *ptr) \
{ \
M_M3MPOOL_CONTRACT(mem, type); \
+39 -38
View File
@@ -161,95 +161,95 @@
/* Define the core functions */
#define M_PR1OQUEUE_DEF_CORE(name, type, oplist, prioqueue_t, it_t) \
\
static inline void \
M_INLINE void \
M_F(name, _init)(prioqueue_t p) \
{ \
M_F(name, _array_init)(p->array); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_set)(prioqueue_t p, prioqueue_t const o) \
{ \
M_F(name, _array_init_set)(p->array, o->array); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _set)(prioqueue_t p, prioqueue_t const o) \
{ \
M_F(name, _array_set)(p->array, o->array); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(prioqueue_t p) \
{ \
M_F(name, _array_clear)(p->array); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_move)(prioqueue_t p, prioqueue_t o) \
{ \
M_F(name, _array_init_move)(p->array, o->array); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _move)(prioqueue_t p, prioqueue_t o) \
{ \
M_F(name, _array_move)(p->array, o->array); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _swap)(prioqueue_t p, prioqueue_t o) \
{ \
M_F(name, _array_swap)(p->array, o->array); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _reset)(prioqueue_t p) \
{ \
M_F(name, _array_reset)(p->array); \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _i_parent)(size_t i) \
{ \
M_ASSERT (i > 0); \
return (i - 1) / 2; \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _i_lchild)(size_t i) \
{ \
M_ASSERT(i <= ((SIZE_MAX)-2)/2); \
return 2*i + 1; \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _i_rchild)(size_t i) \
{ \
M_ASSERT(i <= ((SIZE_MAX)-2)/2); \
return 2*i + 2; \
} \
\
static inline int \
M_INLINE int \
M_F(name, _i_cmp)(const prioqueue_t p, size_t i, size_t j) \
{ \
return M_CALL_CMP(oplist, *M_F(name, _array_cget)(p->array, i), \
*M_F(name, _array_cget)(p->array, j)); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _empty_p)(prioqueue_t const p) \
{ \
return M_F(name, _array_empty_p)(p->array); \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _size)(prioqueue_t const p) \
{ \
return M_F(name, _array_size)(p->array); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _push)(prioqueue_t p, type const x) \
{ \
/* Push back the new element at the end of the array */ \
@@ -267,13 +267,13 @@
} \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _front)(prioqueue_t const p) \
{ \
return M_F(name, _array_cget)(p->array, 0); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _pop)(type *x, prioqueue_t p) \
{ \
/* Swap the front element with the last element */ \
@@ -303,26 +303,27 @@
M_IF_METHOD(EQUAL, oplist) \
( \
/* EQUAL & CMP may be uncorrelated */ \
static inline bool \
M_INLINE bool \
M_F(name, _equal_p)(prioqueue_t const p, prioqueue_t const q) \
{ \
return M_F(name, _array_equal_p)(p->array, q->array); \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _i_find)(prioqueue_t p, type const x) \
{ \
size_t size = M_F(name, _array_size)(p->array); \
size_t i = 0; \
for(i = 0; i < size; i++) { \
/* FIXME: Can we use CMP and the partial order to go faster? */ \
/* We cannot use CMP and the partial order to go faster \
EQUAL & CMP may be uncorrelated */ \
if (M_CALL_EQUAL(oplist, *M_F(name, _array_cget)(p->array, i), x)) \
break; \
} \
return i; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _erase)(prioqueue_t p, type const x) \
{ \
/* First pass: search for an item EQUAL to x */ \
@@ -351,7 +352,7 @@
return true; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _update)(prioqueue_t p, type const xold, type const xnew) \
{ \
/* NOTE: xold can be the same pointer than xnew */ \
@@ -394,62 +395,62 @@
#define M_PR1OQUEUE_DEF_IT(name, type, oplist, prioqueue_t, it_t) \
\
/* Define iterators over the array iterator */ \
static inline void \
M_INLINE void \
M_F(name, _it)(it_t it, prioqueue_t const v) \
{ \
M_F(name, _array_it)(it, v->array); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_last)(it_t it, prioqueue_t const v) \
{ \
M_F(name, _array_it_last)(it, v->array); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_end)(it_t it, prioqueue_t const v) \
{ \
M_F(name, _array_it_end)(it, v->array); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_set)(it_t it, const it_t org) \
{ \
M_F(name, _array_it_set)(it, org); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _end_p)(const it_t it) \
{ \
return M_F(name, _array_end_p)(it); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _last_p)(const it_t it) \
{ \
return M_F(name, _array_last_p)(it); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_equal_p)(const it_t it1, \
const it_t it2) \
{ \
return M_F(name, _array_it_equal_p)(it1, it2); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _next)(it_t it) \
{ \
M_F(name, _array_next)(it); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _previous)(it_t it) \
{ \
M_F(name, _array_previous)(it); \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _cref)(const it_t it) \
{ \
return M_F(name, _array_cref)(it); \
@@ -458,7 +459,7 @@
/* Define the IO functions */
#define M_PR1OQUEUE_DEF_IO(name, type, oplist, prioqueue_t, it_t) \
M_IF_METHOD(OUT_STR, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _out_str)(FILE *file, const prioqueue_t p) \
{ \
M_F(name, _array_out_str)(file, p->array); \
@@ -466,7 +467,7 @@
,/* No OUT_STR */) \
\
M_IF_METHOD(IN_STR, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _in_str)(prioqueue_t p, FILE *file) \
{ \
return M_F(name, _array_in_str)(p->array, file); \
@@ -474,7 +475,7 @@
,/* No IN_STR */) \
\
M_IF_METHOD(GET_STR, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _get_str)(string_t str, const prioqueue_t p, bool append) \
{ \
M_F(name, _array_get_str)(str, p->array, append); \
@@ -482,7 +483,7 @@
,/* No GET_STR */) \
\
M_IF_METHOD(PARSE_STR, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _parse_str)(prioqueue_t p, const char str[], const char **endp) \
{ \
return M_F(name, _array_parse_str)(p->array, str, endp); \
@@ -490,7 +491,7 @@
,/* No PARSE_STR */) \
\
M_IF_METHOD(OUT_SERIAL, oplist)( \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _out_serial)(m_serial_write_t f, const prioqueue_t p) \
{ \
return M_F(name, _array_out_serial)(f, p->array); \
@@ -498,7 +499,7 @@
,/* No OUT_SERIAL */) \
\
M_IF_METHOD2(IN_SERIAL, INIT, oplist)( \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _in_serial)(prioqueue_t p, m_serial_read_t f) \
{ \
return M_F(name, _array_in_serial)(p->array, f); \
+51 -54
View File
@@ -109,9 +109,6 @@
M_IF_METHOD(IN_SERIAL, oplist)(IN_SERIAL(M_F(name, _in_serial)),), \
M_IF_METHOD(EQUAL, oplist)(EQUAL(M_F(name, _equal_p)),), \
M_IF_METHOD(HASH, oplist)(HASH(M_F(name, _hash)),) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
)
@@ -227,28 +224,28 @@ typedef enum {
/* Definition of the global variable used to reference this pool */ \
M_GET_MEMPOOL_LINKAGE oplist M_F(name, _mempool_t) M_GET_MEMPOOL oplist; \
/* Allocator function */ \
static inline node_t *M_C3(m_rbtr33_,name,_new)(void) { \
M_INLINE node_t *M_C3(m_rbtr33_,name,_new)(void) { \
return M_F(name, _mempool_alloc)(M_GET_MEMPOOL oplist); \
} \
/* Deallocator function */ \
static inline void M_C3(m_rbtr33_,name,_del)(node_t *ptr) { \
M_INLINE void M_C3(m_rbtr33_,name,_del)(node_t *ptr) { \
M_F(name, _mempool_free)(M_GET_MEMPOOL oplist, ptr); \
} \
\
, /* No mempool allocation */ \
/* Classic Allocator function (common case) */ \
static inline node_t *M_C3(m_rbtr33_,name,_new)(void) { \
M_INLINE node_t *M_C3(m_rbtr33_,name,_new)(void) { \
return M_CALL_NEW(oplist, node_t); \
} \
/* Classic deallocator function (common case) */ \
static inline void M_C3(m_rbtr33_,name,_del)(node_t *ptr) { \
M_INLINE void M_C3(m_rbtr33_,name,_del)(node_t *ptr) { \
M_CALL_DEL(oplist, ptr); \
} ) \
/* Define the core functions */
#define M_RBTR33_DEF_CORE(name, type, oplist, tree_t, node_t, it_t) \
\
static inline void \
M_INLINE void \
M_F(name, _init)(tree_t tree) \
{ \
M_ASSERT (tree != NULL); \
@@ -257,7 +254,7 @@ typedef enum {
M_RBTR33_CONTRACT(tree); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _reset)(tree_t tree) \
{ \
M_RBTR33_CONTRACT(tree); \
@@ -302,14 +299,14 @@ typedef enum {
tree->size = 0; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(tree_t tree) \
{ \
/* Nothing more than clean the tree as everything is cleared */ \
M_F(name, _reset)(tree); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _push)(tree_t tree, type const data) \
{ \
M_RBTR33_CONTRACT(tree); \
@@ -435,7 +432,7 @@ typedef enum {
M_RBTR33_CONTRACT (tree); \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _size)(const tree_t tree) \
{ \
M_RBTR33_CONTRACT (tree); \
@@ -443,7 +440,7 @@ typedef enum {
} \
\
/* Set the iterator to the first (child=0) or last (child=1) element */ \
static inline void \
M_INLINE void \
M_C3(m_rbtr33_,name,_it)(it_t it, const tree_t tree, int child) \
{ \
M_RBTR33_CONTRACT (tree); \
@@ -465,19 +462,19 @@ typedef enum {
it->cpt = cpt; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it)(it_t it, const tree_t tree) \
{ \
M_C3(m_rbtr33_,name,_it)(it, tree, 0); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_last)(it_t it, const tree_t tree) \
{ \
M_C3(m_rbtr33_,name,_it)(it, tree, 1); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_end)(it_t it, const tree_t tree) \
{ \
M_RBTR33_CONTRACT (tree); \
@@ -486,14 +483,14 @@ typedef enum {
it->cpt = 0; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_set)(it_t it, const it_t ref) \
{ \
M_ASSERT (it != NULL && ref != NULL); \
*it = *ref; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _end_p)(const it_t it) \
{ \
M_ASSERT (it != NULL); \
@@ -501,7 +498,7 @@ typedef enum {
} \
\
/* Go to the next (child = 0)or previous element (child = 1) */ \
static inline void \
M_INLINE void \
M_C3(m_rbtr33_,name,_next)(it_t it, int child) \
{ \
M_ASSERT (it != NULL); \
@@ -533,19 +530,19 @@ typedef enum {
it->cpt = cpt; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _next)(it_t it) \
{ \
M_C3(m_rbtr33_,name,_next)(it, 0); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _previous)(it_t it) \
{ \
M_C3(m_rbtr33_,name,_next)(it, 1); \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _ref)(const it_t it) \
{ \
M_ASSERT(it != NULL); \
@@ -555,13 +552,13 @@ typedef enum {
return &(it->stack[it->cpt-1]->data); \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _cref)(const it_t it) \
{ \
return M_CONST_CAST(type, M_F(name, _ref)(it)); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_equal_p)(const it_t it1, const it_t it2) \
{ \
M_ASSERT(it1 != NULL && it2 != NULL); \
@@ -572,7 +569,7 @@ typedef enum {
&& (it1->cpt == 0 || it1->stack[it1->cpt-1] == it2->stack[it2->cpt-1]); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_from)(it_t it, const tree_t tree, type const data) \
{ \
M_RBTR33_CONTRACT (tree); \
@@ -601,7 +598,7 @@ typedef enum {
} \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_until_p)(it_t it, type const data) \
{ \
M_ASSERT (it != NULL); \
@@ -612,7 +609,7 @@ typedef enum {
return (cmp >= 0); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_while_p)(it_t it, type const data) \
{ \
M_ASSERT (it != NULL); \
@@ -623,7 +620,7 @@ typedef enum {
return (cmp <= 0); \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _min)(const tree_t tree) \
{ \
M_RBTR33_CONTRACT (tree); \
@@ -636,7 +633,7 @@ typedef enum {
return &n->data; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _max)(const tree_t tree) \
{ \
M_RBTR33_CONTRACT (tree); \
@@ -649,19 +646,19 @@ typedef enum {
return &n->data; \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _cmin)(const tree_t tree) \
{ \
return M_CONST_CAST(type, M_F(name, _min)(tree)); \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _cmax)(const tree_t tree) \
{ \
return M_CONST_CAST(type, M_F(name, _max)(tree)); \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _get)(const tree_t tree, type const data) \
{ \
M_RBTR33_CONTRACT (tree); \
@@ -680,14 +677,14 @@ typedef enum {
return NULL; \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _cget)(const tree_t tree, type const data) \
{ \
return M_CONST_CAST(type, M_F(name, _get)(tree, data)); \
} \
\
/* Create a copy of the given node (recursively) */ \
static inline node_t * \
M_INLINE node_t * \
M_C3(m_rbtr33_,name,_copy_node)(const node_t *o) \
{ \
if (o == NULL) return NULL; \
@@ -703,7 +700,7 @@ typedef enum {
return n; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_set)(tree_t tree, const tree_t ref) \
{ \
M_RBTR33_CONTRACT (ref); \
@@ -714,7 +711,7 @@ typedef enum {
M_RBTR33_CONTRACT (tree); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _set)(tree_t tree, const tree_t ref) \
{ \
M_RBTR33_CONTRACT (tree); \
@@ -724,7 +721,7 @@ typedef enum {
M_F(name,_init_set)(tree, ref); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_move)(tree_t tree, tree_t ref) \
{ \
M_RBTR33_CONTRACT (ref); \
@@ -736,7 +733,7 @@ typedef enum {
M_RBTR33_CONTRACT (tree); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _move)(tree_t tree, tree_t ref) \
{ \
M_RBTR33_CONTRACT (tree); \
@@ -747,7 +744,7 @@ typedef enum {
M_RBTR33_CONTRACT (tree); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _swap)(tree_t tree1, tree_t tree2) \
{ \
M_RBTR33_CONTRACT (tree1); \
@@ -758,7 +755,7 @@ typedef enum {
M_RBTR33_CONTRACT (tree2); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _empty_p)(const tree_t tree) \
{ \
M_RBTR33_CONTRACT (tree); \
@@ -766,19 +763,19 @@ typedef enum {
} \
\
/* Take care of the case n == NULL too */ \
static inline bool \
M_INLINE bool \
M_C3(m_rbtr33_,name,_black_p)(const node_t *n) \
{ \
return (n == NULL) ? true : M_RBTR33_IS_BLACK(n); \
} \
\
static inline void \
M_INLINE void \
M_C3(m_rbtr33_,name,_set_black)(node_t *n) \
{ \
if (n != NULL) M_RBTR33_SET_BLACK(n); \
} \
\
static inline node_t * \
M_INLINE node_t * \
M_C3(m_rbtr33_,name,_rotate)(node_t *pp, node_t *ppp, const bool right) \
{ \
M_ASSERT (pp != NULL && ppp != NULL); \
@@ -795,7 +792,7 @@ typedef enum {
\
M_IF_DEBUG( \
/* Compute the depth of a node */ \
static inline size_t \
M_INLINE size_t \
M_C3(m_rbtr33_,name,_compute_depth)(const node_t *n) \
{ \
if (n == NULL) return 1; \
@@ -804,7 +801,7 @@ typedef enum {
} \
) \
\
static inline bool \
M_INLINE bool \
M_F(name, _pop_at)(type *data_ptr, tree_t tree, type const key) \
{ \
M_RBTR33_CONTRACT (tree); \
@@ -964,7 +961,7 @@ typedef enum {
return true; \
} \
\
static inline void M_F(name,_remove)(tree_t t, it_t it) \
M_INLINE void M_F(name,_remove)(tree_t t, it_t it) \
{ \
/* Not optimum: another search in the tree is performed */ \
type data; \
@@ -979,7 +976,7 @@ typedef enum {
} \
\
M_IF_METHOD(EQUAL, oplist)( \
static inline bool M_F(name,_equal_p)(const tree_t t1, const tree_t t2) { \
M_INLINE bool M_F(name,_equal_p)(const tree_t t1, const tree_t t2) { \
M_RBTR33_CONTRACT(t1); \
M_RBTR33_CONTRACT(t2); \
if (t1->size != t2->size) return false; \
@@ -1006,7 +1003,7 @@ typedef enum {
, /* NO EQUAL METHOD */ ) \
\
M_IF_METHOD(HASH, oplist)( \
static inline size_t M_F(name,_hash)(const tree_t t1) { \
M_INLINE size_t M_F(name,_hash)(const tree_t t1) { \
M_RBTR33_CONTRACT(t1); \
M_HASH_DECL(hash); \
/* NOTE: We can't compute the hash directly for the same reason \
@@ -1025,7 +1022,7 @@ typedef enum {
/* Define the I/O functions */
#define M_RBTR33_DEF_IO(name, type, oplist, tree_t, node_t, it_t) \
M_IF_METHOD(GET_STR, oplist)( \
static inline void M_F(name, _get_str)(m_string_t str, \
M_INLINE void M_F(name, _get_str)(m_string_t str, \
tree_t const t1, bool append) { \
M_RBTR33_CONTRACT(t1); \
M_ASSERT(str != NULL); \
@@ -1047,7 +1044,7 @@ typedef enum {
, /* NO GET_STR */ ) \
\
M_IF_METHOD(OUT_STR, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _out_str)(FILE *file, tree_t const rbtree) \
{ \
M_RBTR33_CONTRACT(rbtree); \
@@ -1069,7 +1066,7 @@ typedef enum {
, /* no out_str */ ) \
\
M_IF_METHOD(PARSE_STR, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _parse_str)(tree_t rbtree, const char str[], const char **endp) \
{ \
M_RBTR33_CONTRACT(rbtree); \
@@ -1100,7 +1097,7 @@ typedef enum {
, /* no parse_str */ ) \
\
M_IF_METHOD(IN_STR, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _in_str)(tree_t rbtree, FILE *file) \
{ \
M_RBTR33_CONTRACT(rbtree); \
@@ -1126,7 +1123,7 @@ typedef enum {
, /* no in_str */ ) \
\
M_IF_METHOD(OUT_SERIAL, oplist)( \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _out_serial)(m_serial_write_t f, tree_t const t1) \
{ \
M_RBTR33_CONTRACT(t1); \
@@ -1152,7 +1149,7 @@ typedef enum {
, /* no OUT_SERIAL */ ) \
\
M_IF_METHOD(IN_SERIAL, oplist)( \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _in_serial)(tree_t t1, m_serial_read_t f) \
{ \
M_RBTR33_CONTRACT(t1); \
+66 -120
View File
@@ -41,7 +41,7 @@ M_BEGIN_PROTECTED_CODE
* Write size_t in the stream in a compact form to reduce consumption
* (and I/O bandwidth)
*/
static inline bool
M_INLINE bool
m_ser1al_bin_write_size(FILE *f, const size_t size)
{
bool b;
@@ -88,7 +88,7 @@ m_ser1al_bin_write_size(FILE *f, const size_t size)
* Read size_t in the stream from a compact form to reduce consumption
* (and I/O bandwidth)
*/
static inline bool
M_INLINE bool
m_ser1al_bin_read_size(FILE *f, size_t *size)
{
int c;
@@ -111,7 +111,7 @@ m_ser1al_bin_read_size(FILE *f, size_t *size)
/* Write the boolean 'data' into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_write_boolean(m_serial_write_t serial, const bool data)
{
FILE *f = (FILE *)serial->data[0].p;
@@ -121,69 +121,54 @@ m_ser1al_bin_write_boolean(m_serial_write_t serial, const bool data)
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_write_integer(m_serial_write_t serial,const long long data, const size_t size_of_type)
{
int8_t i8;
int16_t i16;
int32_t i32;
int64_t i64;
size_t n;
FILE *f = (FILE *)serial->data[0].p;
switch (size_of_type) {
case 1:
i8 = (int8_t) data;
if (size_of_type == 1) {
int8_t i8 = (int8_t) data;
n = fwrite (M_ASSIGN_CAST(const void*, &i8), sizeof i8, 1, f);
break;
case 2:
i16 = (int16_t) data;
} else if (size_of_type == 2) {
int16_t i16 = (int16_t) data;
n = fwrite (M_ASSIGN_CAST(const void*, &i16), sizeof i16, 1, f);
break;
case 4:
i32 = (int32_t) data;
} else if (size_of_type == 4) {
int32_t i32 = (int32_t) data;
n = fwrite (M_ASSIGN_CAST(const void*, &i32), sizeof i32, 1, f);
break;
case 8:
i64 = (int64_t) data;
} else {
M_ASSERT(size_of_type == 8);
int64_t i64 = (int64_t) data;
n = fwrite (M_ASSIGN_CAST(const void*, &i64), sizeof i64, 1, f);
break;
default:
M_ASSERT_INIT(false, "an integer of suitable size (8/16/32/64)");
break;
}
return n == 1 ? M_SERIAL_OK_DONE : m_core_serial_fail();
}
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_write_float(m_serial_write_t serial, const long double data, const size_t size_of_type)
{
float f1;
double f2;
long double f3;
size_t n;
FILE *f = (FILE *)serial->data[0].p;
if (size_of_type == sizeof f1) {
f1 = (float) data;
if (size_of_type == sizeof (float) ) {
float f1 = (float) data;
n = fwrite (M_ASSIGN_CAST(const void*, &f1), sizeof f1, 1, f);
} else if (size_of_type == sizeof f2) {
f2 = (double) data;
} else if (size_of_type == sizeof (double) ) {
double f2 = (double) data;
n = fwrite (M_ASSIGN_CAST(const void*, &f2), sizeof f2, 1, f);
} else if (size_of_type == sizeof f3) {
f3 = (long double) data;
n = fwrite (M_ASSIGN_CAST(const void*, &f3), sizeof f3, 1, f);
} else {
M_ASSERT_INIT(false, "a float of suitable size");
M_ASSERT(size_of_type == sizeof (long double) );
long double f3 = (long double) data;
n = fwrite (M_ASSIGN_CAST(const void*, &f3), sizeof f3, 1, f);
}
return n == 1 ? M_SERIAL_OK_DONE : m_core_serial_fail();
}
/* Write the null-terminated string 'data'into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_write_string(m_serial_write_t serial, const char data[], size_t length)
{
M_ASSERT_SLOW(length == strlen(data) );
@@ -203,50 +188,39 @@ m_ser1al_bin_write_string(m_serial_write_t serial, const char data[], size_t len
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_write_array_start(m_serial_local_t local, m_serial_write_t serial, const size_t number_of_elements)
{
(void) local; //Unused
if (number_of_elements == (size_t)-1) return M_SERIAL_FAIL_RETRY;
FILE *f = (FILE *)serial->data[0].p;
size_t n = fwrite (M_ASSIGN_CAST(const void*, &number_of_elements), sizeof number_of_elements, 1, f);
local->data[0].b = (number_of_elements == 0);
return n == 1 ? M_SERIAL_OK_CONTINUE : m_core_serial_fail();
}
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_write_array_next(m_serial_local_t local, m_serial_write_t serial)
{
FILE *f = (FILE *)serial->data[0].p;
// Need separator if we don't know the real size
if (local->data[0].b) {
size_t n = 0xABCDEF;
n = fwrite (M_ASSIGN_CAST(const void*, &n), sizeof n, 1, f);
return n == 1 ? M_SERIAL_OK_CONTINUE : m_core_serial_fail();
} else {
return M_SERIAL_OK_CONTINUE;
}
(void) local; // Unused
(void) serial; // Unused
return M_SERIAL_OK_CONTINUE;
}
/* End the writing of an array into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_write_array_end(m_serial_local_t local, m_serial_write_t serial)
{
FILE *f = (FILE *)serial->data[0].p;
// Need mark if we don't know the real size
if (local->data[0].b) {
size_t n = 0x12345678;
n = fwrite (M_ASSIGN_CAST(const void*, &n), sizeof n, 1, f);
return n == 1 ? M_SERIAL_OK_CONTINUE : m_core_serial_fail();
} else {
return M_SERIAL_OK_CONTINUE;
}
(void) local; // Unused
(void) serial; // Unused
return M_SERIAL_OK_CONTINUE;
}
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_write_map_value(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -258,7 +232,7 @@ m_ser1al_bin_write_map_value(m_serial_local_t local, m_serial_write_t 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_write_tuple_start(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -268,7 +242,7 @@ m_ser1al_bin_write_tuple_start(m_serial_local_t local, m_serial_write_t serial)
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_write_tuple_id(m_serial_local_t local, m_serial_write_t serial, const char *const field_name[], const int max, const int index)
{
(void) local; // argument not used
@@ -281,7 +255,7 @@ m_ser1al_bin_write_tuple_id(m_serial_local_t local, m_serial_write_t serial, con
/* End the write of a tuple into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_write_tuple_end(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -294,7 +268,7 @@ m_ser1al_bin_write_tuple_end(m_serial_local_t local, m_serial_write_t serial)
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_write_variant_start(m_serial_local_t local, m_serial_write_t serial, const char *const field_name[], const int max, const int index)
{
(void) field_name;
@@ -307,7 +281,7 @@ m_ser1al_bin_write_variant_start(m_serial_local_t local, m_serial_write_t serial
/* End Writing a variant into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_write_variant_end(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -335,13 +309,13 @@ static const m_serial_write_interface_t m_ser1al_bin_write_interface = {
m_ser1al_bin_write_variant_end
};
static inline void m_serial_bin_write_init(m_serial_write_t serial, FILE *f)
M_INLINE void m_serial_bin_write_init(m_serial_write_t serial, FILE *f)
{
serial->m_interface = &m_ser1al_bin_write_interface;
serial->data[0].p = M_ASSIGN_CAST(void*, f);
}
static inline void m_serial_bin_write_clear(m_serial_write_t serial)
M_INLINE void m_serial_bin_write_clear(m_serial_write_t serial)
{
(void) serial; // Nothing to do
}
@@ -363,7 +337,7 @@ typedef m_serial_write_t m_serial_bin_write_t;
/* Read from the stream 'serial' a boolean.
Set '*b' with the boolean value if succeeds
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_read_boolean(m_serial_read_t serial, bool *b){
FILE *f = (FILE*) serial->data[0].p;
size_t n = fread (M_ASSIGN_CAST(void*, b), sizeof (bool), 1, f);
@@ -373,7 +347,7 @@ m_ser1al_bin_read_boolean(m_serial_read_t serial, bool *b){
/* Read from the stream 'serial' an integer that can be represented with 'size_of_type' bytes.
Set '*i' with the integer value if succeeds
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_read_integer(m_serial_read_t serial, long long *i, const size_t size_of_type){
int8_t i8;
int16_t i16;
@@ -381,26 +355,19 @@ m_ser1al_bin_read_integer(m_serial_read_t serial, long long *i, const size_t siz
int64_t i64;
size_t n;
FILE *f = (FILE *)serial->data[0].p;
switch (size_of_type) {
case 1:
if (size_of_type == 1) {
n = fread (M_ASSIGN_CAST(void*, &i8), sizeof i8, 1, f);
*i = i8;
break;
case 2:
} else if (size_of_type == 2) {
n = fread (M_ASSIGN_CAST(void*, &i16), sizeof i16, 1, f);
*i = i16;
break;
case 4:
} else if (size_of_type == 4) {
n = fread (M_ASSIGN_CAST(void*, &i32), sizeof i32, 1, f);
*i = i32;
break;
case 8:
} else {
M_ASSERT(size_of_type == 8);
n = fread (M_ASSIGN_CAST(void*, &i64), sizeof i64, 1, f);
*i = i64;
break;
default:
M_ASSERT_INIT(false, "an integer of suitable size");
break;
}
return n == 1 ? M_SERIAL_OK_DONE : m_core_serial_fail();
}
@@ -408,7 +375,7 @@ m_ser1al_bin_read_integer(m_serial_read_t serial, long long *i, const size_t siz
/* Read from the stream 'serial' a float that can be represented with 'size_of_type' bytes.
Set '*r' with the boolean value if succeeds
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_read_float(m_serial_read_t serial, long double *r, const size_t size_of_type){
float f1;
double f2;
@@ -421,11 +388,10 @@ m_ser1al_bin_read_float(m_serial_read_t serial, long double *r, const size_t siz
} else if (size_of_type == sizeof f2) {
n = fread (M_ASSIGN_CAST(void*, &f2), sizeof f2, 1, f);
*r = f2;
} else if (size_of_type == sizeof f3) {
} else {
M_ASSERT(size_of_type == sizeof f3);
n = fread (M_ASSIGN_CAST(void*, &f3), sizeof f3, 1, f);
*r = f3;
} else {
M_ASSERT_INIT(false, "a float of suitable size");
}
return n == 1 ? M_SERIAL_OK_DONE : m_core_serial_fail();
}
@@ -433,7 +399,7 @@ m_ser1al_bin_read_float(m_serial_read_t serial, long double *r, const size_t siz
/* Read from the stream 'serial' a string.
Set 's' with the string if succeeds
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_read_string(m_serial_read_t serial, struct string_s *s){
FILE *f = (FILE*) serial->data[0].p;
M_ASSERT(f != NULL && s != NULL);
@@ -458,53 +424,33 @@ m_ser1al_bin_read_string(m_serial_read_t serial, struct string_s *s){
Return M_SERIAL_OK_CONTINUE if it succeeds and the array continue,
M_SERIAL_OK_DONE if it succeeds and the array ends (the array is empty),
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_read_array_start(m_serial_local_t local, m_serial_read_t serial, size_t *num)
{
FILE *f = (FILE*) serial->data[0].p;
size_t n = fread (M_ASSIGN_CAST(void*, num), sizeof *num, 1, f);
if (n != 1)
return m_core_serial_fail();
local->data[0].b = (*num == 0);
local->data[1].s = *num;
if (local->data[0].b) {
// Size not know ==> use of marker in the stream.
size_t p;
n = fread (M_ASSIGN_CAST(void*, &p), sizeof p, 1, f);
if (n != 1)
return m_core_serial_fail();
return p == 0xABCDEF ? M_SERIAL_OK_CONTINUE : p == 0x12345678 ? M_SERIAL_OK_DONE : m_core_serial_fail();
}
return M_SERIAL_OK_CONTINUE;
return (n != 1) ? m_core_serial_fail() : (local->data[1].s == 0) ? M_SERIAL_OK_DONE : M_SERIAL_OK_CONTINUE;
}
/* Continue reading from the stream 'serial' an array.
Return M_SERIAL_OK_CONTINUE if it succeeds and the array continue,
M_SERIAL_OK_DONE if it succeeds and the array ends,
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_read_array_next(m_serial_local_t local, m_serial_read_t serial)
{
FILE *f = (FILE*) serial->data[0].p;
if (local->data[0].b) {
// Size not know ==> use of marker in the stream.
size_t p, n;
n = fread (M_ASSIGN_CAST(void*, &p), sizeof p, 1, f);
if (n != 1)
return m_core_serial_fail();
return p == 0xABCDEF ? M_SERIAL_OK_CONTINUE : p == 0x12345678 ? M_SERIAL_OK_DONE : m_core_serial_fail();
} else {
M_ASSERT(local->data[1].s > 0);
local->data[1].s --;
return local->data[1].s == 0 ? M_SERIAL_OK_DONE : M_SERIAL_OK_CONTINUE;
}
(void) serial; // Unused
M_ASSERT(local->data[1].s > 0);
local->data[1].s --;
return local->data[1].s == 0 ? M_SERIAL_OK_DONE : M_SERIAL_OK_CONTINUE;
}
/* Continue reading from the stream 'serial' the value separator
Return M_SERIAL_OK_CONTINUE if it succeeds and the map continue,
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_read_map_value(m_serial_local_t local, m_serial_read_t serial)
{
(void) local; // argument not used
@@ -515,7 +461,7 @@ m_ser1al_bin_read_map_value(m_serial_local_t local, m_serial_read_t serial)
/* Start reading a tuple from the stream 'serial'.
Return M_SERIAL_OK_CONTINUE if it succeeds and the tuple continues,
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_read_tuple_start(m_serial_local_t local, m_serial_read_t serial)
{
(void) serial;
@@ -529,7 +475,7 @@ m_ser1al_bin_read_tuple_start(m_serial_local_t local, m_serial_read_t serial)
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_read_tuple_id(m_serial_local_t local, m_serial_read_t serial, const char *const field_name [], const int max, int *id)
{
(void) serial;
@@ -546,7 +492,7 @@ m_ser1al_bin_read_tuple_id(m_serial_local_t local, m_serial_read_t serial, const
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_read_variant_start(m_serial_local_t local, m_serial_read_t serial, const char *const field_name[], const int max, int*id)
{
(void) field_name;
@@ -560,7 +506,7 @@ m_ser1al_bin_read_variant_start(m_serial_local_t local, m_serial_read_t serial,
/* End reading a variant from the stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds and the variant ends,
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_bin_read_variant_end(m_serial_local_t local, m_serial_read_t serial)
{
(void) local; // argument not used
@@ -584,13 +530,13 @@ static const m_serial_read_interface_t m_ser1al_bin_read_interface = {
m_ser1al_bin_read_variant_end
};
static inline void m_serial_bin_read_init(m_serial_read_t serial, FILE *f)
M_INLINE void m_serial_bin_read_init(m_serial_read_t serial, FILE *f)
{
serial->m_interface = &m_ser1al_bin_read_interface;
serial->data[0].p = M_ASSIGN_CAST(void*, f);
}
static inline void m_serial_bin_read_clear(m_serial_read_t serial)
M_INLINE void m_serial_bin_read_clear(m_serial_read_t serial)
{
(void) serial; // Nothing to do
}
+71 -71
View File
@@ -36,7 +36,7 @@ M_BEGIN_PROTECTED_CODE
/* Write the boolean 'data' into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_boolean(m_serial_write_t serial, const bool data)
{
FILE *f = (FILE *)serial->data[0].p;
@@ -46,7 +46,7 @@ m_ser1al_json_write_boolean(m_serial_write_t serial, const bool data)
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_integer(m_serial_write_t serial,const long long data, const size_t size_of_type)
{
(void) size_of_type; // Ignored
@@ -57,7 +57,7 @@ m_ser1al_json_write_integer(m_serial_write_t serial,const long long data, const
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_float(m_serial_write_t serial, const long double data, const size_t size_of_type)
{
(void) size_of_type; // Ignored
@@ -68,7 +68,7 @@ m_ser1al_json_write_float(m_serial_write_t serial, const long double data, const
/* Write the null-terminated string 'data'into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_string(m_serial_write_t serial, const char data[], size_t length)
{
M_ASSERT_SLOW(length == strlen(data) );
@@ -81,7 +81,7 @@ m_ser1al_json_write_string(m_serial_write_t serial, const char data[], size_t le
v2->u.heap.alloc = length + 1;
v2->ptr = (char*)ptr;
m_string_out_str(f, v2);
return M_SERIAL_OK_DONE;
return M_UNLIKELY(ferror(f)) ? m_core_serial_fail() : M_SERIAL_OK_DONE;
}
/* Start writing an array of 'number_of_elements' objects into the serial stream 'serial'.
@@ -90,7 +90,7 @@ m_ser1al_json_write_string(m_serial_write_t serial, const char data[], size_t le
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_array_start(m_serial_local_t local, m_serial_write_t serial, const size_t number_of_elements)
{
(void) local; // argument not used
@@ -102,7 +102,7 @@ m_ser1al_json_write_array_start(m_serial_local_t local, m_serial_write_t serial,
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_array_next(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -113,7 +113,7 @@ m_ser1al_json_write_array_next(m_serial_local_t local, m_serial_write_t serial)
/* End the writing of an array into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_array_end(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -128,7 +128,7 @@ m_ser1al_json_write_array_end(m_serial_local_t local, m_serial_write_t serial)
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_map_start(m_serial_local_t local, m_serial_write_t serial, const size_t number_of_elements)
{
(void) local; // argument not used
@@ -140,7 +140,7 @@ m_ser1al_json_write_map_start(m_serial_local_t local, m_serial_write_t serial, c
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_map_value(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -151,7 +151,7 @@ m_ser1al_json_write_map_value(m_serial_local_t local, m_serial_write_t serial)
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_map_next(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -162,7 +162,7 @@ m_ser1al_json_write_map_next(m_serial_local_t local, m_serial_write_t serial)
/* End the writing of a map into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_map_end(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -175,7 +175,7 @@ m_ser1al_json_write_map_end(m_serial_local_t local, m_serial_write_t 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_tuple_start(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -186,7 +186,7 @@ m_ser1al_json_write_tuple_start(m_serial_local_t local, m_serial_write_t serial)
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_tuple_id(m_serial_local_t local, m_serial_write_t serial, const char *const field_name[], const int max, const int index)
{
(void) local; // argument not used
@@ -198,7 +198,7 @@ m_ser1al_json_write_tuple_id(m_serial_local_t local, m_serial_write_t serial, co
/* End the write of a tuple into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_tuple_end(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -212,7 +212,7 @@ m_ser1al_json_write_tuple_end(m_serial_local_t local, m_serial_write_t serial)
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_variant_start(m_serial_local_t local, m_serial_write_t serial, const char *const field_name[], const int max, const int index)
{
(void) local; // argument not used
@@ -231,7 +231,7 @@ m_ser1al_json_write_variant_start(m_serial_local_t local, m_serial_write_t seria
/* End Writing a variant into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_write_variant_end(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -262,14 +262,14 @@ static const m_serial_write_interface_t m_ser1al_json_write_interface = {
};
/* Initialize the JSON serial object for writing any object to JSON format in the given FILE */
static inline void m_serial_json_write_init(m_serial_write_t serial, FILE *f)
M_INLINE void m_serial_json_write_init(m_serial_write_t serial, FILE *f)
{
serial->m_interface = &m_ser1al_json_write_interface;
serial->data[0].p = M_ASSIGN_CAST(void*, f);
}
/* CLear the JSON serial object for writing*/
static inline void m_serial_json_write_clear(m_serial_write_t serial)
M_INLINE void m_serial_json_write_clear(m_serial_write_t serial)
{
(void) serial; // Nothing to do
}
@@ -288,7 +288,7 @@ typedef m_serial_write_t m_serial_json_write_t;
/********************************************************************************/
/* Helper function to skip a space */
static inline int
M_INLINE int
m_ser1al_json_read_skip (FILE *f)
{
int c;
@@ -302,7 +302,7 @@ m_ser1al_json_read_skip (FILE *f)
/* Read from the stream 'serial' a boolean.
Set '*b' with the boolean value if succeeds
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_read_boolean(m_serial_read_t serial, bool *b){
FILE *f = (FILE*) serial->data[0].p;
int c = m_ser1al_json_read_skip(f);
@@ -334,7 +334,7 @@ m_ser1al_json_read_boolean(m_serial_read_t serial, bool *b){
/* Read from the stream 'serial' an integer that can be represented with 'size_of_type' bytes.
Set '*i' with the integer value if succeeds
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_read_integer(m_serial_read_t serial, long long *i, const size_t size_of_type){
(void) size_of_type; // Ignored
FILE *f = (FILE*) serial->data[0].p;
@@ -344,7 +344,7 @@ m_ser1al_json_read_integer(m_serial_read_t serial, long long *i, const size_t si
/* Read from the stream 'serial' a float that can be represented with 'size_of_type' bytes.
Set '*r' with the boolean value if succeeds
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_read_float(m_serial_read_t serial, long double *r, const size_t size_of_type){
(void) size_of_type; // Ignored
FILE *f = (FILE*) serial->data[0].p;
@@ -354,7 +354,7 @@ m_ser1al_json_read_float(m_serial_read_t serial, long double *r, const size_t si
/* Read from the stream 'serial' a string.
Set 's' with the string if succeeds
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_read_string(m_serial_read_t serial, struct m_string_s *s){
FILE *f = (FILE*) serial->data[0].p;
int n = m_core_fscanf(f, " "); // Skip any leading spaces.
@@ -369,7 +369,7 @@ m_ser1al_json_read_string(m_serial_read_t serial, struct m_string_s *s){
Return M_SERIAL_OK_CONTINUE if it succeeds and the array continue,
M_SERIAL_OK_DONE if it succeeds and the array ends (the array is empty),
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_read_array_start(m_serial_local_t local, m_serial_read_t serial, size_t *num)
{
(void) local; // argument not used
@@ -387,7 +387,7 @@ m_ser1al_json_read_array_start(m_serial_local_t local, m_serial_read_t serial, s
Return M_SERIAL_OK_CONTINUE if it succeeds and the array continue,
M_SERIAL_OK_DONE if it succeeds and the array ends,
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_read_array_next(m_serial_local_t local, m_serial_read_t serial)
{
(void) local; // argument not used
@@ -405,7 +405,7 @@ m_ser1al_json_read_array_next(m_serial_local_t local, m_serial_read_t serial)
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_core_serial_fail() otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_read_map_start(m_serial_local_t local, m_serial_read_t serial, size_t *num)
{
(void) local; // argument not used
@@ -422,7 +422,7 @@ m_ser1al_json_read_map_start(m_serial_local_t local, m_serial_read_t serial, siz
/* Continue reading from the stream 'serial' the value separator
Return M_SERIAL_OK_CONTINUE if it succeeds and the map continue,
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_read_map_value(m_serial_local_t local, m_serial_read_t serial)
{
(void) local; // argument not used
@@ -437,7 +437,7 @@ m_ser1al_json_read_map_value(m_serial_local_t local, m_serial_read_t serial)
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_read_map_next(m_serial_local_t local, m_serial_read_t serial)
{
(void) local; // argument not used
@@ -451,7 +451,7 @@ m_ser1al_json_read_map_next(m_serial_local_t local, m_serial_read_t serial)
/* Start reading a tuple from the stream 'serial'.
Return M_SERIAL_OK_CONTINUE if it succeeds and the tuple continues,
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_read_tuple_start(m_serial_local_t local, m_serial_read_t serial)
{
(void) local; // argument not used
@@ -468,7 +468,7 @@ m_ser1al_json_read_tuple_start(m_serial_local_t local, m_serial_read_t serial)
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_read_tuple_id(m_serial_local_t local, m_serial_read_t serial, const char *const field_name [], const int max, int *id)
{
(void) local; // argument not used
@@ -507,7 +507,7 @@ m_ser1al_json_read_tuple_id(m_serial_local_t local, m_serial_read_t serial, cons
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_read_variant_start(m_serial_local_t local, m_serial_read_t serial, const char *const field_name[], const int max, int*id)
{
(void) local; // argument not used
@@ -542,7 +542,7 @@ m_ser1al_json_read_variant_start(m_serial_local_t local, m_serial_read_t serial,
/* End reading a variant from the stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds and the variant ends,
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_json_read_variant_end(m_serial_local_t local, m_serial_read_t serial)
{
(void) local; // argument not used
@@ -570,14 +570,14 @@ static const m_serial_read_interface_t m_ser1al_json_read_interface = {
};
/* Initialize the JSON serial object for reading any object from JSON format in the given FILE */
static inline void m_serial_json_read_init(m_serial_read_t serial, FILE *f)
M_INLINE void m_serial_json_read_init(m_serial_read_t serial, FILE *f)
{
serial->m_interface = &m_ser1al_json_read_interface;
serial->data[0].p = M_ASSIGN_CAST(void*, f);
}
/* Clear the JSON serial object for reading from the FILE */
static inline void m_serial_json_read_clear(m_serial_read_t serial)
M_INLINE void m_serial_json_read_clear(m_serial_read_t serial)
{
(void) serial; // Nothing to do
}
@@ -597,7 +597,7 @@ typedef m_serial_read_t m_serial_json_read_t;
/* Write the boolean 'data' into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_boolean(m_serial_write_t serial, const bool data)
{
struct m_string_s *f = (struct m_string_s *)serial->data[0].p;
@@ -607,7 +607,7 @@ m_ser1al_str_json_write_boolean(m_serial_write_t serial, const bool data)
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_integer(m_serial_write_t serial,const long long data, const size_t size_of_type)
{
(void) size_of_type; // Ignored
@@ -618,7 +618,7 @@ m_ser1al_str_json_write_integer(m_serial_write_t serial,const long long data, co
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_float(m_serial_write_t serial, const long double data, const size_t size_of_type)
{
(void) size_of_type; // Ignored
@@ -629,7 +629,7 @@ m_ser1al_str_json_write_float(m_serial_write_t serial, const long double data, c
/* Write the null-terminated string 'data'into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_string(m_serial_write_t serial, const char data[], size_t length)
{
M_ASSERT_SLOW(length == strlen(data) );
@@ -651,7 +651,7 @@ m_ser1al_str_json_write_string(m_serial_write_t serial, const char data[], size_
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_array_start(m_serial_local_t local, m_serial_write_t serial, const size_t number_of_elements)
{
(void) local; // argument not used
@@ -663,7 +663,7 @@ m_ser1al_str_json_write_array_start(m_serial_local_t local, m_serial_write_t ser
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_array_next(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -674,7 +674,7 @@ m_ser1al_str_json_write_array_next(m_serial_local_t local, m_serial_write_t seri
/* End the writing of an array into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_array_end(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -689,7 +689,7 @@ m_ser1al_str_json_write_array_end(m_serial_local_t local, m_serial_write_t seria
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_map_start(m_serial_local_t local, m_serial_write_t serial, const size_t number_of_elements)
{
(void) local; // argument not used
@@ -701,7 +701,7 @@ m_ser1al_str_json_write_map_start(m_serial_local_t local, m_serial_write_t seria
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_map_value(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -712,7 +712,7 @@ m_ser1al_str_json_write_map_value(m_serial_local_t local, m_serial_write_t seria
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_map_next(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -723,7 +723,7 @@ m_ser1al_str_json_write_map_next(m_serial_local_t local, m_serial_write_t serial
/* End the writing of a map into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_map_end(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -736,7 +736,7 @@ m_ser1al_str_json_write_map_end(m_serial_local_t local, m_serial_write_t 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_tuple_start(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -747,7 +747,7 @@ m_ser1al_str_json_write_tuple_start(m_serial_local_t local, m_serial_write_t ser
/* 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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_tuple_id(m_serial_local_t local, m_serial_write_t serial, const char *const field_name[], const int max, const int index)
{
(void) local; // argument not used
@@ -759,7 +759,7 @@ m_ser1al_str_json_write_tuple_id(m_serial_local_t local, m_serial_write_t serial
/* End the write of a tuple into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_tuple_end(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -773,7 +773,7 @@ m_ser1al_str_json_write_tuple_end(m_serial_local_t local, m_serial_write_t seria
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_variant_start(m_serial_local_t local, m_serial_write_t serial, const char *const field_name[], const int max, const int index)
{
(void) local; // argument not used
@@ -792,7 +792,7 @@ m_ser1al_str_json_write_variant_start(m_serial_local_t local, m_serial_write_t s
/* End Writing a variant into the serial stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_write_variant_end(m_serial_local_t local, m_serial_write_t serial)
{
(void) local; // argument not used
@@ -822,14 +822,14 @@ static const m_serial_write_interface_t m_ser1al_str_json_write_interface = {
};
/* Initialize the JSON serial object for writing any object to JSON format in the given FILE */
static inline void m_serial_str_json_write_init(m_serial_write_t serial, m_string_t s)
M_INLINE void m_serial_str_json_write_init(m_serial_write_t serial, m_string_t s)
{
serial->m_interface = &m_ser1al_str_json_write_interface;
serial->data[0].p = M_ASSIGN_CAST(struct m_string_s *, s);
}
/* CLear the JSON serial object for writing*/
static inline void m_serial_str_json_write_clear(m_serial_write_t serial)
M_INLINE void m_serial_str_json_write_clear(m_serial_write_t serial)
{
(void) serial; // Nothing to do
}
@@ -847,7 +847,7 @@ typedef m_serial_write_t m_serial_str_json_write_t;
/********************************************************************************/
/* Helper function to read a character and advance the stream */
static inline char
M_INLINE char
m_ser1al_str_json_getc(const char **p)
{
char c = **p;
@@ -857,7 +857,7 @@ m_ser1al_str_json_getc(const char **p)
}
/* Helper function to skip space(s) */
static inline void
M_INLINE void
m_ser1al_str_json_skip (const char **p)
{
while (isspace (**p)) {
@@ -866,7 +866,7 @@ m_ser1al_str_json_skip (const char **p)
}
/* Helper function to read a string with characters not present in reject */
static inline void
M_INLINE void
m_ser1al_str_json_gets(size_t alloc, char field[], const char reject[], const char **s)
{
M_ASSERT (alloc > 0);
@@ -881,7 +881,7 @@ m_ser1al_str_json_gets(size_t alloc, char field[], const char reject[], const ch
/* Read from the stream 'serial' a boolean.
Set '*b' with the boolean value if succeeds
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_read_boolean(m_serial_read_t serial, bool *b){
const char **f = &serial->data[0].cstr;
m_ser1al_str_json_skip(f);
@@ -914,7 +914,7 @@ m_ser1al_str_json_read_boolean(m_serial_read_t serial, bool *b){
/* Read from the stream 'serial' an integer that can be represented with 'size_of_type' bytes.
Set '*i' with the integer value if succeeds
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_read_integer(m_serial_read_t serial, long long *i, const size_t size_of_type){
(void) size_of_type; // Ignored
const char **f = &serial->data[0].cstr;
@@ -928,7 +928,7 @@ m_ser1al_str_json_read_integer(m_serial_read_t serial, long long *i, const size_
/* Read from the stream 'serial' a float that can be represented with 'size_of_type' bytes.
Set '*r' with the boolean value if succeeds
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_read_float(m_serial_read_t serial, long double *r, const size_t size_of_type){
(void) size_of_type; // Ignored
const char **f = &serial->data[0].cstr;
@@ -942,7 +942,7 @@ m_ser1al_str_json_read_float(m_serial_read_t serial, long double *r, const size_
/* Read from the stream 'serial' a string.
Set 's' with the string if succeeds
Return M_SERIAL_OK_DONE if it succeeds, M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_read_string(m_serial_read_t serial, struct m_string_s *s){
const char **f = &serial->data[0].cstr;
m_ser1al_str_json_skip(f);
@@ -959,7 +959,7 @@ m_ser1al_str_json_read_string(m_serial_read_t serial, struct m_string_s *s){
Return M_SERIAL_OK_CONTINUE if it succeeds and the array continue,
M_SERIAL_OK_DONE if it succeeds and the array ends (the array is empty),
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_read_array_start(m_serial_local_t local, m_serial_read_t serial, size_t *num)
{
(void) local; // argument not used
@@ -984,7 +984,7 @@ m_ser1al_str_json_read_array_start(m_serial_local_t local, m_serial_read_t seria
Return M_SERIAL_OK_CONTINUE if it succeeds and the array continue,
M_SERIAL_OK_DONE if it succeeds and the array ends,
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_read_array_next(m_serial_local_t local, m_serial_read_t serial)
{
(void) local; // argument not used
@@ -1001,7 +1001,7 @@ m_ser1al_str_json_read_array_next(m_serial_local_t local, m_serial_read_t serial
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_core_serial_fail() otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_read_map_start(m_serial_local_t local, m_serial_read_t serial, size_t *num)
{
(void) local; // argument not used
@@ -1025,7 +1025,7 @@ m_ser1al_str_json_read_map_start(m_serial_local_t local, m_serial_read_t serial,
/* Continue reading from the stream 'serial' the value separator
Return M_SERIAL_OK_CONTINUE if it succeeds and the map continue,
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_read_map_value(m_serial_local_t local, m_serial_read_t serial)
{
(void) local; // argument not used
@@ -1039,7 +1039,7 @@ m_ser1al_str_json_read_map_value(m_serial_local_t local, m_serial_read_t serial)
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_read_map_next(m_serial_local_t local, m_serial_read_t serial)
{
(void) local; // argument not used
@@ -1052,7 +1052,7 @@ m_ser1al_str_json_read_map_next(m_serial_local_t local, m_serial_read_t serial)
/* Start reading a tuple from the stream 'serial'.
Return M_SERIAL_OK_CONTINUE if it succeeds and the tuple continues,
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_read_tuple_start(m_serial_local_t local, m_serial_read_t serial)
{
(void) local; // argument not used
@@ -1068,7 +1068,7 @@ m_ser1al_str_json_read_tuple_start(m_serial_local_t local, m_serial_read_t seria
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_read_tuple_id(m_serial_local_t local, m_serial_read_t serial, const char *const field_name [], const int max, int *id)
{
(void) local; // argument not used
@@ -1109,7 +1109,7 @@ m_ser1al_str_json_read_tuple_id(m_serial_local_t local, m_serial_read_t serial,
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 */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_read_variant_start(m_serial_local_t local, m_serial_read_t serial, const char *const field_name[], const int max, int*id)
{
(void) local; // argument not used
@@ -1146,7 +1146,7 @@ m_ser1al_str_json_read_variant_start(m_serial_local_t local, m_serial_read_t ser
/* End reading a variant from the stream 'serial'.
Return M_SERIAL_OK_DONE if it succeeds and the variant ends,
M_SERIAL_FAIL otherwise */
static inline m_serial_return_code_t
M_INLINE m_serial_return_code_t
m_ser1al_str_json_read_variant_end(m_serial_local_t local, m_serial_read_t serial)
{
(void) local; // argument not used
@@ -1173,14 +1173,14 @@ static const m_serial_read_interface_t m_ser1al_str_json_read_interface = {
};
/* Initialize the JSON serial object for reading any object from JSON format in the given const string */
static inline void m_serial_str_json_read_init(m_serial_read_t serial, const char str[])
M_INLINE void m_serial_str_json_read_init(m_serial_read_t serial, const char str[])
{
serial->m_interface = &m_ser1al_str_json_read_interface;
serial->data[0].cstr = str;
}
/* Clear the JSON serial object for reading from the FILE */
static inline const char *m_serial_str_json_read_clear(m_serial_read_t serial)
M_INLINE const char *m_serial_str_json_read_clear(m_serial_read_t serial)
{
// Nothing to clear. Return pointer to the last data parsed.
return serial->data[0].cstr;
+26 -29
View File
@@ -119,9 +119,6 @@ M_BEGIN_PROTECTED_CODE
SWAP(M_F(name, _swap)) \
,NAME(name) \
,TYPE(M_F(name, _ct)) \
,M_IF_METHOD(NEW, oplist)(NEW(M_GET_NEW oplist),) \
,M_IF_METHOD(REALLOC, oplist)(REALLOC(M_GET_REALLOC oplist),) \
,M_IF_METHOD(DEL, oplist)(DEL(M_GET_DEL oplist),) \
)
// OPLIST to handle a counter of atomic type
@@ -139,10 +136,10 @@ M_BEGIN_PROTECTED_CODE
IT_CREF(m_shar3d_integer_cref))
/* Atomic like interface for basic integers */
static inline void m_shar3d_integer_init_set(int *p, int val) { *p = val; }
static inline int m_shar3d_integer_add(int *p, int val) { int r = *p; *p += val; return r; }
static inline int m_shar3d_integer_sub(int *p, int val) { int r = *p; *p -= val; return r; }
static inline int m_shar3d_integer_cref(int *p) { return *p; }
M_INLINE void m_shar3d_integer_init_set(int *p, int val) { *p = val; }
M_INLINE int m_shar3d_integer_add(int *p, int val) { int r = *p; *p += val; return r; }
M_INLINE int m_shar3d_integer_sub(int *p, int val) { int r = *p; *p -= val; return r; }
M_INLINE int m_shar3d_integer_cref(int *p) { return *p; }
/********************************** INTERNAL *********************************/
@@ -192,13 +189,13 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
/* Define the core functions */
#define M_SHAR3D_PTR_DEF_CORE(name, type, oplist, cpt_oplist, shared_t) \
\
static inline void \
M_INLINE void \
M_F(name, _init)(shared_t shared) \
{ \
*shared = NULL; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init2)(shared_t shared, type *data) \
{ \
M_ASSERT (shared != NULL); \
@@ -221,7 +218,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
} \
\
M_IF_METHOD(INIT, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _init_new)(shared_t shared) \
{ \
/* NOTE: Alloc 1 struct with both structures. */ \
@@ -242,14 +239,14 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
} \
, /* No INIT */ ) \
\
static inline bool \
M_INLINE bool \
M_F(name, _NULL_p)(const shared_t shared) \
{ \
M_SHAR3D_CONTRACT(shared, cpt_oplist); \
return *shared == NULL; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_set)(shared_t dest, \
const shared_t shared) \
{ \
@@ -263,7 +260,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
M_SHAR3D_CONTRACT(dest, cpt_oplist); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(shared_t dest) \
{ \
M_SHAR3D_CONTRACT(dest, cpt_oplist); \
@@ -284,14 +281,14 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
M_SHAR3D_CONTRACT(dest, cpt_oplist); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _reset)(shared_t dest) \
{ \
/* NOTE: Clear will also set dest to NULL */ \
M_F(name, _clear)(dest); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _set)(shared_t dest, \
const shared_t shared) \
{ \
@@ -301,7 +298,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
M_F(name, _init_set)(dest, shared); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_move)(shared_t dest, \
shared_t shared) \
{ \
@@ -312,7 +309,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
M_SHAR3D_CONTRACT(dest, cpt_oplist); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _move)(shared_t dest, \
shared_t shared) \
{ \
@@ -323,7 +320,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
M_F(name, _init_move)(dest, shared); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _swap)(shared_t p1, \
shared_t p2) \
{ \
@@ -335,7 +332,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
M_SHAR3D_CONTRACT(p2, cpt_oplist); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _equal_p)(const shared_t p1, \
const shared_t p2) \
{ \
@@ -344,7 +341,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
return *p1 == *p2; \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _cref)(const shared_t shared) \
{ \
M_SHAR3D_CONTRACT(shared, cpt_oplist); \
@@ -354,7 +351,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
return M_CONST_CAST (type, data); \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _ref)(shared_t shared) \
{ \
M_SHAR3D_CONTRACT(shared, cpt_oplist); \
@@ -413,7 +410,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
/* Define the core functions */
#define M_SHAR3D_RESOURCE_DEF_CORE(name, type, oplist, shared_t, it_t) \
static inline void \
M_INLINE void \
M_F(name, _init)(shared_t s, size_t n) \
{ \
M_ASSERT(s != NULL); \
@@ -431,7 +428,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
M_SHAR3D_RESOURCE_CONTRACT(s); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(shared_t s) \
{ \
M_SHAR3D_RESOURCE_CONTRACT(s); \
@@ -444,7 +441,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
m_genint_clear(s->core); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it)(it_t it, shared_t s) \
{ \
M_SHAR3D_RESOURCE_CONTRACT(s); \
@@ -458,14 +455,14 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
} \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _end_p)(it_t it) \
{ \
M_ASSERT (it != NULL); \
return it->idx == M_GENINT_ERROR; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _ref)(it_t it) \
{ \
M_ASSERT (it != NULL && it->ref != NULL && it->idx != M_GENINT_ERROR); \
@@ -473,7 +470,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
return &it->ref->buffer[it->idx].x; \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _cref)(it_t it) \
{ \
M_ASSERT (it != NULL && it->ref != NULL && it->idx != M_GENINT_ERROR); \
@@ -481,7 +478,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
return M_CONST_CAST (type, &it->ref->buffer[it->idx].x); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _end)(it_t it, shared_t s) \
{ \
M_SHAR3D_RESOURCE_CONTRACT(s); \
@@ -497,7 +494,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
} \
} \
\
static inline void \
M_INLINE void \
M_F(name, _it_set)(it_t itd, it_t its) \
{ \
M_ASSERT (itd != NULL && its != NULL); \
+33 -33
View File
@@ -197,7 +197,7 @@ M_BEGIN_PROTECTED_CODE
/* Define the core functions */
#define M_SNAPSH0T_SPSC_DEF_CORE(name, type, oplist, snapshot_t) \
\
static inline void \
M_INLINE void \
M_F(name, _init)(snapshot_t snap) \
{ \
M_ASSERT(snap != NULL); \
@@ -208,7 +208,7 @@ M_BEGIN_PROTECTED_CODE
M_SNAPSH0T_SPSC_CONTRACT(snap); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(snapshot_t snap) \
{ \
M_SNAPSH0T_SPSC_CONTRACT(snap); \
@@ -218,7 +218,7 @@ M_BEGIN_PROTECTED_CODE
} \
\
/* const is missing for org due to use of atomic_load of org */ \
static inline void \
M_INLINE void \
M_F(name, _init_set)(snapshot_t snap, snapshot_t org) \
{ \
M_SNAPSH0T_SPSC_CONTRACT(org); \
@@ -231,7 +231,7 @@ M_BEGIN_PROTECTED_CODE
} \
\
/* const is missing for org due to use of atomic_load of org */ \
static inline void \
M_INLINE void \
M_F(name, _set)(snapshot_t snap, snapshot_t org) \
{ \
M_SNAPSH0T_SPSC_CONTRACT(snap); \
@@ -244,7 +244,7 @@ M_BEGIN_PROTECTED_CODE
} \
\
M_IF_METHOD(INIT_MOVE, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _init_move)(snapshot_t snap, snapshot_t org) \
{ \
M_SNAPSH0T_SPSC_CONTRACT(org); \
@@ -259,7 +259,7 @@ M_BEGIN_PROTECTED_CODE
,) /* IF_METHOD (INIT_MOVE) */ \
\
M_IF_METHOD(MOVE, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _move)(snapshot_t snap, \
snapshot_t org) \
{ \
@@ -275,7 +275,7 @@ M_BEGIN_PROTECTED_CODE
} \
,) /* IF_METHOD (MOVE) */ \
\
static inline type * \
M_INLINE type * \
M_F(name, _write)(snapshot_t snap) \
{ \
M_SNAPSH0T_SPSC_CONTRACT(snap); \
@@ -294,7 +294,7 @@ M_BEGIN_PROTECTED_CODE
return &snap->data[M_SNAPSH0T_SPSC_W(nextFlags)].x; \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _read)(snapshot_t snap) \
{ \
M_SNAPSH0T_SPSC_CONTRACT(snap); \
@@ -319,7 +319,7 @@ M_BEGIN_PROTECTED_CODE
} \
\
/* Non const due to use of atomic_load */ \
static inline bool \
M_INLINE bool \
M_F(name, _updated_p)(snapshot_t snap) \
{ \
M_SNAPSH0T_SPSC_CONTRACT(snap); \
@@ -328,7 +328,7 @@ M_BEGIN_PROTECTED_CODE
} \
\
/* Non const due to use of atomic_load */ \
static inline type * \
M_INLINE type * \
M_F(name, _get_write_buffer)(snapshot_t snap) \
{ \
M_SNAPSH0T_SPSC_CONTRACT(snap); \
@@ -337,7 +337,7 @@ M_BEGIN_PROTECTED_CODE
} \
\
/* Non const due to use of atomic_load */ \
static inline type const * \
M_INLINE type const * \
M_F(name, _get_read_buffer)(snapshot_t snap) \
{ \
M_SNAPSH0T_SPSC_CONTRACT(snap); \
@@ -382,7 +382,7 @@ typedef struct m_snapsh0t_mrsw_s {
} while (0)
/* Initialize m_snapsh0t_mrsw_ct for n readers (constructor) */
static inline void
M_INLINE void
m_snapsh0t_mrsw_init(m_snapsh0t_mrsw_ct s, size_t n)
{
M_ASSERT (s != NULL);
@@ -415,7 +415,7 @@ m_snapsh0t_mrsw_init(m_snapsh0t_mrsw_ct s, size_t n)
}
/* Clear m_snapsh0t_mrsw_ct (destructor) */
static inline void
M_INLINE void
m_snapsh0t_mrsw_clear(m_snapsh0t_mrsw_ct s)
{
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
@@ -426,7 +426,7 @@ m_snapsh0t_mrsw_clear(m_snapsh0t_mrsw_ct s)
}
/* Return the current index that is written in the buffer */
static inline unsigned int
M_INLINE unsigned int
m_snapsh0t_mrsw_get_write_idx(m_snapsh0t_mrsw_ct s)
{
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
@@ -434,7 +434,7 @@ m_snapsh0t_mrsw_get_write_idx(m_snapsh0t_mrsw_ct s)
}
/* Return the number of readers */
static inline unsigned int
M_INLINE unsigned int
m_snapsh0t_mrsw_size(m_snapsh0t_mrsw_ct s)
{
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
@@ -443,7 +443,7 @@ m_snapsh0t_mrsw_size(m_snapsh0t_mrsw_ct s)
/* Give the current index that is written to the readers,
and return new available index for the writer thread */
static inline unsigned int
M_INLINE unsigned int
m_snapsh0t_mrsw_write_idx(m_snapsh0t_mrsw_ct s, unsigned int idx)
{
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
@@ -485,7 +485,7 @@ m_snapsh0t_mrsw_write_idx(m_snapsh0t_mrsw_ct s, unsigned int idx)
}
/* Perform a swap of the current write buffer and return a new one */
static inline unsigned int
M_INLINE unsigned int
m_snapsh0t_mrsw_write(m_snapsh0t_mrsw_ct s)
{
s->currentWrite = m_snapsh0t_mrsw_write_idx(s, s->currentWrite);
@@ -494,7 +494,7 @@ m_snapsh0t_mrsw_write(m_snapsh0t_mrsw_ct s)
}
/* Start writing to the write buffer and return its index */
static inline unsigned int
M_INLINE unsigned int
m_snapsh0t_mrsw_write_start(m_snapsh0t_mrsw_ct s)
{
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
@@ -509,7 +509,7 @@ m_snapsh0t_mrsw_write_start(m_snapsh0t_mrsw_ct s)
}
/* End writing to the given write buffer */
static inline void
M_INLINE void
m_snapsh0t_mrsw_write_end(m_snapsh0t_mrsw_ct s, unsigned int idx)
{
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
@@ -531,7 +531,7 @@ m_snapsh0t_mrsw_write_end(m_snapsh0t_mrsw_ct s, unsigned int idx)
}
/* Start reading the latest written buffer and return the index to it */
static inline unsigned int
M_INLINE unsigned int
m_snapsh0t_mrsw_read_start(m_snapsh0t_mrsw_ct s)
{
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
@@ -574,7 +574,7 @@ m_snapsh0t_mrsw_read_start(m_snapsh0t_mrsw_ct s)
}
/* End the reading the given buffer */
static inline void
M_INLINE void
m_snapsh0t_mrsw_read_end(m_snapsh0t_mrsw_ct s, unsigned int idx)
{
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
@@ -639,7 +639,7 @@ m_snapsh0t_mrsw_read_end(m_snapsh0t_mrsw_ct s, unsigned int idx)
/* Define the core functions */
#define M_SNAPSH0T_SPMC_DEF_CORE(name, type, oplist, snapshot_t) \
\
static inline void \
M_INLINE void \
M_F(name, _init)(snapshot_t snap, size_t nReader) \
{ \
M_ASSERT (snap != NULL); \
@@ -658,7 +658,7 @@ m_snapsh0t_mrsw_read_end(m_snapsh0t_mrsw_ct s, unsigned int idx)
M_SNAPSH0T_SPMC_CONTRACT(snap); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(snapshot_t snap) \
{ \
M_SNAPSH0T_SPMC_CONTRACT(snap); \
@@ -670,7 +670,7 @@ m_snapsh0t_mrsw_read_end(m_snapsh0t_mrsw_ct s, unsigned int idx)
m_snapsh0t_mrsw_clear(snap->core); \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _write)(snapshot_t snap) \
{ \
M_SNAPSH0T_SPMC_CONTRACT(snap); \
@@ -678,7 +678,7 @@ m_snapsh0t_mrsw_read_end(m_snapsh0t_mrsw_ct s, unsigned int idx)
return &snap->data[idx].x; \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _read_start)(snapshot_t snap) \
{ \
M_SNAPSH0T_SPMC_CONTRACT(snap); \
@@ -686,7 +686,7 @@ m_snapsh0t_mrsw_read_end(m_snapsh0t_mrsw_ct s, unsigned int idx)
return M_CONST_CAST(type, &snap->data[idx].x); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _read_end)(snapshot_t snap, type const *old) \
{ \
M_SNAPSH0T_SPMC_CONTRACT(snap); \
@@ -700,7 +700,7 @@ m_snapsh0t_mrsw_read_end(m_snapsh0t_mrsw_ct s, unsigned int idx)
m_snapsh0t_mrsw_read_end(snap->core, idx); \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _get_write_buffer)(snapshot_t snap) \
{ \
M_SNAPSH0T_SPMC_CONTRACT(snap); \
@@ -746,7 +746,7 @@ m_snapsh0t_mrsw_read_end(m_snapsh0t_mrsw_ct s, unsigned int idx)
/* Define the core functions */
#define M_SNAPSH0T_MPMC_DEF_CORE(name, type, oplist, snapshot_t) \
\
static inline void \
M_INLINE void \
M_F(name, _init)(snapshot_t snap, size_t nReader, size_t nWriter) \
{ \
M_F(name, _mrsw_init)(snap->core, nReader + nWriter -1 ); \
@@ -755,13 +755,13 @@ m_snapsh0t_mrsw_read_end(m_snapsh0t_mrsw_ct s, unsigned int idx)
m_snapsh0t_mrsw_write_end(snap->core->core, idx); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(snapshot_t snap) \
{ \
M_F(name, _mrsw_clear)(snap->core); \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _write_start)(snapshot_t snap) \
{ \
M_SNAPSH0T_SPMC_CONTRACT(snap->core); \
@@ -769,7 +769,7 @@ m_snapsh0t_mrsw_read_end(m_snapsh0t_mrsw_ct s, unsigned int idx)
return &snap->core->data[idx].x; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _write_end)(snapshot_t snap, type *old) \
{ \
M_SNAPSH0T_SPMC_CONTRACT(snap->core); \
@@ -782,13 +782,13 @@ m_snapsh0t_mrsw_read_end(m_snapsh0t_mrsw_ct s, unsigned int idx)
m_snapsh0t_mrsw_write_end(snap->core->core, idx); \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _read_start)(snapshot_t snap) \
{ \
return M_F(name, _mrsw_read_start)(snap->core); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _read_end)(snapshot_t snap, type const *old) \
{ \
M_F(name, _mrsw_read_end)(snap->core, old); \
+239 -143
View File
File diff suppressed because it is too large. Load diff
+266 -47
View File
@@ -27,7 +27,9 @@
/* Auto-detect the thread backend to use if the user has not override it */
#ifndef M_USE_THREAD_BACKEND
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
# if defined(INC_FREERTOS_H)
# define M_USE_THREAD_BACKEND 4
# elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
&& !defined(__STDC_NO_THREADS__)
# define M_USE_THREAD_BACKEND 1
# elif defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
@@ -58,7 +60,7 @@ typedef cnd_t m_cond_t[1];
typedef thrd_t m_thread_t[1];
/* Initialize the mutex (constructor) */
static inline void m_mutex_init(m_mutex_t m)
M_INLINE void m_mutex_init(m_mutex_t m)
{
int rc = mtx_init(m, mtx_plain);
// Abort program in case of initialization failure
@@ -67,25 +69,25 @@ static inline void m_mutex_init(m_mutex_t m)
}
/* Clear the mutex (destructor) */
static inline void m_mutex_clear(m_mutex_t m)
M_INLINE void m_mutex_clear(m_mutex_t m)
{
mtx_destroy(m);
}
/* Lock the mutex */
static inline void m_mutex_lock(m_mutex_t m)
M_INLINE void m_mutex_lock(m_mutex_t m)
{
mtx_lock(m);
}
/* Unlock the mutex */
static inline void m_mutex_unlock(m_mutex_t m)
M_INLINE void m_mutex_unlock(m_mutex_t m)
{
mtx_unlock(m);
}
/* Initialize the condition variable (constructor) */
static inline void m_cond_init(m_cond_t c)
M_INLINE void m_cond_init(m_cond_t c)
{
int rc = cnd_init(c);
// Abort program in case of initialization failure
@@ -94,31 +96,31 @@ static inline void m_cond_init(m_cond_t c)
}
/* Clear the condition variable (destructor) */
static inline void m_cond_clear(m_cond_t c)
M_INLINE void m_cond_clear(m_cond_t c)
{
cnd_destroy(c);
}
/* Signal the condition variable to at least one waiting thread */
static inline void m_cond_signal(m_cond_t c)
M_INLINE void m_cond_signal(m_cond_t c)
{
cnd_signal(c);
}
/* Signal the condition variable to all waiting threads */
static inline void m_cond_broadcast(m_cond_t c)
M_INLINE void m_cond_broadcast(m_cond_t c)
{
cnd_broadcast(c);
}
/* Wait for signaling the condition variable by another thread */
static inline void m_cond_wait(m_cond_t c, m_mutex_t m)
M_INLINE void m_cond_wait(m_cond_t c, m_mutex_t m)
{
cnd_wait(c, m);
}
/* Create the thread (constructor) and start it */
static inline void m_thread_create(m_thread_t t, void (*func)(void*), void* arg)
M_INLINE void m_thread_create(m_thread_t t, void (*func)(void*), void* arg)
{
int rc = thrd_create(t, (int(*)(void*))(void(*)(void))func, arg);
// Abort program in case of initialization failure
@@ -126,7 +128,7 @@ static inline void m_thread_create(m_thread_t t, void (*func)(void*), void* arg)
}
/* Wait for the thread to terminate and destroy it (destructor) */
static inline void m_thread_join(m_thread_t t)
M_INLINE void m_thread_join(m_thread_t t)
{
int rc = thrd_join(*t, NULL);
M_ASSERT (rc == thrd_success);
@@ -136,14 +138,14 @@ static inline void m_thread_join(m_thread_t t)
/* The thread has nothing meaningfull to do.
Inform the OS to let other threads be scheduled */
static inline void m_thread_yield(void)
M_INLINE void m_thread_yield(void)
{
thrd_yield();
}
/* Sleep the thread for at least usec microseconds.
Return true if the sleep was successful */
static inline bool m_thread_sleep(unsigned long long usec)
Return true if the sleep was successful (or we cannot know) */
M_INLINE bool m_thread_sleep(unsigned long long usec)
{
struct timespec tv;
tv.tv_sec = (long) (usec / 1000000ULL);
@@ -159,7 +161,7 @@ typedef once_flag m_once_t[1];
#define M_ONCE_INIT_VALUE { ONCE_FLAG_INIT }
// Call the function exactly once
static inline void m_once_call(m_once_t o, void (*func)(void))
M_INLINE void m_once_call(m_once_t o, void (*func)(void))
{
call_once(o,func);
}
@@ -223,68 +225,68 @@ typedef CRITICAL_SECTION m_mutex_t[1];
typedef CONDITION_VARIABLE m_cond_t[1];
/* Initialize a mutex (Constructor)*/
static inline void m_mutex_init(m_mutex_t m)
M_INLINE void m_mutex_init(m_mutex_t m)
{
InitializeCriticalSection(m);
}
/* Clear a mutex (destructor) */
static inline void m_mutex_clear(m_mutex_t m)
M_INLINE void m_mutex_clear(m_mutex_t m)
{
DeleteCriticalSection(m);
}
/* Lock a mutex */
static inline void m_mutex_lock(m_mutex_t m)
M_INLINE void m_mutex_lock(m_mutex_t m)
{
EnterCriticalSection(m);
}
/* Unlock a mutex */
static inline void m_mutex_unlock(m_mutex_t m)
M_INLINE void m_mutex_unlock(m_mutex_t m)
{
LeaveCriticalSection(m);
}
/* Initialize a condition variable (constructor) */
static inline void m_cond_init(m_cond_t c)
M_INLINE void m_cond_init(m_cond_t c)
{
InitializeConditionVariable(c);
}
/* Clear a condition variable (destructor) */
static inline void m_cond_clear(m_cond_t c)
M_INLINE void m_cond_clear(m_cond_t c)
{
(void) c; // There is no destructor for this object.
}
/* Signal a condition variable to at least one waiting thread */
static inline void m_cond_signal(m_cond_t c)
M_INLINE void m_cond_signal(m_cond_t c)
{
WakeConditionVariable(c);
}
/* Signal a condition variable to all waiting threads */
static inline void m_cond_broadcast(m_cond_t c)
M_INLINE void m_cond_broadcast(m_cond_t c)
{
WakeAllConditionVariable(c);
}
/* Wait for a condition variable */
static inline void m_cond_wait(m_cond_t c, m_mutex_t m)
M_INLINE void m_cond_wait(m_cond_t c, m_mutex_t m)
{
SleepConditionVariableCS(c, m, INFINITE);
}
/* Create a thread (constructor) and start it */
static inline void m_thread_create(m_thread_t t, void (*func)(void*), void *arg)
M_INLINE void m_thread_create(m_thread_t t, void (*func)(void*), void *arg)
{
*t = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) (uintptr_t) func, arg, 0, NULL);
M_ASSERT_INIT (*t != NULL, "thread");
}
/* Wait for the thread to terminate and destroy it (destructor) */
static inline void m_thread_join(m_thread_t t)
M_INLINE void m_thread_join(m_thread_t t)
{
DWORD dwWaitResult = WaitForSingleObject(*t, INFINITE);
(void) dwWaitResult;
@@ -294,14 +296,14 @@ static inline void m_thread_join(m_thread_t t)
/* The thread has nothing meaningfull to do.
Inform the OS to let other threads be scheduled */
static inline void m_thread_yield(void)
M_INLINE void m_thread_yield(void)
{
Sleep(0);
}
/* Sleep the thread for at least usec microseconds
Return true if the sleep was successful */
static inline bool m_thread_sleep(unsigned long long usec)
M_INLINE bool m_thread_sleep(unsigned long long usec)
{
LARGE_INTEGER ft;
M_ASSERT (usec <= LLONG_MAX);
@@ -317,7 +319,7 @@ static inline bool m_thread_sleep(unsigned long long usec)
typedef INIT_ONCE m_once_t[1];
#define M_ONCE_INIT_VALUE { INIT_ONCE_STATIC_INIT }
static inline BOOL CALLBACK m_once_callback( PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContext)
M_INLINE BOOL CALLBACK m_once_callback( PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContext)
{
void (*func)(void);
(void) InitOnce;
@@ -326,7 +328,7 @@ static inline BOOL CALLBACK m_once_callback( PINIT_ONCE InitOnce, PVOID Paramete
(*func)();
return TRUE;
}
static inline void m_once_call(m_once_t o, void (*func)(void))
M_INLINE void m_once_call(m_once_t o, void (*func)(void))
{
InitOnceExecuteOnce(o, m_once_callback, (void*)(intptr_t)func, NULL);
}
@@ -343,7 +345,7 @@ M_END_PROTECTED_CODE
/**************************** PTHREAD version ******************************/
#else
#elif M_USE_THREAD_BACKEND == 3
#include <pthread.h>
#ifdef _POSIX_PRIORITY_SCHEDULING
@@ -368,7 +370,7 @@ typedef pthread_cond_t m_cond_t[1];
typedef pthread_t m_thread_t[1];
/* Initialize the mutex (constructor) */
static inline void m_mutex_init(m_mutex_t m)
M_INLINE void m_mutex_init(m_mutex_t m)
{
int _rc = pthread_mutex_init(m, NULL);
// Abort program in case of initialization failure
@@ -377,19 +379,19 @@ static inline void m_mutex_init(m_mutex_t m)
}
/* Clear the mutex (destructor) */
static inline void m_mutex_clear(m_mutex_t m)
M_INLINE void m_mutex_clear(m_mutex_t m)
{
pthread_mutex_destroy(m);
}
/* Lock the mutex */
static inline void m_mutex_lock(m_mutex_t m)
M_INLINE void m_mutex_lock(m_mutex_t m)
{
pthread_mutex_lock(m);
}
/* Unlock the mutex */
static inline void m_mutex_unlock(m_mutex_t m)
M_INLINE void m_mutex_unlock(m_mutex_t m)
{
pthread_mutex_unlock(m);
}
@@ -398,13 +400,13 @@ static inline void m_mutex_unlock(m_mutex_t m)
#define M_MUTEXI_INIT_VALUE { PTHREAD_MUTEX_INITIALIZER }
/* Internal function compatible with lazy lock */
static inline void m_mutexi_lazy_lock(m_mutex_t m)
M_INLINE void m_mutexi_lazy_lock(m_mutex_t m)
{
pthread_mutex_lock(m);
}
/* Initialize the condition variable (constructor) */
static inline void m_cond_init(m_cond_t c)
M_INLINE void m_cond_init(m_cond_t c)
{
int _rc = pthread_cond_init(c, NULL);
// Abort program in case of initialization failure
@@ -413,38 +415,38 @@ static inline void m_cond_init(m_cond_t c)
}
/* Clear the condition variable (destructor) */
static inline void m_cond_clear(m_cond_t c)
M_INLINE void m_cond_clear(m_cond_t c)
{
pthread_cond_destroy(c);
}
/* Signal a condition variable to at least a waiting thread */
static inline void m_cond_signal(m_cond_t c)
M_INLINE void m_cond_signal(m_cond_t c)
{
pthread_cond_signal(c);
}
/* Signal a condition variable to all waiting threads */
static inline void m_cond_broadcast(m_cond_t c)
M_INLINE void m_cond_broadcast(m_cond_t c)
{
pthread_cond_broadcast(c);
}
/* Waiting for a condition variable */
static inline void m_cond_wait(m_cond_t c, m_mutex_t m)
M_INLINE void m_cond_wait(m_cond_t c, m_mutex_t m)
{
pthread_cond_wait(c, m);
}
/* Create a thread (constructor) and start it */
static inline void m_thread_create(m_thread_t t, void (*func)(void*), void *arg)
M_INLINE void m_thread_create(m_thread_t t, void (*func)(void*), void *arg)
{
int _rc = pthread_create(t, NULL, (void*(*)(void*))(void(*)(void))func, arg);
M_ASSERT_INIT (_rc == 0, "thread");
}
/* Wait for the thread to terminate and destroy it (destructor) */
static inline void m_thread_join(m_thread_t t)
M_INLINE void m_thread_join(m_thread_t t)
{
int _rc = pthread_join(*t, NULL);
(void)_rc; // Avoid warning about variable unused.
@@ -453,7 +455,7 @@ static inline void m_thread_join(m_thread_t t)
/* The thread has nothing meaningfull to do.
Inform the OS to let other threads be scheduled */
static inline void m_thread_yield(void)
M_INLINE void m_thread_yield(void)
{
#ifdef _POSIX_PRIORITY_SCHEDULING
sched_yield();
@@ -462,7 +464,7 @@ static inline void m_thread_yield(void)
/* Sleep for at least usec microseconds
Return true if the sleep was successful */
static inline bool m_thread_sleep(unsigned long long usec)
M_INLINE bool m_thread_sleep(unsigned long long usec)
{
struct timeval tv;
/* We don't want to use usleep or nanosleep so that
@@ -475,7 +477,7 @@ static inline bool m_thread_sleep(unsigned long long usec)
typedef pthread_once_t m_once_t[1];
#define M_ONCE_INIT_VALUE { PTHREAD_ONCE_INIT }
static inline void m_once_call(m_once_t o, void (*func)(void))
M_INLINE void m_once_call(m_once_t o, void (*func)(void))
{
pthread_once(o,func);
}
@@ -488,6 +490,223 @@ static inline void m_once_call(m_once_t o, void (*func)(void))
M_END_PROTECTED_CODE
/****************************** FreeRTOS version ********************************/
#elif M_USE_THREAD_BACKEND == 4
#include <stdatomic.h>
#include <semphr.h>
#include <task.h>
#include "m-core.h"
M_BEGIN_PROTECTED_CODE
/* Default value for the stack */
#ifndef M_USE_TASK_STACK_SIZE
#define M_USE_TASK_STACK_SIZE configMINIMAL_STACK_SIZE
#endif
/* Default value for the priority tasks */
#ifndef M_USE_TASK_PRIORITY
#define M_USE_TASK_PRIORITY ( tskIDLE_PRIORITY )
#endif
/* Define a mutex type based on FreeRTOS definition */
typedef struct m_mutex_s {
SemaphoreHandle_t handle;
StaticSemaphore_t MutexBuffer;
} m_mutex_t[1];
/* Define a thread type based on FreeRTOS definition */
typedef struct m_cond_s {
SemaphoreHandle_t handle;
StaticSemaphore_t SemBuffer;
unsigned int NumThreadWaiting;
} m_cond_t[1];
/* Define a thread type based on FreeRTOS definition */
typedef struct m_thread_s {
SemaphoreHandle_t SemHandle;
StaticSemaphore_t SemBuffer;
TaskHandle_t TaskHandle;
StaticTask_t TaskBuffer;
void (*EntryPoint)(void *);
void* ArgsEntryPoint;
StackType_t* StackBuffer;
} m_thread_t[1];
/* Initialize the mutex (constructor) */
M_INLINE void m_mutex_init(m_mutex_t m)
{
/* Create a mutex semaphore without using any dynamic allocation */
m->handle = xSemaphoreCreateMutexStatic(&m->MutexBuffer);
// It cannot fail, so we won't use M_ASSERT_INIT
M_ASSERT(m->handle);
}
/* Clear the mutex (destructor) */
M_INLINE void m_mutex_clear(m_mutex_t m)
{
vSemaphoreDelete(m->handle);
}
/* Lock the mutex */
M_INLINE void m_mutex_lock(m_mutex_t m)
{
xSemaphoreTake(m->handle, portMAX_DELAY);
}
/* Unlock the mutex */
M_INLINE void m_mutex_unlock(m_mutex_t m)
{
xSemaphoreGive(m->handle);
}
/* Initialize the condition variable (constructor) */
M_INLINE void m_cond_init(m_cond_t c)
{
c->NumThreadWaiting = 0;
// Create a semaphore to implement the conditional variable
// Initial value is 0 and valid range is <= 0
c->handle = xSemaphoreCreateCountingStatic( INT_MAX, 0, &c->SemBuffer );
// It cannot fail, so we won't use M_ASSERT_INIT
M_ASSERT(c->handle);
}
/* Clear the condition variable (destructor) */
M_INLINE void m_cond_clear(m_cond_t c)
{
vSemaphoreDelete(c->handle);
}
/* Signal the condition variable to at least one waiting thread */
M_INLINE void m_cond_signal(m_cond_t c)
{
// This function is called within the mutex lock
// NumThreadWaiting doesn't need to be atomic
if (c->NumThreadWaiting > 0) {
// Wakeup one thread by posting on the semaphore
xSemaphoreGive(c->handle);
} // Otherwise there is no waiting thread, so nothing to signal
}
/* Signal the condition variable to all waiting threads */
M_INLINE void m_cond_broadcast(m_cond_t c)
{
// This function is called within the mutex lock
// NumThreadWaiting doesn't need to be atomic
if (c->NumThreadWaiting > 0) {
// Wakeup all thread by posting on the semaphore
// as many times as there are waiting threads
for(unsigned i = 0; i < c->NumThreadWaiting; i++) {
xSemaphoreGive(c->handle);
}
} // Otherwise there is no waiting thread, so nothing to signal
}
/* Wait for signaling the condition variable by another thread */
M_INLINE void m_cond_wait(m_cond_t c, m_mutex_t m)
{
// This function is called within the mutex lock
// Increment the number of waiting thread
c->NumThreadWaiting ++;
m_mutex_unlock(m);
// Wait for post in the semaphore
xSemaphoreTake(c->handle, portMAX_DELAY);
m_mutex_lock(m);
c->NumThreadWaiting --;
}
M_INLINE void m_thr3ad_wrapper( void *args)
{
struct m_thread_s *thread_ptr = args;
thread_ptr->EntryPoint(thread_ptr->ArgsEntryPoint);
// Give back the semaphore.
xSemaphoreGive(thread_ptr->SemHandle);
// Wait for destruction
while (true) { vTaskSuspend(NULL); }
}
/* Create the thread (constructor) and start it */
M_INLINE void m_thread_create(m_thread_t t, void (*func)(void*), void* arg)
{
// Create a semaphore to implement the final wait
t->SemHandle = xSemaphoreCreateCountingStatic( 1, 0, &t->SemBuffer );
M_ASSERT(t->SemHandle);
// Save the argument to the thread
t->EntryPoint = func;
t->ArgsEntryPoint = arg;
// Allocate the stack
t->StackBuffer = pvPortMalloc( sizeof (StackType_t) * M_USE_TASK_STACK_SIZE);
M_ASSERT_INIT(t->StackBuffer, "STACK");
// Create the task without using any dynamic allocation
t->TaskHandle = xTaskCreateStatic(m_thr3ad_wrapper, "M*LIB", M_USE_TASK_STACK_SIZE, (void*) t, M_USE_TASK_PRIORITY, t->StackBuffer, &t->TaskBuffer);
// It cannot fail, so we won't use M_ASSERT_INIT
M_ASSERT(t->TaskHandle);
}
/* Wait for the thread to terminate and destroy it (destructor) */
M_INLINE void m_thread_join(m_thread_t t)
{
xSemaphoreTake(t->SemHandle, portMAX_DELAY);
vTaskDelete(t->TaskHandle);
vPortFree(t->StackBuffer);
vSemaphoreDelete(t->SemHandle);
t->TaskHandle = 0;
t->StackBuffer = 0;
t->SemHandle = 0;
}
/* The thread has nothing meaningfull to do.
Inform the OS to let other threads be scheduled */
M_INLINE void m_thread_yield(void)
{
taskYIELD();
}
/* Sleep the thread for at least usec microseconds.
Return true if the sleep was successful */
M_INLINE bool m_thread_sleep(unsigned long long usec)
{
TickType_t delay = (TickType_t) (usec / portTICK_PERIOD_MS / 1000ULL);
vTaskDelay(delay);
return true;
}
// a helper structure for m_once_call
typedef struct {
atomic_int count;
} m_once_t[1];
// Initial value for m_once_t
#define M_ONCE_INIT_VALUE { { ATOMIC_VAR_INIT(0) } }
// Call the function exactly once
M_INLINE void m_once_call(m_once_t o, void (*func)(void))
{
if (atomic_load(&o->count) != 2) {
int n = 0;
if (atomic_compare_exchange_strong( &o->count, &n, 1)) {
// First thread success
func();
atomic_store(&o->count, 2);
}
// Wait for function call (FIXME: priority inversion possible?)
while (atomic_load(&o->count) != 2) { m_thread_yield(); }
} // Already called. Nothing to do
}
// Attribute to use to allocate a global variable to a thread.
#define M_THREAD_ATTR __thread
M_END_PROTECTED_CODE
/******************************** INVALID VALUE **********************************/
#else
# error Value of M_USE_THREAD_BACKEND is incorrect. Please see the documentation for valid usage.
#endif
// TODO: Obsolete M_LOCK macro.
+78 -78
View File
@@ -204,7 +204,7 @@ typedef int32_t m_tr33_index_t;
/* Define the core & unique methods of a tree */
#define M_TR33_DEF_P4_CORE(name, type, oplist, tree_t, it_t) \
/* Initialize a generic tree (empty) */ \
static inline void \
M_INLINE void \
M_F(name, _init)(tree_t tree) { \
tree->size = 0; \
tree->capacity = 0; \
@@ -215,7 +215,7 @@ typedef int32_t m_tr33_index_t;
M_TR33_CONTRACT(tree); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _reset)(tree_t tree) { \
M_TR33_CONTRACT(tree); \
if (tree->size > 0) { \
@@ -241,7 +241,7 @@ typedef int32_t m_tr33_index_t;
M_TR33_CONTRACT(tree); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _clear)(tree_t tree) { \
M_F(name, _reset)(tree); \
struct M_F(name,_node_s)*ptr = tree->tab == NULL ? NULL : tree->tab-1;\
@@ -251,7 +251,7 @@ typedef int32_t m_tr33_index_t;
tree->tab = NULL; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _reserve)(tree_t tree, size_t alloc) { \
M_TR33_CONTRACT(tree); \
/* Nothing to do if the request is lower than the current capacity. */ \
@@ -298,14 +298,14 @@ typedef int32_t m_tr33_index_t;
M_TR33_CONTRACT(tree); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _lock)(tree_t tree, bool lock) { \
M_TR33_CONTRACT(tree); \
tree->allow_realloc = lock ? INT32_MAX : 0; \
M_TR33_CONTRACT(tree); \
} \
\
static inline m_tr33_index_t \
M_INLINE m_tr33_index_t \
M_C3(m_tr33_, name, _alloc_node)(tree_t tree) { \
m_tr33_index_t ret = tree->free_index; \
if (M_UNLIKELY(ret < 0)) { \
@@ -350,7 +350,7 @@ typedef int32_t m_tr33_index_t;
return ret; \
} \
\
static inline void \
M_INLINE void \
M_C3(m_tr33_, name, _free_node)(tree_t tree, m_tr33_index_t i) { \
tree->tab[i].parent = M_TR33_NO_NODE; \
tree->tab[i].left = M_TR33_NO_NODE; \
@@ -360,7 +360,7 @@ typedef int32_t m_tr33_index_t;
tree->free_index = i; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _set_root)(tree_t tree, type const data) { \
M_TR33_CONTRACT(tree); \
M_F(name, _reset)(tree); \
@@ -380,7 +380,7 @@ typedef int32_t m_tr33_index_t;
\
/* The iterator references the first root node */ \
/* usually for pre-order walk */ \
static inline it_t \
M_INLINE it_t \
M_F(name, _it)(tree_t tree) { \
M_TR33_CONTRACT(tree); \
it_t it; \
@@ -390,7 +390,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _it_end)(tree_t tree) { \
M_TR33_CONTRACT(tree); \
it_t it; \
@@ -400,53 +400,53 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _end_p)(it_t it) { \
M_TR33_IT_CONTRACT(it, false); \
return it.index < 0; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _ref)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
return &it.tree->tab[it.index].data; \
} \
\
static inline type const * \
M_INLINE type const * \
M_F(name, _cref)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
return M_CONST_CAST(type, &it.tree->tab[it.index].data); \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _up_ref)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
m_tr33_index_t i = it.tree->tab[it.index].parent; \
return i < 0 ? NULL : &it.tree->tab[i].data; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _down_ref)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
m_tr33_index_t i = it.tree->tab[it.index].child; \
return i < 0 ? NULL : &it.tree->tab[i].data; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _left_ref)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
m_tr33_index_t i = it.tree->tab[it.index].left; \
return i < 0 ? NULL : &it.tree->tab[i].data; \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _right_ref)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
m_tr33_index_t i = it.tree->tab[it.index].right; \
return i < 0 ? NULL : &it.tree->tab[i].data; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _insert_up_raw)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
m_tr33_index_t i = M_C3(m_tr33_, name, _alloc_node)(it.tree); \
@@ -476,7 +476,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _insert_up)(it_t pos, type const data) { \
it_t it = M_F(name, _insert_up_raw)(pos); \
M_CALL_INIT_SET(oplist, it.tree->tab[it.index].data, data); \
@@ -484,7 +484,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _move_up)(it_t pos, type *data) { \
it_t it = M_F(name, _insert_up_raw)(pos); \
M_DO_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \
@@ -492,7 +492,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _insert_down_raw)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
m_tr33_index_t i = M_C3(m_tr33_, name, _alloc_node)(it.tree); \
@@ -513,7 +513,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _insert_down)(it_t pos, type const data) { \
it_t it = M_F(name, _insert_down_raw)(pos); \
M_CALL_INIT_SET(oplist, it.tree->tab[it.index].data, data); \
@@ -521,7 +521,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _move_down)(it_t pos, type *data) { \
it_t it = M_F(name, _insert_down_raw)(pos); \
M_DO_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \
@@ -529,7 +529,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _insert_child_raw)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
/* Insert a node as a child of another, making the current childreen \
@@ -550,7 +550,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _insert_child)(it_t pos, type const data) { \
it_t it = M_F(name, _insert_child_raw)(pos); \
M_CALL_INIT_SET(oplist, it.tree->tab[it.index].data, data); \
@@ -558,7 +558,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _move_child)(it_t pos, type *data) { \
it_t it = M_F(name, _insert_child_raw)(pos); \
M_DO_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \
@@ -566,7 +566,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _insert_left_raw)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
M_ASSERT(it.index != it.tree->root_index); \
@@ -590,7 +590,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _insert_left)(it_t pos, type const data) { \
it_t it = M_F(name, _insert_left_raw)(pos); \
M_CALL_INIT_SET(oplist, it.tree->tab[it.index].data, data); \
@@ -598,7 +598,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _move_left)(it_t pos, type *data) { \
it_t it = M_F(name, _insert_left_raw)(pos); \
M_DO_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \
@@ -606,7 +606,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _insert_right_raw)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
M_ASSERT(it.index != it.tree->root_index); \
@@ -624,7 +624,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _insert_right)(it_t pos, type const data) { \
it_t it = M_F(name, _insert_right_raw)(pos); \
M_CALL_INIT_SET(oplist, it.tree->tab[it.index].data, data); \
@@ -632,7 +632,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _move_right)(it_t pos, type *data) { \
it_t it = M_F(name, _insert_right_raw)(pos); \
M_DO_INIT_MOVE(oplist, it.tree->tab[it.index].data, *data); \
@@ -640,7 +640,7 @@ typedef int32_t m_tr33_index_t;
return it; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_up)(it_t *it) { \
M_ASSERT(it != NULL); \
M_TR33_IT_CONTRACT(*it, true); \
@@ -653,7 +653,7 @@ typedef int32_t m_tr33_index_t;
return ret; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_down)(it_t *it) { \
M_ASSERT(it != NULL); \
M_TR33_IT_CONTRACT(*it, true); \
@@ -666,7 +666,7 @@ typedef int32_t m_tr33_index_t;
return ret; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_left)(it_t *it) { \
M_ASSERT(it != NULL); \
M_TR33_IT_CONTRACT(*it, true); \
@@ -679,7 +679,7 @@ typedef int32_t m_tr33_index_t;
return ret; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_right)(it_t *it) { \
M_ASSERT(it != NULL); \
M_TR33_IT_CONTRACT(*it, true); \
@@ -692,26 +692,26 @@ typedef int32_t m_tr33_index_t;
return ret; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _root_p)(const it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
return it.tree->tab[it.index].parent == M_TR33_ROOT_NODE; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _node_p)(const it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
return it.tree->tab[it.index].child != M_TR33_NO_NODE; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _leaf_p)(const it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
return it.tree->tab[it.index].child == M_TR33_NO_NODE; \
} \
\
/* Compute the degree of a node in linear time */ \
static inline int32_t \
M_INLINE int32_t \
M_F(name, _degree)(const it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
int32_t ret = 0; \
@@ -724,7 +724,7 @@ typedef int32_t m_tr33_index_t;
} \
\
/* Compute the depth of a node in linear time */ \
static inline int32_t \
M_INLINE int32_t \
M_F(name, _depth)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
int32_t ret = 0; \
@@ -736,13 +736,13 @@ typedef int32_t m_tr33_index_t;
return ret; \
} \
\
static inline struct M_F(name, _s) * \
M_INLINE struct M_F(name, _s) * \
M_F(name, _tree)(it_t it) { \
M_TR33_IT_CONTRACT(it, false); \
return it.tree; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _swap_at)(it_t it1, it_t it2, bool swapChild) { \
M_ASSUME(it1.tree == it2.tree); \
M_TR33_IT_CONTRACT(it1, true); \
@@ -823,7 +823,7 @@ typedef int32_t m_tr33_index_t;
M_TR33_IT_CONTRACT(it2, true); \
} \
\
static inline type * \
M_INLINE type * \
M_F(name, _unlink)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
m_tr33_index_t parent, child, left, right, child_r; \
@@ -884,7 +884,7 @@ typedef int32_t m_tr33_index_t;
return &it.tree->tab[it.index].data; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _remove)(it_t it) { \
M_TR33_IT_CONTRACT(it, false); \
if (M_UNLIKELY(it.index < 0)) { return false; } \
@@ -895,7 +895,7 @@ typedef int32_t m_tr33_index_t;
\
/* Scan all nodes, first the parent then the children (uses with _it) */ \
/* pre-order walk */ \
static inline void \
M_INLINE void \
M_F(name, _next)(it_t *it) { \
M_TR33_IT_CONTRACT(*it, true); \
/* First go down, if impossible go right */ \
@@ -915,7 +915,7 @@ typedef int32_t m_tr33_index_t;
\
/* Scan all nodes, first the children then the parent */ \
/* post-order walk */ \
static inline it_t \
M_INLINE it_t \
M_F(name, _it_post)(tree_t tree) { \
M_TR33_CONTRACT(tree); \
it_t it; \
@@ -929,7 +929,7 @@ typedef int32_t m_tr33_index_t;
\
/* Scan all nodes, first the children then the parent (uses with _it_post) */ \
/* post-order walk */ \
static inline void \
M_INLINE void \
M_F(name, _next_post)(it_t *it) { \
M_TR33_IT_CONTRACT(*it, true); \
/* First go right */ \
@@ -947,7 +947,7 @@ typedef int32_t m_tr33_index_t;
M_TR33_IT_CONTRACT(*it, false); \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _it_equal_p)(it_t it1, it_t it2) { \
M_TR33_IT_CONTRACT(it1, false); \
M_TR33_IT_CONTRACT(it2, false); \
@@ -956,7 +956,7 @@ typedef int32_t m_tr33_index_t;
\
/* Scan all nodes, first the parent, then the children */ \
/* post-order walk */ \
static inline it_t \
M_INLINE it_t \
M_F(name, _it_subpre)(it_t it) { \
/* Nothing to do as it is already on the parent! */ \
return it; \
@@ -964,7 +964,7 @@ typedef int32_t m_tr33_index_t;
\
/* Scan the nodes of it_ref, first the parent then the children */ \
/* pre-order walk */ \
static inline void \
M_INLINE void \
M_F(name, _next_subpre)(it_t *it, it_t it_ref) { \
M_TR33_IT_CONTRACT(*it, true); \
M_TR33_IT_CONTRACT(it_ref, true); \
@@ -985,7 +985,7 @@ typedef int32_t m_tr33_index_t;
\
/* Scan all nodes, first the children then the parent */ \
/* post-order walk */ \
static inline it_t \
M_INLINE it_t \
M_F(name, _it_subpost)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
/* Evaluate child first, so go down to the lowest child */ \
@@ -996,7 +996,7 @@ typedef int32_t m_tr33_index_t;
\
/* Scan all nodes, first the children then the parent (uses with _it_subpost) */ \
/* post-order walk */ \
static inline void \
M_INLINE void \
M_F(name, _next_subpost)(it_t *it, it_t ref) { \
M_TR33_IT_CONTRACT(*it, true); \
M_TR33_IT_CONTRACT(ref, true); \
@@ -1018,7 +1018,7 @@ typedef int32_t m_tr33_index_t;
assert(b); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _prune)(it_t it) { \
M_TR33_IT_CONTRACT(it, true); \
/* remove the node, including its childs */ \
@@ -1033,7 +1033,7 @@ typedef int32_t m_tr33_index_t;
} \
} \
\
static inline it_t \
M_INLINE it_t \
M_F(name, _lca)(it_t it1, it_t it2) { \
M_TR33_IT_CONTRACT(it1, true); \
M_TR33_IT_CONTRACT(it2, true); \
@@ -1062,7 +1062,7 @@ typedef int32_t m_tr33_index_t;
return it1; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _graft_child)(it_t it1, const it_t it2) { \
M_ASSERT(it1.tree == it2.tree); \
M_TR33_IT_CONTRACT(it1, true); \
@@ -1094,7 +1094,7 @@ typedef int32_t m_tr33_index_t;
} \
\
M_IF_METHOD(CMP,oplist)( \
static inline void \
M_INLINE void \
M_F(name, _sort_child)(it_t it0) { \
M_TR33_IT_CONTRACT(it0, true); \
it_t it1 = it0; \
@@ -1122,7 +1122,7 @@ typedef int32_t m_tr33_index_t;
/* Define the classic extended missing methods of a tree */
#define M_TR33_DEF_P4_EXT(name, type, oplist, tree_t, it_t) \
static inline void \
M_INLINE void \
M_F(name, _init_set)(tree_t tree, const tree_t ref) { \
tree->size = ref->size; \
tree->capacity = ref->capacity; \
@@ -1155,14 +1155,14 @@ typedef int32_t m_tr33_index_t;
M_TR33_CONTRACT(tree); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _set)(tree_t tree, const tree_t ref) { \
/* No optimum, but good enought for present time */ \
M_F(name, _clear)(tree); \
M_F(name, _init_set)(tree, ref); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _init_move)(tree_t tree, tree_t ref) { \
tree->size = ref->size; \
tree->capacity = ref->capacity; \
@@ -1175,13 +1175,13 @@ typedef int32_t m_tr33_index_t;
ref->tab = NULL; \
} \
\
static inline void \
M_INLINE void \
M_F(name, _move)(tree_t tree, tree_t ref) { \
M_F(name, _clear)(tree); \
M_F(name, _init_move)(tree, ref); \
} \
\
static inline void \
M_INLINE void \
M_F(name, _swap)(tree_t tree1, tree_t tree2) { \
M_TR33_CONTRACT(tree1); \
M_TR33_CONTRACT(tree2); \
@@ -1195,32 +1195,32 @@ typedef int32_t m_tr33_index_t;
M_TR33_CONTRACT(tree2); \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _size)(const tree_t tree) { \
M_TR33_CONTRACT(tree); \
return (size_t) tree->size; \
} \
\
static inline bool \
M_INLINE bool \
M_F(name, _empty_p)(const tree_t tree) { \
M_TR33_CONTRACT(tree); \
return tree->size == 0; \
} \
\
static inline size_t \
M_INLINE size_t \
M_F(name, _capacity)(const tree_t tree) { \
M_TR33_CONTRACT(tree); \
return (size_t) tree->capacity; \
} \
\
/* Service not really usefull as the affectation operator works with it */\
static inline void \
M_INLINE void \
M_F(name, _it_set)(it_t *dst, it_t src ){ \
*dst = src; \
} \
\
M_IF_METHOD(EQUAL, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _equal_p)(/*const*/ tree_t t1, /*const*/ tree_t t2) { \
M_TR33_CONTRACT(t1); \
M_TR33_CONTRACT(t2); \
@@ -1282,7 +1282,7 @@ typedef int32_t m_tr33_index_t;
, /* No EQUAL */ ) \
\
M_IF_METHOD(HASH, oplist)( \
static inline size_t \
M_INLINE size_t \
M_F(name, _hash)(/* const */ tree_t t1) { \
M_HASH_DECL(hash); \
for(it_t it = M_F(name, _it)(t1); \
@@ -1299,7 +1299,7 @@ typedef int32_t m_tr33_index_t;
/* Define the IO methods of a tree */
#define M_TR33_DEF_P4_IO(name, type, oplist, tree_t, it_t) \
M_IF_METHOD(GET_STR, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _get_str)(string_t str, /*const*/ tree_t tree, bool append) { \
(append ? m_string_cat_cstr : m_string_set_cstr) (str, "["); \
it_t it = M_F(name, _it)(tree); \
@@ -1335,7 +1335,7 @@ M_F(name, _get_str)(string_t str, /*const*/ tree_t tree, bool append) { \
, /* No GET_STR */ ) \
\
M_IF_METHOD(PARSE_STR, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _parse_str)(tree_t tree, const char str[], const char **endp) { \
M_TR33_CONTRACT(tree); \
int cmd = 0; \
@@ -1400,7 +1400,7 @@ exit: \
, /* No PARSE_STR */ ) \
\
M_IF_METHOD(OUT_STR, oplist)( \
static inline void \
M_INLINE void \
M_F(name, _out_str)(FILE *f, /*const*/ tree_t tree) { \
fputc('[', f); \
it_t it = M_F(name, _it)(tree); \
@@ -1436,7 +1436,7 @@ M_F(name, _out_str)(FILE *f, /*const*/ tree_t tree) { \
, /* No OUT_STR */ ) \
\
M_IF_METHOD(IN_STR, oplist)( \
static inline bool \
M_INLINE bool \
M_F(name, _in_str)(tree_t tree, FILE *f) { \
M_TR33_CONTRACT(tree); \
int cmd = 0; \
@@ -1511,7 +1511,7 @@ exit: \
/* Definition of the emplace_back functions */
#define M_TR33_EMPLACE_ROOT_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
static inline M_F(name, _it_ct) \
M_INLINE M_F(name, _it_ct) \
function_name(name_t tree \
M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \
{ \
@@ -1533,7 +1533,7 @@ exit: \
}
#define M_TR33_EMPLACE_UP_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
static inline name_t \
M_INLINE name_t \
function_name(name_t pos \
M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \
{ \
@@ -1544,7 +1544,7 @@ exit: \
}
#define M_TR33_EMPLACE_DOWN_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
static inline name_t \
M_INLINE name_t \
function_name(name_t pos \
M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \
{ \
@@ -1555,7 +1555,7 @@ exit: \
}
#define M_TR33_EMPLACE_CHILD_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
static inline name_t \
M_INLINE name_t \
function_name(name_t pos \
M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \
{ \
@@ -1566,7 +1566,7 @@ exit: \
}
#define M_TR33_EMPLACE_LEFT_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
static inline name_t \
M_INLINE name_t \
function_name(name_t pos \
M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \
{ \
@@ -1577,7 +1577,7 @@ exit: \
}
#define M_TR33_EMPLACE_RIGHT_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
static inline name_t \
M_INLINE name_t \
function_name(name_t pos \
M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \
{ \
+22 -20
View File
@@ -30,11 +30,12 @@
/*
* Select mechanism to use for support of RAII and exception,
* so that for each variables defined in M_LET,
* their destructor is still called on throwing exceptions.
* so that for each variable defined using M_LET,
* its destructor is still called when exceptions are thrown.
* It is either the C++ try,
* it uses a GCC or CLANG extension,
* or the standard c compliant way (much slower).
* or it uses a GCC or CLANG extension,
* or the standard C compliant way (much slower).
* The user can override the desired mechanism.
*/
#ifndef M_USE_TRY_MECHANISM
# if defined(__has_extension)
@@ -75,11 +76,12 @@
* error_code shall be the first argument.
* Other arguments are integers or pointers stored in the exception.
* error code shall be a constant positive integer.
* There is no genericity of the exception data structure itself.
*/
#define M_THROW(...) do { \
M_STATIC_ASSERT(M_RET_ARG1 (__VA_ARGS__) != 0, \
M_LIB_NOT_A_CONSTANT_NON_NULL_INTEGER, \
"The error code shall be a non null constant"); \
"The error code shall be a non null positive constant"); \
M_STATIC_ASSERT(M_NARGS (__VA_ARGS__) <= 1+M_USE_MAX_CONTEXT, \
M_LIB_TOO_MANY_ARGUMENTS, \
"There are too many arguments for an exception."); \
@@ -88,7 +90,7 @@
/*
* Size of the context data that are stored in an exception.
* Size of the context data that are stored in an exception data structure.
*/
#ifndef M_USE_MAX_CONTEXT
#define M_USE_MAX_CONTEXT 10
@@ -98,9 +100,9 @@
* The exception itself.
*
* It is POD data where every fields can be used by the user.
* It has been decided to have only one exception to simplify error
* code, and because :
* - using generic types is much hard in C to do (still possible)
* It has been decided to have only one exception data structure
* to simplify error code and because :
* - using generic types is much harder in C to do (still possible)
* - it will make exceptions more usable for errors which should not
* be handled by exceptions.
*
@@ -306,7 +308,7 @@ typedef struct m_try_s {
{ __VA_ARGS__ } } )
// Copy an exception to another.
static inline void
M_INLINE void
m_exception_set(struct m_exception_s *out, const struct m_exception_s *in)
{
if (in != out) {
@@ -357,7 +359,7 @@ extern M_ATTR_NO_RETURN M_ATTR_COLD_FUNCTION void m_throw(const struct m_excepti
}
// Rethrow the error
static inline void
M_INLINE void
m_rethrow(void)
{
M_ASSERT(m_global_error_list != NULL);
@@ -366,7 +368,7 @@ m_rethrow(void)
// Catch the error code associated to the TRY block state
// and provide a pointer to the exception (which is a global).
static inline bool
M_INLINE bool
m_catch(m_try_t state, unsigned error_code, const struct m_exception_s **exception)
{
M_ASSERT(m_global_error_list == state);
@@ -383,7 +385,7 @@ m_catch(m_try_t state, unsigned error_code, const struct m_exception_s **excepti
}
// Initialize the state to a TRY state.
static inline void
M_INLINE void
m_try_init(m_try_t state)
{
state->kind = M_STATE_TRY;
@@ -395,7 +397,7 @@ m_try_init(m_try_t state)
M_LIKELY ((m_try_init(s), m_try_setjmp(((s)->data.buf)) != 1))
// Disable the current TRY block.
static inline void
M_INLINE void
m_try_clear(m_try_t state)
{
// Even if there is a CATCH block and an unstack of the exception
@@ -422,7 +424,7 @@ m_try_clear(m_try_t state)
// However we register the position in the stack frame now so that in case of partial initialization
// of the object (if the INIT operator of the object calls other INIT operators of composed fields),
// since partial initialization will be unstacked naturally by the composing object.
static inline bool
M_INLINE bool
m_try_cb_pre(m_try_t state)
{
state->kind = M_STATE_CLEAR_CB;
@@ -431,7 +433,7 @@ m_try_cb_pre(m_try_t state)
}
// We register the function to call of the initialized object.
static inline bool
M_INLINE bool
m_try_cb_post(m_try_t state, void (M_TRY_FUNC_OPERATOR func)(void*), void *data)
{
state->data.clear.func = func;
@@ -442,14 +444,14 @@ m_try_cb_post(m_try_t state, void (M_TRY_FUNC_OPERATOR func)(void*), void *data)
// The object will be cleared.
// We can pop the stack frame of the errors.
static inline void
M_INLINE void
m_try_cb_final(m_try_t state)
{
m_global_error_list = state->next;
}
// Pre initialization function. Save the stack frame for a longjmp
static inline bool
M_INLINE bool
m_try_jump_pre(m_try_t state)
{
state->kind = M_STATE_CLEAR_JMPBUF;
@@ -458,7 +460,7 @@ m_try_jump_pre(m_try_t state)
}
// Post initialization function. Register the stack frame for a longjmp
static inline void
M_INLINE void
m_try_jump_post(m_try_t state)
{
m_global_error_list = state;
@@ -469,7 +471,7 @@ m_try_jump_post(m_try_t state)
// The object will be cleared.
// We can pop the stack frame of the errors.
static inline void
M_INLINE void
m_try_jump_final(m_try_t state)
{
m_global_error_list = state->next;
+35 -35
View File
@@ -242,40 +242,42 @@ namespace m_lib {
/* Define the INIT method calling the INIT method for all params */
#define M_TUPL3_DEFINE_INIT(name, ...) \
static inline void M_F(name, _init)(M_F(name,_ct) my) { \
M_MAP(M_TUPL3_DEFINE_INIT_FUNC , __VA_ARGS__) \
M_INLINE void M_F(name, _init)(M_F(name,_ct) my) { \
M_MAP(M_TUPL3_DEFINE_INIT_FUNC , __VA_ARGS__) {} \
}
#define M_TUPL3_DEFINE_INIT_FUNC(a) \
M_TUPL3_CALL_INIT(a, my -> M_TUPL3_GET_FIELD a );
M_CHAIN_OBJ(M_TUPL3_GET_FIELD a, M_TUPL3_GET_OPLIST a, my -> M_TUPL3_GET_FIELD a)
/* Define the INIT_SET method calling the INIT_SET method for all params */
#define M_TUPL3_DEFINE_INIT_SET(name, ...) \
static inline void M_F(name, _init_set)(M_F(name,_ct) my , M_F(name,_ct) const org) { \
M_INLINE void M_F(name, _init_set)(M_F(name,_ct) my , M_F(name,_ct) const org) { \
M_TUPL3_CONTRACT(org); \
M_MAP(M_TUPL3_DEFINE_INIT_SET_FUNC , __VA_ARGS__) \
M_MAP(M_TUPL3_DEFINE_INIT_SET_FUNC , __VA_ARGS__) {} \
}
#define M_TUPL3_DEFINE_INIT_SET_FUNC(a) \
M_TUPL3_CALL_INIT_SET(a, my -> M_TUPL3_GET_FIELD a , org -> M_TUPL3_GET_FIELD a );
M_CHAIN_OBJ(M_TUPL3_GET_FIELD a, M_TUPL3_GET_OPLIST a, \
my -> M_TUPL3_GET_FIELD a , org -> M_TUPL3_GET_FIELD a )
/* Define the INIT_WITH method calling the INIT_SET method for all params. */
#define M_TUPL3_DEFINE_INIT_SET2(name, ...) \
static inline void M_F(name, _init_emplace)(M_F(name,_ct) my \
M_INLINE void M_F(name, _init_emplace)(M_F(name,_ct) my \
M_MAP(M_TUPL3_DEFINE_INIT_SET2_PROTO, __VA_ARGS__) \
) { \
M_MAP(M_TUPL3_DEFINE_INIT_SET2_FUNC , __VA_ARGS__) \
M_MAP(M_TUPL3_DEFINE_INIT_SET2_FUNC , __VA_ARGS__) {} \
}
#define M_TUPL3_DEFINE_INIT_SET2_PROTO(a) \
, M_TUPL3_GET_TYPE a const M_TUPL3_GET_FIELD a
#define M_TUPL3_DEFINE_INIT_SET2_FUNC(a) \
M_TUPL3_CALL_INIT_SET(a, my -> M_TUPL3_GET_FIELD a , M_TUPL3_GET_FIELD a );
M_CHAIN_OBJ(M_TUPL3_GET_FIELD a, M_TUPL3_GET_OPLIST a, \
my -> M_TUPL3_GET_FIELD a , M_TUPL3_GET_FIELD a )
/* Define the SET method calling the SET method for all params. */
#define M_TUPL3_DEFINE_SET(name, ...) \
static inline void M_F(name, _set)(M_F(name,_ct) my , \
M_INLINE void M_F(name, _set)(M_F(name,_ct) my , \
M_F(name,_ct) const org) { \
M_TUPL3_CONTRACT(my); \
M_TUPL3_CONTRACT(org); \
@@ -288,7 +290,7 @@ namespace m_lib {
/* Define the SET_WITH method calling the SET method for all params. */
#define M_TUPL3_DEFINE_SET2(name, ...) \
static inline void M_F(name, _emplace)(M_F(name,_ct) my \
M_INLINE void M_F(name, _emplace)(M_F(name,_ct) my \
M_MAP(M_TUPL3_DEFINE_SET2_PROTO, __VA_ARGS__) \
) { \
M_TUPL3_CONTRACT(my); \
@@ -303,7 +305,7 @@ namespace m_lib {
/* Define the CLEAR method calling the CLEAR method for all params. */
#define M_TUPL3_DEFINE_CLEAR(name, ...) \
static inline void M_F(name, _clear)(M_F(name,_ct) my) { \
M_INLINE void M_F(name, _clear)(M_F(name,_ct) my) { \
M_TUPL3_CONTRACT(my); \
M_MAP(M_TUPL3_DEFINE_CLEAR_FUNC , __VA_ARGS__) \
}
@@ -317,18 +319,18 @@ namespace m_lib {
M_MAP3(M_TUPL3_DEFINE_GETTER_FIELD_PROTO, name, __VA_ARGS__)
#define M_TUPL3_DEFINE_GETTER_FIELD_PROTO(name, num, a) \
static inline M_TUPL3_GET_TYPE a * M_C3(name, _get_at_, M_TUPL3_GET_FIELD a) \
M_INLINE M_TUPL3_GET_TYPE a * M_C3(name, _get_at_, M_TUPL3_GET_FIELD a) \
(M_F(name,_ct) my) { \
M_TUPL3_CONTRACT(my); \
return &(my->M_TUPL3_GET_FIELD a); \
} \
static inline M_TUPL3_GET_TYPE a const * M_C3(name, _cget_at_, M_TUPL3_GET_FIELD a) \
M_INLINE M_TUPL3_GET_TYPE a const * M_C3(name, _cget_at_, M_TUPL3_GET_FIELD a) \
(M_F(name,_ct) const my) { \
M_TUPL3_CONTRACT(my); \
return &(my->M_TUPL3_GET_FIELD a); \
} \
/* Same but uses numerical index for accessing the field (internal) */ \
static inline M_TUPL3_GET_TYPE a * M_C4(m_tupl3_, name, _get_at_, num) \
M_INLINE M_TUPL3_GET_TYPE a * M_C4(m_tupl3_, name, _get_at_, num) \
(M_F(name,_ct) my) { \
return &(my->M_TUPL3_GET_FIELD a); \
} \
@@ -339,7 +341,7 @@ namespace m_lib {
M_MAP2(M_TUPL3_DEFINE_SETTER_FIELD_PROTO, name, __VA_ARGS__)
#define M_TUPL3_DEFINE_SETTER_FIELD_PROTO(name, a) \
static inline void M_C3(name, _set_, M_TUPL3_GET_FIELD a) \
M_INLINE void M_C3(name, _set_, M_TUPL3_GET_FIELD a) \
(M_F(name,_ct) my, M_TUPL3_GET_TYPE a const M_TUPL3_GET_FIELD a) { \
M_TUPL3_CONTRACT(my); \
M_TUPL3_CALL_SET(a, my ->M_TUPL3_GET_FIELD a, M_TUPL3_GET_FIELD a); \
@@ -348,7 +350,7 @@ namespace m_lib {
/* Define the CMP method by calling CMP methods for all params. */
#define M_TUPL3_DEFINE_CMP(name, ...) \
static inline int M_F(name, _cmp)(M_F(name,_ct) const e1 , \
M_INLINE int M_F(name, _cmp)(M_F(name,_ct) const e1 , \
M_F(name,_ct) const e2) { \
int i; \
M_TUPL3_CONTRACT(e1); \
@@ -369,7 +371,7 @@ namespace m_lib {
FIXME: All oplists shall define the CMP operator or at least one?
*/
#define M_TUPL3_DEFINE_CMP_ORDER(name, ...) \
static inline int M_F(name, _cmp_order)(M_F(name,_ct) const e1 , \
M_INLINE int M_F(name, _cmp_order)(M_F(name,_ct) const e1 , \
M_F(name,_ct) const e2, \
const int order[]) { \
int i, r; \
@@ -403,7 +405,7 @@ namespace m_lib {
)
#define M_TUPL3_DEFINE_CMP_FIELD_FUNC(name, field, func_cmp, oplist) \
static inline int M_C3(name, _cmp_, field)(M_F(name,_ct) const e1 , \
M_INLINE int M_C3(name, _cmp_, field)(M_F(name,_ct) const e1 , \
M_F(name,_ct) const e2) { \
M_TUPL3_CONTRACT(e1); \
M_TUPL3_CONTRACT(e2); \
@@ -413,7 +415,7 @@ namespace m_lib {
/* Define a EQUAL method by calling the EQUAL methods for all params */
#define M_TUPL3_DEFINE_EQUAL(name, ...) \
static inline bool M_F(name, _equal_p)(M_F(name,_ct) const e1 , \
M_INLINE bool M_F(name, _equal_p)(M_F(name,_ct) const e1 , \
M_F(name,_ct) const e2) { \
bool b; \
M_TUPL3_CONTRACT(e1); \
@@ -431,7 +433,7 @@ namespace m_lib {
/* Define a HASH method by calling the HASH methods for all params */
#define M_TUPL3_DEFINE_HASH(name, ...) \
static inline size_t M_F(name, _hash)(M_F(name,_ct) const e1) { \
M_INLINE size_t M_F(name, _hash)(M_F(name,_ct) const e1) { \
M_TUPL3_CONTRACT(e1); \
M_HASH_DECL(hash); \
M_MAP(M_TUPL3_DEFINE_HASH_FUNC_P0, __VA_ARGS__) \
@@ -446,7 +448,7 @@ namespace m_lib {
/* Define a GET_STR method by calling the GET_STR methods for all params */
#define M_TUPL3_DEFINE_GET_STR(name, ...) \
static inline void M_F(name, _get_str)(m_string_t str, \
M_INLINE void M_F(name, _get_str)(m_string_t str, \
M_F(name,_ct) const el, \
bool append) { \
bool comma = false; \
@@ -465,7 +467,7 @@ namespace m_lib {
/* Define a OUT_STR method by calling the OUT_STR methods for all params */
#define M_TUPL3_DEFINE_OUT_STR(name, ...) \
static inline void M_F(name, _out_str)(FILE *f, \
M_INLINE void M_F(name, _out_str)(FILE *f, \
M_F(name,_ct) const el) { \
bool comma = false; \
M_TUPL3_CONTRACT(el); \
@@ -483,7 +485,7 @@ namespace m_lib {
/* Define a IN_STR method by calling the IN_STR methods for all params */
#define M_TUPL3_DEFINE_IN_STR(name, ...) \
static inline bool M_F(name, _in_str)(M_F(name,_ct) el, FILE *f) { \
M_INLINE bool M_F(name, _in_str)(M_F(name,_ct) el, FILE *f) { \
bool comma = false; \
M_TUPL3_CONTRACT(el); \
M_ASSERT (f != NULL); \
@@ -506,7 +508,7 @@ namespace m_lib {
/* Define a PARSE_STR method by calling the PARSE_STR methods for all params */
#define M_TUPL3_DEFINE_PARSE_STR(name, ...) \
static inline bool M_F(name, _parse_str)(M_F(name,_ct) el, \
M_INLINE bool M_F(name, _parse_str)(M_F(name,_ct) el, \
const char str[], \
const char **endptr) { \
M_TUPL3_CONTRACT(el); \
@@ -540,7 +542,7 @@ namespace m_lib {
/* Define a OUT_SERIAL method by calling the OUT_SERIAL methods for all params */
#define M_TUPL3_DEFINE_OUT_SERIAL(name, ...) \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _out_serial)(m_serial_write_t f, \
M_F(name,_ct) const el) { \
M_TUPL3_CONTRACT(el); \
@@ -567,7 +569,7 @@ namespace m_lib {
/* Define a IN_SERIAL method by calling the IN_SERIAL methods for all params */
#define M_TUPL3_DEFINE_IN_SERIAL(name, ...) \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _in_serial)(M_F(name,_ct) el, m_serial_read_t f) { \
M_TUPL3_CONTRACT(el); \
M_ASSERT (f != NULL && f->m_interface != NULL); \
@@ -598,9 +600,10 @@ namespace m_lib {
break; \
/* Define a INIT_MOVE method by calling the INIT_MOVE methods for all params */
/* Define a INIT_MOVE method by calling the INIT_MOVE methods for all params
INIT_MOVE cannot fail and cannot throw any exception */
#define M_TUPL3_DEFINE_INIT_MOVE(name, ...) \
static inline void M_F(name, _init_move)(M_F(name,_ct) el, M_F(name,_ct) org) { \
M_INLINE void M_F(name, _init_move)(M_F(name,_ct) el, M_F(name,_ct) org) { \
M_TUPL3_CONTRACT(el); \
M_MAP(M_TUPL3_DEFINE_INIT_MOVE_FUNC , __VA_ARGS__) \
}
@@ -611,7 +614,7 @@ namespace m_lib {
/* Define a MOVE method by calling the MOVE methods for all params */
#define M_TUPL3_DEFINE_MOVE(name, ...) \
static inline void M_F(name, _move)(M_F(name,_ct) el, M_F(name,_ct) org) { \
M_INLINE void M_F(name, _move)(M_F(name,_ct) el, M_F(name,_ct) org) { \
M_TUPL3_CONTRACT(el); \
M_MAP(M_TUPL3_DEFINE_MOVE_FUNC , __VA_ARGS__) \
}
@@ -622,7 +625,7 @@ namespace m_lib {
/* Define a SWAP method by calling the SWAP methods for all params */
#define M_TUPL3_DEFINE_SWAP(name, ...) \
static inline void M_F(name, _swap)(M_F(name,_ct) el1, M_F(name,_ct) el2) { \
M_INLINE void M_F(name, _swap)(M_F(name,_ct) el1, M_F(name,_ct) el2) { \
M_TUPL3_CONTRACT(el1); \
M_TUPL3_CONTRACT(el2); \
M_MAP(M_TUPL3_DEFINE_SWAP_FUNC , __VA_ARGS__) \
@@ -634,7 +637,7 @@ namespace m_lib {
/* Define a RESET method by calling the RESET methods for all params */
#define M_TUPL3_DEFINE_RESET(name, ...) \
static inline void M_F(name, _reset)(M_F(name,_ct) el1) { \
M_INLINE void M_F(name, _reset)(M_F(name,_ct) el1) { \
M_TUPL3_CONTRACT(el1); \
M_MAP(M_TUPL3_DEFINE_RESET_FUNC , __VA_ARGS__) \
} \
@@ -742,9 +745,6 @@ namespace m_lib {
M_IF_METHOD_ALL(MOVE, __VA_ARGS__)(MOVE(M_F(name, _move)),), \
M_IF_METHOD_ALL(SWAP, __VA_ARGS__)(SWAP(M_F(name, _swap)),), \
M_IF_METHOD_ALL(RESET, __VA_ARGS__)(RESET(M_F(name, _reset)),), \
M_IF_METHOD(NEW, M_RET_ARG1(__VA_ARGS__,))(NEW(M_DELAY2(M_GET_NEW) M_RET_ARG1(__VA_ARGS__,)),), \
M_IF_METHOD(REALLOC, M_RET_ARG1(__VA_ARGS__,))(REALLOC(M_DELAY2(M_GET_REALLOC) M_RET_ARG1(__VA_ARGS__,)),), \
M_IF_METHOD(DEL, M_RET_ARG1(__VA_ARGS__,))(DEL(M_DELAY2(M_GET_DEL) M_RET_ARG1(__VA_ARGS__,)),), \
EMPLACE_TYPE( ( M_REDUCE2(M_TUPL3_OPLIST_SUBTYPE, M_ID, name, M_SEQ(1, M_NARGS(__VA_ARGS__))) ) ) \
)
+27 -30
View File
@@ -219,14 +219,14 @@
/* Define the INIT function. Init the variant to empty */
#define M_VAR1ANT_DEFINE_INIT(name, ...) \
static inline void M_F(name, _init)(M_F(name,_ct) my) { \
M_INLINE void M_F(name, _init)(M_F(name,_ct) my) { \
my->type = M_F(name, _EMPTY); \
}
/* Define the INIT_SET function. */
#define M_VAR1ANT_DEFINE_INIT_SET(name, ...) \
static inline void M_F(name, _init_set)(M_F(name,_ct) my , \
M_INLINE void M_F(name, _init_set)(M_F(name,_ct) my , \
M_F(name,_ct) const org) { \
M_VAR1ANT_CONTRACT(name, org); \
my->type = org->type; \
@@ -246,7 +246,7 @@
/* Define the SET function. */
#define M_VAR1ANT_DEFINE_SET(name, ...) \
static inline void M_F(name, _set)(M_F(name,_ct) my , \
M_INLINE void M_F(name, _set)(M_F(name,_ct) my , \
M_F(name,_ct) const org) { \
M_VAR1ANT_CONTRACT(name, my); \
M_VAR1ANT_CONTRACT(name, org); \
@@ -273,7 +273,7 @@
/* Define the CLEAR function. */
#define M_VAR1ANT_DEFINE_CLEAR(name, ...) \
static inline void M_F(name, _clear)(M_F(name,_ct) my) { \
M_INLINE void M_F(name, _clear)(M_F(name,_ct) my) { \
M_VAR1ANT_CONTRACT(name, my); \
switch (my->type) { \
M_MAP2(M_VAR1ANT_DEFINE_CLEAR_FUNC, name, __VA_ARGS__) \
@@ -291,11 +291,11 @@
/* Define the TEST_P function. */
#define M_VAR1ANT_DEFINE_TEST_P(name, ...) \
static inline bool M_F(name, _empty_p)(M_F(name,_ct) const my) { \
M_INLINE bool M_F(name, _empty_p)(M_F(name,_ct) const my) { \
M_VAR1ANT_CONTRACT(name, my); \
return my->type == M_F(name, _EMPTY); \
} \
static inline enum M_F(name, _enum) \
M_INLINE enum M_F(name, _enum) \
M_F(name, _type)(M_F(name,_ct) my) { \
M_VAR1ANT_CONTRACT(name, my); \
return my->type; \
@@ -303,7 +303,7 @@
M_MAP2(M_VAR1ANT_DEFINE_TEST_FUNC, name, __VA_ARGS__)
#define M_VAR1ANT_DEFINE_TEST_FUNC(name, a) \
static inline bool \
M_INLINE bool \
M_C4(name, _, M_VAR1ANT_GET_FIELD a, _p)(M_F(name,_ct) const my) { \
M_VAR1ANT_CONTRACT(name, my); \
return my->type == M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value); \
@@ -315,7 +315,7 @@
M_MAP2(M_VAR1ANT_DEFINE_INIT_FIELD_FUNC, name, __VA_ARGS__)
#define M_VAR1ANT_DEFINE_INIT_FIELD_FUNC(name, a) \
static inline void \
M_INLINE void \
M_C3(name, _init_, M_VAR1ANT_GET_FIELD a)(M_F(name,_ct) my) { \
/* Reinit variable with the given value */ \
my->type = M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value); \
@@ -328,7 +328,7 @@
M_MAP2(M_VAR1ANT_DEFINE_INIT_SETTER_FIELD_FUNC, name, __VA_ARGS__)
#define M_VAR1ANT_DEFINE_INIT_SETTER_FIELD_FUNC(name, a) \
static inline void \
M_INLINE void \
M_C3(name, _init_set_, M_VAR1ANT_GET_FIELD a)(M_F(name,_ct) my, \
M_VAR1ANT_GET_TYPE a const M_VAR1ANT_GET_FIELD a ) { \
my->type = M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value); \
@@ -342,7 +342,7 @@
M_MAP2(M_VAR1ANT_DEFINE_SETTER_FIELD_FUNC, name, __VA_ARGS__)
#define M_VAR1ANT_DEFINE_SETTER_FIELD_FUNC(name, a) \
static inline void \
M_INLINE void \
M_C3(name, _set_, M_VAR1ANT_GET_FIELD a)(M_F(name,_ct) my, \
M_VAR1ANT_GET_TYPE a const M_VAR1ANT_GET_FIELD a ) { \
M_VAR1ANT_CONTRACT(name, my); \
@@ -364,7 +364,7 @@
M_MAP2(M_VAR1ANT_DEFINE_GETTER_FIELD_FUNC, name, __VA_ARGS__)
#define M_VAR1ANT_DEFINE_GETTER_FIELD_FUNC(name, a) \
static inline M_VAR1ANT_GET_TYPE a * \
M_INLINE M_VAR1ANT_GET_TYPE a * \
M_C3(name, _get_, M_VAR1ANT_GET_FIELD a)(M_F(name,_ct) my) { \
M_VAR1ANT_CONTRACT(name, my); \
if (my->type != M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value) ) { \
@@ -373,7 +373,7 @@
return &my -> value . M_VAR1ANT_GET_FIELD a; \
} \
\
static inline M_VAR1ANT_GET_TYPE a const * \
M_INLINE M_VAR1ANT_GET_TYPE a const * \
M_C3(name, _cget_, M_VAR1ANT_GET_FIELD a)(M_F(name,_ct) const my) { \
M_VAR1ANT_CONTRACT(name, my); \
if (my->type != M_C4(name, _, M_VAR1ANT_GET_FIELD a, _value) ) { \
@@ -397,7 +397,7 @@
M_EMPLACE_QUEUE_DEF( (name, M_VAR1ANT_GET_FIELD a), M_F(name,_ct), M_C3(name, _emplace_, M_VAR1ANT_GET_FIELD a), M_VAR1ANT_GET_OPLIST a, M_VAR1ANT_DEFINE_EMPLACE_DEF)
#define M_VAR1ANT_DEFINE_INIT_EMPLACE_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
static inline void \
M_INLINE void \
function_name(name_t my \
M_EMPLACE_LIST_TYPE_VAR(ab, exp_emplace_type) ) \
{ \
@@ -406,7 +406,7 @@ static inline void \
} \
#define M_VAR1ANT_DEFINE_EMPLACE_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
static inline void \
M_INLINE void \
function_name(name_t my \
M_EMPLACE_LIST_TYPE_VAR(ab, exp_emplace_type) ) \
{ \
@@ -418,7 +418,7 @@ static inline void \
/* Define the EQUAL_P function. */
#define M_VAR1ANT_DEFINE_EQUAL(name, ...) \
static inline bool M_F(name, _equal_p)(M_F(name,_ct) const e1 , \
M_INLINE bool M_F(name, _equal_p)(M_F(name,_ct) const e1 , \
M_F(name,_ct) const e2) { \
bool b; \
M_VAR1ANT_CONTRACT(name, e1); \
@@ -442,7 +442,7 @@ static inline void \
/* Define the HASH function. */
#define M_VAR1ANT_DEFINE_HASH(name, ...) \
static inline size_t M_F(name, _hash)(M_F(name,_ct) const e1) { \
M_INLINE size_t M_F(name, _hash)(M_F(name,_ct) const e1) { \
M_VAR1ANT_CONTRACT(name, e1); \
M_HASH_DECL(hash); \
M_HASH_UP (hash, (unsigned int) (e1 -> type)); \
@@ -462,7 +462,7 @@ static inline void \
/* Define the INIT_MOVE function. */
#define M_VAR1ANT_DEFINE_INIT_MOVE(name, ...) \
static inline void \
M_INLINE void \
M_F(name, _init_move)(M_F(name,_ct) el, M_F(name,_ct) org) { \
M_VAR1ANT_CONTRACT(name, org); \
el -> type = org -> type; \
@@ -486,7 +486,7 @@ static inline void \
It can be optimized if both types are the same.
*/
#define M_VAR1ANT_DEFINE_MOVE(name, ...) \
static inline void \
M_INLINE void \
M_F(name, _move)(M_F(name,_ct) el, M_F(name,_ct) org) { \
M_VAR1ANT_CONTRACT(name, el); \
M_VAR1ANT_CONTRACT(name, org); \
@@ -500,7 +500,7 @@ static inline void \
M_MAP2(M_VAR1ANT_DEFINE_MOVER_FUNC, name, __VA_ARGS__)
#define M_VAR1ANT_DEFINE_MOVER_FUNC(name, a) \
static inline void \
M_INLINE void \
M_C3(name, _move_, M_VAR1ANT_GET_FIELD a)(M_F(name,_ct) my, \
M_VAR1ANT_GET_TYPE a M_VAR1ANT_GET_FIELD a ) { \
M_VAR1ANT_CONTRACT(name, my); \
@@ -514,7 +514,7 @@ static inline void \
/* Define the SWAP function */
#define M_VAR1ANT_DEFINE_SWAP(name, ...) \
static inline void \
M_INLINE void \
M_F(name, _swap)(M_F(name,_ct) el1, M_F(name,_ct) el2) { \
M_VAR1ANT_CONTRACT(name, el1); \
M_VAR1ANT_CONTRACT(name, el2); \
@@ -550,7 +550,7 @@ static inline void \
/* Define the GET_STR function */
#define M_VAR1ANT_DEFINE_GET_STR(name, ...) \
static inline void M_F(name, _get_str)(m_string_t str, \
M_INLINE void M_F(name, _get_str)(m_string_t str, \
M_F(name,_ct) const el, \
bool append) { \
M_VAR1ANT_CONTRACT(name, el); \
@@ -574,7 +574,7 @@ static inline void \
/* Define the PARSE_STR function */
#define M_VAR1ANT_DEFINE_PARSE_STR(name, ...) \
static inline bool M_F(name, _parse_str)(M_F(name,_ct) el, \
M_INLINE bool M_F(name, _parse_str)(M_F(name,_ct) el, \
const char str[], \
const char **endp) { \
M_VAR1ANT_CONTRACT(name, el); \
@@ -617,7 +617,7 @@ static inline void \
/* Define the OUT_STR function */
#define M_VAR1ANT_DEFINE_OUT_STR(name, ...) \
static inline void M_F(name, _out_str)(FILE *f, \
M_INLINE void M_F(name, _out_str)(FILE *f, \
M_F(name,_ct) const el) { \
M_VAR1ANT_CONTRACT(name, el); \
M_ASSERT (f != NULL); \
@@ -638,7 +638,7 @@ static inline void \
/* Define the IN_STR function */
#define M_VAR1ANT_DEFINE_IN_STR(name, ...) \
static inline bool M_F(name, _in_str)(M_F(name,_ct) el, \
M_INLINE bool M_F(name, _in_str)(M_F(name,_ct) el, \
FILE *f) { \
M_VAR1ANT_CONTRACT(name, el); \
M_ASSERT (f != NULL); \
@@ -680,7 +680,7 @@ static inline void \
/* Define the OUT_SERIAL function */
#define M_VAR1ANT_DEFINE_OUT_SERIAL(name, ...) \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _out_serial)(m_serial_write_t f, \
M_F(name,_ct) const el) { \
M_VAR1ANT_CONTRACT(name, el); \
@@ -711,7 +711,7 @@ static inline void \
/* Define the IN_SERIAL function */
#define M_VAR1ANT_DEFINE_IN_SERIAL(name, ...) \
static inline m_serial_return_code_t \
M_INLINE m_serial_return_code_t \
M_F(name, _in_serial)(M_F(name,_ct) el, \
m_serial_read_t f) { \
M_VAR1ANT_CONTRACT(name, el); \
@@ -745,7 +745,7 @@ static inline void \
/* Define the RESET function */
#define M_VAR1ANT_DEFINE_RESET_FUNC(name, ...) \
static inline void M_F(name, _reset)(M_F(name,_ct) my) \
M_INLINE void M_F(name, _reset)(M_F(name,_ct) my) \
{ \
M_VAR1ANT_CONTRACT(name, my); \
M_F(name, _clear)(my); \
@@ -787,9 +787,6 @@ static inline void \
M_IF_METHOD_ALL(INIT_MOVE, __VA_ARGS__)(INIT_MOVE(M_F(name, _init_move)),), \
M_IF_METHOD_ALL(INIT_MOVE, __VA_ARGS__)(MOVE(M_F(name, _move)),), \
M_IF_METHOD_ALL(SWAP, __VA_ARGS__)(SWAP(M_F(name, _swap)),), \
M_IF_METHOD(NEW, M_RET_ARG1(__VA_ARGS__,))(NEW(M_DELAY2(M_GET_NEW) M_RET_ARG1(__VA_ARGS__,)),), \
M_IF_METHOD(REALLOC, M_RET_ARG1(__VA_ARGS__,))(REALLOC(M_DELAY2(M_GET_REALLOC) M_RET_ARG1(__VA_ARGS__,)),), \
M_IF_METHOD(DEL, M_RET_ARG1(__VA_ARGS__,))(DEL(M_DELAY2(M_GET_DEL) M_RET_ARG1(__VA_ARGS__,)),), \
)
+21 -21
View File
@@ -188,11 +188,11 @@ typedef struct m_worker_sync_s {
input is (fieldname, type) or (fieldname, type, oplist)
Output shall be : M_OPEXTEND(M_GLOBAL_OPLIST_OR_DEF(type_or_oplist)(), TYPE(type)) / M_OPEXTEND(oplist, TYPE(type))
*/
#define M_WORK3R_SPAWN_EXTEND_P0(...) M_SUFFIX_FUNCTION_BY_NARGS(M_WORK3R_SPAWN_EXTEND_P0, M_ID __VA_ARGS__) __VA_ARGS__
#define M_WORK3R_SPAWN_EXTEND_P0_2(field, type) M_OPEXTEND(M_GLOBAL_OPLIST_OR_DEF(type)(), TYPE(type))
#define M_WORK3R_SPAWN_EXTEND_P0_3(field, type, oplist) M_IF_OPLIST(oplist)(M_WORK3R_SPAWN_EXTEND_P0_3_OK, M_WORK3R_SPAWN_EXTEND_P0_3_KO)(field, type, oplist)
#define M_WORK3R_SPAWN_EXTEND_P0_3_OK(field, type, oplist) M_OPEXTEND(oplist, TYPE(type))
#define M_WORK3R_SPAWN_EXTEND_P0_3_KO(field, type, oplist) \
#define M_WORK3R_SPAWN_EXTEND_P0(...) M_BY_NARGS(M_WORK3R_SPAWN_EXTEND_P0, M_ID __VA_ARGS__) __VA_ARGS__
#define M_WORK3R_SPAWN_EXTEND_P0__2(field, type) M_OPEXTEND(M_GLOBAL_OPLIST_OR_DEF(type)(), TYPE(type))
#define M_WORK3R_SPAWN_EXTEND_P0__3(field, type, oplist) M_IF_OPLIST(oplist)(M_WORK3R_SPAWN_EXTEND_P0__3_OK, M_WORK3R_SPAWN_EXTEND_P0__3_KO)(field, type, oplist)
#define M_WORK3R_SPAWN_EXTEND_P0__3_OK(field, type, oplist) M_OPEXTEND(oplist, TYPE(type))
#define M_WORK3R_SPAWN_EXTEND_P0__3_KO(field, type, oplist) \
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(M_WORKER_SPAWN_EXTEND): the argument is not a valid oplist: " M_MAP(M_AS_STR, oplist))
/* Deferred evaluation for the definition,
@@ -232,7 +232,7 @@ typedef struct m_worker_sync_s {
/* Define the callback */
#define M_WORK3R_SPAWN_EXTEND_DEF_CALLBACK(name, ...) \
static inline void \
M_INLINE void \
M_C3(m_work3r_, name, _clear)(struct M_C3(m_worker_, name, _s) *p) \
{ \
M_MAP3(M_WORK3R_SPAWN_EXTEND_DEF_CALLBACK_CLEAR, data, __VA_ARGS__) \
@@ -240,7 +240,7 @@ typedef struct m_worker_sync_s {
M_MEMORY_DEL(p); \
} \
\
static inline void \
M_INLINE void \
M_C3(m_work3r_, name, _callback)(void *data) \
{ \
struct M_C3(m_worker_, name, _s) *p = (struct M_C3(m_worker_, name, _s) *) data; \
@@ -258,7 +258,7 @@ typedef struct m_worker_sync_s {
/* Define the emplace like spawn method */
#define M_WORK3R_SPAWN_EXTEND_DEF_EMPLACE(name, ...) \
static inline void \
M_INLINE void \
M_C(m_worker_spawn_, name)(m_worker_sync_t block, M_C3(m_worker_, name, _callback_ct) callback, \
M_MAP3_C(M_WORK3R_SPAWN_EXTEND_DEF_EMPLACE_FIELD, data, __VA_ARGS__) \
) \
@@ -299,7 +299,7 @@ typedef struct m_worker_sync_s {
/* Return the number of CPU cores available in the system.
Works for WINDOWS, MACOS, *BSD, LINUX.
*/
static inline int
M_INLINE int
m_work3r_get_cpu_count(void)
{
#if defined(_WIN32)
@@ -332,7 +332,7 @@ m_work3r_get_cpu_count(void)
#endif
/* Execute the registered work order **synchronously** */
static inline void
M_INLINE void
m_work3r_exec(m_work3r_order_ct *w)
{
M_ASSERT (w!= NULL && w->block != NULL);
@@ -356,7 +356,7 @@ m_work3r_exec(m_work3r_order_ct *w)
/* The worker thread main loop*/
static inline void
M_INLINE void
m_work3r_thread(void *arg)
{
// Get back the given argument
@@ -397,7 +397,7 @@ m_work3r_thread(void *arg)
@resetFunc: function to reset the state of a worker between work orders (or NULL if none)
@clearFunc: function to clear the state of a worker before terminaning (or NULL if none)
*/
static inline void
M_INLINE void
m_worker_init(m_worker_t g, int numWorker, unsigned int extraQueue, void (*resetFunc)(void), void (*clearFunc)(void))
{
M_ASSERT (numWorker >= -1);
@@ -437,7 +437,7 @@ m_worker_init(m_worker_t g, int numWorker, unsigned int extraQueue, void (*reset
#define m_worker_init(...) m_worker_init(M_DEFAULT_ARGS(5, (0, 0, NULL, NULL), __VA_ARGS__))
/* Clear of the worker module (destructor) */
static inline void
M_INLINE void
m_worker_clear(m_worker_t g)
{
M_ASSERT (m_work3r_queue_empty_p (g->queue_g));
@@ -462,7 +462,7 @@ m_worker_clear(m_worker_t g)
/* Start a new collaboration between workers of pool 'g'
by defining the synchronization point 'block' */
static inline void
M_INLINE void
m_worker_start(m_worker_sync_t block, m_worker_t g)
{
atomic_init (&block->num_spawn, 0);
@@ -475,7 +475,7 @@ m_worker_start(m_worker_sync_t block, m_worker_t g)
The synchronization point is defined a 'block'
The work order if composed of the function 'func' and its 'data'
*/
static inline void
M_INLINE void
m_worker_spawn(m_worker_sync_t block, void (*func)(void *data), void *data)
{
const m_work3r_order_ct w = { block, data, func M_WORK3R_EXTRA_ORDER };
@@ -493,7 +493,7 @@ m_worker_spawn(m_worker_sync_t block, void (*func)(void *data), void *data)
#if M_USE_WORKER_CLANG_BLOCK
/* Spawn or not the given work order to workers,
or do it ourself if no worker is available */
static inline void
M_INLINE void
m_work3r_spawn_block(m_worker_sync_t block, void (^func)(void *data), void *data)
{
const m_work3r_order_ct w = { block, data, NULL, func };
@@ -512,7 +512,7 @@ m_work3r_spawn_block(m_worker_sync_t block, void (^func)(void *data), void *data
#if M_USE_WORKER_CPP_FUNCTION
/* Spawn or not the given work order to workers,
or do it ourself if no worker is available */
static inline void
M_INLINE void
m_work3r_spawn_function(m_worker_sync_t block, std::function<void(void *data)> func, void *data)
{
const m_work3r_order_ct w = { block, data, NULL, func };
@@ -529,7 +529,7 @@ m_work3r_spawn_function(m_worker_sync_t block, std::function<void(void *data)> f
#endif
/* Test if all work orders of the given synchronization point are finished */
static inline bool
M_INLINE bool
m_worker_sync_p(m_worker_sync_t block)
{
/* If the number of spawns is greated than the number
@@ -539,7 +539,7 @@ m_worker_sync_p(m_worker_sync_t block)
}
/* Wait for all work orders of the given synchronization point to be finished */
static inline void
M_INLINE void
m_worker_sync(m_worker_sync_t block)
{
M_WORK3R_DEBUG ("Waiting for thread terminasion.\n");
@@ -554,7 +554,7 @@ m_worker_sync(m_worker_sync_t block)
}
/* Flush any work order in the queue ourself if some remains.*/
static inline void
M_INLINE void
m_worker_flush(m_worker_t g)
{
m_work3r_order_ct w;
@@ -566,7 +566,7 @@ m_worker_flush(m_worker_t g)
/* Return the number of workers */
static inline size_t
M_INLINE size_t
m_worker_count(m_worker_t g)
{
return g->numWorker_g + 1;
+4 -1
View File
@@ -173,6 +173,9 @@ gene-serial:
gene-try:
$(CC) $(CFLAGS) $(CPPFLAGS) -O3 -march=native -DNDEBUG -S -std=c11 tgen-try.c && less tgen-try.s
gene-tuple:
$(CC) $(CFLAGS) $(CPPFLAGS) -O3 -march=native -DNDEBUG -S -std=c11 tgen-tuple.c && less tgen-tuple.s
#####################################################################################################
# Coverage
#####################################################################################################
@@ -253,7 +256,7 @@ sanitize:
awk ' printit { print } /END_COVERAGE/ { printit=1}' $< > $<.end.c
$(CC) $(CPPFLAGS) -E -DNDEBUG -DWITHIN_COVERAGE $< |grep -v '^#' |awk ' /END_COVERAGE/ { printit=0} printit { print } /START_COVERAGE/ { printit=1 }' |perl -p -e "s/;(?![\"'])/;\n/g ; s/}(?![\"'])/}\n/g ; s/{(?![\"'])/{\n/g" > $<.middle.c
cat $<.first.c $<.middle.c $<.end.c > $<.c
$(CC) $(CPPFLAGS) -fanalyzer -Wall -W -O2 -g $<.c -o $<.exe 2> `basename $< .c`.analyzer $(LDFLAGS)
$(CC) $(CPPFLAGS) -fanalyzer -Wall -W -Wno-analyzer-malloc-leak -O2 -g $<.c -o $<.exe 2> `basename $< .c`.analyzer $(LDFLAGS)
$(RM) $<.first.c $<.end.c $<.middle.c $<.c $<.exe
analyze:
+1 -1
View File
@@ -201,7 +201,7 @@ static void test_rp_basic(void)
{
rpdict1_t dict;
rpdict1_init(dict);
int z;
int z = 0;
rpdict1_set_at(dict, 2, 3);
rpdict1_get_copy(&z, dict, 2);
assert (z == 3);
+28 -2
View File
@@ -570,8 +570,8 @@ static void test_oplist(void)
assert (M_ID (M_GET_NAME A5));
#define A6 (NAME(A6), INIT_WITH(API_1(M_INIT_WITH_NVAR)))
#define A6_init_with_1(x) 1
#define A6_init_with_2(x, y) 0
#define A6_init_with__1(x) 1
#define A6_init_with__2(x, y) 0
assert (M_ID(M_CALL_INIT_WITH (A6, 0)));
assert (M_ID(!M_CALL_INIT_WITH (A6, 0, 0)));
}
@@ -980,6 +980,31 @@ static void test_generic_api(void)
}
static void f_default(int a, int b, int c)
{
assert( a == 1 );
assert( b == 2 );
assert( c == 3 );
}
static void test_default(void)
{
#define f11(...) f_default(M_DEFAULT_ARGS(3, (1, 2, 3), __VA_ARGS__))
f11(1, 2, 3);
f11(1, 2);
f11(1);
#define f12(...) f_default(M_DEFAULT_ARGS(3, (2, 3), __VA_ARGS__))
f12(1, 2, 3);
f12(1, 2);
f12(1);
#define f13(...) f_default(M_DEFAULT_ARGS(3, (3), __VA_ARGS__))
f13(1, 2, 3);
f13(1, 2);
}
int main(void)
{
test_cat();
@@ -1006,6 +1031,7 @@ int main(void)
test_M_CSTR();
test_properties();
test_generic_api();
test_default();
testobj_final_check();
exit(0);
}
+27
View File
@@ -867,9 +867,36 @@ static void test_let_string(void)
}
}
static void test_insert_remove(void)
{
list_uint_t l;
list_uint_init(l);
list_uint_push_back(l, 1);
list_uint_push_back(l, 2);
list_uint_push_back(l, 3);
list_uint_it_t u;
unsigned w= 4;
list_uint_it(u, l);
list_uint_next(u);
assert ( list_uint_size(l) == 3);
list_uint_insert(l, u, w);
assert ( list_uint_size(l) == 4);
list_uint_remove(l, u);
assert ( list_uint_size(l) == 3);
list_uint_insert(l, u, w);
assert ( list_uint_size(l) == 4);
list_uint_remove(l, u);
assert ( list_uint_size(l) == 3);
list_uint_clear(l);
}
int main(void)
{
test_uint();
test_insert_remove();
test_mpz();
test_dual_push1();
test_dual_it1();
+8 -3
View File
@@ -35,8 +35,8 @@
ARRAY_DEF(a2, int)
#define M_OPL_a2_t() ARRAY_OPLIST(a2, M_BASIC_OPLIST)
ARRAY_DEF(l2, int)
#define M_OPL_l2_t() ARRAY_OPLIST(l2, M_BASIC_OPLIST)
LIST_DEF(l2, int)
#define M_OPL_l2_t() LIST_OPLIST(l2, M_BASIC_OPLIST)
DICT_DEF2(d2, string_t, STRING_OPLIST, int, M_BASIC_OPLIST )
#define M_OPL_d2_t() DICT_OPLIST(d2, STRING_OPLIST, M_BASIC_OPLIST)
@@ -54,7 +54,12 @@ TUPLE_DEF2(my,
(vale, a2_t),
(valf, v2_t),
(valg, l2_t),
(valh, d2_t)
(valh, d2_t),
(vali, unsigned char),
(valj, short),
(valk, long long),
(vall, double),
(valm, long double)
)
#define M_OPL_my_t() TUPLE_OPLIST(my, M_BASIC_OPLIST, M_BASIC_OPLIST, M_BASIC_OPLIST, STRING_OPLIST, M_OPL_a2_t(), M_OPL_v2_t(), M_OPL_l2_t(), M_OPL_d2_t() )
+97
View File
@@ -55,6 +55,37 @@ static void test_utf8_basic(void)
string_push_u(s, i);
assert(string_utf8_p(s) == true);
assert(string_length_u(s) == 1);
string_unicode_t j;
bool b = string_pop_u(&j, s);
assert(b);
assert(i== j);
assert(string_utf8_p(s) == true);
assert(string_length_u(s) == 0);
assert(string_size(s) == 0);
string_push_u(s, 'A');
string_push_u(s, i);
size_t len = string_size(s);
string_push_u(s, i);
assert(string_utf8_p(s) == true);
assert(string_length_u(s) == 3);
b = string_pop_u(&j, s);
assert(b);
assert(i== j);
assert(string_utf8_p(s) == true);
assert(string_length_u(s) == 2);
assert(string_size(s) == len);
b = string_pop_u(NULL, s);
assert(b);
assert(string_utf8_p(s) == true);
assert(string_length_u(s) == 1);
assert(string_size(s) == 1);
b = string_pop_u(NULL, s);
assert(b);
assert(string_utf8_p(s) == true);
assert(string_length_u(s) == 0);
assert(string_size(s) == 0);
b = string_pop_u(NULL, s);
assert(!b);
}
}
@@ -141,6 +172,60 @@ static void test_utf8_it(void)
assert(!string_it_equal_p(it, it2));
string_clear(s);
/* Test replacing of unicode */
string_init(s);
for (string_unicode_t u = 1; u < 0x10ffff; u+=3) {
if (u < 0xD800U || u > 0xDFFFU) {
for(int c1 = 0 ; c1 <= 3; c1+=2) {
for(int c2 = 0 ; c2 <= 20; c2+=5) {
const string_unicode_t u_tab[] = { 0, 'B', 300, 45215, 0x10fffe};
for(int c3 = 0 ; c3 < 5; c3++) {
// Generate string
string_reset(s);
for(int j = 0; j < c1; j++)
string_push_back(s, 'A');
string_push_u(s, u);
for(int j = 0; j < c2; j++)
string_push_back(s, 'C');
// Replace iterator in string
string_it(it, s);
for(int j = 0; j < c1; j++)
string_next(it);
assert( string_get_cref(it) == u);
string_it_set_ref(it, s, u_tab[c3]);
if (u_tab[c3] != 0) {
assert( string_get_cref(it) == u_tab[c3]);
}
// Check constructed string
string_it(it, s);
for(int j = 0; j < c1; j++) {
assert( string_get_cref(it) == 'A');
string_next(it);
}
if (u_tab[c3] != 0) {
assert( *string_cref(it) == u_tab[c3]);
string_next(it);
for(int j = 0; j < c2; j++) {
assert( string_get_cref(it) == 'C');
string_next(it);
}
}
assert(string_end_p(it));
}
}
}
}
}
string_clear(s);
}
static void call_string_cat_vprintf(string_t s, const char format[], ...)
{
va_list args;
va_start (args, format);
string_cat_vprintf(s, format, args);
va_end (args);
}
static void test0(void)
@@ -376,15 +461,27 @@ static void test0(void)
string_set_str(s2, "Hello, world! 10 little suns.");
assert(string_equal_p(s1, s2) == true);
string_set_str(s1, "Hello, world!");
call_string_cat_vprintf(s1, " %d little %s.", 10, "suns");
assert(string_equal_p(s1, s2) == true);
string_set_str(s1, "X:");
string_cat_printf(s1, "");
assert(string_equal_str_p(s1, "X:") == true);
string_set_str(s1, "X:");
call_string_cat_vprintf(s1, "");
assert(string_equal_str_p(s1, "X:") == true);
// Illegal format char
string_set_str(s1, "X:");
string_cat_printf(s1, "%#");
assert(string_equal_str_p(s1, "X:") == true);
string_set_str(s1, "X:");
call_string_cat_vprintf(s1, "%#");
assert(string_equal_str_p(s1, "X:") == true);
string_set_str(s1, " \r\n\t HELLO \n\r\t");
string_strim(s1);
assert (string_cmp_str (s1, "HELLO") == 0);
+193
View File
@@ -399,9 +399,24 @@ static void test3(void)
assert(flow ++ == 0);
M_TRY(test1) {
assert(flow ++ == 1);
#ifdef __GNUC__
#if __GNUC__ >= 13
/* Issue with GCC 13. It reports a variable as being not initialized
whereas it is obviously initialized.
See also https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109530
*/
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
#endif
#endif
M_DEFER( assert(flow++ == 3) ) {
assert(flow ++ == 2);
}
#ifdef __GNUC__
#if __GNUC__ >= 13
_Pragma("GCC diagnostic pop")
#endif
#endif
} M_CATCH(test1, M_ERROR_MEMORY) {
assert(0);
}
@@ -441,6 +456,182 @@ static void test3(void)
assert(init == false);
}
typedef struct {
testobj_t o1;
testobj_t o2;
int num;
} struct_t[1];
// Pseudo execution counter
volatile int g_flow = 0;
// Throw execution when g_flow == g_throw
volatile int g_throw = 0;
static void struct_init(struct_t x)
{
M_CHAIN_INIT(o1, testobj_init(x->o1), testobj_clear(x->o1) )
M_CHAIN_INIT(o2, testobj_init(x->o2), testobj_clear(x->o2) ) {
x->num = 0;
if (++g_flow == g_throw) M_THROW(1);
}
}
static void struct_init_set(struct_t x, const struct_t y)
{
M_CHAIN_INIT(o1, testobj_init_set(x->o1, y->o1), testobj_clear(x->o1) ) {
// Throw within the constructor (object partially constructed)
if (++g_flow == g_throw) M_THROW(1);
M_CHAIN_INIT(o2, testobj_init_set(x->o2, y->o2), testobj_clear(x->o2) ) {
x->num = y->num;
if (++g_flow == g_throw) M_THROW(1);
}
}
}
static void struct_initb(struct_t x)
{
M_CHAIN_OBJ(o1, TESTOBJ_OPLIST, x->o1)
M_CHAIN_OBJ(o2, TESTOBJ_OPLIST, x->o2)
M_CHAIN_OBJ(o3, M_BASIC_OPLIST, x->num) {
if (++g_flow == g_throw) M_THROW(1);
}
}
static void struct_init_setb(struct_t x, const struct_t y)
{
M_CHAIN_OBJ(o1, TESTOBJ_OPLIST, x->o1, y->o1) {
// Throw within the constructor (object partially constructed)
if (++g_flow == g_throw) M_THROW(1);
M_CHAIN_OBJ(o2, TESTOBJ_OPLIST, x->o2, y->o2)
M_CHAIN_OBJ(o3, M_BASIC_OPLIST, x->num, y->num) {
if (++g_flow == g_throw) M_THROW(1);
}
}
}
static void struct_clear(struct_t x)
{
testobj_clear(x->o1);
testobj_clear(x->o2);
}
#define M_OPL_struct_t() M_CLASSIC_OPLIST(struct)
static void test4a(void)
{
g_flow = 0;
g_throw = 4;
M_TRY(main) {
assert(++g_flow == 1);
M_LET(a, struct_t) {
assert(++g_flow == 3);
M_LET( (b, a), struct_t) {
assert(false);
}
}
} M_CATCH(main, 0) {
assert(++g_flow == 5);
}
g_flow = 0;
g_throw = 5;
M_TRY(main) {
assert(++g_flow == 1);
M_LET(a, struct_t) {
assert(++g_flow == 3);
M_LET( (b, a), struct_t) {
assert(false);
}
}
} M_CATCH(main, 0) {
assert(++g_flow == 6);
}
g_flow = 0;
g_throw = 2;
M_TRY(main) {
assert(++g_flow == 1);
M_LET(a, struct_t) {
assert(false);
}
} M_CATCH(main, 0) {
assert(++g_flow == 3);
}
g_flow = 0;
g_throw = 0;
M_TRY(main) {
assert(++g_flow == 1);
M_LET(a, struct_t) {
assert(++g_flow == 3);
M_LET( (b, a), struct_t) {
assert(++g_flow == 6);
}
}
} M_CATCH(main, 0) {
assert(false);
}
}
#define STRUCTB_OPLIST \
(INIT(struct_initb), INIT_SET(struct_init_setb), CLEAR(struct_clear), TYPE(struct_t))
static void test4b(void)
{
g_flow = 0;
g_throw = 4;
M_TRY(main) {
assert(++g_flow == 1);
M_LET(a, STRUCTB_OPLIST) {
assert(++g_flow == 3);
M_LET( (b, a), STRUCTB_OPLIST) {
assert(false);
}
}
} M_CATCH(main, 0) {
assert(++g_flow == 5);
}
g_flow = 0;
g_throw = 5;
M_TRY(main) {
assert(++g_flow == 1);
M_LET(a, STRUCTB_OPLIST) {
assert(++g_flow == 3);
M_LET( (b, a), STRUCTB_OPLIST) {
assert(false);
}
}
} M_CATCH(main, 0) {
assert(++g_flow == 6);
}
g_flow = 0;
g_throw = 2;
M_TRY(main) {
assert(++g_flow == 1);
M_LET(a, STRUCTB_OPLIST) {
assert(false);
}
} M_CATCH(main, 0) {
assert(++g_flow == 3);
}
g_flow = 0;
g_throw = 0;
M_TRY(main) {
assert(++g_flow == 1);
M_LET(a, STRUCTB_OPLIST) {
assert(++g_flow == 3);
M_LET( (b, a), STRUCTB_OPLIST) {
assert(++g_flow == 6);
}
}
} M_CATCH(main, 0) {
assert(false);
}
}
static void test_final(void)
{
// Throw without a try block shall raise the M_RAISE_FATAL macro
@@ -457,6 +648,8 @@ int main(void)
test1();
test2();
test3();
test4a();
test4b();
testobj_final_check();
test_final();
exit(1); // Shall not be reached.
+34
View File
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2017-2023, Patrick Pelissier
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* + Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* + Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdint.h>
#include "m-try.h"
#include "m-tuple.h"
#include "m-string.h"
TUPLE_DEF2( tuple, (name, string_t), (surname, string_t), (value, int))
void duplicate(tuple_t dst, const tuple_t src)
{
tuple_init_set(dst, src);
}