Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
L
libzmq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
libzmq
Commits
a43c842e
Unverified
Commit
a43c842e
authored
Jun 27, 2019
by
Luca Boccassi
Committed by
GitHub
Jun 27, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3556 from ssbl/better-names
Problem: variable and type names are not descriptive
parents
68b744fa
d1e6fe19
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
205 additions
and
184 deletions
+205
-184
radix_tree.cpp
src/radix_tree.cpp
+170
-150
radix_tree.hpp
src/radix_tree.hpp
+35
-34
No files found.
src/radix_tree.cpp
View file @
a43c842e
...
...
@@ -36,143 +36,145 @@
#include <string.h>
#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
;
memcpy
(
&
u32
,
data_
,
sizeof
(
u32
));
return
u32
;
}
void
node
::
set_refcount
(
uint32_t
value
)
void
node
_t
::
set_refcount
(
uint32_t
value
)
{
memcpy
(
data_
,
&
value
,
sizeof
(
value
));
}
uint32_t
node
::
prefix_length
()
uint32_t
node
_t
::
prefix_length
()
{
uint32_t
u32
;
memcpy
(
&
u32
,
data_
+
sizeof
(
uint32_t
),
sizeof
(
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
));
}
uint32_t
node
::
edgecount
()
uint32_t
node
_t
::
edgecount
()
{
uint32_t
u32
;
memcpy
(
&
u32
,
data_
+
2
*
sizeof
(
uint32_t
),
sizeof
(
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
));
}
unsigned
char
*
node
::
prefix
()
unsigned
char
*
node
_t
::
prefix
()
{
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
());
}
unsigned
char
*
node
::
first_bytes
()
unsigned
char
*
node
_t
::
first_bytes
()
{
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
());
}
unsigned
char
node
::
first_byte_at
(
size_t
i
)
unsigned
char
node
_t
::
first_byte_at
(
size_t
index
)
{
zmq_assert
(
i
<
edgecount
());
return
first_bytes
()[
i
];
zmq_assert
(
i
ndex
<
edgecount
());
return
first_bytes
()[
i
ndex
];
}
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
());
first_bytes
()[
i
]
=
byte
;
zmq_assert
(
i
ndex
<
edgecount
());
first_bytes
()[
i
ndex
]
=
byte
;
}
unsigned
char
*
node
::
node_pt
rs
()
unsigned
char
*
node
_t
::
node_pointe
rs
()
{
return
prefix
()
+
prefix_length
()
+
edgecount
();
}
void
node
::
set_node_ptrs
(
const
unsigned
char
*
pt
rs
)
void
node
_t
::
set_node_pointers
(
const
unsigned
char
*
pointe
rs
)
{
memcpy
(
node_p
trs
(),
pt
rs
,
edgecount
()
*
sizeof
(
void
*
));
memcpy
(
node_p
ointers
(),
pointe
rs
,
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
(
i
ndex
<
edgecount
());
unsigned
char
*
data
;
memcpy
(
&
data
,
node_p
trs
()
+
i
*
sizeof
(
void
*
),
sizeof
(
data
));
return
node
(
data
);
memcpy
(
&
data
,
node_p
ointers
()
+
index
*
sizeof
(
void
*
),
sizeof
(
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
());
memcpy
(
node_ptrs
()
+
i
*
sizeof
(
void
*
),
&
n
.
data_
,
sizeof
(
n
.
data_
));
zmq_assert
(
index
<
edgecount
());
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_node_at
(
i
,
n
);
set_first_byte_at
(
i
ndex
,
first_
byte
);
set_node_at
(
i
ndex
,
node
);
}
bool
node
::
operator
==
(
node
other
)
const
bool
node
_t
::
operator
==
(
node_t
other
)
const
{
return
data_
==
other
.
data_
;
}
bool
node
::
operator
!=
(
node
other
)
const
bool
node
_t
::
operator
!=
(
node_t
other
)
const
{
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
*
));
unsigned
char
*
new_data
=
static_cast
<
unsigned
char
*>
(
realloc
(
data_
,
sz
));
static_cast
<
unsigned
char
*>
(
realloc
(
data_
,
node_size
));
zmq_assert
(
new_data
);
data_
=
new_data
;
set_prefix_length
(
static_cast
<
uint32_t
>
(
prefix_length
));
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
);
node
n
(
data
);
n
.
set_refcount
(
static_cast
<
uint32_t
>
(
refs
));
n
.
set_prefix_length
(
static_cast
<
uint32_t
>
(
bytes
));
n
.
set_edgecount
(
static_cast
<
uint32_t
>
(
edges
));
return
n
;
node
_t
node
(
data
);
n
ode
.
set_refcount
(
static_cast
<
uint32_t
>
(
refcount
));
n
ode
.
set_prefix_length
(
static_cast
<
uint32_t
>
(
prefix_length
));
n
ode
.
set_edgecount
(
static_cast
<
uint32_t
>
(
edgecount
));
return
n
ode
;
}
// ----------------------------------------------------------------------
...
...
@@ -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
)
free_nodes
(
n
.
node_at
(
i
));
free
(
n
.
data_
);
for
(
size_t
i
=
0
;
i
<
n
ode
.
edgecount
();
++
i
)
free_nodes
(
n
ode
.
node_at
(
i
));
free
(
n
ode
.
data_
);
}
zmq
::
radix_tree
::~
radix_tree
()
...
...
@@ -193,64 +195,74 @@ zmq::radix_tree::~radix_tree ()
free_nodes
(
root_
);
}
match_result
::
match_result
(
size_t
i
,
size_t
j
,
match_result
_t
::
match_result_t
(
size_t
key_bytes_matched
,
size_t
prefix_bytes_matched
,
size_t
edge_index
,
size_t
gp
_edge_index
,
node
current
,
node
parent
,
node
grandparent
)
:
nkey
(
i
),
nprefix
(
j
),
size_t
parent
_edge_index
,
node_t
current
,
node_t
parent
,
node_t
grandparent
)
:
key_bytes_matched
(
key_bytes_matched
),
prefix_bytes_matched
(
prefix_bytes_matched
),
edge_index
(
edge_index
),
gp_edge_index
(
gp
_edge_index
),
parent_edge_index
(
parent
_edge_index
),
current_node
(
current
),
parent_node
(
parent
),
grandparent_node
(
grandparent
)
{
}
match_result
zmq
::
radix_tree
::
match
(
const
unsigned
char
*
key
,
size_t
size
,
bool
check
=
false
)
const
match_result
_t
zmq
::
radix_tree
::
match
(
const
unsigned
char
*
key
,
size_t
key_
size
,
bool
is_lookup
=
false
)
const
{
zmq_assert
(
key
);
size_t
i
=
0
;
// Number of characters matched in key.
size_t
j
=
0
;
// Number of characters matched in current node.
size_t
edge_idx
=
0
;
// Index of outgoing edge from the parent node.
size_t
gp_edge_idx
=
0
;
// Index of outgoing edge from grandparent.
node
current_node
=
root_
;
node
parent_node
=
current_node
;
node
grandparent_node
=
current_node
;
// Node we're currently at in the traversal and its predecessors.
node_t
current_node
=
root_
;
node_t
parent_node
=
current_node
;
node_t
grandparent_node
=
current_node
;
// Index of the next byte to match in the key.
size_t
key_byte_index
=
0
;
// 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
)
{
for
(
j
=
0
;
j
<
current_node
.
prefix_length
()
&&
i
<
size
;
++
j
,
++
i
)
{
if
(
current_node
.
prefix
()[
j
]
!=
key
[
i
])
for
(
prefix_byte_index
=
0
;
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
;
}
// Even if a prefix of the key matches and we're doing a
// 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
)
{
i
=
size
;
key_byte_index
=
key_
size
;
break
;
}
// There was a mismatch or we've matched the whole key, so
// 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
;
// We need to match the rest of the key. Check if there's an
// outgoing edge from this node.
node
next_node
=
current_node
;
for
(
size_t
k
=
0
;
k
<
current_node
.
edgecount
();
++
k
)
{
if
(
current_node
.
first_byte_at
(
k
)
==
key
[
i
])
{
gp_edge_idx
=
edge_id
x
;
edge_i
dx
=
k
;
next_node
=
current_node
.
node_at
(
k
);
node
_t
next_node
=
current_node
;
for
(
size_t
i
=
0
;
i
<
current_node
.
edgecount
();
++
i
)
{
if
(
current_node
.
first_byte_at
(
i
)
==
key
[
key_byte_index
])
{
parent_edge_index
=
edge_inde
x
;
edge_i
ndex
=
i
;
next_node
=
current_node
.
node_at
(
i
);
break
;
}
}
...
...
@@ -262,27 +274,29 @@ match_result zmq::radix_tree::match (const unsigned char *key,
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
,
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
);
size_t
i
=
result
.
nkey
;
size_t
j
=
result
.
nprefix
;
size_t
edge_i
dx
=
result
.
edge_index
;
node
current_node
=
result
.
current_node
;
node
parent_node
=
result
.
parent_node
;
match_result
_t
match_result
=
match
(
key
,
key_
size
);
size_t
key_bytes_matched
=
match_result
.
key_bytes_matched
;
size_t
prefix_bytes_matched
=
match_result
.
prefix_bytes_matched
;
size_t
edge_i
ndex
=
match_
result
.
edge_index
;
node
_t
current_node
=
match_
result
.
current_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.
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
// create an edge from the current node to a new leaf node
// that has the rest of the key as the prefix.
node
key_node
=
make_node
(
1
,
size
-
i
,
0
);
key_node
.
set_prefix
(
key
+
i
);
node
_t
key_node
=
make_node
(
1
,
key_size
-
key_bytes_matched
,
0
);
key_node
.
set_prefix
(
key
+
key_bytes_matched
);
// Reallocate for one more edge.
current_node
.
resize
(
current_node
.
prefix_length
(),
...
...
@@ -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
// of node pointers one byte to the right. Since resize()
// increments the edgecount by 1, node_p
t
rs() tells us the
// increments the edgecount by 1, node_p
ointe
rs() tells us the
// destination address. The chunk of node pointers starts
// at one byte to the left of this destination.
//
// 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
*
));
// Add an edge to the new node.
current_node
.
set_edge_at
(
current_node
.
edgecount
()
-
1
,
key
[
i
],
key_node
);
current_node
.
set_edge_at
(
current_node
.
edgecount
()
-
1
,
key
[
key_bytes_matched
],
key
_node
);
// We need to update all pointers to the current node
// after the call to resize().
if
(
current_node
.
prefix_length
()
==
0
)
root_
.
data_
=
current_node
.
data_
;
else
parent_node
.
set_node_at
(
edge_i
d
x
,
current_node
);
parent_node
.
set_node_at
(
edge_i
nde
x
,
current_node
);
++
size_
;
return
true
;
}
...
...
@@ -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,
// and the other node will have the rest of the characters
// from the current node's prefix.
node
key_node
=
make_node
(
1
,
size
-
i
,
0
);
node
split_node
=
make_node
(
current_node
.
refcount
(),
current_node
.
prefix_length
()
-
j
,
node_t
key_node
=
make_node
(
1
,
key_size
-
key_bytes_matched
,
0
);
node_t
split_node
=
make_node
(
current_node
.
refcount
(),
current_node
.
prefix_length
()
-
prefix_bytes_matched
,
current_node
.
edgecount
());
// Copy the prefix chunks to the new nodes.
key_node
.
set_prefix
(
key
+
i
);
split_node
.
set_prefix
(
current_node
.
prefix
()
+
j
);
key_node
.
set_prefix
(
key
+
key_bytes_matched
);
split_node
.
set_prefix
(
current_node
.
prefix
()
+
prefix_bytes_matched
);
// Copy the current node's edges to the new node.
split_node
.
set_first_bytes
(
current_node
.
first_bytes
());
split_node
.
set_node_p
trs
(
current_node
.
node_pt
rs
());
split_node
.
set_node_p
ointers
(
current_node
.
node_pointe
rs
());
// Resize the current node to accommodate a prefix comprising
// the matched characters and 2 outgoing edges to the above
// nodes. Set the refcount to 0 since this node doesn't hold a
// key.
current_node
.
resize
(
j
,
2
);
current_node
.
resize
(
prefix_bytes_matched
,
2
);
current_node
.
set_refcount
(
0
);
// 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)
current_node
.
set_edge_at
(
1
,
split_node
.
prefix
()[
0
],
split_node
);
++
size_
;
parent_node
.
set_node_at
(
edge_i
d
x
,
current_node
);
parent_node
.
set_node_at
(
edge_i
nde
x
,
current_node
);
return
true
;
}
// 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
// from the current node's prefix match.
// Create a node that contains the rest of the characters from
// the current node's prefix and the outgoing edges from the
// current node.
node
split_node
=
make_node
(
current_node
.
refcount
(),
current_node
.
prefix_length
()
-
j
,
node_t
split_node
=
make_node
(
current_node
.
refcount
(),
current_node
.
prefix_length
()
-
prefix_bytes_matched
,
current_node
.
edgecount
());
split_node
.
set_prefix
(
current_node
.
prefix
()
+
j
);
split_node
.
set_prefix
(
current_node
.
prefix
()
+
prefix_bytes_matched
);
split_node
.
set_first_bytes
(
current_node
.
first_bytes
());
split_node
.
set_node_p
trs
(
current_node
.
node_pt
rs
());
split_node
.
set_node_p
ointers
(
current_node
.
node_pointe
rs
());
// Resize the current node to hold only the matched characters
// 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
// since this key wasn't inserted earlier. We don't need to
// set the prefix because the first
j bytes in the prefix are
// preserved by resize().
// set the prefix because the first
`prefix_bytes_matched` bytes
//
in the prefix are
preserved by resize().
current_node
.
set_edge_at
(
0
,
split_node
.
prefix
()[
0
],
split_node
);
current_node
.
set_refcount
(
1
);
++
size_
;
parent_node
.
set_node_at
(
edge_i
d
x
,
current_node
);
parent_node
.
set_node_at
(
edge_i
nde
x
,
current_node
);
return
true
;
}
zmq_assert
(
i
==
size
);
zmq_assert
(
j
==
current_node
.
prefix_length
());
zmq_assert
(
key_bytes_matched
==
key_
size
);
zmq_assert
(
prefix_bytes_matched
==
current_node
.
prefix_length
());
++
size_
;
current_node
.
set_refcount
(
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
);
size_t
i
=
result
.
nkey
;
size_t
j
=
result
.
nprefix
;
size_t
edge_i
dx
=
result
.
edge_index
;
size_t
gp_edge_idx
=
result
.
gp
_edge_index
;
node
current_node
=
result
.
current_node
;
node
parent_node
=
result
.
parent_node
;
node
grandparent_node
=
result
.
grandparent_node
;
match_result
_t
match_result
=
match
(
key
,
key_
size
);
size_t
key_bytes_matched
=
match_result
.
key_bytes_matched
;
size_t
prefix_bytes_matched
=
match_result
.
prefix_bytes_matched
;
size_t
edge_i
ndex
=
match_
result
.
edge_index
;
size_t
parent_edge_index
=
match_result
.
parent
_edge_index
;
node
_t
current_node
=
match_
result
.
current_node
;
node
_t
parent_node
=
match_
result
.
parent_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
)
return
false
;
...
...
@@ -419,7 +437,7 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t size)
if
(
outgoing_edges
==
1
)
{
// 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
// 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)
// Copy the rest of child node's data to the current node.
current_node
.
set_first_bytes
(
child
.
first_bytes
());
current_node
.
set_node_p
trs
(
child
.
node_pt
rs
());
current_node
.
set_node_p
ointers
(
child
.
node_pointe
rs
());
current_node
.
set_refcount
(
child
.
refcount
());
free
(
child
.
data_
);
parent_node
.
set_node_at
(
edge_i
d
x
,
current_node
);
parent_node
.
set_node_at
(
edge_i
nde
x
,
current_node
);
return
true
;
}
...
...
@@ -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.
// If the parent doesn't hold a key or if it isn't the root,
// we can merge it with its single child node.
zmq_assert
(
edge_i
d
x
<
2
);
node
other_child
=
parent_node
.
node_at
(
!
edge_id
x
);
zmq_assert
(
edge_i
nde
x
<
2
);
node
_t
other_child
=
parent_node
.
node_at
(
!
edge_inde
x
);
// Make room for the child node's prefix and edges. We need to
// 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)
// Copy the rest of child node's data to the current node.
parent_node
.
set_first_bytes
(
other_child
.
first_bytes
());
parent_node
.
set_node_p
trs
(
other_child
.
node_pt
rs
());
parent_node
.
set_node_p
ointers
(
other_child
.
node_pointe
rs
());
parent_node
.
set_refcount
(
other_child
.
refcount
());
free
(
current_node
.
data_
);
free
(
other_child
.
data_
);
grandparent_node
.
set_node_at
(
gp_edge_id
x
,
parent_node
);
grandparent_node
.
set_node_at
(
parent_edge_inde
x
,
parent_node
);
return
true
;
}
...
...
@@ -477,17 +495,18 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t size)
// parent.
zmq_assert
(
outgoing_edges
==
0
);
// Move the first byte and node pointer to the back of the byte
// and pointer chunks respectively.
size_t
last_idx
=
parent_node
.
edgecount
()
-
1
;
unsigned
char
last_byte
=
parent_node
.
first_byte_at
(
last_idx
);
node
last_ptr
=
parent_node
.
node_at
(
last_idx
);
parent_node
.
set_edge_at
(
edge_idx
,
last_byte
,
last_ptr
);
// Replace the edge to the current node with the last edge. An
// edge consists of a byte and a pointer to the next node. First
// replace the byte.
size_t
last_index
=
parent_node
.
edgecount
()
-
1
;
unsigned
char
last_byte
=
parent_node
.
first_byte_at
(
last_index
);
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
// deleting the last byte in the region of first bytes by
// overwriting it.
memmove
(
parent_node
.
node_p
trs
()
-
1
,
parent_node
.
node_pt
rs
(),
memmove
(
parent_node
.
node_p
ointers
()
-
1
,
parent_node
.
node_pointe
rs
(),
parent_node
.
edgecount
()
*
sizeof
(
void
*
));
// 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)
if
(
parent_node
.
prefix_length
()
==
0
)
root_
.
data_
=
parent_node
.
data_
;
else
grandparent_node
.
set_node_at
(
gp_edge_id
x
,
parent_node
);
grandparent_node
.
set_node_at
(
parent_edge_inde
x
,
parent_node
);
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
)
return
true
;
match_result
result
=
match
(
key
,
size
,
true
);
return
result
.
nkey
==
size
&&
result
.
nprefix
==
result
.
current_node
.
prefix_length
()
&&
result
.
current_node
.
refcount
()
>
0
;
match_result_t
match_result
=
match
(
key
,
key_size
,
true
);
return
match_result
.
key_bytes_matched
==
key_size
&&
match_result
.
prefix_bytes_matched
==
match_result
.
current_node
.
prefix_length
()
&&
match_result
.
current_node
.
refcount
()
>
0
;
}
static
void
visit_keys
(
node
n
,
visit_keys
(
node
_t
node
,
std
::
vector
<
unsigned
char
>
&
buffer
,
void
(
*
func
)
(
unsigned
char
*
data
,
size_t
size
,
void
*
arg
),
void
*
arg
)
{
for
(
size_t
i
=
0
;
i
<
n
.
prefix_length
();
++
i
)
buffer
.
push_back
(
n
.
prefix
()[
i
]);
for
(
size_t
i
=
0
;
i
<
n
ode
.
prefix_length
();
++
i
)
buffer
.
push_back
(
n
ode
.
prefix
()[
i
]);
if
(
n
.
refcount
()
>
0
)
{
if
(
n
ode
.
refcount
()
>
0
)
{
zmq_assert
(
!
buffer
.
empty
());
func
(
&
buffer
[
0
],
buffer
.
size
(),
arg
);
}
for
(
size_t
i
=
0
;
i
<
n
.
edgecount
();
++
i
)
visit_keys
(
n
.
node_at
(
i
),
buffer
,
func
,
arg
);
for
(
size_t
i
=
0
;
i
<
n
.
prefix_length
();
++
i
)
for
(
size_t
i
=
0
;
i
<
n
ode
.
edgecount
();
++
i
)
visit_keys
(
n
ode
.
node_at
(
i
),
buffer
,
func
,
arg
);
for
(
size_t
i
=
0
;
i
<
n
ode
.
prefix_length
();
++
i
)
buffer
.
pop_back
();
}
...
...
src/radix_tree.hpp
View file @
a43c842e
...
...
@@ -60,54 +60,55 @@
// 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
// of the chunk of first bytes and node pointers respectively.
struct
node
struct
node
_t
{
unsigned
char
*
data_
;
explicit
node
(
unsigned
char
*
data
);
explicit
node
_t
(
unsigned
char
*
data
);
bool
operator
==
(
node
other
)
const
;
bool
operator
!=
(
node
other
)
const
;
bool
operator
==
(
node
_t
other
)
const
;
bool
operator
!=
(
node
_t
other
)
const
;
inline
uint32_t
refcount
();
inline
uint32_t
prefix_length
();
inline
uint32_t
edgecount
();
inline
unsigned
char
*
prefix
();
inline
unsigned
char
*
first_bytes
();
inline
unsigned
char
first_byte_at
(
size_t
i
);
inline
unsigned
char
*
node_p
t
rs
();
inline
node
node_at
(
size_t
i
);
inline
unsigned
char
first_byte_at
(
size_t
i
ndex
);
inline
unsigned
char
*
node_p
ointe
rs
();
inline
node
_t
node_at
(
size_t
index
);
inline
void
set_refcount
(
uint32_t
value
);
inline
void
set_prefix_length
(
uint32_t
value
);
inline
void
set_edgecount
(
uint32_t
value
);
inline
void
set_prefix
(
const
unsigned
char
*
prefix
);
inline
void
set_first_bytes
(
const
unsigned
char
*
bytes
);
inline
void
set_first_byte_at
(
size_t
i
,
unsigned
char
byte
);
inline
void
set_node_ptrs
(
const
unsigned
char
*
ptrs
);
inline
void
set_node_at
(
size_t
i
,
node
n
);
inline
void
set_edge_at
(
size_t
i
,
unsigned
char
byte
,
node
n
);
inline
void
set_first_byte_at
(
size_t
index
,
unsigned
char
byte
);
inline
void
set_node_pointers
(
const
unsigned
char
*
pointers
);
inline
void
set_node_at
(
size_t
index
,
node_t
node
);
inline
void
set_edge_at
(
size_t
index
,
unsigned
char
first_byte
,
node_t
node
);
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
nprefix
;
size_t
key_bytes_matched
;
size_t
prefix_bytes_matched
;
size_t
edge_index
;
size_t
gp
_edge_index
;
node
current_node
;
node
parent_node
;
node
grandparent_node
;
size_t
parent
_edge_index
;
node
_t
current_node
;
node
_t
parent_node
;
node
_t
grandparent_node
;
match_result
(
size_t
i
,
size_t
j
,
match_result
_t
(
size_t
key_bytes_matched
,
size_t
prefix_bytes_matched
,
size_t
edge_index
,
size_t
gp
_edge_index
,
node
current
,
node
parent
,
node
grandparent
);
size_t
parent
_edge_index
,
node_t
current
,
node_t
parent
,
node_t
grandparent
);
};
namespace
zmq
...
...
@@ -120,26 +121,26 @@ class radix_tree
// Add key to the tree. Returns true if this was a new key rather
// 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 ac
ually
// Remove key from the tree. Returns true if
the item is act
ually
// 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.
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.
void
apply
(
void
(
*
func
)
(
unsigned
char
*
data_
,
size_t
size_
,
void
*
arg_
),
void
*
arg
);
void
apply
(
void
(
*
func
_
)
(
unsigned
char
*
data
,
size_t
size
,
void
*
arg
),
void
*
arg
_
);
size_t
size
()
const
;
private
:
inline
match_result
match
(
const
unsigned
char
*
key
,
size_t
size
,
bool
check
)
const
;
inline
match_result
_t
match
(
const
unsigned
char
*
key
,
size_t
key_size
,
bool
is_lookup
)
const
;
node
root_
;
node
_t
root_
;
size_t
size_
;
};
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment