diff --git a/mie/builder.c b/mie/builder.c index 245063e..b0b2f6e 100644 --- a/mie/builder.c +++ b/mie/builder.c @@ -66,43 +66,39 @@ void mie_builder_put_record( b_queue_push_back(&builder->b_module->m_records, &rec->r_base.v_entry); } +#if 0 void mie_builder_put_data(struct mie_builder *builder, struct mie_data *data) { if (!builder->b_module) { return; } - b_queue_iterator it = {}; - b_queue_foreach (&it, &builder->b_module->m_data) { - struct mie_value *cur - = b_unbox(struct mie_value, it.entry, v_entry); - - if (!strcmp(cur->v_name.n_str, data->d_base.v_name.n_str)) { - return; - } + const char *data_name = data->d_base.v_name.n_str; + struct mie_data *v = mie_module_get_data(builder->b_module, data_name); + if (v) { + return; } - b_queue_push_back(&builder->b_module->m_data, &data->d_base.v_entry); + mie_module_put_data(builder->b_module, data); } +#endif +#if 0 void mie_builder_put_type(struct mie_builder *builder, struct mie_type *type) { if (!builder->b_module) { return; } - b_queue_iterator it = {}; - b_queue_foreach (&it, &builder->b_module->m_types) { - struct mie_value *cur - = b_unbox(struct mie_value, it.entry, v_entry); - - if (!strcmp(cur->v_name.n_str, type->t_base.v_name.n_str)) { - return; - } + const char *type_name = type->t_base.v_name.n_str; + struct mie_data *v = mie_module_get_data(builder->b_module, type_name); + if (v) { + return; } - b_queue_push_back(&builder->b_module->m_data, &type->t_base.v_entry); + mie_module_put_data(builder->b_module, MIE_VALUE); } +#endif void mie_builder_set_insert_point( struct mie_builder *builder, struct mie_block *block) @@ -127,7 +123,32 @@ struct mie_value *mie_builder_get_data_ptr( return NULL; } - mie_module_put_data(builder->b_module, data); + mie_module_put_data(builder->b_module, data, data_ident); + } + + return MIE_VALUE(data); +} + +struct mie_value *mie_builder_get_string_ptr( + struct mie_builder *builder, const char *s) +{ + if (!builder->b_module) { + return NULL; + } + + struct mie_data *data = mie_module_get_string_ptr(builder->b_module, s); + if (!data) { + struct mie_type *str + = mie_ctx_get_type(builder->b_ctx, MIE_TYPE_STR); + struct mie_value *value = mie_ctx_get_string(builder->b_ctx, s); + + data = mie_data_create_const((struct mie_const *)value); + + if (!data) { + return NULL; + } + + mie_module_put_data(builder->b_module, data, ".str"); } return MIE_VALUE(data); diff --git a/mie/const.c b/mie/const.c index c4a50ab..6edc77a 100644 --- a/mie/const.c +++ b/mie/const.c @@ -2,6 +2,22 @@ #include #include +struct mie_const *mie_const_create(struct mie_type *type) +{ + struct mie_const *c = malloc(sizeof *c); + if (!c) { + return NULL; + } + + memset(c, 0x0, sizeof *c); + + mie_value_init(&c->c_base, MIE_VALUE_CONST); + + c->c_type = type; + + return c; +} + static struct mie_type *get_type(struct mie_value *v) { struct mie_const *c = MIE_CONST(v); diff --git a/mie/convert/text-write.c b/mie/convert/text-write.c index 0bdf08e..b39b40d 100644 --- a/mie/convert/text-write.c +++ b/mie/convert/text-write.c @@ -1,5 +1,6 @@ #include "convert.h" +#include #include #include #include @@ -153,7 +154,7 @@ static b_status write_operand_const( break; case MIE_TYPE_STR: case MIE_TYPE_ATOM: - write_string(converter, c->c_v.v_str); + write_string_f(converter, "\"%s\"", c->c_v.v_str); break; case MIE_TYPE_CLASS: write_string_f(converter, "@%s", value->v_name.n_str); @@ -266,9 +267,10 @@ static b_status write_module( write_char(converter, '\n'); } - b_queue_foreach (&it, &mod->m_data) { - struct mie_value *data - = b_unbox(struct mie_value, it.entry, v_entry); + b_hashmap_iterator it2; + b_hashmap_foreach(&it2, mod->m_data) + { + struct mie_value *data = it2.value->value_data; status = write_value_to_text(converter, data); if (!B_OK(status)) { @@ -276,7 +278,7 @@ static b_status write_module( } } - if (!b_queue_empty(&mod->m_data)) { + if (!b_hashmap_is_empty(mod->m_data)) { write_char(converter, '\n'); } @@ -552,7 +554,8 @@ static b_status write_data( break; case MIE_DATA_CONST: write_operand_const( - converter, data->d_const.c_value, F_INCLUDE_TYPE); + converter, MIE_VALUE(data->d_const.c_value), + F_INCLUDE_TYPE); break; default: write_string(converter, ""); diff --git a/mie/ctx.c b/mie/ctx.c index 621101e..d3c70e3 100644 --- a/mie/ctx.c +++ b/mie/ctx.c @@ -43,6 +43,7 @@ struct mie_ctx *mie_ctx_create(void) out->ctx_false = MIE_CONST(mie_ctx_get_int(out, 0, 1)); out->ctx_sel_cache = b_hashmap_create(free, free); + out->ctx_string_cache = b_hashmap_create(free, free); return out; } @@ -214,3 +215,38 @@ struct mie_value *mie_ctx_get_selector(struct mie_ctx *ctx, const char *sel) return MIE_VALUE(sel_value); } + +struct mie_value *mie_ctx_get_string(struct mie_ctx *ctx, const char *s) +{ + b_hashmap_key key = { + .key_data = s, + .key_size = strlen(s), + }; + + const b_hashmap_value *cache_entry + = b_hashmap_get(ctx->ctx_string_cache, &key); + + if (cache_entry) { + return cache_entry->value_data; + } + + struct mie_const *string_value = malloc(sizeof *string_value); + if (!string_value) { + return NULL; + } + + mie_value_init(&string_value->c_base, MIE_VALUE_CONST); + string_value->c_type = mie_ctx_get_type(ctx, MIE_TYPE_STR); + string_value->c_v.v_str = b_strdup(s); + + key.key_data = string_value->c_v.v_str; + + b_hashmap_value hashmap_value = { + .value_data = string_value, + .value_size = sizeof *string_value, + }; + + b_hashmap_put(ctx->ctx_string_cache, &key, &hashmap_value); + + return MIE_VALUE(string_value); +} diff --git a/mie/data.c b/mie/data.c index 3d9d31a..be62f9d 100644 --- a/mie/data.c +++ b/mie/data.c @@ -33,6 +33,23 @@ struct mie_data *mie_data_create_extern_global( return data; } +struct mie_data *mie_data_create_const(struct mie_const *value) +{ + struct mie_data *data = malloc(sizeof *data); + if (!data) { + return NULL; + } + + memset(data, 0x0, sizeof *data); + + mie_value_init(&data->d_base, MIE_VALUE_DATA); + + data->d_type = MIE_DATA_CONST; + data->d_const.c_value = value; + + return data; +} + static struct mie_type *get_type(struct mie_value *v) { if (!ptr_type.t_id) { diff --git a/mie/include/mie/builder.h b/mie/include/mie/builder.h index a1ca8b7..7c91bd1 100644 --- a/mie/include/mie/builder.h +++ b/mie/include/mie/builder.h @@ -27,18 +27,6 @@ enum mie_builder_flags { MIE_BUILDER_IGNORE_RESULT = 0x01u, }; -extern struct mie_ctx *mie_ctx_create(void); -extern void mie_ctx_destroy(struct mie_ctx *ctx); - -extern struct mie_type *mie_ctx_get_type( - struct mie_ctx *ctx, enum mie_type_id type_id); -extern struct mie_type *mie_ctx_get_int_type( - struct mie_ctx *ctx, unsigned int nr_bits); -extern struct mie_value *mie_ctx_get_bool(struct mie_ctx *ctx, bool val); -extern struct mie_value *mie_ctx_get_int( - struct mie_ctx *ctx, long long val, unsigned int nr_bits); -extern struct mie_value *mie_ctx_get_selector(struct mie_ctx *ctx, const char *sel); - extern struct mie_builder *mie_builder_create( struct mie_ctx *ctx, struct mie_module *mod); extern void mie_builder_destroy(struct mie_builder *builder); @@ -59,6 +47,8 @@ extern void mie_builder_set_insert_point( extern struct mie_value *mie_builder_get_data_ptr( struct mie_builder *builder, const char *data_ident); +extern struct mie_value *mie_builder_get_string_ptr( + struct mie_builder *builder, const char *s); extern struct mie_value *mie_builder_ret( struct mie_builder *builder, struct mie_value *val); diff --git a/mie/include/mie/const.h b/mie/include/mie/const.h index 581001d..58e0e53 100644 --- a/mie/include/mie/const.h +++ b/mie/include/mie/const.h @@ -18,4 +18,6 @@ struct mie_const { } c_v; }; +extern struct mie_const *mie_const_create(struct mie_type *type); + #endif diff --git a/mie/include/mie/ctx.h b/mie/include/mie/ctx.h index 616fd8b..3ed83e2 100644 --- a/mie/include/mie/ctx.h +++ b/mie/include/mie/ctx.h @@ -9,6 +9,7 @@ struct mie_ctx { struct mie_type *ctx_types[__MIE_TYPE_COUNT]; b_btree ctx_int_cache; struct b_hashmap *ctx_sel_cache; + struct b_hashmap *ctx_string_cache; }; extern struct mie_ctx *mie_ctx_create(void); @@ -21,6 +22,7 @@ extern struct mie_type *mie_ctx_get_int_type( extern struct mie_value *mie_ctx_get_bool(struct mie_ctx *ctx, bool val); extern struct mie_value *mie_ctx_get_int( struct mie_ctx *ctx, long long val, unsigned int nr_bits); +extern struct mie_value *mie_ctx_get_string(struct mie_ctx *ctx, const char *s); extern struct mie_value *mie_ctx_get_selector(struct mie_ctx *ctx, const char *sel); #endif diff --git a/mie/include/mie/data.h b/mie/include/mie/data.h index d4cd0b0..7d9688b 100644 --- a/mie/include/mie/data.h +++ b/mie/include/mie/data.h @@ -16,7 +16,7 @@ struct mie_data { enum mie_data_type d_type; union { struct { - struct mie_value *c_value; + struct mie_const *c_value; } d_const; struct { @@ -27,5 +27,6 @@ struct mie_data { extern struct mie_data *mie_data_create_extern_global( struct mie_type *type, const char *ident); +extern struct mie_data *mie_data_create_const(struct mie_const *value); #endif diff --git a/mie/include/mie/module.h b/mie/include/mie/module.h index 50fd6b2..7740faa 100644 --- a/mie/include/mie/module.h +++ b/mie/include/mie/module.h @@ -4,23 +4,33 @@ #define MIE_MODULE(p) ((struct mie_module *)(p)) #include +#include #include struct mie_func; +struct b_hashmap; struct mie_module { struct mie_value m_base; + struct mie_name_map *m_names; b_queue m_records; - b_queue m_data; b_queue m_types; b_queue m_func; + + struct b_hashmap *m_data; + struct b_hashmap *m_data_strings; }; extern struct mie_module *mie_module_create(void); extern void mie_module_add_function(struct mie_module *mod, struct mie_func *func); +extern struct mie_data *mie_module_get_string_ptr( + struct mie_module *mod, const char *s); extern struct mie_data *mie_module_get_data( struct mie_module *mod, const char *name); extern enum b_status mie_module_put_data( - struct mie_module *mod, struct mie_data *data); + struct mie_module *mod, struct mie_data *data, const char *name); + +extern struct mie_value *mie_module_generate_value_name( + struct mie_module *mod, struct mie_value *val, const char *hint); #endif diff --git a/mie/module.c b/mie/module.c index 65a4131..8a794eb 100644 --- a/mie/module.c +++ b/mie/module.c @@ -1,6 +1,9 @@ +#include +#include #include #include #include +#include #include #include @@ -15,6 +18,10 @@ struct mie_module *mie_module_create(void) mie_value_init(&out->m_base, MIE_VALUE_MODULE); + out->m_names = mie_name_map_create(); + out->m_data = b_hashmap_create(NULL, NULL); + out->m_data_strings = b_hashmap_create(NULL, NULL); + return out; } @@ -23,27 +30,79 @@ void mie_module_add_function(struct mie_module *mod, struct mie_func *func) b_queue_push_back(&mod->m_func, &func->f_base.v_entry); } -struct mie_data *mie_module_get_data(struct mie_module *mod, const char *name) +struct mie_data *mie_module_get_string_ptr(struct mie_module *mod, const char *s) { - b_queue_iterator it; - b_queue_foreach (&it, &mod->m_data) { - struct mie_data *data = (struct mie_data *)b_unbox( - struct mie_value, it.entry, v_entry); - if (!strcmp(data->d_base.v_name.n_str, name)) { - return data; - } + b_hashmap_key key = { + .key_data = s, + .key_size = strlen(s), + }; + + const b_hashmap_value *entry = b_hashmap_get(mod->m_data_strings, &key); + if (entry) { + return entry->value_data; } return NULL; } -enum b_status mie_module_put_data(struct mie_module *mod, struct mie_data *data) +struct mie_data *mie_module_get_data(struct mie_module *mod, const char *name) { - /* TODO enforce unique names */ - b_queue_push_back(&mod->m_data, &data->d_base.v_entry); + b_hashmap_key key = { + .key_data = name, + .key_size = strlen(name), + }; + + const b_hashmap_value *entry = b_hashmap_get(mod->m_data, &key); + if (entry) { + return entry->value_data; + } + + /* don't search m_data_strings, as it is keyed by the string contents + * rather than the data entry name, and its entries are duplicated in + * m_data anyway */ + + return NULL; +} + +enum b_status mie_module_put_data( + struct mie_module *mod, struct mie_data *data, const char *name) +{ + struct mie_value *v + = mie_module_generate_value_name(mod, MIE_VALUE(data), name); + + b_hashmap_key key = { + .key_data = v->v_name.n_str, + .key_size = strlen(name), + }; + + b_hashmap_value value = { + .value_data = data, + .value_size = sizeof *data, + }; + + b_hashmap_put(mod->m_data, &key, &value); + + if (data->d_type != MIE_DATA_CONST) { + return B_SUCCESS; + } + + struct mie_const *const_data = data->d_const.c_value; + if (const_data->c_type->t_id == MIE_TYPE_STR) { + key.key_data = const_data->c_v.v_str; + key.key_size = strlen(key.key_data); + b_hashmap_put(mod->m_data_strings, &key, &value); + } + return B_SUCCESS; } +struct mie_value *mie_module_generate_value_name( + struct mie_module *mod, struct mie_value *val, const char *hint) +{ + struct mie_name *name = mie_name_map_put(mod->m_names, &val->v_name, hint); + return b_unbox(struct mie_value, name, v_name); +} + static void cleanup(struct mie_value *value) { struct mie_module *module = MIE_MODULE(value); @@ -56,13 +115,6 @@ static void cleanup(struct mie_value *value) mie_value_destroy(v); } - b_queue_iterator_begin(&module->m_data, &it); - while (b_queue_iterator_is_valid(&it)) { - struct mie_value *v = b_unbox(struct mie_value, it.entry, v_entry); - b_queue_iterator_erase(&it); - mie_value_destroy(v); - } - b_queue_iterator_begin(&module->m_types, &it); while (b_queue_iterator_is_valid(&it)) { struct mie_value *v = b_unbox(struct mie_value, it.entry, v_entry); @@ -76,6 +128,9 @@ static void cleanup(struct mie_value *value) b_queue_iterator_erase(&it); mie_value_destroy(v); } + + b_hashmap_release(module->m_data_strings); + b_hashmap_release(module->m_data); } const struct mie_value_type module_value_type = {