#ifndef EXAMPLES_CTREE_MAP_VOLATILE_HPP
#define EXAMPLES_CTREE_MAP_VOLATILE_HPP
#include <cstdint>
#include <ex_common.h>
#include <functional>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
#endif
#define BIT_IS_SET(n, i) (!!((n) & (1ULL << (i))))
namespace examples
{
template <typename K, typename T>
class ctree_map_transient {
public:
typedef K key_type;
typedef T *value_type;
typedef std::function<int(key_type, value_type, void *)> callback;
ctree_map_transient() : root(new entry())
{
}
int
insert(uint64_t key, value_type value)
{
auto dest_entry = root;
while (dest_entry->inode != nullptr) {
auto n = dest_entry->inode;
dest_entry = n->entries[BIT_IS_SET(key, n->diff)];
}
entry e(key, value);
if (dest_entry->key == 0 || dest_entry->key == key) {
delete dest_entry->value;
*dest_entry = e;
} else {
insert_leaf(&e, ctree_map_transient::find_crit_bit(
dest_entry->key, key));
}
return 0;
}
template <typename... Args>
int
insert_new(key_type key, const Args &... args)
{
return insert(key, new T(args...));
}
value_type
remove(key_type key)
{
entry *parent = nullptr;
auto leaf = get_leaf(key, &parent);
if (leaf == nullptr)
return nullptr;
auto ret = leaf->value;
if (parent == nullptr) {
leaf->key = 0;
leaf->value = nullptr;
} else {
auto n = parent->inode;
*parent = *(n->entries[parent->inode->entries[0]->key ==
leaf->key]);
delete n->entries[0];
delete n->entries[1];
delete n;
}
return ret;
}
int
remove_free(key_type key)
{
delete remove(key);
return 0;
}
int
clear()
{
if (root->inode) {
root->inode->clear();
delete root->inode;
root->inode = nullptr;
}
delete root->value;
root->value = nullptr;
root->key = 0;
return 0;
}
value_type
get(key_type key)
{
auto ret = get_leaf(key, nullptr);
return ret ? ret->value : nullptr;
}
int
lookup(key_type key) const
{
return get(key) != nullptr;
}
int foreach (callback clb, void *args)
{
if (is_empty())
return 0;
return foreach_node(root, clb, args);
}
int
is_empty() const
{
return root->value == nullptr && root->inode == nullptr;
}
int
check() const
{
return 0;
}
~ctree_map_transient()
{
clear();
delete root;
}
private:
struct node;
struct entry {
entry() : key(0), inode(nullptr), value(nullptr)
{
}
entry(key_type _key, value_type _value)
: key(_key), inode(nullptr), value(_value)
{
}
key_type key;
node *inode;
value_type value;
void
clear()
{
if (inode) {
inode->clear();
delete inode;
}
delete value;
}
};
struct node {
node() : diff(0)
{
entries[0] = nullptr;
entries[1] = nullptr;
}
int diff;
entry *entries[2];
void
clear()
{
if (entries[0]) {
entries[0]->clear();
delete entries[0];
}
if (entries[1]) {
entries[1]->clear();
delete entries[1];
}
}
};
static int
find_crit_bit(key_type lhs, key_type rhs)
{
return find_last_set_64(lhs ^ rhs);
}
void
insert_leaf(const entry *e, int diff)
{
auto new_node = new node();
new_node->diff = diff;
int d = BIT_IS_SET(e->key, new_node->diff);
new_node->entries[d] = new entry(*e);
auto dest_entry = root;
while (dest_entry->inode != nullptr) {
auto n = dest_entry->inode;
if (n->diff < new_node->diff)
break;
dest_entry = n->entries[BIT_IS_SET(e->key, n->diff)];
}
new_node->entries[!d] = new entry(*dest_entry);
dest_entry->key = 0;
dest_entry->inode = new_node;
dest_entry->value = nullptr;
}
entry *
get_leaf(uint64_t key, entry **parent)
{
auto n = root;
entry *p = nullptr;
while (n->inode != nullptr) {
p = n;
n = n->inode->entries[BIT_IS_SET(key, n->inode->diff)];
}
if (n->key == key) {
if (parent)
*parent = p;
return n;
}
return nullptr;
}
int
foreach_node(const entry *e, callback clb, void *arg)
{
int ret = 0;
if (e->inode != nullptr) {
auto n = e->inode;
if (foreach_node(n->entries[0], clb, arg) == 0)
foreach_node(n->entries[1], clb, arg);
} else {
ret = clb(e->key, e->value, arg);
}
return ret;
}
entry *root;
};
}
#endif