OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
patricia.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #ifndef PATRICIA_H
6 #define PATRICIA_H
7 
8 #include <string>
9 #include <cstring>
10 #include <boost/intrusive/detail/parent_from_member.hpp>
11 #include <boost/iterator/iterator_facade.hpp>
12 
13 #define IS_INT_NODE(node) (node->intnode_)
14 
15 namespace Patricia {
16 class Node {
17 public:
18  Node() {
19  left_ = NULL;
20  right_ = NULL;
21  intnode_ = false;
22  bitpos_ = 0;
23  }
24 
27  bool intnode_;
28  std::size_t bitpos_;
29 };
30 
31 class TreeBase {
32 public:
34  root_ = NULL;
35  nodes_ = 0;
36  int_nodes_ = 0;
37  }
38 
39  int nodes_;
42 };
43 
44 template <class D, Node D::* P, class K>
45 class Tree : private TreeBase {
46 public:
47  Tree() : TreeBase() {
48  }
49 
50  class Iterator : public boost::iterator_facade<Iterator,
51  D *,
52  boost::forward_traversal_tag,
53  D *> {
54  public:
55  Iterator() : data_(NULL) {}
56  explicit Iterator(Tree<D, P, K> *tree, D *data) : tree_(tree), data_(data) {
57  }
58 
59  private:
61 
62  void increment() {
63  data_ = tree_->GetNext(data_);
64  }
65  bool equal(const Iterator &it) const {
66  return data_ == it.data_;
67  }
68  D * dereference() const {
69  return data_;
70  }
72  D *data_;
73  };
74 
75  Iterator begin() {
76  return Iterator(this, GetNext(NULL));
77  }
78 
79  Iterator end() {
80  return Iterator();
81  }
82 
83  Iterator LowerBound(D * data) {
84  return Iterator(this, FindNext(data));
85  }
86 
87  std::size_t Size() {
88  return nodes_;
89  }
90 
91  bool Insert(D * data) {
92  return InsertNode(DataToNode(data));
93  }
94 
95  bool Remove(D * data) {
96  return RemoveNode(DataToNode(data));
97  }
98 
99  D * Find(const D * data) {
100  return NodeToData(FindNode(DataToNode(data)));
101  }
102 
103  D * FindNext(const D * data) {
104  return NodeToData(FindNextNode(DataToNode(data)));
105  }
106 
107  D * LPMFind(const D * data) {
108  return NodeToData(FindBestMatchNode(DataToNode(data)));
109  }
110 
111  D * GetNext(D * data) {
112  return NodeToData(GetNextNode(DataToNode(data)));
113  }
114 
115  D * GetPrev(const D * data) {
116  return NodeToData(GetPrevNode(DataToNode(data)));
117  }
118 
119  D * GetLast() {
120  return NodeToData(GetLastNode());
121  }
122 
123 private:
124  const Node *DataToNode (const D * data) {
125  if (data) {
126  return static_cast<const Node *>(&(data->*P));
127  } else {
128  return NULL;
129  }
130  }
131 
132  Node *DataToNode (D * data) {
133  if (data) {
134  return static_cast<Node *>(&(data->*P));
135  } else {
136  return NULL;
137  }
138  }
139 
140  const D *NodeToData (const Node * node) {
141  if (node) {
142  return boost::intrusive::detail::parent_from_member<D, Node>(node, P);
143  } else {
144  return NULL;
145  }
146  }
147 
148  D *NodeToData (Node * node) {
149  if (node) {
150  return boost::intrusive::detail::parent_from_member<D, Node>(node, P);
151  } else {
152  return NULL;
153  }
154  }
155 
156  bool InsertNode(Node *node) {
157  Node * p, * x, *l;
158 
159  // Start at the root_
160  p = NULL;
161  x = root_;
162  while (x) {
163  if (x->bitpos_ >= K::BitLength(NodeToData(node)) && !IS_INT_NODE(x)) {
164  break;
165  }
166  p = x;
167  x = GetBit(node, x->bitpos_) ? x->right_ : x->left_;
168  if (x && (p->bitpos_ >= x->bitpos_)) {
169  /* no x to deal with */
170  x = NULL;
171  break;
172  }
173  }
174 
175  std::size_t i = 0;
176  l = x ? x : p;
177  // Find the first bit that does not match.
178  if (l) {
179  /* if l is internal node pick the left_ node to compare */
180  if (Compare(node, l, 0, i)) {
181  // The key already exists
182  return false;
183  }
184 
185  if (i != K::BitLength(NodeToData(node)) || i != l->bitpos_) {
186  p = NULL;
187  x = root_;
188  while (x && x->bitpos_ <= i && x->bitpos_ < K::BitLength(NodeToData(node))) {
189  p = x;
190  x = GetBit(node, x->bitpos_) ? x->right_ : x->left_;
191  if (x && (p->bitpos_ >= x->bitpos_)) {
192  /* no x to deal with */
193  x = NULL;
194  break;
195  }
196  }
197  }
198  }
199 
200  nodes_++;
201  node->left_ = NULL;
202  node->right_ = NULL;
203  node->bitpos_ = K::BitLength(NodeToData(node));;
204 
205  if (x) {
206  if (x->bitpos_ == i) {
207  /* has to be an internal node */
208  node->right_ = x->right_;
209  node->left_ = x->left_;
210  /* rightmost guy of the left_ subtree will be pointing to x that needs to point to node now. */
211  //node->right_ = RewireRightMost(node, x->left_);
212  RewireRightMost(node, x->left_);
213  delete x;
214  int_nodes_--;
215  l = node;
216  } else {
217  /* key BitLength of x has to be greater than node key BitLength */
218  if (i == K::BitLength(NodeToData(node))) {
219  if (GetBit(l, i)) {
220  node->right_ = x;
221  } else {
222  node->left_ = x;
223  /* right_ most node of the left_ sub tree should point to node */
224  node->right_ = RewireRightMost(node, x);
225  }
226  l = node;
227  } else {
228  /* allocate internal node */
229  l = new Node;
230  int_nodes_++;
231  l->bitpos_ = i;
232  l->intnode_ = true;
233  if (GetBit(node, i)) {
234  l->left_ = x;
235  l->right_ = node;
236  /* right_ most node of the left_ sub tree should point to l */
237  node->right_ = RewireRightMost(l, x);
238  } else {
239  l->left_ = node;
240  l->right_ = x;
241  node->right_ = l;
242  }
243  }
244  }
245  } else {
246  if (p) {
247  if (GetBit(node, p->bitpos_)) {
248  node->right_ = p->right_;
249  } else {
250  node->right_ = p;
251  }
252  }
253  l = node;
254  }
255 
256  if (p) {
257  if (GetBit(node, p->bitpos_)) {
258  p->right_ = l;
259  } else {
260  p->left_ = l;
261  }
262  } else {
263  root_ = l;
264  }
265 
266  return true;
267  }
268 
269  bool RemoveNode(Node * node) {
270  Node * pPrev = NULL;
271  Node * p = NULL;
272  Node * x = root_;
273 
274  while (x) {
275  if (x->bitpos_ > K::BitLength(NodeToData(node))) {
276  x = NULL;
277  break;
278  } else if (x->bitpos_ == K::BitLength(NodeToData(node)) && !IS_INT_NODE(x)) {
279  break;
280  }
281  pPrev = p;
282  p = x;
283  x = GetBit(node, x->bitpos_) ? x->right_ : x->left_;
284  if (x && (p->bitpos_ >= x->bitpos_)) {
285  /* no x to deal with */
286  x = NULL;
287  break;
288  }
289  }
290 
291  if(!x || !Compare(node, x)){
292  return false;
293  }
294 
295  Node * t = NULL;
296 
297  if (x->left_ && x->right_ && x->bitpos_ < x->right_->bitpos_) {
298  /* need to allocate internal node to replace the going node */
299  t = new Node;
300  t->bitpos_ = x->bitpos_;
301  t->intnode_ = true;
302  int_nodes_++;
303  t->left_ = x->left_;
304  t->right_ = x->right_;
305  RewireRightMost(t, x->left_);
306  if (!p) {
307  root_ =t ;
308  } else if (GetBit(x, p->bitpos_)) {
309  p->right_ = t;
310  } else {
311  p->left_ = t;
312  }
313  } else if (x->left_) {
314  if (!p) {
315  root_ = x->left_;
316  } else if (GetBit(x, p->bitpos_)) {
317  p->right_ = x->left_;
318  } else {
319  p->left_ = x->left_;
320  }
321  RewireRightMost(x->right_, x->left_);
322  } else if (x->right_ && x->bitpos_ < x->right_->bitpos_) {
323  if (!p) {
324  root_ = x->right_;
325  } else if (GetBit(x, p->bitpos_)) {
326  p->right_ = x->right_;
327  } else {
328  p->left_ = x->right_;
329  }
330  } else {
331  if (!p) {
332  root_ = NULL;
333  } else if (IS_INT_NODE(p)) {
334  if (GetBit(x, p->bitpos_)){
335  t = p->left_;
336  //RewireRightMost((pPrev->left_ == p) ? pPrev : NULL, t);
337  RewireRightMost(x->right_, t);
338  } else {
339  t = p->right_;
340  }
341  if (!pPrev) {
342  root_ = t;
343  } else if (GetBit(x, pPrev->bitpos_)) {
344  pPrev->right_ = t;
345  } else {
346  pPrev->left_ = t;
347  }
348  delete p;
349  int_nodes_--;
350  } else {
351  if (GetBit(x, p->bitpos_)) {
352  p->right_ = x->right_;
353  } else {
354  p->left_ = NULL;
355  }
356  }
357  }
358 
359  nodes_--;
360  node->left_ = NULL;
361  node->right_ = NULL;
362  return true;
363  }
364 
365  Node * FindNode(const Node * node) {
366  Node * p, * x;
367 
368  p = NULL;
369  x = root_;
370  while (x) {
371  if (x->bitpos_ > K::BitLength(NodeToData(node))) {
372  x = NULL;
373  break;
374  } else if (x->bitpos_ == K::BitLength(NodeToData(node)) && !IS_INT_NODE(x)) {
375  break;
376  }
377  p = x;
378  x = GetBit(node, x->bitpos_) ? x->right_ : x->left_;
379  if (x && (p->bitpos_ >= x->bitpos_)) {
380  /* no x to deal with */
381  x = NULL;
382  break;
383  }
384  }
385 
386  if(!x || !Compare(node, x)){
387  return NULL;
388  }
389 
390  return x;
391  }
392 
393  Node * FindNextNode(const Node * node) {
394  Node * p, * x, *l;
395  std::size_t i = 0;
396 
397  p = NULL;
398  l = NULL;
399  x = root_;
400  while (x) {
401  if (!IS_INT_NODE(x)) {
402  if (Compare(node, x, i, i)) {
403  return GetNextNode(x);
404  }
405  if (x->bitpos_ > K::BitLength(NodeToData(node)) || i != x->bitpos_) {
406  break;
407  }
408  l = x;
409  }
410  p = x;
411  x = GetBit(node, x->bitpos_) ? x->right_ : x->left_;
412  if (x && (p->bitpos_ >= x->bitpos_)) {
413  break;
414  }
415  }
416 
417  if (l) {
418  x = l;
419  while (x && x->bitpos_ <= i) {
420  l = x;
421  x = GetBit(node, x->bitpos_) ? x->right_ : x->left_;
422  if (x && (l->bitpos_ >= x->bitpos_)) {
423  break;
424  }
425  }
426  if (K::BitLength(NodeToData(node)) != l->bitpos_) {
427  if (GetBit(node, l->bitpos_)) {
428  if (!x) {
429  return NULL;
430  }
431  if (l->bitpos_ > x->bitpos_) {
432  while (x && l->bitpos_ > x->bitpos_) {
433  l = x;
434  x = x->right_;
435  }
436  l = x;
437  } else if (GetBit(node, i)) {
438  /* x is on left */
439  while (x->right_ &&
440  x->bitpos_ < x->right_->bitpos_) {
441  x = x->right_;
442  }
443  l = x;
444  x = x->right_;
445  while (x && l->bitpos_ > x->bitpos_) {
446  l = x;
447  x = x->right_;
448  }
449  l = x;
450  } else {
451  l = x;
452  }
453  } else {
454  if (!x || GetBit(node, i)) {
455  x = l->right_;
456  while (x && l->bitpos_ > x->bitpos_) {
457  l = x;
458  x = x->right_;
459  }
460  l = x;
461  } else {
462  l = x;
463  }
464  }
465 
466  if (x && !IS_INT_NODE(x)) {
467  return x;
468  }
469  }
470  return GetNextNode(l);
471  } else {
472  if (!GetBit(node, i)) {
473  /* all elements of the tree are on right */
474  return x;
475  }
476  }
477 
478  return NULL;
479  }
480 
481  Node * FindBestMatchNode(const Node * node) {
482  Node * p, * x, *l;
483  std::size_t i = 0;
484 
485  l = NULL;
486  p = NULL;
487  x = root_;
488  while (x) {
489  if (!IS_INT_NODE(x)) {
490  if (Compare(node, x, i, i)) {
491  return x;
492  }
493  if (i == x->bitpos_) {
494  l = x;
495  }
496  }
497  if (x->bitpos_ > K::BitLength(NodeToData(node))) {
498  break;
499  }
500  p = x;
501  x = GetBit(node, x->bitpos_) ? x->right_ : x->left_;
502  if (x && (p->bitpos_ >= x->bitpos_)) {
503  break;
504  }
505  }
506 
507  return l;
508  }
509 
510  Node * GetNextNode(Node * node) {
511  Node *x, *l;
512 
513  if (!root_) {
514  return NULL;
515  }
516 
517  x = root_;
518  if (node || IS_INT_NODE(x)) {
519  if (node) {
520  x = node;
521  }
522  l = x;
523  while (x) {
524  if (x->bitpos_ < l->bitpos_) {
525  l = x;
526  x = l->right_;
527  } else {
528  l = x;
529  x = l->left_ ? l->left_ : l->right_;
530  }
531  if (x && x->bitpos_ > l->bitpos_ &&
532  !IS_INT_NODE(x)) {
533  break;
534  }
535  }
536  }
537 
538  return x;
539  }
540 
541  Node * GetPrevNode(const Node * node) {
542  Node * p, * x, *l, *r, *right_turn, *greatest_partial;
543 
544  p = NULL;
545  l = NULL;
546  x = root_;
547  right_turn = NULL;
548  greatest_partial = NULL;
549  while (x) {
550  if (x->bitpos_ > K::BitLength(NodeToData(node))) {
551  x = NULL;
552  break;
553  } else if (x->bitpos_ == K::BitLength(NodeToData(node)) && !IS_INT_NODE(x)) {
554  break;
555  }
556  p = x;
557  if (GetBit(node, x->bitpos_)) {
558  right_turn = x;
559  x = x->right_;
560  } else {
561  if (!IS_INT_NODE(x)) {
562  greatest_partial = x;
563  }
564  x = x->left_;
565  }
566  if (x && (p->bitpos_ >= x->bitpos_)) {
567  x = NULL;
568  break;
569  }
570  }
571 
572  if (!x || !Compare(node, x)) {
573  return NULL;
574  }
575 
576  if (right_turn && greatest_partial) {
577  if (greatest_partial->bitpos_ > right_turn->bitpos_) {
578  return greatest_partial;
579  }
580  }
581 
582  if (!right_turn) {
583  return greatest_partial;
584  }
585 
586  x = right_turn->left_;
587  while (x) {
588  l = x->left_;
589  r = x->right_;
590  if (r && r->bitpos_ > x->bitpos_) {
591  x = r;
592  } else if (l) {
593  x = l;
594  } else {
595  return x;
596  }
597  }
598 
599  return x;
600  }
601 
603  Node *x;
604 
605  if (!root_) {
606  return NULL;
607  }
608 
609  x = root_;
610  while (x) {
611  if (x->right_) {
612  if (x->right_->bitpos_ < x->bitpos_) {
613  if (!x->left_) {
614  return x;
615  }
616  x = x->left_;
617  } else {
618  x = x->right_;
619  }
620  } else {
621  if (!x->left_) {
622  return x;
623  }
624  x = x->left_;
625  }
626  }
627 
628  return x;
629  }
630 
631  bool GetBit(const Node * node, std::size_t pos) {
632  const D * data = NodeToData(node);
633  if (pos >= K::BitLength(data)) {
634  return false;
635  }
636 
637  return K::ByteValue(data, pos >> 3) & (0x80 >> (pos & 7));
638  }
639 
640  bool Compare(const Node *node_left, const Node *node_right) {
641  const D * data_left = NodeToData(node_left);
642  const D * data_right = NodeToData(node_right);
643  if (K::BitLength(data_left) != K::BitLength(data_right)) {
644  return false;
645  }
646 
647  std::size_t byteLen = K::BitLength(data_left) >> 3;
648  std::size_t pos;
649 
650  for (pos = 0; pos < byteLen; ++pos) {
651  if (K::ByteValue(data_left, pos) != K::ByteValue(data_right, pos)) {
652  return false;
653  }
654  }
655 
656  for (pos <<= 3; pos < K::BitLength(data_left); ++pos) {
657  if (GetBit(node_left, pos) != GetBit(node_right, pos)) {
658  return false;
659  }
660  }
661 
662  return true;
663  }
664 
665  bool Compare(const Node *node_left, const Node *node_right, std::size_t start, std::size_t& pos) {
666  const D * data_left = NodeToData(node_left);
667  const D * data_right = NodeToData(node_right);
668  std::size_t shortLen;
669 
670  bool isEqual;
671 
672  if (K::BitLength(data_left) < K::BitLength(data_right)) {
673  shortLen = K::BitLength(data_left);
674  isEqual = false;
675  } else {
676  shortLen = K::BitLength(data_right);
677  isEqual = (K::BitLength(data_left) == K::BitLength(data_right));
678  }
679 
680  std::size_t byteLen = shortLen >> 3;
681 
682  for (pos = start >> 3; pos < byteLen; ++pos) {
683  if (K::ByteValue(data_left, pos) != K::ByteValue(data_right, pos)) {
684  break;
685  }
686  }
687 
688  pos <<= 3;
689  if (pos < start) {
690  pos = start;
691  }
692 
693  for (; pos < shortLen; ++pos) {
694  if (GetBit(node_left, pos) != GetBit(node_right, pos)) {
695  return false;
696  }
697  }
698 
699  return isEqual;
700  }
701 
703  Node *pRight;
704  if (!x) {
705  return NULL;
706  }
707 
708  while (x->right_ && x->right_->bitpos_ > x->bitpos_) {
709  x = x->right_;
710  }
711  pRight = x->right_;
712  x->right_ = p;
713  return pRight;
714  }
715 
716 
717 };
718 
719 };
720 
721 #endif /* PATRICIA_H */
722 
D * GetNext(D *data)
Definition: patricia.h:111
bool intnode_
Definition: patricia.h:27
bool RemoveNode(Node *node)
Definition: patricia.h:269
Iterator end()
Definition: patricia.h:79
D * GetPrev(const D *data)
Definition: patricia.h:115
std::size_t bitpos_
Definition: patricia.h:28
bool InsertNode(Node *node)
Definition: patricia.h:156
Iterator LowerBound(D *data)
Definition: patricia.h:83
bool equal(const Iterator &it) const
Definition: patricia.h:65
Node * right_
Definition: patricia.h:26
#define IS_INT_NODE(node)
Definition: patricia.h:13
Node * RewireRightMost(Node *p, Node *x)
Definition: patricia.h:702
Node * FindNode(const Node *node)
Definition: patricia.h:365
D * NodeToData(Node *node)
Definition: patricia.h:148
Node * GetNextNode(Node *node)
Definition: patricia.h:510
D * dereference() const
Definition: patricia.h:68
Node * left_
Definition: patricia.h:25
Node * FindBestMatchNode(const Node *node)
Definition: patricia.h:481
friend class boost::iterator_core_access
Definition: patricia.h:60
D * LPMFind(const D *data)
Definition: patricia.h:107
bool GetBit(const Node *node, std::size_t pos)
Definition: patricia.h:631
Node * FindNextNode(const Node *node)
Definition: patricia.h:393
D * FindNext(const D *data)
Definition: patricia.h:103
bool Compare(const Node *node_left, const Node *node_right)
Definition: patricia.h:640
Iterator begin()
Definition: patricia.h:75
std::size_t Size()
Definition: patricia.h:87
Node * GetPrevNode(const Node *node)
Definition: patricia.h:541
Node * DataToNode(D *data)
Definition: patricia.h:132
Iterator(Tree< D, P, K > *tree, D *data)
Definition: patricia.h:56
const Node * DataToNode(const D *data)
Definition: patricia.h:124
bool Compare(const Node *node_left, const Node *node_right, std::size_t start, std::size_t &pos)
Definition: patricia.h:665
D * Find(const D *data)
Definition: patricia.h:99
Node * GetLastNode()
Definition: patricia.h:602
const D * NodeToData(const Node *node)
Definition: patricia.h:140
Tree< D, P, K > * tree_
Definition: patricia.h:71
bool Remove(D *data)
Definition: patricia.h:95
D * GetLast()
Definition: patricia.h:119
bool Insert(D *data)
Definition: patricia.h:91