3 #ifndef __ZMQ_GENERIC_MTRIE_IMPL_HPP_INCLUDED__
4 #define __ZMQ_GENERIC_MTRIE_IMPL_HPP_INCLUDED__
21 _pipes (0), _num_prefixes (0), _min (0), _count (0), _live_nodes (0)
32 }
else if (_count > 1) {
33 for (
unsigned short i = 0;
i != _count; ++
i) {
46 const unsigned char c = *
prefix_;
48 if (c < it->_min || c >=
it->_min +
it->_count) {
55 }
else if (
it->_count == 1) {
56 const unsigned char oldc =
it->_min;
58 it->_count = (
it->_min < c ? c -
it->_min :
it->_min - c) + 1;
62 for (
unsigned short i = 0;
i !=
it->_count; ++
i)
63 it->_next.table[
i] = 0;
64 it->_min = std::min (
it->_min, c);
65 it->_next.table[oldc -
it->_min] = oldp;
66 }
else if (
it->_min < c) {
68 const unsigned short old_count =
it->_count;
69 it->_count = c -
it->_min + 1;
73 for (
unsigned short i = old_count;
i !=
it->_count;
i++)
77 const unsigned short old_count =
it->_count;
78 it->_count = (
it->_min + old_count) - c;
82 memmove (
it->_next.table +
it->_min - c,
it->_next.table,
84 for (
unsigned short i = 0;
i !=
it->_min - c;
i++)
91 if (
it->_count == 1) {
92 if (!
it->_next.node) {
102 if (!
it->_next.table[c -
it->_min]) {
103 it->_next.table[c -
it->_min] =
111 it =
it->_next.table[c -
it->_min];
116 const bool result = !
it->_pipes;
121 _num_prefixes.add (1);
123 it->_pipes->insert (pipe_);
128 template <
typename T>
129 template <
typename Arg>
131 void (*func_) (prefix_t
data_,
147 std::list<struct iter> stack;
148 unsigned char *buff =
NULL;
149 size_t maxbuffsize = 0;
150 struct iter
it = {
this,
NULL,
NULL, 0, 0, 0, 0,
false};
151 stack.push_back (
it);
153 while (!stack.empty ()) {
157 if (!
it.processed_for_removal) {
159 if (
it.node->_pipes &&
it.node->_pipes->erase (pipe_)) {
160 if (!call_on_uniq_ ||
it.node->_pipes->empty ()) {
161 func_ (buff,
it.size, arg_);
164 if (
it.node->_pipes->empty ()) {
170 if (
it.size >= maxbuffsize) {
171 maxbuffsize =
it.size + 256;
173 static_cast<unsigned char *
> (realloc (buff, maxbuffsize));
177 switch (
it.node->_count) {
185 buff[
it.size] =
it.node->_min;
188 it.processed_for_removal =
true;
189 stack.push_back (
it);
190 struct iter
next = {
it.node->_next.node,
198 stack.push_back (
next);
206 if (
it.current_child == 0) {
208 it.new_min =
it.node->_min +
it.node->_count - 1;
210 it.new_max =
it.node->_min;
215 buff[
it.size] =
it.node->_min +
it.current_child;
216 it.processed_for_removal =
true;
217 stack.push_back (
it);
218 if (
it.node->_next.table[
it.current_child]) {
220 it.node->_next.table[
it.current_child],
228 stack.push_back (
next);
235 it.processed_for_removal =
false;
237 switch (
it.node->_count) {
246 if (
it.node->_next.node->is_redundant ()) {
249 --
it.node->_live_nodes;
256 if (
it.node->_next.table[
it.current_child]) {
258 if (
it.node->_next.table[
it.current_child]
261 it.node->_next.table[
it.current_child]);
264 --
it.node->_live_nodes;
273 if (
it.current_child +
it.node->_min
276 it.current_child +
it.node->_min;
277 if (
it.current_child +
it.node->_min
280 it.current_child +
it.node->_min;
289 if (
it.current_child >=
it.node->_count)
290 it.current_child = 0;
292 stack.push_back (
it);
302 switch (
it.node->_live_nodes) {
304 free (
it.node->_next.table);
305 it.node->_next.table =
NULL;
317 <
it.node->_min +
it.node->_count);
321 .table[
it.new_min -
it.node->_min];
323 free (
it.node->_next.table);
324 it.node->_next.node = node;
327 it.node->_min =
it.new_min;
330 if (
it.new_min >
it.node->_min
331 ||
it.new_max <
it.node->_min
332 +
it.node->_count - 1) {
337 it.node->_next.table;
341 +
it.node->_count - 1);
345 +
it.node->_count - 1);
350 it.new_max -
it.new_min + 1;
351 it.node->_next.table =
357 memmove (
it.node->_next.table,
359 + (
it.new_min -
it.node->_min),
364 it.node->_min =
it.new_min;
375 template <
typename T>
388 std::list<struct iter> stack;
389 struct iter
it = {
this,
NULL,
prefix_, size_, 0, 0, 0,
false};
390 stack.push_back (
it);
392 while (!stack.empty ()) {
396 if (!
it.processed_for_removal) {
398 if (!
it.node->_pipes) {
403 typename pipes_t::size_type erased =
404 it.node->_pipes->erase (pipe_);
405 if (
it.node->_pipes->empty ()) {
408 ret = last_value_removed;
412 ret = (erased == 1) ? values_remain : not_found;
416 it.current_child = *
it.prefix;
417 if (!
it.node->_count ||
it.current_child <
it.node->_min
418 ||
it.current_child >=
it.node->_min +
it.node->_count) {
425 ?
it.node->_next.node
426 :
it.node->_next.table[
it.current_child -
it.node->_min];
432 it.processed_for_removal =
true;
433 stack.push_back (
it);
435 it.next_node,
NULL,
it.prefix + 1,
it.size - 1, 0, 0, 0,
false};
436 stack.push_back (
next);
438 it.processed_for_removal =
false;
440 if (
it.next_node->is_redundant ()) {
444 if (
it.node->_count == 1) {
445 it.node->_next.node =
NULL;
447 --
it.node->_live_nodes;
450 it.node->_next.table[
it.current_child -
it.node->_min] = 0;
452 --
it.node->_live_nodes;
455 if (
it.node->_live_nodes == 1) {
460 for (
i = 0;
i <
it.node->_count; ++
i)
461 if (
it.node->_next.table[
i])
468 free (
it.node->_next.table);
469 it.node->_next.table =
NULL;
470 it.node->_next.node = oldp;
471 }
else if (
it.current_child ==
it.node->_min) {
474 for (
i = 1;
i <
it.node->_count; ++
i)
475 if (
it.node->_next.table[
i])
480 it.node->_count -=
i;
482 it.node->_next.table =
486 memmove (
it.node->_next.table, old_table +
i,
489 }
else if (
it.current_child
490 ==
it.node->_min +
it.node->_count - 1) {
493 for (
i = 1;
i <
it.node->_count; ++
i)
494 if (
it.node->_next.table[
it.node->_count - 1 -
i])
498 it.node->_count -=
i;
500 it.node->_next.table =
504 memmove (
it.node->_next.table, old_table,
513 if (ret == last_value_removed) {
515 _num_prefixes.sub (1);
521 template <
typename T>
522 template <
typename Arg>
525 void (*func_) (
value_t *pipe_, Arg arg_),
530 if (current->_pipes) {
531 for (
typename pipes_t::iterator
it = current->_pipes->begin (),
532 end = current->_pipes->end ();
543 if (current->_count == 0)
546 if (current->_count == 1) {
548 if (
data_[0] != current->_min) {
551 current = current->_next.node;
554 if (
data_[0] < current->_min
555 ||
data_[0] >= current->_min + current->_count) {
558 current = current->_next.table[
data_[0] - current->_min];
565 return !_pipes && _live_nodes == 0;