static int entry_read(void) { signed char t[64]; unsigned char p[32]; int s; int tree; int v; int n; int i; s=tree_read(t,p); if(s<=0)return s; for(tree=0; tree<ntrees; tree++) { if(trees[tree].s==s &&memcmp(trees[tree].t,t,2*s*sizeof(*t))==0 &&memcmp(trees[tree].p,p,s*sizeof(*p))==0) { break; } } if(tree>=ntrees) { if(ctrees<=ntrees) { ctrees=ctrees<<1|1; trees=(ec_tree *)realloc(trees,ctrees*sizeof(*trees)); } ec_tree_init(trees+tree,t,p,s); ntrees++; } if(centries<=nentries) { centries=centries<<1|1; entries=(ec_code_entry *)realloc(entries,centries*sizeof(*entries)); } entries[nentries].tree=tree; if(scanf("%i%i",&v,&n)<2)return 0; entries[nentries].v=(unsigned char)v; entries[nentries].n=(unsigned char)n; for(i=0; n-->0;)i=t[2*i+(v>>n&1)]; entries[nentries].l=-i-1; nentries++; return 1; }
/** * Small procedure to create a basic conjunctive query tree from a tokenised path. * * @param str Incoming path token. * @param data A qelem** in disguise that should be updated. * @return Always zero. */ static int _path_to_query_proc(const char *str, unsigned long data) { DEBUG("str: \"%s\"", str); qelem *newnode=NULL; qelem **qroot=(qelem**)data; int is_tag = get_tag(str); unsigned long path_hash = hash_path(str); int is_file = have_file_by_hash(path_hash); if (is_tag) { tdata dblock; if (tree_read(is_tag, (tblock*)&dblock)) { PMSG(LOG_ERR, "I/O error reading block\n"); qtree_free(qroot, 1); return -EIO; } if (dblock.flags & DATA_FLAGS_NOSUB) { newnode=_qtree_make_is_nosub(str); } else { newnode=_qtree_make_is(str); } } else if (is_file) { newnode=_qtree_make_is_inode(path_hash); } else { DEBUG("Tag \"%s\" does not exist"); qtree_free(qroot, 1); return -ENOENT; } if (*qroot) { *qroot=_qtree_make_and(newnode, *qroot); } else { *qroot=newnode; } return 0; }
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; }