Port ARRAY & STRING to new memory model with memory context support

This commit is contained in:
Patrick Pelissier committed 2025-05-07 21:02:23 +02:00
1 parent 37b2f4d2ac
commit 3f8c30e592
3 files changed
+269 -201

No files matched your search

+68 -87
View File
@@ -137,6 +137,7 @@
/********************************** INTERNAL *********************************/ /********************************** INTERNAL *********************************/
/* Define the internal contract of an array */ /* 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 { \ #define M_ARRA4_CONTRACT(a) do { \
M_ASSERT (a != NULL); \ M_ASSERT (a != NULL); \
M_ASSERT (a->size <= a->alloc); \ M_ASSERT (a->size <= a->alloc); \
@@ -171,9 +172,10 @@
#define M_ARRA4_DEF_P3(name, type, oplist, array_t, it_t) \ #define M_ARRA4_DEF_P3(name, type, oplist, array_t, it_t) \
M_ARRA4_DEF_TYPE(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) \ 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_CORE(name, type, oplist, array_t, it_t) \
M_ARRA4_DEF_IO(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 the types */
#define M_ARRA4_DEF_TYPE(name, type, oplist, array_t, it_t) \ #define M_ARRA4_DEF_TYPE(name, type, oplist, array_t, it_t) \
@@ -212,21 +214,20 @@
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
} \ } \
\ \
M_INLINE void \ M_P(void, name, _reset, array_t v) \
M_F(name, _reset)(array_t v) \
{ \ { \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
M_ASSERT_POOL(); \
for(size_t i = 0; i < v->size; i++) \ for(size_t i = 0; i < v->size; i++) \
M_CALL_CLEAR(oplist, v->ptr[i]); \ M_CALL_CLEAR(oplist, v->ptr[i]); \
v->size = 0; \ v->size = 0; \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
} \ } \
\ \
M_INLINE void \ M_P(void, name, _clear, array_t v) \
M_F(name, _clear)(array_t v) \
{ \ { \
M_ARRA4_CONTRACT(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); \ M_CALL_FREE(oplist, type, v->ptr, v->alloc); \
/* This is so reusing the object implies an assertion failure */ \ /* This is so reusing the object implies an assertion failure */ \
v->alloc = 1; \ v->alloc = 1; \
@@ -234,8 +235,7 @@
} \ } \
\ \
M_IF_METHOD2(INIT_SET, SET, oplist)( \ M_IF_METHOD2(INIT_SET, SET, oplist)( \
M_INLINE void \ M_P(void, name, _set, array_t d, const array_t s) \
M_F(name, _set)(array_t d, const array_t s) \
{ \ { \
M_ARRA4_CONTRACT(d); \ M_ARRA4_CONTRACT(d); \
M_ARRA4_CONTRACT(s); \ M_ARRA4_CONTRACT(s); \
@@ -264,13 +264,12 @@
M_ARRA4_CONTRACT(d); \ M_ARRA4_CONTRACT(d); \
} \ } \
\ \
M_INLINE void \ M_P(void, name, _init_set, array_t d, const array_t s) \
M_F(name, _init_set)(array_t d, const array_t s) \
{ \ { \
M_ASSERT (d != 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, _init)(d); \
M_F(name, _set)(d, s); \ M_F(name, _set) M_R(d, s); \
} \ } \
} \ } \
, /* No SET & INIT_SET */) \ , /* No SET & INIT_SET */) \
@@ -289,19 +288,18 @@
M_ARRA4_CONTRACT(d); \ M_ARRA4_CONTRACT(d); \
} \ } \
\ \
M_INLINE void \ M_P(void, name, _move, array_t d, array_t s) \
M_F(name, _move)(array_t d, array_t s) \
{ \ { \
M_ASSERT (d != 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_F(name, _init_move)(d, s); \
} \ } \
\ \
M_IF_METHOD(SET, oplist)( \ M_IF_METHOD(SET, oplist)( \
M_INLINE void \ M_P(void, name, _set_at, array_t v, size_t i, type const x) \
M_F(name, _set_at)(array_t v, size_t i, type const x) \
{ \ { \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
M_ASSERT_POOL(); \
M_ASSERT(v->size > 0 && v->ptr != NULL); \ M_ASSERT(v->size > 0 && v->ptr != NULL); \
M_ASSERT_INDEX(i, v->size); \ M_ASSERT_INDEX(i, v->size); \
M_CALL_SET(oplist, v->ptr[i], x); \ M_CALL_SET(oplist, v->ptr[i], x); \
@@ -317,15 +315,14 @@
return &v->ptr[v->size-1]; \ return &v->ptr[v->size-1]; \
} \ } \
\ \
M_INLINE type * \ M_P(type *, name, _push_raw, array_t v) \
M_F(name, _push_raw)(array_t v) \
{ \ { \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
if (M_UNLIKELY (v->size >= v->alloc)) { \ if (M_UNLIKELY (v->size >= v->alloc)) { \
M_ASSERT(v->size == v->alloc); \ M_ASSERT(v->size == v->alloc); \
size_t alloc = M_CALL_INC_ALLOC(oplist, v->alloc); \ size_t alloc = M_CALL_INC_ALLOC(oplist, v->alloc); \
if (M_UNLIKELY_NOMEM (alloc <= v->alloc)) { \ if (M_UNLIKELY_NOMEM (alloc <= v->alloc)) { \
M_MEMORY_FULL(type, alloc); \ M_MEMORY_FULL(type, -1U); \
return NULL; \ return NULL; \
} \ } \
M_ASSERT (alloc > v->size); \ M_ASSERT (alloc > v->size); \
@@ -346,10 +343,9 @@
} \ } \
\ \
M_IF_METHOD(INIT_SET, oplist)( \ M_IF_METHOD(INIT_SET, oplist)( \
M_INLINE void \ M_P(void, name, _push_back, array_t v, type const x) \
M_F(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) ) \ if (M_UNLIKELY (data == NULL) ) \
return; \ return; \
M_IF_EXCEPTION( v->size --); \ M_IF_EXCEPTION( v->size --); \
@@ -359,10 +355,9 @@
, /* No INIT_SET */ ) \ , /* No INIT_SET */ ) \
\ \
M_IF_METHOD(INIT, oplist)( \ M_IF_METHOD(INIT, oplist)( \
M_INLINE type * \ M_P(type *, name, _push_new, array_t v) \
M_F(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) ) \ if (M_UNLIKELY (data == NULL) ) \
return NULL; \ return NULL; \
M_IF_EXCEPTION( v->size --); \ M_IF_EXCEPTION( v->size --); \
@@ -373,11 +368,10 @@
, /* No INIT */ ) \ , /* No INIT */ ) \
\ \
M_IF_AT_LEAST_METHOD(INIT_SET, INIT_MOVE, oplist)( \ M_IF_AT_LEAST_METHOD(INIT_SET, INIT_MOVE, oplist)( \
M_INLINE void \ M_P(void, name, _push_move, array_t v, type *x) \
M_F(name, _push_move)(array_t v, type *x) \
{ \ { \
M_ASSERT (x != NULL); \ 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) ) \ if (M_UNLIKELY (data == NULL) ) \
return; \ return; \
M_DO_INIT_MOVE (oplist, *data, *x); \ M_DO_INIT_MOVE (oplist, *data, *x); \
@@ -385,8 +379,7 @@
, /* INIT_SET | INIT_MOVE */ ) \ , /* INIT_SET | INIT_MOVE */ ) \
\ \
M_IF_METHOD(INIT_SET, oplist)( \ M_IF_METHOD(INIT_SET, oplist)( \
M_INLINE void \ M_P(void, name, _push_at, array_t v, size_t key, type const x) \
M_F(name, _push_at)(array_t v, size_t key, type const x) \
{ \ { \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
M_ASSERT_INDEX(key, v->size+1); \ M_ASSERT_INDEX(key, v->size+1); \
@@ -394,7 +387,7 @@
M_ASSERT(v->size == v->alloc); \ M_ASSERT(v->size == v->alloc); \
size_t alloc = M_CALL_INC_ALLOC(oplist, v->alloc); \ size_t alloc = M_CALL_INC_ALLOC(oplist, v->alloc); \
if (M_UNLIKELY_NOMEM (alloc <= v->alloc)) { \ if (M_UNLIKELY_NOMEM (alloc <= v->alloc)) { \
M_MEMORY_FULL(type, alloc); \ M_MEMORY_FULL(type, -1U); \
return ; \ return ; \
} \ } \
M_ASSERT (alloc > v->size); \ M_ASSERT (alloc > v->size); \
@@ -417,8 +410,7 @@
, /* No INIT_SET */ ) \ , /* No INIT_SET */ ) \
\ \
M_IF_METHOD(INIT, oplist)( \ M_IF_METHOD(INIT, oplist)( \
M_INLINE void \ M_P(void, name, _resize, array_t v, size_t size) \
M_F(name, _resize)(array_t v, size_t size) \
{ \ { \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
if (v->size > size) { \ if (v->size > size) { \
@@ -448,8 +440,7 @@
} \ } \
, /* No INIT */ ) \ , /* No INIT */ ) \
\ \
M_INLINE void \ M_P(void, name, _reserve, array_t v, size_t alloc) \
M_F(name, _reserve)(array_t v, size_t alloc) \
{ \ { \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
/* NOTE: Reserve below needed size to perform a shrink to fit */ \ /* NOTE: Reserve below needed size to perform a shrink to fit */ \
@@ -473,8 +464,7 @@
} \ } \
\ \
M_IF_METHOD(INIT, oplist)( \ M_IF_METHOD(INIT, oplist)( \
M_INLINE type * \ M_P(type *, name, _safe_get, array_t v, size_t idx) \
M_F(name, _safe_get)(array_t v, size_t idx) \
{ \ { \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
const size_t size = idx + 1; \ const size_t size = idx + 1; \
@@ -485,7 +475,7 @@
size_t alloc = M_CALL_INC_ALLOC(oplist, size) ; \ size_t alloc = M_CALL_INC_ALLOC(oplist, size) ; \
/* In case of overflow of size_t */ \ /* In case of overflow of size_t */ \
if (M_UNLIKELY_NOMEM (alloc <= v->alloc)) { \ if (M_UNLIKELY_NOMEM (alloc <= v->alloc)) { \
M_MEMORY_FULL(type, alloc); \ M_MEMORY_FULL(type, -1U); \
return NULL; \ return NULL; \
} \ } \
type *ptr = M_CALL_REALLOC(oplist, type, v->ptr, v->alloc, alloc); \ type *ptr = M_CALL_REALLOC(oplist, type, v->ptr, v->alloc, alloc); \
@@ -509,10 +499,10 @@
, /* No INIT */) \ , /* No INIT */) \
\ \
M_IF_AT_LEAST_METHOD(SET, INIT_MOVE, oplist)( \ M_IF_AT_LEAST_METHOD(SET, INIT_MOVE, oplist)( \
M_INLINE void \ M_P(void, name, _pop_back, type *dest, array_t v) \
M_F(name, _pop_back)(type *dest, array_t v) \
{ \ { \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
M_ASSERT_POOL(); \
M_ASSERT (v->ptr != NULL); \ M_ASSERT (v->ptr != NULL); \
M_ASSERT_INDEX(0, v->size); \ M_ASSERT_INDEX(0, v->size); \
v->size--; \ v->size--; \
@@ -526,6 +516,8 @@
, /* SET | INIT_MOVE */ ) \ , /* SET | INIT_MOVE */ ) \
\ \
M_IF_AT_LEAST_METHOD(INIT_SET, INIT_MOVE, oplist)( \ 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_INLINE void \
M_F(name, _pop_move)(type *dest, array_t v) \ M_F(name, _pop_move)(type *dest, array_t v) \
{ \ { \
@@ -534,19 +526,20 @@
M_ASSERT_INDEX(0, v->size); \ M_ASSERT_INDEX(0, v->size); \
M_ASSERT (dest != NULL); \ M_ASSERT (dest != NULL); \
v->size--; \ v->size--; \
/* FIXME: M_DO_INIT_MOVE may use INIT_SET so allocator !*/ \
M_DO_INIT_MOVE (oplist, *dest, v->ptr[v->size]); \ M_DO_INIT_MOVE (oplist, *dest, v->ptr[v->size]); \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
} \ } \
, /* INIT_SET | INIT_MOVE */ ) \ , /* INIT_SET | INIT_MOVE */ ) \
\ \
/* TODO: Factorize all INIT dependent methods within the same IF*/ \
M_IF_METHOD(INIT, oplist)( \ M_IF_METHOD(INIT, oplist)( \
M_INLINE void \ M_P(void, name, _pop_until, array_t v, it_t pos) \
M_F(name, _pop_until)(array_t v, it_t pos) \
{ \ { \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
M_ASSERT (v == pos->array); \ M_ASSERT (v == pos->array); \
M_ASSERT_INDEX(pos->index, v->size+1); \ 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 */ ) \ , /* No INIT */ ) \
\ \
@@ -572,12 +565,13 @@
} \ } \
\ \
M_IF_AT_LEAST_METHOD(SET, INIT_MOVE, oplist)( \ M_IF_AT_LEAST_METHOD(SET, INIT_MOVE, oplist)( \
M_INLINE void \ M_P(void, name, _pop_at, type *dest, array_t v, size_t i) \
M_F(name, _pop_at)(type *dest, array_t v, size_t i) \
{ \ { \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
M_ASSERT_POOL(); \
M_ASSERT (v->size > 0 && v->ptr != NULL); \ M_ASSERT (v->size > 0 && v->ptr != NULL); \
M_ASSERT_INDEX(i, v->size); \ M_ASSERT_INDEX(i, v->size); \
/* FIXME: type is trivially movable */ \
if (dest) \ if (dest) \
M_DO_MOVE (oplist, *dest, v->ptr[i]); \ M_DO_MOVE (oplist, *dest, v->ptr[i]); \
else \ else \
@@ -587,19 +581,17 @@
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
} \ } \
\ \
M_INLINE bool \ M_P(bool, name, _erase, array_t a, size_t i) \
M_F(name, _erase)(array_t a, size_t i) \
{ \ { \
M_ARRA4_CONTRACT(a); \ M_ARRA4_CONTRACT(a); \
if (i >= a->size) return false; \ 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; \ return true; \
} \ } \
, /* SET | INIT_MOVE */ ) \ , /* SET | INIT_MOVE */ ) \
\ \
M_IF_METHOD(INIT, oplist)( \ M_IF_METHOD(INIT, oplist)( \
M_INLINE void \ M_P(void, name, _insert_v, array_t v, size_t i, size_t num) \
M_F(name, _insert_v)(array_t v, size_t i, size_t num) \
{ \ { \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
M_ASSERT_INDEX(i, v->size+1); \ M_ASSERT_INDEX(i, v->size+1); \
@@ -615,7 +607,7 @@
if (size > v->alloc) { \ if (size > v->alloc) { \
size_t alloc = M_CALL_INC_ALLOC(oplist, size) ; \ size_t alloc = M_CALL_INC_ALLOC(oplist, size) ; \
if (M_UNLIKELY_NOMEM (alloc <= v->alloc)) { \ if (M_UNLIKELY_NOMEM (alloc <= v->alloc)) { \
M_MEMORY_FULL(type, alloc); \ M_MEMORY_FULL(type, -1U); \
return ; \ return ; \
} \ } \
type *ptr = M_CALL_REALLOC(oplist, type, v->ptr, v->alloc, alloc); \ type *ptr = M_CALL_REALLOC(oplist, type, v->ptr, v->alloc, alloc); \
@@ -637,10 +629,10 @@
} \ } \
, /* No INIT */) \ , /* No INIT */) \
\ \
M_INLINE void \ M_P(void, name, _remove_v, array_t v, size_t i, size_t j) \
M_F(name, _remove_v)(array_t v, size_t i, size_t j) \
{ \ { \
M_ARRA4_CONTRACT(v); \ M_ARRA4_CONTRACT(v); \
M_ASSERT_POOL(); \
M_ASSERT(i < j && v->ptr != NULL); \ M_ASSERT(i < j && v->ptr != NULL); \
M_ASSERT_INDEX(i, v->size); \ M_ASSERT_INDEX(i, v->size); \
M_ASSERT_INDEX(j, v->size+1); \ M_ASSERT_INDEX(j, v->size+1); \
@@ -797,22 +789,20 @@
} \ } \
\ \
M_IF_METHOD(INIT_SET, oplist)( \ M_IF_METHOD(INIT_SET, oplist)( \
M_INLINE void \ M_P(void, name, _insert, array_t a, it_t it, type const x) \
M_F(name, _insert)(array_t a, it_t it, type const x) \
{ \ { \
M_ASSERT (it != NULL && a == it->array); \ M_ASSERT (it != NULL && a == it->array); \
size_t index = M_F(name, _end_p)(it) ? 0 : it->index+1; \ 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; \ it->index = index; \
} \ } \
, /* End of INIT_SET */ ) \ , /* End of INIT_SET */ ) \
\ \
M_IF_AT_LEAST_METHOD(SET, INIT_MOVE, oplist)( \ M_IF_AT_LEAST_METHOD(SET, INIT_MOVE, oplist)( \
M_INLINE void \ M_P(void, name, _remove, array_t a, it_t it) \
M_F(name, _remove)(array_t a, it_t it) \
{ \ { \
M_ASSERT (it != NULL && a == it->array); \ 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 */ \ /* NOTE: it->index will naturally point to the next element */ \
} \ } \
, /* End of SET | INIT_SET */ ) \ , /* End of SET | INIT_SET */ ) \
@@ -902,8 +892,7 @@
M_ASSERT (org_tab == tab); \ M_ASSERT (org_tab == tab); \
} \ } \
\ \
M_INLINE void \ M_P(void, name, _special_stable_sort, array_t l) \
M_F(name, _special_stable_sort)(array_t l) \
{ \ { \
if (M_UNLIKELY (l->size < 2)) \ if (M_UNLIKELY (l->size < 2)) \
return; \ return; \
@@ -953,8 +942,7 @@
} \ } \
, /* no HASH */ ) \ , /* no HASH */ ) \
\ \
M_INLINE void \ M_P(void, name, _splice, array_t a1, array_t a2) \
M_F(name, _splice)(array_t a1, array_t a2) \
{ \ { \
M_ARRA4_CONTRACT(a1); \ M_ARRA4_CONTRACT(a1); \
M_ARRA4_CONTRACT(a2); \ M_ARRA4_CONTRACT(a2); \
@@ -987,12 +975,10 @@
#define M_ARRA4_DEF_IO(name, type, oplist, array_t, it_t) \ #define M_ARRA4_DEF_IO(name, type, oplist, array_t, it_t) \
\ \
M_IF_METHOD(GET_STR, oplist)( \ M_IF_METHOD(GET_STR, oplist)( \
M_INLINE void \ M_P(void, name, _get_str, m_string_t str, array_t const array, bool append) \
M_F(name, _get_str)(m_string_t str, array_t const array, \
bool append) \
{ \ { \
M_ARRA4_CONTRACT(array); \ 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; \ it_t it; \
for (M_F(name, _it)(it, array) ; \ for (M_F(name, _it)(it, array) ; \
!M_F(name, _end_p)(it); \ !M_F(name, _end_p)(it); \
@@ -1000,9 +986,9 @@
type const *item = M_F(name, _cref)(it); \ type const *item = M_F(name, _cref)(it); \
M_CALL_GET_STR(oplist, str, *item, true); \ M_CALL_GET_STR(oplist, str, *item, true); \
if (!M_F(name, _last_p)(it)) \ 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 */ ) \ , /* no GET_STR */ ) \
\ \
@@ -1024,12 +1010,11 @@
, /* no OUT_STR */ ) \ , /* no OUT_STR */ ) \
\ \
M_IF_METHOD2(PARSE_STR, INIT, oplist)( \ M_IF_METHOD2(PARSE_STR, INIT, oplist)( \
M_INLINE bool \ M_P(bool, name, _parse_str, array_t array, const char str[], const char**endp) \
M_F(name, _parse_str)(array_t array, const char str[], const char**endp) \
{ \ { \
M_ARRA4_CONTRACT(array); \ M_ARRA4_CONTRACT(array); \
M_ASSERT (str != NULL); \ M_ASSERT (str != NULL); \
M_F(name,_reset)(array); \ M_F(name,_reset)M_R(array); \
int c = *str++; \ int c = *str++; \
if (M_UNLIKELY (c != '[')) { c = 0; goto exit; } \ if (M_UNLIKELY (c != '[')) { c = 0; goto exit; } \
c = m_core_str_nospace(&str); \ c = m_core_str_nospace(&str); \
@@ -1041,7 +1026,7 @@
bool b = M_CALL_PARSE_STR(oplist, item, str, &str); \ bool b = M_CALL_PARSE_STR(oplist, item, str, &str); \
c = m_core_str_nospace(&str); \ c = m_core_str_nospace(&str); \
if (b == false || c == 0) { c = 0; break; } \ 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); \ } while (c == M_GET_SEPARATOR oplist); \
} \ } \
exit: \ exit: \
@@ -1052,12 +1037,11 @@
, /* no PARSE_STR & INIT */ ) \ , /* no PARSE_STR & INIT */ ) \
\ \
M_IF_METHOD2(IN_STR, INIT, oplist)( \ M_IF_METHOD2(IN_STR, INIT, oplist)( \
M_INLINE bool \ M_P(bool, name, _in_str, array_t array, FILE *file) \
M_F(name, _in_str)(array_t array, FILE *file) \
{ \ { \
M_ARRA4_CONTRACT(array); \ M_ARRA4_CONTRACT(array); \
M_ASSERT (file != NULL); \ M_ASSERT (file != NULL); \
M_F(name,_reset)(array); \ M_F(name,_reset)M_R(array); \
int c = fgetc(file); \ int c = fgetc(file); \
if (M_UNLIKELY (c != '[')) return false; \ if (M_UNLIKELY (c != '[')) return false; \
c = fgetc(file); \ c = fgetc(file); \
@@ -1069,7 +1053,7 @@
bool b = M_CALL_IN_STR(oplist, item, file); \ bool b = M_CALL_IN_STR(oplist, item, file); \
c = m_core_fgetc_nospace(file); \ c = m_core_fgetc_nospace(file); \
if (b == false || c == EOF) { c = 0; break; } \ 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); \ } while (c == M_GET_SEPARATOR oplist); \
} \ } \
M_ARRA4_CONTRACT(array); \ M_ARRA4_CONTRACT(array); \
@@ -1099,25 +1083,24 @@
, /* no OUT_SERIAL */ ) \ , /* no OUT_SERIAL */ ) \
\ \
M_IF_METHOD2(IN_SERIAL, INIT, oplist)( \ M_IF_METHOD2(IN_SERIAL, INIT, oplist)( \
M_INLINE m_serial_return_code_t \ M_P(m_serial_return_code_t, name, _in_serial, array_t array, m_serial_read_t f) \
M_F(name, _in_serial)(array_t array, m_serial_read_t f) \
{ \ { \
M_ARRA4_CONTRACT(array); \ M_ARRA4_CONTRACT(array); \
M_ASSERT (f != NULL && f->m_interface != NULL); \ M_ASSERT (f != NULL && f->m_interface != NULL); \
m_serial_return_code_t ret; \ m_serial_return_code_t ret; \
m_serial_local_t local; \ m_serial_local_t local; \
size_t estimated_size = 0; \ 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); \ ret = f->m_interface->read_array_start(local, f, &estimated_size); \
if (M_UNLIKELY (ret != M_SERIAL_OK_CONTINUE)) { \ if (M_UNLIKELY (ret != M_SERIAL_OK_CONTINUE)) { \
return ret; \ return ret; \
} \ } \
M_F(name, _reserve)(array, estimated_size); \ M_F(name, _reserve) M_R(array, estimated_size); \
M_QLET(1, item, type, oplist) { \ M_QLET(1, item, type, oplist) { \
do { \ do { \
ret = M_CALL_IN_SERIAL(oplist, item, f); \ ret = M_CALL_IN_SERIAL(oplist, item, f); \
if (ret != M_SERIAL_OK_DONE) { break; } \ 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); \ ret = f->m_interface->read_array_next(local, f); \
} while (ret == M_SERIAL_OK_CONTINUE); \ } while (ret == M_SERIAL_OK_CONTINUE); \
} \ } \
@@ -1128,11 +1111,9 @@
/* Definition of the emplace_back function for arrays */ /* Definition of the emplace_back function for arrays */
#define M_ARRA4_EMPLACE_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \ #define M_ARRA4_EMPLACE_DEF(name, name_t, function_name, oplist, init_func, exp_emplace_type) \
M_INLINE void \ M_P(void, name, function_name, name_t v M_EMPLACE_LIST_TYPE_VAR(a, exp_emplace_type) ) \
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) ) \ if (M_UNLIKELY (data == NULL) ) \
return; \ return; \
M_IF_EXCEPTION( v->size --); \ M_IF_EXCEPTION( v->size --); \
+72 -3
View File
@@ -379,11 +379,13 @@ M_BEGIN_PROTECTED_CODE
#endif #endif
/* Define allocators for array /* 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 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. * 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. * 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'. * 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 #ifndef M_MEMORY_REALLOC
#ifdef __cplusplus #ifdef __cplusplus
@@ -409,6 +411,40 @@ M_BEGIN_PROTECTED_CODE
#endif #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 **********************/ /********************* ERROR handling **********************/
/************************************************************/ /************************************************************/
@@ -440,6 +476,7 @@ M_BEGIN_PROTECTED_CODE
* NOTE: Can be overriden by user if it needs to keep finer access * NOTE: Can be overriden by user if it needs to keep finer access
* on the assertions. * on the assertions.
*/ */
//TODO: If NDEBUG, simply do nothing "no expression", to speed up compilation speed.
#ifndef M_ASSERT #ifndef M_ASSERT
#define M_ASSERT(expr) assert(expr) #define M_ASSERT(expr) assert(expr)
#endif #endif
@@ -450,6 +487,7 @@ M_BEGIN_PROTECTED_CODE
* NOTE: Can be overriden by user if it needs to keep finer access * NOTE: Can be overriden by user if it needs to keep finer access
* on the assertions. * on the assertions.
*/ */
//TODO: If NDEBUG, simply do nothing "no expression", to speed up compilation speed.
#ifndef M_ASSERT_SLOW #ifndef M_ASSERT_SLOW
# if defined(M_USE_ADDITIONAL_CHECKS) && M_USE_ADDITIONAL_CHECKS # if defined(M_USE_ADDITIONAL_CHECKS) && M_USE_ADDITIONAL_CHECKS
# define M_ASSERT_SLOW(n) assert(n) # 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) */ /* Transform a C variable into a m_string_t (needs m-string.h) */
#define M_GET_STRING_ARG(str, x, append) \ #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 */ /* No use of GET_STR if no inclusion of m-string */
#define M_GET_STR_METHOD_FOR_DEFAULT_TYPE /* */ #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_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_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_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 */ /* API transformation support for indirection */
#define M_OPLAPI_INDIRECT_0 M_OPLAPI_ERROR #define M_OPLAPI_INDIRECT_0 M_OPLAPI_ERROR
#define M_OPLAPI_INDIRECT_API_0(...) M_OPLAPI_0 #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_EXTRACT_API_6(...) __VA_ARGS__
#define M_OPLAPI_INDIRECT_API_7(...) M_OPLAPI_7 #define M_OPLAPI_INDIRECT_API_7(...) M_OPLAPI_7
#define M_OPLAPI_EXTRACT_API_7(...) __VA_ARGS__ #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. /* 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."),\ "The " #operator " operator has no method associated in the given OPLIST."),\
(return_type) 0) (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_MOVE(...) M_NO_DEFAULT(INIT_MOVE, void)
#define M_NO_DEF_INIT_WITH(...) M_NO_DEFAULT(INIT_WITH, void) #define M_NO_DEF_INIT_WITH(...) M_NO_DEFAULT(INIT_WITH, void)
#define M_NO_DEF_MOVE(...) M_NO_DEFAULT(MOVE, 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) \ #define M_ENUM_IN_SERIAL(oplist, var, serial) \
( var = (M_GET_TYPE oplist)(true ? m_core_in_serial_enum(serial) : 0), (serial)->tmp.r) ( var = (M_GET_TYPE oplist)(true ? m_core_in_serial_enum(serial) : 0), (serial)->tmp.r)
#define M_ENUM_GET_STR(str, var, append) \ #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) \ #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)) ( 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__ ) #define M_IPTR(...) ( & __VA_ARGS__ )
/* Perform an INIT_MOVE if present, or emulate it using INIT_SET/CLEAR */ /* 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 { \ #define M_DO_INIT_MOVE(oplist, dest, src) do { \
M_IF_METHOD(INIT_MOVE, oplist)(M_CALL_INIT_MOVE(oplist, (dest), (src)), \ M_IF_METHOD(INIT_MOVE, oplist)(M_CALL_INIT_MOVE(oplist, (dest), (src)), \
M_CALL_INIT_SET(oplist, (dest), (src)) ; \ M_CALL_INIT_SET(oplist, (dest), (src)) ; \
+129 -111
View File
@@ -281,8 +281,7 @@ m_string_init(m_string_t s)
} }
/* Clear the Dynamic string (destructor) */ /* Clear the Dynamic string (destructor) */
M_INLINE void M_P(void, m_string, _clear, m_string_t v)
m_string_clear(m_string_t v)
{ {
M_STR1NG_CONTRACT(v); M_STR1NG_CONTRACT(v);
if (!m_str1ng_embedded_p(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. and return a heap pointer to the string.
The ownership of the data is transferred back to the caller The ownership of the data is transferred back to the caller
and the returned pointer has to be released by M_MEMORY_FREE. */ and the returned pointer has to be released by M_MEMORY_FREE. */
M_INLINE char * M_P(char *, m_string, _clear_get_cstr, m_string_t v)
m_string_clear_get_cstr(m_string_t v)
{ {
M_STR1NG_CONTRACT(v); M_STR1NG_CONTRACT(v);
char *p = v->u.heap.ptr; 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. The string 'v' no longer has a working size field.
Return a pointer to the writable string. Return a pointer to the writable string.
*/ */
M_INLINE char * M_P(char *, m_str1ng, _fit2size, m_string_t v, size_t size_alloc)
m_str1ng_fit2size (m_string_t v, size_t size_alloc)
{ {
M_ASSERT_INDEX (0, size_alloc); M_ASSERT_INDEX (0, size_alloc);
// Note: this function may be called in context where the contract // 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' /* Modify the string capacity to be able to handle at least 'alloc'
characters (including final nul char). characters (including final nul char).
It may reduce the allocation of the string if possible */ It may reduce the allocation of the string if possible */
M_INLINE void M_P(void, m_string, _reserve, m_string_t v, size_t alloc)
m_string_reserve(m_string_t v, size_t alloc)
{ {
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
const size_t size = m_string_size(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 */ /* Set the string to the C string str */
M_INLINE void M_P(void, m_string, _set_cstr, m_string_t v, const char str[])
m_string_set_cstr(m_string_t v, const char str[])
{ {
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
M_ASSERT(str != NULL); M_ASSERT(str != NULL);
size_t size = strlen(str); 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 // The memcpy will also copy the final null char of the string
memcpy(ptr, str, size+1); memcpy(ptr, str, size+1);
m_str1ng_set_size(v, size); 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 */ /* Set the string to the n first characters of the C string str */
M_INLINE void M_P(void, m_string, _set_cstrn, m_string_t v, const char str[], size_t n)
m_string_set_cstrn(m_string_t v, const char str[], size_t n)
{ {
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
M_ASSERT(str != NULL); M_ASSERT(str != NULL);
size_t len = strlen(str); size_t len = strlen(str);
size_t size = M_MIN (len, n); 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 // The memcpy will not copy the final null char of the string
memcpy(ptr, str, size); memcpy(ptr, str, size);
// Cannot copy the final null char using memcpy // 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 */ /* Set the string to the other one */
M_INLINE void M_P(void, m_string, _set, m_string_t v1, const m_string_t v2)
m_string_set (m_string_t v1, const m_string_t v2)
{ {
M_STR1NG_CONTRACT (v1); M_STR1NG_CONTRACT (v1);
M_STR1NG_CONTRACT (v2); M_STR1NG_CONTRACT (v2);
if (M_LIKELY (v1 != v2)) { if (M_LIKELY (v1 != v2)) {
const size_t size = m_string_size(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); memcpy(ptr, m_string_get_cstr(v2), size+1);
m_str1ng_set_size(v1, size); 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 */ /* Set the string to the n first characters of other one */
M_INLINE void M_P(void, m_string, _set_n, m_string_t v, const m_string_t ref, size_t offset, size_t length)
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 (v);
M_STR1NG_CONTRACT (ref); M_STR1NG_CONTRACT (ref);
M_ASSERT_INDEX (offset, m_string_size(ref) + 1); M_ASSERT_INDEX (offset, m_string_size(ref) + 1);
size_t size = M_MIN (m_string_size(ref) - offset, length); 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 // v may be equal to ref, so a memmove is needed instead of a memcpy
memmove(ptr, m_string_get_cstr(ref) + offset, size); memmove(ptr, m_string_get_cstr(ref) + offset, size);
// Cannot copy the final null char using memcpy // 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 /* Initialize the string and set it to the other one
(constructor) */ (constructor) */
M_INLINE void M_P(void, m_string, _init_set, m_string_t v1, const m_string_t v2)
m_string_init_set(m_string_t v1, const m_string_t v2)
{ {
// In case of exception, v1 remains initialized, // In case of exception, v1 remains initialized,
// but without any allocation done. // but without any allocation done.
// Therefore it is safe, not to clear v1 on exception. // Therefore it is safe, not to clear v1 on exception.
m_string_init(v1); 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 /* Initialize the string and set it to the C string
(constructor) */ (constructor) */
M_INLINE void M_P(void, m_string, _init_set_cstr, m_string_t v1, const char str[])
m_string_init_set_cstr(m_string_t v1, const char str[])
{ {
// In case of exception, v1 remains initialized, // In case of exception, v1 remains initialized,
// but without any allocation done. // but without any allocation done.
// Therefore it is safe, not to clear v1 on exception. // Therefore it is safe, not to clear v1 on exception.
m_string_init(v1); 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, /* 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, /* Set the string to the other one,
and destroy the other one. and destroy the other one.
(destructor) */ (destructor) */
M_INLINE void M_P(void, m_string, _move, m_string_t v1, m_string_t v2)
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); m_string_init_move(v1,v2);
} }
/* Push the byte-character 'c' in the string 'v' */ /* Push the byte-character 'c' in the string 'v' */
M_INLINE void M_P(void, m_string, _push_back, m_string_t v, char c)
m_string_push_back (m_string_t v, char c)
{ {
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
const size_t size = m_string_size(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+0] = c;
ptr[size+1] = 0; ptr[size+1] = 0;
m_str1ng_set_size(v, size+1); 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 */ /* Concatenate the string with the C string */
M_INLINE void M_P(void, m_string, _cat_cstr, m_string_t v, const char str[])
m_string_cat_cstr(m_string_t v, const char str[])
{ {
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
M_ASSERT (str != NULL); M_ASSERT (str != NULL);
const size_t old_size = m_string_size(v); const size_t old_size = m_string_size(v);
const size_t size = strlen(str); 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); memcpy(&ptr[old_size], str, size + 1);
m_str1ng_set_size(v, old_size + size); m_str1ng_set_size(v, old_size + size);
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
} }
/* Concatenate the string with the other string */ /* Concatenate the string with the other string */
M_INLINE void M_P(void, m_string, _cat, m_string_t v, const m_string_t v2)
m_string_cat(m_string_t v, const m_string_t v2)
{ {
M_STR1NG_CONTRACT (v2); M_STR1NG_CONTRACT (v2);
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
const size_t size = m_string_size(v2); const size_t size = m_string_size(v2);
if (M_LIKELY (size > 0)) { if (M_LIKELY (size > 0)) {
const size_t old_size = m_string_size(v); 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); memcpy(&ptr[old_size], m_string_get_cstr(v2), size);
ptr[old_size + size] = 0; ptr[old_size + size] = 0;
m_str1ng_set_size(v, old_size + size); 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 into the C string str2 from start
By default, start is zero. By default, start is zero.
*/ */
M_INLINE size_t M_P(size_t, m_string, _replace_cstr, m_string_t v, const char str1[], const char str2[], size_t start)
m_string_replace_cstr (m_string_t v, const char str1[], const char str2[], size_t start)
{ {
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
M_ASSERT (str1 != NULL && str2 != NULL); 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 str2_l = strlen(str2);
const size_t size = m_string_size(v); const size_t size = m_string_size(v);
M_ASSERT(size + 1 + str2_l > str1_l); 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) { if (str1_l != str2_l) {
memmove(&ptr[i+str2_l], &ptr[i+str1_l], size - i - str1_l + 1); memmove(&ptr[i+str2_l], &ptr[i+str1_l], size - i - str1_l + 1);
m_str1ng_set_size(v, size + str2_l - str1_l); 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 into the C string v2 from start
By default, start is zero. By default, start is zero.
*/ */
M_INLINE size_t 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_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 (v);
M_STR1NG_CONTRACT (v1); M_STR1NG_CONTRACT (v1);
M_STR1NG_CONTRACT (v2); 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 /* Replace in the string the sub-string at position 'pos' for 'len' bytes
into the C string str2. */ into the C string str2. */
M_INLINE void M_P(void, m_string, _replace_at, m_string_t v, size_t pos, size_t len, const char str2[])
m_string_replace_at (m_string_t v, size_t pos, size_t len, const char str2[])
{ {
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
M_ASSERT(str2 != NULL); 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) { if (str1_l != str2_l) {
// Move bytes from the string // Move bytes from the string
M_ASSERT_INDEX (str1_l, size + str2_l + 1); 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_ASSERT_INDEX (pos + str1_l, size + 1);
M_ASSUME (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); 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) */ /* Replace all occurences of str1 into str2 when strlen(str1) < strlen(str2) */
M_INLINE void 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_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_STR1NG_CONTRACT (v);
M_ASSERT(str1len < str2len); 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 vlen = m_string_size(v);
size_t alloc = 1 + vlen / str1len * str2len; 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 *src = org + vlen - 1;
char *end = org + m_string_capacity(v); char *end = org + m_string_capacity(v);
char *dst = end; 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_STR1NG_CONTRACT (v);
} }
M_INLINE void M_P(void, m_string, _replace_all_cstr, m_string_t v, const char str1[], const char str2[])
m_string_replace_all_cstr (m_string_t v, const char str1[], const char str2[])
{ {
size_t str1_l = strlen(str1); size_t str1_l = strlen(str1);
size_t str2_l = strlen(str2); 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) { if (str1_l >= str2_l) {
m_str1ng_replace_all_cstr_1ge2(v, str1, str1_l, str2, str2_l ); m_str1ng_replace_all_cstr_1ge2(v, str1, str1_l, str2, str2_l );
} else { } 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_P(void, m_string, _replace_all, m_string_t v, const m_string_t str1, const m_string_t str2)
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 str1_l = m_string_size(str1);
size_t str2_l = m_string_size(str2); 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) { 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 ); m_str1ng_replace_all_cstr_1ge2(v, m_string_get_cstr(str1), str1_l, m_string_get_cstr(str2), str2_l );
} else { } 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). # error Unexpected UINT_MAX value (workaround: Define M_USE_FAST_STRING_CONV to 0).
#endif #endif
M_INLINE void M_P(void, m_string, _set_ui, m_string_t v, unsigned int n)
m_string_set_ui(m_string_t v, unsigned int n)
{ {
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
char buffer[M_STR1NG_INT_MAX_SIZE]; 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; unsigned i = 0, j = 0;
do { do {
// 0123456789 are mandatory in this order as characters, as per C standard. // 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; n /= 10U;
} while (n != 0); } while (n != 0);
M_ASSERT_INDEX(i, M_STR1NG_INT_MAX_SIZE); M_ASSERT_INDEX(i, M_STR1NG_INT_MAX_SIZE);
char *d = m_str1ng_get_cstr(v);
while (i > 0) { while (i > 0) {
d[j++] = buffer[--i]; d[j++] = buffer[--i];
} }
@@ -1106,13 +1084,12 @@ m_string_set_ui(m_string_t v, unsigned int n)
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
} }
M_INLINE void M_P(void, m_string, _set_si, m_string_t v, int n)
m_string_set_si(m_string_t v, int n)
{ {
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
// Compute the maximum number of characters needed for the buffer. // Compute the maximum number of characters needed for the buffer.
char buffer[M_STR1NG_INT_MAX_SIZE]; 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; unsigned i = 0, j = 0;
bool neg = n < 0; bool neg = n < 0;
unsigned n0 = neg ? 0U -(unsigned) n : (unsigned) n; unsigned n0 = neg ? 0U -(unsigned) n : (unsigned) n;
@@ -1122,7 +1099,6 @@ m_string_set_si(m_string_t v, int n)
n0 /= 10U; n0 /= 10U;
} while (n0 != 0); } while (n0 != 0);
M_ASSERT_INDEX(i, M_STR1NG_INT_MAX_SIZE); M_ASSERT_INDEX(i, M_STR1NG_INT_MAX_SIZE);
char *d = m_str1ng_get_cstr(v);
if (neg) d[j++] = '-'; if (neg) d[j++] = '-';
while (i > 0) { while (i > 0) {
d[j++] = buffer[--i]; d[j++] = buffer[--i];
@@ -1136,8 +1112,7 @@ m_string_set_si(m_string_t v, int n)
#if M_USE_STDARG #if M_USE_STDARG
/* Format in the string the given printf format */ /* Format in the string the given printf format */
M_INLINE int M_P(int, m_string, _vprintf, m_string_t v, const char format[], va_list args)
m_string_vprintf (m_string_t v, const char format[], va_list args)
{ {
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
M_ASSERT (format != NULL); 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_set_size(v, 0) );
M_IF_EXCEPTION( m_str1ng_get_cstr(v)[0] = 0 ); M_IF_EXCEPTION( m_str1ng_get_cstr(v)[0] = 0 );
// We have to realloc our string to fit the needed size // 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); alloc = m_string_capacity(v);
// and redo the parsing. // and redo the parsing.
size = vsnprintf (ptr, alloc, format, args_org); 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)) { if (M_LIKELY (size >= 0)) {
m_str1ng_set_size(v, (size_t) size); m_str1ng_set_size(v, (size_t) size);
} else { } 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); m_str1ng_set_size(v, 0);
ptr[0] = 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 */ /* Format in the string the given printf format */
M_INLINE int // FIXME: BROKEN to add a parameter **after** the '...'!
m_string_printf (m_string_t v, const char format[], ...) M_P(int, m_string, _printf, m_string_t v, const char format[], ...)
{ {
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
M_ASSERT (format != NULL); M_ASSERT (format != NULL);
va_list args; va_list args;
va_start (args, format); 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); va_end (args);
return ret; return ret;
} }
/* Append to the string the formatted string of the given printf format */ /* Append to the string the formatted string of the given printf format */
M_INLINE int M_P(int, m_string, _cat_vprintf, m_string_t v, const char format[], va_list args)
m_string_cat_vprintf (m_string_t v, const char format[], va_list args)
{ {
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
M_ASSERT (format != NULL); 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_set_size(v, old_size) );
M_IF_EXCEPTION( m_str1ng_get_cstr(v)[old_size] = 0 ); M_IF_EXCEPTION( m_str1ng_get_cstr(v)[old_size] = 0 );
// We have to realloc our string to fit the needed size // 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); alloc = m_string_capacity(v);
// and redo the parsing. // and redo the parsing.
size = vsnprintf (&ptr[old_size], alloc - old_size, format, args_org); 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 */ /* Append to the string the formatted string of the given printf format */
M_INLINE int //FIXME:
m_string_cat_printf (m_string_t v, const char format[], ...) M_P(int, m_string, _cat_printf, m_string_t v, const char format[], ...)
{ {
M_STR1NG_CONTRACT (v); M_STR1NG_CONTRACT (v);
M_ASSERT (format != NULL); M_ASSERT (format != NULL);
va_list args; va_list args;
va_start (args, format); 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); va_end (args);
return ret; return ret;
} }
#if M_USE_FAST_STRING_CONV == 0 #if M_USE_FAST_STRING_CONV == 0
M_INLINE void M_P(void, m_string, _set_ui, m_string_t v, unsigned int n)
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_P(void, m_string, _set_si, m_string_t v, int n)
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 #endif
@@ -1252,12 +1224,11 @@ m_string_set_si(m_string_t v, int n)
#if M_USE_STDIO #if M_USE_STDIO
/* Get a line/pure-line/file from the FILE and store it in the string */ /* Get a line/pure-line/file from the FILE and store it in the string */
M_INLINE bool M_P(bool, m_string, _fgets, m_string_t v, FILE *f, m_string_fgets_t arg)
m_string_fgets(m_string_t v, FILE *f, m_string_fgets_t arg)
{ {
M_STR1NG_CONTRACT(v); M_STR1NG_CONTRACT(v);
M_ASSERT (f != NULL); 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 size = 0;
size_t alloc = m_string_capacity(v); size_t alloc = m_string_capacity(v);
ptr[0] = 0; 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: /* The string buffer is not big enough:
increase it and continue reading */ increase it and continue reading */
/* v cannot be a full embedded type */ /* 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); 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 Words are supposed to be separated each other by the given list of separator
separator shall be a CONSTANT C array. separator shall be a CONSTANT C array.
*/ */
M_INLINE bool M_P(bool, m_string, _fget_word, m_string_t v, const char separator[], FILE *f)
m_string_fget_word (m_string_t v, const char separator[], FILE *f)
{ {
char buffer[128]; char buffer[128];
char c = 0; 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 */ /* Next char is not a separator: continue parsing */
m_str1ng_set_size(v, size); m_str1ng_set_size(v, size);
M_IF_EXCEPTION( m_str1ng_get_cstr(v)[size] = 0); 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); alloc = m_string_capacity(v);
M_ASSERT (alloc > size + 1); M_ASSERT (alloc > size + 1);
ptr[size++] = c; 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 /* Transform the string 'v2' into a formatted string
and set it to (or append in) the string 'v'. */ and set it to (or append in) the string 'v'. */
M_INLINE void M_P(void, m_string, _get_str, m_string_t v, const m_string_t v2, bool append)
m_string_get_str(m_string_t v, const m_string_t v2, bool append)
{ {
M_STR1NG_CONTRACT(v2); M_STR1NG_CONTRACT(v2);
M_STR1NG_CONTRACT(v); 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 size = append ? m_string_size(v) : 0;
size_t v2_size = m_string_size(v2); size_t v2_size = m_string_size(v2);
size_t targetSize = size + v2_size + 3; 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 ++] = '"'; ptr[size ++] = '"';
for(size_t i = 0 ; i < v2_size; i++) { for(size_t i = 0 ; i < v2_size; i++) {
const char c = m_string_get_char(v2,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': case '\r':
// Special characters which can be displayed in a short form. // Special characters which can be displayed in a short form.
m_str1ng_set_size(v, size); m_str1ng_set_size(v, size);
ptr = m_str1ng_fit2size(v, ++targetSize); ptr = m_str1ng_fit2size M_R(v, ++targetSize);
ptr[size ++] = '\\'; ptr[size ++] = '\\';
// This string acts as a perfect hashmap which supposes an ASCII mapping // This string acts as a perfect hashmap which supposes an ASCII mapping
// and (c^(c>>5)) is the hash function // 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; targetSize += 3;
m_str1ng_set_size(v, size); m_str1ng_set_size(v, size);
M_IF_EXCEPTION(m_str1ng_get_cstr(v)[size] = 0); 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; int d1 = c & 0x07, d2 = (c>>3) & 0x07, d3 = (c>>6) & 0x07;
ptr[size ++] = '\\'; ptr[size ++] = '\\';
ptr[size ++] = (char) ('0' + d3); 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 /* Read the formatted string from the FILE
and set the converted value in the string 'v'. and set the converted value in the string 'v'.
Return true in case of success */ Return true in case of success */
M_INLINE bool M_P(bool, m_string, _in_str, m_string_t v, FILE *f)
m_string_in_str(m_string_t v, FILE *f)
{ {
M_STR1NG_CONTRACT(v); M_STR1NG_CONTRACT(v);
M_ASSERT (f != NULL); M_ASSERT (f != NULL);
@@ -1610,7 +1578,7 @@ m_string_in_str(m_string_t v, FILE *f)
break; break;
} }
} }
m_string_push_back (v, (char) c); m_string_push_back M_R(v, (char) c);
c = fgetc(f); c = fgetc(f);
} }
return c == '"'; return c == '"';
@@ -1623,8 +1591,7 @@ m_string_in_str(m_string_t v, FILE *f)
Return true in case of success Return true in case of success
If endptr is not null, update the position of the parsing. If endptr is not null, update the position of the parsing.
*/ */
M_INLINE bool M_P(bool, m_string, _parse_str, m_string_t v, const char str[], const char **endptr)
m_string_parse_str(m_string_t v, const char str[], const char **endptr)
{ {
M_STR1NG_CONTRACT(v); M_STR1NG_CONTRACT(v);
M_ASSERT (str != NULL); M_ASSERT (str != NULL);
@@ -1662,7 +1629,7 @@ m_string_parse_str(m_string_t v, const char str[], const char **endptr)
break; break;
} }
} }
m_string_push_back (v, (char) c); m_string_push_back M_R(v, (char) c);
c = *str++; c = *str++;
} }
success = (c == '"'); 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_INLINE m_serial_return_code_t
m_string_out_serial(m_serial_write_t serial, const m_string_t v) 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); M_ASSERT (serial != NULL && serial->m_interface != NULL);
return serial->m_interface->write_string(serial, m_string_get_cstr(v), m_string_size(v) ); 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 */ /* Update the value referenced by the iterator to the given value */
M_INLINE void M_P(void, m_string, _it_set_ref, m_string_it_t it, m_string_t s, m_string_unicode_t new_u)
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_IT_CONTRACT(it);
M_STR1NG_CONTRACT(s); 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); M_ASSUME( it->ptr >= ptr);
size_t offset = (size_t) (it->ptr - ptr); size_t offset = (size_t) (it->ptr - ptr);
// Special case if the unicode codepoint is 0 // Special case if the unicode codepoint is 0
if (new_u == 0) { if (M_UNLIKELY(new_u == 0)) {
// Null the string // Null the string
m_str1ng_set_size(s, offset); m_str1ng_set_size(s, offset);
ptr[offset] = 0; 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); size_t old_u_size = (size_t) (str - it->ptr);
// We need to replace old_u by new_u. Both are variable length // We need to replace old_u by new_u. Both are variable length
size_t str_size = m_string_size(s); size_t str_size = m_string_size(s);
if (new_u_size != old_u_size) { if (M_UNLIKELY (new_u_size != old_u_size)) {
ptr = m_str1ng_fit2size(s, str_size + new_u_size - old_u_size + 1); 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) ); M_ASSUME( str_size+1 > (offset + old_u_size) );
memmove(&ptr[offset+new_u_size], &ptr[offset + old_u_size], memmove(&ptr[offset+new_u_size], &ptr[offset + old_u_size],
str_size+1 - 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 */ /* Push unicode code point into string, encoding it in UTF8 */
M_INLINE void M_P(void, m_string, _push_u, m_string_t str, m_string_unicode_t u)
m_string_push_u (m_string_t str, m_string_unicode_t u)
{ {
M_STR1NG_CONTRACT(str); M_STR1NG_CONTRACT(str);
char buffer[4+1]; char buffer[4+1];
m_str1ng_utf8_encode(buffer, u); 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 */ /* Pop last unicode code point into string, encoding it in UTF8 */
@@ -2153,13 +2119,22 @@ namespace m_lib {
m_lib::m_aligned_string<sizeof (s)>(s).string m_lib::m_aligned_string<sizeof (s)>(s).string
#endif #endif
#ifdef M_USE_POOL
/* Initialize and set a string to the given formatted value. */ /* 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, ...) \ #define m_string_init_printf(v, ...) \
(m_string_printf ( m_str1ng_init_ref(v), __VA_ARGS__) ) (m_string_printf ( m_str1ng_init_ref(v), __VA_ARGS__) )
/* Initialize and set a string to the given formatted value. */ /* Initialize and set a string to the given formatted value. */
#define m_string_init_vprintf(v, format, args) \ #define m_string_init_vprintf(v, format, args) \
(m_string_vprintf ( m_str1ng_init_ref(v), format, args) ) (m_string_vprintf ( m_str1ng_init_ref(v), format, args) )
#endif
/* Initialize a string with the given list of arguments. /* Initialize a string with the given list of arguments.
Check if it is a formatted input or not by counting the number 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. */ C string and string. */
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
#define M_STR1NG_INIT_WITH(v, ...) \ #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 #else
#define M_STR1NG_INIT_WITH(v, ...) \ #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 #endif
/* Define the OPLIST of a STRING */ /* Define the OPLIST of a STRING */
@@ -2201,6 +2176,31 @@ namespace m_lib {
,EMPLACE_TYPE(const char*) \ ,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 */ /* Register the OPLIST as a global one */
#define M_OPL_m_string_t() M_STRING_OPLIST #define M_OPL_m_string_t() M_STRING_OPLIST
@@ -2274,10 +2274,28 @@ namespace m_lib {
)(a,b,c) )(a,b,c)
/* Init & Set the string a to the string (or C string) b (constructor) */ /* 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) #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 */ /* 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) #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 */ /* 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) #define m_string_cat(a,b) M_STR1NG_SELECT2(m_string_cat, m_string_cat_cstr, a, b)