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:
M | README.md | | | 61 | ++++++++++++++++++++++++++++++++++++++----------------------- |
M | cstring.3 | | | 28 | ++++++++++++++++++++++++++++ |
M | cstring.c | | | 73 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- |
M | cstring.h | | | 12 | ++++++++++-- |
M | tests/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");