From: Niki Roo Date: Fri, 28 Jun 2024 12:13:33 +0000 (+0200) Subject: switch to new cutils via submodule X-Git-Url: http://git.nikiroo.be/?a=commitdiff_plain;h=86f24c168e00e3b91e133e68a6e0816a84a41276;p=nsub.git switch to new cutils via submodule --- diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f3f4f1b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/cutils"] + path = src/cutils + url = git@git.nikiroo.be:workspace/cutils.git diff --git a/Makefile b/Makefile index 5117ae9..c542c07 100644 --- a/Makefile +++ b/Makefile @@ -1,71 +1,95 @@ -NAME=nsub - -.PHONY: all build rebuild install uninstall clean mrpropre mrpropre love debug \ - doc man run tests test run-test run-test-more +# +# Simple makefile that will forward all commands to src/xxx +# > NAME: main program (for 'man' and 'run') +# > NAMES: list of all the programs to compile +# > TESTS: list of all test programs to compile and run +# +NAME = nsub +NAMES = $(NAME) cutils +TESTS = + +PREFIX = /usr/local +dstdir = bin + +.PHONY: all build run clean mrpropre mrpropre love debug doc man \ + test run-test run-test-more \ + mess-build mess-run mess-clean mess-propre mess-doc mess-man \ + mess-test mess-run-test mess-run-test-more \ + $(NAMES) $(TESTS) all: build -build: bin/nsub - @echo Build successful. - -run: bin/nsub - bin/nsub - -tests: test +build: mess-build $(NAMES) -test: - $(MAKE) -C src -f tests.d - -run-test: - $(MAKE) -C src -f tests.d run +test: mess-test $(TESTS) -run-test-more: - $(MAKE) -C src -f tests.d run-more +# Main buildables +M_OPTS=$(MAKECMDGOALS) --no-print-directory PREFIX=$(PREFIX) DEBUG=$(DEBUG) +$(NAMES) $(TESTS): + $(MAKE) -C src/$@ $(M_OPTS) -rebuild: clean build +# Manual +man: mess-man + @$(MAKE) -f man.d $(MAKECMDGOALS) NAME=$(NAME) -doc: - doxygen +# Run +run: mess-run $(NAME) -man: VERSION README*.md - $(MAKE) -f man.d NAME=$(NAME) +# Run main test +run-test: mess-run-test $(TESTS) +run-test-more: mess-run-test-more $(TESTS) +# Doc/man/misc +doc: mess-doc + doxygen love: @echo " ...not war." - debug: - $(MAKE) DEBUG=1 + $(MAKE) $(MAKECMDGOALS) PREFIX=$(PREFIX) NAME=$(NAME) DEBUG=1 +# Clean +clean: mess-clean $(TESTS) $(NAMES) mrproper: mrpropre - -mrpropre: clean - $(MAKE) -C src -f tests.d mrpropre - $(MAKE) -C src -f utils.d mrpropre - $(MAKE) -C src -f nsub.d mrpropre - rm -f man/man1/*.1 man/*/man1/*.1 - rmdir man/*/man1 man/* man || true +mrpropre: mess-propre $(TESTS) $(NAMES) man rm -rf doc/html doc/latex doc/man - rmdir doc || true - -clean: - $(MAKE) -C src -f tests.d clean - $(MAKE) -C src -f utils.d clean - $(MAKE) -C src -f nsub.d clean - -install: - $(MAKE) -C src -f nsub.d install - @if [ -e "man/man1/$(NAME).1" ]; then \ - cp -r man/ "$(PREFIX)"/share/; \ - else \ - echo "No manual has been built (see \`make man')"; \ - fi - -uninstall: - $(MAKE) -C src -f nsub.d uninstall - -bin/nsub: bin/utils.o - $(MAKE) -C src -f nsub.d DEBUG=$(DEBUG) - -bin/utils.o: - $(MAKE) -C src -f utils.d DEBUG=$(DEBUG) + rmdir doc 2>/dev/null || true + +# Install/uninstall +install: mess-install $(NAMES) man +uninstall: mess-uninstall $(NAMES) man + +# Messages +mess-build: + @echo + @echo ">>>>>>>>>> Building $(NAMES)..." +mess-run: + @echo + @echo ">>>>>>>>>> Running $(NAME)..." +mess-clean: + @echo + @echo ">>>>>>>>>> Cleaning $(NAMES) $(TESTS)..." +mess-propre: + @echo + @echo ">>>>>>>>>> Calling Mr Propre..." +mess-doc: + @echo + @echo ">>>>>>>>>> Generating documentation for $(NAME)..." +mess-man: + @echo + @echo ">>>>>>>>>> Manual of $(NAME): $(MAKECMDGOALS)..." +mess-test: + @echo + @echo ">>>>>>>>>> Building all tests: $(TESTS)..." +mess-run-test: + @echo + @echo ">>>>>>>>>> Running tests: $(TESTS)..." +mess-run-test-more: + @echo + @echo ">>>>>>>>>> Running more tests: $(TESTS)..." +mess-install: + @echo + @echo ">>>>>>>>>> Installing $(NAME) into $(PREFIX)..." +mess-uninstall: + @echo + @echo ">>>>>>>>>> Uninstalling $(NAME) from $(PREFIX)..." diff --git a/man.d b/man.d index 3d50066..ab527b4 100644 --- a/man.d +++ b/man.d @@ -1,43 +1,70 @@ -# Requires variable: NAME +# Requires variables: NAME, PREFIX (for install and uninstall only) -.PHONY: man +.PHONY: man mrpropre mrproper install uninstall -man: README*.md - @echo Checking for possible manual pages... - @if [ -e README.md ]; then \ - echo Sources found for man pages; \ - if pandoc -v >/dev/null 2>&1; then \ - ls README*.md 2>/dev/null \ - | grep 'README\(-..\|\)\.md' \ - | while read man; do \ - echo " Processing page $$lang..."; \ - lang="`echo "$$man" \ - | sed 's:README\.md:en:' \ - | sed 's:README-\(.*\)\.md:\1:'`"; \ - mkdir -p man/"$$lang"/man1; \ +man: VERSION README.md README*.md + @if pandoc -v >/dev/null 2>&1; then \ + ls README*.md 2>/dev/null \ + | grep 'README\(-..\|\)\.md' \ + | while read man; do \ + lang="`echo "$$man" \ + | sed 's:README\.md:en:' \ + | sed 's:README-\(.*\)\.md:\1:'`"; \ + echo "Processing language: $$lang..."; \ + echo mkdir -p man/"$$lang"/man1; \ + mkdir -p man/"$$lang"/man1; \ + echo "pandoc [...] > man/$$lang"/man1/"${NAME}.1"; \ + ( \ + echo ".TH \"${NAME}\" 1 `\ + date +%Y-%m-%d\ + ` \"version `cat VERSION`\""; \ + echo; \ + UNAME="`echo "${NAME}" \ + | sed 's:\(.*\):\U\1:g'`"; \ ( \ - echo ".TH \"${NAME}\" 1 `\ - date +%Y-%m-%d\ - ` \"version `cat VERSION`\""; \ - echo; \ - UNAME="`echo "${NAME}" \ - | sed 's:\(.*\):\U\1:g'`"; \ - ( \ - cat "$$man" | head -n1 \ - | sed 's:.*(README\(-fr\|\)\.md).*::g'; \ - cat "$$man" | tail -n+2; \ - ) | sed 's:^#\(#.*\):\1:g' \ + cat "$$man" | head -n1 \ + | sed 's:.*(README\(-..\|\)\.md).*::g'; \ + cat "$$man" | tail -n+2; \ + ) | sed 's:^#\(#.*\):\1:g' \ | sed 's:^\(#.*\):\U\1:g;s:# *'"$$UNAME"':# NAME\n'"${NAME}"' \\- :g' \ | sed 's:--:——:g' \ | pandoc -f markdown -t man | sed 's:——:--:g' ; \ - ) > man/"$$lang"/man1/"${NAME}.1"; \ - done; \ - mkdir -p "man/man1"; \ - cp man/en/man1/"${NAME}".1 man/man1/; \ - else \ - echo "man pages generation: pandoc required" >&2; \ - false; \ - fi; \ - fi; + ) > man/"$$lang"/man1/"${NAME}.1"; \ + done; \ + echo mkdir -p "man/man1"; \ + mkdir -p "man/man1"; \ + echo cp man/en/man1/"${NAME}".1 man/man1/; \ + cp man/en/man1/"${NAME}".1 man/man1/; \ + else \ + echo "man pages generation: pandoc required" >&2; \ + false; \ + fi; \ +mrproper: mrpropre +mrpropre: + rm -f man/man1/*.1 man/*/man1/*.1 + rmdir man/*/man1 man/* man 2>/dev/null || true + +install: + @if [ -e "man/man1/$(NAME).1" ]; then \ + echo mkdir -p "$(PREFIX)"/share/man; \ + mkdir -p "$(PREFIX)"/share/man; \ + echo cp -r man "$(PREFIX)"/share/; \ + cp -r man "$(PREFIX)"/share/; \ + else \ + echo "No manual has been built (see \`make man')"; \ + fi + +uninstall: + @if [ -e "man/man1/$(NAME).1" ]; then \ + find man/ -type f | while read -r page; do \ + echo rm "$(PREFIX)/share/$$page";\ + rm "$(PREFIX)/share/$$page";\ + done; \ + echo rmdir "$(PREFIX)/share/man" 2>/dev/null \|\| true; \ + rmdir "$(PREFIX)/share/man" 2>/dev/null || true; \ + rmdir "$(PREFIX)/share" 2>/dev/null || true; \ + else \ + echo "No manual has been built (see \`make man')"; \ + fi diff --git a/src/cutils b/src/cutils new file mode 160000 index 0000000..9e29e2f --- /dev/null +++ b/src/cutils @@ -0,0 +1 @@ +Subproject commit 9e29e2f55d36a2e05a3420825b8ecc33006a45eb diff --git a/src/nsub.d b/src/nsub.d deleted file mode 100644 index 57aa2ce..0000000 --- a/src/nsub.d +++ /dev/null @@ -1,58 +0,0 @@ -# Note: 99+ required for for-loop initial declaration (CentOS 6) - -CFLAGS += -Wall -pedantic -I./ -std=c99 -CXXFLAGS += -Wall -pedantic -I./ -PREFIX = /usr/local - -ifdef DEBUG -CFLAGS += -ggdb -O0 -CXXFLAGS += -ggdb -O0 -endif - -.PHONY: all install uninstall clean mrpropre mrpropre - -all: ../bin/nsub - -SOURCES=$(wildcard nsub/*.c) -HEADERS=$(wildcard nsub/*.h) - -## Correct, but longer: - -## OBJECTS=$(SOURCES:%.c=%.o) -## -## nsub/nsub.o: nsub/nsub.c -## -## $(OBJECTS): nsub/nsub.h -## -## # easier, but more recompiles: -## $(OBJECTS): $(HEADERS) -## -##../bin/nsub: $(OBJECTS) ../bin/libutils.o -## $(CC) $(CFLAGS) $^ -o $@ - -## Quicker: -../bin/nsub: $(SOURCES) $(HEADERS) - # In two steps, so it works with clang, too - $(CC) $(CFLAGS) $^ -c && mv *.o nsub/ - $(CC) nsub/*.o ../bin/libutils.o -o $@ && rm -f nsub/*.o nsub/*.h.gch - -clean: - rm -f nsub/*.o - -mrproper: mrpropre - -mrpropre: clean - rm -f ../bin/nsub - rmdir ../bin || true - -install: - @echo "installing nsub to $(PREFIX)..." - mkdir -p "$(PREFIX)/bin" \ - && cp ../bin/nsub "$(PREFIX)/bin/" - -uninstall: - @echo "uninstalling nsub from $(PREFIX)..." - rm -f "$(PREFIX)/bin/nsub" \ - && rmdir "$(PREFIX)/bin" 2>/dev/null || true \ - && rmdir "$(PREFIX)" 2>/dev/null || true - diff --git a/src/nsub/Makefile b/src/nsub/Makefile new file mode 100644 index 0000000..a2f2c3d --- /dev/null +++ b/src/nsub/Makefile @@ -0,0 +1,10 @@ +# Simply pass everything to makefile.d, but calling from "../" + +.PHONY: all build install uninstall clean mrpropre mrpropre \ + run test run-test run-test-more default \ + nsub + +default $(MAKECMDGOALS): + @$(MAKE) --no-print-directory -C ../ -f $(CURDIR)/makefile.d \ + $(MAKECMDGOALS) + diff --git a/src/nsub/makefile.d b/src/nsub/makefile.d new file mode 100644 index 0000000..5218164 --- /dev/null +++ b/src/nsub/makefile.d @@ -0,0 +1,68 @@ +# Note: 99+ required for for-loop initial declaration (CentOS 6) +# Note: gnu99 (instead of c99) required for libcutils-net + +NAME = nsub +NAMES = $(NAME) +srcdir = $(NAME) +dstdir = ../bin + +CFLAGS += -Wall -pedantic -I./ -std=gnu99 +CXXFLAGS += -Wall -pedantic -I./ +# LDFLAGS += -lcheck +PREFIX = /usr/local + +ifdef DEBUG +CFLAGS += -ggdb -O0 +CXXFLAGS += -ggdb -O0 +endif + +.PHONY: all build install uninstall clean mrpropre mrpropre \ + $(NAMES) + +SOURCES=$(wildcard $(srcdir)/*.c) +HEADERS=$(wildcard $(srcdir)/*.h) +OBJECTS=$(SOURCES:%.c=%.o) + +# Main targets + +all: build + +build: $(NAMES) + +nsub: $(dstdir)/nsub + +run: + $(dstdir)/nsub --help + +################ +# Dependencies # +################ +OBJECTS+=$(dstdir)/libcutils.o +$(dstdir)/libcutils.o: + $(MAKE) --no-print-directory -C cutils/ cutils +################ + +$(dstdir)/nsub: $(OBJECTS) + mkdir -p $(dstdir) + $(CC) $(OBJECTS) -o $@ + +debug: + $(MAKE) -f $(srcdir)/makefile.d DEBUG=1 + +clean: + rm -f $(srcdir)/*.o + +mrproper: mrpropre + +mrpropre: clean + rm -f $(dstdir)/nsub + rmdir $(dstdir) 2>/dev/null || true + +install: + mkdir -p "$(PREFIX)/bin" + cp $(dstdir)/nsub "$(PREFIX)/bin/" + +uninstall: + rm "$(PREFIX)/bin/nsub" + rmdir "$(PREFIX)/bin" 2>/dev/null + diff --git a/src/nsub/nsub.c b/src/nsub/nsub.c index 6b9b728..bab09de 100644 --- a/src/nsub/nsub.c +++ b/src/nsub/nsub.c @@ -21,7 +21,7 @@ #include #include "nsub.h" -#include "utils/utils.h" +#include "cutils/cutils.h" /* Public */ diff --git a/src/nsub/nsub.h b/src/nsub/nsub.h index 2a6bd42..35bf334 100644 --- a/src/nsub/nsub.h +++ b/src/nsub/nsub.h @@ -20,7 +20,7 @@ /** * @file nsub.h * @author Niki - * @date 2022 + * @date 2024 * * @brief Subtitle/Lyrics conversion program (webvtt/srt/lrc) * @@ -38,7 +38,7 @@ * * @note all timings are in milliseconds. */ -#include "utils/array.h" +#include "cutils/array.h" /** * A subtitle or lyric format to import from/export to. diff --git a/src/nsub/nsub_read_lrc.c b/src/nsub/nsub_read_lrc.c index d9360ca..01d4120 100644 --- a/src/nsub/nsub_read_lrc.c +++ b/src/nsub/nsub_read_lrc.c @@ -20,7 +20,7 @@ #include #include "nsub.h" -#include "utils/utils.h" +#include "cutils/cutils.h" /* Declarations */ diff --git a/src/nsub/nsub_read_srt.c b/src/nsub/nsub_read_srt.c index 30becc4..daf486b 100644 --- a/src/nsub/nsub_read_srt.c +++ b/src/nsub/nsub_read_srt.c @@ -21,7 +21,7 @@ #include #include "nsub.h" -#include "utils/utils.h" +#include "cutils/cutils.h" /* Declarations */ diff --git a/src/nsub/nsub_read_webvtt.c b/src/nsub/nsub_read_webvtt.c index 35a3977..c57708e 100644 --- a/src/nsub/nsub_read_webvtt.c +++ b/src/nsub/nsub_read_webvtt.c @@ -21,7 +21,7 @@ #include #include "nsub.h" -#include "utils/utils.h" +#include "cutils/cutils.h" /* Declarations */ diff --git a/src/nsub/nsub_write_lrc.c b/src/nsub/nsub_write_lrc.c index 9d391f3..08c1470 100644 --- a/src/nsub/nsub_write_lrc.c +++ b/src/nsub/nsub_write_lrc.c @@ -20,7 +20,7 @@ #include #include "nsub.h" -#include "utils/utils.h" +#include "cutils/cutils.h" /* Declarations */ diff --git a/src/nsub/nsub_write_srt.c b/src/nsub/nsub_write_srt.c index 141bdb1..0cb0e4a 100644 --- a/src/nsub/nsub_write_srt.c +++ b/src/nsub/nsub_write_srt.c @@ -20,7 +20,7 @@ #include #include "nsub.h" -#include "utils/utils.h" +#include "cutils/cutils.h" /* Declarations */ diff --git a/src/tests.d b/src/tests.d deleted file mode 100644 index 97a38c3..0000000 --- a/src/tests.d +++ /dev/null @@ -1,33 +0,0 @@ -# Note: 99+ required for for-loop initial declaration (CentOS 6) - -CFLAGS += -Wall -pedantic -I./ -I ../ -std=c99 -CXXFLAGS += -Wall -pedantic -I./ -I ../ - -ifdef DEBUG -CFLAGS += -ggdb -O0 -CXXFLAGS += -ggdb -O0 -endif - -.PHONY: all clean mrpropre mrpropre test tests run run-more - -all: test - -tests: test - -test: tests/launcher.o - $(MAKE) -C tests/ -f utils.d - -clean: - $(MAKE) -C tests/ -f utils.d clean - rm -f tests/launcher.o - -mrproper: mrpropre - -mrpropre: clean - $(MAKE) -C tests/ -f utils.d mrpropre - -run: - $(MAKE) -C tests/ -f utils.d run - -run-more: - $(MAKE) -C tests/ -f utils.d run-more diff --git a/src/tests/launcher.c b/src/tests/launcher.c deleted file mode 100644 index 855bf25..0000000 --- a/src/tests/launcher.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2022 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "launcher.h" - -#include -#include -#include -#include - -// Shared globals -int launcher_color = -1; - -// Private functions -static int has_colour(); -static char *waiting_color(); -static char *passed_color(); -static char *failed_color(); -static char *stop_color(); - -// Private vars -// static char BLEU[] = { (char) 27, '[', '3', '4', 'm', '\0' }; -// static char TEAL[] = { (char) 27, '[', '3', '6', 'm', '\0' }; -// static char GRIS[] = { (char) 27, '[', '3', '7', 'm', '\0' }; -static char VERT[] = { (char) 27, '[', '3', '2', 'm', '\0' }; -static char ROUGE[] = { (char) 27, '[', '3', '1', 'm', '\0' }; -static char ORANGE[] = { (char) 27, '[', '3', '3', 'm', '\0' }; -static char STOP[] = { (char) 27, '[', '0', 'm', '\0' }; -static char bs9[] = { 8, 8, 8, 8, 8, 8, 8, 8, 8, '\0' }; - -// COLORTERM : if it exists and is not empty, the system will default to -// colour mode (--color) as opposed to --no-color - -// CK_ENV : Gets the print mode from the environment variable CK_VERBOSITY, -// which can have the values "silent", "minimal", "normal", "verbose". If the -// variable is not found or the value is not recognised, the print mode is set -// to CK_NORMAL. - -// How to start the program: -// ======================== -// -// $0 -// test the code (normal tests only) -// $0 --more -// run extra tests (if available; usually, they are specified as extra if they -// take long to process) -// -// -// $0 --name NAME -// do not test, just format the name as if it was tested -// $0 --passed -// format the line as if it was passes -// $0 --failed -// format the line as if it was failed - -char *tests_name = NULL; - -void test_init(const char name[]) { - int i; - int cols; - struct winsize ws; - - ioctl(1, TIOCGWINSZ, &ws); - cols = ws.ws_col; - - if (!tests_name) { - tests_name = malloc(sizeof(char) * (cols + 1)); - } - - for (i = 0; i < (cols + 1); i++) { - if (i < 4) - tests_name[i] = ' '; - else - tests_name[i] = '.'; - } - - strcpy(tests_name + 4, name); - tests_name[strlen(name) + 4] = ' '; - tests_name[cols - 6 - 1 - 4] = '\0'; - - fprintf(stderr, "%s", tests_name); - fprintf(stderr, "%s[%s%s%s] ", " ", waiting_color(), " ?? ", - stop_color()); -} - -void test_success() { - fprintf(stderr, "%s[%s%s%s] ", bs9, passed_color(), " OK ", - stop_color()); -} - -void test_failure() { - fprintf(stderr, "%s[%s%s%s] ", bs9, failed_color(), "FAIL", - stop_color()); -} - -int test_start(int more) { - int failed; - SRunner *runner; - - runner = get_tests(more); - - failed = 0; - if (runner) { - srunner_run_all(runner, CK_ENV); - - failed = srunner_ntests_failed(runner); - srunner_free(runner); - } else { - printf(">>> No tests have been found <<<\n"); - } - - return failed; -} - -int main(int argc, char **argv) { - int more = 0; - int cont = 1; - - for (int i = 1; i < argc; i++) { - if (!strcmp("--name", argv[i])) { - if ((i + 1) >= argc) - return 1; - test_init(argv[++i]); - cont = 0; - } else if (!strcmp("--passed", argv[i])) { - test_success(); - cont = 0; - } else if (!strcmp("--failed", argv[i])) { - test_failure(); - cont = 0; - } else if (!strcmp("--more", argv[i])) { - more = 1; - } else if (!strcmp("--color", argv[i])) { - launcher_color = 1; - } else if (!strcmp("--no-color", argv[i])) { - launcher_color = 0; - } - } - - if (!cont) - return 0; - - return test_start(more); -} - -static int has_colour() { - if (launcher_color == -1) { - // TODO: could we do better? - const char *cterm = getenv("COLORTERM"); - if (cterm && cterm[0]) - launcher_color = 1; - else - launcher_color = 0; - } - - return launcher_color; -} - -static char *waiting_color() { - if (has_colour()) - return ORANGE; - return ""; -} - -static char *passed_color() { - if (has_colour()) - return VERT; - return ""; -} - -static char *failed_color() { - if (has_colour()) - return ROUGE; - return ""; -} - -static char *stop_color() { - if (has_colour()) - return STOP; - return ""; -} diff --git a/src/tests/launcher.h b/src/tests/launcher.h deleted file mode 100644 index b1e6e63..0000000 --- a/src/tests/launcher.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _LAUNCHER_H -#define _LAUNCHER_H - -#include - -#define START(name) \ -START_TEST(name) {\ - test_init(#name);\ - -#define END \ - test_success();\ -}\ -END_TEST\ - -#define FAIL(...) \ -ck_abort_msg(__VA_ARGS__)\ - -#define ASSERT_EQUALS_STR(title, expected, received) \ - do { if (strcmp(expected, received)) { \ -ck_abort_msg("%s\n\tExpected: <%s>\n\tReceived: <%s>", title, expected, received); \ -}} while(0) - -#define ASSERT_EQUALS_INT(title, expected, received) \ - do { if (expected != received) { \ -ck_abort_msg("%s\n\tExpected: %lld\n\tReceived: %lld", title, (long long)expected, (long long)received); \ -}} while(0) - -#define ASSERT_EQUALS_SIZE(title, expected, received) \ - do { if (expected != received) { \ -ck_abort_msg("%s\n\tExpected: %zu\n\tReceived: %zu", title, expected, received); \ -}} while(0) - -extern int launcher_color; - -SRunner *get_tests(int more); - -void test_init(const char name[]); - -int test_start(int more); - -void test_success(); - -void test_failure(); - -#endif - diff --git a/src/tests/utils.d b/src/tests/utils.d deleted file mode 100644 index fdbf77a..0000000 --- a/src/tests/utils.d +++ /dev/null @@ -1,41 +0,0 @@ -# Note: 99+ required for for-loop initial declaration (CentOS 6) - -CFLAGS += -Wall -pedantic -I./ -I ../ -std=c99 -CXXFLAGS += -Wall -pedantic -I./ -I ../ -LDFLAGS += -lcheck -ifdef DEBIAN -LDFLAGS += -lsubunit -lm -lpthread -lrt -endif - -ifdef DEBUG -CFLAGS += -ggdb -O0 -CXXFLAGS += -ggdb -O0 -endif - -.PHONY: all clean mrpropre mrpropre test tests run run-more - -SOURCES=$(wildcard utils/*.c) -OBJECTS=$(SOURCES:%.c=%.o) - -all: test - -tests: test - -test: launcher.o ../../bin/libutils.o $(OBJECTS) - mkdir -p bin - $(CC) $(CFLAGS) $^ -o bin/utils $(LDFLAGS) - -run: - bin/utils - -run-more: - bin/utils --more - -clean: - rm -f utils/*.o - -mrproper: mrpropre - -mrpropre: clean - rm -f bin/utils - rmdir bin || true diff --git a/src/tests/utils/array.c b/src/tests/utils/array.c deleted file mode 100644 index 404c6a6..0000000 --- a/src/tests/utils/array.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2022 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "utils/array.h" - -#include -#include -#include - -#include "launcher.h" - -static array_t *a; - -static void setup() { - a = new_array(sizeof(char), 80); -} - -static void teardown() { - free_array(a); - a = NULL; -} - -static void reset() { - teardown(); - setup(); -} - -START(init) - if (!a) - FAIL("new_array returned NULL"); - - if (array_count(a)) - FAIL("empty array has a size of %zu", array_count(a)); - - END - -START(clear) - char car = 'T'; - - array_push(a, &car); - array_push(a, &car); - array_clear(a); - if (array_count(a)) - FAIL("empty array has a size of %zu", array_count(a)); - - END - -START(convert) - char car = 'T'; - char eos = '\0'; - char *str; - - array_push(a, &car); - array_push(a, &car); - array_push(a, &eos); - - str = (char*) array_convert(a); - ASSERT_EQUALS_STR("array of chars to string conversion", "TT", str); - - free(str); - a = NULL; - - END - -START(data) - char car = 'T'; - char eos = '\0'; - char *str; - - array_push(a, &car); - array_push(a, &car); - array_push(a, &eos); - - str = (char*) array_data(a); - ASSERT_EQUALS_STR("array of chars to string conversion", "TT", str); - - END - -START(count) - char car = 'T'; - char eos = '\0'; - - ASSERT_EQUALS_INT("empty array", 0, array_count(a)); - reset(); - - array_push(a, &car); - ASSERT_EQUALS_INT("1-char array", 1, array_count(a)); - reset(); - - array_push(a, &car); - array_push(a, &car); - array_push(a, &eos); - ASSERT_EQUALS_INT("array with a NUL at the end", 3, array_count(a)); - reset(); - - END - -START(pointers) - char *ptr; - char car; - - ptr = array_new(a); - *ptr = 'T'; - ASSERT_EQUALS_INT("add a new element via ptr", 1, array_count(a)); - - ptr = array_first(a); - car = *ptr; - if (car != 'T') - FAIL("first_ptr: 'T' was expected, but we got: '%c'", car); - - reset(); - - char *testy = "Testy"; - ptr = array_newn(a, strlen(testy) + 1); - for (size_t i = 0; i <= strlen(testy); i++) { - *ptr = testy[i]; - ptr++; - } - - ptr = array_first(a); - for (size_t i = 0; i < strlen(testy); i++) { - ASSERT_EQUALS_STR("next_ptr", testy + i, (char* )ptr); - ptr = array_next(a, ptr); - } - - array_loop_i(a, ptr2, char, i) { - if (i < strlen(testy)) - ASSERT_EQUALS_STR("array_loop", testy + i, ptr2); - else if (i == strlen(testy)) - ASSERT_EQUALS_STR("array_loop (last)", "", ptr2); - else - FAIL("array_loop went out of bounds"); - } - - END - -START(get) - char *str = "Testy"; - size_t sz = strlen(str); - - array_pushn(a, str, sz + 1); - - for (size_t i = 0; i < sz + 1; i++) { - char expected = str[i]; - char *ret = array_get(a, i); - ASSERT_EQUALS_INT("get each element", expected, *ret); - } - - END - -START(pop) - char *rep; - - if (array_pop(a)) - FAIL("popping an item from an empty array"); - - rep = array_new(a); - *rep = 'T'; - - rep = array_pop(a); - if (!rep) - FAIL("cannot pop item from 1-sized array"); - - ASSERT_EQUALS_INT("bad item popped", (int )'T', (int )*rep); - - if (a->count) - FAIL("popped 1-sized array still has %zu items", a->count); - - rep = array_new(a); - *rep = 'T'; - rep = array_new(a); - *rep = 'T'; - - rep = array_pop(a); - ASSERT_EQUALS_INT("bad item 1 popped", (int )'T', (int )*rep); - ASSERT_EQUALS_INT("popping should remove 1 from count", 1, a->count); - - rep = array_pop(a); - ASSERT_EQUALS_INT("bad item 2 popped", (int )'T', (int )*rep); - ASSERT_EQUALS_INT("popping should remove 1 from count", 0, a->count); - - END - -START(cut_at) - char *rep; - - if (array_cut_at(a, 4)) - FAIL("cutting an empty array returned something"); - - rep = array_new(a); - *rep = 'T'; - rep = array_new(a); - *rep = 'T'; - - if (array_cut_at(a, 4)) - FAIL("cutting an array above its count returned something"); - - if (!array_cut_at(a, 1)) - FAIL("failed to cut an array"); - ASSERT_EQUALS_INT("cutting at 1 should get a 1-sized array", 1, - a->count); - - if (!array_cut_at(a, 0)) - FAIL("failed to cut an array"); - ASSERT_EQUALS_INT("cutting at 0 should get a 1-sized array", 0, - a->count); - - END - -START(compact) - char car = 'T'; - char eos = '\0'; - - array_compact(a); - - array_push(a, &car); - array_push(a, &car); - array_push(a, &eos); - - ASSERT_EQUALS_STR("compacted array has wrong data", "TT", - (char* )array_data(a)); - - END - - // TODO -START(NO_TEST_YET_qsort) - END -START(NO_TEST_YET_push) - END -START(NO_TEST_YET_set) - END -START(NO_TEST_YET_copy) - END - -Suite *test_array(const char title[]) { - Suite *suite = suite_create(title); - - TCase *core = tcase_create("core"); - tcase_add_checked_fixture(core, setup, teardown); - tcase_add_test(core, init); - tcase_add_test(core, clear); - tcase_add_test(core, convert); - tcase_add_test(core, data); - tcase_add_test(core, count); - tcase_add_test(core, pointers); // new, newn, first, next - tcase_add_test(core, get); - tcase_add_test(core, pop); - tcase_add_test(core, cut_at); - tcase_add_test(core, compact); - - tcase_add_test(core, NO_TEST_YET_qsort); - tcase_add_test(core, NO_TEST_YET_push); - tcase_add_test(core, NO_TEST_YET_set); - tcase_add_test(core, NO_TEST_YET_copy); - - suite_add_tcase(suite, core); - - return suite; -} - -Suite *test_array_more(const char title[]) { - Suite *suite = suite_create(title); - - TCase *tmore = tcase_create("more"); - tcase_add_checked_fixture(tmore, setup, teardown); - // TODO - - suite_add_tcase(suite, tmore); - - return suite; -} diff --git a/src/tests/utils/base64.c b/src/tests/utils/base64.c deleted file mode 100644 index a477a30..0000000 --- a/src/tests/utils/base64.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2022 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "utils/base64.h" - -#include - -#include "launcher.h" - -static void setup() { -} - -static void teardown() { -} - -static char decoded[] = "This is Le Test, we will UTF-8 the String, too!"; -static char encoded[] = - "VGhpcyBpcyBMZSBUZXN0LCB3ZSB3aWxsIFVURi04IHRoZSBTdHJpbmcsIHRvbyE="; - -static char decoded_utf8[] = "Le café d'Abigaëlle"; -static char encoded_utf8[] = "TGUgY2Fmw6kgZCdBYmlnYcOrbGxl"; - -START(decode) - char *tmp = base64_decode(encoded); - ASSERT_EQUALS_STR("decoding", decoded, tmp); - free(tmp); - END - -START(encode) - char *tmp = base64_encode(decoded); - ASSERT_EQUALS_STR("encoding", encoded, tmp); - free(tmp); - END - -START(utf8) - char *tmp; - - tmp = base64_decode(encoded_utf8); - ASSERT_EQUALS_STR("UTF-8 decoding", decoded_utf8, tmp); - free(tmp); - - tmp = base64_encode(decoded_utf8); - ASSERT_EQUALS_STR("UTF-8 encoding", encoded_utf8, tmp); - free(tmp); - - END - -START(both_ways) - char *enc = base64_encode(decoded); - char *dec = base64_decode(enc); - ASSERT_EQUALS_STR("both ways DEC", decoded, dec); - ASSERT_EQUALS_STR("both ways ENC", encoded, enc); - free(dec); - free(enc); - END - -START(big) - size_t sz = 10 * 1024 * 1024; - char *dec = malloc((sz + 1) * sizeof(char)); - for (int i = 0; i < sz; i++) { - dec[i] = '0' + (i % 10); - } - dec[sz] = '\0'; - - char *enc = base64_encode(dec); - char *dec2 = base64_decode(enc); - - ASSERT_EQUALS_STR("long encode/decode cycle", dec, dec2); - free(dec2); - free(enc); - free(dec); - - END - -START(lots) - size_t count = 1 * 1000 * 1000; - for (size_t i = 0; i < count; i++) { - char *enc = base64_encode(decoded); - char *dec = base64_decode(enc); - - if (strcmp(decoded, dec)) { - FAIL("Failed short encode/decode cycle at index %zu", i); - } - - free(enc); - free(dec); - } - - END - -Suite *test_base64(const char title[]) { - Suite *suite = suite_create(title); - - TCase *core = tcase_create("core"); - tcase_add_checked_fixture(core, setup, teardown); - tcase_add_test(core, decode); - tcase_add_test(core, encode); - tcase_add_test(core, utf8); - - suite_add_tcase(suite, core); - - return suite; -} - -Suite *test_base64_more(const char title[]) { - Suite *suite = suite_create(title); - - TCase *tmore = tcase_create("more"); - tcase_add_checked_fixture(tmore, setup, teardown); - tcase_add_test(tmore, both_ways); - tcase_add_test(tmore, big); - tcase_add_test(tmore, lots); - - suite_add_tcase(suite, tmore); - - return suite; -} diff --git a/src/tests/utils/cstring.c b/src/tests/utils/cstring.c deleted file mode 100644 index 267d695..0000000 --- a/src/tests/utils/cstring.c +++ /dev/null @@ -1,861 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2022 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include "launcher.h" -#include "utils/cstring.h" - -#define TEST_FILE_READLINE "utils/test_readline.txt" - -cstring_t *s; - -static void setup() { - s = new_cstring(); -} - -static void teardown() { - free_cstring(s); - s = NULL; -} - -static void reset() { - teardown(); - setup(); -} - -START(init) - if (!s) - FAIL("new_cstring returned NULL"); - - if (s->length) - FAIL("empty cstring has a size of %zu", s->length); - - END - -START(add_car) - cstring_add_car(s, 'T'); - ASSERT_EQUALS_STR("Cannot add a single char", "T", s->string); - - cstring_add_car(s, 'e'); - cstring_add_car(s, 's'); - cstring_add_car(s, 't'); - cstring_add_car(s, 'y'); - ASSERT_EQUALS_STR("Cannot add multiple chars", "Testy", s->string); - - END - -START(add_all_but_p) - char *str; - - str = "testy"; - cstring_add(s, str); - ASSERT_EQUALS_STR("Short string", str, s->string); - reset(); - - str = "Fanfan entre dans un bar"; - cstring_add(s, str); - ASSERT_EQUALS_STR("Medium string", str, s->string); - reset(); - - str = "Ligne 1\nLigne 2\nLigne 3, attention 4 = vide\n"; - cstring_add(s, str); - ASSERT_EQUALS_STR("Multi-line", str, s->string); - reset(); - - str = "Les accents en français sont bien là et se " - "retrouvent avec une fréquence élevée"; - cstring_add(s, str); - ASSERT_EQUALS_STR("accents", str, s->string); - reset(); - - str = "cents: ¢, copyright: ©, arrows: →↓↑←"; - cstring_add(s, str); - ASSERT_EQUALS_STR("UTF-8", str, s->string); - reset(); - - str = "Os iusti meditabitur sapientiam,\n" - "Et lingua\n" - "eius loquetur\n" - "indicium.\n" - "\n" - "Beatus\n" - "vir qui\n" - "suffert tentationem, Quoniqm\n" - "cum probates\n" - "fuerit accipient\n" - "coronam vitae\n" - "\n" - "Kyrie, fons bonitatis.\n" - "Kyrie, ignis divine, eleison.\n" - "\n" - "O quam sancta, quam serena,\n" - "Quam benigma, quam amoena esse Virgo creditur.\n" - "O quam sancta, quam serena,\n" - "Quam benigma, quam amoena,\n" - "O castitatis lilium.\n" - "\n" - "Kyrie, fons bonitatis.\n" - "Kyrie, ignis divine, eleison.\n" - "\n" - "O quam sancta, quam serena,\n" - "Quam benigma, quam amoena,\n" - "O castitatis lilium.\n"; - cstring_add(s, str); - ASSERT_EQUALS_STR("Long, multi-line string", str, s->string); - reset(); - - str = "String 1, String 2"; - cstring_add(s, "String 1, "); - cstring_add(s, "String 2"); - ASSERT_EQUALS_STR("Concat with add", str, s->string); - reset(); - - str = "0123456789"; - cstring_addf(s, str, 4); - ASSERT_EQUALS_STR("addf error (start at 4)", "456789", s->string); - reset(); - - str = "0123456789"; - cstring_addf(s, str, 4); - cstring_addf(s, str, 8); - str = "45678989"; - ASSERT_EQUALS_STR("Concat with addf", str, s->string); - reset(); - - str = "0123456789"; - cstring_addn(s, str, 4); - ASSERT_EQUALS_STR("addn error (4)", "0123", s->string); - reset(); - - str = "0123456789"; - cstring_addn(s, str, 4); - cstring_addn(s, str, 2); - str = "012301"; - ASSERT_EQUALS_STR("Concat with addn", str, s->string); - reset(); - - str = "0123456789"; - cstring_addfn(s, str, 4, 3); - ASSERT_EQUALS_STR("addf error (4, 3)", "456", s->string); - reset(); - - str = "0123456789"; - cstring_addfn(s, str, 4, 3); - cstring_addfn(s, str, 2, 2); - str = "45623"; - ASSERT_EQUALS_STR("Concat with addfn", str, s->string); - reset(); - - END - -START(addp) - char *str; - - cstring_addp(s, "%d", 42); - ASSERT_EQUALS_STR("Simple int", "42", s->string); - reset(); - - cstring_addp(s, "%02d", 1); - ASSERT_EQUALS_STR("Leading zero int", "01", s->string); - reset(); - - cstring_addp(s, "%d", 352646); - ASSERT_EQUALS_STR("Large int", "352646", s->string); - reset(); - - str = "Simple test string"; - cstring_addp(s, "%s", str); - ASSERT_EQUALS_STR("Simple string", str, s->string); - reset(); - - str = "String 1, String 2"; - cstring_addp(s, "%s", "String 1, "); - cstring_addp(s, "%s", "String 2"); - ASSERT_EQUALS_STR("Cumulative strings", str, s->string); - reset(); - - END - -START(cut_at) - cstring_add(s, "0123456789"); - cstring_cut_at(s, 4); - ASSERT_EQUALS_STR("cut at failed", "0123", s->string); - - END - -START(substring) - free_cstring(s); - s = cstring_substring("0123456789", 4, 2); - ASSERT_EQUALS_STR("substring failed 4,2", "45", s->string); - - free_cstring(s); - s = cstring_substring("0123456789", 0, 4); - ASSERT_EQUALS_STR("substring failed 0,4", "0123", s->string); - - free_cstring(s); - s = cstring_substring("0123456789", 3, 0); - ASSERT_EQUALS_STR("substring failed 3,0", "3456789", s->string); - - free_cstring(s); - s = cstring_substring("0123456789", 0, 0); - ASSERT_EQUALS_STR("substring failed 0,0", "0123456789", s->string); - - END - -START(reverse) - cstring_add(s, "kayak"); - cstring_reverse(s->string); - ASSERT_EQUALS_STR("reversing a palyndrome failed", "kayak", s->string); - reset(); - - cstring_add(s, "plantigrade"); - cstring_reverse(s->string); - ASSERT_EQUALS_STR("reverse failed", "edargitnalp", s->string); - reset(); - - cstring_add(s, "123"); - cstring_reverse(s->string); - ASSERT_EQUALS_STR("reverse failed", "321", s->string); - reset(); - - cstring_add(s, "1234"); - cstring_reverse(s->string); - ASSERT_EQUALS_STR("reverse failed", "4321", s->string); - reset(); - - END - -START(replace) - cstring_add(s, "test string AC/DC"); - ASSERT_EQUALS_INT("(a) Bad number of replacements returned", 0, - cstring_replace(s, "", "")); - ASSERT_EQUALS_STR("Replacement failed", "test string AC/DC", s->string); - - reset(); - cstring_add(s, "test string AC/DC"); - ASSERT_EQUALS_INT("(b) Bad number of replacements returned", 1, - cstring_replace(s, "AC/DC", "AC/DC")); - ASSERT_EQUALS_STR("Replacement failed", "test string AC/DC", s->string); - - reset(); - cstring_add(s, "test string AC/DC"); - ASSERT_EQUALS_INT("(c) Bad number of replacements returned", 1, - cstring_replace(s, "AC/DC", "woof")); - ASSERT_EQUALS_STR("Replacement failed", "test string woof", s->string); - - reset(); - cstring_add(s, "test string AC/DC"); - ASSERT_EQUALS_INT("(d) Bad number of replacements returned", 2, - cstring_replace(s, "C", "*")); - ASSERT_EQUALS_STR("Replacement failed", "test string A*/D*", s->string); - - reset(); - cstring_add(s, "test string AC/DC"); - ASSERT_EQUALS_INT("(e) Bad number of replacements returned", 1, - cstring_replace(s, "test ", "")); - ASSERT_EQUALS_STR("Replacement failed", "string AC/DC", s->string); - - reset(); - cstring_add(s, "test string AC/DC"); - ASSERT_EQUALS_INT("(f) Bad number of replacements returned", 1, - cstring_replace(s, "test ", "longer test ")); - ASSERT_EQUALS_STR("Replacement failed", "longer test string AC/DC", - s->string); - - END - -START(replace_car) - cstring_add(s, "test string AC/DC"); - ASSERT_EQUALS_INT("(a) Bad number of replacements returned", 0, - cstring_replace_car(s->string, '?', '!')); - ASSERT_EQUALS_STR("Replacement failed", "test string AC/DC", s->string); - - reset(); - cstring_add(s, "test string AC/DC"); - ASSERT_EQUALS_INT("(b) Bad number of replacements returned", 1, - cstring_replace_car(s->string, '/', '/')); - ASSERT_EQUALS_STR("Replacement failed", "test string AC/DC", s->string); - - reset(); - cstring_add(s, "test string AC/DC"); - ASSERT_EQUALS_INT("(c) Bad number of replacements returned", 1, - cstring_replace_car(s->string, 'A', 'a')); - ASSERT_EQUALS_STR("Replacement failed", "test string aC/DC", s->string); - - reset(); - cstring_add(s, "test string AC/DC"); - ASSERT_EQUALS_INT("(d) Bad number of replacements returned", 2, - cstring_replace_car(s->string, 'C', '*')); - ASSERT_EQUALS_STR("Replacement failed", "test string A*/D*", s->string); - - reset(); - cstring_add(s, "test string AC/DC"); - ASSERT_EQUALS_INT("(e) Bad number of replacements returned", 1, - cstring_replace_car(s->string, '/', '\0')); - ASSERT_EQUALS_STR("Replacement failed", "test string AC", s->string); - - END - -START(starts_with) - char *start; - - cstring_add(s, "fichier.ext"); - - start = "fichier"; - if (!cstring_starts_with(s->string, start, 0)) - FAIL("fichier.ext does not start with %s", start); - - start = "ichier"; - if (cstring_starts_with(s->string, start, 0)) - FAIL("fichier.ext starts with %s", start); - - start = "afichier"; - if (cstring_starts_with(s->string, start, 0)) - FAIL("fichier.ext starts with %s", start); - - start = ""; - if (!cstring_starts_with(s->string, start, 0)) - FAIL("fichier.ext does not start with nothing"); - - start = "chier"; - if (!cstring_starts_with(s->string, start, 2)) - FAIL("fichier.ext +2 does not start with %s", start); - - END - -START(ends_with) - char *end; - - cstring_add(s, "fichier.ext"); - - end = ".ext"; - if (!cstring_ends_with(s->string, end)) - FAIL("fichier.ext does not end in %s", end); - - end = ".ex"; - if (cstring_ends_with(s->string, end)) - FAIL("fichier.ext ends in %s", end); - - end = "aext"; - if (cstring_ends_with(s->string, end)) - FAIL("fichier.ext does not end in %s", end); - - end = ""; - if (!cstring_ends_with(s->string, end)) - FAIL("fichier.ext does not end with nothing"); - - END - -START(find) - char *str = "Une petite string pour y chercher des choses"; - - ASSERT_EQUALS_INT("(a) find error", 0, cstring_find(str, "Une", 0)); - ASSERT_EQUALS_INT("(b) find error", -1, cstring_find(str, "Une", 1)); - ASSERT_EQUALS_INT("(c) find error", 4, cstring_find(str, "petite", 0)); - ASSERT_EQUALS_INT("(d) find error", 4, cstring_find(str, "petite", 1)); - ASSERT_EQUALS_INT("(e) find error", 4, cstring_find(str, "petite", 2)); - ASSERT_EQUALS_INT("(f) find error", 4, cstring_find(str, "petite", 3)); - ASSERT_EQUALS_INT("(g) find error", 4, cstring_find(str, "petite", 4)); - ASSERT_EQUALS_INT("(h) find error", -1, cstring_find(str, "petite", 5)); - ASSERT_EQUALS_INT("(i) find error", 38, cstring_find(str, "choses", 0)); - ASSERT_EQUALS_INT("(j) find error", -1, cstring_find(str, "Oops", 0)); - ASSERT_EQUALS_INT("(k) find error", 2, cstring_find(str, "e", 0)); - ASSERT_EQUALS_INT("(l) find error", 2, cstring_find(str, "e", 1)); - ASSERT_EQUALS_INT("(m) find error", 2, cstring_find(str, "e", 2)); - ASSERT_EQUALS_INT("(n) find error", 5, cstring_find(str, "e", 3)); - ASSERT_EQUALS_INT("(o) find error", 9, cstring_find(str, "e", 6)); - - END - -START(rfind) - char *str = "Une petite string pour y chercher des choses"; - - ASSERT_EQUALS_INT("(a) find error", 0, cstring_rfind(str, "Une", 0)); - ASSERT_EQUALS_INT("(b) find error", 0, cstring_rfind(str, "Une", 1)); - ASSERT_EQUALS_INT("(c) find error", 4, cstring_rfind(str, "petite", 0)); - ASSERT_EQUALS_INT("(d) find error", 4, - cstring_rfind(str, "petite", 11)); - ASSERT_EQUALS_INT("(e) find error", -1, - cstring_rfind(str, "petite", 2)); - ASSERT_EQUALS_INT("(f) find error", 38, - cstring_rfind(str, "choses", 0)); - ASSERT_EQUALS_INT("(g) find error", -1, cstring_rfind(str, "Oops", 0)); - ASSERT_EQUALS_INT("(h) find error", 42, cstring_rfind(str, "e", 0)); - ASSERT_EQUALS_INT("(i) find error", 42, cstring_rfind(str, "e", -1)); - ASSERT_EQUALS_INT("(j) find error", 35, cstring_rfind(str, "e", -2)); - ASSERT_EQUALS_INT("(k) find error", 35, cstring_rfind(str, "e", -3)); - ASSERT_EQUALS_INT("(l) find error", 35, cstring_rfind(str, "e", 38)); - - END - -START(clear) - if (!s) - FAIL("new_cstring returned NULL"); - - if (s->length) - FAIL("empty cstring has a size of %zu", s->length); - - cstring_add(s, "testy"); - cstring_clear(s); - if (s->length) - FAIL("cleared cstring has a size of %zu", s->length); - - END - -START(convert) - char *str; - - str = cstring_convert(s); - s = NULL; - - ASSERT_EQUALS_STR("Convert failed with an empty string", "", str); - - reset(); - - cstring_add(s, "testy"); - str = cstring_convert(s); - s = NULL; - ASSERT_EQUALS_STR("Convert did not return the same string", "testy", - str); - - END - -START(clone) - cstring_t *clone; - - clone = cstring_clone(NULL); - if (clone) - FAIL("Cloning NULL must return NULL"); - - clone = cstring_clone(""); - ASSERT_EQUALS_STR("Cannot clone the empty string", "", clone->string); - free_cstring(clone); - - cstring_add(s, "Testy viva la vida"); - clone = cstring_clone(s->string); - ASSERT_EQUALS_STR("Failed to clone the string", s->string, - clone->string); - free_cstring(clone); - - END - -START(rtrim) - char *expected; - - expected = "testy"; - cstring_add(s, expected); - cstring_add(s, " "); - - cstring_rtrim(s, ' '); - ASSERT_EQUALS_STR("(a) Failed to rtrim", expected, s->string); - - reset(); - - expected = " testy"; - cstring_add(s, expected); - cstring_add(s, " "); - - cstring_rtrim(s, ' '); - ASSERT_EQUALS_STR("(b) Failed to rtrim", expected, s->string); - - reset(); - - expected = " testy "; - cstring_add(s, expected); - cstring_add(s, "..."); - - cstring_rtrim(s, '.'); - ASSERT_EQUALS_STR("(c) Failed to rtrim", expected, s->string); - - reset(); - - expected = "...testy "; - cstring_add(s, expected); - cstring_add(s, "..."); - - cstring_rtrim(s, '.'); - ASSERT_EQUALS_STR("(d) Failed to rtrim", expected, s->string); - - END - -START(trim) - char *expected; - - expected = "testy"; - cstring_add(s, expected); - cstring_add(s, " "); - - cstring_trim(s, ' '); - ASSERT_EQUALS_STR("(a) Failed to trim", expected, s->string); - - reset(); - - expected = "testy"; - cstring_add(s, " "); - cstring_add(s, expected); - cstring_add(s, " "); - - cstring_trim(s, ' '); - ASSERT_EQUALS_STR("(b) Failed to trim", expected, s->string); - - reset(); - - expected = " testy "; - cstring_add(s, expected); - cstring_add(s, "..."); - - cstring_trim(s, '.'); - ASSERT_EQUALS_STR("(c) Failed to trim", expected, s->string); - - reset(); - - expected = " testy "; - cstring_add(s, "..."); - cstring_add(s, expected); - cstring_add(s, "..."); - - cstring_trim(s, '.'); - ASSERT_EQUALS_STR("(d) Failed to trim", expected, s->string); - - END - -START(remove_crlf) - char *str = "testy"; - - cstring_add(s, str); - s->length = cstring_remove_crlf(s->string); - ASSERT_EQUALS_STR("no-op failed", str, s->string); - - reset(); - cstring_add(s, str); - cstring_add(s, "\n"); - s->length = cstring_remove_crlf(s->string); - ASSERT_EQUALS_STR("\\n failed", str, s->string); - - reset(); - cstring_add(s, str); - cstring_add(s, "\r\n"); - s->length = cstring_remove_crlf(s->string); - ASSERT_EQUALS_STR("\\r\\n failed", str, s->string); - - reset(); - cstring_add(s, str); - cstring_add(s, "\n\n"); - s->length = cstring_remove_crlf(s->string); - ASSERT_EQUALS_STR("\\n\\n failed", "testy\n", s->string); - - reset(); - cstring_add(s, str); - cstring_add(s, "\r\n\r\n"); - s->length = cstring_remove_crlf(s->string); - ASSERT_EQUALS_STR("\\r\\n\\r\\n failed", "testy\r\n", s->string); - - reset(); - cstring_add(s, "\n"); - s->length = cstring_remove_crlf(s->string); - ASSERT_EQUALS_STR("\\n uniq failed", "", s->string); - - END - -START(toupper) - cstring_add(s, ""); - cstring_toupper(s); - ASSERT_EQUALS_STR("Failed to uppercase empty", "", s->string); - - reset(); - - cstring_add(s, "Simple Testy"); - cstring_toupper(s); - ASSERT_EQUALS_STR("Failed to uppercase", "SIMPLE TESTY", s->string); - - reset(); - - cstring_add(s, "C'est l'été"); - cstring_toupper(s); - ASSERT_EQUALS_STR("Failed to uppercase", "C'EST L'ÉTÉ", s->string); - - reset(); - - cstring_add(s, "Test en français"); - cstring_toupper(s); - ASSERT_EQUALS_STR("Failed to uppercase", "TEST EN FRANÇAIS", s->string); - - END - -START(tolower) - cstring_add(s, ""); - cstring_tolower(s); - ASSERT_EQUALS_STR("Failed to lowercase empty", "", s->string); - - reset(); - - cstring_add(s, "Simple Testy"); - cstring_tolower(s); - ASSERT_EQUALS_STR("Failed to lowercase", "simple testy", s->string); - - reset(); - - cstring_add(s, "Été ! C'est l'été !"); - cstring_tolower(s); - ASSERT_EQUALS_STR("Failed to lowercase", "été ! c'est l'été !", - s->string); - - reset(); - - cstring_add(s, "Test en français"); - cstring_tolower(s); - ASSERT_EQUALS_STR("Failed to lowercase", "test en français", s->string); - - reset(); - - cstring_add(s, "À la claire fontaine"); - cstring_tolower(s); - ASSERT_EQUALS_STR("Failed to lowercase", "à la claire fontaine", - s->string); - - END - -START(readline) - int read; - FILE *testin = fopen(TEST_FILE_READLINE, "r"); - if (!testin) - FAIL("Test file not found: test_readln.txt"); - - read = cstring_readline(s, testin); - if (!read) - FAIL("first line should not be last"); - ASSERT_EQUALS_STR("first line incorrect", "ligne 1", s->string); - reset(); - - read = cstring_readline(s, testin); - if (!read) - FAIL("second line should not be last"); - ASSERT_EQUALS_STR("second line incorrect", "", s->string); - reset(); - - read = cstring_readline(s, testin); - if (!read) - FAIL("third line should not be last"); - ASSERT_EQUALS_STR("third line incorrect", "ligne 3", s->string); - reset(); - - if (cstring_readline(s, testin)) { - FAIL("fourth line should not exist"); - } - - END - -START(add_path) - cstring_add_path(s, "root"); - ASSERT_EQUALS_STR("failed to create root path", "/root", s->string); - - cstring_add_path(s, "dir"); - ASSERT_EQUALS_STR("failed to add a dir", "/root/dir", s->string); - - cstring_add_path(s, "sub/"); - ASSERT_EQUALS_STR("extra / failed", "/root/dir/sub", s->string); - - END - -START(pop_path) - cstring_add(s, ""); - ASSERT_EQUALS_INT("empty test failed", 0, cstring_pop_path(s, 1)); - - reset(); - cstring_add(s, "root"); - ASSERT_EQUALS_INT("0 nbr test failed", 0, cstring_pop_path(s, 0)); - ASSERT_EQUALS_STR("0 test failed", "root", s->string); - - reset(); - cstring_add(s, "root/"); - ASSERT_EQUALS_INT("0² nbr test failed", 0, cstring_pop_path(s, 0)); - ASSERT_EQUALS_STR("0² test failed", "root", s->string); - - reset(); - cstring_add(s, "/"); - ASSERT_EQUALS_INT("root test nbr failed", 0, cstring_pop_path(s, 1)); - ASSERT_EQUALS_STR("root test failed", "/", s->string); - - reset(); - cstring_add(s, "/"); - ASSERT_EQUALS_INT("root² test nbr failed", 0, cstring_pop_path(s, 2)); - ASSERT_EQUALS_STR("root² test failed", "/", s->string); - - reset(); - cstring_add(s, "/root"); - ASSERT_EQUALS_INT("/root test nbr failed", 1, cstring_pop_path(s, 1)); - ASSERT_EQUALS_STR("/root test failed", "/", s->string); - - reset(); - cstring_add(s, "/root"); - ASSERT_EQUALS_INT("/root³ test nbr failed", 1, cstring_pop_path(s, 2)); - ASSERT_EQUALS_STR("/root³ test failed", "/", s->string); - - reset(); - cstring_add(s, "/root/dir/file"); - ASSERT_EQUALS_INT("2 test nbr failed", 2, cstring_pop_path(s, 2)); - ASSERT_EQUALS_STR("2 test failed", "/root", s->string); - - reset(); - cstring_add(s, "/root/dir/file/"); - ASSERT_EQUALS_INT("trailing / test nbr failed", 1, - cstring_pop_path(s, 1)); - ASSERT_EQUALS_STR("trailing / test failed", "/root/dir", s->string); - - END - -START(basename) - char *str; - - cstring_add(s, ""); - str = cstring_basename(s->string, NULL); - ASSERT_EQUALS_STR("empty test", "", str); - free(str); - - reset(); - cstring_add(s, "/root/path/dir/file"); - str = cstring_basename(s->string, NULL); - ASSERT_EQUALS_STR("simple test", "file", str); - free(str); - - reset(); - cstring_add(s, "/root/path/dir/file"); - str = cstring_basename(s->string, ".ext"); - ASSERT_EQUALS_STR("no ext test", "file", str); - free(str); - - reset(); - cstring_add(s, "/root/path/dir/file.test"); - str = cstring_basename(s->string, ".ext"); - ASSERT_EQUALS_STR("wrong ext test", "file.test", str); - free(str); - - reset(); - cstring_add(s, "/root/path/dir/file.ext"); - str = cstring_basename(s->string, ".ext"); - ASSERT_EQUALS_STR("good ext test", "file", str); - free(str); - - END - -START(dirname) - char *str; - - cstring_add(s, "/root/path"); - str = cstring_dirname(s->string); - ASSERT_EQUALS_STR("simple test", "/root", str); - free(str); - - reset(); - cstring_add(s, "/root/path/"); - str = cstring_dirname(s->string); - ASSERT_EQUALS_STR("trailing / test", "/root", str); - free(str); - - reset(); - cstring_add(s, "/"); - str = cstring_dirname(s->string); - ASSERT_EQUALS_STR("root is root of root test", "/", str); - free(str); - - END - -START(concat) - char *cc; - - cc = cstring_concat(NULL); - if (cc) - FAIL("concat of NULL should return NULL, not: <%s>", cc); - - cc = cstring_concat("only", NULL); - ASSERT_EQUALS_STR("Single parameter", "only", cc); - free(cc); - - cc = cstring_concat("Only", "Fans", NULL); - ASSERT_EQUALS_STR("Test 2 params", "OnlyFans", cc); - free(cc); - - cc = cstring_concat("Fanfan", " ", "et", " Tulipe", - " entrent dans un bar", NULL); - ASSERT_EQUALS_STR("Test multiple params", - "Fanfan et Tulipe entrent dans un bar", cc); - free(cc); - - END - -START(many_adds) - size_t count = 10 * 1000 * 1000; - for (size_t i = 0; i < count; i++) { - cstring_add(s, "1234567890"); - } - - ASSERT_EQUALS_SIZE("Lot of adds", count * 10, s->length); - - END - -Suite *test_cstring(const char title[]) { - Suite *suite = suite_create(title); - - TCase *core = tcase_create("core"); - tcase_add_checked_fixture(core, setup, teardown); - tcase_add_test(core, init); - tcase_add_test(core, add_car); - tcase_add_test(core, add_all_but_p); - tcase_add_test(core, addp); - tcase_add_test(core, cut_at); - tcase_add_test(core, substring); - tcase_add_test(core, reverse); - tcase_add_test(core, replace); - tcase_add_test(core, replace_car); - tcase_add_test(core, starts_with); - tcase_add_test(core, ends_with); - tcase_add_test(core, find); - tcase_add_test(core, rfind); - tcase_add_test(core, clear); - tcase_add_test(core, convert); - tcase_add_test(core, clone); - tcase_add_test(core, rtrim); - tcase_add_test(core, trim); - tcase_add_test(core, remove_crlf); - tcase_add_test(core, toupper); - tcase_add_test(core, tolower); - tcase_add_test(core, readline); - tcase_add_test(core, add_path); - tcase_add_test(core, pop_path); - tcase_add_test(core, basename); - tcase_add_test(core, dirname); - tcase_add_test(core, concat); - - suite_add_tcase(suite, core); - - return suite; -} - -Suite *test_cstring_more(const char title[]) { - Suite *suite = suite_create(title); - - TCase *tmore = tcase_create("more"); - tcase_add_checked_fixture(tmore, setup, teardown); - tcase_add_test(tmore, many_adds); - - suite_add_tcase(suite, tmore); - - return suite; -} diff --git a/src/tests/utils/desktop.c b/src/tests/utils/desktop.c deleted file mode 100644 index 8047e1a..0000000 --- a/src/tests/utils/desktop.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2022 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "../../utils/desktop.h" - -#include - -#include "../launcher.h" - -desktop_t *d; - -static void setup() { - d = new_desktop("utils/test.desktop", 24); -} - -static void teardown() { - free_desktop(d); -} - -START(init) - if (!d) - FAIL("new_desktop returned NULL"); - - ASSERT_EQUALS_STR("Name", "IRC", d->name); - ASSERT_EQUALS_STR("Icon", "irssi", d->icon); - ASSERT_EQUALS_STR("Exec", "irssi", d->icon); - - END - - // TODO -START(NO_TEST_YET_submenu) - END -START(NO_TEST_YET_icons) - END -START(NO_TEST_YET_find_icon) - END -START(NO_TEST_YET_find_id) - END - -Suite *test_desktop(const char title[]) { - - d = new_desktop("test.desktop", 24); - free_desktop(d); - - Suite *suite = suite_create(title); - - TCase *core = tcase_create("core"); - tcase_add_checked_fixture(core, setup, teardown); - tcase_add_test(core, init); - tcase_add_test(core, NO_TEST_YET_submenu); - tcase_add_test(core, NO_TEST_YET_icons); - tcase_add_test(core, NO_TEST_YET_find_icon); - tcase_add_test(core, NO_TEST_YET_find_id); - - suite_add_tcase(suite, core); - - return suite; -} - -Suite *test_desktop_more(const char title[]) { - Suite *suite = suite_create(title); - - TCase *tmore = tcase_create("more"); - tcase_add_checked_fixture(tmore, setup, teardown); - // TODO - - suite_add_tcase(suite, tmore); - - return suite; -} diff --git a/src/tests/utils/main.c b/src/tests/utils/main.c deleted file mode 100644 index 4f2986a..0000000 --- a/src/tests/utils/main.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2022 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "main.h" -#include "launcher.h" - -SRunner *runner = NULL; -void add_test(Suite *test); - -SRunner *get_tests(int more) { - add_test(test_cstring("cstring")); - if (more) - add_test(test_cstring_more("cstring -- more (longer)")); - - add_test(test_array("array")); - if (more) - add_test(test_array_more("array -- more (longer)")); - - add_test(test_base64("base64")); - if (more) - add_test(test_base64_more("base64 -- more (longer)")); - - add_test(test_desktop("desktop")); - if (more) - add_test(test_desktop_more("desktop -- more (longer)")); - - return runner; -} - -void add_test(Suite *test) { - if (!runner) { - runner = srunner_create(test); - } else { - srunner_add_suite(runner, test); - } -} diff --git a/src/tests/utils/main.h b/src/tests/utils/main.h deleted file mode 100644 index f27dafa..0000000 --- a/src/tests/utils/main.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2022 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef SRC_TESTS_UTILS_MAIN_H_ -#define SRC_TESTS_UTILS_MAIN_H_ - -#include - -Suite *test_cstring(const char title[]); -Suite *test_cstring_more(const char title[]); -Suite *test_array(const char title[]); -Suite *test_array_more(const char title[]); -Suite *test_base64(const char title[]); -Suite *test_base64_more(const char title[]); -Suite *test_desktop(const char title[]); -Suite *test_desktop_more(const char title[]); - -#endif /* SRC_TESTS_UTILS_MAIN_H_ */ diff --git a/src/tests/utils/test.desktop b/src/tests/utils/test.desktop deleted file mode 100644 index 234d390..0000000 --- a/src/tests/utils/test.desktop +++ /dev/null @@ -1,10 +0,0 @@ -[Desktop Entry] -Version=1.0 -Name=IRC -Comment=Launch an IRC client -Exec=irssi -Icon=irssi -Terminal=true -Categories=Internet -Type=Application -StartupNotify=true diff --git a/src/tests/utils/test_readline.txt b/src/tests/utils/test_readline.txt deleted file mode 100644 index 10f2897..0000000 --- a/src/tests/utils/test_readline.txt +++ /dev/null @@ -1,3 +0,0 @@ -ligne 1 - -ligne 3 diff --git a/src/utils.d b/src/utils.d deleted file mode 100644 index 15a45e2..0000000 --- a/src/utils.d +++ /dev/null @@ -1,56 +0,0 @@ -# Note: 99+ required for for-loop initial declaration (CentOS 6) -# Note: gnu required for net.c/net.h - -CFLAGS += -Wall -pedantic -I./ -std=gnu99 -CXXFLAGS += -Wall -pedantic -I./ -PREFIX = /usr/local - -ifdef DEBUG -CFLAGS += -ggdb -O0 -CXXFLAGS += -ggdb -O0 -endif - -.PHONY: all install uninstall clean mrpropre mrpropre - -all: ../bin/libutils.o - -SOURCES=$(wildcard utils/*.c) -HEADERS=$(wildcard utils/*.h) -OBJECTS=$(SOURCES:%.c=%.o) - -utils/array.o: utils/array.[ch] -utils/desktop.o: utils/desktop.[ch] utils/array.h - -# easier, but more recompiles: -# $(OBJECTS): $(HEADERS) - -../bin/libutils.o: $(OBJECTS) - mkdir -p ../bin - # note: -r = --relocatable, but former also works with Clang - $(LD) -r $(OBJECTS) -o $@ - -clean: - rm -f utils/*.o - -mrproper: mrpropre - -mrpropre: clean - rm -f ../bin/libutils.o - rmdir ../bin || true - -install: - @echo "installing utils to $(PREFIX)..." - mkdir -p "$(PREFIX)/lib/cutils/" \ - && cp ../bin/libutils.o "$(PREFIX)/lib/cutils/" \ - && mkdir -p "$(PREFIX)/include/cutils/utils/" \ - && cp utils/*.h "$(PREFIX)/include/cutils/utils/" \ - -uninstall: - @echo "uninstalling utils from $(PREFIX)..." - rm -f "$(PREFIX)/lib/cutils/utils.o" \ - && rmdir "$(PREFIX)/lib/cutils/utils" 2>/dev/null || true \ - && rm -f "$(PREFIX)/include/cutils/utils/"*.h \ - && rmdir "$(PREFIX)/include/cutils/utils" 2>/dev/null || true \ - && rmdir "$(PREFIX)/lib/cutils" 2>/dev/null || true \ - && rmdir "$(PREFIX)/include/cutils" 2>/dev/null || true - diff --git a/src/utils/array.c b/src/utils/array.c deleted file mode 100644 index e5bb7ee..0000000 --- a/src/utils/array.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2020 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include - -#include "array.h" - -typedef struct { - size_t elem_size; - size_t buffer; - void *data; -} priv_t; - -/* make sure we have at least n+1 elements in the buffer, grow if needed */ -/* +1 is so we can always end with a NULL value for array_data/convert() */ -static int array_assure(array_t *me, size_t nb_elem); - -/* for qsort operations */ -static int array_qsorts_func(const void *a, const void *b); -static int array_qsorti_func(const void *a, const void *b); -static int array_qsortl_func(const void *a, const void *b); -static int array_qsortf_func(const void *a, const void *b); -static int array_qsorts_rfunc(const void *a, const void *b); -static int array_qsorti_rfunc(const void *a, const void *b); -static int array_qsortl_rfunc(const void *a, const void *b); -static int array_qsortf_rfunc(const void *a, const void *b); - -array_t *new_array(size_t elem_size, size_t initial) { - if (!initial) - return NULL; - - array_t *me = malloc(sizeof(array_t)); - if (!init_array(me, elem_size, initial)) { - free(me); - me = NULL; - } - - return me; -} - -int init_array(array_t *me, size_t elem_size, size_t initial) { - if (!initial) - return 0; - - strcpy(me->CNAME, "[CArray ]"); - - me->priv = malloc(sizeof(priv_t)); - if (!me->priv) - return 0; - - priv_t *priv = (priv_t *) me->priv; - strcpy(me->CNAME, "[CArray ]"); - priv->elem_size = elem_size; - me->count = 0; - priv->buffer = initial; - priv->data = malloc(elem_size * initial); - if (!priv->data) { - free(me->priv); - return 0; - } - - return 1; -} - -void free_array(array_t *me) { - if (me) - uninit_array(me); - - free(me); -} - -void uninit_array(array_t *me) { - priv_t *priv = (priv_t *) me->priv; - me->count = 0; - priv->buffer = 0; - free(priv->data); - priv->data = NULL; - free(priv); - me->priv = NULL; - me->CNAME[0] = '!'; -} - -void array_clear(array_t *me) { - me->count = 0; -} - -// convert to void * data (free the rest) -void *array_convert(array_t *me) { - priv_t *priv = (priv_t *) me->priv; - void *data = array_data(me); - free(priv); - free(me); - return data; -} - -void *array_data(array_t *me) { - priv_t *priv = (priv_t *) me->priv; - - // Note: this should be impossible - if (me->count >= priv->buffer) - array_assure(me, me->count + 1); - - // cast to (char *) because we want 'byte' arithmetic - void *after_end = (void *) (((char *) priv->data) - + (me->count * priv->elem_size)); - - // last item is always NULL - memset(after_end, '\0', priv->elem_size); - - return priv->data; -} - -size_t array_count(array_t *me) { - return me->count; -} - -void *array_new(array_t *me) { - return array_newn(me, 1); -} - -void *array_newn(array_t *me, size_t how_many) { - if (!array_assure(me, me->count + how_many)) - return 0; - - me->count += how_many; - return array_get(me, me->count - how_many); -} - -void *array_first(array_t *me) { - if (!me->count) - return NULL; - - priv_t *priv = (priv_t *) me->priv; - return priv->data; -} - -void *array_last(array_t *me) { - if (!me->count) - return NULL; - - priv_t *priv = (priv_t *) me->priv; - // cast to (char *) because we want 'byte' arithmetic - return (void *) (((char *) priv->data) + ((me->count - 1) * priv->elem_size)); -} - -void *array_prev(array_t *me, void *ptr) { - priv_t *priv = (priv_t *) me->priv; - - // cast to (char *) because we want 'byte' arithmetic - char *cptr = (char *) ptr; - char *cdata = (char*) priv->data; - - if (cptr) { - cptr -= priv->elem_size; - if (cptr >= cdata) { - return cptr; - } - } - - return NULL; -} - -void *array_next(array_t *me, void *ptr) { - priv_t *priv = (priv_t *) me->priv; - - // cast to (char *) because we want 'byte' arithmetic - char *cptr = (char *) ptr; - char *cdata = (char*) priv->data; - - if (cptr) { - cptr += priv->elem_size; - char *last = cdata + ((me->count - 1) * priv->elem_size); - if (cptr <= last) { - return cptr; - } - } - - return NULL; -} - -void *array_get(array_t *me, size_t i) { - priv_t *priv = (priv_t *) me->priv; - - // cast to (char *) because we want 'byte' arithmetic - return (void *) (((char *) priv->data) + (i * priv->elem_size)); -} - -void *array_pop(array_t *me) { - return array_cut_at(me, me->count - 1); -} - -void *array_cut_at(array_t *me, size_t n) { - if (n < me->count) { - void *item = array_get(me, n); - me->count = n; - return item; - } - - return NULL; -} - -void array_compact(array_t *me) { - priv_t *priv = (priv_t *) me->priv; - - int c = me->count ? me->count : 1; - priv->data = realloc(priv->data, c * priv->elem_size); - priv->buffer = c; -} - -void array_qsort(array_t *me, int (*compar)(const void *, const void *)) { - priv_t *priv = (priv_t *) me->priv; - qsort(priv->data, me->count, priv->elem_size, compar); -} - -void array_qsorts(array_t *me, int rev) { - array_qsort(me, rev ? array_qsorts_rfunc : array_qsorts_func); -} -static int array_qsorts_func(const void *a, const void *b) { - char *stra = ((char **) a)[0]; - char *strb = ((char **) b)[0]; - return strcmp(stra, strb); -} -static int array_qsorts_rfunc(const void *a, const void *b) { - char *stra = ((char **) a)[0]; - char *strb = ((char **) b)[0]; - return strcmp(strb, stra); -} - -void array_qsorti(array_t *me, int rev) { - array_qsort(me, rev ? array_qsorti_rfunc : array_qsorti_func); -} -static int array_qsorti_func(const void *a, const void *b) { - long ia, ib; - ia = ((int *) a)[0]; - ib = ((int *) b)[0]; - if (ia < ib) - return -1; - return !(ia == ib); -} -static int array_qsorti_rfunc(const void *a, const void *b) { - long ia, ib; - ia = ((int *) a)[0]; - ib = ((int *) b)[0]; - if (ia > ib) - return -1; - return !(ia == ib); -} - -void array_qsortl(array_t *me, int rev) { - array_qsort(me, rev ? array_qsortl_rfunc : array_qsortl_func); -} -static int array_qsortl_func(const void *a, const void *b) { - long la, lb; - la = ((long *) a)[0]; - lb = ((long *) b)[0]; - if (la < lb) - return -1; - return !(la == lb); -} -static int array_qsortl_rfunc(const void *a, const void *b) { - long la, lb; - la = ((long *) a)[0]; - lb = ((long *) b)[0]; - if (la > lb) - return -1; - return !(la == lb); -} - -void array_qsortf(array_t *me, int rev) { - array_qsort(me, rev ? array_qsortf_rfunc : array_qsortf_func); -} -static int array_qsortf_func(const void *a, const void *b) { - float fa, fb; - fa = ((float *) a)[0]; - fb = ((float *) b)[0]; - // Also works: - //memcpy(&fa, a, sizeof(float)); - //memcpy(&fb, b, sizeof(float)); - if (fa < fb) - return -1; - return !(fa == fb); -} -static int array_qsortf_rfunc(const void *a, const void *b) { - float fa, fb; - fa = ((float *) a)[0]; - fb = ((float *) b)[0]; - // Also works: - //memcpy(&fa, a, sizeof(float)); - //memcpy(&fb, b, sizeof(float)); - if (fa > fb) - return -1; - return !(fa == fb); -} - -int array_push(array_t *me, void *data) { - return array_setn(me, me->count, data, 1); -} - -int array_pushn(array_t *me, void *data, size_t n) { - return array_setn(me, me->count, data, n); -} - -int array_copy(array_t *me, void *target, size_t i) { - return array_copyn(me, target, i, 1); -} - -int array_copyn(array_t *me, void *target, size_t i, size_t n) { - priv_t *priv = (priv_t *) me->priv; - - if (i + n < me->count) { - // cast to (char *) because we want 'byte' arithmetic - memcpy(target, ((char *) (priv->data)) + (i * priv->elem_size), - n * priv->elem_size); - - return 1; - } - - return 0; -} - -int array_set(array_t *me, size_t i, void *data) { - return array_setn(me, i, data, 1); -} - -int array_setn(array_t *me, size_t i, void *data, size_t n) { - // allow new items BUT NOT holes in the array - if (i > me->count) - return 0; - - if (!array_assure(me, i + n)) - return 0; - - priv_t *priv = (priv_t *) me->priv; - - // cast to (char *) because we want 'byte' arithmetic - memcpy(((char *) (priv->data)) + (i * priv->elem_size), data, - n * priv->elem_size); - if ((i + n) > me->count) - me->count = i + n; - - return 1; -} - -/* Privates functions */ - -static int array_assure(array_t *me, size_t nb_elem) { - priv_t *priv = (priv_t *) me->priv; - - if (priv->buffer <= nb_elem) { - priv->buffer *= 2; - if (priv->buffer < nb_elem) { - priv->buffer = nb_elem; - } - - void *tmp = realloc(priv->data, priv->elem_size * priv->buffer); - if (!tmp) - return 0; - - priv->data = tmp; - } - - return 1; -} diff --git a/src/utils/array.h b/src/utils/array.h deleted file mode 100644 index 3638562..0000000 --- a/src/utils/array.h +++ /dev/null @@ -1,465 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2020 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * @file array.h - * @author Niki - * @date 2020 - 2022 - * - * @brief A simple auto-growing array-list - * - * A simple auto-growing array-list, with a minimum buffer of 1. - * - * It has a link to `qsort`, too, so you don't need to retype all - * the parameters you already passed to the array. - * - * It is created with `new_array()` and must be freed with : - * - `free_array()` for normal operations - * - `array_convert()` if you want to free the array but keep the data - * (the data is now your responsibility to free or not, it was allocated - * with `malloc`/`realloc`) - * - * Example usage: - * ```C - * array lines = new_array(sizeof(char *), 100); - * - * const char *l1 = "2. À l'arrière"; - * const char *l2 = "3. En réserve"; - * const char *l3 = "1. Première ligne"; - * - * // push mode (usually used for int, char, long...) - * array_push(lines, &l1); - * array_push(lines, &l2); - * - * // new mode (usually used for structures) - * char **tmp = array_new(lines); - * *tmp = l3; - * - * // sort as Strings (also possible with int, long and custom functions) - * array_qsorts(lines, 0); - * - * char **last_line = array_get(lines, array_count(lines) - 1); - * printf("Last line is now: %s\n", *last_line); - * // -> last_line is now: 3. En réserve - * - * array_loop(lines, line, char) { - * printf("Line: %s\n", line); - * } - * // -> Line: 1. Première ligne - * // -> Line: 2. En réserve - * // -> Line: 3. À l'arrière - * - * free_array(lines); - * ``` - */ - -#ifndef ARRAY_H -#define ARRAY_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -/** - * Declare a new TYPE * pointer and loop through the array with it. - * - * How to use: - * ```C - * array_loop(me, line, char) { - * printf("Item: %s\n", line); - * } - * ``` - */ -#define array_loop(me, ptr, TYPE) \ - for (TYPE *ptr = array_first(me); ptr; ptr = array_next(me, ptr)) - -/** - * Similar to array_loop, but add a counter i starting at 0. - * - * @see array_loop - * - * How to use: - * ```C - * array_loop_i(me, line, char, i) { - * printf("Item n°%d: %s\n", i, line); - * } - * ``` - * - * @note this macro does expand as 2 separate lines, surround with { } if needed - */ -#define array_loop_i(me, ptr, TYPE, i) \ - size_t i = 0; \ - for (TYPE *ptr = array_first(me); ptr; ptr = array_next(me, ptr), i++) - -/** - * @brief A simple auto-growing array-list - * - * The structure contains a private field (which you should not use) and the - * current count of how many items were added. You should probably not modify - * the count either (setting it higher is a bad idea and while it should be - * possible to set it lower, you are strongly advised to use - * array_cut_at instead). - * - * @see array_cut_at - */ -typedef struct { - char CNAME[10]; - size_t count; - void *priv; -} array_t; - -/** - * Create a new array. - * - * @note always identical to malloc + init_array - * - * @param elem_size the size of one element - * @param initial the initial number of items the buffer can hold (not 0) - * - * @see malloc() - * @see init_array(array_t *self) - * - * @return a new array (you must later call `free_array()` or `array_convert()`) - */ -array_t *new_array(size_t elem_size, size_t initial); - -/** - * Initialise a new array. - * - * @param elem_size the size of one element - * @param initial the initial number of items the buffer can hold (not 0) - */ -int init_array(array_t *self, size_t elem_size, size_t initial); - -/** - * Free the resources held for the given array: you must not use it any more. - * Note that if you use pointers and not direct data, you may want to free - * those yourself first. - * - * @note always equivalent to uninit_array + free - * - * @see uninit_array(array_t *self) - * @see free(void *data) - * @see array_clear - * @see array_loop - */ -void free_array(array_t *me); - -/** - * Free the resources held for the given array: you must not use it any more. - * Note that if you use pointers and not direct data, you may want to free - * those yourself first. - * - * @see free_array(array_t *self) - * @see array_clear - * @see array_loop - */ -void uninit_array(array_t *me); - -/** - * Clear the array, that is, resets its current size to 0 (buffer unchanged). - * - * @note if you hold custom structures with owned resources in the array, you - * should deallocate them properly before - */ -void array_clear(array_t *me); - -/** - * Convert the array to a block of memory where all values are adjacent. - * - * @note an extra NULL value is assured to be present as last element - * - * @return the data (you must later call `free()` on it) - */ -void *array_convert(array_t *me); - -/** - * Return a pointer to the internal storage used by this array. - * This is the same value as would return `array_convert()`, - * but the array is still valid. - * - * Be careful if you change the content (you should not). - * - * @note an extra NULL value is assured to be present as last element - * - * @return the internal storage area - */ -void *array_data(array_t *me); - -/** - * Return the current number of elements in the array. - * - * @return the number of elements in the array - */ -size_t array_count(array_t *me); - -/** - * Create a new element in the array and return a pointer to it. - * - * @return a pointer to the (newly allocated) last element of the array - */ -void *array_new(array_t *me); - -/** - * Create n elements in the array and return a pointer to the - * first one ({see array_next(void *)} to get the next ones). - * - * @param n how many elements to add - * - * @return a pointer to the (newly allocated) first new element of the array - */ -void *array_newn(array_t *me, size_t n); - -/** - * Return a pointer to the first element of the array (for instance, if you - * store integers, it will be (int *); if you store strings, it will - * be char **). - * - * @return a pointer to the first element, or NULL if no elements are - * present - */ -void *array_first(array_t *me); - -/** - * Return a pointer to the last element of the array (for instance, if you - * store integers, it will be (int *); if you store strings, it will - * be char **). - * - * @return a pointer to the last element, or NULL if no elements are - * present - */ -void *array_last(array_t *me); - -/** - * Return the pointer to the previous element, or NULL if it was the first. - * - * @param ptr a pointer from an array (the array must be valid) - * - * @return the previous element, or NULL - */ -void *array_prev(array_t *me, void *ptr); - -/** - * Return the pointer to the next element, or NULL if it was the last. - * - * @param ptr a pointer from an array (the array must be valid) - * - * @return the next element, or NULL - */ -void *array_next(array_t *me, void *ptr); - -/** - * Retrieve the the pointer of an item. - * The address of the item will be returned. - * - * @param i the index of the element to retrieve - * - * @note if the index is out of bounds, you will get invalid data - * - * @return the pointer to the i'th element - */ -void *array_get(array_t *me, size_t i); - -/** - * Return a pointer to the last element of this array and remove it from the - * array, if the array is not empty. - * - * @note be careful, the memory pointed to by the element will be reused the - * next time we add an element -- you should not use it after this; in - * short, the return value is mainly so you can call free on - * value pointed to by this pointer (not the pointer itself) if it - * is a pointer to memory you own, or use it locally before continuing to - * use the array - * @note in case this was not clear, do not call free on the - * returned value - * - * @return a pointer to the last (now removed) item, or NULL if no element - */ -void *array_pop(array_t *me); - -/** - * Cut the array at the given size and return a pointer to the first element - * that was removed if any. - * - * @note be careful, the memory pointed to by the element(s) will be reused the - * next time we add an element -- you should not use it after this; in - * short, the return value is mainly so you can call free on - * value(s) pointed to by this pointer (not the pointer itself) if - * it is a pointer to memory you own, or use it locally before continuing - * to use the array - * @note in case this was not clear, do not call free on the - * returned value(s) - * - * @return a pointer to the first removed element, or NULL - */ -void *array_cut_at(array_t *me, size_t n); - -/** - * Compact the array (resize the buffer so it is equals to the current number - * of items in the array or size 1 if there are no items in the array). - */ -void array_compact(array_t *me); - -/** - * Sort the array with a call to `qsort()`. - * All the appropriate parameters are passed, except the sorting function. - * - * @param compar a custom comparison function - * @param (parameters) - * * `itm1`: a **pointer** to one of your data element (for instance, - * if you store floats, it will be a `(float *)`, - * so you would need to cast it via `((float *)itm1)[0]` - * * `itm2`: another **pointer** to compare with the first one - * @param (returns) - * * `-1`: if element A is less than element B - * * `0`: if both elements are equals - * * `1`: if element A is more than element B - */ -void array_qsort(array_t *me, int (*compar)(const void *itm1, const void *itm2)); - -/** - * Sort the array with `qsort()`, data is `char *`. - * - * @param rev FALSE for normal order, TRUE for reverse order - * - * @see array_qsort - */ -void array_qsorts(array_t *me, int rev); - -/** - * Sort the array with `qsort()`, data is `int`. - * - * @param rev FALSE for normal order, TRUE for reverse order - * - * @see array_qsort - */ -void array_qsorti(array_t *me, int rev); - -/** - * Sort the array with `qsort()`, data is `long`. - * - * @param rev FALSE for normal order, TRUE for reverse order - * - * @see array_qsort - */ -void array_qsortl(array_t *me, int rev); - -/** - * Sort the array with `qsort()`, data is `float`. - * - * @param rev FALSE for normal order, TRUE for reverse order - * - * @see array_qsort - */ -void array_qsortf(array_t *me, int rev); - -/** - * Add an element to the array (will create a new item in the array and copy the - * data from the given element in it). - * - * @param data the memory position of the element to add - * - * @return FALSE if the array is too short and we cannot allocate enough - * contiguous memory for its needs - */ -int array_push(array_t *me, void *data); - -/** - * Add multiple elements to the array (will create new items in the array and - * copy the data from the given elements in them). - * - * @param data the memory position of the elements to add, adjacent to each - * other - * @param n the number of elements to copy from `data` - * - * @return FALSE if the array is too short and we cannot allocate enough - * contiguous memory for its needs - */ -int array_pushn(array_t *me, void *data, size_t n); - -/** - * Retrieve the content of an item. - * The item will be copied to the given address location if it exists. - * - * @param target an address where to write a copy of the item - * @param i the index of the element to retrieve - * - * @return TRUE if the item exists (if i is an element of the array) - */ -int array_copy(array_t *me, void *target, size_t i); - -/** - * Retrieve the content of multiple items if they exist. - * The items will be copied in a sequence to the given address location. - * - * @param target an address where to write a copy of the items - * @param i the index of the first element to retrieve - * @param n the number of elements to retrieve - * - * @return TRUE if the item exists (if i to n are elements - * of the array) - */ -int array_copyn(array_t *me, void *target, size_t i, size_t n); - -/** - * Set an element of the array to the given value. - * Can also append an element at the end of the array (i.e., i can be - * the size of the array and this will result in an array with one more - * element). - * Memory will be copied from the given data to the array. - * - * @param i the element index - * @param data the data that will replace the current value, or new data - * to append after the current elements (you can add items just at - * the end of the array (index = count), but it is not allowed to - * set items after that index, so not to create holes) - * - * @return FALSE if the array is too short and we cannot allocate enough - * contiguous memory for its needs, or if the index is out of bounds - */ -int array_set(array_t *me, size_t i, void *data); - -/** - * Set elements of the array to the given value. - * Can also append elements at the end of the array (i.e., i can be - * the size of the array and this will result in an array with n more - * elements). - * Memory will be copied from the given data to the array. - * - * @param i the element index to start the insertion at - * @param data the data that will replace the current values, or new data - * to append after the current elements (you can add items just at - * the end of the array (index = count), but it is not allowed to - * set items with `i` after that index, so not to create holes) - * @param n the number of elements to copy from `data` and to insert at `i` - * - * @return FALSE if the array is too short and we cannot allocate enough - * contiguous memory for its needs, or if the index is out of bounds - */ -int array_setn(array_t *me, size_t i, void *data, size_t n); - -#endif /* ARRAY_H */ - -#ifdef __cplusplus -} -#endif - diff --git a/src/utils/base64.c b/src/utils/base64.c deleted file mode 100644 index d151fe3..0000000 --- a/src/utils/base64.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2013 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "base64.h" - -#include -#include - -static char encoding_table[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', - 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', - 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', - 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; - -static int decoding_table_flg = 0; -static char decoding_table[256]; - -static void init_dtable() { - if (!decoding_table_flg) { - for (int i = 0; i < 64; i++) - decoding_table[(unsigned char) encoding_table[i]] = i; - decoding_table_flg = 1; - } -} - -char *base64_encode(const char *data) { - size_t input_length = strlen(data); - size_t output_length = 4 * ((input_length + 2) / 3); - - char *encoded_data = malloc(output_length + 1); - if (!encoded_data) - return NULL; - - for (unsigned int i = 0, j = 0; i < input_length;) { - unsigned int octet_a = i < input_length ? (unsigned char) data[i++] : 0; - unsigned int octet_b = i < input_length ? (unsigned char) data[i++] : 0; - unsigned int octet_c = i < input_length ? (unsigned char) data[i++] : 0; - - unsigned int triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; - - encoded_data[j++] = (char) encoding_table[(triple >> 3 * 6) & 0x3F]; - encoded_data[j++] = (char) encoding_table[(triple >> 2 * 6) & 0x3F]; - encoded_data[j++] = (char) encoding_table[(triple >> 1 * 6) & 0x3F]; - encoded_data[j++] = (char) encoding_table[(triple >> 0 * 6) & 0x3F]; - } - - if ((input_length % 3) > 0) - encoded_data[output_length - 1] = '='; - if ((input_length % 3) == 1) - encoded_data[output_length - 2] = '='; - - encoded_data[output_length] = '\0'; - - return encoded_data; -} - -char *base64_decode(const char *data) { - init_dtable(); - - size_t input_length = strlen(data); - if (input_length % 4 != 0) - return NULL; - - size_t output_length = ((input_length / 4) * 3); - if (data[input_length - 1] == '=') - output_length--; - if (data[input_length - 2] == '=') - output_length--; - - char *decoded_data = malloc(output_length + 1); - if (!decoded_data) - return NULL; - - for (unsigned int i = 0, j = 0; i < input_length; i += 4) { - unsigned int sextet_a = 0; - unsigned int sextet_b = 0; - unsigned int sextet_c = 0; - unsigned int sextet_d = 0; - - if (data[i] != '=') { - sextet_a = decoding_table[(unsigned char) data[i + 0]]; - sextet_b = decoding_table[(unsigned char) data[i + 1]]; - sextet_c = decoding_table[(unsigned char) data[i + 2]]; - sextet_d = decoding_table[(unsigned char) data[i + 3]]; - } - - unsigned int triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) - + (sextet_c << 1 * 6) + (sextet_d << 0 * 6); - - if (j < output_length) - decoded_data[j++] = (char) ((triple >> 2 * 8) & 0xFF); - if (j < output_length) - decoded_data[j++] = (char) ((triple >> 1 * 8) & 0xFF); - if (j < output_length) - decoded_data[j++] = (char) ((triple >> 0 * 8) & 0xFF); - } - - decoded_data[output_length] = '\0'; - return decoded_data; -} - diff --git a/src/utils/base64.h b/src/utils/base64.h deleted file mode 100644 index b6c3f25..0000000 --- a/src/utils/base64.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2013 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * @file base64.h - * @author Niki - * @date 2013 - 2022 - * - * @brief Base64 encode and decode - * - * This file only provides 2 functions, base64_encode and - * base64_decode, which works on NUL-terminated strings and do what - * you expect them to. - * - * @see base64_encode(const char data[]) - * @see base64_decode(const char data[]) - */ - - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef BASE64_H -#define BASE64_H - -#include - -/** - * Encode the given data to Base64. - * - * @note can return NULL if there is not enough memory to allocated the answer - * - * @param data the data to encode - * - * @return a newly-allocated string for which you are responsible, or NULL - */ -char *base64_encode(const char data[]); - -/** - * Decode the given data to Base64. - * - * @note can return NULL if there is not enough memory to allocated the answer - * - * @param data the data to decode - * - * @return a newly-allocated string for which you are responsible, or NULL - */ -char *base64_decode(const char data[]); - -#endif - -#ifdef __cplusplus -} -#endif diff --git a/src/utils/cstring.c b/src/utils/cstring.c deleted file mode 100644 index 07215e7..0000000 --- a/src/utils/cstring.c +++ /dev/null @@ -1,773 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2011 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - Name: cstring.c - Copyright: niki (gpl3 or later) 2011 - Author: niki - Date: 2011-06-16 - Description: cstring is a collection of helper functions to manipulate text - */ - -#include "cstring.h" - -#include -#include -#include -#include -#include - -// For upper/lowercase -#include - -#ifndef BUFFER_SIZE -#define BUFFER_SIZE 81 -#endif - -#ifdef WIN32 -#define CSTRING_SEP '\\' -#else -#define CSTRING_SEP '/' -#endif - -// Private functions - -typedef struct { - size_t buffer_length; -} priv_t; - -/** Swap the data */ -static void cstring_swap(cstring_t *a, cstring_t *b); -/** Change the case to upper -or- lower case (UTF8-compatible) */ -static void cstring_change_case(cstring_t *self, int up); -/** For path-related functions */ -static void normalize_path(cstring_t *self); - -// Private variables - -static char *locale = NULL; - -// end of privates - -cstring_t *new_cstring() { - cstring_t *self = malloc(sizeof(cstring_t)); - if (!init_cstring(self)) { - free(self); - self = NULL; - } - - return self; -} - -int init_cstring(cstring_t *self) { - strcpy(self->CNAME, "[CString]"); - - self->priv = malloc(sizeof(priv_t)); - if (!self->priv) - return 0; - self->string = malloc(sizeof(char) * BUFFER_SIZE); - if (!self->string) { - free(self->priv); - return 0; - } - - self->length = 0; - ((priv_t *) self->priv)->buffer_length = BUFFER_SIZE; - self->string[0] = '\0'; - - return 1; -} - -void free_cstring(cstring_t *self) { - if (self) - uninit_cstring(self); - - free(self); -} - -void uninit_cstring(cstring_t *self) { - free(self->priv); - free(self->string); - self->priv = NULL; - self->string = NULL; - self->length = 0; - self->CNAME[0] = '!'; -} - -void cstring_swap(cstring_t *a, cstring_t *b) { - void *tmp_p; - char *tmp_s; - size_t tmp_l; - - tmp_s = a->string; - tmp_l = a->length; - tmp_p = a->priv; - - a->string = b->string; - a->length = b->length; - a->priv = b->priv; - - b->string = tmp_s; - b->length = tmp_l; - b->priv = tmp_p; -} - -int cstring_grow(cstring_t *self, int min_extra) { - priv_t *priv = ((priv_t *) self->priv); - - size_t sz = priv->buffer_length; - size_t req = self->length + min_extra; - - if (req > sz) { - if (sz > BUFFER_SIZE) - sz *= 2; - else - sz += BUFFER_SIZE; - - if (req > sz) - sz = req; - - return cstring_grow_to(self, sz); - } - - return 1; -} - -int cstring_grow_to(cstring_t *self, int min_buffer) { - priv_t *priv = ((priv_t *) self->priv); - - if (min_buffer > priv->buffer_length) { - priv->buffer_length = min_buffer; - void *mem = realloc(self->string, sizeof(char) * priv->buffer_length); - - if (mem) - self->string = (char *) mem; - else - return 0; - } - - return 1; -} - -void cstring_compact(cstring_t *self) { - if (self != NULL) { - priv_t *priv = ((priv_t *) self->priv); - - priv->buffer_length = self->length + 1; - self->string = (char *) realloc(self->string, self->length + 1); - } -} - -int cstring_add_car(cstring_t *self, char source) { - if (!cstring_grow(self, 1)) - return 0; - - self->string[self->length] = source; - self->length++; - self->string[self->length] = '\0'; - - return 1; -} - -int cstring_add(cstring_t *self, const char source[]) { - return cstring_addf(self, source, 0); -} - -int cstring_addf(cstring_t *self, const char source[], size_t idx) { - return cstring_addfn(self, source, idx, 0); -} - -int cstring_addn(cstring_t *self, const char source[], size_t n) { - return cstring_addfn(self, source, 0, n); -} - -int cstring_addfn(cstring_t *self, const char source[], size_t idx, size_t n) { - size_t ss; - - ss = strlen(source); - if (source && ss > idx && idx >= 0) { - ss -= idx; - - if (n && n < ss) - ss = n; - - if (ss) { - // "+1" for the added '\0' - if (!cstring_grow(self, ss + 1)) - return 0; - - memcpy(self->string + self->length, source + idx, ss); - self->length += ss; - self->string[self->length] = '\0'; - } - } - - return 1; -} - -int cstring_addp(cstring_t *self, const char *fmt, ...) { - va_list ap; - char empty = '\0'; - - va_start(ap, fmt); - int sz = vsnprintf(&empty, 0, fmt, ap); - va_end(ap); - - char *tmp = malloc((sz + 1) * sizeof(char)); - if (!tmp) - return 0; - - va_start(ap, fmt); - sz = vsnprintf(tmp, sz + 1, fmt, ap); - va_end(ap); - - int ok = cstring_add(self, tmp); - free(tmp); - - return ok; -} - -void cstring_cut_at(cstring_t *self, size_t size) { - if (self->length > size) { - self->string[size] = '\0'; - self->length = size; - } -} - -cstring_t *cstring_substring(const char self[], size_t start, size_t length) { - size_t sz = strlen(self); - cstring_t * sub = new_cstring(); - - if (start <= sz) { - const char *source = (self + start); - - if (!length) - cstring_add(sub, source); - else - cstring_addn(sub, source, length); - } - - return sub; -} - -/* - clist *cstring_splitc(cstring *self, char delim, char quote) { - clist *list; - cstring *d, *q; - - d = new_cstring(); - q = new_cstring(); - - if (delim) - cstring_add_car(d, delim); - if (quote) - cstring_add_car(q, quote); - - list = cstring_split(self, d, q); - - free_cstring(d); - free_cstring(q); - - return list; - } - - clist *cstring_splits(cstring *self, const char delim[], const char quote[]) { - clist *list; - cstring *d, *q; - - d = new_cstring(); - q = new_cstring(); - - if (delim) - cstring_add(d, delim); - if (quote) - cstring_add(q, quote); - - list = cstring_split(self, d, q); - - free_cstring(d); - free_cstring(q); - - return list; - } - clist *cstring_split(cstring *self, cstring *delim, cstring *quote) { - clist *list; - cstring *elem; - clist_node *node; - size_t i; - int in_quote; - int hasdelim; - - hasdelim = delim && delim->length > 0; - - list = clist_new(); - in_quote = 0; - elem = NULL; - for (i = 0; i < self->length; i++) { - if (quote->length > 0 && cstring_starts_with(self, quote, i)) { - in_quote = !in_quote; - i += quote->length - 1; - } else { - if (elem == NULL) { - elem = new_cstring(); - node = clist_node_new(); - node->data = elem; - node->free_data = free_cstring; - clist_add(list, node); - } - if (!in_quote && hasdelim && cstring_starts_with(self, delim, i)) { - elem = new_cstring(); - node = clist_node_new(); - node->data = elem; - node->free_data = free_cstring; - clist_add(list, node); - i += delim->length - 1; - } else { - cstring_add_car(elem, self->string[i]); - } - } - } - - return list; - } - */ - -void cstring_reverse(char *self) { - size_t i; - size_t last; - char tmp; - - size_t sz = strlen(self); - if (sz) { - last = sz - 1; - for (i = 0; i <= (last / 2); i++) { - tmp = self[i]; - self[i] = self[last - i]; - self[last - i] = tmp; - } - } -} - -int cstring_replace(cstring_t *self, const char from[], const char to[]) { - cstring_t *buffer; - size_t i; - size_t step; - int occur; - - // easy optimisation: - if (!from || !from[0]) - return 0; - if (from && to && from[0] && to[0] && !from[1] && !to[1]) - return cstring_replace_car(self->string, from[0], to[0]); - - // optimise for same-size strings? - - step = strlen(from) - 1; - buffer = new_cstring(); - occur = 0; - for (i = 0; i < self->length; i++) { - if (cstring_starts_with(self->string, from, i)) { - cstring_add(buffer, to); - i += step; - occur++; - } else { - cstring_add_car(buffer, self->string[i]); - } - } - - cstring_swap(self, buffer); - free_cstring(buffer); - return occur; -} - -int cstring_replace_car(char *self, char from, char to) { - size_t i; - int occur = 0; - - for (i = 0; self[i]; i++) { - if (self[i] == from) { - self[i] = to; - occur++; - } - } - - return occur; -} - -int cstring_starts_with(const char string[], const char find[], - size_t start_idx) { - size_t i; - - for (i = 0; - string[start_idx + i] == find[i] && string[start_idx + i] != '\0' - && find[i] != '\0'; i++) - ; - - return find[i] == '\0'; -} - -int cstring_ends_with(const char self[], const char find[]) { - size_t sz = strlen(self); - size_t sz_needle = strlen(find); - if (sz_needle <= sz) { - if (!strcmp(self + (sz - sz_needle), find)) - return 1; - } - - return 0; -} - -long cstring_find(const char self[], const char find[], size_t start_index) { - size_t sz = strlen(self); - if (sz > start_index) { - char *found = strstr(self + start_index, find); - if (found) { - return (long) (found - self); - } - } - - return -1; -} - -long cstring_rfind(char self[], const char find[], long rstart_index) { - size_t sz = strlen(self); - size_t sz_needle = strlen(find); - - if (rstart_index <= 0) - rstart_index += (sz - 1); - - if (sz > rstart_index && sz_needle <= sz) { - for (size_t i = rstart_index;; i--) { - if (cstring_starts_with(self, find, i)) - return i; - - if (!i) - break; - } - } - - return -1; -} - -void cstring_clear(cstring_t *self) { - self->length = 0; - self->string[0] = '\0'; -} - -char *cstring_convert(cstring_t *self) { - char *string; - - if (!self) - return NULL; - - // Note: this could be skipped. - cstring_compact(self); - - string = (self->string); - self->string = NULL; - - free_cstring(self); - - return string; -} - -cstring_t *cstring_clone(const char self[]) { - if (self == NULL) - return NULL; - - cstring_t *clone = new_cstring(); - cstring_add(clone, self); - - return clone; -} - -void cstring_rtrim(cstring_t *self, char car) { - for (size_t i = self->length - 1; i >= 0; i--) { - if (self->string[i] != car) - break; - self->string[i] = '\0'; - self->length--; - } -} - -void cstring_trim(cstring_t *self, char car) { - if (car == '\0') - return; - - cstring_rtrim(self, car); - - int i = 0; - while (self->string[i] == car) - i++; - - if (i) { - cstring_t *tmp = new_cstring(); - cstring_add(tmp, self->string + i); - - cstring_swap(self, tmp); - free_cstring(tmp); - } -} - -size_t cstring_remove_crlf(char *self) { - size_t sz = strlen(self); - if (sz && self[sz - 1] == '\n') - sz--; - if (sz && self[sz - 1] == '\r') - sz--; - - self[sz] = '\0'; - - return sz; -} - -void cstring_toupper(cstring_t *self) { - cstring_change_case(self, 1); -} - -void cstring_tolower(cstring_t *self) { - cstring_change_case(self, 0); -} - -void cstring_change_case(cstring_t *self, int up) { - // Change LC_ALL to LANG if not found - // TODO: only take part we need (also, this is still bad practise) - if (!locale) { - locale = setlocale(LC_ALL, NULL); - if (!locale || !locale[0] || !strcmp("C", locale)) { - char *lang = getenv("LANG"); - if (lang && lang[0]) { - locale = setlocale(LC_ALL, lang); - if (!locale) - locale = ""; - } - } - } - - cstring_t *rep; - mbstate_t state_from, state_to; - wchar_t wide; - char tmp[10]; - size_t count; - - // init the state (NULL = internal hidden state, not thread-safe) - memset(&state_from, '\0', sizeof(mbstate_t)); - memset(&state_to, '\0', sizeof(mbstate_t)); - - rep = new_cstring(); - - size_t i = 0; - while (i < self->length) { - count = mbrtowc(&wide, self->string + i, self->length - i, &state_from); - - //incomplete (should not happen) - if (count == (size_t) -2) { - // return; - cstring_add_car(rep, '_'); - i++; - continue; - } - // invalid multibyte sequence - if (count == (size_t) -1) { - // return; - cstring_add_car(rep, '_'); - i++; - continue; - } - - // End of String (should not happen, see WHILE condition) - if (!count) - break; - - // char is ok - i += count; - - if (up) - wide = (wchar_t) towupper((wint_t) wide); - else - wide = (wchar_t) towlower((wint_t) wide); - - count = wcrtomb(tmp, wide, &state_to); - if (count == (size_t) -1) { - // failed to convert :( - cstring_add_car(rep, '_'); - } else { - tmp[count] = '\0'; - cstring_add(rep, tmp); - } - } - - cstring_swap(self, rep); - free_cstring(rep); -} - -static char buffer[BUFFER_SIZE]; -int cstring_readline(cstring_t *self, FILE *file) { - size_t size = 0; - int full_line; - - // sanity check: - if (!file) - return 0; - - buffer[BUFFER_SIZE - 1] = '\0'; // just in case - - if (!feof(file)) { - cstring_clear(self); - buffer[0] = '\0'; - - // Note: fgets() could return NULL if EOF is reached - if (!fgets(buffer, (int) BUFFER_SIZE - 1, file)) - return 0; - - size = strlen(buffer); - full_line = ((file && feof(file)) || size == 0 - || buffer[size - 1] == '\n'); - size = cstring_remove_crlf(buffer); - cstring_add(self, buffer); - - // No luck, we need to continue getting data - while (!full_line) { - if (!fgets(buffer, (int) BUFFER_SIZE - 1, file)) - break; - - size = strlen(buffer); - full_line = ((file && feof(file)) || size == 0 - || buffer[size - 1] == '\n'); - size = cstring_remove_crlf(buffer); - cstring_add(self, buffer); - } - - return 1; - } - - return 0; -} - -static void normalize_path(cstring_t *self) { - while (self->length && self->string[self->length - 1] == CSTRING_SEP) - self->length--; - self->string[self->length] = '\0'; -} - -void cstring_add_path(cstring_t *self, const char subpath[]) { - while (self->length && self->string[self->length - 1] == CSTRING_SEP) - self->length--; - cstring_add_car(self, CSTRING_SEP); - if (subpath && subpath[0]) { - cstring_add(self, subpath); - } - - normalize_path(self); -} - -int cstring_pop_path(cstring_t *self, int how_many) { - int count = 0; - size_t tmp; - char first = '\0'; - - if (self->length) - first = self->string[0]; - - normalize_path(self); - for (int i = 0; i < how_many; i++) { - tmp = self->length; - while (self->length && self->string[self->length - 1] != CSTRING_SEP) - self->length--; - while (self->length && self->string[self->length - 1] == CSTRING_SEP) - self->length--; - if (self->length != tmp) - count++; - } - normalize_path(self); - - // Root is root of root - if (first == CSTRING_SEP && !self->length) - cstring_add_car(self, CSTRING_SEP); - - return count; -} - -char *cstring_basename(const char path[], const char ext[]) { - size_t i; - size_t sz = strlen(path); - - i = sz; - while (i && path[i] != CSTRING_SEP) - i--; - - cstring_t *rep; - if (path[i] != CSTRING_SEP) { - rep = cstring_clone(path); - } else { - rep = new_cstring(); - cstring_addf(rep, path, i + 1); - } - - if (ext && ext[0] && cstring_ends_with(rep->string, ext)) { - cstring_cut_at(rep, rep->length - strlen(ext)); - } - - return cstring_convert(rep); -} - -char *cstring_dirname(const char path[]) { - cstring_t *rep = cstring_clone(path); - cstring_pop_path(rep, 1); - return cstring_convert(rep); -} - -int cstring_is_utf8(cstring_t *self) { - size_t rep = mbstowcs(NULL, self->string, 0); - // -2 = invalid, -1 = not whole - return (rep != (size_t) -2) && (rep != (size_t) -1); -} - -char *cstring_concat(const char str1[], ...) { - if (!str1) - return NULL; - - va_list args; - size_t total; - size_t prec; - char *arg; - char *ptr; - char *rep; - - total = strlen(str1); - va_start(args, str1); - while ((arg = va_arg(args, char *))) { - total += strlen(arg); - } - va_end(args); - - rep = malloc(total * sizeof(char) + 1); - ptr = rep; - ptr = strcpy(ptr, str1); - prec = strlen(str1); - - va_start(args, str1); - while ((arg = va_arg(args, char *))) { - ptr = strcpy(ptr + prec, arg); - prec = strlen(arg); - } - va_end(args); - - return rep; -} diff --git a/src/utils/cstring.h b/src/utils/cstring.h deleted file mode 100644 index 98679dc..0000000 --- a/src/utils/cstring.h +++ /dev/null @@ -1,507 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2013 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * @file cstring.h - * @author Niki - * @date 2013 - 2022 - * - * @brief Some string utility functions - * - * This file implements some basic functions of a string, most often by working - * directly with char * (but when needed with the provided - * cstring object). - */ - -#ifndef CSTRING_H -#define CSTRING_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** - * @brief A NUL-byte terminated string, with a known length - * - * The structure contains a suite of characters terminated by a NUL byte - * (or just a NUL byte), and a length. - * It is advised NOT to modify either of those directly. - * You can use cstring_convert to get a char *, though - * (in this case, the cstring MUST NOT be used again, and you are - * responsible for freeing said char *). - * - * @see cstring_convert - */ -typedef struct { - char CNAME[10]; - char *string; - size_t length; - void *priv; -} cstring_t; - -/** - * Instantiate a new cstring. - * - * @note always identical to malloc + init_cstring - * - * Create (and allocate the memory for) a new cstring. - * Do not forget to call cstring_free(cstring) when done. - * - * @see malloc() - * @see init_cstring(cstring_t *self) - */ -cstring_t *new_cstring(); - -/** - * Instantiate a new cstring. - * - * Create (and allocate the memory for) a new cstring. - * Do not forget to call uninit_cstring(cstring_t *self) when done. - * - * @see new_cstring() - * @see uninit_cstring(cstring_t *self) - */ -int init_cstring(cstring_t *self); - -/** - * Free the given cstring. - * - * Free all the resources allocated for this cstring. - * - * @note always equivalent to uninit_cstring + free - * - * @see uninit_cstring(cstring_t *self) - * @see free(void *data) - */ -void free_cstring(cstring_t *self); - -/** - * Free the given cstring. - * - * Free all the resources allocated for this cstring. - * - * @param self the cstring to free, which MUST NOT be used again afterward - */ -void uninit_cstring(cstring_t *self); - -/** - * Grow the cstring to accommodate that many characters in addition to those - * already held, if needed. - * - * @param self the string to grow - * @param min the minimum number of extra characters it should be able to hold - * - * @return TRUE if success (FALSE means it was unable to grow due to memory - * pressure) - */ -int cstring_grow(cstring_t *self, int min_extra); - -/** - * Grow the cstring to accommodate that many characters in total, if needed. - * - * @param self the string to grow - * @param min the minimum number of characters it should be able to hold - * - * @return TRUE if success (FALSE means it was unable to grow due to memory - * pressure) - */ -int cstring_grow_to(cstring_t *self, int min_buffer); - -/** - * Compact the memory used by this string. - * - * @param self the string to work on - */ -void cstring_compact(cstring_t *self); - -/** - * Add a char at the end of the given cstring. - * - * @param self the cstring to work on - * @param source the character to add - * - * @return TRUE if success (FALSE means it was unable to grow due to memory - * pressure) - */ -int cstring_add_car(cstring_t *self, char source); - -/** - * Add a string (a sequence of char that MUST end with '\0') at the end of the - * given cstring. - * - * @param self the string to work on - * @param source the string to add - * - * @return TRUE if success (FALSE means it was unable to grow due to memory - * pressure) - */ -int cstring_add(cstring_t *self, const char source[]); - -/** - * Add a string (a sequence of char that MUST end with '\0') at the end of the - * given cstring, starting from index. - * - * @param self the cstring to work on - * @param source the string to add - * @param idx the starting index at which to copy from the source - * - * @return TRUE if success (FALSE means it was unable to grow due to memory - * pressure) - */ -int cstring_addf(cstring_t *self, const char source[], size_t idx); - -/** - * Add a string (a sequence of char that MAY end with '\0') at the end of the - * given string, up to N chars long. - * - * @param self the string to work on - * @param source the string to add - * @param n the maximum number of chars to add (excluding the NUL byte), or 0 - * to add the whole source (which MUST then end with a '\0') - * - * @return TRUE if success (FALSE means it was unable to grow due to memory - * pressure) - */ -int cstring_addn(cstring_t *self, const char source[], size_t n); - -/** - * Add a string (a sequence of char that MAY end with '\0') at the end of the - * given cstring, starting from index, up to N chars long. - * - * @param self the string to work on - * @param source the string to add - * @param idx the starting index at which to copy from the source - * @param n the maximum number of chars to add (excluding the NUL byte) or 0 - * to add the whole source (which MUST then end with a '\0') - * - * @return TRUE if success (FALSE means it was unable to grow due to memory - * pressure) - */ -int cstring_addfn(cstring_t *self, const char source[], size_t idx, size_t n); - -/** - * Add a string via the usual printf formatters. - * - * @param self the string to add to - * @param fmt the required format specifiers (@{see printf}) - * @param ... the printf-format parameters - * - * @return TRUE if success (FALSE means it was unable to grow due to memory - * pressure) - */ -int cstring_addp(cstring_t *self, const char *fmt, ...); - -/** - * Cut the string at the given size if it is greater. - * - * E.g.: it will have (at most) this many characters (without counting NULL) in - * it after. - * - * @param self the string to work on - * @param size the size to cut at (the maximum size of the cstring after this - * operation, NUL excepted) - */ -void cstring_cut_at(cstring_t *self, size_t size); - -/** - * Create a substring of this one. - * - * @param self the string to work on - * @param start the index to start at - * @param length the number of characters to copy, 0 for 'up to the end' - * - * @return a newly allocated cstring - */ -cstring_t *cstring_substring(const char self[], size_t start, size_t length); - -/** - * Split a cstring into "smaller" cstrings every time the given separator is found. - * Will also allow empty fields, ie: "a,b,,c" will return 4 cstrings, the third being empty). - * - * @param self the cstring to work on - * @param delim the separator, which can be longer than one character - * - * @return a list of cstring - */ -//TODO: use a [] -//clist *cstring_split(cstring *self, cstring *delim, cstring *quote); -/** - * Split a cstring into "smaller" cstrings every time the given separator (which MUST end in \0) is found. - * Will also allow empty fields, ie: "a,b,,c" will return 4 cstrings, the third being empty). - * - * @param self the cstring to work on - * @param delim the separator, which can be longer than one character and MUST end with \0 - * - * @return a list of cstring - */ -//TODO: use a [] -//clist *cstring_splits(cstring *self, const char delim[], const char quote[]); -/** - * Split a cstring into "smaller" cstrings every time the given separator is found. - * Will also allow empty fields, ie: "a,b,,c" will return 4 cstrings, the third being empty). - * - * @param self the cstring to work on - * @param delim the separator - * - * @return a list of cstring - */ -//TODO: use a [] -//clist *cstring_splitc(cstring *self, char delim, char quote); -/** - * Reverse the given string. - * - * @param self the string to work on - */ -void cstring_reverse(char *self); - -/** - * Replace all occurrences of a string inside the given cstring by another. - * - * @param self the string to work on - * @param from the string to replace - * @param to the replacement string - * - * @return the number of occurrences changed - */ -int cstring_replace(cstring_t *self, const char from[], const char to[]); - -/** - * Replace all occurrences of a char inside the given string by another. - * - * @param self the string to work on - * @param from the char to replace - * @param to the replacement char - * - * @return the number of occurrences changed - */ -int cstring_replace_car(char *self, char from, char to); - -/** - * Check if the string starts with the given pattern. - * - * @param self the string to work on - * @param find the string to find - * @param start_idx the index at which to start the comparison - * - * @return 1 if it does - */ -int cstring_starts_with(const char self[], const char find[], size_t start_idx); - -/** - * Check if the string ends with the given pattern. - * - * @param self the string to work on - * @param find the string to find (if empty, will always be found) - * @param start_index the index at which to start the comparison - * - * @return 1 if it does - */ -int cstring_ends_with(const char self[], const char find[]); - -/** - * Find the given substring in this one. - * - * @param self the string to work on - * @param find the string to find - * @param start_index the index at which to start the search - * - * @return the start index of the found string if found, or a negative value - * if not - */ -long cstring_find(const char self[], const char find[], size_t rstart_index); - -/** - * Find the given substring in this one, but search in the reverse direction. - * - * @param self the string to work on - * @param find the string to find - * @param rstart_index the index at which to start the search, or 0 for - * "end of string" (remember that it is reverse, you would then never - * find anything with a real rstart_index of 0), or a negative value - * to count from the end of the string (-2 means 2 character before the - * end) - * - * @return the start index of the found string if found, or a negative value - * if not - */ -long cstring_rfind(char self[], const char find[], long rstart_index); - -/** - * Clear (truncate its size to 0) the given string. - * - * @param self the string to work on - */ -void cstring_clear(cstring_t *self); - -/** - * Convert this cstring into a string - * This means that you MUST NOT call cstring_free nor use the cstring anymore. - * NULL will return NULL. - * - * @param self the cstring to work on - */ -char *cstring_convert(cstring_t *self); - -/** - * Clone this string. - * NULL will return NULL. - * - * @param self the string to clone - */ -cstring_t *cstring_clone(const char self[]); - -/** - * Trim this cstring of all trailing 'car' instances. - * - * @param self the cstring to work on - * @param car the character to trim (right only) - * - * @return a right trimmed cstring - */ -void cstring_rtrim(cstring_t *self, char car); - -/** - * Trim this cstring of all 'car' instances from the start and/or the - * end of the string. - * - * @param self the cstring to work on - * @param car the character to trim - * - * @return a trimmed cstring - */ -void cstring_trim(cstring_t *self, char car); - -/** - * Remove the \r and \n sequence (or one OR the other) at the end of the string. - * - * @param self the string to change - * - * @return the new length of the string - */ -size_t cstring_remove_crlf(char *self); - -/** - * Change the case to upper-case (UTF-8 compatible, but the string MUST be - * whole). - * - * @note: if LC_ALL is not set or is set to C and a viable $LANG exists, it will - * set LC_ALL to $LANG - * - * @param self the cstring to work on - */ -void cstring_toupper(cstring_t *self); - -/** - * Change the case to lower-case (UTF-8 compatible, but the string MUST be - * whole). - * - * @note: if LC_ALL is not set or is set to C and a viable $LANG exists, it will - * set LC_ALL to $LANG - * - * @param self the cstring to work on - */ -void cstring_tolower(cstring_t *self); - -/** - * Read a whole line (CR, LN or CR+LN terminated) from the given file stream. - * - * @param self the cstring to read into - * @param file the file to read - * - * @return 1 if a line was read, 0 if not - */ -int cstring_readline(cstring_t *self, FILE *file); - -/** - * Add a path to the given cstring (if it is currently empty, it - * will result in a root path). - * - * Will be separated by a forward '/' except on non-standard systems - * that uses reverse slash (i.e., Windows). - * - * @param self the base cstring (empty for a root path) - * @param subpath the path component to add - */ -void cstring_add_path(cstring_t *self, const char subpath[]); - -/** - * Remove the how_many components of the path described by this - * cstring. Will ignore extra path separators and always trim it from the final - * result (i.e., some//path/ is identical to some/path). - * - * @note popping "0" path will simply make sure the string does not end in "/" - * - * @param how_many how many path components to remove (for instance, to go from - * /some/path/to/file to /some/path you would need 2) - */ -int cstring_pop_path(cstring_t *self, int how_many); - -/** - * Return the basename component of this path (for instance, - * '/home/user/file.ext' becomes 'file.ext'). - * - * @param path the path to get the dir of (it can be a dir itself) - * @param ext the extension to remove if any (can be empty or NULL for none) - * - * @note the extension should include the "." if any - * - * @return a new string representing the parent directory - */ -char *cstring_basename(const char path[], const char ext[]); - -/** - * Return the dirname of this path (for instance, - * '/home/user/file.ext' becomes '/home/user'). - * - * @param path the path to get the dir of (it can be a dir itself) - * - * @return a new string representing the parent directory - */ -char *cstring_dirname(const char path[]); - -/** - * Check if the string is a correct and whole UTF-8 string (i.e., it is indeed - * an UTF-8 string and doesn't contain incomplete UTF-8 sequences). - * - * @return TRUE if it is UTF-8 - */ -int cstring_is_utf8(cstring_t *self); - -/** - * Concat all the given string and return the concatenation as a newly allocated - * string that you now own. - * - * @note the last parameter must be NULL - * - * @note if NULL is passed as first parameter, NULL will be returned - * - * @param str1 the first string - * - * @return the concatenated string or NULL if str1 is NULL - */ -char *cstring_concat(const char str1[], ...); - -#endif - -#ifdef __cplusplus -} -#endif - diff --git a/src/utils/desktop.c b/src/utils/desktop.c deleted file mode 100644 index 7ba34c6..0000000 --- a/src/utils/desktop.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2021 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "utils.h" - -#define EXT "desktop" - -/* Private functions */ -static int desktop_compare(const void *a, const void* b); -static int desktop_test_file(const char filename[]); -/* */ - -desktop_t *new_desktop(const char filename[], int best_size) { - desktop_t *me = malloc(sizeof(desktop_t)); - if (!init_desktop(me, filename, best_size)) { - free(me); - me = NULL; - } - - return me; -} - -int init_desktop(desktop_t *me, const char filename[], int best_size) { - strcpy(me->CNAME, "[Desktop]"); - - me->name = NULL; - me->exec = NULL; - me->icon = NULL; - me->icon_file = NULL; - me->children = NULL; - me->id = 0; - - // Copy name - me->name = strdup(filename); - - // Get extension an remove ".desktop" from name - char *ext = rindex(me->name, '.'); - if (ext) { - size_t idot = (ext - me->name); - ext++; - if (!strcmp(ext, EXT)) - me->name[idot] = '\0'; - } - if (ext) - ext = strdup(ext); - - // If PNG of the same name, use as default icon - me->icon_file = desktop_find_icon(me->name, best_size); - - // Pretify default name (remove dir part) - char *slash = rindex(me->name, '/'); - if (slash && !slash[1]) { - slash[0] = '\0'; - slash = rindex(me->name, '/'); - } - if (slash) { - char *copy = strdup(slash + 1); - free(me->name); - me->name = copy; - } - - // Try with the base name, too - if (!me->icon_file) { - me->icon_file = desktop_find_icon(me->name, best_size); - } - - DIR *dp = opendir(filename); - if (dp) { - // Try to get the default folder icon if no icon yet - if (!me->icon_file) { - me->icon_file = desktop_find_icon("folder", best_size); - } - - me->children = new_array(sizeof(desktop_t), 32); - for (struct dirent *ep = readdir(dp); ep; ep = readdir(dp)) { - if (!strcmp(ep->d_name, ".")) - continue; - if (!strcmp(ep->d_name, "..")) - continue; - - desktop_t *child = array_new(me->children); - char *childname = cstring_concat(filename, "/", ep->d_name, NULL); - if (!init_desktop(child, childname, best_size)) - array_pop(me->children); - free(childname); - } - - array_qsort(me->children, desktop_compare); - - closedir(dp); - free(ext); - return 1; - } - - // Only process ".desktop" files - if (!ext || strcmp(ext, EXT)) { - uninit_desktop(me); - free(ext); - return 0; - } - - FILE *file; - cstring_t *line; - char *startsWith; - - file = fopen(filename, "r"); - if (file) { - line = new_cstring(); - while (cstring_readline(line, file)) { - startsWith = "Name="; - if (cstring_starts_with(line->string, startsWith, 0)) { - free(me->name); - me->name = strdup(line->string + strlen(startsWith)); - } - - startsWith = "Exec="; - if (cstring_starts_with(line->string, startsWith, 0)) { - free(me->exec); - me->exec = strdup(line->string + strlen(startsWith)); - // TODO: %f %F %u %U %i %c %k: inject values instead - char *cars = "ifFuUck"; - for (char *ptr = index(me->exec, '%'); ptr; - ptr = index(ptr, '%')) { - if (index(cars, ptr[1])) { - ptr[0] = ' '; - ptr[1] = ' '; - } - ptr++; - } - } - - startsWith = "Icon="; - if (cstring_starts_with(line->string, startsWith, 0)) { - free(me->icon); - me->icon = strdup(line->string + strlen(startsWith)); - } - } - free_cstring(line); - fclose(file); - } - - // Find icon file linked to icon - if (me->icon && !me->icon_file) { - me->icon_file = desktop_find_icon(me->icon, best_size); - } - // ...or any we can find, actually - if (!me->icon_file) { - me->icon_file = desktop_find_icon(me->name, best_size); - } - - free(ext); - return 1; -} - -void free_desktop(desktop_t *me) { - if (me) - uninit_desktop(me); - - free(me); -} - -void uninit_desktop(desktop_t *me) { - free(me->name); - free(me->exec); - free(me->icon); - free(me->icon_file); - me->name = NULL; - me->exec = NULL; - me->icon = NULL; - me->icon_file = NULL; - free_array(me->children); - me->children = NULL; - me->CNAME[0] = '!'; -} - -desktop_t *desktop_find_id(array_t *children, int id) { - desktop_t *found = NULL; - - array_loop(children, child, desktop_t) - { - if (child->id == id) { - found = child; - break; - } - - if (child->children) { - found = desktop_find_id(child->children, id); - break; - } - } - - return found; -} - -/* Private functions */ - -static int desktop_compare(const void *a, const void* b) { - desktop_t *me1 = (desktop_t *)a; - desktop_t *me2 = (desktop_t *)b; - - if (me1->children && !(me2->children)) - return -1; - if (!(me1->children) && me2->children) - return 1; - - return strcmp(me1->name, me2->name); -} - -static int desktop_test_file(const char filename[]) { - FILE *test; - DIR *test_dir; - - test = fopen(filename, "r"); - if (test) { - fclose(test); - test_dir = opendir(filename); - if (test_dir) { - closedir(test_dir); - } else { - return 1; - } - } - - return 0; -} - -#define TRY_DIR(a,b,c) \ - do { \ - tmp = cstring_concat(a, b, c, basename, ".png", NULL); \ - if(desktop_test_file(tmp)) \ - return tmp; \ - free(tmp); \ - } while(0) - -static char *theme = NULL; -static char *ltheme = NULL; -char *desktop_find_icon(const char basename[], int icon_size) { - char *tmp = NULL; - char *home = getenv("HOME"); - char icon_size_str[100]; - sprintf(icon_size_str, "%dx%d", icon_size, icon_size); - - if (!theme) { - tmp = cstring_concat(home, "/.gtkrc-2.0", NULL); - FILE *file = fopen(tmp, "r"); - free(tmp); - if (file) { - const char *startsWith = "gtk-icon-theme-name="; - size_t n = strlen(startsWith); - - cstring_t *line = new_cstring(); - while (cstring_readline(line, file)) { - if (cstring_starts_with(line->string, startsWith, 0)) { - free(theme); - if (line->string[n] == '"') { - theme = strdup(line->string + n + 1); - theme[strlen(theme) - 1] = '\0'; - } else { - theme = strdup(line->string + n); - } - } - } - free_cstring(line); - fclose(file); - - if (!theme || !theme[0]) { - theme = strdup(""); - ltheme = strdup(""); - } else { - tmp = theme; - theme = cstring_concat("/usr/share/icons/", tmp, "/", NULL); - ltheme = cstring_concat(home, "/", ".icons/", tmp, "/", NULL); - free(tmp); - } - - } - } - - // Allow NULL - if (!basename || !basename[0]) - return NULL; - - // exact match - tmp = strdup(basename); - if (desktop_test_file(tmp)) - return tmp; - free(tmp); - - // same name, with ".png" - TRY_DIR("", "", ""); - - // local icons - TRY_DIR(home, "/.local/share/icons/", ""); - - // theme icons - if (theme && theme[0]) { - // exact size (apps, places) - TRY_DIR(theme, icon_size_str, "/apps/"); - TRY_DIR(theme, icon_size_str, "/places/"); - - // scalable (apps, places) - TRY_DIR(ltheme, "scalable", "/apps/"); - TRY_DIR(ltheme, "scalable", "/places/"); - } - - // shared icons, exact size (apps, places) - TRY_DIR("/usr/share/icons/hicolors/", icon_size_str, "/apps/"); - TRY_DIR("/usr/share/icons/hicolors/", icon_size_str, "/places/"); - - // shared icons, scalable (apps, places) - TRY_DIR("/usr/share/icons/hicolors/scalable/apps/", "", ""); - TRY_DIR("/usr/share/icons/hicolors/scalable/places/", "", ""); - - return NULL; -} diff --git a/src/utils/desktop.h b/src/utils/desktop.h deleted file mode 100644 index bf39398..0000000 --- a/src/utils/desktop.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2021 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * @file desktop.h - * @author Niki - * @date 2021 - 2022 - * - * @brief Manipulate .desktop files (as described by - * FreeDesktop.org) - * - * This structure helps you manipulate .desktop files (as described by - * FreeDesktop.org). - * - * @note the desktop object can use icons; for the selection of those, an exact - * match will first be tried (same name as the desktop file, with - * a .png extension), then we will look into the local - * .local/share/icons and if we still haven't found an icon, into - * the theme (first by looking for a best_size sized icon and if - * not in scalable) - * - * @note we support the use of desktop objects for menu, too, and that includes - * submenu items support - */ -#ifndef DESKTOP_H -#define DESKTOP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include "array.h" - -/** - * The structure used to represent desktop objects. - */ -struct { - char CNAME[10]; - /** The user name of the desktop object. */ - char *name; - /** The icon name, if any. */ - char *icon; - /** The icon file that corresponds, if any. */ - char *icon_file; - /** The EXEC command to start. */ - char *exec; - /** The submenu items of this desktop object (for a menu/submenu). */ - array_t *children; - /** A custom external ID for this desktop object, for your own use. */ - int id; -}typedef desktop_t; - -/** - * Create a new desktop object from the given .desktop file. - * - * @note always identical to malloc + init_desktop - * - * @param filename the path to the actual .desktop file - * @param best_size the default size for the icon (see icon selection in the - * description of the {@see desktop} object - * - * @see malloc() - * @see init_desktop(desktop_t *self, const char filename[], int best_size) - * @see free_desktop(desktop_t *self) - * - * @return the desktop object - */ -desktop_t *new_desktop(const char filename[], int best_size); - -/** - * Create a new desktop object from the given .desktop file. - * - * @param filename the path to the actual .desktop file - * @param best_size the default size for the icon (see icon selection in the - * description of the {@see desktop} object - * - * @see new_desktop(const char filename[], int best_size) - * @see uninit_desktop(desktop_t *self) - * - * @return TRUE if success (could fail if the target is not a .desktop - * file - */ -int init_desktop(desktop_t *self, const char filename[], int best_size); - -/** - * Free the given desktop object. - * - * @note always equivalent to uninit_desktop + free - * - * @see uninit_desktop(desktop_t *self) - * @see free(void *data) - */ -void free_desktop(desktop_t *self); - -/** - * Free the resources used by the given desktop object -- do not use it anymore - * after this call. - */ -void uninit_desktop(desktop_t *self); - -/** - * Find a submenu item by the given ID ({@see desktop_set_id(desktop *, int)}). - * - * TODO: use full objects instead - * @param children the array of pointers to desktop objects to look through - * @param menu_id the ID of the submenu we want to find - * - * @return the given submenu if found, or NULL - */ -desktop_t *desktop_find_id(array_t *children, int menu_id); - -/** - * Look for the icon file related to this basename. - * - * @param basename the base name of the icon we want to look for - * @param icon_size the best_size to use for the icon (see the description of - * the {@desktop} object) - * - * @return the path to the best related icon we found (you own it), or NULL - */ -char *desktop_find_icon(const char basename[], int icon_size); - -#endif /* DESKTOP_H */ - -#ifdef __cplusplus -} -#endif - diff --git a/src/utils/net.c b/src/utils/net.c deleted file mode 100644 index 83edceb..0000000 --- a/src/utils/net.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2012 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include - -#ifndef WIN32 - #include - #include -#else - #include -#endif - -#include "net.h" - -#define bool int -#define true 1 -#define false 0 - -/** - * Get the sockaddr, IPv4 or IPv6. - * @param sa the socket address is in this structure - * @return the sockaddr_in or sockaddr_in6 inside this socketaddr, - * depending if it is IPv4 or IPv6 - */ -void *get_in_addr(struct sockaddr *sa); - -#ifndef WIN32 -/** - * Reap all zombie processes. - * This function will be called when a child process terminates, and - * will loop on all zombie processes to properly acknowledge them - * so they can die. - * - * @param s - */ -void sigchld_handler(int pid); - -void sigchld_handler(int pid) { - if (pid > 0 || pid < 0) pid = 0; - - // Reap all zombie processes - while (waitpid(-1, NULL, WNOHANG) > 0); -} -#endif - -int net_init(){ -#if defined (WIN32) - WSADATA WSAData; - return !WSAStartup(MAKEWORD(2,2), &WSAData); -#endif - return 1; -} - -void net_cleanup(){ -#if defined (WIN32) - WSACleanup(); -#endif -} - -int net_set_non_blocking(int fd) { - return net_set_blocking(fd, 0); -} - -int net_set_blocking(int fd, int block) { - int flags; - -/* If they have O_NONBLOCK, use the POSIX way to do it */ -#if defined (O_NONBLOCK) - /* O_NONBLOCK is defined but broken on SunOS 4.1.x and AIX 3.2.5. */ - if ((flags = fcntl(fd, F_GETFL, 0)) == -1) { - flags = 0; - } - if (block) { - return fcntl(fd, F_SETFL, flags ^ O_NONBLOCK); - } - else { - return fcntl(fd, F_SETFL, flags | O_NONBLOCK); - } -#else - flags = block?0:1; - return ioctl(fd, FIONBIO, (int)(&flags)); -#endif -} - -int net_connect(const char server[], int port) { - int sockfd; - struct addrinfo hints, *servinfo, *p; - int rv; - char string[10]; - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - // convert the port number to a string - sprintf(string, "%i\0", port); - rv = getaddrinfo(server, string, &hints, &servinfo); - // - - if (rv != 0) { - // DO NOT dirty the stderr - //fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); - return -1; - } - - // loop through all the results and connect to the first we can - for (p = servinfo; p != NULL; p = p->ai_next) { - if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) - == -1) { - //perror("client: socket"); - continue; - } - - if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) { - close(sockfd); - //perror("client: connect"); - continue; - } - - break; - } - - if (p == NULL) { - //fprintf(stderr, "client: failed to connect\n"); - return -1; - } - - freeaddrinfo(servinfo); - - return sockfd; -} - -int net_accept(int ssocketd) { - struct sockaddr_storage their_addr; - socklen_t sin_size; - - sin_size = sizeof(their_addr); - return accept(ssocketd, (struct sockaddr *) &their_addr, &sin_size); -} - -int net_listen(int port, int backlog) { -#ifndef WIN32 - struct sigaction sa; -#endif - int sockfd; - struct addrinfo hints, *servinfo, *p; - char yes = 1; - int rv; - char string[10]; - - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; // use my IP - - // convert the port number to a string - sprintf(string, "%i\0", port); - rv = getaddrinfo(NULL, string, &hints, &servinfo); - // - - if (rv != 0) { - // DO NOT dirty the stderr - //fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); - return -1; - } - - // loop through all the results and bind to the first we can - for (p = servinfo; p != NULL; p = p->ai_next) { - if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { - //perror("server: socket"); - continue; - } - - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { - //perror("setsockopt"); - return -1; - } - - if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { - close(sockfd); - //perror("server: bind"); - continue; - } - - break; - } - - if (p == NULL) { - //fprintf(stderr, "server: failed to bind\n"); - return -1; - } - - // all done with this structure - freeaddrinfo(servinfo); - - if (listen(sockfd, backlog) == -1) { - //perror("listen"); - return -1; - } - -#ifndef WIN32 - sa.sa_handler = sigchld_handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - if (sigaction(SIGCHLD, &sa, NULL) == -1) { - //perror("sigaction"); - return -1; - } -#endif - - return sockfd; -} - -void net_close_socketd(int socketd) { - close(socketd); -} - -#ifndef MSG_NOSIGNAL -#define MSG_NOSIGNAL 0 -#endif -ssize_t net_write(int fd, const void *buf, size_t n) { - // In UNIX: send() with flag set to '0' == write() - // In WIN32: cannot write() to a socket - return send(fd, (char *)buf, n, MSG_NOSIGNAL); -} - -ssize_t net_read(int fd, void *buf, size_t nbytes) { - // In UNIX: recv() with flag set to '0' == send() - // In WIN32: cannot read() from a socket - return recv(fd, (char *)buf, nbytes, 0); -} - -void *get_in_addr(struct sockaddr *sa) { - if (sa->sa_family == AF_INET) { - return &(((struct sockaddr_in*) sa)->sin_addr); - } - else { - return &(((struct sockaddr_in6*) sa)->sin6_addr); - } -} - diff --git a/src/utils/net.h b/src/utils/net.h deleted file mode 100644 index 73140f3..0000000 --- a/src/utils/net.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2012 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * @file net.h - * @author niki - * @date 2011 - 2022 - * - * @brief Send/receive data from the network - * - * Allows you to make connections to/from a server, and to send/receive data - * through those connections. - */ - -#ifndef NET_H -#define NET_H - -#ifdef __cplusplus -extern "C" { -#endif - -// WHY ?? -#ifdef _WIN32 -#ifndef WIN32 -#define WIN32 -#endif -#endif - -#ifdef WIN32 -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x501 -#endif -#include -#include -typedef SSIZE_T ssize_t; -#define close(s) closesocket(s) -#define ioctl(a,b,c) ioctlsocket(a,b,c) -#pragma comment(lib, "wsock32.lib"); -#pragma comment(lib, "ws2_32.lib"); -#else -#include -#include -#include -#include -#include -#include -#endif - -/* for ssize_t */ -#include - -/** - * You must call this function before doing any network related operation, - * because of some legacy WIN32 rule. - * (It is a noop on all other platforms.) - * - * @return FALSE when the Windows host does not support WinSock and thus, - * no network for you (you still need to call net_cleanup) - */ -int net_init(); - -/** - * You must call this function after you are done using network related - * operations within this DLL, because of some legacy WIN32 rule. - * (It is a noop on all other platforms.) - */ -void net_cleanup(); - -/** - * Set the given socket to (non-)blocking I/O mode. - * This function can work with file sockets, too. - * - * @param fd the file descriptor or socket to change - * @param block TRUE to block, FALSE not to block - * - * @return TRUE if success - */ -int net_set_blocking(int fd, int block); - -/** - * Connect to this server on this port, and return a socket descriptor - * to write to or read from it. - * - * @param server the server to connect to - * @param port the port to connect on - * - * @return the server socket or a negative value on error - */ -int net_connect(const char server[], int port); - -/** - * Open a port and returns a (server) socket descriptor from which you can - * accept connections. - * - * @param port the port to connect on - * @param backlog the maximum number of client connections we will queue for - * this socket until you handle them - * - * @return the server socket, or a negative value on error - */ -int net_listen(int port, int backlog); - -/** - * Block (or not) and wait for a client to connect on this socket. - * When this is done, return a socket to this specific client/server - * connection. It can takes the connections from a queue, - * as defined in net_listen. - * - * @param ssocketd the server socket on which to accept a connection - * - * @return the socket, or a negative value on error - */ -int net_accept(int ssocketd); - -/** - * Close a socket (or a server socket). - * - * @param socketd the (server) socket to close - */ -void net_close_socketd(int socketd); - -/** - * Write to this socket, as you would with a file. - * - * @param fd the socket to write to - * @param buf the buffer to read from - * @param n the number of bytes to write - * - * @return the actual number of bytes written or a negative number if error - */ -ssize_t net_write(int fd, const void *buf, size_t n); - -/** - * Read from this socket, as you would with a file. - * - * @param fd the socket to read from - * @param buf the buffer to write to - * @param nbytes the number of bytes to read - * - * @return the actual number of bytes read - */ -ssize_t net_read(int fd, void *buf, size_t nbytes); - -#endif - -#ifdef __cplusplus -extern} -#endif diff --git a/src/utils/print.h b/src/utils/print.h deleted file mode 100644 index f0872a6..0000000 --- a/src/utils/print.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @file print.h - * @author Samantaz Fox - * @date 2019 - * - * @brief File name and line numbers - * - * Small utility header designed to print file name and line number - * along with debug/info messages. - * - * Usage example: - * ERROR("program exited with code %d\n", getErrorCode() ); - * - * Known issues: - * - Must take at least one argument in addition to format string - * - * - * Copyright 2019 (C) Samantaz Fox - * https://github.com/SamantazFox/Micro-projects/raw/master/library/print.h - * - * This file is in the public domain. - * Feel free to copy, modify or redistribute it! -*/ - -#ifndef __PRINT_H__ -#define __PRINT_H__ - - -#ifdef __cplusplus - #include -#else - #include -#endif - - -#define TRACE(_format, ...) \ - do { \ - fprintf(stdout, "[Trace] %s:%d\t" _format, __FILE__, __LINE__, __VA_ARGS__); \ - } while (0) - -#define DEBUG(_format, ...) \ - do { \ - fprintf(stdout, "[Debug] %s:%d\t" _format, __FILE__, __LINE__, __VA_ARGS__); \ - } while (0) - -#define INFO(_format, ...) \ - do { \ - fprintf(stdout, "[Info ] %s:%d\t" _format, __FILE__, __LINE__, __VA_ARGS__); \ - } while (0) - -#define WARN(_format, ...) \ - do { \ - fprintf(stderr, "[Warn ] %s:%d\t" _format, __FILE__, __LINE__, __VA_ARGS__); \ - } while (0) - -#define ERROR(_format, ...) \ - do { \ - fprintf(stderr, "[Error] %s:%d\t" _format, __FILE__, __LINE__, __VA_ARGS__); \ - } while (0) - - -#endif /* !__PRINT_H__ */ diff --git a/src/utils/timing.h b/src/utils/timing.h deleted file mode 100644 index 1dd0cae..0000000 --- a/src/utils/timing.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2020 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * @file timing.h - * @author Niki - * @date 2020 - 2022 - * - * @brief Timing macros START and STOP - * - * 2 macro are provided to print the elapsed time between the 2 to stdout. - */ - -#ifndef TIMING_H -#define TIMING_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** - * Start the timer. - */ -#define START struct timeval TIMING_start, TIMING_stop; \ - /* 1 usec = 0.000001 s */ \ - char cusec[7]; \ - gettimeofday(&TIMING_start, NULL); - -/** - * Stop the timer and print the elapsed time to stdout. - */ -#define STOP gettimeofday(&TIMING_stop, NULL); \ - TIMING_stop.tv_sec = TIMING_stop.tv_sec - TIMING_start.tv_sec; \ - TIMING_stop.tv_usec = TIMING_stop.tv_usec - TIMING_start.tv_usec; \ - sprintf(cusec, "%0.6d", TIMING_stop.tv_usec); \ - printf("TIME: %d.%s sec\n", TIMING_stop.tv_sec, cusec); \ - gettimeofday(&TIMING_start, NULL); - -#endif // TIMING_H - -#ifdef __cplusplus -} -#endif - diff --git a/src/utils/utils.c b/src/utils/utils.c deleted file mode 100644 index f9586f9..0000000 --- a/src/utils/utils.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2020 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include "utils.h" -#include "cstring.h" - -#ifndef strnlen -size_t strnlen(const char *s, size_t maxlen) { - size_t i; - for (i = 0; s[i]; i++) { - if (i >= maxlen) - return maxlen; - } - - return i; -} -#endif - -#ifndef strdup -char *strdup(const char *source) { - size_t sz = strlen(source); - char *new = malloc((sz + 1) * sizeof(char)); - strcpy(new, source); - return new; -} -#endif diff --git a/src/utils/utils.h b/src/utils/utils.h deleted file mode 100644 index ef6a9f5..0000000 --- a/src/utils/utils.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * CUtils: some small C utilities - * - * Copyright (C) 2020 Niki Roo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * @file utils.h - * @author Niki - * @date 2020 - 2022 - * - * @brief Include all the other .h as well as C99-compatible - * strdup/strnlen functions if they are not already defined - */ -#ifndef UTILS_H -#define UTILS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "cstring.h" -#include "array.h" -#include "desktop.h" -#include "print.h" -#include "timing.h" - -/* Helps with C99 compatibility for code that is not */ - -#if _POSIX_C_SOURCE < 200809L && _XOPEN_SOURCE < 500 -#ifndef _GNU_SOURCE -/** - * The strnlen() function returns the number of bytes in the string pointed to - * by s, excluding the terminating null byte ('\0'), but at most maxlen. - * In doing this, strnlen() looks only at the first maxlen characters in the - * string pointed to by s and never beyond s[maxlen-1]. - * - * @return The strnlen() function returns strlen(s), if that is less than - * maxlen, or maxlen if there is no null terminating ('\0') among the first - * maxlen characters pointed to by s - */ -size_t strnlen(const char *s, size_t maxlen); -#endif -#endif -#if _POSIX_C_SOURCE < 200809L && _XOPEN_SOURCE < 500 -/** - * The strdup() function returns a pointer to a new string which is a - * duplicate of the string s. Memory for the new string is obtained with - * malloc(3), and can be freed with free(3). - * - * - * @return On success, the strdup() function returns a pointer to the duplicated - * string. It returns NULL if insufficient memory was available, with - * errno set to indicate the error. - */ -char *strdup(const char *source); -#endif - -/* */ - -#endif // UTILS_H - -#ifdef __cplusplus -} -#endif -