libgrapheme

Freestanding C library for unicode string handling
git clone https://git.sinitax.com/suckless/libgrapheme
Log | Files | Refs | README | LICENSE | sfeed.txt

commit c0d28c3cad5c9e02dfa93b3ff3e6953ad0f22d75
parent 0e95e5c797b1dc41117e1ea5455f2a7f2932868d
Author: Laslo Hunhold <dev@frign.de>
Date:   Fri, 24 Feb 2023 18:21:02 +0100

Replace all POSIX-features to become fully ISO-C99

As it turned out, the only things that needed replacing were
getline(), strdup() and the timing in the benchmarks. Analogously,
we replace -D_DEFAULT_SOURCE with -D_ISOC99_SOURCE.

This way we further extend the number of platforms where libgrapheme can
be compiled and run on, e.g. MSVC still does not include getline().

Signed-off-by: Laslo Hunhold <dev@frign.de>

Diffstat:
Mbenchmark/util.c | 13++++++-------
Mconfig.mk | 2+-
Mgen/util.c | 59++++++++++++++++++++++++++++++++++++++++++++++++++---------
3 files changed, 57 insertions(+), 17 deletions(-)

diff --git a/benchmark/util.c b/benchmark/util.c @@ -71,10 +71,9 @@ generate_utf8_test_buffer(const struct break_test *test, size_t testlen, } static double -time_diff(struct timespec *a, struct timespec *b) +time_diff(clock_t a, clock_t b) { - return (double)(b->tv_sec - a->tv_sec) + - (double)(b->tv_nsec - a->tv_nsec) * 1E-9; + return (double)(b - a) / CLOCKS_PER_SEC; } void @@ -82,14 +81,14 @@ run_benchmark(void (*func)(const void *), const void *payload, const char *name, const char *comment, const char *unit, double *baseline, size_t num_iterations, size_t units_per_iteration) { - struct timespec start, end; + clock_t start, end; size_t i; double diff; printf("\t%s ", name); fflush(stdout); - clock_gettime(CLOCK_MONOTONIC, &start); + start = clock(); for (i = 0; i < num_iterations; i++) { func(payload); @@ -98,8 +97,8 @@ run_benchmark(void (*func)(const void *), const void *payload, const char *name, fflush(stdout); } } - clock_gettime(CLOCK_MONOTONIC, &end); - diff = time_diff(&start, &end) / (double)num_iterations / + end = clock(); + diff = time_diff(start, end) / (double)num_iterations / (double)units_per_iteration; if (isnan(*baseline)) { diff --git a/config.mk b/config.mk @@ -14,7 +14,7 @@ SONAME = libgrapheme.so.$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH) BINSUFFIX = # flags -CPPFLAGS = -D_DEFAULT_SOURCE +CPPFLAGS = -D_ISOC99_SOURCE CFLAGS = -std=c99 -Os -Wall -Wextra -Wpedantic LDFLAGS = -s diff --git a/gen/util.c b/gen/util.c @@ -146,6 +146,43 @@ range_parse(const char *str, struct range *range) return 0; } +static bool +get_line(char **buf, size_t *bufsize, FILE *fp, size_t *len) +{ + int ret = EOF; + + for (*len = 0;; (*len)++) { + if (*len > 0 && *buf != NULL && (*buf)[*len - 1] == '\n') { + /* + * if the previously read character was a newline, + * we fake an end-of-file so we NUL-terminate and + * are done. + */ + ret = EOF; + } else { + ret = fgetc(fp); + } + + if (*len >= *bufsize) { + /* the buffer needs to be expanded */ + *bufsize += 512; + if ((*buf = realloc(*buf, *bufsize)) == NULL) { + fprintf(stderr, "get_line: Out of memory.\n"); + exit(1); + } + } + + if (ret != EOF) { + (*buf)[*len] = (char)ret; + } else { + (*buf)[*len] = '\0'; + break; + } + } + + return *len == 0 && (feof(fp) || ferror(fp)); +} + void parse_file_with_callback(const char *fname, int (*callback)(const char *, char **, size_t, char *, @@ -154,8 +191,7 @@ parse_file_with_callback(const char *fname, { FILE *fp; char *line = NULL, **field = NULL, *comment; - size_t linebufsize = 0, i, fieldbufsize = 0, j, nfields; - ssize_t len; + size_t linebufsize = 0, i, fieldbufsize = 0, j, nfields, len; /* open file */ if (!(fp = fopen(fname, "r"))) { @@ -164,7 +200,7 @@ parse_file_with_callback(const char *fname, exit(1); } - while ((len = getline(&line, &linebufsize, fp)) >= 0) { + while (!get_line(&line, &linebufsize, fp, &len)) { /* remove trailing newline */ if (len > 0 && line[len - 1] == '\n') { line[len - 1] = '\0'; @@ -654,7 +690,8 @@ break_test_callback(const char *fname, char **field, size_t nfields, { struct break_test *t, **test = ((struct break_test_payload *)payload)->test; - size_t i, *testlen = ((struct break_test_payload *)payload)->testlen; + size_t i, *testlen = ((struct break_test_payload *)payload)->testlen, + commentlen; char *token; (void)fname; @@ -733,11 +770,15 @@ break_test_callback(const char *fname, char **field, size_t nfields, } /* store comment */ - if (comment != NULL && - ((*test)[*testlen - 1].descr = strdup(comment)) == NULL) { - fprintf(stderr, "break_test_callback: strdup: %s.\n", - strerror(errno)); - return 1; + if (comment != NULL) { + commentlen = strlen(comment) + 1; + if (((*test)[*testlen - 1].descr = malloc(commentlen)) == + NULL) { + fprintf(stderr, "break_test_callback: malloc: %s.\n", + strerror(errno)); + return 1; + } + memcpy((*test)[*testlen - 1].descr, comment, commentlen); } return 0;