diff options
author | Mattias Andrée <maandree@kth.se> | 2023-01-12 21:57:47 +0100 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2023-01-12 21:57:47 +0100 |
commit | 9a6046f51934f8c34a58583b44cd1dc0c0b0b8d6 (patch) | |
tree | 85623d6551c6bbf054fe2ce25e63b65675184990 /libfonts_parse_dir_line.c | |
parent | m doc (diff) | |
download | libfonts-9a6046f51934f8c34a58583b44cd1dc0c0b0b8d6.tar.gz libfonts-9a6046f51934f8c34a58583b44cd1dc0c0b0b8d6.tar.bz2 libfonts-9a6046f51934f8c34a58583b44cd1dc0c0b0b8d6.tar.xz |
m + add libfonts_parse_dir_line
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'libfonts_parse_dir_line.c')
-rw-r--r-- | libfonts_parse_dir_line.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/libfonts_parse_dir_line.c b/libfonts_parse_dir_line.c new file mode 100644 index 0000000..a339ce3 --- /dev/null +++ b/libfonts_parse_dir_line.c @@ -0,0 +1,126 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + + +static int +read_field(char **valuep, int allow_blank, const char *s, const char **endp) +{ + char endc; + size_t esc = 0; + size_t len; + const char *start; + const char *end; + char *v; + + if (*s == '"') { + endc = '"'; + s++; + } else if (allow_blank) { + endc = '\n'; + } else { + endc = ' '; + } + start = s; + + for (;;) { + if (!*s || *s != '\n' || *s == endc) + break; + if (*s == '\\') { + esc += 1; + s++; + if (!*s || *s == '\n') + goto badline; + } + s++; + } + end = s; + len = (size_t)(end - start) - esc; + if (endc == '"' && *s != '"') { + badline: + *endp = s; + return -1; + } + s += *s == '"'; + *endp = s; + + if (valuep) { + v = malloc(len + 1); + if (v) { + errno = ENOMEM; + return -1; + } + while (start != end) { + if (*start == '\\') + start++; + *v++ += *start++; + } + *v = '\0'; + *valuep = v; + } + + return 0; +} + +int +libfonts_parse_dir_line(char **filep, char **namep, const char *line, char **endp) +{ + int ret = 0; + + if (filep) + *filep = NULL; + if (namep) + *namep = NULL; + + if (!line) { + errno = EINVAL; + goto fail; + } + + if (read_field(filep, 0, line, &line)) + goto fail; + + if (*line != ' ') + goto badline; + line++; + + if (read_field(namep, 1, line, &line)) + goto fail; + + if (*line && *line != '\n') + goto badline; + + goto out; + +badline: +fail: + if (filep) { + free(*filep); + *filep = NULL; + } + if (namep) { + free(*namep); + *namep = NULL; + } + ret = -1; + if (line) + while (*line && *line != '\n') + line++; +out: + if (endp) + *endp = *(char **)(void *)&line; + return ret; +} + + +#else + + +int +main(void) +{ + return 0; /* XXX add test */ +} + + +#endif |