cstring

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

commit 9ce134335486b3b6a7337be22a3d00e35c235729
parent 9497790140b5c75524157d3379a8a5d9faaa1ae3
Author: Christos Margiolis <christos@margiolis.net>
Date:   Thu, 15 Oct 2020 13:31:05 +0300

added more tests and test Makefile, fixed cstring_erase

Diffstat:
MMakefile | 41++++++++++++++++++++++++-----------------
MREADME.md | 4++--
Mcstring.3 | 0
Mcstring.c | 8++++----
Mcstring.h | 2+-
Atests/Makefile | 38++++++++++++++++++++++++++++++++++++++
Dtests/test.c | 63---------------------------------------------------------------
Atests/test_basic.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atests/test_insert.c | 11+++++++++++
9 files changed, 141 insertions(+), 87 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,10 +1,10 @@ LIB = cstring VERSION = 0.1 -DIST = ${BIN}-${VERSION} +DIST = ${LIB}-${VERSION} MAN3 = ${LIB}.3 PREFIX = /usr/local MAN_DIR = ${PREFIX}/man/man3 -HDR_DIR = ${PREFIX}/include +INC_DIR = ${PREFIX}/include LIB_DIR = ${PREFIX}/lib EXT = c @@ -14,11 +14,12 @@ OBJ = ${SRC:%.${EXT}=%.o} AR = ar ARFLAGS = rs CC = gcc -CPPFLAGS += -Iinclude -DCSTRING_DBG -DVERSION=\"${VERSION}\" -#CPPFLAGS += -Iinclude -DVERSION=\"${VERSION}\" -CFLAGS += -Wall -std=c99 -pedantic -O3 -LDFLAGS += -Llib -#LDLIBS += +INCS = -Iinclude +# Uncomment if you want to compile the library in debug mode +#CPPFLAGS = -DCSTRING_DBG -DVERSION=\"${VERSION}\" +CPPFLAGS = -DVERSION=\"${VERSION}\" +CFLAGS = -Wall -std=c99 -pedantic -O3 ${INCS} ${CPPFLAGS} +LDFLAGS = -Llib CP = cp -f RM = rm -f @@ -27,37 +28,43 @@ MKDIR = mkdir -p TAR = tar -cf GZIP = gzip -all: ${LIB} +all: options ${LIB} + +options: + @echo ${LIB} build options: + @echo "CFLAGS = ${CFLAGS}" + @echo "LDFLAGS = ${LDFLAGS}" + @echo "CC = ${CC}" ${LIB}: ${OBJ} ${AR} ${ARFLAGS} lib${LIB}.a ${OBJ} %.o: %.${EXT} - ${CC} ${CPPFLAGS} ${CFLAGS} -c $< -o $@ + ${CC} ${CFLAGS} -c $< -o $@ dist: clean ${MKDIR} ${DIST} - ${CP} -R tests ${SRC} ${MAN3} cstring.h Makefile README.md ${DIST} + ${CP} -R tests ${SRC} ${MAN3} LICENSE Makefile README.md ${DIST} ${TAR} ${DIST}.tar ${DIST} ${GZIP} ${DIST}.tar ${RM_DIR} ${DIST} install: all - ${MKDIR} ${DESTDIR}${LIB_DIR} ${DESTDIR}${HDR_DIR} ${DESTDIR}${MAN_DIR} - ${CP} ${LIB}.h ${DESTDIR}${HDR_DIR} + ${MKDIR} ${DESTDIR}${LIB_DIR} ${DESTDIR}${INC_DIR} ${DESTDIR}${MAN_DIR} + ${CP} ${LIB}.h ${DESTDIR}${INC_DIR} ${CP} lib${LIB}.a ${DESTDIR}${LIB_DIR} ${CP} ${MAN3} ${DESTDIR}${MAN_DIR} sed "s/VERSION/${VERSION}/g" < ${MAN3} > ${DESTDIR}${MAN_DIR}/${MAN3} - chmod 644 ${DESTDIR}${HDR_DIR}/${LIB}.h + chmod 755 ${DESTDIR}${INC_DIR}/${LIB}.h chmod 644 ${DESTDIR}${LIB_DIR}/lib${LIB}.a chmod 644 ${DESTDIR}${MAN_DIR}/${MAN3} -uninstall: all - ${RM} ${DESTDIR}${HDR_DIR}/${LIB}.h +uninstall: + ${RM} ${DESTDIR}${INC_DIR}/${LIB}.h ${RM} ${DESTDIR}${LIB_DIR}/lib${LIB}.a ${RM} ${DESTDIR}${MAN_DIR}/${MAN3} clean: - ${RM} ${OBJ} ${LIB} lib${LIB}.a + ${RM} ${LIB} ${OBJ} lib${LIB}.a ${DIST}.tar.gz -.PHONY: all clean dist install uninstall +.PHONY: all options clean dist install uninstall diff --git a/README.md b/README.md @@ -84,7 +84,7 @@ The recommended way of initializing an empty string is by doing `cstring foo = c ## Macros -* `CSTRING_OUT_OF_BOUNDS`: Check if `pos` is out of bounds. +* `CSTRING_OUT_OF_BOUNDS`: Check if value is out of bounds. * `CSTRING_ARR_LEN`: Determine an array's length. The macro must be called in the same function the array is declared. * `CSTRING_FLAG_CHECK`: Check if flag is on. * `CSTRING_MALLOC`: Allocate memory with error checking. @@ -112,7 +112,7 @@ int main(int argc, char **argv) { cstring s = cstring_create("Foo"); - cstring_append(&s, "bar."); + cstring_append(&s, "bar"); printf("%s\n", s.str); cstring_delete(&s); diff --git a/cstring.3 b/cstring.3 diff --git a/cstring.c b/cstring.c @@ -124,6 +124,7 @@ cstring_insert(cstring *cs, const char *s, size_t i) } #ifdef CSTRING_DBG +// FIX IT #define CSTRING_DBG_EXPECTED_ERASE_STR(cs, pos, len) do { \ CSTRING_DBG_LOG("%s", "CSTRING_DBG_EXPECTED_ERASE_STR: "); \ size_t _i; \ @@ -142,8 +143,8 @@ void cstring_erase(cstring *cs, size_t pos, size_t len) { if (!cstring_empty(cs) - && !CSTRING_OUT_OF_BOUNDS(cs, pos) - && !CSTRING_OUT_OF_BOUNDS(cs, len)) + && (!CSTRING_OUT_OF_BOUNDS(cs, pos) + || !CSTRING_OUT_OF_BOUNDS(cs, len))) { #ifdef CSTRING_DBG CSTRING_DBG_LOG("STR: %s | INDEX: %ld | LEN: %ld\n", cs->str, pos, len); @@ -154,7 +155,7 @@ cstring_erase(cstring *cs, size_t pos, size_t len) char *tmp; CSTRING_MALLOC(tmp, newlen + 1); memcpy(tmp, cs->str, pos); - memcpy(tmp + pos, cs->str + pos + len, cs->len - len + pos); + memcpy(tmp + pos, cs->str + pos + len, cs->len - pos - len); CSTRING_FREE(cs); /* Useless check but keep it for consistency */ cs->len = newlen; cs->str = tmp; @@ -254,7 +255,6 @@ cstring_swap(cstring *lhs, cstring *rhs) *rhs = tmp; } -// FIX void cstring_sort_partial(cstring *cs, size_t pos, diff --git a/cstring.h b/cstring.h @@ -11,7 +11,7 @@ extern "C" { #define CSTRING_NPOS -1 #define CSTRING_INIT_EMPTY "" -#define CSTRING_OUT_OF_BOUNDS(cs, pos) ((pos) > cs->len) +#define CSTRING_OUT_OF_BOUNDS(cs, val) ((val) > cs->len) #define CSTRING_ARR_LEN(arr) ((size_t)sizeof((arr)) / sizeof((arr)[0])) #define CSTRING_FLAG_CHECK(flag, bit) (((flag) & (int)(bit)) == (int)(bit)) diff --git a/tests/Makefile b/tests/Makefile @@ -0,0 +1,38 @@ +BINS = test_basic test_insert +CC = gcc +CFLAGS = -Wall -std=c99 -pedantic -O3 +LDFLAGS = -Llib -lcstring + +all: options ${BINS} + +options: + @echo "build options:" + @echo "CFLAGS = ${CFLAGS}" + @echo "LDFLAGS = ${LDFLAGS}" + @echo "CC = ${CC}" + +run: + @echo "---------------------------" + @echo "---------------------------" + @echo "RUNNING: test_basic" + @echo "---------------------------" + @echo "---------------------------" + ./test_basic + + @echo "---------------------------" + @echo "---------------------------" + @echo "RUNNING: test_insert" + @echo "---------------------------" + @echo "---------------------------" + ./test_insert + +clean: + rm -f ${BINS} *.o + +test_basic: test_basic.c + ${CC} test_basic.c ${CFLAGS} -o test_basic ${LDFLAGS} + +test_insert: test_insert.c + ${CC} test_insert.c ${CFLAGS} -o test_insert ${LDFLAGS} + +.PHONY: all options run clean diff --git a/tests/test.c b/tests/test.c @@ -1,63 +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_sort_chars(&s, CSTRING_SORT_ASCENDING, NULL); - printf("cstring_sort_chars: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); - - // BUG - cstring_assign(&s, "New string"); - printf("cstring_assign: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); - - cstring_append(&s, "Appended text"); - printf("cstring_append: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); - - cstring_prepend(&s, "OK"); - printf("cstring_prepend: %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); - - // BUGS - 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)) - puts("cstring_delete: Deleted string."); - - return 0; -} diff --git a/tests/test_basic.c b/tests/test_basic.c @@ -0,0 +1,61 @@ +#include "cstring.h" + +// Compilation: gcc test_basic.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_sort_chars(&s, CSTRING_SORT_ASCENDING, NULL); + printf("cstring_sort_chars: %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_append(&s, "Appended text"); + printf("cstring_append: %s (Len: %ld, Capacity: %ld)\n", s.str, s.len, s.capacity); + + cstring_prepend(&s, "OK"); + printf("cstring_prepend: %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_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)) + puts("cstring_delete: Deleted string."); + + return 0; +} diff --git a/tests/test_insert.c b/tests/test_insert.c @@ -0,0 +1,11 @@ +#include <stdio.h> +#include <cstring.h> + +int +main(int argc, char **argv) +{ + cstring s = cstring_create("HHHHHHEEEEEEEEEEEEEEEEEEEEEYYYYYYYYYYYYYY"); + printf("%s\n", s.str); + cstring_delete(&s); + return 0; +}