summaryrefslogtreecommitdiff
path: root/src/adb_walk_istream.c
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2021-06-02 22:35:58 +0300
committerTimo Teräs <timo.teras@iki.fi>2021-06-02 22:35:58 +0300
commit1456296b43462cce0de55049b653c5225e7feac5 (patch)
tree3099b1f36b0199068e07620a24205c4830f8d567 /src/adb_walk_istream.c
parent209201bc5d400b68d71af0830efe9085c3648665 (diff)
downloadapk-tools-1456296b43462cce0de55049b653c5225e7feac5.tar.gz
apk-tools-1456296b43462cce0de55049b653c5225e7feac5.tar.bz2
apk-tools-1456296b43462cce0de55049b653c5225e7feac5.tar.xz
apk-tools-1456296b43462cce0de55049b653c5225e7feac5.zip
add adbgen applet to generate databases from it's text dump
Diffstat (limited to 'src/adb_walk_istream.c')
-rw-r--r--src/adb_walk_istream.c131
1 files changed, 131 insertions, 0 deletions
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 <errno.h>
+#include "adb.h"
+
+//#define DEBUG_PRINT
+#ifdef DEBUG_PRINT
+#include <stdio.h>
+#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);
+}