cstring

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

commit 21d4d074f6424f434aa88c3213cbc898f14dbcde
parent 22f66d0e6af558b9023c37c5683ac999efd6e90e
Author: Christos Margiolis <christos@margiolis.net>
Date:   Thu, 24 Sep 2020 12:57:11 +0300

added more find and erase functions

Diffstat:
MREADME.md | 61++++++++++++++++++++++++++++++++++++++-----------------------
Mcstring.3 | 28++++++++++++++++++++++++++++
Mcstring.c | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mcstring.h | 12++++++++++--
Mtests/test.c | 7+++++++
5 files changed, 148 insertions(+), 33 deletions(-)

diff --git a/README.md b/README.md @@ -1,6 +1,6 @@ # cstring -A simple and lightweight string library for C. +A simple and lightweight string library for C inspired by C++'s STL `string` class. ## Building @@ -33,28 +33,43 @@ The recommended way of initializing an empty string is by doing `cstring foo = c ## Functions -* `cstring_create`: Initiliazes string -* `cstring_delete`: Deallocates string -* `cstring_assign`: Assigns a new string to the current string -* `cstring_append`: Appends a string to the current string -* `cstring_insert`: Inserts a string at a specific index -* `cstring_push_back`: Adds a character at the end of the string -* `cstring_pop_back`: Removes the last character in the string -* `cstring_replace_char`: Replaces a character at a specific index -* `cstring_clear`: Erases the whole string -* `cstring_exists`: Checks to see if a (sub)string exists in the string -* `cstring_front`: Returns the first character of the string -* `cstring_back`: Returns the last character of the string -* `cstring_empty`: Checks if the string is empty -* `cstring_copy`: Makes a copy of a given `const char *` -* `cstring_resize`: Resizes the array stored inside the string `struct` -* `cstring_getline`: Reads a line from a stream -* `cstring_equal`: True if the strings are equal -* `cstring_not_equal`: True if the strings are not equal -* `cstring_greater`: True if the left hand string is greater than the right hand one -* `cstring_greater_or_equal`: True if the left hand string is greater than or equal to the right hand one -* `cstring_less`: True if the left hand string is less than the right hand one -* `cstring_less_or_equal`: True if the left hand string is less than or equal to the right hand one +* `cstring cstring_create(const char *s)`: Initiliaze string +* `void cstring_delete(cstring *cs)`: Deallocate string +* `void cstring_assign(cstring *cs, const char *s)`: Assign new string +* `void cstring_append(cstring *cs, const char *s)`: Append to end of string +* `void cstring_prepend(cstring *cs, const char *s)`: Prepend to beginning of string +* `void cstring_insert(cstring *cs, const char *s, size_t i)`: Insert to a specific index +* `void cstring_erase(cstring *cs, size_t pos, size_t len)`: Erase portion of string +* `void cstring_erase_matching(cstring *cs, const char *s)`: Erase first match +* `void cstring_erase_all_matching(cstring *cs, const char *s)`: Erase all matches +* `void cstring_trim(cstring *cs, char c)`: Trim character +* `void cstring_push_back(cstring *cs, char c)`: Add character to end of string +* `void cstring_pop_back(cstring *cs)`: Remove the last character from string +* `void cstring_replace_char(cstring *cs, size_t i, char c)`: Replace character at a specific index +* `void cstring_replace_str(cstring *cs, const char *s, size_t pos, size_t len)`: Replace portion of string +* `cstring cstring_substr(const cstring *cs, size_t pos, size_t len)`: Extract a substring +* `void cstring_swap(cstring *lhs, cstring *rhs)`: Swap contents of two strings +* `void cstring_shrink_to_fit(cstring *cs)`: Shrink string's capacity to fit its size +* `void cstring_clear(cstring *cs)`: Clear contents of string +* `size_t cstring_find(const cstring *cs, const char *s)`: Find index of first match (string) +* `size_t cstring_find_first_of(const cstring *cs, char c)`: Find index of first match (character) +* `size_t cstring_find_last_of(const cstring *cs, char c)`: Find index of last match (character) +* `char cstring_front(const cstring *cs)`: Get first character in string +* `char cstring_back(const cstring *cs)`: Get last character in string +* `int cstring_empty(const cstring *cs)`: Check if string is empty +* `int cstring_starts_with_str(const cstring *cs, const char *s)`: Check if string starts with `s` +* `int cstring_ends_with_str(const cstring *cs, const char *s)`: Check if string ends with `s` +* `int cstring_starts_with_char(const cstring *cs, char c)`: Check if string starts with `c` +* `int cstring_ends_with_char(const cstring *cs, char c)`: Check if string ends with `c` +* `char *cstring_copy(const char *cs)`: Copy contents of `s` +* `void cstring_resize(cstring *cs, size_t newcapacity)`: Resize string +* `cstring *cstring_getline(FILE *fd, cstring *cs, char delim)`: Read a line from a `FILE` stream +* `int cstring_equal(const cstring *lhs, const cstring *rhs)`: Check if strings are equal +* `int cstring_not_equal(const cstring *lhs, const cstring *rhs)`: Check if strings are not equal +* `int cstring_greater(const cstring *lhs, const cstring *rhs)`: Check if `lhs` is greater than `rhs` +* `int cstring_greater_or_equal(const cstring *lhs, const cstring *rhs)`: True `lhs` is greater of equal to `rhs` +* `int cstring_less(const cstring *lhs, const cstring *rhs)`: Check if `lhs` is less than `rhs` +* `int cstring_less_or_equal(const cstring *lhs, const cstring *rhs)`: Check if `lhs` is less or equal to `rhs` ## Example diff --git a/cstring.3 b/cstring.3 @@ -18,12 +18,24 @@ Assign a new string to the current string. .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 +.BR void\ cstring_erase_matching(cstring\ *cs,\ const\ char\ *s) +Erase first match from the string. +.TP +.BR void\ cstring_erase_all_matching(cstring\ *cs,\ const\ char\ *s) +Erase all matches from the string. +.TP +.BR void\ cstring_trim(cstring\ *cs,\ char\ c) +Trim character from string. +.TP .BR void\ cstring_push_back(cstring\ *cs,\ char\ c) Add a character at the end of the string. .TP @@ -66,6 +78,22 @@ Returns the last character of the string. .BR int\ cstring_empty(const\ cstring\ *cs) Check to see if the string is empty. .TP +.BR int\ cstring_starts_with_str(const\ cstring\ *cs,\ const\ char\ *s) +Check to see if string begins with +.I s +.TP +.BR int\ cstring_ends_with_str(const\ cstring\ *cs,\ const\ char\ *s) +Check to see if string ends with +.I s +.TP +.BR int\ cstring_starts_with_char(const\ cstring\ *cs,\ char\ c) +Check to see if string starts with +.I c +.TP +.BR int\ cstring_ends_with_char(const\ cstring\ *cs,\ char\ c) +Check to see if string ends with +.I c +.TP .BR char\ *cstring_copy(const\ char\ *s) Make a copy of a given .I const\ char\ * diff --git a/cstring.c b/cstring.c @@ -44,9 +44,18 @@ cstring_append(cstring *cs, const char *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_empty(cs) && !CSTRING_OUT_OF_BOUNDS(cs, i)) { + if (!CSTRING_OUT_OF_BOUNDS(cs, i) + && !cstring_empty(cs) + && s != NULL) + { size_t slen = strlen(s); size_t newlen = cs->len + slen; char *tmp1 = (char *)malloc(i + 1); @@ -68,9 +77,9 @@ cstring_insert(cstring *cs, const char *s, size_t i) void cstring_erase(cstring *cs, size_t pos, size_t len) { - if (!CSTRING_OUT_OF_BOUNDS(cs, pos) - && !CSTRING_OUT_OF_BOUNDS(cs, len) - && pos < len) + if (!cstring_empty(cs) + && !CSTRING_OUT_OF_BOUNDS(cs, pos) + && !CSTRING_OUT_OF_BOUNDS(cs, len)) { size_t newlen = cs->len - len; char *tmp = (char *)malloc(newlen + 1); @@ -84,6 +93,32 @@ cstring_erase(cstring *cs, size_t pos, size_t len) } void +cstring_erase_matching(cstring *cs, const char *s) +{ + if (s != NULL) + cstring_erase(cs, cstring_find(cs, s), strlen(s)); +} + +void +cstring_erase_all_matching(cstring *cs, const char *s) +{ + if (s != NULL) { + size_t len = strlen(s); + size_t i = cstring_find(cs, s); + for (; i != CSTRING_NPOS; i = cstring_find(cs, s)) + cstring_erase(cs, i, len); + } +} + +void +cstring_trim(cstring *cs, char c) +{ + size_t i = cstring_find_first_of(cs, c); + for (; i != CSTRING_NPOS; i = cstring_find_first_of(cs, c)) + cstring_erase(cs, i, 1); +} + +void cstring_push_back(cstring *cs, char c) { if (CSTRING_EXCEEDS_CAPACITY(cs->len + 1, cs->capacity)) @@ -116,8 +151,7 @@ cstring_replace_str(cstring *cs, const char *s, size_t pos, size_t len) { if (!CSTRING_OUT_OF_BOUNDS(cs, pos) && !CSTRING_OUT_OF_BOUNDS(cs, len) - && !CSTRING_OUT_OF_BOUNDS(cs, pos + len) - && pos < len) + && !CSTRING_OUT_OF_BOUNDS(cs, pos + len)) { int i = pos; for (; i < len && *s; s++, i++) @@ -129,8 +163,7 @@ cstring cstring_substr(const cstring *cs, size_t pos, size_t len) { if (CSTRING_OUT_OF_BOUNDS(cs, pos) - || CSTRING_OUT_OF_BOUNDS(cs, len) - || pos < len) + || CSTRING_OUT_OF_BOUNDS(cs, len)) return cstring_create(""); cstring substr = cstring_create(&cs->str[pos]); substr.len = len; @@ -208,6 +241,30 @@ 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); +} + char * cstring_copy(const char *s) { diff --git a/cstring.h b/cstring.h @@ -13,7 +13,7 @@ #define CSTRING_FIND_OCCURENCE(cs, s, func) \ char *_found; \ if ((_found = func(cs->str, (s))) != NULL) \ - return (_found - cs->str + 1) + return (_found - cs->str) // MAYBE NEEDS +1 typedef struct cstring { char *str; @@ -25,8 +25,12 @@ 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_insert(cstring *, const char *, size_t); +extern void cstring_prepend(cstring *, const char *); +extern void cstring_insert(cstring *, const char *, size_t); // FIX extern void cstring_erase(cstring *, size_t, size_t); +extern void cstring_erase_matching(cstring *, const char *); +extern void cstring_erase_all_matching(cstring *, const char *); +extern void cstring_trim(cstring *, char); extern void cstring_push_back(cstring *, char); extern void cstring_pop_back(cstring *); extern void cstring_replace_char(cstring *, size_t, char); @@ -41,6 +45,10 @@ extern size_t cstring_find_last_of(const cstring *, 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); diff --git a/tests/test.c b/tests/test.c @@ -40,6 +40,13 @@ main(int argc, char **argv) cstring_erase(&s, 1, 4); printf("cstring_erase: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); + cstring_assign(&s, "hello aaaa hello abbb helo hello"); + cstring_erase_all_matching(&s, "hello"); + printf("cstring_erase_all_matching: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); + + cstring_trim(&s, ' '); + printf("cstring_trim: %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");