1/*
2 Copyright (c) 2018 Contributors as noted in the AUTHORS file
3
4 This file is part of libzmq, the ZeroMQ core engine in C++.
5
6 libzmq is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License (LGPL) as published
8 by the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 As a special exception, the Contributors give you permission to link
12 this library with independent modules to produce an executable,
13 regardless of the license terms of these independent modules, and to
14 copy and distribute the resulting executable under terms of your choice,
15 provided that you also meet, for each linked independent module, the
16 terms and conditions of the license of that module. An independent
17 module is a module which is not derived from or based on this library.
18 If you modify this library, you must extend this exception to your
19 version of the library.
20
21 libzmq is distributed in the hope that it will be useful, but WITHOUT
22 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 License for more details.
25
26 You should have received a copy of the GNU Lesser General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>.
28*/
29
30#ifndef RADIX_TREE_HPP
31#define RADIX_TREE_HPP
32
33#include <stddef.h>
34
35#include "stdint.hpp"
36
37// Wrapper type for a node's data layout.
38//
39// There are 3 32-bit unsigned integers that act as a header. These
40// integers represent the following values in this order:
41//
42// (1) The reference count of the key held by the node. This is 0 if
43// the node doesn't hold a key.
44//
45// (2) The number of characters in the node's prefix. The prefix is a
46// part of one or more keys in the tree, e.g. the prefix of each node
47// in a trie consists of a single character.
48//
49// (3) The number of outgoing edges from this node.
50//
51// The rest of the layout consists of 3 chunks in this order:
52//
53// (1) The node's prefix as a sequence of one or more bytes. The root
54// node always has an empty prefix, unlike other nodes in the tree.
55//
56// (2) The first byte of the prefix of each of this node's children.
57//
58// (3) The pointer to each child node.
59//
60// The link to each child is looked up using its index, e.g. the child
61// with index 0 will have its first byte and node pointer at the start
62// of the chunk of first bytes and node pointers respectively.
63struct node_t
64{
65 explicit node_t (unsigned char *data_);
66
67 bool operator== (node_t other_) const;
68 bool operator!= (node_t other_) const;
69
70 inline uint32_t refcount ();
71 inline uint32_t prefix_length ();
72 inline uint32_t edgecount ();
73 inline unsigned char *prefix ();
74 inline unsigned char *first_bytes ();
75 inline unsigned char first_byte_at (size_t index_);
76 inline unsigned char *node_pointers ();
77 inline node_t node_at (size_t index_);
78 inline void set_refcount (uint32_t value_);
79 inline void set_prefix_length (uint32_t value_);
80 inline void set_edgecount (uint32_t value_);
81 inline void set_prefix (const unsigned char *bytes_);
82 inline void set_first_bytes (const unsigned char *bytes_);
83 inline void set_first_byte_at (size_t index_, unsigned char byte_);
84 inline void set_node_pointers (const unsigned char *pointers_);
85 inline void set_node_at (size_t index_, node_t node_);
86 inline void
87 set_edge_at (size_t index_, unsigned char first_byte_, node_t node_);
88 void resize (size_t prefix_length_, size_t edgecount_);
89
90 unsigned char *_data;
91};
92
93node_t make_node (size_t refcount_, size_t prefix_length_, size_t edgecount_);
94
95struct match_result_t
96{
97 match_result_t (size_t key_bytes_matched_,
98 size_t prefix_bytes_matched_,
99 size_t edge_index_,
100 size_t parent_edge_index_,
101 node_t current_,
102 node_t parent_,
103 node_t grandparent);
104
105 size_t _key_bytes_matched;
106 size_t _prefix_bytes_matched;
107 size_t _edge_index;
108 size_t _parent_edge_index;
109 node_t _current_node;
110 node_t _parent_node;
111 node_t _grandparent_node;
112};
113
114namespace zmq
115{
116class radix_tree_t
117{
118 public:
119 radix_tree_t ();
120 ~radix_tree_t ();
121
122 // Add key to the tree. Returns true if this was a new key rather
123 // than a duplicate.
124 bool add (const unsigned char *key_, size_t key_size_);
125
126 // Remove key from the tree. Returns true if the item is actually
127 // removed from the tree.
128 bool rm (const unsigned char *key_, size_t key_size_);
129
130 // Check whether particular key is in the tree.
131 bool check (const unsigned char *key_, size_t key_size_);
132
133 // Apply the function supplied to each key in the tree.
134 void apply (void (*func_) (unsigned char *data, size_t size, void *arg),
135 void *arg_);
136
137 size_t size () const;
138
139 private:
140 inline match_result_t
141 match (const unsigned char *key_, size_t key_size_, bool is_lookup_) const;
142
143 node_t _root;
144 size_t _size;
145};
146}
147
148#endif
149