184 lines
4.4 KiB
C
184 lines
4.4 KiB
C
|
|
#include <mie/trait/trait-table.h>
|
||
|
|
#include <mie/trait/trait.h>
|
||
|
|
|
||
|
|
#define UNIQUE_TRAIT_NS_ID \
|
||
|
|
MIE_ID(0xd6, 0xb6, 0x72, 0xae, 0xef, 0x65, 0x40, 0x24, 0xaa, 0x6d, \
|
||
|
|
0xef, 0xfc, 0x37, 0xda, 0x5c, 0x88)
|
||
|
|
|
||
|
|
#define GENERIC_TRAIT_NS_ID \
|
||
|
|
MIE_ID(0x1a, 0x60, 0xbe, 0x20, 0xa6, 0xa0, 0x43, 0x3a, 0xb1, 0x2c, \
|
||
|
|
0x33, 0x9a, 0xac, 0x52, 0xa0, 0xca)
|
||
|
|
|
||
|
|
struct unique_trait {
|
||
|
|
mie_id u_id;
|
||
|
|
const struct mie_trait *u_trait;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct generic_trait {
|
||
|
|
/* generic trait ID. */
|
||
|
|
mie_id g_id;
|
||
|
|
/* list of struct unique_trait */
|
||
|
|
b_queue g_traits;
|
||
|
|
};
|
||
|
|
|
||
|
|
static struct unique_trait *unique_trait_create(const struct mie_trait *trait)
|
||
|
|
{
|
||
|
|
struct unique_trait *out = malloc(sizeof *out);
|
||
|
|
if (!out) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(out, 0x0, sizeof *out);
|
||
|
|
out->u_id = trait->tr_id;
|
||
|
|
out->u_trait = trait;
|
||
|
|
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void unique_trait_destroy(struct unique_trait *trait)
|
||
|
|
{
|
||
|
|
free(trait);
|
||
|
|
}
|
||
|
|
|
||
|
|
static struct generic_trait *generic_trait_create(const struct mie_trait *trait)
|
||
|
|
{
|
||
|
|
struct generic_trait *out = malloc(sizeof *out);
|
||
|
|
if (!out) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(out, 0x0, sizeof *out);
|
||
|
|
out->g_id = trait->tr_def->tr_id;
|
||
|
|
|
||
|
|
struct unique_trait *entry = unique_trait_create(trait);
|
||
|
|
if (!entry) {
|
||
|
|
free(out);
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
b_queue_push_back(&out->g_traits, &entry->u_id.e_entry);
|
||
|
|
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void generic_trait_destroy(struct generic_trait *trait)
|
||
|
|
{
|
||
|
|
b_queue_entry *cur = b_queue_first(&trait->g_traits);
|
||
|
|
while (cur) {
|
||
|
|
b_queue_entry *next = b_queue_next(cur);
|
||
|
|
b_queue_delete(&trait->g_traits, cur);
|
||
|
|
struct unique_trait *u
|
||
|
|
= b_unbox(struct unique_trait, cur, u_id.e_entry);
|
||
|
|
unique_trait_destroy(u);
|
||
|
|
cur = next;
|
||
|
|
}
|
||
|
|
|
||
|
|
free(trait);
|
||
|
|
}
|
||
|
|
|
||
|
|
void mie_trait_table_init(struct mie_trait_table *out)
|
||
|
|
{
|
||
|
|
memset(out, 0x0, sizeof *out);
|
||
|
|
|
||
|
|
mie_id unique_ns = UNIQUE_TRAIT_NS_ID;
|
||
|
|
mie_id_map_init(&out->tr_unique, &unique_ns);
|
||
|
|
|
||
|
|
mie_id generic_ns = GENERIC_TRAIT_NS_ID;
|
||
|
|
mie_id_map_init(&out->tr_generic, &generic_ns);
|
||
|
|
}
|
||
|
|
|
||
|
|
void mie_trait_table_cleanup(struct mie_trait_table *table)
|
||
|
|
{
|
||
|
|
/* TODO */
|
||
|
|
}
|
||
|
|
|
||
|
|
const struct mie_trait *mie_trait_table_get_unique(
|
||
|
|
const struct mie_trait_table *table, const char *dialect_name,
|
||
|
|
const char *trait_name)
|
||
|
|
{
|
||
|
|
mie_id id;
|
||
|
|
struct mie_id_builder id_ctx;
|
||
|
|
mie_id_builder_begin(&id_ctx, mie_id_map_get_ns(&table->tr_unique));
|
||
|
|
mie_id_builder_add_cstr(&id_ctx, dialect_name);
|
||
|
|
mie_id_builder_add_char(&id_ctx, '.');
|
||
|
|
mie_id_builder_add_cstr(&id_ctx, trait_name);
|
||
|
|
mie_id_builder_end(&id_ctx, &id);
|
||
|
|
|
||
|
|
const mie_id *result = mie_id_map_get(&table->tr_unique, &id);
|
||
|
|
const struct unique_trait *entry
|
||
|
|
= b_unbox(struct unique_trait, entry, u_id);
|
||
|
|
return entry ? entry->u_trait : NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
static enum mie_status put_unique_trait(
|
||
|
|
struct mie_trait_table *table, const struct mie_trait *trait)
|
||
|
|
{
|
||
|
|
return MIE_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
static enum mie_status put_generic_trait(
|
||
|
|
struct mie_trait_table *table, const struct mie_trait *trait)
|
||
|
|
{
|
||
|
|
return MIE_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
enum mie_status mie_trait_table_put(
|
||
|
|
struct mie_trait_table *table, const struct mie_trait *trait)
|
||
|
|
{
|
||
|
|
if (trait->tr_def->tr_flags & MIE_TRAIT_F_PARAMETISED) {
|
||
|
|
return put_generic_trait(table, trait);
|
||
|
|
}
|
||
|
|
|
||
|
|
return put_unique_trait(table, trait);
|
||
|
|
}
|
||
|
|
|
||
|
|
enum mie_status mie_trait_table_get_generic(
|
||
|
|
const struct mie_trait_table *table, const char *dialect_name,
|
||
|
|
const char *trait_name, struct mie_trait_table_iterator *it)
|
||
|
|
{
|
||
|
|
mie_id id;
|
||
|
|
struct mie_id_builder id_ctx;
|
||
|
|
mie_id_builder_begin(&id_ctx, mie_id_map_get_ns(&table->tr_unique));
|
||
|
|
mie_id_builder_add_cstr(&id_ctx, dialect_name);
|
||
|
|
mie_id_builder_add_char(&id_ctx, '.');
|
||
|
|
mie_id_builder_add_cstr(&id_ctx, trait_name);
|
||
|
|
mie_id_builder_end(&id_ctx, &id);
|
||
|
|
|
||
|
|
const mie_id *result = mie_id_map_get(&table->tr_unique, &id);
|
||
|
|
const struct generic_trait *entry
|
||
|
|
= b_unbox(struct generic_trait, entry, g_id);
|
||
|
|
|
||
|
|
if (!entry || b_queue_empty(&entry->g_traits)) {
|
||
|
|
return MIE_ERR_NO_ENTRY;
|
||
|
|
}
|
||
|
|
|
||
|
|
memset(it, 0x0, sizeof *it);
|
||
|
|
|
||
|
|
it->_e = b_queue_first(&entry->g_traits);
|
||
|
|
struct unique_trait *trait
|
||
|
|
= b_unbox(struct unique_trait, it->_e, u_id.e_entry);
|
||
|
|
|
||
|
|
it->it_trait = trait->u_trait;
|
||
|
|
|
||
|
|
return MIE_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
enum mie_status mie_trait_table_iterator_move_next(
|
||
|
|
struct mie_trait_table_iterator *it)
|
||
|
|
{
|
||
|
|
if (!it->_e) {
|
||
|
|
return MIE_ERR_NO_ENTRY;
|
||
|
|
}
|
||
|
|
|
||
|
|
it->_e = b_queue_next(it->_e);
|
||
|
|
if (!it->_e) {
|
||
|
|
return MIE_ERR_NO_ENTRY;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct unique_trait *trait
|
||
|
|
= b_unbox(struct unique_trait, it->_e, u_id.e_entry);
|
||
|
|
|
||
|
|
it->it_trait = trait->u_trait;
|
||
|
|
return MIE_SUCCESS;
|
||
|
|
}
|