cstring

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

commit 22f66d0e6af558b9023c37c5683ac999efd6e90e
parent 7d2d6077216e8b55332366757c81d18bbf38f9f7
Author: Christos Margiolis <christos@margiolis.net>
Date:   Wed, 23 Sep 2020 23:09:13 +0300

added erase, swap, shrink_to_fit and replace_str functions

Diffstat:
Mcstring.3 | 54+++++++++++++++++++++++++++++++++---------------------
Mcstring.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++--
Mcstring.h | 5++++-
Dtest.c | 41-----------------------------------------
Atests/test.c | 47+++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 134 insertions(+), 65 deletions(-)

diff --git a/cstring.3 b/cstring.3 @@ -4,68 +4,80 @@ cstring \- A simple and lightweight string library for C inspired by C++'s STL string class .SH FUNCTIONS .TP -.BR cstring\ cstring_create(const\ char\ *) +.BR cstring\ cstring_create(const\ char\ *s) Instanciates and initializes a .I cstring object. .TP -.BR void\ cstring_delete(cstring\ *) +.BR void\ cstring_delete(cstring\ *cs) Deallocate string. .TP -.BR void\ cstring_assign(cstring\ *,\ const\ char\ *) +.BR void\ cstring_assign(cstring\ *cs,\ const\ char\ *s) Assign a new string to the current string. .TP -.BR void\ cstring_append(cstring\ *,\ const\ char\ *) -Append a string at the end of the current string. +.BR void\ cstring_append(cstring\ *cs,\ const\ char\ *s) +Append to end of string. .TP -.BR void\ cstring_insert(cstring\ *,\ const\ char\ *,\ size_t) -Insert a string at a specific index. +.BR void\ cstring_insert(cstring\ *cs,\ const\ char\ *s,\ size_t\ i) +Insert at a specific index. .TP -.BR void\ cstring_push_back(cstring\ *,\ char) +.BR void\ cstring_erase(cstring\ *cs,\ size_t\ pos,\ size_t\ len) +Erase a portion of the string. +.TP +.BR void\ cstring_push_back(cstring\ *cs,\ char\ c) Add a character at the end of the string. .TP -.BR void\ cstring_pop_back(cstring\ *) +.BR void\ cstring_pop_back(cstring\ *cs) Remove the last character in the string. .TP -.BR void\ cstring_replace_char(cstring\ *,\ const\ char\ *) +.BR void\ cstring_replace_char(cstring\ *cs,\ size_t\ i,\ char\ c) Replace character at a specific index. .TP -.BR cstring\ cstring_substr(cstring\ *,\ size_t\ ,\ size_t) +.BR void\ cstring_replace_str(cstring\ *cs,\ const\ char\ *s,\ size_t\ pos,\ size_t\ len) +Replace portion of the string. +.TP +.BR cstring\ cstring_substr(cstring\ *cs,\ size_t\ pos,\ size_t\ len) Extract a substring from current string. .TP -.BR void\ cstring_clear(cstring\ *) +.BR void\ cstring_swap(cstring\ *lhs,\ cstring\ *rhs) +Swap contents of two strings. +.TP +.BR void\ cstring_shrink_to_fit(cstring\ *cs) +Reduce string's capacity to its size. +.TP +.BR void\ cstring_clear(cstring\ *cs) Erase the whole string. .TP -.BR size_t\ cstring_find(const\ cstring\ *,\ const\ char\ *) +.BR size_t\ cstring_find(const\ cstring\ *cs,\ const\ char\ *s) Find first occurence of a pattern in string. .TP -.BR size_t\ cstring_find_first_of(const\ cstring\ *,\ char) +.BR size_t\ cstring_find_first_of(const\ cstring\ *cs,\ char\ c) Find first occurence of a character in string. .TP -.BR size_t\ cstring_find_last_of(const\ cstring\ *,\ char) +.BR size_t\ cstring_find_last_of(const\ cstring\ *cs,\ char\ c) Find last occurence of a character in string. .TP -.BR char\ cstring_front(const\ cstring\ *) +.BR char\ cstring_front(const\ cstring\ *cs) Returns the first character of the string. .TP -.BR char\ cstring_back(const\ cstring\ *) +.BR char\ cstring_back(const\ cstring\ *cs) Returns the last character of the string. .TP -.BR int\ cstring_empty(const\ cstring\ *) +.BR int\ cstring_empty(const\ cstring\ *cs) Check to see if the string is empty. .TP -.BR char\ *cstring_copy(const\ char\ *) +.BR char\ *cstring_copy(const\ char\ *s) Make a copy of a given .I const\ char\ * .TP -.BR void\ cstring_resize(cstring\ *,\ size_t) +.BR void\ cstring_resize(cstring\ *cs,\ size_t\ newcapacity) Resize the .I str array inside a given .I cstring struct. .TP -.BR cstring\ *cstring_getline(FILE\ *,\ cstring\ *,\ char) +.BR cstring\ *cstring_getline(FILE\ *fd,\ cstring\ *cs,\ char\ delim) Read a line from a .I FILE stream. Similar behavior to diff --git a/cstring.c b/cstring.c @@ -40,6 +40,7 @@ cstring_append(cstring *cs, const char *s) strcat(cs->str, s); cs->len = newlen; } + else cstring_assign(cs, s); // TEST } void @@ -65,6 +66,24 @@ 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) + { + size_t newlen = cs->len - len; + char *tmp = (char *)malloc(newlen + 1); + memcpy(tmp, cs->str, pos + 1); + memcpy(tmp + pos, cs->str + pos + len, newlen); + free(cs->str); + cs->len = newlen; + cs->str = tmp; + cs->str[cs->len] = '\0'; + } +} + +void cstring_push_back(cstring *cs, char c) { if (CSTRING_EXCEEDS_CAPACITY(cs->len + 1, cs->capacity)) @@ -92,27 +111,56 @@ cstring_replace_char(cstring *cs, size_t i, char c) cs->str[i] = c; } +void +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) + { + int i = pos; + for (; i < len && *s; s++, i++) + cs->str[i] = *s; + } +} + 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) + || pos < len) return cstring_create(""); cstring substr = cstring_create(&cs->str[pos]); substr.len = len; substr.str[len] = '\0'; - // maybe cstring_resize + cstring_shrink_to_fit(&substr); return substr; } void +cstring_swap(cstring *lhs, cstring *rhs) +{ + cstring tmp = *lhs; + *lhs = *rhs; + *rhs = tmp; +} + +void +cstring_shrink_to_fit(cstring *cs) +{ + cs->capacity = cs->len; +} + +void cstring_clear(cstring *cs) { if (!cstring_empty(cs)) free(cs->str); cs->str = (char *)malloc(1); cs->str[0] = '\0'; cs->len = 0; + cs->capacity = 0; } size_t diff --git a/cstring.h b/cstring.h @@ -26,10 +26,14 @@ 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_erase(cstring *, size_t, 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 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_find_first_of(const cstring *, char); @@ -40,7 +44,6 @@ 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 @@ -1,41 +0,0 @@ -#include "cstring.h" - -// Compilation: gcc test.c -lcstring - -int -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_push_back(&s, 'c'); - 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 (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); - - cstring_pop_back(&s); - printf("cstring_pop_back: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); - - cstring_clear(&s); - printf("cstring_clear: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); - - cstring_assign(&s, "CSTRING"); - 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_char(&s, 3, 'x'); - 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"); - - return 0; -} diff --git a/tests/test.c b/tests/test.c @@ -0,0 +1,47 @@ +#include "cstring.h" + +// Compilation: gcc test.c -lcstring + +int +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_push_back(&s, 'c'); + 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 (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); + + cstring_pop_back(&s); + printf("cstring_pop_back: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); + + cstring_clear(&s); + printf("cstring_clear: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); + + cstring_assign(&s, "CSTRING"); + 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_char(&s, 3, 'x'); + printf("cstring_replace_char: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); + + cstring_replace_str(&s, "hell", 0, strlen("hell")); + printf("cstring_replace_str: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); + + cstring_erase(&s, 1, 4); + printf("cstring_erase: %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"); + + return 0; +}