rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

commit d6d02e8f7ea609c6d07b301d409231af979c3477
parent dc07691019816bdee2981422f11a7dedb438ca10
Author: vaplv <vaplv@free.fr>
Date:   Wed, 15 Jan 2020 11:50:11 +0100

Fix the str_len function

The str_len function returned a wrong string length when a null char was
directly set into the string buffer. To fix this issue, the str data
structure does not explicitly store its len anymore and rely on the
strlen function to retrieve it.

Diffstat:
Msrc/str.c | 49+++++++++++++++++++++++++++----------------------
Msrc/str.h | 10+++-------
Msrc/test_str.c | 6++++++
3 files changed, 36 insertions(+), 29 deletions(-)

diff --git a/src/str.c b/src/str.c @@ -66,36 +66,37 @@ str_set(struct str* str, const char* cstr) res = ensure_allocated(str, cstr_len + 1, 0); if(res != RES_OK) return res; strncpy(str->cstr, cstr, cstr_len + 1); - str->len = cstr_len; return RES_OK; } res_T str_insert(struct str* str, const size_t i, const char* cstr) { + size_t len = 0; size_t cstr_len = 0; ASSERT(str); - if(i > str->len) + len = str_len(str); + + if(i > len) return RES_BAD_ARG; cstr_len = strlen(cstr); ASSERT(!MEM_AREA_OVERLAP (str->cstr, str->allocated, cstr, (cstr_len + 1) * sizeof(char))); - if(i == str->len) { + if(i == len) { return str_append(str, cstr); } else { - const res_T res = ensure_allocated(str, cstr_len + str->len + 1, 1); + const res_T res = ensure_allocated(str, cstr_len + len + 1, 1); if(res != RES_OK) return res; memmove (str->cstr + i + cstr_len, str->cstr + i, - (str->len - i) * sizeof(char)); + (len - i) * sizeof(char)); memcpy(str->cstr + i, cstr, cstr_len * sizeof(char)); - str->len = str->len + cstr_len; - str->cstr[str->len] = '\0'; + str->cstr[len + cstr_len] = '\0'; } return RES_OK; } @@ -103,25 +104,27 @@ str_insert(struct str* str, const size_t i, const char* cstr) res_T str_insert_char(struct str* str, const size_t i, const char ch) { - if(i > str->len) + size_t len = 0; + ASSERT(str); + + len = str_len(str); + if(i > len) return RES_BAD_ARG; - if(i == str->len) { + if(i == len) { return str_append_char(str, ch); } else if(ch == '\0') { str->cstr[i] = ch; - str->len = i; } else { - const res_T res = ensure_allocated(str, str->len + 2, 1); + const res_T res = ensure_allocated(str, len + 2, 1); if(res != RES_OK) return res; memmove (str->cstr + i + 1, str->cstr + i, - (str->len - i) * sizeof(char)); + (len - i) * sizeof(char)); str->cstr[i] = ch; - ++str->len; - str->cstr[str->len] = '\0'; + str->cstr[len+1] = '\0'; } return RES_OK; } @@ -129,6 +132,7 @@ str_insert_char(struct str* str, const size_t i, const char ch) res_T str_append(struct str* str, const char* cstr) { + size_t len = 0; size_t cstr_len = 0; res_T res = RES_OK; ASSERT(str && cstr); @@ -137,31 +141,32 @@ str_append(struct str* str, const char* cstr) ASSERT(!MEM_AREA_OVERLAP (str->cstr, str->allocated, cstr, (cstr_len + 1) * sizeof(char))); - res = ensure_allocated(str, cstr_len + str->len + 1, 1); + len = str_len(str); + res = ensure_allocated(str, cstr_len + len + 1, 1); if(res != RES_OK) return res; - memcpy(str->cstr + str->len, cstr, cstr_len * sizeof(char)); - str->len += cstr_len; - str->cstr[str->len] = '\0'; + memcpy(str->cstr + len, cstr, cstr_len * sizeof(char)); + str->cstr[len + cstr_len] = '\0'; return RES_OK; } res_T str_append_char(struct str* str, const char ch) { + size_t len = 0; res_T res = RES_OK; ASSERT( str ); if(ch == '\0') return RES_OK; - res = ensure_allocated(str, str->len + 2, 1); + len = str_len(str); + res = ensure_allocated(str, len + 2, 1); if(res != RES_OK) return res; - str->cstr[str->len] = ch; - ++str->len; - str->cstr[str->len] = '\0'; + str->cstr[len+0] = ch; + str->cstr[len+1] = '\0'; return RES_OK; } diff --git a/src/str.h b/src/str.h @@ -25,7 +25,6 @@ struct str { /* Internal data. Should not be publicly accessed */ struct mem_allocator* allocator; size_t allocated; /* <=> string capacity */ - size_t len; char* cstr; char buffer[16]; /* static buffer. Avoid allocation on small string */ }; @@ -36,7 +35,6 @@ str_init(struct mem_allocator* allocator, struct str* str) ASSERT(str); str->allocator = allocator ? allocator : &mem_default_allocator; str->allocated = sizeof(str->buffer); - str->len = 0; str->cstr = str->buffer; str->buffer[0] = '\0'; } @@ -54,7 +52,7 @@ static INLINE size_t str_len(const struct str* str) { ASSERT(str); - return str->len; + return strlen(str->cstr); } static INLINE char @@ -68,7 +66,6 @@ static INLINE void str_clear(struct str* str) { ASSERT(str); - str->len = 0; str->cstr[0] = '\0'; } @@ -135,7 +132,6 @@ str_copy_and_clear(struct str* dst, struct str* src) MEM_RM(dst->allocator, dst->cstr); dst->cstr = src->cstr; dst->allocated = src->allocated; - dst->len = src->len; /* Reset the src to its initial state */ str_init(src->allocator, src); } else { @@ -168,9 +164,9 @@ str_hash(const struct str* str) ASSERT(str); c_str = str_cget(str); #ifdef ARCH_32BITS - return (size_t)hash_fnv32(c_str, str->len); + return (size_t)hash_fnv32(c_str, str_len(str)); #elif defined ARCH_64BITS - return (size_t)hash_fnv64(c_str, str->len); + return (size_t)hash_fnv64(c_str, str_len(str)); #else #error "Unexpected architecture" #endif diff --git a/src/test_str.c b/src/test_str.c @@ -138,6 +138,12 @@ main(int argc, char** argv) str_release(&str); + str_init(&allocator_proxy, &str); + CHK(str_set(&str, "abcd") == RES_OK); + CHK(str_len(&str) == 4); + str_get(&str)[3] = '\0'; + CHK(str_len(&str) == 3); + check_memory_allocator(&allocator_proxy); mem_shutdown_proxy_allocator(&allocator_proxy); CHK(mem_allocated_size() == 0);