cstring

Lightweight string library for C
git clone git://git.christosmarg.xyz/cstring.git
Log | Files | Refs | README | LICENSE

commit 805f9acde435c5be62a70c4b69ccb1bec894d954
parent 22060bd2333f19c4dbd47606a9bedddcf4b2a9ab
Author: Christos Margiolis <christos@margiolis.net>
Date:   Sat,  3 Oct 2020 03:40:28 +0300

push_back bug fixed (probably), pending erase and assign function bug fixes, pending cstring_move implementation

Diffstat:
Mcstring.3 | 15+++++++--------
Mcstring.c | 106++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Mcstring.h | 8++++++--
Mtests/test.c | 6++----
4 files changed, 88 insertions(+), 47 deletions(-)

diff --git a/cstring.3 b/cstring.3 @@ -134,19 +134,18 @@ The following macros can only be used in debug mode: .BR CSTRING_DBG_LOG(fmt,\ ...) Prints a message in the format of "DEBUG: file:line:func(): msg". .TP -.BR CSTRING_DBG_LOG_STR_INFO(cs) -Uses -.I CSTRING_DBG_LOG -to print all the contents of a +.BR CSTRING_DBG_LOG_CSTR_INFO(cs) +Print all the contents of a .I cstring struct. The argument has to be a pointer. .TP -.BR CSTRING_DBG_LOG_STR_INFO_NPTR(cs) -Uses -.I CSTRING_DBG_LOG -to print all the contents of a +.BR CSTRING_DBG_LOG_CSTR_INFO_NPTR(cs) +Print all the contents of a .I cstring struct. The argument has to be a non-pointer. +.TP +.BR CSTRING_DBG_LOG_STR_INFO(s, len) +Print contents of a normal string. .SH CONSTANTS .TP .BR CSTRING_NPOS diff --git a/cstring.c b/cstring.c @@ -1,10 +1,38 @@ #include "cstring.h" #define CSTRING_EXCEEDS_CAPACITY(len, cap) ((len) >= (cap)) -#define CSTRING_FIND_OCCURENCE(cs, s, func) do { \ - char *_found; \ - if ((_found = func(cs->str, (s))) != NULL) \ - return (_found - cs->str); \ + +#ifdef CSTRING_DBG +#define CSTRING_FREE(cs) do { \ + CSTRING_DBG_LOG("Before CSTRING_FREE: %s\n", cs->str); \ + if (!cstring_empty(cs)) \ + free(cs->str); \ +} while (0) + +/* Might move above erase functions */ +#define CSTRING_EXPECTED_ERASE_STR(cs, pos, len) do { \ + CSTRING_DBG_LOG("%s", "CSTRING_EXPECTED_ERASE_STR: "); \ + size_t _i; \ + for (_i = 0; _i < pos; _i++) \ + printf("%c", cs->str[_i]); \ + for (_i = pos + len; _i < cs->len; _i++) \ + printf("%c", cs->str[_i]); \ + printf("\n"); \ +} while (0) + +#define CSTRING_EXPECTED_ERASE_LEN(cs, len) \ + CSTRING_DBG_LOG("CSTRING_EXPECTED_ERASE_LEN: %ld\n", cs->len - len) +#else +#define CSTRING_FREE(cs) do { \ + if (!cstring_empty(cs)) \ + free(cs->str); \ +} while (0) +#endif /* CSTRING_DBG */ + +#define CSTRING_FIND_OCCURENCE(cs, s, func) do { \ + char *_found; \ + if ((_found = func(cs->str, (s))) != NULL) \ + return (_found - cs->str); \ } while (0) static int @@ -24,7 +52,8 @@ cstring_create(const char *s) cs.str = cstring_copy(s); cstring_resize(&cs, cs.len << 1); #ifdef CSTRING_DBG - CSTRING_DBG_LOG_STR_INFO_NPTR(cs); + CSTRING_DBG_LOG_STR_INFO(s, cs.len); + CSTRING_DBG_LOG_CSTR_INFO_NPTR(cs); #endif /* CSTRING_DBG */ return cs; } @@ -32,7 +61,7 @@ cstring_create(const char *s) void cstring_delete(cstring *cs) { - if (!cstring_empty(cs)) free(cs->str); + CSTRING_FREE(cs); cs->str = NULL; cs->len = 0; cs->capacity = 0; @@ -41,14 +70,14 @@ cstring_delete(cstring *cs) void cstring_assign(cstring *cs, const char *s) { - size_t newlen = strlen(s); - if (CSTRING_EXCEEDS_CAPACITY(newlen, cs->capacity)) - cstring_resize(cs, newlen << 1); - if (!cstring_empty(cs)) free(cs->str); + CSTRING_FREE(cs); cs->str = cstring_copy(s); - cs->len = newlen; + cs->len = strlen(s); + if (CSTRING_EXCEEDS_CAPACITY(cs->len, cs->capacity)) + cstring_resize(cs, cs->len << 1); #ifdef CSTRING_DBG - CSTRING_DBG_LOG_STR_INFO(cs); + CSTRING_DBG_LOG_STR_INFO(s, cs->len); + CSTRING_DBG_LOG_CSTR_INFO(cs); #endif /* CSTRING_DBG */ } @@ -60,17 +89,18 @@ cstring_insert(cstring *cs, const char *s, size_t i) size_t newlen = cs->len + slen; char *tmp; CSTRING_MALLOC(tmp, newlen + 1); - if (CSTRING_EXCEEDS_CAPACITY(newlen, cs->capacity)) - cstring_resize(cs, newlen << 1); memcpy(tmp, cs->str, i); memcpy(tmp + i, s, slen); - memcpy(tmp + slen + i, cs->str + i, newlen - slen - i); - free(cs->str); + memcpy(tmp + i + slen, cs->str + i, newlen - slen - i + 1); + CSTRING_FREE(cs); cs->len = newlen; cs->str = tmp; cs->str[cs->len] = '\0'; + if (CSTRING_EXCEEDS_CAPACITY(newlen, cs->capacity)) + cstring_resize(cs, newlen << 1); #ifdef CSTRING_DBG - CSTRING_DBG_LOG_STR_INFO(cs); + CSTRING_DBG_LOG_STR_INFO(s, slen); + CSTRING_DBG_LOG_CSTR_INFO(cs); #endif /* CSTRING_DBG */ } } @@ -82,15 +112,23 @@ cstring_erase(cstring *cs, size_t pos, size_t len) && !CSTRING_OUT_OF_BOUNDS(cs, pos) && !CSTRING_OUT_OF_BOUNDS(cs, len)) { +#ifdef CSTRING_DBG + CSTRING_DBG_LOG("STR: %s | INDEX: %ld | LEN: %ld\n", cs->str, pos, len); + CSTRING_EXPECTED_ERASE_STR(cs, pos, len); + CSTRING_EXPECTED_ERASE_LEN(cs, len); +#endif /* CSTRING_DBG */ size_t newlen = cs->len - len; char *tmp; CSTRING_MALLOC(tmp, newlen + 1); - memcpy(tmp, cs->str, pos); // pos + 1?? - memcpy(tmp + pos, cs->str + pos + len, newlen); - free(cs->str); + memcpy(tmp, cs->str, pos); + memcpy(tmp + pos, cs->str + pos + len, cs->len - len + pos); + CSTRING_FREE(cs); /* Useless check but keep it for consistency */ cs->len = newlen; cs->str = tmp; cs->str[cs->len] = '\0'; +#ifdef CSTRING_DBG + CSTRING_DBG_LOG_CSTR_INFO(cs); +#endif /* CSTRING_DBG */ } } @@ -128,21 +166,15 @@ cstring_push_back(cstring *cs, char c) cs->str[cs->len] = c; cs->str[++cs->len] = '\0'; #ifdef CSTRING_DBG - CSTRING_DBG_LOG_STR_INFO(cs); + CSTRING_DBG_LOG_CSTR_INFO(cs); #endif /* CSTRING_DBG */ } void cstring_pop_back(cstring *cs) { - if (cs->len > 0) { - char *tmp; - CSTRING_MALLOC(tmp, cs->len); - memcpy(tmp, cs->str, cs->len); - free(cs->str); - tmp[--cs->len] = '\0'; - cs->str = tmp; - } + if (cs->len > 0) + cs->str[--cs->len] = '\0'; } void @@ -189,7 +221,7 @@ cstring_swap(cstring *lhs, cstring *rhs) void cstring_clear(cstring *cs) { - if (!cstring_empty(cs)) free(cs->str); + CSTRING_FREE(cs); CSTRING_MALLOC(cs->str, 1); cs->str[0] = '\0'; cs->len = 0; @@ -282,17 +314,25 @@ cstring_copy(const char *s) char *tmp; CSTRING_MALLOC(tmp, len + 1); memcpy(tmp, s, len + 1); - tmp[len] = '\0'; + tmp[len] = '\0'; /* Add \0 in case s didn't have it */ return tmp; } void cstring_resize(cstring *cs, size_t newcapacity) { - cs->str = (char *)realloc(cs->str, newcapacity + 1); +#ifdef CSTRING_DBG + CSTRING_DBG_LOG("Old capacity: %ld | New capacity: %ld\n", + cs->capacity, newcapacity); +#endif /* CSTRING_DBG */ + char *tmp; + CSTRING_MALLOC(tmp, newcapacity); + memcpy(tmp, cs->str, cs->len + 1); /* copy \0 too */ + CSTRING_FREE(cs); + cs->str = tmp; cs->capacity = newcapacity; #ifdef CSTRING_DBG - CSTRING_DBG_LOG_STR_INFO(cs); + CSTRING_DBG_LOG_CSTR_INFO(cs); #endif /* CSTRING_DBG */ } diff --git a/cstring.h b/cstring.h @@ -23,13 +23,16 @@ extern "C" { fprintf(stderr, "DEBUG: %s:%d:%s(): " fmt, \ __FILE__, __LINE__, __func__, __VA_ARGS__) -#define CSTRING_DBG_LOG_STR_INFO(cs) \ +#define CSTRING_DBG_LOG_CSTR_INFO(cs) \ CSTRING_DBG_LOG("STR: %s | LEN: %ld | CAP: %ld\n", \ cs->str, cs->len, cs->capacity) -#define CSTRING_DBG_LOG_STR_INFO_NPTR(cs) \ +#define CSTRING_DBG_LOG_CSTR_INFO_NPTR(cs) \ CSTRING_DBG_LOG("STR: %s | LEN: %ld | CAP: %ld\n", \ cs.str, cs.len, cs.capacity) + +#define CSTRING_DBG_LOG_STR_INFO(s, len) \ + CSTRING_DBG_LOG("S: %s | LEN: %ld\n", s, len) #endif /* CSTRING_DBG */ typedef struct cstring { @@ -60,6 +63,7 @@ extern size_t cstring_find_first_not_of(const cstring *,const char *); extern size_t cstring_find_last_of(const cstring *, const char *); extern size_t cstring_find_last_not_of(const cstring *, const char *); extern char *cstring_copy(const char *); +//extern void cstring_move(cstring *cs, const char *); extern void cstring_resize(cstring *, size_t); extern cstring *cstring_getline(FILE *, cstring *, char); diff --git a/tests/test.c b/tests/test.c @@ -8,6 +8,7 @@ main(int argc, char **argv) cstring s = cstring_create("Hello world"); printf("cstring_create: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); + // BUG cstring_assign(&s, "New string"); printf("cstring_assign: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); @@ -17,10 +18,6 @@ main(int argc, char **argv) cstring_prepend(&s, "OK"); printf("cstring_prepend: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); - // BUG - /*for (int i = 0; i < 50; i++)*/ - /*cstring_push_back(&s, 'c');*/ - cstring_push_back(&s, 'c'); printf("cstring_push_back: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); @@ -44,6 +41,7 @@ main(int argc, char **argv) cstring_replace_str(&s, "hell", 0, strlen("hell")); printf("cstring_replace_str: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); + // BUGS cstring_erase(&s, 1, 4); printf("cstring_erase: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);