diff --git a/m-array.h b/m-array.h index d6d2a5e3..c8c5b28c 100644 --- a/m-array.h +++ b/m-array.h @@ -137,6 +137,7 @@ /********************************** INTERNAL *********************************/ /* Define the internal contract of an array */ +//TODO: Can be simplified in release build to speed up compilation speed. #define M_ARRA4_CONTRACT(a) do { \ M_ASSERT (a != NULL); \ M_ASSERT (a->size <= a->alloc); \ @@ -171,9 +172,10 @@ #define M_ARRA4_DEF_P3(name, type, oplist, array_t, it_t) \ M_ARRA4_DEF_TYPE(name, type, oplist, array_t, it_t) \ M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \ + /* TODO: Check if type has not disabled INIT_MOVE */ \ M_ARRA4_DEF_CORE(name, type, oplist, array_t, it_t) \ M_ARRA4_DEF_IO(name, type, oplist, array_t, it_t) \ - M_EMPLACE_QUEUE_DEF(name, array_t, M_F(name, _emplace_back), oplist, M_ARRA4_EMPLACE_DEF) + M_EMPLACE_QUEUE_DEF(name, array_t, _emplace_back, oplist, M_ARRA4_EMPLACE_DEF) /* Define the types */ #define M_ARRA4_DEF_TYPE(name, type, oplist, array_t, it_t) \ @@ -212,21 +214,20 @@ M_ARRA4_CONTRACT(v); \ } \ \ - M_INLINE void \ - M_F(name, _reset)(array_t v) \ + M_P(void, name, _reset, array_t v) \ { \ M_ARRA4_CONTRACT(v); \ + M_ASSERT_POOL(); \ for(size_t i = 0; i < v->size; i++) \ M_CALL_CLEAR(oplist, v->ptr[i]); \ v->size = 0; \ M_ARRA4_CONTRACT(v); \ } \ \ - M_INLINE void \ - M_F(name, _clear)(array_t v) \ + M_P(void, name, _clear, array_t v) \ { \ M_ARRA4_CONTRACT(v); \ - M_F(name, _reset)(v); \ + M_F(name, _reset) M_R(v); \ M_CALL_FREE(oplist, type, v->ptr, v->alloc); \ /* This is so reusing the object implies an assertion failure */ \ v->alloc = 1; \ @@ -234,8 +235,7 @@ } \ \ M_IF_METHOD2(INIT_SET, SET, oplist)( \ - M_INLINE void \ - M_F(name, _set)(array_t d, const array_t s) \ + M_P(void, name, _set, array_t d, const array_t s) \ { \ M_ARRA4_CONTRACT(d); \ M_ARRA4_CONTRACT(s); \ @@ -264,13 +264,12 @@ M_ARRA4_CONTRACT(d); \ } \ \ - M_INLINE void \ - M_F(name, _init_set)(array_t d, const array_t s) \ + M_P(void, name, _init_set, array_t d, const array_t s) \ { \ M_ASSERT (d != s); \ - M_ON_EXCEPTION(M_F(name, _clear)(d) ) { \ + M_ON_EXCEPTION(M_F(name, _clear) M_R(d) ) { \ M_F(name, _init)(d); \ - M_F(name, _set)(d, s); \ + M_F(name, _set) M_R(d, s); \ } \ } \ , /* No SET & INIT_SET */) \ @@ -289,19 +288,18 @@ M_ARRA4_CONTRACT(d); \ } \ \ - M_INLINE void \ - M_F(name, _move)(array_t d, array_t s) \ + M_P(void, name, _move, array_t d, array_t s) \ { \ M_ASSERT (d != s); \ - M_F(name, _clear)(d); \ + M_F(name, _clear) M_R(d); \ M_F(name, _init_move)(d, s); \ } \ \ M_IF_METHOD(SET, oplist)( \ - M_INLINE void \ - M_F(name, _set_at)(array_t v, size_t i, type const x) \ + M_P(void, name, _set_at, array_t v, size_t i, type const x) \ { \ M_ARRA4_CONTRACT(v); \ + M_ASSERT_POOL(); \ M_ASSERT(v->size > 0 && v->ptr != NULL); \ M_ASSERT_INDEX(i, v->size); \ M_CALL_SET(oplist, v->ptr[i], x); \ @@ -317,15 +315,14 @@ return &v->ptr[v->size-1]; \ } \ \ - M_INLINE type * \ - M_F(name, _push_raw)(array_t v) \ + M_P(type *, name, _push_raw, array_t v) \ { \ M_ARRA4_CONTRACT(v); \ if (M_UNLIKELY (v->size >= v->alloc)) { \ M_ASSERT(v->size == v->alloc); \ size_t alloc = M_CALL_INC_ALLOC(oplist, v->alloc); \ if (M_UNLIKELY_NOMEM (alloc <= v->alloc)) { \ - M_MEMORY_FULL(type, alloc); \ + M_MEMORY_FULL(type, -1U); \ return NULL; \ } \ M_ASSERT (alloc > v->size); \ @@ -346,10 +343,9 @@ } \ \ M_IF_METHOD(INIT_SET, oplist)( \ - M_INLINE void \ - M_F(name, _push_back)(array_t v, type const x) \ + M_P(void, name, _push_back, array_t v, type const x) \ { \ - type *data = M_F(name, _push_raw)(v); \ + type *data = M_F(name, _push_raw) M_R(v); \ if (M_UNLIKELY (data == NULL) ) \ return; \ M_IF_EXCEPTION( v->size --); \ @@ -359,10 +355,9 @@ , /* No INIT_SET */ ) \ \ M_IF_METHOD(INIT, oplist)( \ - M_INLINE type * \ - M_F(name, _push_new)(array_t v) \ + M_P(type *, name, _push_new, array_t v) \ { \ - type *data = M_F(name, _push_raw)(v); \ + type *data = M_F(name, _push_raw) M_R(v); \ if (M_UNLIKELY (data == NULL) ) \ return NULL; \ M_IF_EXCEPTION( v->size --); \ @@ -373,11 +368,10 @@ , /* No INIT */ ) \ \ M_IF_AT_LEAST_METHOD(INIT_SET, INIT_MOVE, oplist)( \ - M_INLINE void \ - M_F(name, _push_move)(array_t v, type *x) \ + M_P(void, name, _push_move, array_t v, type *x) \ { \ M_ASSERT (x != NULL); \ - type *data = M_F(name, _push_raw)(v); \ + type *data = M_F(name, _push_raw) M_R(v); \ if (M_UNLIKELY (data == NULL) ) \ return; \ M_DO_INIT_MOVE (oplist, *data, *x); \ @@ -385,8 +379,7 @@ , /* INIT_SET | INIT_MOVE */ ) \ \ M_IF_METHOD(INIT_SET, oplist)( \ - M_INLINE void \ - M_F(name, _push_at)(array_t v, size_t key, type const x) \ + M_P(void, name, _push_at, array_t v, size_t key, type const x) \ { \ M_ARRA4_CONTRACT(v); \ M_ASSERT_INDEX(key, v->size+1); \ @@ -394,7 +387,7 @@ M_ASSERT(v->size == v->alloc); \ size_t alloc = M_CALL_INC_ALLOC(oplist, v->alloc); \ if (M_UNLIKELY_NOMEM (alloc <= v->alloc)) { \ - M_MEMORY_FULL(type, alloc); \ + M_MEMORY_FULL(type, -1U); \ return ; \ } \ M_ASSERT (alloc > v->size); \ @@ -417,8 +410,7 @@ , /* No INIT_SET */ ) \ \ M_IF_METHOD(INIT, oplist)( \ - M_INLINE void \ - M_F(name, _resize)(array_t v, size_t size) \ + M_P(void, name, _resize, array_t v, size_t size) \ { \ M_ARRA4_CONTRACT(v); \ if (v->size > size) { \ @@ -448,8 +440,7 @@ } \ , /* No INIT */ ) \ \ - M_INLINE void \ - M_F(name, _reserve)(array_t v, size_t alloc) \ + M_P(void, name, _reserve, array_t v, size_t alloc) \ { \ M_ARRA4_CONTRACT(v); \ /* NOTE: Reserve below needed size to perform a shrink to fit */ \ @@ -473,8 +464,7 @@ } \ \ M_IF_METHOD(INIT, oplist)( \ - M_INLINE type * \ - M_F(name, _safe_get)(array_t v, size_t idx) \ + M_P(type *, name, _safe_get, array_t v, size_t idx) \ { \ M_ARRA4_CONTRACT(v); \ const size_t size = idx + 1; \ @@ -485,7 +475,7 @@ size_t alloc = M_CALL_INC_ALLOC(oplist, size) ; \ /* In case of overflow of size_t */ \ if (M_UNLIKELY_NOMEM (alloc <= v->alloc)) { \ - M_MEMORY_FULL(type, alloc); \ + M_MEMORY_FULL(type, -1U); \ return NULL; \ } \ type *ptr = M_CALL_REALLOC(oplist, type, v->ptr, v->alloc, alloc); \ @@ -509,10 +499,10 @@ , /* No INIT */) \ \ M_IF_AT_LEAST_METHOD(SET, INIT_MOVE, oplist)( \ - M_INLINE void \ - M_F(name, _pop_back)(type *dest, array_t v) \ + M_P(void, name, _pop_back, type *dest, array_t v) \ { \ M_ARRA4_CONTRACT(v); \ + M_ASSERT_POOL(); \ M_ASSERT (v->ptr != NULL); \ M_ASSERT_INDEX(0, v->size); \ v->size--; \ @@ -526,6 +516,8 @@ , /* SET | INIT_MOVE */ ) \ \ M_IF_AT_LEAST_METHOD(INIT_SET, INIT_MOVE, oplist)( \ + /* FIXME: type has to be trivially movable (imposed by array) ! */ \ + /* FIXME: Really allocation or allocation free? */ \ M_INLINE void \ M_F(name, _pop_move)(type *dest, array_t v) \ { \ @@ -534,19 +526,20 @@ M_ASSERT_INDEX(0, v->size); \ M_ASSERT (dest != NULL); \ v->size--; \ + /* FIXME: M_DO_INIT_MOVE may use INIT_SET so allocator !*/ \ M_DO_INIT_MOVE (oplist, *dest, v->ptr[v->size]); \ M_ARRA4_CONTRACT(v); \ } \ , /* INIT_SET | INIT_MOVE */ ) \ \ + /* TODO: Factorize all INIT dependent methods within the same IF*/ \ M_IF_METHOD(INIT, oplist)( \ - M_INLINE void \ - M_F(name, _pop_until)(array_t v, it_t pos) \ + M_P(void, name, _pop_until, array_t v, it_t pos) \ { \ M_ARRA4_CONTRACT(v); \ M_ASSERT (v == pos->array); \ M_ASSERT_INDEX(pos->index, v->size+1); \ - M_F(name, _resize)(v, pos->index); \ + M_F(name, _resize) M_R(v, pos->index); \ } \ , /* No INIT */ ) \ \ @@ -572,12 +565,13 @@ } \ \ M_IF_AT_LEAST_METHOD(SET, INIT_MOVE, oplist)( \ - M_INLINE void \ - M_F(name, _pop_at)(type *dest, array_t v, size_t i) \ + M_P(void, name, _pop_at, type *dest, array_t v, size_t i) \ { \ M_ARRA4_CONTRACT(v); \ + M_ASSERT_POOL(); \ M_ASSERT (v->size > 0 && v->ptr != NULL); \ M_ASSERT_INDEX(i, v->size); \ + /* FIXME: type is trivially movable */ \ if (dest) \ M_DO_MOVE (oplist, *dest, v->ptr[i]); \ else \ @@ -587,19 +581,17 @@ M_ARRA4_CONTRACT(v); \ } \ \ - M_INLINE bool \ - M_F(name, _erase)(array_t a, size_t i) \ + M_P(bool, name, _erase, array_t a, size_t i) \ { \ M_ARRA4_CONTRACT(a); \ if (i >= a->size) return false; \ - M_F(name, _pop_at)(NULL, a, i); \ + M_F(name, _pop_at) M_R(NULL, a, i); \ return true; \ } \ , /* SET | INIT_MOVE */ ) \ \ M_IF_METHOD(INIT, oplist)( \ - M_INLINE void \ - M_F(name, _insert_v)(array_t v, size_t i, size_t num) \ + M_P(void, name, _insert_v, array_t v, size_t i, size_t num) \ { \ M_ARRA4_CONTRACT(v); \ M_ASSERT_INDEX(i, v->size+1); \ @@ -615,7 +607,7 @@ if (size > v->alloc) { \ size_t alloc = M_CALL_INC_ALLOC(oplist, size) ; \ if (M_UNLIKELY_NOMEM (alloc <= v->alloc)) { \ - M_MEMORY_FULL(type, alloc); \ + M_MEMORY_FULL(type, -1U); \ return ; \ } \ type *ptr = M_CALL_REALLOC(oplist, type, v->ptr, v->alloc, alloc); \ @@ -637,10 +629,10 @@ } \ , /* No INIT */) \ \ - M_INLINE void \ - M_F(name, _remove_v)(array_t v, size_t i, size_t j) \ + M_P(void, name, _remove_v, array_t v, size_t i, size_t j) \ { \ M_ARRA4_CONTRACT(v); \ + M_ASSERT_POOL(); \ M_ASSERT(i < j && v->ptr != NULL); \ M_ASSERT_INDEX(i, v->size); \ M_ASSERT_INDEX(j, v->size+1); \ @@ -797,22 +789,20 @@ } \ \ M_IF_METHOD(INIT_SET, oplist)( \ - M_INLINE void \ - M_F(name, _insert)(array_t a, it_t it, type const x) \ + M_P(void, name, _insert, array_t a, it_t it, type const x) \ { \ M_ASSERT (it != NULL && a == it->array); \ size_t index = M_F(name, _end_p)(it) ? 0 : it->index+1; \ - M_F(name, _push_at)(a, index, x); \ + M_F(name, _push_at)M_R(a, index, x); \ it->index = index; \ } \ , /* End of INIT_SET */ ) \ \ M_IF_AT_LEAST_METHOD(SET, INIT_MOVE, oplist)( \ - M_INLINE void \ - M_F(name, _remove)(array_t a, it_t it) \ + M_P(void, name, _remove, array_t a, it_t it) \ { \ M_ASSERT (it != NULL && a == it->array); \ - M_F(name, _pop_at)(NULL, a, it->index); \ + M_F(name, _pop_at) M_R(NULL, a, it->index); \ /* NOTE: it->index will naturally point to the next element */ \ } \ , /* End of SET | INIT_SET */ ) \ @@ -902,8 +892,7 @@ M_ASSERT (org_tab == tab); \ } \ \ - M_INLINE void \ - M_F(name, _special_stable_sort)(array_t l) \ + M_P(void, name, _special_stable_sort, array_t l) \ { \ if (M_UNLIKELY (l->size < 2)) \ return; \ @@ -953,8 +942,7 @@ } \ , /* no HASH */ ) \ \ - M_INLINE void \ - M_F(name, _splice)(array_t a1, array_t a2) \ + M_P(void, name, _splice, array_t a1, array_t a2) \ { \ M_ARRA4_CONTRACT(a1); \ M_ARRA4_CONTRACT(a2); \ @@ -987,12 +975,10 @@ #define M_ARRA4_DEF_IO(name, type, oplist, array_t, it_t) \ \ M_IF_METHOD(GET_STR, oplist)( \ - M_INLINE void \ - M_F(name, _get_str)(m_string_t str, array_t const array, \ - bool append) \ + M_P(void, name, _get_str, m_string_t str, array_t const array, bool append) \ { \ M_ARRA4_CONTRACT(array); \ - (append ? m_string_cat_cstr : m_string_set_cstr) (str, "["); \ + (append ? m_string_cat_cstr : m_string_set_cstr) M_R(str, "["); \ it_t it; \ for (M_F(name, _it)(it, array) ; \ !M_F(name, _end_p)(it); \ @@ -1000,9 +986,9 @@ type const *item = M_F(name, _cref)(it); \ M_CALL_GET_STR(oplist, str, *item, true); \ if (!M_F(name, _last_p)(it)) \ - m_string_push_back (str, M_GET_SEPARATOR oplist); \ + m_string_push_back M_R(str, M_GET_SEPARATOR oplist); \ } \ - m_string_push_back (str, ']'); \ + m_string_push_back M_R(str, ']'); \ } \ , /* no GET_STR */ ) \ \ @@ -1024,12 +1010,11 @@ , /* no OUT_STR */ ) \ \ M_IF_METHOD2(PARSE_STR, INIT, oplist)( \ - M_INLINE bool \ - M_F(name, _parse_str)(array_t array, const char str[], const char**endp) \ + M_P(bool, 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); \ + M_F(name,_reset)M_R(array); \ int c = *str++; \ if (M_UNLIKELY (c != '[')) { c = 0; goto exit; } \ c = m_core_str_nospace(&str); \ @@ -1041,7 +1026,7 @@ 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); \ + M_F(name, _push_back) M_R(array, item); \ } while (c == M_GET_SEPARATOR oplist); \ } \ exit: \ @@ -1052,12 +1037,11 @@ , /* no PARSE_STR & INIT */ ) \ \ M_IF_METHOD2(IN_STR, INIT, oplist)( \ - M_INLINE bool \ - M_F(name, _in_str)(array_t array, FILE *file) \ + M_P(bool, name, _in_str, array_t array, FILE *file) \ { \ M_ARRA4_CONTRACT(array); \ M_ASSERT (file != NULL); \ - M_F(name,_reset)(array); \ + M_F(name,_reset)M_R(array); \ int c = fgetc(file); \ if (M_UNLIKELY (c != '[')) return false; \ c = fgetc(file); \ @@ -1069,7 +1053,7 @@ 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); \ + M_F(name, _push_back) M_R(array, item); \ } while (c == M_GET_SEPARATOR oplist); \ } \ M_ARRA4_CONTRACT(array); \ @@ -1099,25 +1083,24 @@ , /* no OUT_SERIAL */ ) \ \ M_IF_METHOD2(IN_SERIAL, INIT, oplist)( \ - M_INLINE m_serial_return_code_t \ - M_F(name, _in_serial)(array_t array, m_serial_read_t f) \ + M_P(m_serial_return_code_t, name, _in_serial, array_t array, m_serial_read_t f) \ { \ M_ARRA4_CONTRACT(array); \ M_ASSERT (f != NULL && f->m_interface != NULL); \ m_serial_return_code_t ret; \ m_serial_local_t local; \ size_t estimated_size = 0; \ - M_F(name,_reset)(array); \ + M_F(name,_reset)M_R(array); \ ret = f->m_interface->read_array_start(local, f, &estimated_size); \ if (M_UNLIKELY (ret != M_SERIAL_OK_CONTINUE)) { \ return ret; \ } \ - M_F(name, _reserve)(array, estimated_size); \ + M_F(name, _reserve) M_R(array, estimated_size); \ M_QLET(1, 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); \ + M_F(name, _push_back)M_R(array, item); \ ret = f->m_interface->read_array_next(local, f); \ } while (ret == M_SERIAL_OK_CONTINUE); \ } \ @@ -1128,11 +1111,9 @@ /* Definition of the emplace_back function for arrays */ #define M_ARRA4_EMPLACE_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \ - M_INLINE void \ - function_name(name_t v \ - M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \ + M_P(void, name, function_name, name_t v M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \ { \ - M_F(name, _subtype_ct) *data = M_F(name, _push_raw)(v); \ + M_F(name, _subtype_ct) *data = M_F(name, _push_raw) M_R(v); \ if (M_UNLIKELY (data == NULL) ) \ return; \ M_IF_EXCEPTION( v->size --); \ diff --git a/m-core.h b/m-core.h index 1ef264d5..547b5e4f 100644 --- a/m-core.h +++ b/m-core.h @@ -379,11 +379,13 @@ M_BEGIN_PROTECTED_CODE #endif /* Define allocators for array - * void *M_MEMORY_REALLOC(type, ptr, o, n): Return a pointer to a new array of 'n' object of type 'type' + * void *M_MEMORY_REALLOC(type, ptr, o, n, perm): Return a pointer to a new array of 'n' object of type 'type'. * If ptr is NULL, it creates a new array of type 'type' and size 'n' * If ptr is not null, it reallocates the given array of type 'type' and size 'o' to the new size. * It returns NULL in case of memory allocation failure. * void M_MEMORY_FREE(type, ptr, o): Free the object associated to the array of type 'type' at base 'ptr' of size 'o'. + * By default, old size do nothing. + * Can use local optional named parameter "m_pool" which is defined by the called of the macro if M_USE_POOL is defined. */ #ifndef M_MEMORY_REALLOC #ifdef __cplusplus @@ -409,6 +411,40 @@ M_BEGIN_PROTECTED_CODE #endif +#ifndef M_USE_POOL +// Memory pool parameter not used for memory function. Stub it with 0 as it won't be used (global definition). +# define M_P_EXPAND +# define M_R_EXPAND +# define M_R +# define M_ASSERT_POOL() +#else +// Memory pool parameter is used for function using memory. (local definition to the function). +// Expand to a prototype to a function that may not trigger exception +# define M_P_EXPAND M_USE_POOL m_pool, +# define M_R_EXPAND m_pool , +# define M_R(...) (m_pool, __VA_ARGS__) +# define M_ASSERT_POOL() (void) m_pool +#endif + +// Expand to a prototype of a function that may trigger exception / accept memory context +// TODO: If not M_F, M_INLINE overloaded and no M_P_EXPAND, simplify M_P +// (faster build: 0.54s instead of 0.80s in extreme expanding +# define M_P(rettype, name, suffix, ...) M_INLINE rettype M_F(name, suffix)(M_P_EXPAND __VA_ARGS__) +//#define M_P(rettype, name, suffix, ...) static inline rettype name ## suffix(__VA_ARGS__) + +// Expand to a prototype of a function that may not trigger exception or accept memory context +# define M_N(rettype, name, suffix, ...) M_INLINE rettype M_F(name, suffix)(__VA_ARGS__) + + +// TODO: Add for API special, the support of the POOL special keyword ==> m_pool +// Or document m_pool directly? Can still be overriden later. + +// TODO: Add for all Assertions: M_ASSERT_POOL() +// to avoid warnings about unused parameter m_pool. +// Pb: Also included for functions without the pool parameter! + +// FIXME: Not sense to do it for a shared pointer: it is shared across all memory contexts! + /************************************************************/ /********************* ERROR handling **********************/ /************************************************************/ @@ -440,6 +476,7 @@ M_BEGIN_PROTECTED_CODE * NOTE: Can be overriden by user if it needs to keep finer access * on the assertions. */ +//TODO: If NDEBUG, simply do nothing "no expression", to speed up compilation speed. #ifndef M_ASSERT #define M_ASSERT(expr) assert(expr) #endif @@ -450,6 +487,7 @@ M_BEGIN_PROTECTED_CODE * NOTE: Can be overriden by user if it needs to keep finer access * on the assertions. */ +//TODO: If NDEBUG, simply do nothing "no expression", to speed up compilation speed. #ifndef M_ASSERT_SLOW # if defined(M_USE_ADDITIONAL_CHECKS) && M_USE_ADDITIONAL_CHECKS # define M_ASSERT_SLOW(n) assert(n) @@ -2772,7 +2810,7 @@ M_INLINE char m_core_str_nospace(const char **str) /* Transform a C variable into a m_string_t (needs m-string.h) */ #define M_GET_STRING_ARG(str, x, append) \ - (append ? m_string_cat_printf : m_string_printf) (str, M_PRINTF_FORMAT(x), M_CORE_PRINTF_ARG(x)) + (append ? m_string_cat_printf : m_string_printf) M_R(str, M_PRINTF_FORMAT(x), M_CORE_PRINTF_ARG(x)) /* No use of GET_STR if no inclusion of m-string */ #define M_GET_STR_METHOD_FOR_DEFAULT_TYPE /* */ @@ -3662,6 +3700,14 @@ M_INLINE size_t m_core_cstr_hash(const char str[]) #define M_OPLAPI_5(method, oplist, x, ...) , x = M_DELAY3(method)(oplist, __VA_ARGS__) #define M_OPLAPI_6(method, oplist, x, ...) , M_DELAY3(method)(&x, &__VA_ARGS__) #define M_OPLAPI_7(method, oplist, x, ...) , M_DELAY3(method)(oplist, &x, &__VA_ARGS__) +#define M_OPLAPI_0P(method, oplist, ...) , M_DELAY3(method)(m_pool, __VA_ARGS__) +#define M_OPLAPI_1P(method, oplist, ...) , M_DELAY3(method)(oplist, m_pool, __VA_ARGS__) +#define M_OPLAPI_2P(method, oplist, ...) , M_DELAY3(method)(m_pool, & __VA_ARGS__) +#define M_OPLAPI_3P(method, oplist, ...) , M_DELAY3(method)(oplist, m_pool, &__VA_ARGS__) +#define M_OPLAPI_4P(method, oplist, x, ...) , x = M_DELAY3(method)(m_pool, __VA_ARGS__) +#define M_OPLAPI_5P(method, oplist, x, ...) , x = M_DELAY3(method)(oplist, m_pool, __VA_ARGS__) +#define M_OPLAPI_6P(method, oplist, x, ...) , M_DELAY3(method)(m_pool, &x, &__VA_ARGS__) +#define M_OPLAPI_7P(method, oplist, x, ...) , M_DELAY3(method)(oplist, m_pool, &x, &__VA_ARGS__) /* API transformation support for indirection */ #define M_OPLAPI_INDIRECT_0 M_OPLAPI_ERROR #define M_OPLAPI_INDIRECT_API_0(...) M_OPLAPI_0 @@ -3680,6 +3726,22 @@ M_INLINE size_t m_core_cstr_hash(const char str[]) #define M_OPLAPI_EXTRACT_API_6(...) __VA_ARGS__ #define M_OPLAPI_INDIRECT_API_7(...) M_OPLAPI_7 #define M_OPLAPI_EXTRACT_API_7(...) __VA_ARGS__ +#define M_OPLAPI_INDIRECT_API_0P(...) M_OPLAPI_0P +#define M_OPLAPI_EXTRACT_API_0P(...) __VA_ARGS__ +#define M_OPLAPI_INDIRECT_API_1P(...) M_OPLAPI_1P +#define M_OPLAPI_EXTRACT_API_1P(...) __VA_ARGS__ +#define M_OPLAPI_INDIRECT_API_2P(...) M_OPLAPI_2P +#define M_OPLAPI_EXTRACT_API_2P(...) __VA_ARGS__ +#define M_OPLAPI_INDIRECT_API_3P(...) M_OPLAPI_3P +#define M_OPLAPI_EXTRACT_API_3P(...) __VA_ARGS__ +#define M_OPLAPI_INDIRECT_API_4P(...) M_OPLAPI_4P +#define M_OPLAPI_EXTRACT_API_4P(...) __VA_ARGS__ +#define M_OPLAPI_INDIRECT_API_5P(...) M_OPLAPI_5P +#define M_OPLAPI_EXTRACT_API_5P(...) __VA_ARGS__ +#define M_OPLAPI_INDIRECT_API_6P(...) M_OPLAPI_6P +#define M_OPLAPI_EXTRACT_API_6P(...) __VA_ARGS__ +#define M_OPLAPI_INDIRECT_API_7P(...) M_OPLAPI_7P +#define M_OPLAPI_EXTRACT_API_7P(...) __VA_ARGS__ /* Generic API transformation. @@ -3777,6 +3839,11 @@ M_INLINE size_t m_core_cstr_hash(const char str[]) "The " #operator " operator has no method associated in the given OPLIST."),\ (return_type) 0) +// TODO: Use default INIT_MOVE which assume trivially movable type +// by getting throught API_2 the oplist and the size of the type +// If no type defined and no INIT_MOVE defined, just use sizeof (dst) +// Most types are trivially movable. Can remove macro M_DO_INIT_MOVE to use M_CALL_INIT_MOVE +// If disabled in oplist, M_CALL_INIT_MOVE will generate an error. #define M_NO_DEF_INIT_MOVE(...) M_NO_DEFAULT(INIT_MOVE, void) #define M_NO_DEF_INIT_WITH(...) M_NO_DEFAULT(INIT_WITH, void) #define M_NO_DEF_MOVE(...) M_NO_DEFAULT(MOVE, void) @@ -4150,7 +4217,7 @@ m_core_parse2_enum (const char str[], const char **endptr) #define M_ENUM_IN_SERIAL(oplist, var, serial) \ ( var = (M_GET_TYPE oplist)(true ? m_core_in_serial_enum(serial) : 0), (serial)->tmp.r) #define M_ENUM_GET_STR(str, var, append) \ - ((append ? m_string_cat_printf : m_string_printf) (str, "%lld", (long long) (var) )) + ((append ? m_string_cat_printf : m_string_printf) M_R(str, "%lld", (long long) (var) )) #define M_ENUM_PARSE(oplist, var, str, endptr) \ ( var = (M_GET_TYPE oplist) (true ? m_core_parse1_enum(str) : 0), m_core_parse2_enum(str, endptr)) @@ -4269,6 +4336,8 @@ m_core_parse2_enum (const char str[], const char **endptr) #define M_IPTR(...) ( & __VA_ARGS__ ) /* Perform an INIT_MOVE if present, or emulate it using INIT_SET/CLEAR */ +/* FIXME: Use INIT_MOVE if present or assume trivially movable otherwise? */ +/* A non trivially movable type shall provide an INIT_MOVE method or disable it */ #define M_DO_INIT_MOVE(oplist, dest, src) do { \ M_IF_METHOD(INIT_MOVE, oplist)(M_CALL_INIT_MOVE(oplist, (dest), (src)), \ M_CALL_INIT_SET(oplist, (dest), (src)) ; \ @@ -4527,7 +4596,7 @@ m_core_parse2_enum (const char str[], const char **endptr) 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 diff --git a/m-string.h b/m-string.h index b5db698a..82562c9e 100644 --- a/m-string.h +++ b/m-string.h @@ -281,8 +281,7 @@ m_string_init(m_string_t s) } /* Clear the Dynamic string (destructor) */ -M_INLINE void -m_string_clear(m_string_t v) +M_P(void, m_string, _clear, m_string_t v) { M_STR1NG_CONTRACT(v); if (!m_str1ng_embedded_p(v)) { @@ -301,8 +300,7 @@ M_INLINE m_string_ptr m_str1ng_init_ref(m_string_t v) { m_string_init(v); return and return a heap pointer to the string. The ownership of the data is transferred back to the caller and the returned pointer has to be released by M_MEMORY_FREE. */ -M_INLINE char * -m_string_clear_get_cstr(m_string_t v) +M_P(char *, m_string, _clear_get_cstr, m_string_t v) { M_STR1NG_CONTRACT(v); char *p = v->u.heap.ptr; @@ -368,8 +366,7 @@ m_string_empty_p(const m_string_t v) The string 'v' no longer has a working size field. Return a pointer to the writable string. */ -M_INLINE char * -m_str1ng_fit2size (m_string_t v, size_t size_alloc) +M_P(char *, m_str1ng, _fit2size, m_string_t v, size_t size_alloc) { M_ASSERT_INDEX (0, size_alloc); // Note: this function may be called in context where the contract @@ -422,8 +419,7 @@ m_str1ng_fit2size (m_string_t v, size_t size_alloc) /* Modify the string capacity to be able to handle at least 'alloc' characters (including final nul char). It may reduce the allocation of the string if possible */ -M_INLINE void -m_string_reserve(m_string_t v, size_t alloc) +M_P(void, m_string, _reserve, m_string_t v, size_t alloc) { M_STR1NG_CONTRACT (v); const size_t size = m_string_size(v); @@ -474,13 +470,12 @@ m_string_reserve(m_string_t v, size_t alloc) } /* Set the string to the C string str */ -M_INLINE void -m_string_set_cstr(m_string_t v, const char str[]) +M_P(void, m_string, _set_cstr, m_string_t v, const char str[]) { M_STR1NG_CONTRACT (v); M_ASSERT(str != NULL); size_t size = strlen(str); - char *ptr = m_str1ng_fit2size(v, size+1); + char *ptr = m_str1ng_fit2size M_R(v, size+1); // The memcpy will also copy the final null char of the string memcpy(ptr, str, size+1); m_str1ng_set_size(v, size); @@ -488,14 +483,13 @@ m_string_set_cstr(m_string_t v, const char str[]) } /* Set the string to the n first characters of the C string str */ -M_INLINE void -m_string_set_cstrn(m_string_t v, const char str[], size_t n) +M_P(void, m_string, _set_cstrn, m_string_t v, const char str[], size_t n) { M_STR1NG_CONTRACT (v); M_ASSERT(str != NULL); size_t len = strlen(str); size_t size = M_MIN (len, n); - char *ptr = m_str1ng_fit2size(v, size+1); + char *ptr = m_str1ng_fit2size M_R(v, size+1); // The memcpy will not copy the final null char of the string memcpy(ptr, str, size); // Cannot copy the final null char using memcpy @@ -505,14 +499,13 @@ m_string_set_cstrn(m_string_t v, const char str[], size_t n) } /* Set the string to the other one */ -M_INLINE void -m_string_set (m_string_t v1, const m_string_t v2) +M_P(void, m_string, _set, m_string_t v1, const m_string_t v2) { M_STR1NG_CONTRACT (v1); M_STR1NG_CONTRACT (v2); if (M_LIKELY (v1 != v2)) { const size_t size = m_string_size(v2); - char *ptr = m_str1ng_fit2size(v1, size+1); + char *ptr = m_str1ng_fit2size M_R(v1, size+1); memcpy(ptr, m_string_get_cstr(v2), size+1); m_str1ng_set_size(v1, size); } @@ -520,14 +513,13 @@ m_string_set (m_string_t v1, const m_string_t v2) } /* Set the string to the n first characters of other one */ -M_INLINE void -m_string_set_n(m_string_t v, const m_string_t ref, size_t offset, size_t length) +M_P(void, m_string, _set_n, m_string_t v, const m_string_t ref, size_t offset, size_t length) { M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (ref); M_ASSERT_INDEX (offset, m_string_size(ref) + 1); size_t size = M_MIN (m_string_size(ref) - offset, length); - char *ptr = m_str1ng_fit2size(v, size+1); + char *ptr = m_str1ng_fit2size M_R(v, size+1); // v may be equal to ref, so a memmove is needed instead of a memcpy memmove(ptr, m_string_get_cstr(ref) + offset, size); // Cannot copy the final null char using memcpy @@ -538,26 +530,24 @@ m_string_set_n(m_string_t v, const m_string_t ref, size_t offset, size_t length) /* Initialize the string and set it to the other one (constructor) */ -M_INLINE void -m_string_init_set(m_string_t v1, const m_string_t v2) +M_P(void, m_string, _init_set, m_string_t v1, const m_string_t v2) { // In case of exception, v1 remains initialized, // but without any allocation done. // Therefore it is safe, not to clear v1 on exception. m_string_init(v1); - m_string_set(v1,v2); + m_string_set M_R(v1,v2); } /* Initialize the string and set it to the C string (constructor) */ -M_INLINE void -m_string_init_set_cstr(m_string_t v1, const char str[]) +M_P(void, m_string, _init_set_cstr, m_string_t v1, const char str[]) { // In case of exception, v1 remains initialized, // but without any allocation done. // Therefore it is safe, not to clear v1 on exception. m_string_init(v1); - m_string_set_cstr(v1, str); + m_string_set_cstr M_R(v1, str); } /* Initialize the string, set it to the other one, @@ -591,20 +581,18 @@ m_string_swap(m_string_t v1, m_string_t v2) /* Set the string to the other one, and destroy the other one. (destructor) */ -M_INLINE void -m_string_move(m_string_t v1, m_string_t v2) +M_P(void, m_string, _move, m_string_t v1, m_string_t v2) { - m_string_clear(v1); + m_string_clear M_R(v1); m_string_init_move(v1,v2); } /* Push the byte-character 'c' in the string 'v' */ -M_INLINE void -m_string_push_back (m_string_t v, char c) +M_P(void, m_string, _push_back, m_string_t v, char c) { M_STR1NG_CONTRACT (v); const size_t size = m_string_size(v); - char *ptr = m_str1ng_fit2size(v, size+2); + char *ptr = m_str1ng_fit2size M_R(v, size+2); ptr[size+0] = c; ptr[size+1] = 0; m_str1ng_set_size(v, size+1); @@ -612,29 +600,27 @@ m_string_push_back (m_string_t v, char c) } /* Concatenate the string with the C string */ -M_INLINE void -m_string_cat_cstr(m_string_t v, const char str[]) +M_P(void, m_string, _cat_cstr, m_string_t v, const char str[]) { M_STR1NG_CONTRACT (v); M_ASSERT (str != NULL); const size_t old_size = m_string_size(v); const size_t size = strlen(str); - char *ptr = m_str1ng_fit2size(v, old_size + size + 1); + char *ptr = m_str1ng_fit2size M_R(v, old_size + size + 1); memcpy(&ptr[old_size], str, size + 1); m_str1ng_set_size(v, old_size + size); M_STR1NG_CONTRACT (v); } /* Concatenate the string with the other string */ -M_INLINE void -m_string_cat(m_string_t v, const m_string_t v2) +M_P(void, m_string, _cat, m_string_t v, const m_string_t v2) { M_STR1NG_CONTRACT (v2); M_STR1NG_CONTRACT (v); const size_t size = m_string_size(v2); if (M_LIKELY (size > 0)) { const size_t old_size = m_string_size(v); - char *ptr = m_str1ng_fit2size(v, old_size + size + 1); + char *ptr = m_str1ng_fit2size M_R(v, old_size + size + 1); memcpy(&ptr[old_size], m_string_get_cstr(v2), size); ptr[old_size + size] = 0; m_str1ng_set_size(v, old_size + size); @@ -876,8 +862,7 @@ m_string_mid (m_string_t v, size_t index, size_t size) into the C string str2 from start By default, start is zero. */ -M_INLINE size_t -m_string_replace_cstr (m_string_t v, const char str1[], const char str2[], size_t start) +M_P(size_t, m_string, _replace_cstr, m_string_t v, const char str1[], const char str2[], size_t start) { M_STR1NG_CONTRACT (v); M_ASSERT (str1 != NULL && str2 != NULL); @@ -887,7 +872,7 @@ m_string_replace_cstr (m_string_t v, const char str1[], const char str2[], size_ const size_t str2_l = strlen(str2); const size_t size = m_string_size(v); M_ASSERT(size + 1 + str2_l > str1_l); - char *ptr = m_str1ng_fit2size (v, size + str2_l - str1_l + 1); + char *ptr = m_str1ng_fit2size M_R(v, size + str2_l - str1_l + 1); if (str1_l != str2_l) { memmove(&ptr[i+str2_l], &ptr[i+str1_l], size - i - str1_l + 1); m_str1ng_set_size(v, size + str2_l - str1_l); @@ -902,19 +887,17 @@ m_string_replace_cstr (m_string_t v, const char str1[], const char str2[], size_ into the C string v2 from start By default, start is zero. */ -M_INLINE size_t -m_string_replace (m_string_t v, const m_string_t v1, const m_string_t v2, size_t start) +M_P(size_t, m_string, _replace, m_string_t v, const m_string_t v1, const m_string_t v2, size_t start) { M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v1); M_STR1NG_CONTRACT (v2); - return m_string_replace_cstr(v, m_string_get_cstr(v1), m_string_get_cstr(v2), start); + return m_string_replace_cstr M_R(v, m_string_get_cstr(v1), m_string_get_cstr(v2), start); } /* Replace in the string the sub-string at position 'pos' for 'len' bytes into the C string str2. */ -M_INLINE void -m_string_replace_at (m_string_t v, size_t pos, size_t len, const char str2[]) +M_P(void, m_string, _replace_at, m_string_t v, size_t pos, size_t len, const char str2[]) { M_STR1NG_CONTRACT (v); M_ASSERT(str2 != NULL); @@ -925,7 +908,7 @@ m_string_replace_at (m_string_t v, size_t pos, size_t len, const char str2[]) if (str1_l != str2_l) { // Move bytes from the string M_ASSERT_INDEX (str1_l, size + str2_l + 1); - ptr = m_str1ng_fit2size (v, size + str2_l - str1_l + 1); + ptr = m_str1ng_fit2size M_R(v, size + str2_l - str1_l + 1); M_ASSERT_INDEX (pos + str1_l, size + 1); M_ASSUME (pos + str1_l < size + 1); memmove(&ptr[pos+str2_l], &ptr[pos+str1_l], size - pos - str1_l + 1); @@ -1002,8 +985,7 @@ m_str1ng_strstr_r(char org[], char src[], const char pattern[], size_t pattern_s } /* Replace all occurences of str1 into str2 when strlen(str1) < strlen(str2) */ -M_INLINE void -m_str1ng_replace_all_cstr_1lo2 (m_string_t v, const char str1[], size_t str1len, const char str2[], size_t str2len) +M_P(void, m_str1ng, _replace_all_cstr_1lo2, m_string_t v, const char str1[], size_t str1len, const char str2[], size_t str2len) { M_STR1NG_CONTRACT (v); M_ASSERT(str1len < str2len); @@ -1014,7 +996,7 @@ m_str1ng_replace_all_cstr_1lo2 (m_string_t v, const char str1[], size_t str1len, */ size_t vlen = m_string_size(v); size_t alloc = 1 + vlen / str1len * str2len; - char *org = m_str1ng_fit2size(v, alloc); + char *org = m_str1ng_fit2size M_R(v, alloc); char *src = org + vlen - 1; char *end = org + m_string_capacity(v); char *dst = end; @@ -1044,8 +1026,7 @@ m_str1ng_replace_all_cstr_1lo2 (m_string_t v, const char str1[], size_t str1len, M_STR1NG_CONTRACT (v); } -M_INLINE void -m_string_replace_all_cstr (m_string_t v, const char str1[], const char str2[]) +M_P(void, m_string, _replace_all_cstr, m_string_t v, const char str1[], const char str2[]) { size_t str1_l = strlen(str1); size_t str2_l = strlen(str2); @@ -1053,12 +1034,11 @@ m_string_replace_all_cstr (m_string_t v, const char str1[], const char str2[]) if (str1_l >= str2_l) { m_str1ng_replace_all_cstr_1ge2(v, str1, str1_l, str2, str2_l ); } else { - m_str1ng_replace_all_cstr_1lo2(v, str1, str1_l, str2, str2_l ); + m_str1ng_replace_all_cstr_1lo2 M_R(v, str1, str1_l, str2, str2_l); } } -M_INLINE void -m_string_replace_all (m_string_t v, const m_string_t str1, const m_string_t str2) +M_P(void, m_string, _replace_all, m_string_t v, const m_string_t str1, const m_string_t str2) { size_t str1_l = m_string_size(str1); size_t str2_l = m_string_size(str2); @@ -1067,7 +1047,7 @@ m_string_replace_all (m_string_t v, const m_string_t str1, const m_string_t str2 if (str1_l >= str2_l) { m_str1ng_replace_all_cstr_1ge2(v, m_string_get_cstr(str1), str1_l, m_string_get_cstr(str2), str2_l ); } else { - m_str1ng_replace_all_cstr_1lo2(v, m_string_get_cstr(str1), str1_l, m_string_get_cstr(str2), str2_l ); + m_str1ng_replace_all_cstr_1lo2 M_R(v, m_string_get_cstr(str1), str1_l, m_string_get_cstr(str2), str2_l); } } @@ -1084,12 +1064,11 @@ m_string_replace_all (m_string_t v, const m_string_t str1, const m_string_t str2 # error Unexpected UINT_MAX value (workaround: Define M_USE_FAST_STRING_CONV to 0). #endif -M_INLINE void -m_string_set_ui(m_string_t v, unsigned int n) +M_P(void, m_string, _set_ui, m_string_t v, unsigned int n) { M_STR1NG_CONTRACT (v); char buffer[M_STR1NG_INT_MAX_SIZE]; - m_str1ng_fit2size(v, M_STR1NG_INT_MAX_SIZE+1); + char *d = m_str1ng_fit2size M_R(v, M_STR1NG_INT_MAX_SIZE+1); unsigned i = 0, j = 0; do { // 0123456789 are mandatory in this order as characters, as per C standard. @@ -1097,7 +1076,6 @@ m_string_set_ui(m_string_t v, unsigned int n) n /= 10U; } while (n != 0); M_ASSERT_INDEX(i, M_STR1NG_INT_MAX_SIZE); - char *d = m_str1ng_get_cstr(v); while (i > 0) { d[j++] = buffer[--i]; } @@ -1106,13 +1084,12 @@ m_string_set_ui(m_string_t v, unsigned int n) M_STR1NG_CONTRACT (v); } -M_INLINE void -m_string_set_si(m_string_t v, int n) +M_P(void, m_string, _set_si, m_string_t v, int n) { M_STR1NG_CONTRACT (v); // Compute the maximum number of characters needed for the buffer. char buffer[M_STR1NG_INT_MAX_SIZE]; - m_str1ng_fit2size(v, M_STR1NG_INT_MAX_SIZE+1); + char *d = m_str1ng_fit2size M_R(v, M_STR1NG_INT_MAX_SIZE+1); unsigned i = 0, j = 0; bool neg = n < 0; unsigned n0 = neg ? 0U -(unsigned) n : (unsigned) n; @@ -1122,7 +1099,6 @@ m_string_set_si(m_string_t v, int n) n0 /= 10U; } while (n0 != 0); M_ASSERT_INDEX(i, M_STR1NG_INT_MAX_SIZE); - char *d = m_str1ng_get_cstr(v); if (neg) d[j++] = '-'; while (i > 0) { d[j++] = buffer[--i]; @@ -1136,8 +1112,7 @@ m_string_set_si(m_string_t v, int n) #if M_USE_STDARG /* Format in the string the given printf format */ -M_INLINE int -m_string_vprintf (m_string_t v, const char format[], va_list args) +M_P(int, m_string, _vprintf, m_string_t v, const char format[], va_list args) { M_STR1NG_CONTRACT (v); M_ASSERT (format != NULL); @@ -1153,7 +1128,7 @@ m_string_vprintf (m_string_t v, const char format[], va_list args) M_IF_EXCEPTION( m_str1ng_set_size(v, 0) ); M_IF_EXCEPTION( m_str1ng_get_cstr(v)[0] = 0 ); // We have to realloc our string to fit the needed size - ptr = m_str1ng_fit2size (v, (size_t) size + 1); + ptr = m_str1ng_fit2size M_R(v, (size_t) size + 1); alloc = m_string_capacity(v); // and redo the parsing. size = vsnprintf (ptr, alloc, format, args_org); @@ -1162,7 +1137,7 @@ m_string_vprintf (m_string_t v, const char format[], va_list args) if (M_LIKELY (size >= 0)) { m_str1ng_set_size(v, (size_t) size); } else { - // An error occured during the conversion: Assign an empty string. + // An error occurred during the conversion: Assign an empty string. m_str1ng_set_size(v, 0); ptr[0] = 0; } @@ -1172,21 +1147,20 @@ m_string_vprintf (m_string_t v, const char format[], va_list args) } /* Format in the string the given printf format */ -M_INLINE int -m_string_printf (m_string_t v, const char format[], ...) +// FIXME: BROKEN to add a parameter **after** the '...'! +M_P(int, m_string, _printf, m_string_t v, const char format[], ...) { M_STR1NG_CONTRACT (v); M_ASSERT (format != NULL); va_list args; va_start (args, format); - int ret = m_string_vprintf(v, format, args); + int ret = m_string_vprintf M_R(v, format, args); va_end (args); return ret; } /* Append to the string the formatted string of the given printf format */ -M_INLINE int -m_string_cat_vprintf (m_string_t v, const char format[], va_list args) +M_P(int, m_string, _cat_vprintf, m_string_t v, const char format[], va_list args) { M_STR1NG_CONTRACT (v); M_ASSERT (format != NULL); @@ -1203,7 +1177,7 @@ m_string_cat_vprintf (m_string_t v, const char format[], va_list args) M_IF_EXCEPTION( m_str1ng_set_size(v, old_size) ); M_IF_EXCEPTION( m_str1ng_get_cstr(v)[old_size] = 0 ); // We have to realloc our string to fit the needed size - ptr = m_str1ng_fit2size (v, old_size + (size_t) size + 1); + ptr = m_str1ng_fit2size M_R(v, old_size + (size_t) size + 1); alloc = m_string_capacity(v); // and redo the parsing. size = vsnprintf (&ptr[old_size], alloc - old_size, format, args_org); @@ -1222,28 +1196,26 @@ m_string_cat_vprintf (m_string_t v, const char format[], va_list args) } /* Append to the string the formatted string of the given printf format */ -M_INLINE int -m_string_cat_printf (m_string_t v, const char format[], ...) +//FIXME: +M_P(int, m_string, _cat_printf, m_string_t v, const char format[], ...) { M_STR1NG_CONTRACT (v); M_ASSERT (format != NULL); va_list args; va_start (args, format); - int ret = m_string_cat_vprintf(v, format, args); + int ret = m_string_cat_vprintf M_R(v, format, args); va_end (args); return ret; } #if M_USE_FAST_STRING_CONV == 0 -M_INLINE void -m_string_set_ui(m_string_t v, unsigned int n) +M_P(void, m_string, _set_ui, m_string_t v, unsigned int n) { - m_string_printf(v, "%u", n); + m_string_printf M_R(v, "%u", n); } -M_INLINE void -m_string_set_si(m_string_t v, int n) +M_P(void, m_string, _set_si, m_string_t v, int n) { - m_string_printf(v, "%d", n); + m_string_printf M_R(v, "%d", n); } #endif @@ -1252,12 +1224,11 @@ m_string_set_si(m_string_t v, int n) #if M_USE_STDIO /* Get a line/pure-line/file from the FILE and store it in the string */ -M_INLINE bool -m_string_fgets(m_string_t v, FILE *f, m_string_fgets_t arg) +M_P(bool, m_string, _fgets, m_string_t v, FILE *f, m_string_fgets_t arg) { M_STR1NG_CONTRACT(v); M_ASSERT (f != NULL); - char *ptr = m_str1ng_fit2size (v, 100); + char *ptr = m_str1ng_fit2size M_R(v, 100); size_t size = 0; size_t alloc = m_string_capacity(v); ptr[0] = 0; @@ -1286,7 +1257,7 @@ m_string_fgets(m_string_t v, FILE *f, m_string_fgets_t arg) /* The string buffer is not big enough: increase it and continue reading */ /* v cannot be a full embedded type */ - ptr = m_str1ng_fit2size (v, alloc + alloc/2); + ptr = m_str1ng_fit2size M_R(v, alloc + alloc/2); alloc = m_string_capacity(v); } } @@ -1299,8 +1270,7 @@ m_string_fgets(m_string_t v, FILE *f, m_string_fgets_t arg) Words are supposed to be separated each other by the given list of separator separator shall be a CONSTANT C array. */ -M_INLINE bool -m_string_fget_word (m_string_t v, const char separator[], FILE *f) +M_P(bool, m_string, _fget_word, m_string_t v, const char separator[], FILE *f) { char buffer[128]; char c = 0; @@ -1345,7 +1315,7 @@ m_string_fget_word (m_string_t v, const char separator[], FILE *f) /* Next char is not a separator: continue parsing */ m_str1ng_set_size(v, size); M_IF_EXCEPTION( m_str1ng_get_cstr(v)[size] = 0); - ptr = m_str1ng_fit2size (v, alloc + alloc/2); + ptr = m_str1ng_fit2size M_R(v, alloc + alloc/2); alloc = m_string_capacity(v); M_ASSERT (alloc > size + 1); ptr[size++] = c; @@ -1480,8 +1450,7 @@ m_string_oor_set(m_string_t s, unsigned char n) /* Transform the string 'v2' into a formatted string and set it to (or append in) the string 'v'. */ -M_INLINE void -m_string_get_str(m_string_t v, const m_string_t v2, bool append) +M_P(void, m_string, _get_str, m_string_t v, const m_string_t v2, bool append) { M_STR1NG_CONTRACT(v2); M_STR1NG_CONTRACT(v); @@ -1489,7 +1458,7 @@ m_string_get_str(m_string_t v, const m_string_t v2, bool append) size_t size = append ? m_string_size(v) : 0; size_t v2_size = m_string_size(v2); size_t targetSize = size + v2_size + 3; - char *ptr = m_str1ng_fit2size(v, targetSize); + char *ptr = m_str1ng_fit2size M_R(v, targetSize); ptr[size ++] = '"'; for(size_t i = 0 ; i < v2_size; i++) { const char c = m_string_get_char(v2,i); @@ -1501,7 +1470,7 @@ m_string_get_str(m_string_t v, const m_string_t v2, bool append) case '\r': // Special characters which can be displayed in a short form. m_str1ng_set_size(v, size); - ptr = m_str1ng_fit2size(v, ++targetSize); + ptr = m_str1ng_fit2size M_R(v, ++targetSize); ptr[size ++] = '\\'; // This string acts as a perfect hashmap which supposes an ASCII mapping // and (c^(c>>5)) is the hash function @@ -1512,7 +1481,7 @@ m_string_get_str(m_string_t v, const m_string_t v2, bool append) targetSize += 3; m_str1ng_set_size(v, size); M_IF_EXCEPTION(m_str1ng_get_cstr(v)[size] = 0); - ptr = m_str1ng_fit2size(v, targetSize); + ptr = m_str1ng_fit2size M_R(v, targetSize); int d1 = c & 0x07, d2 = (c>>3) & 0x07, d3 = (c>>6) & 0x07; ptr[size ++] = '\\'; ptr[size ++] = (char) ('0' + d3); @@ -1572,8 +1541,7 @@ m_string_out_str(FILE *f, const m_string_t v) /* Read the formatted string from the FILE and set the converted value in the string 'v'. Return true in case of success */ -M_INLINE bool -m_string_in_str(m_string_t v, FILE *f) +M_P(bool, m_string, _in_str, m_string_t v, FILE *f) { M_STR1NG_CONTRACT(v); M_ASSERT (f != NULL); @@ -1610,7 +1578,7 @@ m_string_in_str(m_string_t v, FILE *f) break; } } - m_string_push_back (v, (char) c); + m_string_push_back M_R(v, (char) c); c = fgetc(f); } return c == '"'; @@ -1623,8 +1591,7 @@ m_string_in_str(m_string_t v, FILE *f) Return true in case of success If endptr is not null, update the position of the parsing. */ -M_INLINE bool -m_string_parse_str(m_string_t v, const char str[], const char **endptr) +M_P(bool, m_string, _parse_str, m_string_t v, const char str[], const char **endptr) { M_STR1NG_CONTRACT(v); M_ASSERT (str != NULL); @@ -1662,7 +1629,7 @@ m_string_parse_str(m_string_t v, const char str[], const char **endptr) break; } } - m_string_push_back (v, (char) c); + m_string_push_back M_R(v, (char) c); c = *str++; } success = (c == '"'); @@ -1678,6 +1645,7 @@ m_string_parse_str(m_string_t v, const char str[], const char **endptr) M_INLINE m_serial_return_code_t m_string_out_serial(m_serial_write_t serial, const m_string_t v) { + //FIXME: What to do for memory context? Can be passed through serial M_ASSERT (serial != NULL && serial->m_interface != NULL); return serial->m_interface->write_string(serial, m_string_get_cstr(v), m_string_size(v) ); } @@ -1955,8 +1923,7 @@ m_string_cref (m_string_it_t it) } /* Update the value referenced by the iterator to the given value */ -M_INLINE void -m_string_it_set_ref(m_string_it_t it, m_string_t s, m_string_unicode_t new_u) +M_P(void, m_string, _it_set_ref, m_string_it_t it, m_string_t s, m_string_unicode_t new_u) { M_STR1NG_IT_CONTRACT(it); M_STR1NG_CONTRACT(s); @@ -1965,7 +1932,7 @@ m_string_it_set_ref(m_string_it_t it, m_string_t s, m_string_unicode_t new_u) M_ASSUME( it->ptr >= ptr); size_t offset = (size_t) (it->ptr - ptr); // Special case if the unicode codepoint is 0 - if (new_u == 0) { + if (M_UNLIKELY(new_u == 0)) { // Null the string m_str1ng_set_size(s, offset); ptr[offset] = 0; @@ -1989,8 +1956,8 @@ m_string_it_set_ref(m_string_it_t it, m_string_t s, m_string_unicode_t new_u) size_t old_u_size = (size_t) (str - it->ptr); // We need to replace old_u by new_u. Both are variable length size_t str_size = m_string_size(s); - if (new_u_size != old_u_size) { - ptr = m_str1ng_fit2size(s, str_size + new_u_size - old_u_size + 1); + if (M_UNLIKELY (new_u_size != old_u_size)) { + ptr = m_str1ng_fit2size M_R(s, str_size + new_u_size - old_u_size + 1); M_ASSUME( str_size+1 > (offset + old_u_size) ); memmove(&ptr[offset+new_u_size], &ptr[offset + old_u_size], str_size+1 - offset - old_u_size); @@ -2004,13 +1971,12 @@ m_string_it_set_ref(m_string_it_t it, m_string_t s, m_string_unicode_t new_u) } /* Push unicode code point into string, encoding it in UTF8 */ -M_INLINE void -m_string_push_u (m_string_t str, m_string_unicode_t u) +M_P(void, m_string, _push_u, m_string_t str, m_string_unicode_t u) { M_STR1NG_CONTRACT(str); char buffer[4+1]; m_str1ng_utf8_encode(buffer, u); - m_string_cat_cstr(str, buffer); + m_string_cat_cstr M_R(str, buffer); } /* Pop last unicode code point into string, encoding it in UTF8 */ @@ -2153,13 +2119,22 @@ namespace m_lib { m_lib::m_aligned_string(s).string #endif +#ifdef M_USE_POOL /* Initialize and set a string to the given formatted value. */ +#define m_string_init_printf(pool, v, ...) \ + (m_string_printf ( pool, m_str1ng_init_ref(v), __VA_ARGS__) ) + +/* Initialize and set a string to the given formatted value. */ +#define m_string_init_vprintf(pool, v, format, args) \ + (m_string_vprintf ( pool, m_str1ng_init_ref(v), format, args) ) +#else #define m_string_init_printf(v, ...) \ (m_string_printf ( m_str1ng_init_ref(v), __VA_ARGS__) ) /* Initialize and set a string to the given formatted value. */ #define m_string_init_vprintf(v, format, args) \ (m_string_vprintf ( m_str1ng_init_ref(v), format, args) ) +#endif /* Initialize a string with the given list of arguments. Check if it is a formatted input or not by counting the number of arguments. @@ -2169,10 +2144,10 @@ namespace m_lib { C string and string. */ #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) #define M_STR1NG_INIT_WITH(v, ...) \ - M_IF_NARGS_EQ1(__VA_ARGS__)(m_string_init_set, m_string_init_printf)(v, __VA_ARGS__) + M_IF_NARGS_EQ1(__VA_ARGS__)(m_string_init_set, m_string_init_printf)M_R(v, __VA_ARGS__) #else #define M_STR1NG_INIT_WITH(v, ...) \ - M_IF_NARGS_EQ1(__VA_ARGS__)(m_string_init_set_cstr, m_string_init_printf)(v, __VA_ARGS__) + M_IF_NARGS_EQ1(__VA_ARGS__)(m_string_init_set_cstr, m_string_init_printf)M_R(v, __VA_ARGS__) #endif /* Define the OPLIST of a STRING */ @@ -2201,6 +2176,31 @@ namespace m_lib { ,EMPLACE_TYPE(const char*) \ ) +#define M_STRING_POOL_OPLIST \ + (INIT(m_string_init),INIT_SET(API_0P(m_string_init_set)), SET(API_0P(m_string_set)), \ + INIT_WITH(M_STR1NG_INIT_WITH), \ + INIT_MOVE(m_string_init_move), MOVE(API_0P(m_string_move)), \ + SWAP(m_string_swap), RESET(m_string_reset), \ + EMPTY_P(m_string_empty_p), \ + CLEAR(API_0P(m_string_clear)), HASH(m_string_hash), EQUAL(m_string_equal_p), \ + CMP(m_string_cmp), TYPE(m_string_t), GENTYPE(struct m_string_s*), \ + PARSE_STR(API_0P(m_string_parse_str)), GET_STR(API_0P(m_string_get_str)), \ + OUT_STR(m_string_out_str), IN_STR(API_0P(m_string_in_str)), \ + OUT_SERIAL(m_string_out_serial), IN_SERIAL(m_string_in_serial), \ + EXT_ALGO(M_STR1NG_SPLIT), \ + OOR_EQUAL(m_string_oor_equal_p), OOR_SET(m_string_oor_set) \ + ,SUBTYPE(m_string_unicode_t) \ + ,IT_TYPE(m_string_it_t) \ + ,IT_FIRST(m_string_it) \ + ,IT_END(m_string_it_end) \ + ,IT_SET(m_string_it_set) \ + ,IT_END_P(m_string_end_p) \ + ,IT_EQUAL_P(m_string_it_equal_p) \ + ,IT_NEXT(m_string_next) \ + ,IT_CREF(m_string_cref), PUSH(m_string_push_u) \ + ,EMPLACE_TYPE(const char*) \ + ) + /* Register the OPLIST as a global one */ #define M_OPL_m_string_t() M_STRING_OPLIST @@ -2274,10 +2274,28 @@ namespace m_lib { )(a,b,c) /* Init & Set the string a to the string (or C string) b (constructor) */ +#ifdef M_USE_POOL +#define m_string_init_set(p, a,b) \ + _Generic((b)+0, \ + char*: m_string_init_set_cstr, \ + const char *: m_string_init_set_cstr, \ + default : m_string_init_set \ + )(p,a,b) +#else #define m_string_init_set(a,b) M_STR1NG_SELECT2(m_string_init_set, m_string_init_set_cstr, a, b) +#endif /* Set the string a to the string (or C string) b */ +#ifdef M_USE_POOL +#define m_string_set(p, a,b) \ + _Generic((b)+0, \ + char*: m_string_set_cstr, \ + const char *: m_string_set_cstr, \ + default : m_string_set \ + )(p,a,b) +#else #define m_string_set(a,b) M_STR1NG_SELECT2(m_string_set, m_string_set_cstr, a, b) +#endif /* Concatenate the string (or C string) b to the string a */ #define m_string_cat(a,b) M_STR1NG_SELECT2(m_string_cat, m_string_cat_cstr, a, b)