Unverified Commit a43c842e authored by Luca Boccassi's avatar Luca Boccassi Committed by GitHub

Merge pull request #3556 from ssbl/better-names

Problem: variable and type names are not descriptive
parents 68b744fa d1e6fe19
...@@ -36,143 +36,145 @@ ...@@ -36,143 +36,145 @@
#include <string.h> #include <string.h>
#include <vector> #include <vector>
node::node (unsigned char *data) : data_ (data) node_t::node_t (unsigned char *data) : data_ (data)
{ {
} }
uint32_t node::refcount () uint32_t node_t::refcount ()
{ {
uint32_t u32; uint32_t u32;
memcpy (&u32, data_, sizeof (u32)); memcpy (&u32, data_, sizeof (u32));
return u32; return u32;
} }
void node::set_refcount (uint32_t value) void node_t::set_refcount (uint32_t value)
{ {
memcpy (data_, &value, sizeof (value)); memcpy (data_, &value, sizeof (value));
} }
uint32_t node::prefix_length () uint32_t node_t::prefix_length ()
{ {
uint32_t u32; uint32_t u32;
memcpy (&u32, data_ + sizeof (uint32_t), sizeof (u32)); memcpy (&u32, data_ + sizeof (uint32_t), sizeof (u32));
return u32; return u32;
} }
void node::set_prefix_length (uint32_t value) void node_t::set_prefix_length (uint32_t value)
{ {
memcpy (data_ + sizeof (value), &value, sizeof (value)); memcpy (data_ + sizeof (value), &value, sizeof (value));
} }
uint32_t node::edgecount () uint32_t node_t::edgecount ()
{ {
uint32_t u32; uint32_t u32;
memcpy (&u32, data_ + 2 * sizeof (uint32_t), sizeof (u32)); memcpy (&u32, data_ + 2 * sizeof (uint32_t), sizeof (u32));
return u32; return u32;
} }
void node::set_edgecount (uint32_t value) void node_t::set_edgecount (uint32_t value)
{ {
memcpy (data_ + 2 * sizeof (value), &value, sizeof (value)); memcpy (data_ + 2 * sizeof (value), &value, sizeof (value));
} }
unsigned char *node::prefix () unsigned char *node_t::prefix ()
{ {
return data_ + 3 * sizeof (uint32_t); return data_ + 3 * sizeof (uint32_t);
} }
void node::set_prefix (const unsigned char *bytes) void node_t::set_prefix (const unsigned char *bytes)
{ {
memcpy (prefix (), bytes, prefix_length ()); memcpy (prefix (), bytes, prefix_length ());
} }
unsigned char *node::first_bytes () unsigned char *node_t::first_bytes ()
{ {
return prefix () + prefix_length (); return prefix () + prefix_length ();
} }
void node::set_first_bytes (const unsigned char *bytes) void node_t::set_first_bytes (const unsigned char *bytes)
{ {
memcpy (first_bytes (), bytes, edgecount ()); memcpy (first_bytes (), bytes, edgecount ());
} }
unsigned char node::first_byte_at (size_t i) unsigned char node_t::first_byte_at (size_t index)
{ {
zmq_assert (i < edgecount ()); zmq_assert (index < edgecount ());
return first_bytes ()[i]; return first_bytes ()[index];
} }
void node::set_first_byte_at (size_t i, unsigned char byte) void node_t::set_first_byte_at (size_t index, unsigned char byte)
{ {
zmq_assert (i < edgecount ()); zmq_assert (index < edgecount ());
first_bytes ()[i] = byte; first_bytes ()[index] = byte;
} }
unsigned char *node::node_ptrs () unsigned char *node_t::node_pointers ()
{ {
return prefix () + prefix_length () + edgecount (); return prefix () + prefix_length () + edgecount ();
} }
void node::set_node_ptrs (const unsigned char *ptrs) void node_t::set_node_pointers (const unsigned char *pointers)
{ {
memcpy (node_ptrs (), ptrs, edgecount () * sizeof (void *)); memcpy (node_pointers (), pointers, edgecount () * sizeof (void *));
} }
node node::node_at (size_t i) node_t node_t::node_at (size_t index)
{ {
zmq_assert (i < edgecount ()); zmq_assert (index < edgecount ());
unsigned char *data; unsigned char *data;
memcpy (&data, node_ptrs () + i * sizeof (void *), sizeof (data)); memcpy (&data, node_pointers () + index * sizeof (void *), sizeof (data));
return node (data); return node_t (data);
} }
void node::set_node_at (size_t i, node n) void node_t::set_node_at (size_t index, node_t node)
{ {
zmq_assert (i < edgecount ()); zmq_assert (index < edgecount ());
memcpy (node_ptrs () + i * sizeof (void *), &n.data_, sizeof (n.data_)); memcpy (node_pointers () + index * sizeof (void *), &node.data_,
sizeof (node.data_));
} }
void node::set_edge_at (size_t i, unsigned char byte, node n) void node_t::set_edge_at (size_t index, unsigned char first_byte, node_t node)
{ {
set_first_byte_at (i, byte); set_first_byte_at (index, first_byte);
set_node_at (i, n); set_node_at (index, node);
} }
bool node::operator== (node other) const bool node_t::operator== (node_t other) const
{ {
return data_ == other.data_; return data_ == other.data_;
} }
bool node::operator!= (node other) const bool node_t::operator!= (node_t other) const
{ {
return !(*this == other); return !(*this == other);
} }
void node::resize (size_t prefix_length, size_t edgecount) void node_t::resize (size_t prefix_length, size_t edgecount)
{ {
size_t sz = size_t node_size =
3 * sizeof (uint32_t) + prefix_length + edgecount * (1 + sizeof (void *)); 3 * sizeof (uint32_t) + prefix_length + edgecount * (1 + sizeof (void *));
unsigned char *new_data = unsigned char *new_data =
static_cast<unsigned char *> (realloc (data_, sz)); static_cast<unsigned char *> (realloc (data_, node_size));
zmq_assert (new_data); zmq_assert (new_data);
data_ = new_data; data_ = new_data;
set_prefix_length (static_cast<uint32_t> (prefix_length)); set_prefix_length (static_cast<uint32_t> (prefix_length));
set_edgecount (static_cast<uint32_t> (edgecount)); set_edgecount (static_cast<uint32_t> (edgecount));
} }
node make_node (size_t refs, size_t bytes, size_t edges) node_t make_node (size_t refcount, size_t prefix_length, size_t edgecount)
{ {
size_t size = 3 * sizeof (uint32_t) + bytes + edges * (1 + sizeof (void *)); size_t node_size =
3 * sizeof (uint32_t) + prefix_length + edgecount * (1 + sizeof (void *));
unsigned char *data = static_cast<unsigned char *> (malloc (size)); unsigned char *data = static_cast<unsigned char *> (malloc (node_size));
zmq_assert (data); zmq_assert (data);
node n (data); node_t node (data);
n.set_refcount (static_cast<uint32_t> (refs)); node.set_refcount (static_cast<uint32_t> (refcount));
n.set_prefix_length (static_cast<uint32_t> (bytes)); node.set_prefix_length (static_cast<uint32_t> (prefix_length));
n.set_edgecount (static_cast<uint32_t> (edges)); node.set_edgecount (static_cast<uint32_t> (edgecount));
return n; return node;
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
...@@ -181,11 +183,11 @@ zmq::radix_tree::radix_tree () : root_ (make_node (0, 0, 0)), size_ (0) ...@@ -181,11 +183,11 @@ zmq::radix_tree::radix_tree () : root_ (make_node (0, 0, 0)), size_ (0)
{ {
} }
static void free_nodes (node n) static void free_nodes (node_t node)
{ {
for (size_t i = 0; i < n.edgecount (); ++i) for (size_t i = 0; i < node.edgecount (); ++i)
free_nodes (n.node_at (i)); free_nodes (node.node_at (i));
free (n.data_); free (node.data_);
} }
zmq::radix_tree::~radix_tree () zmq::radix_tree::~radix_tree ()
...@@ -193,64 +195,74 @@ zmq::radix_tree::~radix_tree () ...@@ -193,64 +195,74 @@ zmq::radix_tree::~radix_tree ()
free_nodes (root_); free_nodes (root_);
} }
match_result::match_result (size_t i, match_result_t::match_result_t (size_t key_bytes_matched,
size_t j, size_t prefix_bytes_matched,
size_t edge_index, size_t edge_index,
size_t gp_edge_index, size_t parent_edge_index,
node current, node_t current,
node parent, node_t parent,
node grandparent) : node_t grandparent) :
nkey (i), key_bytes_matched (key_bytes_matched),
nprefix (j), prefix_bytes_matched (prefix_bytes_matched),
edge_index (edge_index), edge_index (edge_index),
gp_edge_index (gp_edge_index), parent_edge_index (parent_edge_index),
current_node (current), current_node (current),
parent_node (parent), parent_node (parent),
grandparent_node (grandparent) grandparent_node (grandparent)
{ {
} }
match_result zmq::radix_tree::match (const unsigned char *key, match_result_t zmq::radix_tree::match (const unsigned char *key,
size_t size, size_t key_size,
bool check = false) const bool is_lookup = false) const
{ {
zmq_assert (key); zmq_assert (key);
size_t i = 0; // Number of characters matched in key. // Node we're currently at in the traversal and its predecessors.
size_t j = 0; // Number of characters matched in current node. node_t current_node = root_;
size_t edge_idx = 0; // Index of outgoing edge from the parent node. node_t parent_node = current_node;
size_t gp_edge_idx = 0; // Index of outgoing edge from grandparent. node_t grandparent_node = current_node;
node current_node = root_; // Index of the next byte to match in the key.
node parent_node = current_node; size_t key_byte_index = 0;
node grandparent_node = current_node; // Index of the next byte to match in the current node's prefix.
size_t prefix_byte_index = 0;
// Index of the edge from parent to current node.
size_t edge_index = 0;
// Index of the edge from grandparent to parent.
size_t parent_edge_index = 0;
while (current_node.prefix_length () > 0 || current_node.edgecount () > 0) { while (current_node.prefix_length () > 0 || current_node.edgecount () > 0) {
for (j = 0; j < current_node.prefix_length () && i < size; ++j, ++i) { for (prefix_byte_index = 0;
if (current_node.prefix ()[j] != key[i]) prefix_byte_index < current_node.prefix_length ()
&& key_byte_index < key_size;
++prefix_byte_index, ++key_byte_index) {
if (current_node.prefix ()[prefix_byte_index]
!= key[key_byte_index])
break; break;
} }
// Even if a prefix of the key matches and we're doing a // Even if a prefix of the key matches and we're doing a
// lookup, this means we've found a matching subscription. // lookup, this means we've found a matching subscription.
if (check && j == current_node.prefix_length () if (is_lookup && prefix_byte_index == current_node.prefix_length ()
&& current_node.refcount () > 0) { && current_node.refcount () > 0) {
i = size; key_byte_index = key_size;
break; break;
} }
// There was a mismatch or we've matched the whole key, so // There was a mismatch or we've matched the whole key, so
// there's nothing more to do. // there's nothing more to do.
if (j != current_node.prefix_length () || i == size) if (prefix_byte_index != current_node.prefix_length ()
|| key_byte_index == key_size)
break; break;
// We need to match the rest of the key. Check if there's an // We need to match the rest of the key. Check if there's an
// outgoing edge from this node. // outgoing edge from this node.
node next_node = current_node; node_t next_node = current_node;
for (size_t k = 0; k < current_node.edgecount (); ++k) { for (size_t i = 0; i < current_node.edgecount (); ++i) {
if (current_node.first_byte_at (k) == key[i]) { if (current_node.first_byte_at (i) == key[key_byte_index]) {
gp_edge_idx = edge_idx; parent_edge_index = edge_index;
edge_idx = k; edge_index = i;
next_node = current_node.node_at (k); next_node = current_node.node_at (i);
break; break;
} }
} }
...@@ -262,27 +274,29 @@ match_result zmq::radix_tree::match (const unsigned char *key, ...@@ -262,27 +274,29 @@ match_result zmq::radix_tree::match (const unsigned char *key,
current_node = next_node; current_node = next_node;
} }
return match_result (i, j, edge_idx, gp_edge_idx, current_node, parent_node, return match_result_t (key_byte_index, prefix_byte_index, edge_index,
grandparent_node); parent_edge_index, current_node, parent_node,
grandparent_node);
} }
bool zmq::radix_tree::add (const unsigned char *key, size_t size) bool zmq::radix_tree::add (const unsigned char *key, size_t key_size)
{ {
match_result result = match (key, size); match_result_t match_result = match (key, key_size);
size_t i = result.nkey; size_t key_bytes_matched = match_result.key_bytes_matched;
size_t j = result.nprefix; size_t prefix_bytes_matched = match_result.prefix_bytes_matched;
size_t edge_idx = result.edge_index; size_t edge_index = match_result.edge_index;
node current_node = result.current_node; node_t current_node = match_result.current_node;
node parent_node = result.parent_node; node_t parent_node = match_result.parent_node;
if (i != size) { if (key_bytes_matched != key_size) {
// Not all characters match, we might have to split the node. // Not all characters match, we might have to split the node.
if (i == 0 || j == current_node.prefix_length ()) { if (key_bytes_matched == 0
|| prefix_bytes_matched == current_node.prefix_length ()) {
// The mismatch is at one of the outgoing edges, so we // The mismatch is at one of the outgoing edges, so we
// create an edge from the current node to a new leaf node // create an edge from the current node to a new leaf node
// that has the rest of the key as the prefix. // that has the rest of the key as the prefix.
node key_node = make_node (1, size - i, 0); node_t key_node = make_node (1, key_size - key_bytes_matched, 0);
key_node.set_prefix (key + i); key_node.set_prefix (key + key_bytes_matched);
// Reallocate for one more edge. // Reallocate for one more edge.
current_node.resize (current_node.prefix_length (), current_node.resize (current_node.prefix_length (),
...@@ -290,24 +304,25 @@ bool zmq::radix_tree::add (const unsigned char *key, size_t size) ...@@ -290,24 +304,25 @@ bool zmq::radix_tree::add (const unsigned char *key, size_t size)
// Make room for the new edge. We need to shift the chunk // Make room for the new edge. We need to shift the chunk
// of node pointers one byte to the right. Since resize() // of node pointers one byte to the right. Since resize()
// increments the edgecount by 1, node_ptrs() tells us the // increments the edgecount by 1, node_pointers() tells us the
// destination address. The chunk of node pointers starts // destination address. The chunk of node pointers starts
// at one byte to the left of this destination. // at one byte to the left of this destination.
// //
// Since the regions can overlap, we use memmove. // Since the regions can overlap, we use memmove.
memmove (current_node.node_ptrs (), current_node.node_ptrs () - 1, memmove (current_node.node_pointers (),
current_node.node_pointers () - 1,
(current_node.edgecount () - 1) * sizeof (void *)); (current_node.edgecount () - 1) * sizeof (void *));
// Add an edge to the new node. // Add an edge to the new node.
current_node.set_edge_at (current_node.edgecount () - 1, key[i], current_node.set_edge_at (current_node.edgecount () - 1,
key_node); key[key_bytes_matched], key_node);
// We need to update all pointers to the current node // We need to update all pointers to the current node
// after the call to resize(). // after the call to resize().
if (current_node.prefix_length () == 0) if (current_node.prefix_length () == 0)
root_.data_ = current_node.data_; root_.data_ = current_node.data_;
else else
parent_node.set_node_at (edge_idx, current_node); parent_node.set_node_at (edge_index, current_node);
++size_; ++size_;
return true; return true;
} }
...@@ -318,24 +333,25 @@ bool zmq::radix_tree::add (const unsigned char *key, size_t size) ...@@ -318,24 +333,25 @@ bool zmq::radix_tree::add (const unsigned char *key, size_t size)
// One node will have the rest of the characters from the key, // One node will have the rest of the characters from the key,
// and the other node will have the rest of the characters // and the other node will have the rest of the characters
// from the current node's prefix. // from the current node's prefix.
node key_node = make_node (1, size - i, 0); node_t key_node = make_node (1, key_size - key_bytes_matched, 0);
node split_node = make_node (current_node.refcount (), node_t split_node =
current_node.prefix_length () - j, make_node (current_node.refcount (),
current_node.edgecount ()); current_node.prefix_length () - prefix_bytes_matched,
current_node.edgecount ());
// Copy the prefix chunks to the new nodes. // Copy the prefix chunks to the new nodes.
key_node.set_prefix (key + i); key_node.set_prefix (key + key_bytes_matched);
split_node.set_prefix (current_node.prefix () + j); split_node.set_prefix (current_node.prefix () + prefix_bytes_matched);
// Copy the current node's edges to the new node. // Copy the current node's edges to the new node.
split_node.set_first_bytes (current_node.first_bytes ()); split_node.set_first_bytes (current_node.first_bytes ());
split_node.set_node_ptrs (current_node.node_ptrs ()); split_node.set_node_pointers (current_node.node_pointers ());
// Resize the current node to accommodate a prefix comprising // Resize the current node to accommodate a prefix comprising
// the matched characters and 2 outgoing edges to the above // the matched characters and 2 outgoing edges to the above
// nodes. Set the refcount to 0 since this node doesn't hold a // nodes. Set the refcount to 0 since this node doesn't hold a
// key. // key.
current_node.resize (j, 2); current_node.resize (prefix_bytes_matched, 2);
current_node.set_refcount (0); current_node.set_refcount (0);
// Add links to the new nodes. We don't need to copy the // Add links to the new nodes. We don't need to copy the
...@@ -344,61 +360,63 @@ bool zmq::radix_tree::add (const unsigned char *key, size_t size) ...@@ -344,61 +360,63 @@ bool zmq::radix_tree::add (const unsigned char *key, size_t size)
current_node.set_edge_at (1, split_node.prefix ()[0], split_node); current_node.set_edge_at (1, split_node.prefix ()[0], split_node);
++size_; ++size_;
parent_node.set_node_at (edge_idx, current_node); parent_node.set_node_at (edge_index, current_node);
return true; return true;
} }
// All characters in the key match, but we still might need to split. // All characters in the key match, but we still might need to split.
if (j != current_node.prefix_length ()) { if (prefix_bytes_matched != current_node.prefix_length ()) {
// All characters in the key match, but not all characters // All characters in the key match, but not all characters
// from the current node's prefix match. // from the current node's prefix match.
// Create a node that contains the rest of the characters from // Create a node that contains the rest of the characters from
// the current node's prefix and the outgoing edges from the // the current node's prefix and the outgoing edges from the
// current node. // current node.
node split_node = make_node (current_node.refcount (), node_t split_node =
current_node.prefix_length () - j, make_node (current_node.refcount (),
current_node.edgecount ()); current_node.prefix_length () - prefix_bytes_matched,
split_node.set_prefix (current_node.prefix () + j); current_node.edgecount ());
split_node.set_prefix (current_node.prefix () + prefix_bytes_matched);
split_node.set_first_bytes (current_node.first_bytes ()); split_node.set_first_bytes (current_node.first_bytes ());
split_node.set_node_ptrs (current_node.node_ptrs ()); split_node.set_node_pointers (current_node.node_pointers ());
// Resize the current node to hold only the matched characters // Resize the current node to hold only the matched characters
// from its prefix and one edge to the new node. // from its prefix and one edge to the new node.
current_node.resize (j, 1); current_node.resize (prefix_bytes_matched, 1);
// Add an edge to the split node and set the refcount to 1 // Add an edge to the split node and set the refcount to 1
// since this key wasn't inserted earlier. We don't need to // since this key wasn't inserted earlier. We don't need to
// set the prefix because the first j bytes in the prefix are // set the prefix because the first `prefix_bytes_matched` bytes
// preserved by resize(). // in the prefix are preserved by resize().
current_node.set_edge_at (0, split_node.prefix ()[0], split_node); current_node.set_edge_at (0, split_node.prefix ()[0], split_node);
current_node.set_refcount (1); current_node.set_refcount (1);
++size_; ++size_;
parent_node.set_node_at (edge_idx, current_node); parent_node.set_node_at (edge_index, current_node);
return true; return true;
} }
zmq_assert (i == size); zmq_assert (key_bytes_matched == key_size);
zmq_assert (j == current_node.prefix_length ()); zmq_assert (prefix_bytes_matched == current_node.prefix_length ());
++size_; ++size_;
current_node.set_refcount (current_node.refcount () + 1); current_node.set_refcount (current_node.refcount () + 1);
return current_node.refcount () == 1; return current_node.refcount () == 1;
} }
bool zmq::radix_tree::rm (const unsigned char *key, size_t size) bool zmq::radix_tree::rm (const unsigned char *key, size_t key_size)
{ {
match_result result = match (key, size); match_result_t match_result = match (key, key_size);
size_t i = result.nkey; size_t key_bytes_matched = match_result.key_bytes_matched;
size_t j = result.nprefix; size_t prefix_bytes_matched = match_result.prefix_bytes_matched;
size_t edge_idx = result.edge_index; size_t edge_index = match_result.edge_index;
size_t gp_edge_idx = result.gp_edge_index; size_t parent_edge_index = match_result.parent_edge_index;
node current_node = result.current_node; node_t current_node = match_result.current_node;
node parent_node = result.parent_node; node_t parent_node = match_result.parent_node;
node grandparent_node = result.grandparent_node; node_t grandparent_node = match_result.grandparent_node;
if (i != size || j != current_node.prefix_length () if (key_bytes_matched != key_size
|| prefix_bytes_matched != current_node.prefix_length ()
|| current_node.refcount () == 0) || current_node.refcount () == 0)
return false; return false;
...@@ -419,7 +437,7 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t size) ...@@ -419,7 +437,7 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t size)
if (outgoing_edges == 1) { if (outgoing_edges == 1) {
// Merge this node with the single child node. // Merge this node with the single child node.
node child = current_node.node_at (0); node_t child = current_node.node_at (0);
// Make room for the child node's prefix and edges. We need to // Make room for the child node's prefix and edges. We need to
// keep the old prefix length since resize() will overwrite // keep the old prefix length since resize() will overwrite
...@@ -434,11 +452,11 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t size) ...@@ -434,11 +452,11 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t size)
// Copy the rest of child node's data to the current node. // Copy the rest of child node's data to the current node.
current_node.set_first_bytes (child.first_bytes ()); current_node.set_first_bytes (child.first_bytes ());
current_node.set_node_ptrs (child.node_ptrs ()); current_node.set_node_pointers (child.node_pointers ());
current_node.set_refcount (child.refcount ()); current_node.set_refcount (child.refcount ());
free (child.data_); free (child.data_);
parent_node.set_node_at (edge_idx, current_node); parent_node.set_node_at (edge_index, current_node);
return true; return true;
} }
...@@ -447,8 +465,8 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t size) ...@@ -447,8 +465,8 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t size)
// Removing this node leaves the parent with one child. // Removing this node leaves the parent with one child.
// If the parent doesn't hold a key or if it isn't the root, // If the parent doesn't hold a key or if it isn't the root,
// we can merge it with its single child node. // we can merge it with its single child node.
zmq_assert (edge_idx < 2); zmq_assert (edge_index < 2);
node other_child = parent_node.node_at (!edge_idx); node_t other_child = parent_node.node_at (!edge_index);
// Make room for the child node's prefix and edges. We need to // Make room for the child node's prefix and edges. We need to
// keep the old prefix length since resize() will overwrite // keep the old prefix length since resize() will overwrite
...@@ -463,12 +481,12 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t size) ...@@ -463,12 +481,12 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t size)
// Copy the rest of child node's data to the current node. // Copy the rest of child node's data to the current node.
parent_node.set_first_bytes (other_child.first_bytes ()); parent_node.set_first_bytes (other_child.first_bytes ());
parent_node.set_node_ptrs (other_child.node_ptrs ()); parent_node.set_node_pointers (other_child.node_pointers ());
parent_node.set_refcount (other_child.refcount ()); parent_node.set_refcount (other_child.refcount ());
free (current_node.data_); free (current_node.data_);
free (other_child.data_); free (other_child.data_);
grandparent_node.set_node_at (gp_edge_idx, parent_node); grandparent_node.set_node_at (parent_edge_index, parent_node);
return true; return true;
} }
...@@ -477,17 +495,18 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t size) ...@@ -477,17 +495,18 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t size)
// parent. // parent.
zmq_assert (outgoing_edges == 0); zmq_assert (outgoing_edges == 0);
// Move the first byte and node pointer to the back of the byte // Replace the edge to the current node with the last edge. An
// and pointer chunks respectively. // edge consists of a byte and a pointer to the next node. First
size_t last_idx = parent_node.edgecount () - 1; // replace the byte.
unsigned char last_byte = parent_node.first_byte_at (last_idx); size_t last_index = parent_node.edgecount () - 1;
node last_ptr = parent_node.node_at (last_idx); unsigned char last_byte = parent_node.first_byte_at (last_index);
parent_node.set_edge_at (edge_idx, last_byte, last_ptr); node_t last_node = parent_node.node_at (last_index);
parent_node.set_edge_at (edge_index, last_byte, last_node);
// Move the chunk of pointers one byte to the left, effectively // Move the chunk of pointers one byte to the left, effectively
// deleting the last byte in the region of first bytes by // deleting the last byte in the region of first bytes by
// overwriting it. // overwriting it.
memmove (parent_node.node_ptrs () - 1, parent_node.node_ptrs (), memmove (parent_node.node_pointers () - 1, parent_node.node_pointers (),
parent_node.edgecount () * sizeof (void *)); parent_node.edgecount () * sizeof (void *));
// Shrink the parent node to the new size, which "deletes" the // Shrink the parent node to the new size, which "deletes" the
...@@ -501,38 +520,39 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t size) ...@@ -501,38 +520,39 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t size)
if (parent_node.prefix_length () == 0) if (parent_node.prefix_length () == 0)
root_.data_ = parent_node.data_; root_.data_ = parent_node.data_;
else else
grandparent_node.set_node_at (gp_edge_idx, parent_node); grandparent_node.set_node_at (parent_edge_index, parent_node);
return true; return true;
} }
bool zmq::radix_tree::check (const unsigned char *key, size_t size) bool zmq::radix_tree::check (const unsigned char *key, size_t key_size)
{ {
if (root_.refcount () > 0) if (root_.refcount () > 0)
return true; return true;
match_result result = match (key, size, true); match_result_t match_result = match (key, key_size, true);
return result.nkey == size return match_result.key_bytes_matched == key_size
&& result.nprefix == result.current_node.prefix_length () && match_result.prefix_bytes_matched
&& result.current_node.refcount () > 0; == match_result.current_node.prefix_length ()
&& match_result.current_node.refcount () > 0;
} }
static void static void
visit_keys (node n, visit_keys (node_t node,
std::vector<unsigned char> &buffer, std::vector<unsigned char> &buffer,
void (*func) (unsigned char *data, size_t size, void *arg), void (*func) (unsigned char *data, size_t size, void *arg),
void *arg) void *arg)
{ {
for (size_t i = 0; i < n.prefix_length (); ++i) for (size_t i = 0; i < node.prefix_length (); ++i)
buffer.push_back (n.prefix ()[i]); buffer.push_back (node.prefix ()[i]);
if (n.refcount () > 0) { if (node.refcount () > 0) {
zmq_assert (!buffer.empty ()); zmq_assert (!buffer.empty ());
func (&buffer[0], buffer.size (), arg); func (&buffer[0], buffer.size (), arg);
} }
for (size_t i = 0; i < n.edgecount (); ++i) for (size_t i = 0; i < node.edgecount (); ++i)
visit_keys (n.node_at (i), buffer, func, arg); visit_keys (node.node_at (i), buffer, func, arg);
for (size_t i = 0; i < n.prefix_length (); ++i) for (size_t i = 0; i < node.prefix_length (); ++i)
buffer.pop_back (); buffer.pop_back ();
} }
......
...@@ -60,54 +60,55 @@ ...@@ -60,54 +60,55 @@
// The link to each child is looked up using its index, e.g. the child // The link to each child is looked up using its index, e.g. the child
// with index 0 will have its first byte and node pointer at the start // with index 0 will have its first byte and node pointer at the start
// of the chunk of first bytes and node pointers respectively. // of the chunk of first bytes and node pointers respectively.
struct node struct node_t
{ {
unsigned char *data_; unsigned char *data_;
explicit node (unsigned char *data); explicit node_t (unsigned char *data);
bool operator== (node other) const; bool operator== (node_t other) const;
bool operator!= (node other) const; bool operator!= (node_t other) const;
inline uint32_t refcount (); inline uint32_t refcount ();
inline uint32_t prefix_length (); inline uint32_t prefix_length ();
inline uint32_t edgecount (); inline uint32_t edgecount ();
inline unsigned char *prefix (); inline unsigned char *prefix ();
inline unsigned char *first_bytes (); inline unsigned char *first_bytes ();
inline unsigned char first_byte_at (size_t i); inline unsigned char first_byte_at (size_t index);
inline unsigned char *node_ptrs (); inline unsigned char *node_pointers ();
inline node node_at (size_t i); inline node_t node_at (size_t index);
inline void set_refcount (uint32_t value); inline void set_refcount (uint32_t value);
inline void set_prefix_length (uint32_t value); inline void set_prefix_length (uint32_t value);
inline void set_edgecount (uint32_t value); inline void set_edgecount (uint32_t value);
inline void set_prefix (const unsigned char *prefix); inline void set_prefix (const unsigned char *prefix);
inline void set_first_bytes (const unsigned char *bytes); inline void set_first_bytes (const unsigned char *bytes);
inline void set_first_byte_at (size_t i, unsigned char byte); inline void set_first_byte_at (size_t index, unsigned char byte);
inline void set_node_ptrs (const unsigned char *ptrs); inline void set_node_pointers (const unsigned char *pointers);
inline void set_node_at (size_t i, node n); inline void set_node_at (size_t index, node_t node);
inline void set_edge_at (size_t i, unsigned char byte, node n); inline void
set_edge_at (size_t index, unsigned char first_byte, node_t node);
void resize (size_t prefix_length, size_t edgecount); void resize (size_t prefix_length, size_t edgecount);
}; };
node make_node (size_t refcount, size_t prefix_length, size_t nedges); node_t make_node (size_t refcount, size_t prefix_length, size_t edgecount);
struct match_result struct match_result_t
{ {
size_t nkey; size_t key_bytes_matched;
size_t nprefix; size_t prefix_bytes_matched;
size_t edge_index; size_t edge_index;
size_t gp_edge_index; size_t parent_edge_index;
node current_node; node_t current_node;
node parent_node; node_t parent_node;
node grandparent_node; node_t grandparent_node;
match_result (size_t i, match_result_t (size_t key_bytes_matched,
size_t j, size_t prefix_bytes_matched,
size_t edge_index, size_t edge_index,
size_t gp_edge_index, size_t parent_edge_index,
node current, node_t current,
node parent, node_t parent,
node grandparent); node_t grandparent);
}; };
namespace zmq namespace zmq
...@@ -120,26 +121,26 @@ class radix_tree ...@@ -120,26 +121,26 @@ class radix_tree
// Add key to the tree. Returns true if this was a new key rather // Add key to the tree. Returns true if this was a new key rather
// than a duplicate. // than a duplicate.
bool add (const unsigned char *prefix_, size_t size_); bool add (const unsigned char *key_, size_t key_size_);
// Remove key from the tree. Returns true if he item is acually // Remove key from the tree. Returns true if the item is actually
// removed from the tree. // removed from the tree.
bool rm (const unsigned char *prefix_, size_t size_); bool rm (const unsigned char *key_, size_t key_size_);
// Check whether particular key is in the tree. // Check whether particular key is in the tree.
bool check (const unsigned char *prefix, size_t size_); bool check (const unsigned char *key_, size_t key_size_);
// Apply the function supplied to each key in the tree. // Apply the function supplied to each key in the tree.
void apply (void (*func) (unsigned char *data_, size_t size_, void *arg_), void apply (void (*func_) (unsigned char *data, size_t size, void *arg),
void *arg); void *arg_);
size_t size () const; size_t size () const;
private: private:
inline match_result inline match_result_t
match (const unsigned char *key, size_t size, bool check) const; match (const unsigned char *key, size_t key_size, bool is_lookup) const;
node root_; node_t root_;
size_t size_; size_t size_;
}; };
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment