int main(void) { STRMAP(char *) map; plan_tests(3); strmap_init(&map); ok1(strmap_add(&map, "hello", "hello")); ok1(strmap_add(&map, "world", "world")); strmap_iterate(&map, find_string, (const char *)"hello"); ok1(found); strmap_clear(&map); /* This exits depending on whether all tests passed */ return exit_status(); }
static int cfgi_create_object(const char *objtype, struct strmap_t *args, void *ctx) { struct cfgi_t *cih = (struct cfgi_t *) ctx; struct cfgi_type_t *cit = strmap_get(cih->types, objtype); struct cfgi_obj_t *obj = (struct cfgi_obj_t *) calloc(1, sizeof(struct cfgi_obj_t)); const char *register_string = strmap_get(args, "register"); const char *name = strmap_get(args, "name"); obj->args = args; obj->type = cit; cfgi_object_update_use(obj); if (register_string == NULL) { obj->register_object = 1; } else { obj->register_object = (0 != atoi(register_string)); } obj->next = cit->objlist; cit->objlist = obj; if (name != NULL) { strmap_add(&cit->templates, name, obj); } return 1; /* 1 means stealing the args resource */ }
static bool gather_undefines(const char *name, struct cdump_type *t, struct cdump_map *undefs) { if (!type_defined(t)) strmap_add(undefs, name, t); return true; }
int cfgi_register_handler(struct cfgi_t *cih, char *objtype, cfgi_callback_t callback) { struct cfgi_type_t *cit; cfg_parser_register_handler(cih->parser, objtype, cfgi_create_object); cit = cfgi_type_create(cih); cit->callback = callback; strmap_add(&cih->types, objtype, cit); /* FIXME: error handling */ return 0; }
bool rirobj_strmap_add( struct rirobj_strmap *map, const struct RFstring *id, struct rir_object *obj ) { bool ret = strmap_add(map, (struct RFstring*)id, obj); RF_ASSERT( ret || errno != EEXIST, "Tried to add an already existing RIR object to the map" ); return ret; }
bool rirtype_strmap_add( struct rirtype_strmap *map, const struct RFstring *id, struct rir_type *t) { struct RFstring *id_copy = rf_string_copy_out(id); if (!id_copy) { return false; } bool ret = strmap_add(map, id_copy, t); RF_ASSERT( ret || errno != EEXIST, "Tried to add an already existing RIR object to the map" ); if (!ret) { rf_string_destroy(id_copy); } return ret; }
/* May allocate a new type if not already found (steals @name) */ static struct cdump_type *get_type(struct cdump_definitions *defs, enum cdump_type_kind kind, const char *name) { struct cdump_map *m; struct cdump_type *t; switch (kind) { case CDUMP_STRUCT: m = &defs->structs; break; case CDUMP_UNION: m = &defs->unions; break; case CDUMP_ENUM: m = &defs->enums; break; case CDUMP_UNKNOWN: case CDUMP_ARRAY: case CDUMP_POINTER: m = NULL; } /* Do we already have it? */ if (m) { t = strmap_get(m, name); if (t) return t; } t = tal(defs, struct cdump_type); t->kind = kind; t->name = name ? tal_steal(t, name) : NULL; /* These are actually the same, but be thorough */ t->u.members = NULL; t->u.enum_vals = NULL; if (m) strmap_add(m, t->name, t); return t; }
LLVMValueRef get_struct_fn( struct llvm_ctx *ctx, IDL_tree ctyp, bool for_encode) { const char *s_id = IDL_IDENT(IDL_TYPE_STRUCT(ctyp).ident).repo_id; char *lookup_name = talloc_asprintf(ctx, "%c%s", for_encode ? 'e' : 'd', s_id); LLVMValueRef fn = strmap_get(&ctx->struct_decoder_fns, lookup_name); if(fn != NULL) { talloc_free(lookup_name); return fn; } const struct packed_format *fmt = packed_format_of(ctyp); assert(fmt != NULL); /* only sane for packable structs */ int namelen = strlen(s_id); char flatname[namelen + 1]; /* FIXME: make this proper, i.e. use a name mangler that works */ for(int i=0; i < namelen; i++) { flatname[i] = isalnum(s_id[i]) ? s_id[i] : '_'; } flatname[namelen] = '\0'; T types[3], rettyp = LLVMVoidTypeInContext(ctx->ctx); types[0] = LLVMPointerType(llvm_rigid_type(ctx, ctyp), 0); int nparms; if(!for_encode) { /* decoder */ types[1] = ctx->i32t; types[2] = ctx->i32t; nparms = fmt->num_bits < BITS_PER_WORD ? 3 : 2; } else if(fmt->num_bits < BITS_PER_WORD) { /* subword encoder */ rettyp = ctx->wordt; types[1] = ctx->wordt; types[2] = ctx->i32t; nparms = 3; } else { /* non-subword encoder */ types[1] = ctx->i32t; nparms = 2; } T fntype = LLVMFunctionType(rettyp, types, nparms, 0); char *fnname = g_strdup_printf("__muidl_idl_%scode__%s", for_encode ? "en" : "de", flatname); fn = LLVMAddFunction(ctx->module, fnname, fntype); LLVMSetLinkage(fn, LLVMExternalLinkage); V params[nparms]; assert(LLVMCountParams(fn) == nparms); LLVMGetParams(fn, params); LLVMAddAttribute(params[0], LLVMNoAliasAttribute); LLVMAddAttribute(params[0], LLVMNoCaptureAttribute); for(int i=0; i<nparms; i++) { LLVMAddAttribute(params[i], LLVMInRegAttribute); } g_free(fnname); bool ok = strmap_add(&ctx->struct_decoder_fns, lookup_name, fn); assert(ok || errno != EEXIST); return fn; }
const struct packed_format *packed_format_of(IDL_tree stype) { static bool first = true; if(first) { first = false; strmap_init(&packed_cache); } const char *s_id = sdecl_name(stype); struct packed_format *ret = strmap_get(&packed_cache, s_id); if(ret != NULL) return ret; struct member_item *items = expand_member_list( IDL_TYPE_STRUCT(stype).member_list); int num_items = 0; while(items[num_items].type != NULL) num_items++; qsort(items, num_items, sizeof(struct member_item), &item_by_bitsize_cmp); /* packing of small (sub-word) items */ GList *items_by_size[BITS_PER_WORD - 1]; for(int i=0; i < (BITS_PER_WORD - 1); i++) { items_by_size[i] = NULL; } int num_small = 0; for(int i=0; i<num_items; i++) { struct member_item *item = &items[i]; /* TODO: produce N items for arrays where bits_each < BITS_PER_WORD, so * that smaller items can be packed after e.g. an array member that * leaves 11 bits unused in each word. */ int bits = MEMBER_BITS(item); if(bits >= BITS_PER_WORD) break; items_by_size[bits] = g_list_prepend(items_by_size[bits], item); num_small++; } for(int i=0; i < (BITS_PER_WORD - 1); i++) { items_by_size[i] = g_list_reverse(items_by_size[i]); } GPtrArray *packed = g_ptr_array_new(); int num_words = pack_items(packed, items_by_size, num_small, NULL, 0, 64); if(num_words > 63) { warn_once("structure `%s' can't be bit-packed\n", s_id); return NULL; } assert(num_words < 64); for(int i=0; i < (BITS_PER_WORD - 1); i++) { g_list_free(items_by_size[i]); } #if 0 printf("%s: packed %d/%d small items into %d words from `%s'\n", __func__, (int)packed->len, num_small, num_words, s_id); #endif /* packing of word-length, and longer, items */ for(int i=0; i<num_items; i++) { struct member_item *item = &items[i]; int nbits = MEMBER_BITS(item); if(nbits < BITS_PER_WORD) continue; g_ptr_array_add(packed, new_packed_item(num_words, 0, nbits, item)); int words = (nbits + BITS_PER_WORD - 1) / BITS_PER_WORD; #if 0 printf("%s: packing item `%s' of %d words (%d bits) as-is\n", __func__, item->name, words, nbits); #endif num_words += words; } #if 0 printf("%s: packed %d items into %d words from `%s'\n", __func__, items->len, num_words, s_id); for(int i=0; i<packed->len; i++) { const struct packed_item *pi = packed->pdata[i]; printf("... `%s' -> word %d, bit %d\n", pi->name, pi->word, pi->bit); } #endif assert(packed->len == num_items); g_free(items); items = NULL; ret = g_malloc(sizeof(struct packed_format) + sizeof(struct packed_item *) * packed->len); ret->num_words = num_words; ret->num_items = packed->len; memcpy(ret->items, &g_ptr_array_index(packed, 0), packed->len * sizeof(void *)); g_ptr_array_free(packed, TRUE); ret->num_bits = 0; for(int i=0; i<ret->num_items; i++) { ret->num_bits += ret->items[i]->len; } bool ok = strmap_add(&packed_cache, s_id, ret); assert(ok || errno != EEXIST); return ret; }
int main(void) { STRMAP(char *) map; const char str[] = "hello"; const char val[] = "there"; const char none[] = ""; char *dup = strdup(str); char *v; /* This is how many tests you plan to run */ plan_tests(42); strmap_init(&map); ok1(!strmap_get(&map, str)); ok1(errno == ENOENT); ok1(!strmap_get(&map, none)); ok1(errno == ENOENT); ok1(!strmap_del(&map, str, NULL)); ok1(errno == ENOENT); ok1(!strmap_del(&map, none, NULL)); ok1(errno == ENOENT); ok1(strmap_add(&map, str, val)); ok1(strmap_get(&map, str) == val); /* We compare the string, not the pointer. */ ok1(strmap_get(&map, dup) == val); ok1(!strmap_get(&map, none)); ok1(errno == ENOENT); /* Add a duplicate should fail. */ ok1(!strmap_add(&map, dup, val)); ok1(errno == EEXIST); ok1(strmap_get(&map, dup) == val); /* Delete should return original string. */ ok1(strmap_del(&map, dup, &v) == str); ok1(v == val); ok1(!strmap_get(&map, str)); ok1(errno == ENOENT); ok1(!strmap_get(&map, none)); ok1(errno == ENOENT); /* Try insert and delete of empty string. */ ok1(strmap_add(&map, none, none)); ok1(strmap_get(&map, none) == none); ok1(!strmap_get(&map, str)); ok1(errno == ENOENT); /* Delete should return original string. */ ok1(strmap_del(&map, "", &v) == none); ok1(v == none); ok1(!strmap_get(&map, str)); ok1(errno == ENOENT); ok1(!strmap_get(&map, none)); ok1(errno == ENOENT); /* Both at once... */ ok1(strmap_add(&map, none, none)); ok1(strmap_add(&map, str, val)); ok1(strmap_get(&map, str) == val); ok1(strmap_get(&map, none) == none); ok1(strmap_del(&map, "does not exist", NULL) == NULL); ok1(strmap_del(&map, "", NULL) == none); ok1(strmap_get(&map, str) == val); ok1(strmap_del(&map, dup, &v) == str); ok1(v == val); ok1(strmap_empty(&map)); free(dup); /* This exits depending on whether all tests passed */ return exit_status(); }