#include #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.hdr.schema = htole32(schema_id); for (s = d->schemas; s->magic; s++) if (s->magic == schema_id) break; if (!s) return -EAPKDBFORMAT; 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 -E2BIG; 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.hdr.schema) return -EAPKDBFORMAT; if (dt->nest >= ARRAY_SIZE(dt->objs)) return -EAPKDBFORMAT; if (dt->curkey[dt->nest] == 0 && dt->objs[dt->nest].schema->kind == ADB_KIND_OBJECT) return -EAPKDBFORMAT; 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 -E2BIG; adb_reset(&dt->idb[dt->nestdb]); dt->idb[dt->nestdb].hdr.schema = htole32(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 -E2BIG; 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) { adb_w_root(&dt->db, 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 -EAPKDBFORMAT; dt->curkey[dt->nest] = adb_s_field_by_name_blob(dt->objs[dt->nest].schema, key); if (dt->curkey[dt->nest] == 0) return -EAPKDBFORMAT; 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, };