cstring

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

commit a33b249a441d7f3a7fd1adbb1cd887ca2e3adcfd
parent 2d0b7a1fec7fdcd2161b64300260cf0b7c7c457d
Author: Christos Margiolis <christos@margiolis.net>
Date:   Thu,  1 Oct 2020 18:46:46 +0300

inlined some functions, simplified append & prepend functions, pending push_back bug fix

Diffstat:
Mcstring.3 | 9++++++---
Mcstring.c | 165++++++++++++++++++-------------------------------------------------------------
Mcstring.h | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Acstring.o | 0
Alibcstring.a | 0
Mtests/test.c | 12++++++------
6 files changed, 148 insertions(+), 155 deletions(-)

diff --git a/cstring.3 b/cstring.3 @@ -15,15 +15,15 @@ Deallocate string. .BR void\ cstring_assign(cstring\ *cs,\ const\ char\ *s) Assign a new string to current string. .TP +.BR void\ cstring_insert(cstring\ *cs,\ const\ char\ *s,\ size_t\ i) +Insert at a specific index. +.TP .BR void\ cstring_append(cstring\ *cs,\ const\ char\ *s) Append to end of string. .TP .BR void\ cstring_prepend(cstring\ *cs,\ const\ char\ *s) Prepend to beginning of string. .TP -.BR void\ cstring_insert(cstring\ *cs,\ const\ char\ *s,\ size_t\ i) -Insert at a specific index. -.TP .BR void\ cstring_erase(cstring\ *cs,\ size_t\ pos,\ size_t\ len) Erase a portion of the string. .TP @@ -63,6 +63,9 @@ Erase the whole string. .BR size_t\ cstring_find(const\ cstring\ *cs,\ const\ char\ *s) Find first occurence of a pattern in string. .TP +.BR size_t\ cstring_rfind(const\ cstring\ *cs,\ const\ char\ *s) +Find last occurence of a pattern in string. +.TP .BR size_t\ cstring_find_first_of(const\ cstring\ *cs,\ const\ char\ *s) Find first occurence of specified characters in string. .TP diff --git a/cstring.c b/cstring.c @@ -21,10 +21,8 @@ cstring_create(const char *s) { cstring cs; cs.len = strlen(s); - cs.capacity = cs.len << 1; - cs.str = (char *)malloc(cs.capacity + 1); - memcpy(cs.str, s, cs.len + 1); - cs.str[cs.len] = '\0'; + cs.str = cstring_copy(s); + cstring_resize(&cs, cs.len << 1); return cs; } @@ -32,8 +30,8 @@ void cstring_delete(cstring *cs) { if (!cstring_empty(cs)) free(cs->str); - cs->str = NULL; - cs->len = 0; + cs->str = NULL; + cs->len = 0; cs->capacity = 0; } @@ -49,37 +47,15 @@ cstring_assign(cstring *cs, const char *s) } void -cstring_append(cstring *cs, const char *s) -{ - if (!cstring_empty(cs)) { - size_t newlen = cs->len + strlen(s); - if (CSTRING_EXCEEDS_CAPACITY(newlen, cs->capacity)) - cstring_resize(cs, newlen << 1); - strcat(cs->str, s); - cs->len = newlen; - } - else cstring_assign(cs, s); -} - -void -cstring_prepend(cstring *cs, const char *s) -{ - cstring_insert(cs, s, 0); -} - -void cstring_insert(cstring *cs, const char *s, size_t i) { - if (!CSTRING_OUT_OF_BOUNDS(cs, i) - && !cstring_empty(cs) // useless check? - && s != NULL) - { + if (!CSTRING_OUT_OF_BOUNDS(cs, i) && s != NULL) { size_t slen = strlen(s); size_t newlen = cs->len + slen; char *tmp = (char *)malloc(newlen + 1); memcpy(tmp, cs->str, i); memcpy(tmp + i, s, slen); - memcpy(tmp + i + slen, cs->str + i, cs->len); + memcpy(tmp + slen + i, cs->str + i , newlen - slen - i); if (CSTRING_EXCEEDS_CAPACITY(newlen, cs->capacity)) cstring_resize(cs, newlen << 1); free(cs->str); @@ -136,8 +112,8 @@ cstring_trim(cstring *cs, const char *s) void cstring_push_back(cstring *cs, char c) { - if (CSTRING_EXCEEDS_CAPACITY(cs->len + 1, cs->capacity)) - cstring_resize(cs, (cs->len + 1) << 1); + if (CSTRING_EXCEEDS_CAPACITY(cs->len, cs->capacity)) + cstring_resize(cs, cs->len << 1); cs->str[cs->len] = c; cs->str[++cs->len] = '\0'; } @@ -196,12 +172,6 @@ cstring_swap(cstring *lhs, cstring *rhs) } void -cstring_shrink_to_fit(cstring *cs) -{ - cstring_resize(cs, cs->len); -} - -void cstring_clear(cstring *cs) { if (!cstring_empty(cs)) free(cs->str); @@ -211,11 +181,14 @@ cstring_clear(cstring *cs) cs->capacity = 0; } +#define CSTRING_CHECK(cs, s) \ + if (cstring_empty(cs) || !*s) \ + return CSTRING_NPOS + size_t cstring_find(const cstring *cs, const char *s) { - if (cstring_empty(cs) || !*s) - return CSTRING_NPOS; + CSTRING_CHECK(cs, s); CSTRING_FIND_OCCURENCE(cs, s, strstr); return CSTRING_NPOS; } @@ -223,17 +196,29 @@ cstring_find(const cstring *cs, const char *s) size_t cstring_rfind(const cstring *cs, const char *s) { - if (cstring_empty(cs) || !*s) - return CSTRING_NPOS; - /* IMPLEMENT */ - return CSTRING_NPOS; + CSTRING_CHECK(cs, s); + /* SIMPLIFY */ + int found; + size_t idx = -1; + size_t slen = strlen(s); + size_t i = 0, j; + for (; i <= cs->len - slen; i++) { + found = 1; + for (j = 0; j < slen; j++) { + if (cs->str[i + j] != s[j]) { + found = 0; + break; + } + } + if (found) idx = i; + } + return (idx == -1 ? CSTRING_NPOS : idx); } size_t cstring_find_first_of(const cstring *cs, const char *s) { - if (cstring_empty(cs) || !*s) - return CSTRING_NPOS; + CSTRING_CHECK(cs, s); for (; *s; s++) { CSTRING_FIND_OCCURENCE(cs, *s, strchr); } @@ -243,8 +228,7 @@ cstring_find_first_of(const cstring *cs, const char *s) size_t cstring_find_first_not_of(const cstring *cs, const char *s) { - if (cstring_empty(cs) || !*s) - return CSTRING_NPOS; + CSTRING_CHECK(cs, s); size_t i = 0; for (; i < cs->len; i++) if (!cstring_is_one_of(cs->str[i], s)) @@ -255,8 +239,7 @@ cstring_find_first_not_of(const cstring *cs, const char *s) size_t cstring_find_last_of(const cstring *cs, const char *s) { - if (cstring_empty(cs) || !*s) - return CSTRING_NPOS; + CSTRING_CHECK(cs, s); size_t i = *(s + strlen(s)); for (; i >= 0; i--) { CSTRING_FIND_OCCURENCE(cs, s[i], strrchr); @@ -267,8 +250,7 @@ cstring_find_last_of(const cstring *cs, const char *s) size_t cstring_find_last_not_of(const cstring *cs, const char *s) { - if (cstring_empty(cs) || !*s) - return CSTRING_NPOS; + CSTRING_CHECK(cs, s); size_t i = cs->len; for (; i >= 0; i--) if (!cstring_is_one_of(cs->str[i], s)) @@ -276,47 +258,7 @@ cstring_find_last_not_of(const cstring *cs, const char *s) return CSTRING_NPOS; } -char -cstring_front(const cstring *cs) -{ - return cs->str[0]; -} - -char -cstring_back(const cstring *cs) -{ - return (!cstring_empty(cs) ? cs->str[cs->len - 1] : cs->str[0]); -} - -int -cstring_empty(const cstring *cs) -{ - return (cs->str == NULL && cs->len == 0); -} - -int -cstring_starts_with_str(const cstring *cs, const char *s) -{ - return (cstring_find(cs, s) == 0); -} - -int -cstring_ends_with_str(const cstring *cs, const char *s) -{ - return (cstring_find(cs, s) == cs->len - strlen(s)); -} - -int -cstring_starts_with_char(const cstring *cs, char c) -{ - return (cs->str[0] == c); -} - -int -cstring_ends_with_char(const cstring *cs, char c) -{ - return (cs->str[cs->len] = c); -} +#undef CSTR_CHECK char * cstring_copy(const char *s) @@ -331,11 +273,8 @@ cstring_copy(const char *s) void cstring_resize(cstring *cs, size_t newcapacity) { - if (!cstring_empty(cs)) { - cs->capacity = newcapacity; - cs->str = (char *)realloc(cs->str, cs->capacity + 1); - cs->str[cs->len] = '\0'; - } + cs->str = (char *)realloc(cs->str, newcapacity); + cs->capacity = newcapacity; } cstring * @@ -349,33 +288,3 @@ cstring_getline(FILE *fd, cstring *cs, char delim) } return (c == EOF) ? NULL : cs; } - -int -cstring_equals(const cstring *lhs, const cstring *rhs) -{ - return (strcmp(lhs->str, rhs->str) == 0); -} - -int -cstring_greater(const cstring *lhs, const cstring *rhs) -{ - return (strcmp(lhs->str, rhs->str) > 0); -} - -int -cstring_greater_or_equals(const cstring *lhs, const cstring *rhs) -{ - return (strcmp(lhs->str, rhs->str) >= 0); -} - -int -cstring_less(const cstring *lhs, const cstring *rhs) -{ - return (strcmp(lhs->str, rhs->str) < 0); -} - -int -cstring_less_or_equals(const cstring *lhs, const cstring *rhs) -{ - return (strcmp(lhs->str, rhs->str) <= 0); -} diff --git a/cstring.h b/cstring.h @@ -5,6 +5,10 @@ #include <stdlib.h> #include <string.h> +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + #define CSTRING_NPOS -1 #define CSTRING_OUT_OF_BOUNDS(cs, pos) ((pos) > cs->len) @@ -17,8 +21,6 @@ typedef struct cstring { extern cstring cstring_create(const char *); extern void cstring_delete(cstring *); extern void cstring_assign(cstring *, const char *); -extern void cstring_append(cstring *, const char *); -extern void cstring_prepend(cstring *, const char *); extern void cstring_insert(cstring *, const char *, size_t); extern void cstring_erase(cstring *, size_t, size_t); extern void cstring_erase_matching(cstring *, const char *); @@ -30,31 +32,110 @@ extern void cstring_replace_char(cstring *, size_t, char); extern void cstring_replace_str(cstring *, const char *, size_t, size_t); extern cstring cstring_substr(const cstring *, size_t, size_t); extern void cstring_swap(cstring *, cstring *); -extern void cstring_shrink_to_fit(cstring *); extern void cstring_clear(cstring *); extern size_t cstring_find(const cstring *, const char *); -extern size_t cstring_rfind(const cstring *, const char *); /* implement */ +extern size_t cstring_rfind(const cstring *, const char *); extern size_t cstring_find_first_of(const cstring *, const char *); 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_front(const cstring *); -extern char cstring_back(const cstring *); -extern int cstring_empty(const cstring *); -extern int cstring_starts_with_str(const cstring *, const char *); -extern int cstring_ends_with_str(const cstring *, const char *); -extern int cstring_starts_with_char(const cstring *, char); -extern int cstring_ends_with_char(const cstring *, char); extern char *cstring_copy(const char *); extern void cstring_resize(cstring *, size_t); extern cstring *cstring_getline(FILE *, cstring *, char); -/* might be useless */ -extern int cstring_equal(const cstring *, const cstring *); -extern int cstring_not_equal(const cstring *, const cstring *); -extern int cstring_greater(const cstring *, const cstring *); -extern int cstring_greater_or_equal(const cstring *, const cstring *); -extern int cstring_less(const cstring *, const cstring *); -extern int cstring_less_or_equal(const cstring *, const cstring *); +/* inlines */ +static inline void +cstring_prepend(cstring *cs, const char *s) +{ + cstring_insert(cs, s, 0); +} + +static inline void +cstring_append(cstring *cs, const char *s) +{ + cstring_insert(cs, s, cs->len); +} + +static inline void +cstring_shrink_to_fit(cstring *cs) +{ + cstring_resize(cs, cs->len); +} + +static inline int +cstring_empty(const cstring *cs) +{ + return (cs->str == NULL && cs->len == 0); +} + +static inline char +cstring_front(const cstring *cs) +{ + return cs->str[0]; +} + +static inline char +cstring_back(const cstring *cs) +{ + return (!cstring_empty(cs) ? cs->str[cs->len - 1] : cs->str[0]); +} + +static inline int +cstring_starts_with_str(const cstring *cs, const char *s) +{ + return (cstring_find(cs, s) == 0); +} + +static inline int +cstring_ends_with_str(const cstring *cs, const char *s) +{ + return (cstring_find(cs, s) == cs->len - strlen(s)); +} + +static inline int +cstring_starts_with_char(const cstring *cs, char c) +{ + return (cs->str[0] == c); +} + +static inline int +cstring_ends_with_char(const cstring *cs, char c) +{ + return (cs->str[cs->len] = c); +} + +static inline int +cstring_equal(const cstring *lhs, const cstring *rhs) +{ + return (strcmp(lhs->str, rhs->str) == 0); +} + +static inline int +cstring_greater(const cstring *lhs, const cstring *rhs) +{ + return (strcmp(lhs->str, rhs->str) > 0); +} + +static inline int +cstring_greater_or_equal(const cstring *lhs, const cstring *rhs) +{ + return (strcmp(lhs->str, rhs->str) >= 0); +} + +static inline int +cstring_less(const cstring *lhs, const cstring *rhs) +{ + return (strcmp(lhs->str, rhs->str) < 0); +} + +static inline int +cstring_less_or_equal(const cstring *lhs, const cstring *rhs) +{ + return (strcmp(lhs->str, rhs->str) <= 0); +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ #endif /* CSTRING_H */ diff --git a/cstring.o b/cstring.o Binary files differ. diff --git a/libcstring.a b/libcstring.a Binary files differ. diff --git a/tests/test.c b/tests/test.c @@ -8,12 +8,15 @@ 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); - cstring_append(&s, "Append"); - printf("cstring_append: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); - cstring_assign(&s, "New string"); printf("cstring_assign: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); + cstring_append(&s, "Appended text"); + printf("cstring_append: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); + + cstring_prepend(&s, "OK"); + printf("cstring_prepend: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); + cstring_push_back(&s, 'c'); printf("cstring_push_back: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); @@ -50,9 +53,6 @@ main(int argc, char **argv) cstring_insert(&s, "New text", 2); printf("cstring_insert: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); - cstring_prepend(&s, "OK"); - printf("cstring_prepend: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); - cstring_delete(&s); if (cstring_empty(&s)) printf("cstring_delete: Deleted string.\n");