summaryrefslogtreecommitdiff
path: root/src/adb_walk_genadb.c
blob: 46700bb70efa4f1db6cb5ccfeadef0ed70090f1c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <errno.h>
#include "adb.h"
#include "apk_print.h"

static int adb_walk_genadb_schema(struct adb_walk *d, uint32_t schema_id)
{
	struct adb_walk_genadb *dt = container_of(d, struct adb_walk_genadb, d);
	const struct adb_db_schema *s;

	dt->db.schema = schema_id;
	for (s = d->schemas; s->magic; s++)
		if (s->magic == schema_id) break;
	if (!s) return -APKE_ADB_SCHEMA;

	adb_wo_init(&dt->objs[0], &dt->vals[0], s->root, &dt->db);
	dt->num_vals += s->root->num_fields;
	if (dt->num_vals >= ARRAY_SIZE(dt->vals)) return -APKE_ADB_LIMIT;
	dt->nest = 0;

	return 0;
}

static int adb_walk_genadb_comment(struct adb_walk *d, apk_blob_t comment)
{
	return 0;
}

static int adb_walk_genadb_start_object(struct adb_walk *d)
{
	struct adb_walk_genadb *dt = container_of(d, struct adb_walk_genadb, d);

	if (!dt->db.schema) return -APKE_ADB_SCHEMA;
	if (dt->nest >= ARRAY_SIZE(dt->objs)) return -APKE_ADB_LIMIT;

	if (dt->curkey[dt->nest] == 0 &&
	    dt->objs[dt->nest].schema->kind == ADB_KIND_OBJECT)
		return -APKE_ADB_SCHEMA;

	dt->nest++;
	adb_wo_init_val(
		&dt->objs[dt->nest], &dt->vals[dt->num_vals],
		&dt->objs[dt->nest-1], dt->curkey[dt->nest-1]);

	if (*adb_ro_kind(&dt->objs[dt->nest-1], dt->curkey[dt->nest-1]) == ADB_KIND_ADB) {
		struct adb_adb_schema *schema = container_of(&dt->objs[dt->nest-1].schema->kind, struct adb_adb_schema, kind);
		if (dt->nestdb >= ARRAY_SIZE(dt->idb)) return -APKE_ADB_LIMIT;
		adb_reset(&dt->idb[dt->nestdb]);
		dt->idb[dt->nestdb].schema = schema->schema_id;
		dt->objs[dt->nest].db = &dt->idb[dt->nestdb];
		dt->nestdb++;
	}

	dt->num_vals += dt->objs[dt->nest].schema->num_fields;
	if (dt->num_vals >= ARRAY_SIZE(dt->vals)) return -APKE_ADB_LIMIT;

	return 0;
}

static int adb_walk_genadb_start_array(struct adb_walk *d, unsigned int num)
{
	return adb_walk_genadb_start_object(d);
}

static int adb_walk_genadb_end(struct adb_walk *d)
{
	struct adb_walk_genadb *dt = container_of(d, struct adb_walk_genadb, d);
	adb_val_t val;

	val = adb_w_obj(&dt->objs[dt->nest]);
	if (ADB_IS_ERROR(val))
		return -ADB_VAL_VALUE(val);

	dt->curkey[dt->nest] = 0;
	dt->num_vals -= dt->objs[dt->nest].schema->num_fields;

	if (dt->nest == 0) {
		dt->stored_object = val;
		return 0;
	}

	dt->nest--;

	if (*adb_ro_kind(&dt->objs[dt->nest], dt->curkey[dt->nest]) == ADB_KIND_ADB) {
		dt->nestdb--;
		adb_w_root(&dt->idb[dt->nestdb], val);
		val = adb_w_adb(&dt->db, &dt->idb[dt->nestdb]);
	}

	if (dt->curkey[dt->nest] == 0) {
		adb_wa_append(&dt->objs[dt->nest], val);
	} else {
		adb_wo_val(&dt->objs[dt->nest], dt->curkey[dt->nest], val);
		dt->curkey[dt->nest] = 0;
	}

	return 0;
}

static int adb_walk_genadb_key(struct adb_walk *d, apk_blob_t key)
{
	struct adb_walk_genadb *dt = container_of(d, struct adb_walk_genadb, d);
	uint8_t kind = dt->objs[dt->nest].schema->kind;

	if (kind != ADB_KIND_OBJECT && kind != ADB_KIND_ADB)
		return -APKE_ADB_SCHEMA;

	dt->curkey[dt->nest] = adb_s_field_by_name_blob(dt->objs[dt->nest].schema, key);
	if (dt->curkey[dt->nest] == 0)
		return -APKE_ADB_SCHEMA;

	return 0;
}

static int adb_walk_genadb_scalar(struct adb_walk *d, apk_blob_t scalar, int multiline)
{
	struct adb_walk_genadb *dt = container_of(d, struct adb_walk_genadb, d);

	if (dt->objs[dt->nest].schema->kind == ADB_KIND_ARRAY) {
		adb_wa_append_fromstring(&dt->objs[dt->nest], scalar);
	} else {
		if (dt->curkey[dt->nest] == 0)
			adb_wo_fromstring(&dt->objs[dt->nest], scalar);
		else
			adb_wo_val_fromstring(&dt->objs[dt->nest], dt->curkey[dt->nest], scalar);
	}
	dt->curkey[dt->nest] = 0;

	return 0;
}

const struct adb_walk_ops adb_walk_genadb_ops = {
	.schema = adb_walk_genadb_schema,
	.comment = adb_walk_genadb_comment,
	.start_array = adb_walk_genadb_start_array,
	.start_object = adb_walk_genadb_start_object,
	.end = adb_walk_genadb_end,
	.key = adb_walk_genadb_key,
	.scalar = adb_walk_genadb_scalar,
};