From 1456296b43462cce0de55049b653c5225e7feac5 Mon Sep 17 00:00:00 2001 From: Timo Teräs Date: Wed, 2 Jun 2021 22:35:58 +0300 Subject: add adbgen applet to generate databases from it's text dump --- src/adb_walk_istream.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/adb_walk_istream.c (limited to 'src/adb_walk_istream.c') diff --git a/src/adb_walk_istream.c b/src/adb_walk_istream.c new file mode 100644 index 0000000..b85565f --- /dev/null +++ b/src/adb_walk_istream.c @@ -0,0 +1,131 @@ +#include +#include "adb.h" + +//#define DEBUG_PRINT +#ifdef DEBUG_PRINT +#include +#define dbg_printf(args...) fprintf(stderr, args) +#else +#define dbg_printf(args...) +#endif + +int adb_walk_istream(struct adb_walk *d, struct apk_istream *is) +{ + const apk_blob_t token = APK_BLOB_STR("\n"); + const apk_blob_t comment = APK_BLOB_STR(" #"); + const apk_blob_t key_sep = APK_BLOB_STR(": "); + char mblockdata[1024*4]; + apk_blob_t l, comm, mblock = APK_BLOB_BUF(mblockdata); + int r = 0, i, multi_line = 0, nesting = 0, new_item = 0; + uint8_t started[64] = {0}; + + if (IS_ERR_OR_NULL(is)) return PTR_ERR(is); + l = apk_istream_get_delim(is, token); + apk_blob_pull_blob_match(&l, APK_BLOB_STR("#%SCHEMA: ")); + if ((r = d->ops->schema(d, apk_blob_pull_uint(&l, 16))) != 0) goto err; + + started[0] = 1; + while (!APK_BLOB_IS_NULL(l = apk_istream_get_delim(is, token))) { + for (i = 0; l.len >= 2 && l.ptr[0] == ' ' && l.ptr[1] == ' '; i++, l.ptr += 2, l.len -= 2) + if (multi_line && i >= multi_line) break; + + for (; nesting > i; nesting--) { + if (multi_line) { + apk_blob_t data = apk_blob_pushed(APK_BLOB_BUF(mblockdata), mblock); + if (APK_BLOB_IS_NULL(data)) { + r = -E2BIG; + goto err; + } + if (data.len && data.ptr[data.len-1] == '\n') data.len--; + dbg_printf("Multiline-Scalar >%d> "BLOB_FMT"\n", nesting, BLOB_PRINTF(data)); + if ((r = d->ops->scalar(d, data, 1)) != 0) goto err; + mblock = APK_BLOB_BUF(mblockdata); + multi_line = 0; + } + if (started[nesting]) { + dbg_printf("End %d\n", nesting); + if ((r = d->ops->end(d)) != 0) goto err; + } + } + if (l.ptr[0] == '-' && l.ptr[1] == ' ') { + l.ptr += 2, l.len -= 2; + if (!started[nesting]) { + dbg_printf("Array %d\n", nesting); + if ((r = d->ops->start_array(d, 0)) != 0) goto err; + started[nesting] = 1; + } + new_item = 1; + } + dbg_printf(" >%d/%d< >"BLOB_FMT"<\n", nesting, i, BLOB_PRINTF(l)); + + if (multi_line) { + dbg_printf("Scalar-Block:>%d> "BLOB_FMT"\n", nesting, BLOB_PRINTF(l)); + apk_blob_push_blob(&mblock, l); + apk_blob_push_blob(&mblock, APK_BLOB_STR("\n")); + new_item = 0; + continue; + } + + if (l.ptr[0] == '#') { + if ((r = d->ops->comment(d, l)) != 0) goto err; + continue; + } + + // contains ' #' -> comment + if (!apk_blob_split(l, comment, &l, &comm)) + comm.len = 0; + + if (l.len) { + apk_blob_t key = APK_BLOB_NULL, scalar = APK_BLOB_NULL; + int start = 0; + + if (apk_blob_split(l, key_sep, &key, &scalar)) { + // contains ': ' -> key + scalar + } else if (l.ptr[l.len-1] == ':') { + // ends ':' -> key + indented object/array + key = APK_BLOB_PTR_LEN(l.ptr, l.len-1); + start = 1; + } else { + scalar = l; + } + if (key.len) { + if (new_item) { + started[++nesting] = 0; + dbg_printf("Array-Object %d\n", nesting); + } + if (!started[nesting]) { + dbg_printf("Object %d\n", nesting); + if ((r = d->ops->start_object(d)) != 0) goto err; + started[nesting] = 1; + } + dbg_printf("Key >%d> "BLOB_FMT"\n", nesting, BLOB_PRINTF(key)); + if ((r = d->ops->key(d, key)) != 0) goto err; + if (start) started[++nesting] = 0; + } + + if (scalar.len) { + if (scalar.ptr[0] == '|') { + dbg_printf("Scalar-block >%d> "BLOB_FMT"\n", nesting, BLOB_PRINTF(scalar)); + // scalar '|' -> starts string literal block + started[++nesting] = 0; + multi_line = nesting; + } else { + dbg_printf("Scalar >%d> "BLOB_FMT"\n", nesting, BLOB_PRINTF(scalar)); + if ((r = d->ops->scalar(d, scalar, 0)) != 0) goto err; + } + } + new_item = 0; + } + + if (comm.len) { + if ((r = d->ops->comment(d, comm)) != 0) goto err; + } + + //fprintf(stderr, ">%d> "BLOB_FMT"\n", indent, BLOB_PRINTF(l)); + } + d->ops->end(d); + +err: + if (r) apk_istream_error(is, r); + return apk_istream_close(is); +} -- cgit v1.2.3-70-g09d2