forked from nblei/RHAMT
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinjector.hpp
155 lines (126 loc) · 5.46 KB
/
injector.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#ifndef _INJECTOR_HPP
#define _INJECTOR_HPP
#include "rhamt.hpp"
#include <stdexcept>
#include <cstdlib>
template<class Key, class T, unsigned FT, class HashType,
class Hash, class Pred, class Alloc>
class Injector {
using RHAMT = ReliableHAMT<Key, T, FT, HashType, Hash, Pred, Alloc>;
using Node = typename RHAMT::Node;
using SN = typename RHAMT::SplitNode;
using LN = typename RHAMT::LeafNode;
public:
RHAMT rhamt;
Injector() {
srand(time(NULL));
rhamt = RHAMT();
}
// Traverse to `depth` along path given by `hash` and swap the `first`
// and `second` child pointers (only the first duplicate) to test
// fast_traverse's ability to detect incorrect leaf node
void swap_children_local(const HashType hash, const int depth,
const unsigned first, const unsigned second);
// Traverse to `depth1` along path `hash1` and to `depth2` along path
// `hash2` and swap the `child`th pointer (first duplicate only) to test
// more severe structural mistakes (i.e. skipping levels)
void swap_children_other(const HashType hash1, const int depth1,
const HashType hash2, const int depth2,
unsigned child);
// Set the selected child pointer to the given value. If `val` is not
// specified, a random value is assinged. The first `count` duplicates
// will be overwritten
void set_child(const HashType hash, const int depth,
unsigned child, std::optional<void*> val,
unsigned count);
// Set the stored hash in the given leaf node to the provided value.
// If `val` is not set, use a random value. Overwrites the first `count`
// duplicates.
void set_hash(const HashType hash,
std::optional<HashType> val, unsigned count);
const T * insert(const Key& key, const T& val) {
return rhamt.insert(key, val);
}
int remove(const Key& key) {
return rhamt.remove(key);
}
const T * read(const Key& key) {
return rhamt.read(key);
}
};
template <class Key, class T, unsigned FT, class HashType, class Hash, class Pred, class Alloc>
void
Injector<Key, T, FT, HashType, Hash, Pred, Alloc>::
swap_children_local(const HashType hash, const int depth,
const unsigned first, const unsigned second)
{
if (first >= RHAMT::nchldrn || second >= RHAMT::nchldrn)
throw std::out_of_range("Child index must be < 32");
if (depth >= RHAMT::maxdepth)
throw std::out_of_range("Depth must be < maxdepth");
SN* curr_node = &rhamt._root;
for (int level = 0; level < depth; ++level) {
HashType shash = RHAMT::subhash(hash, level);
curr_node = reinterpret_cast<SN*>(curr_node->children[shash][0]);
}
std::swap(curr_node->children[first][0], curr_node->children[second][0]);
}
template <class Key, class T, unsigned FT, class HashType, class Hash, class Pred, class Alloc>
void
Injector<Key, T, FT, HashType, Hash, Pred, Alloc>::
swap_children_other(const HashType hash1, const int depth1,
const HashType hash2, const int depth2,
const unsigned child)
{
if (child >= RHAMT::nchldrn)
throw std::out_of_range("Child index must be < 32");
if (depth1 >= RHAMT::maxdepth || depth2 >= RHAMT::maxdepth)
throw std::out_of_range("Depth must be < maxdepth");
SN* curr_node_a = &rhamt._root;
for (int level = 0; level < depth1; ++level) {
HashType shash = RHAMT::subhash(hash1, level);
curr_node_a = reinterpret_cast<SN*>(curr_node_a->children[shash][0]);
}
SN* curr_node_b = &rhamt._root;
for (int level = 0; level < depth2; ++level) {
HashType shash = RHAMT::subhash(hash2, level);
curr_node_b = reinterpret_cast<SN*>(curr_node_b->children[shash][0]);
}
std::swap(curr_node_a->children[child][0], curr_node_b->children[child][0]);
}
template <class Key, class T, unsigned FT, class HashType, class Hash, class Pred, class Alloc>
void
Injector<Key, T, FT, HashType, Hash, Pred, Alloc>::
set_child(const HashType hash, const int depth, unsigned child,
std::optional<void*> val, unsigned count)
{
if (child >= RHAMT::nchldrn)
throw std::out_of_range("Child index must be < 32");
if (depth >= RHAMT::maxdepth)
throw std::out_of_range("Depth must be < maxdepth");
SN* curr_node = &rhamt._root;
for (int level = 0; level < depth; ++level) {
HashType shash = RHAMT::subhash(hash, level);
curr_node = reinterpret_cast<SN*>(curr_node->children[shash][0]);
}
Node* rand_ptr = reinterpret_cast<Node*>(rand());
for (unsigned i = 0; i < count; ++i)
curr_node->children[child][i] = (Node*)val.value_or(rand_ptr);
}
template <class Key, class T, unsigned FT, class HashType, class Hash, class Pred, class Alloc>
void
Injector<Key, T, FT, HashType, Hash, Pred, Alloc>::
set_hash(const HashType hash, std::optional<HashType> val,
unsigned count)
{
int level = 0;
SN* curr_node = &rhamt._root;
for (int level = 0; level < RHAMT::maxdepth; ++level) {
HashType shash = RHAMT::subhash(hash, level);
curr_node = reinterpret_cast<SN*>(curr_node->children[shash][0]);
}
HashType rand_hash = (HashType)rand();
for (int i = 0; i < count; ++i)
reinterpret_cast<LN*>(curr_node)->hash[i] = val.value_or(rand_hash);
}
#endif // _INJECTOR_HPP