commit 918f03bbaf5cad59a306b006cab74674014c8fdf
parent 3cac34409d90fffc98ef2639a2af4c24616c814f
Author: Christos Margiolis <christos@margiolis.net>
Date: Sun, 16 Aug 2020 19:52:14 +0300
improved memory management, minimized some function calls
Diffstat:
4 files changed, 47 insertions(+), 39 deletions(-)
diff --git a/README.md b/README.md
@@ -20,9 +20,9 @@ along with your other files.
* `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_len`: Returns the length of the string
* `cstring_copy`: Makes a copy of a given `const char *`
* `cstring_resize`: Resizes the array stored inside the string `struct`
+* `cstring_len`: Returns the length of the string
* `cstring_equals`: True if the strings are equal
* `cstring_not_equals`: True if the strings are not equal
* `cstring_greater`: True if the left hand string is greater than the right hand one
@@ -34,7 +34,7 @@ along with your other files.
A recommended way of using this string is to **always** call the `cstring_delete` function when you're done
working with it, in order not to cause any memory leaks, as there's no *destructor* to do it for you.
-Open `test.c` for more.
+See `test.c` for more.
```c
#include <stdio.h>
diff --git a/cstring.c b/cstring.c
@@ -5,7 +5,8 @@ cstring_init(const char *s)
{
cstring cs;
cs.str = cstring_copy(s);
- cs.len = cstring_len(&cs);
+ cs.len = strlen(s);
+ cstring_resize(&cs, cs.len << 1);
return cs;
}
@@ -15,28 +16,33 @@ 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;
}
}
void
cstring_assign(cstring *cs, const char *s)
{
+ size_t newlen = strlen(s);
if (!cstring_empty(cs)) free(cs->str);
cs->str = cstring_copy(s);
- cs->len = cstring_len(cs);
+ cs->len = newlen;
+ if (newlen >= cs->capacity) cstring_resize(cs, newlen << 1);
}
void
cstring_append(cstring *cs, const char *s)
{
+ size_t newlen = cs->len + strlen(s);
if (!cstring_empty(cs))
{
- cstring_resize(cs, strlen(s));
+ if (newlen >= cs->capacity)
+ cstring_resize(cs, newlen << 1);
strcat(cs->str, s);
}
- cs->len = cstring_len(cs);
+ cs->len = newlen;
}
void
@@ -44,11 +50,13 @@ cstring_insert(cstring *cs, const char *s, size_t i)
{
if (!cstring_empty(cs) && i < cs->len)
{
+ /* TODO minimize function calls */
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);
- cstring_resize(cs, strlen(s));
+ if (cs->len + strlen(s) >= cs->capacity)
+ cstring_resize(cs, (cs->len + strlen(s)) << 1);
memcpy(cs->str, tmp1, i + 1);
memcpy(cs->str + i, s, strlen(s) + 1);
memcpy(cs->str + strlen(s) + i, tmp2, cs->len - i + 1);
@@ -62,16 +70,16 @@ cstring_insert(cstring *cs, const char *s, size_t i)
void
cstring_push_back(cstring *cs, char c)
{
- cstring_resize(cs, 1);
+ if (cs->len + 1 >= cs->capacity)
+ cstring_resize(cs, (cs->len + 1) << 1);
cs->str[cs->len] = c;
- cs->str[cs->len + 1] = '\0';
- cs->len = cstring_len(cs);
+ cs->str[++cs->len] = '\0';
}
void
cstring_pop_back(cstring *cs)
{
- if (cs->len - 1 > 0)
+ if (cs->len > 0)
{
char *tmp = (char *)malloc(cs->len);
memcpy(tmp, cs->str, cs->len);
@@ -121,37 +129,36 @@ cstring_empty(const cstring *cs)
return (cs->len == 0 || cs->str == NULL);
}
-size_t
-cstring_len(const cstring *cs)
-{
- return strlen(cs->str);
-}
-
char *
cstring_copy(const char *s)
{
- size_t l = strlen(s);
- char *tmp = (char *)malloc(l + 1);
- memcpy(tmp, s, l + 1);
- tmp[l] = '\0';
+ size_t len = strlen(s);
+ char *tmp = (char *)malloc(len + 1);
+ memcpy(tmp, s, len + 1);
+ tmp[len] = '\0';
return tmp;
}
void
-cstring_resize(cstring *cs, size_t n)
+cstring_resize(cstring *cs, size_t new_capacity)
{
- if (cstring_empty(cs))
+ if (!cstring_empty(cs))
{
- size_t l = cs->len + n;
- char *tmp = (char *)malloc(l + 1);
+ char *tmp = (char *)malloc(new_capacity + 1);
memcpy(tmp, cs->str, cs->len + 1);
free(cs->str);
- tmp[l] = '\0';
+ tmp[cs->len] = '\0';
cs->str = tmp;
- cs->len = cstring_len(cs);
+ cs->capacity = new_capacity;
}
}
+size_t
+cstring_len(const cstring *cs)
+{
+ return strlen(cs->str);
+}
+
int
cstring_equals(const cstring *lhs, const cstring *rhs)
{
diff --git a/cstring.h b/cstring.h
@@ -7,6 +7,7 @@
typedef struct {
char *str;
size_t len;
+ size_t capacity;
} cstring;
extern cstring cstring_init(const char *s);
@@ -22,11 +23,11 @@ extern int cstring_exists(const cstring *cs, const char *s);
extern char cstring_front(const cstring *cs);
extern char cstring_back(const cstring *cs);
extern int cstring_empty(const cstring *cs);
-extern size_t cstring_len(const cstring *cs);
extern char *cstring_copy(const char *s);
extern void cstring_resize(cstring *cs, size_t n);
/* might be useless */
+extern size_t cstring_len(const cstring *cs);
extern int cstring_equals(const cstring *lhs, const cstring *rhs);
extern int cstring_not_equals(const cstring *lhs, const cstring *rhs);
extern int cstring_greater(const cstring *lhs, const cstring *rhs);
diff --git a/test.c b/test.c
@@ -5,36 +5,36 @@ int
main(int argc, char **argv)
{
cstring s = cstring_init("Hello world");
- printf("cstring_init: %s (%ld)\n", s.str, s.len);
+ printf("cstring_init: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);
cstring_append(&s, "Append");
- printf("cstring_append: %s (%ld)\n", s.str, s.len);
+ printf("cstring_append: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);
cstring_assign(&s, "New string");
- printf("cstring_assign: %s (%ld)\n", s.str, s.len);
+ 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 (%ld)\n", s.str, s.len);
+ printf("cstring_push_back: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);
cstring_insert(&s, "Inserted text", 4);
- printf("cstring_insert: %s (%ld)\n", s.str, s.len);
+ printf("cstring_insert: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);
cstring_pop_back(&s);
- printf("cstring_pop_back: %s (%ld)\n", s.str, s.len);
+ printf("cstring_pop_back: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);
cstring_clear(&s);
- printf("cstring_clear: %s (%ld)\n", s.str, s.len);
+ printf("cstring_clear: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);
cstring_assign(&s, "CSTRING");
- printf("cstring_assign: %s (%ld)\n", s.str, s.len);
+ printf("cstring_assign: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity);
printf("cstring_front: %c\n", cstring_front(&s));
printf("cstring_back: %c\n", cstring_back(&s));
cstring_replace(&s, 3, 'x');
- printf("cstring_replace: %s (%ld)\n", s.str, s.len);
+ printf("cstring_replace: %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");