add tests and cleanup I/O function - ics2txt - convert icalendar .ics file to p… | |
git clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
--- | |
commit a7b4ceeaf4a57476c0952e0da2def5f92bdfdb9f | |
parent 94bccd0b9ea7049ebeec4fcf2416f6f0b7d221b5 | |
Author: Josuah Demangeon <[email protected]> | |
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(-) | |
--- | |
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; | |
} | |
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 *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; | |
} | |
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); | |
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++) | |
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); | |
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) | |
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; | |
+} | |
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) | |
+} |