-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmatch_tree.hpp
115 lines (88 loc) · 2.71 KB
/
match_tree.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
// Copyright (c) 2010 Roy Sharon <[email protected]>
// See project repositry at <https://github.com/roysharon/Uniclasser>
// Using this file is subject to the MIT License <http://creativecommons.org/licenses/MIT/>
#ifndef SEARCH_TREE_H
#define SEARCH_TREE_H
#include <vector>
#include <ostream>
#include <string>
#include "codevalue.hpp"
#include "predicate.hpp"
#define LASTBIT(t) ((t)1<<(CHAR_BIT*sizeof(t)-1))
#define TRIMMED(ptr) ((uintptr_t)(ptr)&MatchTree::Node::trimmed)
struct MatchTree
{
//----- Nodes -------------------------------------------------------------
struct Node
{
Node() : parent(0), on(0), off(0), pos(LASTBIT(codevalue)) {}
Node(Node *parent, bool on) : parent(parent), on(0), off(0), pos((parent->pos>>1)&(~parent->pos)) {}
~Node() {
removeOn();
removeOff();
}
void removeOn() { if (on != 0 && !TRIMMED(on)) delete on; on = 0; }
void removeOff() { if (off != 0 && !TRIMMED(off)) delete off; off = 0; }
int trimUp()
{
return (TRIMMED(on) && TRIMMED(off) && parent != 0) ? parent->trimDown(this) : 0;
}
int trimDown(Node *child)
{
int n = 0;
if (on == child) { delete on; on = (Node*)trimmed; --n; }
if (off == child) { delete off; off = (Node*)trimmed; --n; }
return n + trimUp();
}
int add(codevalue x)
{
int n = 0;
Node *&node = (x & pos) ? on : off;
if (TRIMMED(node)) return n;
if (node == 0 && pos != 1)
{
node = new Node(this, x & pos);
++n;
}
if (pos == 1) node = (Node*)trimmed;
else n += node->add(x);
n += trimUp();
return n;
}
int removeUp()
{
return (on == 0 && off == 0 && parent != 0) ? parent->removeDown(this) : 0;
}
int removeDown(Node *child)
{
int n = 0;
if (on == child) { removeOn(); --n; }
if (off == child) { removeOff(); --n; }
return n + removeUp();
}
codevalue pos;
Node *on;
Node *off;
Node *parent;
static const uintptr_t trimmed = LASTBIT(uintptr_t);
};
//----- MatchTree --------------------------------------------------------
MatchTree(codevalue_vector &list) : count(0)
{
codevalue last = -1;
for (codevalue_vector::iterator i = list.begin(), e = list.end(); i != e; ++i)
{
if (*i != last) // ignore duplicates
count += root.add(last = *i);
}
}
int create_predicate(IPredicate &predicate);
int create_predicate(IPredicate &predicate, Node* bottom, codevalue mask, codevalue val);
int prune_base(IPredicate &predicate, Node* &bottom, codevalue &mask, codevalue &val);
int prune_top(IPredicate &predicate, Node* &bottom, codevalue mask, codevalue val);
Node* check_branch(MatchTree::Node* bottom, codevalue &mask, codevalue &val);
void remove_trimmed_child(Node* node);
Node root;
int count;
};
#endif