add tests and cleanup I/O function - ics2txt - convert icalendar .ics file to plain text HTML git clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ics2txt DIR Log DIR Files DIR Refs DIR Tags DIR README --- DIR commit a7b4ceeaf4a57476c0952e0da2def5f92bdfdb9f DIR parent 94bccd0b9ea7049ebeec4fcf2416f6f0b7d221b5 HTML Author: Josuah Demangeon <me@josuah.net> Date: Sun, 28 Jun 2020 10:34:46 +0200 add tests and cleanup I/O function Diffstat: M ics2tsv.c | 7 +++++-- M src/ical.c | 72 +++++++++---------------------- M src/ical.h | 2 +- M src/map.c | 6 ++++++ M src/map.h | 1 + M src/util.c | 5 +++-- A test/map.c | 18 ++++++++++++++++++ A test/random-ics.awk | 40 +++++++++++++++++++++++++++++++ 8 files changed, 94 insertions(+), 57 deletions(-) --- DIR diff --git a/ics2tsv.c b/ics2tsv.c @@ -1,4 +1,5 @@ #include <stdio.h> +#include <stdlib.h> #include "ical.h" #include "log.h" @@ -8,17 +9,19 @@ int print_ical_to_tsv(FILE *fp) { struct ical_contentline contentline; - char *line = NULL; + char *line = NULL, *ln = NULL; size_t sz = 0; ssize_t r; ical_init_contentline(&contentline); - while ((r = ical_read_line(&line, &sz, fp)) > 0) { + while ((r = ical_read_line(&line, &ln, &sz, fp)) > 0) { debug("readling line \"%s\"", line); if (ical_parse_contentline(&contentline, line) < 0) die("parsing line \"%s\"", line); } + free(line); + free(ln); return r; } DIR diff --git a/src/ical.c b/src/ical.c @@ -8,38 +8,28 @@ #include "util.h" int -ical_read_line(char **line, size_t *sz, FILE *fp) +ical_read_line(char **line, char **ln, size_t *sz, FILE *fp) { - ssize_t r; - char *tail = NULL; - size_t tail_sz = 0; - int c, ret = -1; + int c; + void *v; - if ((r = getline(line, sz, fp)) <= 0) - return r; - strchomp(*line); - - for (;;) { - if ((c = fgetc(fp)) == EOF) { - ret = ferror(fp) ? -1 : 0; - goto end; - } - if (c != ' ') - break; - if ((r = getline(&tail, &tail_sz, fp)) <= 0) { - ret = r; - goto end; - } - strchomp(tail); - if (strappend(line, tail) < 0) - goto end; - } + if ((v = realloc(*line, 1)) == NULL) + return -1; + *line = v; + (*line)[0] = '\0'; + + do { + if (getline(ln, sz, fp) <= 0) + return ferror(fp) ? -1 : 0; + strchomp(*ln); + if (strappend(line, *ln) < 0) + return -1; + if ((c = fgetc(fp)) == EOF) + return ferror(fp) ? -1 : 1; + } while (c == ' '); - ret = 1; -end: - free(tail); ungetc(c, fp); - return ret; + return 1; } int @@ -48,48 +38,26 @@ ical_parse_contentline(struct ical_contentline *contentline, char *line) char *column, *equal, *param, *cp; size_t sz; - debug("0"); - if ((column = strchr(line, ':')) == NULL) return -1; *column = '\0'; - - { - size_t len; - - debug("1.1"); - len = strlen(column + 1); - debug("1.2"); - } - - if ((contentline->value = strdup(column + 1)) == NULL) return -1; - debug("2"); - - cp = strchr(line, ';'); - cp = (cp == NULL) ? (NULL) : (cp + 1); - - debug("3"); - + if ((cp = strchr(line, ';')) != NULL) + cp++; while ((param = strsep(&cp, ";")) != NULL) { if ((equal = strchr(param, '=')) == NULL) return -1; *equal = '\0'; - if (map_set(&contentline->param, param, equal + 1) < 0) return -1; } - debug("4"); - sz = sizeof(contentline->name); if (strlcpy(contentline->name, line, sz) >= sz) return errno=EMSGSIZE, -1; - debug("5"); - return 0; } DIR diff --git a/src/ical.h b/src/ical.h @@ -17,7 +17,7 @@ struct ical_contentline { }; /** src/ical.c **/ -int ical_read_line(char **line, size_t *sz, FILE *fp); +int ical_read_line(char **line, char **ln, size_t *sz, FILE *fp); int ical_parse_contentline(struct ical_contentline *contentline, char *line); void ical_init_contentline(struct ical_contentline *contentline); void ical_free_contentline(struct ical_contentline *contentline); DIR diff --git a/src/map.c b/src/map.c @@ -87,6 +87,12 @@ map_del(struct map *map, char *key) } void +map_init(struct map *map) +{ + memset(map, 0, sizeof(*map)); +} + +void map_free_values(struct map *map) { for (size_t i = 0; i < map->len; i++) DIR diff --git a/src/map.h b/src/map.h @@ -17,6 +17,7 @@ struct map { void * map_get(struct map *map, char *key); int map_set(struct map *map, char *key, void *value); int map_del(struct map *map, char *key); +void map_init(struct map *map); void map_free_values(struct map *map); void map_free(struct map *map); DIR diff --git a/src/util.c b/src/util.c @@ -10,7 +10,8 @@ strlcpy(char *buf, char const *str, size_t sz) { size_t len, cpy; - cpy = ((len = strlen(str)) > sz) ? (sz) : (len); + len = strlen(str); + cpy = (len > sz) ? (sz) : (len); memcpy(buf, str, cpy + 1); buf[sz - 1] = '\0'; return len; @@ -54,7 +55,7 @@ strappend(char **base_p, char const *s) size_t base_len, s_len; void *v; - base_len = strlen(*base_p); + base_len = (*base_p == NULL) ? (0) : (strlen(*base_p)); s_len = strlen(s); if ((v = realloc(*base_p, base_len + s_len + 1)) == NULL) DIR diff --git a/test/map.c b/test/map.c @@ -0,0 +1,18 @@ +#include <string.h> +#include <stdio.h> + +#include "map.h" + +int main(int argc, char **argv) { + struct map map; + + memset(&map, 0, sizeof(map)); + + for (argv++; *argv != NULL; argv++) + if (map_set(&map, *argv, "abra") < 0) + return 1; + + fprintf(stdout, "."); + + return 0; +} DIR diff --git a/test/random-ics.awk b/test/random-ics.awk @@ -0,0 +1,40 @@ +#!/usr/bin/awk -f + +function random(n) { + "exec od -An </dev/urandom" | getline num + return num % n +} + +BEGIN { + data = "exec tr -cd -- '-a-zA-Z0-9\n' </dev/urandom" + + first = 1 + while (data | getline) { + if (random(2) && !first) { + print(" " $0) + continue + } + first = 0 + + col = random(26) + 1 + out = substr($0, 1, col) + $0 = substr($0, col + 1) + n = random(30) + for (i = 0; i <= n; i++) { + col = random(30) + 5 + if (length($0) < col) + continue + eq = random(int(col / 2)) + 1 + out = out substr($0, 1, eq) "=" substr($1, eq + 1, col) ";" + $0 = substr($0, col + 1) + } + out = out $0 ":" + data | getline + out = out $0 + if (out ~ "\n" || out !~ ":") + exit(1) + print(out) + } + + close(cmd) +}