commit 7d2d6077216e8b55332366757c81d18bbf38f9f7
parent 76e965dfaa56d81fff432641517a0b1e69b53463
Author: Christos Margiolis <christos@margiolis.net>
Date: Tue, 22 Sep 2020 20:07:02 +0300
removed cstring_exists, added some utility macros, implemented a few find functions
Diffstat:
M | cstring.3 | | | 48 | ++++++++++++++++++++++++++++++++++++++++++++++-- |
M | cstring.c | | | 64 | ++++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
M | cstring.h | | | 16 | +++++++++++++++- |
M | test.c | | | 3 | --- |
4 files changed, 113 insertions(+), 18 deletions(-)
diff --git a/cstring.3 b/cstring.3
@@ -30,11 +30,20 @@ Remove the last character in the string.
.BR void\ cstring_replace_char(cstring\ *,\ const\ char\ *)
Replace character at a specific index.
.TP
+.BR cstring\ cstring_substr(cstring\ *,\ size_t\ ,\ size_t)
+Extract a substring from current string.
+.TP
.BR void\ cstring_clear(cstring\ *)
Erase the whole string.
.TP
-.BR int\ cstring_exists(const\ cstring\ *,\ const\ char\ *)
-Check to see if a (sub)string exists in the string.
+.BR size_t\ cstring_find(const\ cstring\ *,\ const\ char\ *)
+Find first occurence of a pattern in string.
+.TP
+.BR size_t\ cstring_find_first_of(const\ cstring\ *,\ char)
+Find first occurence of a character in string.
+.TP
+.BR size_t\ cstring_find_last_of(const\ cstring\ *,\ char)
+Find last occurence of a character in string.
.TP
.BR char\ cstring_front(const\ cstring\ *)
Returns the first character of the string.
@@ -61,6 +70,41 @@ Read a line from a
.I FILE
stream. Similar behavior to
.I stdio's\ getline
+.SH MACROS
+The following macros should be used carefully
+.TP
+.BR CSTRING_OUT_OF_BOUNDS(cs,\ pos)
+Check if
+.I pos
+is out of bounds.
+.TP
+.BR CSTRING_EXCEEDS_CAPACITY(len,\ cap)
+Check if
+.I len
+is more than
+.I cap
+in order to resize the string.
+.TP
+.BR CSTRING_FIND_OCCURENCE(cs,\ s,\ func)
+Although it should be used internally, this macro
+returns the index at which
+.I s
+occurs in the string according to
+.I func
+which is used as a callback function, although it is
+meant to support
+.I strstr
+,
+.I strchr
+and
+.I strrchr
+from
+.I string.h
+.SH CONSTANTS
+.TP
+.BR CSTRING_NPOS
+This constant signifies that a pattern hasn't been found inside
+the string. It's value is -1.
.SH USAGE
You must
.B always
diff --git a/cstring.c b/cstring.c
@@ -26,7 +26,8 @@ cstring_assign(cstring *cs, const char *s)
if (!cstring_empty(cs)) free(cs->str);
cs->str = cstring_copy(s);
cs->len = newlen;
- if (newlen >= cs->capacity) cstring_resize(cs, newlen << 1);
+ if (CSTRING_EXCEEDS_CAPACITY(newlen, cs->capacity))
+ cstring_resize(cs, newlen << 1);
}
void
@@ -34,7 +35,8 @@ cstring_append(cstring *cs, const char *s)
{
if (!cstring_empty(cs)) {
size_t newlen = cs->len + strlen(s);
- if (newlen >= cs->capacity) cstring_resize(cs, newlen << 1);
+ if (CSTRING_EXCEEDS_CAPACITY(newlen, cs->capacity))
+ cstring_resize(cs, newlen << 1);
strcat(cs->str, s);
cs->len = newlen;
}
@@ -43,14 +45,15 @@ cstring_append(cstring *cs, const char *s)
void
cstring_insert(cstring *cs, const char *s, size_t i)
{
- if (!cstring_empty(cs) && i < cs->len) {
+ if (!cstring_empty(cs) && !CSTRING_OUT_OF_BOUNDS(cs, i)) {
size_t slen = strlen(s);
size_t newlen = cs->len + slen;
char *tmp1 = (char *)malloc(i + 1);
char *tmp2 = (char *)malloc(cs->len - i + 1);
memcpy(tmp1, cs->str, i + 1);
memcpy(tmp2, cs->str + i, cs->len + 1);
- if (newlen >= cs->capacity) cstring_resize(cs, newlen << 1);
+ if (CSTRING_EXCEEDS_CAPACITY(newlen, cs->capacity))
+ cstring_resize(cs, newlen << 1);
memcpy(cs->str, tmp1, i + 1);
memcpy(cs->str + i, s, slen + 1);
memcpy(cs->str + slen + i, tmp2, cs->len - i + 1);
@@ -64,8 +67,9 @@ cstring_insert(cstring *cs, const char *s, size_t i)
void
cstring_push_back(cstring *cs, char c)
{
- if (cs->len + 1 >= cs->capacity) cstring_resize(cs, (cs->len + 1) << 1);
- cs->str[cs->len] = c;
+ if (CSTRING_EXCEEDS_CAPACITY(cs->len + 1, cs->capacity))
+ cstring_resize(cs, (cs->len + 1) << 1);
+ cs->str[cs->len] = c;
cs->str[++cs->len] = '\0';
}
@@ -84,22 +88,58 @@ cstring_pop_back(cstring *cs)
void
cstring_replace_char(cstring *cs, size_t i, char c)
{
- if (i < cs->len) cs->str[i] = c;
+ if (!CSTRING_OUT_OF_BOUNDS(cs, i))
+ cs->str[i] = c;
+}
+
+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)
+ || len < pos)
+ return cstring_create("");
+ cstring substr = cstring_create(&cs->str[pos]);
+ substr.len = len;
+ substr.str[len] = '\0';
+ // maybe cstring_resize
+ return substr;
}
void
cstring_clear(cstring *cs)
{
if (!cstring_empty(cs)) free(cs->str);
- cs->str = (char *)malloc(1);
+ cs->str = (char *)malloc(1);
cs->str[0] = '\0';
- cs->len = 0;
+ cs->len = 0;
}
-int
-cstring_exists(const cstring *cs, const char *s)
+size_t
+cstring_find(const cstring *cs, const char *s)
+{
+ if (cstring_empty(cs) || !*s)
+ return CSTRING_NPOS;
+ CSTRING_FIND_OCCURENCE(cs, s, strstr);
+ return CSTRING_NPOS;
+}
+
+size_t
+cstring_find_first_of(const cstring *cs, char c)
+{
+ if (cstring_empty(cs) || c == '\0')
+ return CSTRING_NPOS;
+ CSTRING_FIND_OCCURENCE(cs, c, strchr);
+ return CSTRING_NPOS;
+}
+
+size_t
+cstring_find_last_of(const cstring *cs, char c)
{
- return (strstr(cs->str, s) != NULL);
+ if (cstring_empty(cs) || c == '\0')
+ return CSTRING_NPOS;
+ CSTRING_FIND_OCCURENCE(cs, c, strrchr);
+ return CSTRING_NPOS;
}
char
diff --git a/cstring.h b/cstring.h
@@ -5,6 +5,16 @@
#include <stdlib.h>
#include <string.h>
+#define CSTRING_NPOS -1
+
+#define CSTRING_OUT_OF_BOUNDS(cs, pos) ((pos) > cs->len)
+#define CSTRING_EXCEEDS_CAPACITY(len, cap) ((len) >= (cap))
+
+#define CSTRING_FIND_OCCURENCE(cs, s, func) \
+ char *_found; \
+ if ((_found = func(cs->str, (s))) != NULL) \
+ return (_found - cs->str + 1)
+
typedef struct cstring {
char *str;
size_t len;
@@ -19,14 +29,18 @@ extern void cstring_insert(cstring *, const char *, size_t);
extern void cstring_push_back(cstring *, char);
extern void cstring_pop_back(cstring *);
extern void cstring_replace_char(cstring *, size_t, char);
+extern cstring cstring_substr(const cstring *, size_t, size_t);
extern void cstring_clear(cstring *);
-extern int cstring_exists(const cstring *, const char *);
+extern size_t cstring_find(const cstring *, const char *);
+extern size_t cstring_find_first_of(const cstring *, char);
+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 char *cstring_copy(const char *);
extern void cstring_resize(cstring *, size_t);
extern cstring *cstring_getline(FILE *, cstring *, char);
+//extern cstring *cstring_tok(const cstring *, const char *);
/* might be useless */
extern int cstring_equal(const cstring *, const cstring *);
diff --git a/test.c b/test.c
@@ -14,9 +14,6 @@ main(int argc, char **argv)
cstring_assign(&s, "New string");
printf("cstring_assign: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);
- if (cstring_exists(&s, "string"))
- printf("cstring_exists: \"string\" exists!\n");
-
cstring_push_back(&s, 'c');
printf("cstring_push_back: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);