code / tomo

Lines41.3K C23.7K Markdown9.7K YAML5.0K Tomo2.3K
7 others 763
Python231 Shell230 make212 INI47 Text21 SVG16 Lua6
(62 lines)
1 // This file defines some functions to make it easy to parse simply formatted
2 // strings **correctly** without memory bugs.
3 //
4 // strparse(input_str, format...) - parse a string
5 //
6 // Examples:
7 //
8 // const char *filename; long line_num;
9 // const char *err = NULL;
10 // if ((err=strparse("foo.c:12", &filename, ":", &line_num)))
11 // errx(1, "Failed to parse file:line at: ", err);
12 //
13 // const char *item1, *item2;
14 // if ((err=strparse("one, two", &item1, ",", PARSE_WHITESPACE, &item2)))
15 // errx(1, "Failed to parse items at: ", err);
17 #pragma once
19 #include <stdbool.h>
20 #include <stdint.h>
21 #include <stdio.h>
23 #include "mapmacro.h"
25 typedef struct {
26 char c;
27 } some_char_t;
28 #define PARSE_SOME_OF(chars) ((some_char_t *)chars)
29 #define PARSE_WHITESPACE PARSE_SOME_OF(" \t\r\n\v")
30 typedef enum { PARSE_LITERAL, PARSE_LONG, PARSE_DOUBLE, PARSE_BOOL, PARSE_STRING, PARSE_SOME_OF } parse_type_e;
32 typedef struct {
33 parse_type_e type;
34 void *dest;
35 } parse_element_t;
37 #define _parse_type(dest) \
38 _Generic((dest), \
39 some_char_t *: PARSE_SOME_OF, \
40 const char *: PARSE_LITERAL, \
41 char *: PARSE_LITERAL, \
42 const char **: PARSE_STRING, \
43 char **: PARSE_STRING, \
44 double *: PARSE_DOUBLE, \
45 long *: PARSE_LONG, \
46 bool *: PARSE_BOOL)
48 #define as_void_star(x) ((void *)x)
49 #define strparse(str, ...) \
50 simpleparse(str, sizeof((const void *[]){__VA_ARGS__}) / sizeof(void *), \
51 (parse_type_e[]){MAP_LIST(_parse_type, __VA_ARGS__)}, (void *[]){MAP_LIST(as_void_star, __VA_ARGS__)})
52 #define fparse(file, ...) \
53 ({ \
54 char *_file_contents = NULL; \
55 size_t _capacity; \
56 ssize_t _just_read = getdelim(&_file_contents, &_capacity, '\0', file); \
57 const char *_parse_err = _just_read > 0 ? strparse(_file_contents, __VA_ARGS__) : "No such file"; \
58 if (_file_contents) free(_file_contents); \
59 _parse_err; \
60 })
62 const char *simpleparse(const char *str, int n, parse_type_e types[n], void *destinations[n]);