218 lines
4.8 KiB
C
218 lines
4.8 KiB
C
#include <blue/core/bstr.h>
|
|
#include <blue/core/endian.h>
|
|
#include <blue/core/hash.h>
|
|
#include <blue/core/random.h>
|
|
#include <mie/id.h>
|
|
#include <string.h>
|
|
|
|
static inline int id_memcmp(const uint8_t *a, const uint8_t *b)
|
|
{
|
|
return memcmp(a, b, MIE_ID_NR_BYTES);
|
|
}
|
|
|
|
static mie_id *get_id(const b_btree *tree, mie_id *key)
|
|
{
|
|
b_btree_node *cur = tree->b_root;
|
|
while (cur) {
|
|
mie_id *cur_node = b_unbox(mie_id, cur, e_node);
|
|
int cmp = memcmp(
|
|
key->id_bytes, cur_node->id_bytes, sizeof key->id_bytes);
|
|
|
|
if (cmp > 0) {
|
|
cur = b_btree_right(cur);
|
|
} else if (cmp < 0) {
|
|
cur = b_btree_left(cur);
|
|
} else {
|
|
return cur_node;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void put_id(b_btree *tree, mie_id *node)
|
|
{
|
|
if (!tree->b_root) {
|
|
tree->b_root = &node->e_node;
|
|
b_btree_insert_fixup(tree, &node->e_node);
|
|
return;
|
|
}
|
|
|
|
b_btree_node *cur = tree->b_root;
|
|
while (1) {
|
|
mie_id *cur_node = b_unbox(mie_id, cur, e_node);
|
|
b_btree_node *next = NULL;
|
|
int cmp = memcmp(
|
|
node->id_bytes, cur_node->id_bytes, sizeof node->id_bytes);
|
|
|
|
if (cmp > 0) {
|
|
next = b_btree_right(cur);
|
|
|
|
if (!next) {
|
|
b_btree_put_right(cur, &node->e_node);
|
|
break;
|
|
}
|
|
} else if (cmp < 0) {
|
|
next = b_btree_left(cur);
|
|
|
|
if (!next) {
|
|
b_btree_put_left(cur, &node->e_node);
|
|
break;
|
|
}
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
cur = next;
|
|
}
|
|
|
|
b_btree_insert_fixup(tree, &node->e_node);
|
|
}
|
|
|
|
void mie_id_init(
|
|
mie_id *out, uint32_t a, uint16_t b, uint16_t c, uint16_t d, uint64_t e)
|
|
{
|
|
b_i32 x_a = b_i32_htob(a);
|
|
b_i16 x_b = b_i16_htob(b);
|
|
b_i16 x_c = b_i16_htob(c);
|
|
b_i16 x_d = b_i16_htob(d);
|
|
b_i64 x_e = b_i64_htob(e);
|
|
|
|
memcpy(&out->id_bytes[0], x_a.i_bytes, sizeof x_a.i_bytes);
|
|
memcpy(&out->id_bytes[4], x_b.i_bytes, sizeof x_b.i_bytes);
|
|
memcpy(&out->id_bytes[6], x_c.i_bytes, sizeof x_c.i_bytes);
|
|
memcpy(&out->id_bytes[8], x_d.i_bytes, sizeof x_d.i_bytes);
|
|
memcpy(&out->id_bytes[10], &x_e.i_bytes[2], sizeof x_e.i_bytes - 2);
|
|
}
|
|
|
|
void mie_id_init_zero(mie_id *out)
|
|
{
|
|
memset(out, 0x0, sizeof *out);
|
|
}
|
|
|
|
void mie_id_init_random(mie_id *out)
|
|
{
|
|
b_random_ctx *random = b_random_global_ctx();
|
|
b_random_next_bytes(
|
|
random, (unsigned char *)out->id_bytes, sizeof out->id_bytes);
|
|
}
|
|
|
|
void mie_id_init_ns(mie_id *out, const mie_id *ns, const b_rope *name)
|
|
{
|
|
struct mie_id_builder ctx;
|
|
mie_id_builder_begin(&ctx, ns);
|
|
mie_id_builder_add_rope(&ctx, name);
|
|
mie_id_builder_end(&ctx, out);
|
|
}
|
|
|
|
void mie_id_to_string(const mie_id *id, char *out, size_t max)
|
|
{
|
|
b_bstr str;
|
|
b_bstr_begin(&str, out, max);
|
|
for (size_t i = 0; i < sizeof id->id_bytes; i++) {
|
|
if (i == 4 || i == 6 || i == 8 || i == 10) {
|
|
b_bstr_write_char(&str, '-');
|
|
}
|
|
|
|
b_bstr_write_fmt(&str, NULL, "%02x", id->id_bytes[i]);
|
|
}
|
|
}
|
|
|
|
void mie_id_builder_begin(struct mie_id_builder *builder, const mie_id *ns)
|
|
{
|
|
memset(builder, 0x0, sizeof *builder);
|
|
b_hash_ctx_init(&builder->b_hash, B_HASH_SHA1);
|
|
b_hash_ctx_update(&builder->b_hash, ns->id_bytes, sizeof ns->id_bytes);
|
|
}
|
|
|
|
void mie_id_builder_add(struct mie_id_builder *builder, const void *p, size_t len)
|
|
{
|
|
b_hash_ctx_update(&builder->b_hash, p, len);
|
|
}
|
|
|
|
void mie_id_builder_add_rope(struct mie_id_builder *builder, const b_rope *rope)
|
|
{
|
|
b_hash_ctx_update_rope(&builder->b_hash, rope);
|
|
}
|
|
|
|
void mie_id_builder_add_marker(
|
|
struct mie_id_builder *builder, enum mie_id_builder_marker marker)
|
|
{
|
|
unsigned char c = marker;
|
|
b_hash_ctx_update(&builder->b_hash, &c, sizeof c);
|
|
}
|
|
|
|
void mie_id_builder_end(struct mie_id_builder *builder, mie_id *out)
|
|
{
|
|
memset(out, 0x0, sizeof *out);
|
|
b_hash_ctx_finish(&builder->b_hash, out->id_bytes, sizeof out->id_bytes);
|
|
|
|
out->id_bytes[6] &= 0x0F;
|
|
out->id_bytes[6] |= 0x50;
|
|
|
|
out->id_bytes[8] &= 0x3F;
|
|
out->id_bytes[8] |= 0x80;
|
|
}
|
|
|
|
void mie_id_map_init(struct mie_id_map *map, const mie_id *ns)
|
|
{
|
|
memset(map, 0x0, sizeof *map);
|
|
|
|
map->map_ns_id = *ns;
|
|
}
|
|
|
|
const mie_id *mie_id_map_get_ns(const struct mie_id_map *map)
|
|
{
|
|
return &map->map_ns_id;
|
|
}
|
|
|
|
void mie_id_map_put(struct mie_id_map *map, mie_id *id, const b_rope *name)
|
|
{
|
|
mie_id_init_ns(id, &map->map_ns_id, name);
|
|
put_id(&map->map_entries, id);
|
|
}
|
|
|
|
void mie_id_map_put_id(struct mie_id_map *map, mie_id *node)
|
|
{
|
|
put_id(&map->map_entries, node);
|
|
}
|
|
|
|
mie_id *mie_id_map_get(const struct mie_id_map *map, mie_id *id)
|
|
{
|
|
return get_id(&map->map_entries, id);
|
|
}
|
|
|
|
enum mie_status mie_id_map_iterator_begin(
|
|
struct mie_id_map_iterator *it, const struct mie_id_map *map)
|
|
{
|
|
memset(it, 0x0, sizeof *it);
|
|
|
|
it->_n = b_btree_first(&map->map_entries);
|
|
|
|
if (!it->_n) {
|
|
return MIE_ERR_NO_DATA;
|
|
}
|
|
|
|
it->it_id = b_unbox(mie_id, it->_n, e_node);
|
|
|
|
return MIE_SUCCESS;
|
|
}
|
|
|
|
enum mie_status mie_id_map_iterator_move_next(struct mie_id_map_iterator *it)
|
|
{
|
|
if (!it->_n) {
|
|
it->it_id = NULL;
|
|
return MIE_ERR_NO_DATA;
|
|
}
|
|
|
|
it->_n = b_btree_next(it->_n);
|
|
if (!it->_n) {
|
|
it->it_id = NULL;
|
|
return MIE_ERR_NO_DATA;
|
|
}
|
|
|
|
it->it_id = b_unbox(mie_id, it->_n, e_node);
|
|
|
|
return MIE_SUCCESS;
|
|
}
|