add tests and cleanup I/O function - ics2txt - convert icalendar .ics file to plain text
(HTM) 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
(HTM) 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)
+}