diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-14 22:45:08 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-14 22:45:08 +0200 |
commit | f584bc5e4dc7da4ac20306f5072a2b2b01147c4b (patch) | |
tree | 83bdf4157747e425ae80c17601be72f421d7756c /src | |
parent | f343f6f13f470915f971f3ca9361ff267960ca6a (diff) | |
download | bdl-f584bc5e4dc7da4ac20306f5072a2b2b01147c4b.tar.gz bdl-f584bc5e4dc7da4ac20306f5072a2b2b01147c4b.zip |
Add a custom logging dsl
Diffstat (limited to 'src')
-rw-r--r-- | src/badlib.h | 237 | ||||
-rw-r--r-- | src/main.c | 58 |
2 files changed, 268 insertions, 27 deletions
diff --git a/src/badlib.h b/src/badlib.h index 8ce4634..bc3312f 100644 --- a/src/badlib.h +++ b/src/badlib.h | |||
@@ -11,6 +11,9 @@ | |||
11 | // - Sort arrays / linked lists with custom functions? | 11 | // - Sort arrays / linked lists with custom functions? |
12 | // - Implement binary search for searching into an array: | 12 | // - Implement binary search for searching into an array: |
13 | // SearchResult find_array(Array haystack, Array needle). | 13 | // SearchResult find_array(Array haystack, Array needle). |
14 | // - Move logger functions to str_from_int, str_from_float etc. | ||
15 | // - Logger functions for hash map, arrays and growable arrays (print the entire | ||
16 | // thing or at least a small range). | ||
14 | // | 17 | // |
15 | 18 | ||
16 | #include <stdbool.h> | 19 | #include <stdbool.h> |
@@ -453,6 +456,59 @@ str_insert(Str orig, Str value, sz position, Arena *a) { | |||
453 | // }; | 456 | // }; |
454 | // } | 457 | // } |
455 | 458 | ||
459 | char | ||
460 | str_next(Str *s) { | ||
461 | assert(s->mem); | ||
462 | if (s->size == 0) { | ||
463 | return EOF; | ||
464 | } | ||
465 | char c = *s->mem++; | ||
466 | s->size--; | ||
467 | return c; | ||
468 | } | ||
469 | |||
470 | char | ||
471 | str_peek(Str s) { | ||
472 | assert(s.mem); | ||
473 | return *s.mem; | ||
474 | } | ||
475 | |||
476 | sz | ||
477 | str_to_int(Str s) { | ||
478 | sz num = 0; | ||
479 | if (str_has_prefix(s, cstr("0b"))) { | ||
480 | // Binary number. | ||
481 | s = str_remove_prefix(s, cstr("0b")); | ||
482 | while (s.size) { | ||
483 | char c = str_next(&s); | ||
484 | assert(c == '0' || c == '1'); | ||
485 | num = num * 2 + (c - '0'); | ||
486 | } | ||
487 | } else if (str_has_prefix(s, cstr("0x"))) { | ||
488 | // Hex number. | ||
489 | s = str_remove_prefix(s, cstr("0x")); | ||
490 | while (s.size) { | ||
491 | char c = str_next(&s); | ||
492 | assert((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')); | ||
493 | if (c >= '0' && c <= '9') { | ||
494 | num = num * 16 + (c - '0'); | ||
495 | } else if (c >= 'a' && c <= 'f') { | ||
496 | num = num * 16 + (c - 'a' + 10); | ||
497 | } else if (c >= 'A' && c <= 'F') { | ||
498 | num = num * 16 + (c - 'A' + 10); | ||
499 | } | ||
500 | } | ||
501 | } else { | ||
502 | // Decimal number. | ||
503 | while (s.size) { | ||
504 | char c = str_next(&s); | ||
505 | assert(c >= '0' && c <= '9'); | ||
506 | num = num * 10 + (c - '0'); | ||
507 | } | ||
508 | } | ||
509 | return num; | ||
510 | } | ||
511 | |||
456 | // | 512 | // |
457 | // Queue. | 513 | // Queue. |
458 | // | 514 | // |
@@ -901,6 +957,7 @@ void | |||
901 | log_flush(Logger *l) { | 957 | log_flush(Logger *l) { |
902 | if (l->buf.size) { | 958 | if (l->buf.size) { |
903 | fprintf(l->dest, "%.*s", (int)l->buf.size, l->buf.mem); | 959 | fprintf(l->dest, "%.*s", (int)l->buf.size, l->buf.mem); |
960 | l->buf.size = 0; | ||
904 | } | 961 | } |
905 | } | 962 | } |
906 | 963 | ||
@@ -931,6 +988,7 @@ void | |||
931 | log_byte(Logger *l, u8 b) { | 988 | log_byte(Logger *l, u8 b) { |
932 | assert(l); | 989 | assert(l); |
933 | Buf *buf = &l->buf; | 990 | Buf *buf = &l->buf; |
991 | if (buf->size == 0) log_init(l); | ||
934 | sz avail = buf->cap - buf->size; | 992 | sz avail = buf->cap - buf->size; |
935 | if (avail == 0) { | 993 | if (avail == 0) { |
936 | log_flush(l); | 994 | log_flush(l); |
@@ -1051,4 +1109,183 @@ log_float(Logger *l, f64 num, sz precision) { | |||
1051 | log_int(l, fractional); | 1109 | log_int(l, fractional); |
1052 | } | 1110 | } |
1053 | 1111 | ||
1112 | #include <stdarg.h> | ||
1113 | |||
1114 | typedef struct Vec2 { | ||
1115 | sz x, y; | ||
1116 | } Vec2; | ||
1117 | |||
1118 | typedef void(LogFunc)(Logger *l, void *in); | ||
1119 | |||
1120 | void | ||
1121 | log_vec2(Logger *l, void *v) { | ||
1122 | assert(l); | ||
1123 | Vec2 *vec = v; | ||
1124 | log_str(l, cstr("Vec2 { x: ")); | ||
1125 | log_int(l, vec->x); | ||
1126 | log_str(l, cstr(", y: ")); | ||
1127 | log_int(l, vec->y); | ||
1128 | log_str(l, cstr(" }")); | ||
1129 | } | ||
1130 | |||
1131 | void | ||
1132 | log_func_arena(Logger *l, void *in) { | ||
1133 | assert(l); | ||
1134 | Arena *val = in; | ||
1135 | log_str(l, cstr("Arena{ size: ")); | ||
1136 | log_int(l, val->size); | ||
1137 | log_str(l, cstr(" cap: ")); | ||
1138 | log_int(l, val->cap); | ||
1139 | log_str(l, cstr(" mem: ")); | ||
1140 | log_hex(l, (ptrsize)val->beg, 16); | ||
1141 | log_str(l, cstr(" }")); | ||
1142 | } | ||
1143 | |||
1144 | void | ||
1145 | log_func_buf(Logger *l, void *in) { | ||
1146 | assert(l); | ||
1147 | Buf *val = in; | ||
1148 | log_str(l, cstr("Buf{ size: ")); | ||
1149 | log_int(l, val->size); | ||
1150 | log_str(l, cstr(" cap: ")); | ||
1151 | log_int(l, val->cap); | ||
1152 | log_str(l, cstr(" mem: ")); | ||
1153 | log_hex(l, (ptrsize)val->mem, 16); | ||
1154 | log_str(l, cstr(" }")); | ||
1155 | } | ||
1156 | |||
1157 | void | ||
1158 | log_func_array(Logger *l, void *in) { | ||
1159 | assert(l); | ||
1160 | Array *val = in; | ||
1161 | log_str(l, cstr("Buf{ size: ")); | ||
1162 | log_int(l, val->size); | ||
1163 | log_str(l, cstr(" mem: ")); | ||
1164 | log_hex(l, (ptrsize)val->mem, 16); | ||
1165 | log_str(l, cstr(" }")); | ||
1166 | } | ||
1167 | |||
1168 | typedef struct LogFuncMap { | ||
1169 | Str name; | ||
1170 | LogFunc *func; | ||
1171 | } LogFuncMap; | ||
1172 | |||
1173 | LogFuncMap log_funcs[] = { | ||
1174 | {cstr("Arena"), log_func_arena}, | ||
1175 | {cstr("Buf"), log_func_buf}, | ||
1176 | {cstr("Array"), log_func_array}, | ||
1177 | }; | ||
1178 | |||
1179 | void | ||
1180 | log_print(Logger *l, Str format, ...) { | ||
1181 | va_list argp; | ||
1182 | va_start(argp, format); | ||
1183 | va_start(argp, format); | ||
1184 | while (format.size) { | ||
1185 | char c = str_next(&format); | ||
1186 | if (c == '%') { | ||
1187 | c = str_next(&format); | ||
1188 | switch (c) { | ||
1189 | case '%': { | ||
1190 | log_byte(l, '%'); | ||
1191 | } break; | ||
1192 | case 'd': { | ||
1193 | // Integer decimal formatting. | ||
1194 | sz num = va_arg(argp, sz); | ||
1195 | log_int(l, num); | ||
1196 | } break; | ||
1197 | case 'x': { | ||
1198 | // Hex number formatting. | ||
1199 | sz num = va_arg(argp, sz); | ||
1200 | char n = str_peek(format); | ||
1201 | sz zeroes = 0; | ||
1202 | if (n == '{') { | ||
1203 | str_next(&format); | ||
1204 | SearchResult res = array_find_next(format, cstr("}")); | ||
1205 | if (res.found) { | ||
1206 | Str arg = format; | ||
1207 | arg.size = res.pos; | ||
1208 | sz inc = res.pos + res.matched; | ||
1209 | format.mem += inc; | ||
1210 | format.size -= inc; | ||
1211 | zeroes = str_to_int(arg); | ||
1212 | } else { | ||
1213 | break; | ||
1214 | } | ||
1215 | } | ||
1216 | log_hex(l, num, zeroes); | ||
1217 | } break; | ||
1218 | case 'b': { | ||
1219 | // Binary number formatting. | ||
1220 | sz num = va_arg(argp, sz); | ||
1221 | char n = str_peek(format); | ||
1222 | sz zeroes = 0; | ||
1223 | if (n == '{') { | ||
1224 | str_next(&format); | ||
1225 | SearchResult res = array_find_next(format, cstr("}")); | ||
1226 | if (res.found) { | ||
1227 | Str arg = format; | ||
1228 | arg.size = res.pos; | ||
1229 | sz inc = res.pos + res.matched; | ||
1230 | format.mem += inc; | ||
1231 | format.size -= inc; | ||
1232 | zeroes = str_to_int(arg); | ||
1233 | } else { | ||
1234 | break; | ||
1235 | } | ||
1236 | } | ||
1237 | log_bin(l, num, zeroes); | ||
1238 | } break; | ||
1239 | case 'f': { | ||
1240 | // Floating point formatting. | ||
1241 | f64 num = va_arg(argp, f64); | ||
1242 | char n = str_peek(format); | ||
1243 | sz precision = 4; | ||
1244 | if (n == '{') { | ||
1245 | str_next(&format); | ||
1246 | SearchResult res = array_find_next(format, cstr("}")); | ||
1247 | if (res.found) { | ||
1248 | Str arg = format; | ||
1249 | arg.size = res.pos; | ||
1250 | sz inc = res.pos + res.matched; | ||
1251 | format.mem += inc; | ||
1252 | format.size -= inc; | ||
1253 | precision = str_to_int(arg); | ||
1254 | } else { | ||
1255 | break; | ||
1256 | } | ||
1257 | } | ||
1258 | log_float(l, num, precision); | ||
1259 | } break; | ||
1260 | case 's': { | ||
1261 | // String formatting. | ||
1262 | Str val = va_arg(argp, Str); | ||
1263 | log_str(l, val); | ||
1264 | } break; | ||
1265 | case '{': { | ||
1266 | SearchResult res = array_find_next(format, cstr("}")); | ||
1267 | if (res.found) { | ||
1268 | Str arg = format; | ||
1269 | arg.size = res.pos; | ||
1270 | sz inc = res.pos + res.matched; | ||
1271 | format.mem += inc; | ||
1272 | format.size -= inc; | ||
1273 | void *val = va_arg(argp, void *); | ||
1274 | for (sz i = 0; i < LEN(log_funcs); i++) { | ||
1275 | if (str_eq(arg, log_funcs[i].name)) { | ||
1276 | log_funcs[i].func(l, val); | ||
1277 | break; | ||
1278 | } | ||
1279 | } | ||
1280 | } | ||
1281 | } break; | ||
1282 | } | ||
1283 | continue; | ||
1284 | } | ||
1285 | log_byte(l, c); | ||
1286 | } | ||
1287 | log_flush(l); | ||
1288 | va_end(argp); | ||
1289 | } | ||
1290 | |||
1054 | #endif // BADLIB_H | 1291 | #endif // BADLIB_H |
@@ -49,33 +49,37 @@ process_file(Str path) { | |||
49 | .dest = stdout, | 49 | .dest = stdout, |
50 | .storage = &logger_arena, | 50 | .storage = &logger_arena, |
51 | }; | 51 | }; |
52 | log_str(&logger_info, cstr("<<< ")); | 52 | log_print(&logger_info, cstr("<<< %x{4} %b{4} %f{2} %s %{Vec2} %{Vec2} %{Arena} >>>\n"), |
53 | log_int(&logger_info, -1234); | 53 | 123, 3, 1.345, cstr("BOOM!"), &(Vec2){100, 255}, &(Vec2){10, 15}, &logger_arena); |
54 | log_str(&logger_info, cstr(" | ")); | 54 | // log_print(&logger_info, cstr("<<< %x{4} >>>\n"), |
55 | log_hex(&logger_info, (sz)&logger_info, 16); | 55 | // 123); |
56 | log_str(&logger_info, cstr(" | ")); | 56 | // log_str(&logger_info, cstr("<<< ")); |
57 | log_hex(&logger_info, 15, 8); | 57 | // log_int(&logger_info, -1234); |
58 | log_str(&logger_info, cstr(" | ")); | 58 | // log_str(&logger_info, cstr(" | ")); |
59 | log_hex(&logger_info, 16, 8); | 59 | // log_hex(&logger_info, (sz)&logger_info, 16); |
60 | log_str(&logger_info, cstr(" | ")); | 60 | // log_str(&logger_info, cstr(" | ")); |
61 | log_bin(&logger_info, 15, 8); | 61 | // log_hex(&logger_info, 15, 8); |
62 | log_str(&logger_info, cstr(" | ")); | 62 | // log_str(&logger_info, cstr(" | ")); |
63 | log_bin(&logger_info, 16, 8); | 63 | // log_hex(&logger_info, 16, 8); |
64 | log_str(&logger_info, cstr(" | ")); | 64 | // log_str(&logger_info, cstr(" | ")); |
65 | log_float(&logger_info, 3.1234, 0); | 65 | // log_bin(&logger_info, 15, 8); |
66 | log_str(&logger_info, cstr(" | ")); | 66 | // log_str(&logger_info, cstr(" | ")); |
67 | log_float(&logger_info, 3.14, 4); | 67 | // log_bin(&logger_info, 16, 8); |
68 | log_str(&logger_info, cstr(" | ")); | 68 | // log_str(&logger_info, cstr(" | ")); |
69 | log_float(&logger_info, -0.01415, 8); | 69 | // log_float(&logger_info, 3.1234, 0); |
70 | log_str(&logger_info, cstr(" | ")); | 70 | // log_str(&logger_info, cstr(" | ")); |
71 | log_float(&logger_info, (f64)0x7ff0000000000000L, 0); | 71 | // log_float(&logger_info, 3.14, 4); |
72 | log_str(&logger_info, cstr(" | ")); | 72 | // log_str(&logger_info, cstr(" | ")); |
73 | log_float(&logger_info, (f64)0xfff0000000000000L, 0); | 73 | // log_float(&logger_info, -0.01415, 8); |
74 | log_str(&logger_info, cstr(" | ")); | 74 | // log_str(&logger_info, cstr(" | ")); |
75 | log_float(&logger_info, (f64)0x7ff8000000000000L, 0); | 75 | // log_float(&logger_info, (f64)0x7ff0000000000000L, 0); |
76 | log_str(&logger_info, cstr(" >>>")); | 76 | // log_str(&logger_info, cstr(" | ")); |
77 | log_str(&logger_info, cstr("\n")); | 77 | // log_float(&logger_info, (f64)0xfff0000000000000L, 0); |
78 | log_flush(&logger_info); | 78 | // log_str(&logger_info, cstr(" | ")); |
79 | // log_float(&logger_info, (f64)0x7ff8000000000000L, 0); | ||
80 | // log_str(&logger_info, cstr(" >>>")); | ||
81 | // log_str(&logger_info, cstr("\n")); | ||
82 | // log_flush(&logger_info); | ||
79 | 83 | ||
80 | // Logger logger_err = { | 84 | // Logger logger_err = { |
81 | // .dest = stderr, | 85 | // .dest = stderr, |