summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/prefix_filter.cpp387
-rw-r--r--src/prefix_filter.hpp75
2 files changed, 178 insertions, 284 deletions
diff --git a/src/prefix_filter.cpp b/src/prefix_filter.cpp
index 5d21fb6..9ee18d2 100644
--- a/src/prefix_filter.cpp
+++ b/src/prefix_filter.cpp
@@ -20,129 +20,36 @@
*/
#include <new>
+#include <map>
+#include <stddef.h>
+#include <stdlib.h>
#include "../include/xs.h"
#include "prefix_filter.hpp"
#include "err.hpp"
-xs::prefix_filter_t::prefix_filter_t ()
+struct pfx_node_t
{
- init (&root);
-}
-
-xs::prefix_filter_t::~prefix_filter_t ()
-{
- close (&root);
-}
-
-int xs::prefix_filter_t::subscribe (void *core_, void *subscriber_,
- const unsigned char *data_, size_t size_)
-{
- return add (&root, data_, size_, subscriber_) ? 1 : 0;
-}
-
-int xs::prefix_filter_t::unsubscribe (void *core_, void *subscriber_,
- const unsigned char *data_, size_t size_)
-{
- return rm (&root, data_, size_, subscriber_) ? 1 : 0;
-}
-
-void xs::prefix_filter_t::unsubscribe_all (void *core_, void *subscriber_)
-{
- rm (&root, subscriber_, core_);
-}
-
-void xs::prefix_filter_t::enumerate (void *core_)
-{
- unsigned char *buff = NULL;
- list (&root, &buff, 0, 0, core_);
- free (buff);
-}
-
-int xs::prefix_filter_t::match (void *core_,
- const unsigned char *data_, size_t size_)
-{
- // This function is on critical path. It deliberately doesn't use
- // recursion to get a bit better performance.
- node_t *current = &root;
- while (true) {
-
- // We've found a corresponding subscription!
- if (current->subscribers)
- return 1;
-
- // We've checked all the data and haven't found matching subscription.
- if (!size_)
- return 0;
-
- // If there's no corresponding slot for the first character
- // of the prefix, the message does not match.
- unsigned char c = *data_;
- if (c < current->min || c >= current->min + current->count)
- return 0;
-
- // Move to the next character.
- if (current->count == 1)
- current = current->next.node;
- else {
- current = current->next.table [c - current->min];
- if (!current)
- return 0;
- }
- data_++;
- size_--;
- }
-
-}
+ // Pointer to particular subscriber associated with the reference count.
+ typedef std::map <void*, int> subscribers_t;
+ subscribers_t *subscribers;
+
+ unsigned char min;
+ unsigned short count;
+ unsigned short live_nodes;
+ union {
+ struct pfx_node_t *node;
+ struct pfx_node_t **table;
+ } next;
+};
-void xs::prefix_filter_t::match_all (void *core_,
- const unsigned char *data_, size_t size_)
+static bool pfx_is_redundant (pfx_node_t *node_)
{
- node_t *current = &root;
- while (true) {
-
- // Signal the subscribers attached to this node.
- if (current->subscribers) {
- for (node_t::subscribers_t::iterator it =
- current->subscribers->begin ();
- it != current->subscribers->end (); ++it) {
- int rc = xs_filter_matching (core_, it->first);
- errno_assert (rc == 0);
- }
- }
-
- // If we are at the end of the message, there's nothing more to match.
- if (!size_)
- break;
-
- // If there are no subnodes in the trie, return.
- if (current->count == 0)
- break;
-
- // If there's one subnode (optimisation).
- if (current->count == 1) {
- if (data_ [0] != current->min)
- break;
- current = current->next.node;
- data_++;
- size_--;
- continue;
- }
-
- // If there are multiple subnodes.
- if (data_ [0] < current->min || data_ [0] >=
- current->min + current->count)
- break;
- if (!current->next.table [data_ [0] - current->min])
- break;
- current = current->next.table [data_ [0] - current->min];
- data_++;
- size_--;
- }
+ return !node_->subscribers && node_->live_nodes == 0;
}
-void xs::prefix_filter_t::init (node_t *node_)
+static void pfx_init (pfx_node_t *node_)
{
node_->subscribers = NULL;
node_->min = 0;
@@ -150,7 +57,7 @@ void xs::prefix_filter_t::init (node_t *node_)
node_->live_nodes = 0;
}
-void xs::prefix_filter_t::close (node_t *node_)
+static void pfx_close (pfx_node_t *node_)
{
if (node_->subscribers) {
delete node_->subscribers;
@@ -159,30 +66,30 @@ void xs::prefix_filter_t::close (node_t *node_)
if (node_->count == 1) {
xs_assert (node_->next.node);
- close (node_->next.node);
- delete node_->next.node;
+ pfx_close (node_->next.node);
+ free (node_->next.node);
node_->next.node = NULL;
}
else if (node_->count > 1) {
for (unsigned short i = 0; i != node_->count; ++i)
if (node_->next.table [i]) {
- close (node_->next.table [i]);
- delete node_->next.table [i];
+ pfx_close (node_->next.table [i]);
+ free (node_->next.table [i]);
}
free (node_->next.table);
}
}
-bool xs::prefix_filter_t::add (node_t *node_, const unsigned char *prefix_,
- size_t size_, void *subscriber_)
+static bool pfx_add (pfx_node_t *node_,
+ const unsigned char *prefix_, size_t size_, void *subscriber_)
{
// We are at the node corresponding to the prefix. We are done.
if (!size_) {
bool result = !node_->subscribers;
if (!node_->subscribers)
- node_->subscribers = new (std::nothrow) node_t::subscribers_t;
- node_t::subscribers_t::iterator it = node_->subscribers->insert (
- node_t::subscribers_t::value_type (subscriber_, 0)).first;
+ node_->subscribers = new (std::nothrow) pfx_node_t::subscribers_t;
+ pfx_node_t::subscribers_t::iterator it = node_->subscribers->insert (
+ pfx_node_t::subscribers_t::value_type (subscriber_, 0)).first;
++it->second;
return result;
}
@@ -199,11 +106,11 @@ bool xs::prefix_filter_t::add (node_t *node_, const unsigned char *prefix_,
}
else if (node_->count == 1) {
unsigned char oldc = node_->min;
- node_t *oldp = node_->next.node;
+ pfx_node_t *oldp = node_->next.node;
node_->count =
(node_->min < c ? c - node_->min : node_->min - c) + 1;
- node_->next.table = (node_t**)
- malloc (sizeof (node_t*) * node_->count);
+ node_->next.table = (pfx_node_t**)
+ malloc (sizeof (pfx_node_t*) * node_->count);
xs_assert (node_->next.table);
for (unsigned short i = 0; i != node_->count; ++i)
node_->next.table [i] = 0;
@@ -215,8 +122,9 @@ bool xs::prefix_filter_t::add (node_t *node_, const unsigned char *prefix_,
// The new character is above the current character range.
unsigned short old_count = node_->count;
node_->count = c - node_->min + 1;
- node_->next.table = (node_t**) realloc ((void*) node_->next.table,
- sizeof (node_t*) * node_->count);
+ node_->next.table =
+ (pfx_node_t**) realloc ((void*) node_->next.table,
+ sizeof (pfx_node_t*) * node_->count);
xs_assert (node_->next.table);
for (unsigned short i = old_count; i != node_->count; i++)
node_->next.table [i] = NULL;
@@ -226,11 +134,12 @@ bool xs::prefix_filter_t::add (node_t *node_, const unsigned char *prefix_,
// The new character is below the current character range.
unsigned short old_count = node_->count;
node_->count = (node_->min + old_count) - c;
- node_->next.table = (node_t**) realloc ((void*) node_->next.table,
- sizeof (node_t*) * node_->count);
+ node_->next.table =
+ (pfx_node_t**) realloc ((void*) node_->next.table,
+ sizeof (pfx_node_t*) * node_->count);
xs_assert (node_->next.table);
memmove (node_->next.table + node_->min - c, node_->next.table,
- old_count * sizeof (node_t*));
+ old_count * sizeof (pfx_node_t*));
for (unsigned short i = 0; i != node_->min - c; i++)
node_->next.table [i] = NULL;
node_->min = c;
@@ -240,41 +149,34 @@ bool xs::prefix_filter_t::add (node_t *node_, const unsigned char *prefix_,
// If next node does not exist, create one.
if (node_->count == 1) {
if (!node_->next.node) {
- node_->next.node = new (std::nothrow) node_t;
+ node_->next.node = (pfx_node_t*) malloc (sizeof (pfx_node_t));
alloc_assert (node_->next.node);
- init (node_->next.node);
+ pfx_init (node_->next.node);
++node_->live_nodes;
xs_assert (node_->next.node);
}
- return add (node_->next.node, prefix_ + 1, size_ - 1, subscriber_);
+ return pfx_add (node_->next.node, prefix_ + 1, size_ - 1, subscriber_);
}
else {
if (!node_->next.table [c - node_->min]) {
- node_->next.table [c - node_->min] = new (std::nothrow) node_t;
+ node_->next.table [c - node_->min] =
+ (pfx_node_t*) malloc (sizeof (pfx_node_t));
alloc_assert (node_->next.table [c - node_->min]);
- init (node_->next.table [c - node_->min]);
+ pfx_init (node_->next.table [c - node_->min]);
++node_->live_nodes;
xs_assert (node_->next.table [c - node_->min]);
}
- return add (node_->next.table [c - node_->min], prefix_ + 1, size_ - 1,
- subscriber_);
+ return pfx_add (node_->next.table [c - node_->min],
+ prefix_ + 1, size_ - 1, subscriber_);
}
}
-
-void xs::prefix_filter_t::rm (node_t *node_, void *subscriber_, void *arg_)
-{
- unsigned char *buff = NULL;
- rm_helper (node_, subscriber_, &buff, 0, 0, arg_);
- free (buff);
-}
-
-void xs::prefix_filter_t::rm_helper (node_t *node_, void *subscribers_,
+static void pfx_rm_all (pfx_node_t *node_, void *subscribers_,
unsigned char **buff_, size_t buffsize_, size_t maxbuffsize_, void *arg_)
{
// Remove the subscription from this node.
if (node_->subscribers) {
- node_t::subscribers_t::iterator it =
+ pfx_node_t::subscribers_t::iterator it =
node_->subscribers->find (subscribers_);
if (it != node_->subscribers->end ()) {
xs_assert (it->second);
@@ -306,13 +208,13 @@ void xs::prefix_filter_t::rm_helper (node_t *node_, void *subscribers_,
if (node_->count == 1) {
(*buff_) [buffsize_] = node_->min;
buffsize_++;
- rm_helper (node_->next.node, subscribers_, buff_, buffsize_,
+ pfx_rm_all (node_->next.node, subscribers_, buff_, buffsize_,
maxbuffsize_, arg_);
// Prune the node if it was made redundant by the removal
- if (is_redundant (node_->next.node)) {
- close (node_->next.node);
- delete node_->next.node;
+ if (pfx_is_redundant (node_->next.node)) {
+ pfx_close (node_->next.node);
+ free (node_->next.node);
node_->next.node = 0;
node_->count = 0;
--node_->live_nodes;
@@ -322,21 +224,22 @@ void xs::prefix_filter_t::rm_helper (node_t *node_, void *subscribers_,
}
// If there are multiple subnodes.
- //
+
// New min non-null character in the node table after the removal.
unsigned char new_min = node_->min;
+
// New max non-null character in the node table after the removal.
unsigned char new_max = node_->min + node_->count - 1;
for (unsigned short c = 0; c != node_->count; c++) {
(*buff_) [buffsize_] = node_->min + c;
if (node_->next.table [c]) {
- rm_helper (node_->next.table [c], subscribers_, buff_,
+ pfx_rm_all (node_->next.table [c], subscribers_, buff_,
buffsize_ + 1, maxbuffsize_, arg_);
// Prune redudant nodes from the the trie.
- if (is_redundant (node_->next.table [c])) {
- close (node_->next.table [c]);
- delete node_->next.table [c];
+ if (pfx_is_redundant (node_->next.table [c])) {
+ pfx_close (node_->next.table [c]);
+ free (node_->next.table [c]);
node_->next.table [c] = 0;
xs_assert (node_->live_nodes > 0);
@@ -362,7 +265,7 @@ void xs::prefix_filter_t::rm_helper (node_t *node_, void *subscribers_,
xs_assert (new_min == new_max);
xs_assert (new_min >= node_->min &&
new_min < node_->min + node_->count);
- node_t *node = node_->next.table [new_min - node_->min];
+ pfx_node_t *node = node_->next.table [new_min - node_->min];
xs_assert (node);
free (node_->next.table);
node_->next.node = node;
@@ -373,7 +276,7 @@ void xs::prefix_filter_t::rm_helper (node_t *node_, void *subscribers_,
(new_min > node_->min || new_max < node_->min + node_->count - 1)) {
xs_assert (new_max - new_min + 1 > 1);
- node_t **old_table = node_->next.table;
+ pfx_node_t **old_table = node_->next.table;
xs_assert (new_min > node_->min ||
new_max < node_->min + node_->count - 1);
xs_assert (new_min >= node_->min);
@@ -381,25 +284,26 @@ void xs::prefix_filter_t::rm_helper (node_t *node_, void *subscribers_,
xs_assert (new_max - new_min + 1 < node_->count);
node_->count = new_max - new_min + 1;
- node_->next.table = (node_t**) malloc (sizeof (node_t*) * node_->count);
+ node_->next.table =
+ (pfx_node_t**) malloc (sizeof (pfx_node_t*) * node_->count);
xs_assert (node_->next.table);
memmove (node_->next.table, old_table + (new_min - node_->min),
- sizeof (node_t*) * node_->count);
+ sizeof (pfx_node_t*) * node_->count);
free (old_table);
node_->min = new_min;
}
}
-bool xs::prefix_filter_t::rm (node_t *node_, const unsigned char *prefix_,
+static bool pfx_rm (pfx_node_t *node_, const unsigned char *prefix_,
size_t size_, void *subscriber_)
{
if (!size_) {
// Remove the subscription from this node.
if (node_->subscribers) {
- node_t::subscribers_t::iterator it =
+ pfx_node_t::subscribers_t::iterator it =
node_->subscribers->find (subscriber_);
if (it != node_->subscribers->end ()) {
xs_assert (it->second);
@@ -420,17 +324,17 @@ bool xs::prefix_filter_t::rm (node_t *node_, const unsigned char *prefix_,
if (!node_->count || c < node_->min || c >= node_->min + node_->count)
return false;
- node_t *next_node = node_->count == 1 ? node_->next.node :
+ pfx_node_t *next_node = node_->count == 1 ? node_->next.node :
node_->next.table [c - node_->min];
if (!next_node)
return false;
- bool ret = rm (next_node, prefix_ + 1, size_ - 1, subscriber_);
+ bool ret = pfx_rm (next_node, prefix_ + 1, size_ - 1, subscriber_);
- if (is_redundant (next_node)) {
- close (next_node);
- delete next_node;
+ if (pfx_is_redundant (next_node)) {
+ pfx_close (next_node);
+ free (next_node);
xs_assert (node_->count > 0);
if (node_->count == 1) {
@@ -449,7 +353,7 @@ bool xs::prefix_filter_t::rm (node_t *node_, const unsigned char *prefix_,
// If there's only one live node in the table we can
// switch to using the more compact single-node
// representation
- node_t *node = 0;
+ pfx_node_t *node = 0;
for (unsigned short i = 0; i < node_->count; ++i) {
if (node_->next.table [i]) {
node = node_->next.table [i];
@@ -475,17 +379,17 @@ bool xs::prefix_filter_t::rm (node_t *node_, const unsigned char *prefix_,
}
xs_assert (new_min != node_->min);
- node_t **old_table = node_->next.table;
+ pfx_node_t **old_table = node_->next.table;
xs_assert (new_min > node_->min);
xs_assert (node_->count > new_min - node_->min);
node_->count = node_->count - (new_min - node_->min);
- node_->next.table =
- (node_t**) malloc (sizeof (node_t*) * node_->count);
+ node_->next.table = (pfx_node_t**)
+ malloc (sizeof (pfx_node_t*) * node_->count);
xs_assert (node_->next.table);
memmove (node_->next.table, old_table + (new_min - node_->min),
- sizeof (node_t*) * node_->count);
+ sizeof (pfx_node_t*) * node_->count);
free (old_table);
node_->min = new_min;
@@ -503,13 +407,13 @@ bool xs::prefix_filter_t::rm (node_t *node_, const unsigned char *prefix_,
xs_assert (new_count != node_->count);
node_->count = new_count;
- node_t **old_table = node_->next.table;
- node_->next.table =
- (node_t**) malloc (sizeof (node_t*) * node_->count);
+ pfx_node_t **old_table = node_->next.table;
+ node_->next.table = (pfx_node_t**)
+ malloc (sizeof (pfx_node_t*) * node_->count);
xs_assert (node_->next.table);
memmove (node_->next.table, old_table,
- sizeof (node_t*) * node_->count);
+ sizeof (pfx_node_t*) * node_->count);
free (old_table);
}
}
@@ -518,7 +422,7 @@ bool xs::prefix_filter_t::rm (node_t *node_, const unsigned char *prefix_,
return ret;
}
-void xs::prefix_filter_t::list (node_t *node_, unsigned char **buff_,
+static void pfx_list (pfx_node_t *node_, unsigned char **buff_,
size_t buffsize_, size_t maxbuffsize_, void *arg_)
{
// If this node is a subscription, apply the function.
@@ -542,7 +446,7 @@ void xs::prefix_filter_t::list (node_t *node_, unsigned char **buff_,
if (node_->count == 1) {
(*buff_) [buffsize_] = node_->min;
buffsize_++;
- list (node_->next.node, buff_, buffsize_, maxbuffsize_, arg_);
+ pfx_list (node_->next.node, buff_, buffsize_, maxbuffsize_, arg_);
return;
}
@@ -550,18 +454,12 @@ void xs::prefix_filter_t::list (node_t *node_, unsigned char **buff_,
for (unsigned short c = 0; c != node_->count; c++) {
(*buff_) [buffsize_] = node_->min + c;
if (node_->next.table [c])
- list (node_->next.table [c], buff_, buffsize_ + 1, maxbuffsize_,
- arg_);
+ pfx_list (node_->next.table [c], buff_, buffsize_ + 1,
+ maxbuffsize_, arg_);
}
}
-bool xs::prefix_filter_t::is_redundant (node_t *node_)
-{
- return !node_->subscribers && node_->live_nodes == 0;
-}
-
-// Implementation of the C interface of the filter.
-// Following functions convert raw C calls into calls to C++ object methods.
+// Implementation of the public filter interface.
static int id (void *core_)
{
@@ -570,79 +468,150 @@ static int id (void *core_)
static void *pf_create (void *core_)
{
- void *pf = (void*) new (std::nothrow) xs::prefix_filter_t;
- alloc_assert (pf);
- return pf;
+ pfx_node_t *root = (pfx_node_t*) malloc (sizeof (pfx_node_t*));
+ alloc_assert (root);
+ pfx_init (root);
+ return (void*) root;
}
static void pf_destroy (void *core_, void *pf_)
{
- delete (xs::prefix_filter_t*) pf_;
+ pfx_close ((pfx_node_t*) pf_);
}
static int pf_subscribe (void *core_, void *pf_, void *subscriber_,
const unsigned char *data_, size_t size_)
{
- return ((xs::prefix_filter_t*) pf_)->subscribe (core_, subscriber_,
- data_, size_);
+ return pfx_add ((pfx_node_t*) pf_, data_, size_, subscriber_) ? 1 : 0;
}
static int pf_unsubscribe (void *core_, void *pf_, void *subscriber_,
const unsigned char *data_, size_t size_)
{
- return ((xs::prefix_filter_t*) pf_)->unsubscribe (core_, subscriber_,
- data_, size_);
+ return pfx_rm ((pfx_node_t*) pf_, data_, size_, subscriber_) ? 1 : 0;
}
static void pf_unsubscribe_all (void *core_, void *pf_, void *subscriber_)
{
- ((xs::prefix_filter_t*) pf_)->unsubscribe_all (core_, subscriber_);
+ unsigned char *buff = NULL;
+ pfx_rm_all ((pfx_node_t*) pf_, subscriber_, &buff, 0, 0, core_);
+ free (buff);
}
static void pf_match (void *core_, void *pf_,
const unsigned char *data_, size_t size_)
{
- ((xs::prefix_filter_t*) pf_)->match_all (core_, data_, size_);
+ pfx_node_t *current = (pfx_node_t*) pf_;
+ while (true) {
+
+ // Signal the subscribers attached to this node.
+ if (current->subscribers) {
+ for (pfx_node_t::subscribers_t::iterator it =
+ current->subscribers->begin ();
+ it != current->subscribers->end (); ++it) {
+ int rc = xs_filter_matching (core_, it->first);
+ errno_assert (rc == 0);
+ }
+ }
+
+ // If we are at the end of the message, there's nothing more to match.
+ if (!size_)
+ break;
+
+ // If there are no subnodes in the trie, return.
+ if (current->count == 0)
+ break;
+
+ // If there's one subnode (optimisation).
+ if (current->count == 1) {
+ if (data_ [0] != current->min)
+ break;
+ current = current->next.node;
+ data_++;
+ size_--;
+ continue;
+ }
+
+ // If there are multiple subnodes.
+ if (data_ [0] < current->min || data_ [0] >=
+ current->min + current->count)
+ break;
+ if (!current->next.table [data_ [0] - current->min])
+ break;
+ current = current->next.table [data_ [0] - current->min];
+ data_++;
+ size_--;
+ }
}
static void *sf_create (void *core_)
{
- void *sf = (void*) new (std::nothrow) xs::prefix_filter_t;
- alloc_assert (sf);
- return sf;
+ pfx_node_t *root = (pfx_node_t*) malloc (sizeof (pfx_node_t*));
+ alloc_assert (root);
+ pfx_init (root);
+ return (void*) root;
}
static void sf_destroy (void *core_, void *sf_)
{
- delete (xs::prefix_filter_t*) sf_;
+ pfx_close ((pfx_node_t*) sf_);
}
static int sf_subscribe (void *core_, void *sf_,
const unsigned char *data_, size_t size_)
{
- return ((xs::prefix_filter_t*) sf_)->subscribe (core_, NULL,
- data_, size_);
+ return pfx_add ((pfx_node_t*) sf_, data_, size_, NULL) ? 1 : 0;
}
static int sf_unsubscribe (void *core_, void *sf_,
const unsigned char *data_, size_t size_)
{
- return ((xs::prefix_filter_t*) sf_)->unsubscribe (core_, NULL,
- data_, size_);
+ return pfx_rm ((pfx_node_t*) sf_, data_, size_, NULL) ? 1 : 0;
}
static void sf_enumerate (void *core_, void *sf_)
{
- ((xs::prefix_filter_t*) sf_)->enumerate (core_);
+ unsigned char *buff = NULL;
+ pfx_list ((pfx_node_t*) sf_, &buff, 0, 0, core_);
+ free (buff);
}
static int sf_match (void *core_, void *sf_,
const unsigned char *data_, size_t size_)
{
- return ((xs::prefix_filter_t*) sf_)->match (core_, data_, size_);
+ // This function is on critical path. It deliberately doesn't use
+ // recursion to get a bit better performance.
+ pfx_node_t *current = (pfx_node_t*) sf_;
+ while (true) {
+
+ // We've found a corresponding subscription!
+ if (current->subscribers)
+ return 1;
+
+ // We've checked all the data and haven't found matching subscription.
+ if (!size_)
+ return 0;
+
+ // If there's no corresponding slot for the first character
+ // of the prefix, the message does not match.
+ unsigned char c = *data_;
+ if (c < current->min || c >= current->min + current->count)
+ return 0;
+
+ // Move to the next character.
+ if (current->count == 1)
+ current = current->next.node;
+ else {
+ current = current->next.table [c - current->min];
+ if (!current)
+ return 0;
+ }
+ data_++;
+ size_--;
+ }
}
-static xs_filter_t filter = {
+static xs_filter_t pfx_filter = {
XS_PLUGIN_FILTER,
1,
id,
@@ -660,5 +629,5 @@ static xs_filter_t filter = {
sf_match,
};
-void *xs::prefix_filter = (void*) &filter;
+void *xs::prefix_filter = (void*) &pfx_filter;
diff --git a/src/prefix_filter.hpp b/src/prefix_filter.hpp
index 0faa865..63bc409 100644
--- a/src/prefix_filter.hpp
+++ b/src/prefix_filter.hpp
@@ -22,87 +22,12 @@
#ifndef __XS_PREFIX_FILTER_HPP_INCLUDED__
#define __XS_PREFIX_FILTER_HPP_INCLUDED__
-#include <stddef.h>
-#include <map>
-
-#include "stdint.hpp"
-
namespace xs
{
// Canonical extension object.
extern void *prefix_filter;
- class prefix_filter_t
- {
- public:
-
- prefix_filter_t ();
- ~prefix_filter_t ();
-
- int subscribe (void *core_, void *subscriber_,
- const unsigned char *data_, size_t size_);
- int unsubscribe (void *core_, void *subscriber_,
- const unsigned char *data_, size_t size_);
- void unsubscribe_all (void *core_, void *subscriber_);
- void enumerate (void *core_);
- int match (void *core_, const unsigned char *data_, size_t size_);
- void match_all (void *core_, const unsigned char *data_, size_t size_);
-
- private:
-
- struct node_t
- {
- // Pointer to particular subscriber associated with
- // the reference count.
- typedef std::map <void*, int> subscribers_t;
- subscribers_t *subscribers;
-
- unsigned char min;
- unsigned short count;
- unsigned short live_nodes;
- union {
- struct node_t *node;
- struct node_t **table;
- } next;
-
- };
-
- static void init (node_t *node_);
- static void close (node_t *node_);
-
- // Add key to the trie. Returns true if it's a new subscription
- // rather than a duplicate.
- static bool add (node_t *node_, const unsigned char *prefix_,
- size_t size_, void *subscriber_);
-
- // Remove specific subscription from the trie. Return true is it
- // was actually removed rather than de-duplicated.
- static bool rm (node_t *node_, const unsigned char *prefix_,
- size_t size_, void *subscriber_);
-
- // Remove all subscriptions for a specific peer from the trie.
- // If there are no subscriptions left on some topics, invoke the
- // supplied callback function.
- static void rm (node_t *node_, void *subscriber_, void *arg_);
-
- static void rm_helper (node_t *node_, void *subscriber_,
- unsigned char **buff_, size_t buffsize_, size_t maxbuffsize_,
- void *arg_);
-
- // Lists all the subscriptions in the trie.
- static void list (node_t *node_, unsigned char **buff_,
- size_t buffsize_, size_t maxbuffsize_, void *arg_);
-
- // Checks whether node can be safely removed.
- static bool is_redundant (node_t *node_);
-
- node_t root;
-
- prefix_filter_t (const prefix_filter_t&);
- const prefix_filter_t &operator = (const prefix_filter_t&);
- };
-
}
#endif