END_TEST START_TEST(test_read_write) { ident_t i1, i2, i3; i1 = ident_new("goobar"); i2 = ident_new("foo"); i3 = ident_new("foo"); fbuf_t *f = fbuf_open("test.ident", FBUF_OUT); fail_if(f == NULL); ident_wr_ctx_t wctx = ident_write_begin(f); ident_write(i1, wctx); ident_write(i2, wctx); ident_write(i3, wctx); ident_write_end(wctx); fbuf_close(f); f = fbuf_open("test.ident", FBUF_IN); fail_if(f == NULL); ident_rd_ctx_t rctx = ident_read_begin(f); ident_t j1, j2, j3; j1 = ident_read(rctx); j2 = ident_read(rctx); j3 = ident_read(rctx); ident_read_end(rctx); fail_unless(i1 == j1); fail_unless(i2 == j2); fail_unless(i3 == j3); fail_unless(j2 == j3); fbuf_close(f); remove("test.ident"); }
type_t type_read(type_rd_ctx_t ctx) { fbuf_t *f = tree_read_file(ctx->tree_ctx); uint16_t marker = read_u16(f); if (marker == UINT16_C(0xffff)) return NULL; // Null marker else if (marker == UINT16_C(0xfffe)) { // Back reference marker unsigned index = read_u32(f); assert(index < ctx->n_types); return ctx->store[index]; } assert(marker < T_LAST_TYPE_KIND); type_t t = type_new((type_kind_t)marker); t->ident = ident_read(ctx->ident_ctx); // Stash pointer for later back references // This must be done early as a child node of this type may // reference upwards if (ctx->n_types == ctx->store_sz) { ctx->store_sz *= 2; ctx->store = xrealloc(ctx->store, ctx->store_sz * sizeof(type_t)); } ctx->store[ctx->n_types++] = t; const uint32_t has = has_map[t->kind]; const int nitems = __builtin_popcount(has); uint32_t mask = 1; for (int n = 0; n < nitems; mask <<= 1) { if (has & mask) { if (ITEM_TYPE_ARRAY & mask) { type_array_t *a = &(t->items[n].type_array); type_array_resize(a, read_u16(f), NULL); for (unsigned i = 0; i < a->count; i++) a->items[i] = type_read(ctx); } else if (ITEM_TYPE & mask) t->items[n].type = type_read(ctx); else if (ITEM_TREE & mask) t->items[n].tree = tree_read(ctx->tree_ctx); else if (ITEM_TREE_ARRAY & mask) { tree_array_t *a = &(t->items[n].tree_array); tree_array_resize(a, read_u16(f), NULL); for (unsigned i = 0; i < a->count; i++) a->items[i] = tree_read(ctx->tree_ctx); } else if (ITEM_RANGE_ARRAY & mask) { range_array_t *a = &(t->items[n].range_array); range_t dummy = { NULL, NULL, 0 }; range_array_resize(a, read_u16(f), dummy); for (unsigned i = 0; i < a->count; i++) { a->items[i].kind = read_u8(f); a->items[i].left = tree_read(ctx->tree_ctx); a->items[i].right = tree_read(ctx->tree_ctx); } } else item_without_type(mask); n++; } } return t; }