diff --git a/README.md b/README.md index 4f7ad834..0a287a07 100644 --- a/README.md +++ b/README.md @@ -544,10 +544,10 @@ 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. 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. 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 always assume that the objects are trivially movable). An INIT\_MOVE operator shall not fail. -* 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). TBC if this operator is really needed as calling CLEAR then INIT\_MOVE is what do all known implementation, and is efficient. A MOVE operator shall not fail. +* 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. 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. 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 always assume that the objects are trivially movable). An INIT\_MOVE operator shall not fail. 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). TBC if this operator is really needed as calling CLEAR then INIT\_MOVE is what do all known implementation, and is efficient. A MOVE operator shall not fail. Moved objects shall use the same memory allocator. * INIT\_WITH(obj, ...): Initialize the object 'obj' with the given variable set of arguments (constructor). Arguments can be of different types. It is up to the method of the objet to decide how to initialize the object based on this initialization array. This operator is used in the M\_LET macro to initialize objects with their given values. -* SWAP(objd, objc): Swap the states of the object 'objc' and the object 'objd'. +* SWAP(objd, objc): Swap the states of the object 'objc' and the object 'objd'. The objects shall use the same allocator. * RESET(obj): Reset the object to its init state (Emptying the object if it is an object). * EMPTY\_P(obj) --> bool: Test if the container object is empty (true) or not. * GET\_SIZE (container) --> size\_t: Return the number of elements in the container object. @@ -583,9 +583,9 @@ Other documented operators are: * SPLICE\_BACK(objd, objs, it\_obj): Move the object of the container 'objs' referenced by the iterator 'it\_obj' to the container 'objd'. Where it is moved is container dependent (it is recommended however to be like the PUSH method). Afterward 'it\_obj' references the next item in 'containerSrc' (as per IT\_NEXT semantics). 'it\_obj' shall not be an end of the container. Both objects shall use the same allocator. * SPLICE\_AT(objd, id\_objd, objs, it\_objs): Move the object referenced by the iterator 'it\_objs' from the container 'objs' just after the object referenced by the iterator 'it\_objd' in the container 'objd'. If 'it\_objd' references an end of the container, it is inserted as the first item of the container (See operator 'IT\_INSERT'). Afterward 'it\_objs' references the next item in the container 'objs', and 'it\_objd' references the moved item in the container 'objd'. 'it\_objs' shall not be an end of the container. Both objects shall use the same allocator. * OUT\_STR(FILE* f, obj): Output 'obj' as a custom formatted string into the FILE stream 'f'. Format is container dependent, but is human readable. -* IN\_STR(obj, FILE* f) --> bool: Set 'obj' to the value associated to the string representation of the object in the FILE stream 'f'. Return true in case of success (in that case the stream 'f' has been advanced to the end of the parsing of the object), false otherwise (in that case, the stream 'f' is in an undetermined position but is likely where the parsing fails). It ensures that an object which is output in a FILE through OUT\_STR, and an object which is read from this FILE through IN\_STR are considered as equal. +* IN\_STR(obj, FILE* f) --> bool: Set 'obj' to the value associated to the formatted string representation of the object in the FILE stream 'f'. Return true in case of success (in that case the stream 'f' has been advanced to the end of the parsing of the object), false otherwise (in that case, the stream 'f' is in an undetermined position but is likely where the parsing fails). It ensures that an object which is output in a FILE through OUT\_STR, and an object which is read from this FILE through IN\_STR are considered as equal. * GET\_STR(string\_t str, obj, bool append): Set 'str' to a formatted string representation of the object 'obj'. Append to the string if 'append' is true, set it otherwise. This operator requires the module m-string. -* PARSE\_STR(obj, const char *str, const char **endp) --> bool: Set 'obj' to the value associated to the formatted string representation of the object in the char stream 'str'. Return true in case of success (in that case if endp is not NULL, it points to the end of the parsing of the object), false otherwise (in that case, if endp is not NULL, it points to an undetermined position but likely to be where the parsing fails). It ensures that an object which is output in a string through GET\_STR, and an object which is read from this string through GET\_STR are considered as equal. +* PARSE\_STR(obj, const char *str, const char **endp) --> bool: Set 'obj' to the value associated to the formatted string representation of the object in the char stream 'str'. Return true in case of success (in that case if endp is not NULL, it points to the end of the parsing of the object), false otherwise (in that case, if endp is not NULL, it points to an undetermined position but likely to be where the parsing fails). It ensures that an object which is written in a string through GET\_STR, and an object which is read from this string through PARSE\_STR are considered as equal. * OUT\_SERIAL(m\_serial\_write\_t *serial, obj) --> m\_serial\_return\_code\_t : Output 'obj' into the configurable serialization stream 'serial' (See #[m-serial-json.h](#m-serial-json) for details and example) as per the serial object semantics. Return M\_SERIAL\_OK\_DONE in case of success, or M\_SERIAL\_FAIL otherwise . * IN\_SERIAL(obj, m\_serial\_read\_t *serial) --> m\_serial\_return\_code\_t: Set 'obj' to its representation from the configurable serialization stream 'serial' (See #[m-serial-json.h](#m-serial-json) for details and example) as per the serial object semantics. M\_SERIAL\_OK\_DONE in case of success (in that case the stream 'serial' has been advanced up to the complete parsing of the object), or M\_SERIAL\_FAIL otherwise (in that case, the stream 'serial' is in an undetermined position but usually around the next characters after the first failure). * OOR\_SET(obj, int\_value): Some containers want to store some information within the uninitialized objects (for example Open Addressing Hash Table). This method stores the integer value 'int\_value' into an uninitialized object 'obj'. It shall be able to differentiate between uninitialized object and initialized object (How is type dependent). The way to store this information is fully object dependent. In general, you use out-of-range value for detecting such values. The object remains uninitialized but sets to of out-of-range value (OOR). int\_value can be 0 or 1.