cstring

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

commit 3cac34409d90fffc98ef2639a2af4c24616c814f
Author: Christos Margiolis <christos@margiolis.net>
Date:   Sat, 15 Aug 2020 21:09:58 +0300

initial commit

Diffstat:
AMakefile | 32++++++++++++++++++++++++++++++++
AREADME.md | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Acstring.c | 183+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acstring.h | 37+++++++++++++++++++++++++++++++++++++
Atest.c | 43+++++++++++++++++++++++++++++++++++++++++++
5 files changed, 348 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,32 @@ +TARGET = cstring + +SRC = $(wildcard *.c) +OBJ = $(SRC:%.c=%.o) + +CC = gcc +CPPFLAGS += -Iinclude -pedantic +CFLAGS += -Wall -std=c99 -O3 +LDFLAGS += -Llib +#LDLIBS += + +MOVE = mv +MKDIR_P = mkdir -p + +.PHONY: all clean + +all: $(TARGET) + +$(TARGET): $(OBJ) + $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ + +%.o: %.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + +run: + ./$(TARGET) + +install: $(TARGET) + cp $(TARGET) $(INSTALL_PATH) + +clean: + $(RM) $(OBJ) $(TARGET) diff --git a/README.md b/README.md @@ -0,0 +1,53 @@ +# cstring + +## Usage + +Simply include the source files in your projects and compile them +along with your other files. + +## Functions + +* `cstring_init`: 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`: 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_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_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 +* `cstring_greater_or_equals`: 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_equals`: True if the left hand string is less than or equal to the right hand one + +## Example + +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. + +```c +#include <stdio.h> +#include "cstring.h" + +int +main(int argc, char **argv) +{ + cstring s = cstring_init("Example string"); + cstring_append(&s, "more text..."); + printf("%s\n", s.str); + cstring_delete(&s); + + return 0; +} +``` diff --git a/cstring.c b/cstring.c @@ -0,0 +1,183 @@ +#include "cstring.h" + +cstring +cstring_init(const char *s) +{ + cstring cs; + cs.str = cstring_copy(s); + cs.len = cstring_len(&cs); + return cs; +} + +void +cstring_delete(cstring *cs) +{ + if (!cstring_empty(cs)) + { + free(cs->str); + cs->str = NULL; + cs->len = 0; + } +} + +void +cstring_assign(cstring *cs, const char *s) +{ + if (!cstring_empty(cs)) free(cs->str); + cs->str = cstring_copy(s); + cs->len = cstring_len(cs); +} + +void +cstring_append(cstring *cs, const char *s) +{ + if (!cstring_empty(cs)) + { + cstring_resize(cs, strlen(s)); + strcat(cs->str, s); + } + cs->len = cstring_len(cs); +} + +void +cstring_insert(cstring *cs, const char *s, size_t i) +{ + if (!cstring_empty(cs) && i < cs->len) + { + 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)); + 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); + cs->len = cstring_len(cs); + cs->str[cs->len] = '\0'; + free(tmp1); + free(tmp2); + } +} + +void +cstring_push_back(cstring *cs, char c) +{ + cstring_resize(cs, 1); + cs->str[cs->len] = c; + cs->str[cs->len + 1] = '\0'; + cs->len = cstring_len(cs); +} + +void +cstring_pop_back(cstring *cs) +{ + if (cs->len - 1 > 0) + { + char *tmp = (char *)malloc(cs->len); + memcpy(tmp, cs->str, cs->len); + free(cs->str); + tmp[cs->len - 1] = '\0'; + cs->str = tmp; + cs->len--; + } +} + +void +cstring_replace(cstring *cs, size_t i, char c) +{ + if (i < cs->len) cs->str[i] = c; +} + +void +cstring_clear(cstring *cs) +{ + if (!cstring_empty(cs)) free(cs->str); + cs->str = (char *)malloc(1); + cs->str[0] = '\0'; + cs->len = 0; +} + +int +cstring_exists(const cstring *cs, const char *s) +{ + return (strstr(cs->str, s) != NULL); +} + +char +cstring_front(const cstring *cs) +{ + return cs->str[0]; +} + +char +cstring_back(const cstring *cs) +{ + return (!cstring_empty(cs) ? cs->str[cs->len -1] : cs->str[0]); +} + +int +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'; + return tmp; +} + +void +cstring_resize(cstring *cs, size_t n) +{ + if (cstring_empty(cs)) + { + size_t l = cs->len + n; + char *tmp = (char *)malloc(l + 1); + memcpy(tmp, cs->str, cs->len + 1); + free(cs->str); + tmp[l] = '\0'; + cs->str = tmp; + cs->len = cstring_len(cs); + } +} + +int +cstring_equals(const cstring *lhs, const cstring *rhs) +{ + return (strcmp(lhs->str, rhs->str) == 0); +} + +int +cstring_greater(const cstring *lhs, const cstring *rhs) +{ + return (strcmp(lhs->str, rhs->str) > 0); +} + +int +cstring_greater_or_equals(const cstring *lhs, const cstring *rhs) +{ + return (strcmp(lhs->str, rhs->str) >= 0); +} + +int +cstring_less(const cstring *lhs, const cstring *rhs) +{ + return (strcmp(lhs->str, rhs->str) < 0); +} + +int +cstring_less_or_equals(const cstring *lhs, const cstring *rhs) +{ + return (strcmp(lhs->str, rhs->str) <= 0); +} diff --git a/cstring.h b/cstring.h @@ -0,0 +1,37 @@ +#ifndef CSTRING_H +#define CSTRING_H + +#include <stdlib.h> +#include <string.h> + +typedef struct { + char *str; + size_t len; +} cstring; + +extern cstring cstring_init(const char *s); +extern void cstring_delete(cstring *cs); +extern void cstring_assign(cstring *cs, const char *s); +extern void cstring_append(cstring *cs, const char *s); +extern void cstring_insert(cstring *cs, const char *s, size_t i); +extern void cstring_push_back(cstring *cs, char c); +extern void cstring_pop_back(cstring *cs); +extern void cstring_replace(cstring *cs, size_t i, char c); +extern void cstring_clear(cstring *cs); +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 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); +extern int cstring_greater_or_equals(const cstring *lhs, const cstring *rhs); +extern int cstring_less(const cstring *lhs, const cstring *rhs); +extern int cstring_less_or_equals(const cstring *lhs, const cstring *rhs); + +#endif /* CSTRING_H */ diff --git a/test.c b/test.c @@ -0,0 +1,43 @@ +#include <stdio.h> +#include "cstring.h" + +int +main(int argc, char **argv) +{ + cstring s = cstring_init("Hello world"); + printf("cstring_init: %s (%ld)\n", s.str, s.len); + + cstring_append(&s, "Append"); + printf("cstring_append: %s (%ld)\n", s.str, s.len); + + cstring_assign(&s, "New string"); + printf("cstring_assign: %s (%ld)\n", s.str, s.len); + + 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); + + cstring_insert(&s, "Inserted text", 4); + printf("cstring_insert: %s (%ld)\n", s.str, s.len); + + cstring_pop_back(&s); + printf("cstring_pop_back: %s (%ld)\n", s.str, s.len); + + cstring_clear(&s); + printf("cstring_clear: %s (%ld)\n", s.str, s.len); + + cstring_assign(&s, "CSTRING"); + printf("cstring_assign: %s (%ld)\n", s.str, s.len); + 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); + + cstring_delete(&s); + if (cstring_empty(&s)) printf("cstring_delete: Deleted string.\n"); + + return 0; +}