2011-05-30 10:07:34 +02:00
|
|
|
/*
|
2016-01-28 15:07:31 +01:00
|
|
|
Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
|
2011-05-30 10:07:34 +02:00
|
|
|
|
2015-06-02 22:33:55 +02:00
|
|
|
This file is part of libzmq, the ZeroMQ core engine in C++.
|
2011-05-30 10:07:34 +02:00
|
|
|
|
2015-06-02 22:33:55 +02:00
|
|
|
libzmq is free software; you can redistribute it and/or modify it under
|
|
|
|
the terms of the GNU Lesser General Public License (LGPL) as published
|
|
|
|
by the Free Software Foundation; either version 3 of the License, or
|
2011-05-30 10:07:34 +02:00
|
|
|
(at your option) any later version.
|
|
|
|
|
2015-06-02 22:33:55 +02:00
|
|
|
As a special exception, the Contributors give you permission to link
|
|
|
|
this library with independent modules to produce an executable,
|
|
|
|
regardless of the license terms of these independent modules, and to
|
|
|
|
copy and distribute the resulting executable under terms of your choice,
|
|
|
|
provided that you also meet, for each linked independent module, the
|
|
|
|
terms and conditions of the license of that module. An independent
|
|
|
|
module is a module which is not derived from or based on this library.
|
|
|
|
If you modify this library, you must extend this exception to your
|
|
|
|
version of the library.
|
|
|
|
|
|
|
|
libzmq is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
|
|
|
License for more details.
|
2011-05-30 10:07:34 +02:00
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include <new>
|
|
|
|
#include <algorithm>
|
|
|
|
|
2015-08-21 16:12:22 -07:00
|
|
|
#include "macros.hpp"
|
2011-05-30 10:07:34 +02:00
|
|
|
#include "platform.hpp"
|
|
|
|
#if defined ZMQ_HAVE_WINDOWS
|
|
|
|
#include "windows.hpp"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "err.hpp"
|
|
|
|
#include "pipe.hpp"
|
|
|
|
#include "mtrie.hpp"
|
|
|
|
|
|
|
|
zmq::mtrie_t::mtrie_t () :
|
2012-01-03 16:34:45 +01:00
|
|
|
pipes (0),
|
2011-05-30 10:07:34 +02:00
|
|
|
min (0),
|
2012-01-03 16:24:16 +01:00
|
|
|
count (0),
|
|
|
|
live_nodes (0)
|
2011-05-30 10:07:34 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
zmq::mtrie_t::~mtrie_t ()
|
|
|
|
{
|
2012-01-03 16:34:45 +01:00
|
|
|
if (pipes) {
|
2015-08-17 00:35:11 +04:30
|
|
|
LIBZMQ_DELETE(pipes);
|
2012-01-03 16:34:45 +01:00
|
|
|
}
|
|
|
|
|
2012-01-26 13:26:09 +01:00
|
|
|
if (count == 1) {
|
|
|
|
zmq_assert (next.node);
|
2015-08-17 00:35:11 +04:30
|
|
|
LIBZMQ_DELETE(next.node);
|
2012-01-26 13:26:09 +01:00
|
|
|
}
|
2015-08-17 00:35:11 +04:30
|
|
|
else if (count > 1) {
|
|
|
|
for (unsigned short i = 0; i != count; ++i) {
|
|
|
|
LIBZMQ_DELETE(next.table[i]);
|
|
|
|
}
|
2011-05-30 10:07:34 +02:00
|
|
|
free (next.table);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool zmq::mtrie_t::add (unsigned char *prefix_, size_t size_, pipe_t *pipe_)
|
2011-06-01 11:54:33 +02:00
|
|
|
{
|
|
|
|
return add_helper (prefix_, size_, pipe_);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool zmq::mtrie_t::add_helper (unsigned char *prefix_, size_t size_,
|
|
|
|
pipe_t *pipe_)
|
2011-05-30 10:07:34 +02:00
|
|
|
{
|
|
|
|
// We are at the node corresponding to the prefix. We are done.
|
|
|
|
if (!size_) {
|
2012-01-03 16:34:45 +01:00
|
|
|
bool result = !pipes;
|
2012-07-02 06:11:29 +02:00
|
|
|
if (!pipes) {
|
|
|
|
pipes = new (std::nothrow) pipes_t;
|
|
|
|
alloc_assert (pipes);
|
|
|
|
}
|
2012-01-03 16:34:45 +01:00
|
|
|
pipes->insert (pipe_);
|
2011-05-30 10:07:34 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char c = *prefix_;
|
|
|
|
if (c < min || c >= min + count) {
|
|
|
|
|
|
|
|
// The character is out of range of currently handled
|
2015-09-06 18:46:32 +02:00
|
|
|
// characters. We have to extend the table.
|
2011-05-30 10:07:34 +02:00
|
|
|
if (!count) {
|
|
|
|
min = c;
|
|
|
|
count = 1;
|
|
|
|
next.node = NULL;
|
|
|
|
}
|
2015-08-20 07:46:34 -07:00
|
|
|
else
|
2012-10-24 09:18:52 +09:00
|
|
|
if (count == 1) {
|
2011-05-30 10:07:34 +02:00
|
|
|
unsigned char oldc = min;
|
|
|
|
mtrie_t *oldp = next.node;
|
|
|
|
count = (min < c ? c - min : min - c) + 1;
|
|
|
|
next.table = (mtrie_t**)
|
|
|
|
malloc (sizeof (mtrie_t*) * count);
|
2012-05-28 23:13:09 +02:00
|
|
|
alloc_assert (next.table);
|
2011-05-30 10:07:34 +02:00
|
|
|
for (unsigned short i = 0; i != count; ++i)
|
|
|
|
next.table [i] = 0;
|
|
|
|
min = std::min (min, c);
|
|
|
|
next.table [oldc - min] = oldp;
|
|
|
|
}
|
2015-08-20 07:46:34 -07:00
|
|
|
else
|
2012-10-24 09:18:52 +09:00
|
|
|
if (min < c) {
|
2011-05-30 10:07:34 +02:00
|
|
|
// The new character is above the current character range.
|
|
|
|
unsigned short old_count = count;
|
|
|
|
count = c - min + 1;
|
2012-07-02 07:55:13 +02:00
|
|
|
next.table = (mtrie_t**) realloc (next.table,
|
2011-05-30 10:07:34 +02:00
|
|
|
sizeof (mtrie_t*) * count);
|
2012-05-28 23:13:09 +02:00
|
|
|
alloc_assert (next.table);
|
2011-05-30 10:07:34 +02:00
|
|
|
for (unsigned short i = old_count; i != count; i++)
|
|
|
|
next.table [i] = NULL;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// The new character is below the current character range.
|
|
|
|
unsigned short old_count = count;
|
|
|
|
count = (min + old_count) - c;
|
2012-07-02 07:55:13 +02:00
|
|
|
next.table = (mtrie_t**) realloc (next.table,
|
2011-05-30 10:07:34 +02:00
|
|
|
sizeof (mtrie_t*) * count);
|
2012-05-28 23:13:09 +02:00
|
|
|
alloc_assert (next.table);
|
2011-05-30 10:07:34 +02:00
|
|
|
memmove (next.table + min - c, next.table,
|
|
|
|
old_count * sizeof (mtrie_t*));
|
|
|
|
for (unsigned short i = 0; i != min - c; i++)
|
|
|
|
next.table [i] = NULL;
|
|
|
|
min = c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If next node does not exist, create one.
|
|
|
|
if (count == 1) {
|
|
|
|
if (!next.node) {
|
|
|
|
next.node = new (std::nothrow) mtrie_t;
|
2012-05-28 23:13:09 +02:00
|
|
|
alloc_assert (next.node);
|
2012-07-02 07:55:13 +02:00
|
|
|
++live_nodes;
|
2011-05-30 10:07:34 +02:00
|
|
|
}
|
2011-06-01 11:54:33 +02:00
|
|
|
return next.node->add_helper (prefix_ + 1, size_ - 1, pipe_);
|
2011-05-30 10:07:34 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!next.table [c - min]) {
|
|
|
|
next.table [c - min] = new (std::nothrow) mtrie_t;
|
2012-05-28 23:13:09 +02:00
|
|
|
alloc_assert (next.table [c - min]);
|
2012-07-02 07:55:13 +02:00
|
|
|
++live_nodes;
|
2011-05-30 10:07:34 +02:00
|
|
|
}
|
2011-06-01 11:54:33 +02:00
|
|
|
return next.table [c - min]->add_helper (prefix_ + 1, size_ - 1, pipe_);
|
2011-05-30 10:07:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void zmq::mtrie_t::rm (pipe_t *pipe_,
|
|
|
|
void (*func_) (unsigned char *data_, size_t size_, void *arg_),
|
2015-07-21 23:35:50 +01:00
|
|
|
void *arg_, bool call_on_uniq_)
|
2011-05-30 10:07:34 +02:00
|
|
|
{
|
|
|
|
unsigned char *buff = NULL;
|
2015-07-21 23:35:50 +01:00
|
|
|
rm_helper (pipe_, &buff, 0, 0, func_, arg_, call_on_uniq_);
|
2011-05-30 10:07:34 +02:00
|
|
|
free (buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
void zmq::mtrie_t::rm_helper (pipe_t *pipe_, unsigned char **buff_,
|
|
|
|
size_t buffsize_, size_t maxbuffsize_,
|
|
|
|
void (*func_) (unsigned char *data_, size_t size_, void *arg_),
|
2015-07-21 23:35:50 +01:00
|
|
|
void *arg_, bool call_on_uniq_)
|
2011-05-30 10:07:34 +02:00
|
|
|
{
|
|
|
|
// Remove the subscription from this node.
|
2015-07-21 23:35:50 +01:00
|
|
|
if (pipes && pipes->erase (pipe_)) {
|
|
|
|
if (!call_on_uniq_ || pipes->empty ()) {
|
|
|
|
func_ (*buff_, buffsize_, arg_);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pipes->empty ()) {
|
2015-08-17 00:35:11 +04:30
|
|
|
LIBZMQ_DELETE(pipes);
|
2015-07-21 23:35:50 +01:00
|
|
|
}
|
2012-01-03 16:34:45 +01:00
|
|
|
}
|
2011-05-30 10:07:34 +02:00
|
|
|
|
|
|
|
// Adjust the buffer.
|
|
|
|
if (buffsize_ >= maxbuffsize_) {
|
|
|
|
maxbuffsize_ = buffsize_ + 256;
|
|
|
|
*buff_ = (unsigned char*) realloc (*buff_, maxbuffsize_);
|
|
|
|
alloc_assert (*buff_);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there are no subnodes in the trie, return.
|
|
|
|
if (count == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// If there's one subnode (optimisation).
|
|
|
|
if (count == 1) {
|
|
|
|
(*buff_) [buffsize_] = min;
|
|
|
|
buffsize_++;
|
|
|
|
next.node->rm_helper (pipe_, buff_, buffsize_, maxbuffsize_,
|
2015-07-21 23:35:50 +01:00
|
|
|
func_, arg_, call_on_uniq_);
|
2012-02-16 15:56:19 +01:00
|
|
|
|
|
|
|
// Prune the node if it was made redundant by the removal
|
2012-01-03 16:24:16 +01:00
|
|
|
if (next.node->is_redundant ()) {
|
2015-08-17 00:35:11 +04:30
|
|
|
LIBZMQ_DELETE(next.node);
|
2012-01-26 13:26:09 +01:00
|
|
|
count = 0;
|
2012-01-03 16:24:16 +01:00
|
|
|
--live_nodes;
|
2012-02-16 15:56:19 +01:00
|
|
|
zmq_assert (live_nodes == 0);
|
2012-01-03 16:24:16 +01:00
|
|
|
}
|
2011-05-30 10:07:34 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there are multiple subnodes.
|
2012-02-16 15:56:19 +01:00
|
|
|
//
|
|
|
|
// New min non-null character in the node table after the removal
|
2012-02-27 11:51:30 +01:00
|
|
|
unsigned char new_min = min + count - 1;
|
2012-02-16 15:56:19 +01:00
|
|
|
// New max non-null character in the node table after the removal
|
2012-02-27 11:51:30 +01:00
|
|
|
unsigned char new_max = min;
|
2011-11-05 16:05:18 +01:00
|
|
|
for (unsigned short c = 0; c != count; c++) {
|
2011-05-30 10:07:34 +02:00
|
|
|
(*buff_) [buffsize_] = min + c;
|
2012-01-26 13:26:09 +01:00
|
|
|
if (next.table [c]) {
|
2011-05-30 10:07:34 +02:00
|
|
|
next.table [c]->rm_helper (pipe_, buff_, buffsize_ + 1,
|
2015-07-21 23:35:50 +01:00
|
|
|
maxbuffsize_, func_, arg_, call_on_uniq_);
|
2012-02-16 15:56:19 +01:00
|
|
|
|
2012-02-27 11:51:30 +01:00
|
|
|
// Prune redundant nodes from the mtrie
|
2012-01-26 13:26:09 +01:00
|
|
|
if (next.table [c]->is_redundant ()) {
|
2015-08-17 00:35:11 +04:30
|
|
|
LIBZMQ_DELETE(next.table[c]);
|
2012-02-16 15:56:19 +01:00
|
|
|
|
|
|
|
zmq_assert (live_nodes > 0);
|
2012-01-26 13:26:09 +01:00
|
|
|
--live_nodes;
|
|
|
|
}
|
2012-02-16 15:56:19 +01:00
|
|
|
else {
|
2012-02-27 11:51:30 +01:00
|
|
|
// The node is not redundant, so it's a candidate for being
|
|
|
|
// the new min/max node.
|
|
|
|
//
|
|
|
|
// We loop through the node array from left to right, so the
|
|
|
|
// first non-null, non-redundant node encountered is the new
|
|
|
|
// minimum index. Conversely, the last non-redundant, non-null
|
|
|
|
// node encountered is the new maximum index.
|
|
|
|
if (c + min < new_min)
|
2012-02-16 15:56:19 +01:00
|
|
|
new_min = c + min;
|
2012-02-27 11:51:30 +01:00
|
|
|
if (c + min > new_max)
|
2012-02-16 15:56:19 +01:00
|
|
|
new_max = c + min;
|
|
|
|
}
|
2012-01-03 16:24:16 +01:00
|
|
|
}
|
|
|
|
}
|
2012-02-16 15:56:19 +01:00
|
|
|
|
|
|
|
zmq_assert (count > 1);
|
|
|
|
|
2012-06-25 13:37:32 +02:00
|
|
|
// Free the node table if it's no longer used.
|
|
|
|
if (live_nodes == 0) {
|
|
|
|
free (next.table);
|
|
|
|
next.table = NULL;
|
|
|
|
count = 0;
|
|
|
|
}
|
2012-02-16 15:56:19 +01:00
|
|
|
// Compact the node table if possible
|
2015-08-20 07:46:34 -07:00
|
|
|
else
|
2012-10-24 09:18:52 +09:00
|
|
|
if (live_nodes == 1) {
|
2012-02-16 15:56:19 +01:00
|
|
|
// If there's only one live node in the table we can
|
|
|
|
// switch to using the more compact single-node
|
|
|
|
// representation
|
|
|
|
zmq_assert (new_min == new_max);
|
|
|
|
zmq_assert (new_min >= min && new_min < min + count);
|
|
|
|
mtrie_t *node = next.table [new_min - min];
|
|
|
|
zmq_assert (node);
|
|
|
|
free (next.table);
|
|
|
|
next.node = node;
|
|
|
|
count = 1;
|
|
|
|
min = new_min;
|
|
|
|
}
|
2012-10-24 09:18:52 +09:00
|
|
|
else
|
|
|
|
if (new_min > min || new_max < min + count - 1) {
|
2012-02-16 15:56:19 +01:00
|
|
|
zmq_assert (new_max - new_min + 1 > 1);
|
|
|
|
|
|
|
|
mtrie_t **old_table = next.table;
|
|
|
|
zmq_assert (new_min > min || new_max < min + count - 1);
|
|
|
|
zmq_assert (new_min >= min);
|
|
|
|
zmq_assert (new_max <= min + count - 1);
|
|
|
|
zmq_assert (new_max - new_min + 1 < count);
|
|
|
|
|
|
|
|
count = new_max - new_min + 1;
|
|
|
|
next.table = (mtrie_t**) malloc (sizeof (mtrie_t*) * count);
|
2012-05-28 23:13:09 +02:00
|
|
|
alloc_assert (next.table);
|
2012-02-16 15:56:19 +01:00
|
|
|
|
|
|
|
memmove (next.table, old_table + (new_min - min),
|
|
|
|
sizeof (mtrie_t*) * count);
|
|
|
|
free (old_table);
|
|
|
|
|
|
|
|
min = new_min;
|
|
|
|
}
|
2011-05-30 10:07:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool zmq::mtrie_t::rm (unsigned char *prefix_, size_t size_, pipe_t *pipe_)
|
|
|
|
{
|
2011-06-01 11:54:33 +02:00
|
|
|
return rm_helper (prefix_, size_, pipe_);
|
|
|
|
}
|
2011-05-30 10:07:34 +02:00
|
|
|
|
2011-06-01 11:54:33 +02:00
|
|
|
bool zmq::mtrie_t::rm_helper (unsigned char *prefix_, size_t size_,
|
|
|
|
pipe_t *pipe_)
|
|
|
|
{
|
|
|
|
if (!size_) {
|
2012-01-03 16:34:45 +01:00
|
|
|
if (pipes) {
|
|
|
|
pipes_t::size_type erased = pipes->erase (pipe_);
|
|
|
|
zmq_assert (erased == 1);
|
|
|
|
if (pipes->empty ()) {
|
2015-08-17 00:35:11 +04:30
|
|
|
LIBZMQ_DELETE(pipes);
|
2012-01-03 16:34:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return !pipes;
|
2011-06-01 11:54:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char c = *prefix_;
|
|
|
|
if (!count || c < min || c >= min + count)
|
|
|
|
return false;
|
2011-05-30 10:07:34 +02:00
|
|
|
|
2011-06-01 11:54:33 +02:00
|
|
|
mtrie_t *next_node =
|
|
|
|
count == 1 ? next.node : next.table [c - min];
|
2011-05-30 10:07:34 +02:00
|
|
|
|
2011-06-01 11:54:33 +02:00
|
|
|
if (!next_node)
|
|
|
|
return false;
|
2011-05-30 10:07:34 +02:00
|
|
|
|
2012-01-03 16:24:16 +01:00
|
|
|
bool ret = next_node->rm_helper (prefix_ + 1, size_ - 1, pipe_);
|
|
|
|
|
|
|
|
if (next_node->is_redundant ()) {
|
2015-08-17 00:35:11 +04:30
|
|
|
LIBZMQ_DELETE(next_node);
|
2012-02-16 15:56:19 +01:00
|
|
|
zmq_assert (count > 0);
|
|
|
|
|
2012-01-26 13:26:09 +01:00
|
|
|
if (count == 1) {
|
2012-01-03 16:24:16 +01:00
|
|
|
next.node = 0;
|
2012-01-26 13:26:09 +01:00
|
|
|
count = 0;
|
2012-02-16 15:56:19 +01:00
|
|
|
--live_nodes;
|
|
|
|
zmq_assert (live_nodes == 0);
|
2012-01-26 13:26:09 +01:00
|
|
|
}
|
2012-02-16 15:56:19 +01:00
|
|
|
else {
|
2012-01-03 16:24:16 +01:00
|
|
|
next.table [c - min] = 0;
|
2012-02-16 15:56:19 +01:00
|
|
|
zmq_assert (live_nodes > 1);
|
|
|
|
--live_nodes;
|
|
|
|
|
|
|
|
// Compact the table if possible
|
|
|
|
if (live_nodes == 1) {
|
|
|
|
// If there's only one live node in the table we can
|
|
|
|
// switch to using the more compact single-node
|
|
|
|
// representation
|
2012-07-02 07:55:13 +02:00
|
|
|
unsigned short i;
|
|
|
|
for (i = 0; i < count; ++i)
|
|
|
|
if (next.table [i])
|
2012-02-16 15:56:19 +01:00
|
|
|
break;
|
|
|
|
|
2012-07-02 07:55:13 +02:00
|
|
|
zmq_assert (i < count);
|
|
|
|
min += i;
|
2012-02-16 15:56:19 +01:00
|
|
|
count = 1;
|
2012-07-02 07:55:13 +02:00
|
|
|
mtrie_t *oldp = next.table [i];
|
|
|
|
free (next.table);
|
|
|
|
next.node = oldp;
|
2012-02-16 15:56:19 +01:00
|
|
|
}
|
2012-10-24 09:18:52 +09:00
|
|
|
else
|
|
|
|
if (c == min) {
|
2012-02-16 15:56:19 +01:00
|
|
|
// We can compact the table "from the left"
|
2012-07-02 07:55:13 +02:00
|
|
|
unsigned short i;
|
|
|
|
for (i = 1; i < count; ++i)
|
|
|
|
if (next.table [i])
|
2012-02-16 15:56:19 +01:00
|
|
|
break;
|
|
|
|
|
2012-07-02 07:55:13 +02:00
|
|
|
zmq_assert (i < count);
|
|
|
|
min += i;
|
|
|
|
count -= i;
|
2012-02-16 15:56:19 +01:00
|
|
|
mtrie_t **old_table = next.table;
|
|
|
|
next.table = (mtrie_t**) malloc (sizeof (mtrie_t*) * count);
|
2012-05-28 23:13:09 +02:00
|
|
|
alloc_assert (next.table);
|
2012-07-02 07:55:13 +02:00
|
|
|
memmove (next.table, old_table + i, sizeof (mtrie_t*) * count);
|
2012-02-16 15:56:19 +01:00
|
|
|
free (old_table);
|
|
|
|
}
|
2012-10-24 09:18:52 +09:00
|
|
|
else
|
|
|
|
if (c == min + count - 1) {
|
2012-02-16 15:56:19 +01:00
|
|
|
// We can compact the table "from the right"
|
2012-07-02 07:55:13 +02:00
|
|
|
unsigned short i;
|
|
|
|
for (i = 1; i < count; ++i)
|
|
|
|
if (next.table [count - 1 - i])
|
2012-02-16 15:56:19 +01:00
|
|
|
break;
|
|
|
|
|
2012-07-02 07:55:13 +02:00
|
|
|
zmq_assert (i < count);
|
|
|
|
count -= i;
|
2012-02-16 15:56:19 +01:00
|
|
|
mtrie_t **old_table = next.table;
|
|
|
|
next.table = (mtrie_t**) malloc (sizeof (mtrie_t*) * count);
|
2012-05-28 23:13:09 +02:00
|
|
|
alloc_assert (next.table);
|
2012-02-16 15:56:19 +01:00
|
|
|
memmove (next.table, old_table, sizeof (mtrie_t*) * count);
|
|
|
|
free (old_table);
|
|
|
|
}
|
|
|
|
}
|
2012-01-03 16:24:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2011-05-30 10:07:34 +02:00
|
|
|
}
|
|
|
|
|
2011-06-11 20:29:56 +02:00
|
|
|
void zmq::mtrie_t::match (unsigned char *data_, size_t size_,
|
|
|
|
void (*func_) (pipe_t *pipe_, void *arg_), void *arg_)
|
2011-05-30 10:07:34 +02:00
|
|
|
{
|
2011-09-16 16:34:28 +02:00
|
|
|
mtrie_t *current = this;
|
2011-09-26 14:02:31 +02:00
|
|
|
while (true) {
|
2011-09-16 16:34:28 +02:00
|
|
|
|
|
|
|
// Signal the pipes attached to this node.
|
2012-01-03 16:34:45 +01:00
|
|
|
if (current->pipes) {
|
|
|
|
for (pipes_t::iterator it = current->pipes->begin ();
|
|
|
|
it != current->pipes->end (); ++it)
|
|
|
|
func_ (*it, arg_);
|
|
|
|
}
|
2011-09-16 16:34:28 +02:00
|
|
|
|
2011-09-26 14:02:31 +02:00
|
|
|
// If we are at the end of the message, there's nothing more to match.
|
|
|
|
if (!size_)
|
|
|
|
break;
|
|
|
|
|
2011-09-16 16:34:28 +02:00
|
|
|
// If there are no subnodes in the trie, return.
|
|
|
|
if (current->count == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// If there's one subnode (optimisation).
|
2015-08-20 07:46:34 -07:00
|
|
|
if (current->count == 1) {
|
2011-09-16 16:34:28 +02:00
|
|
|
if (data_ [0] != current->min)
|
|
|
|
break;
|
|
|
|
current = current->next.node;
|
|
|
|
data_++;
|
|
|
|
size_--;
|
2015-08-20 07:46:34 -07:00
|
|
|
continue;
|
|
|
|
}
|
2011-09-16 16:34:28 +02:00
|
|
|
|
2015-08-20 07:46:34 -07:00
|
|
|
// If there are multiple subnodes.
|
2011-09-29 11:35:31 +02:00
|
|
|
if (data_ [0] < current->min || data_ [0] >=
|
|
|
|
current->min + current->count)
|
2011-09-16 16:34:28 +02:00
|
|
|
break;
|
2011-09-29 11:35:31 +02:00
|
|
|
if (!current->next.table [data_ [0] - current->min])
|
2011-09-16 16:34:28 +02:00
|
|
|
break;
|
2011-09-29 11:35:31 +02:00
|
|
|
current = current->next.table [data_ [0] - current->min];
|
2011-09-16 16:34:28 +02:00
|
|
|
data_++;
|
|
|
|
size_--;
|
2011-05-30 10:07:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-26 13:26:09 +01:00
|
|
|
bool zmq::mtrie_t::is_redundant () const
|
2012-01-03 16:24:16 +01:00
|
|
|
{
|
2012-01-03 16:34:45 +01:00
|
|
|
return !pipes && live_nodes == 0;
|
2012-01-03 16:24:16 +01:00
|
|
|
}
|