libDwm-0.6.0
DwmPatricia.hh
Go to the documentation of this file.
1 /* ex: set tabstop=2 expandtab: */
2 //===========================================================================
3 // @(#) $DwmPath: dwm/libDwm/tags/libDwm-0.6.0/include/DwmPatricia.hh 8401 $
4 // @(#) $Id: DwmPatricia.hh 8401 2016-04-17 06:44:31Z dwm $
5 //===========================================================================
6 // Copyright (c) Daniel W. McRobb 2006-2007
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions
11 // are met:
12 //
13 // 1. Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 // 2. Redistributions in binary form must reproduce the above copyright
16 // notice, this list of conditions and the following disclaimer in the
17 // documentation and/or other materials provided with the distribution.
18 // 3. The names of the authors and copyright holders may not be used to
19 // endorse or promote products derived from this software without
20 // specific prior written permission.
21 //
22 // IN NO EVENT SHALL DANIEL W. MCROBB BE LIABLE TO ANY PARTY FOR
23 // DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
24 // INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE,
25 // EVEN IF DANIEL W. MCROBB HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
26 // DAMAGE.
27 //
28 // THE SOFTWARE PROVIDED HEREIN IS ON AN "AS IS" BASIS, AND
29 // DANIEL W. MCROBB HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
30 // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. DANIEL W. MCROBB MAKES NO
31 // REPRESENTATIONS AND EXTENDS NO WARRANTIES OF ANY KIND, EITHER
32 // IMPLIED OR EXPRESS, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 // WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE,
34 // OR THAT THE USE OF THIS SOFTWARE WILL NOT INFRINGE ANY PATENT,
35 // TRADEMARK OR OTHER RIGHTS.
36 //===========================================================================
37 
38 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
42 
43 #ifndef _PATRICIA_HH_
44 #define _PATRICIA_HH_
45 
46 extern "C" {
47  #include <stdlib.h>
48 }
49 
50 #include <algorithm>
51 #include <iostream>
52 #include <vector>
53 
54 #include "DwmIO.hh"
55 #include "DwmReadable.hh"
56 #include "DwmWritable.hh"
57 #include "DwmGZReadable.hh"
58 #include "DwmGZWritable.hh"
59 #include "DwmBZ2Readable.hh"
60 #include "DwmBZ2Writable.hh"
61 
62 namespace Dwm {
63 
64  //--------------------------------------------------------------------------
66  //--------------------------------------------------------------------------
67  template <typename KeyType>
68  inline int GetBit(const KeyType & key, int bit)
69  {
70  if (bit < 0)
71  return(2);
72  if ((unsigned int)bit < sizeof(KeyType) * 8) {
73  const uint8_t *p = (const uint8_t *)(&key);
74  return(((p[bit >> 3]) >> (7 - (bit & 0x7))) & 0x1);
75  }
76  return(0);
77  }
78 
79  //--------------------------------------------------------------------------
81  //--------------------------------------------------------------------------
82  template <typename KeyType>
83  inline int BitFirstDifferent(const KeyType & key1, const KeyType & key2)
84  {
85  unsigned int n = 0;
86  int d = 0;
87  const uint8_t *p1 = (const uint8_t *)&key1;
88  const uint8_t *p2 = (const uint8_t *)&key2;
89  for ( ; n < sizeof(KeyType); ++n) {
90  if (p1[n] != p2[n])
91  break;
92  }
93  if (n == sizeof(KeyType)) {
94  return(sizeof(KeyType) * 8);
95  }
96  else {
97  while (GetBit<uint8_t>(p1[n], d) == GetBit<uint8_t>(p2[n], d) && d < 8)
98  d++;
99  return ((n << 3) + d);
100  }
101  }
102 
103  template <typename KeyType>
104  inline bool IsMatch(const KeyType & key1, const KeyType & key2)
105  {
106  return(key2 == key1);
107  }
108 
109  //--------------------------------------------------------------------------
111  //--------------------------------------------------------------------------
112  template <typename KeyType, typename ValueType,
113  typename KeyEqual> class Patricia;
114 
115  //------------------------------------------------------------------------
118  //------------------------------------------------------------------------
119  template <typename KeyType, typename ValueType>
121  {
122  public:
123  //------------------------------------------------------------------------
125  //------------------------------------------------------------------------
127  : _bitIndex(-1), _key(), _data()
128  {
129  _left = this;
130  _right = this;
131  }
132 
133  PatriciaNode(const PatriciaNode & pn)
134  {
135  _key = pn._key;
136  _data = pn._data;
137  _bitIndex = pn._bitIndex;
138  if (pn._left != & pn)
139  _left = new PatriciaNode<KeyType,ValueType>(pn._left);
140  else
141  _left = this;
142  if (pn.right != &pn)
143  _right = new PatriciaNode<KeyType,ValueType>(pn._right);
144  else
145  _right = this;
146  }
147 
149  {
150  if (&pn != this) {
151  _key = pn._key;
152  _data = pn._data;
153  _bitIndex = pn._bitIndex;
154  if (pn._left != & pn)
155  _left = new PatriciaNode<KeyType,ValueType>(pn._left);
156  else
157  _left = this;
158  if (pn.right != &pn)
159  _right = new PatriciaNode<KeyType,ValueType>(pn._right);
160  else
161  _right = this;
162  }
163  return(*this);
164  }
165 
166  //------------------------------------------------------------------------
168  //------------------------------------------------------------------------
169  PatriciaNode(const KeyType & key, const ValueType & data, int bitIdx,
172  : _bitIndex(bitIdx), _key(key), _data(data), _left(left), _right(right)
173  {
174  }
175 
176  //------------------------------------------------------------------------
178  //------------------------------------------------------------------------
180  {
181  }
182 
183  //------------------------------------------------------------------------
185  //------------------------------------------------------------------------
186  void Initialize(const KeyType & key,
187  const ValueType & data,
188  int bitIdx,
191  {
192  _key = key;
193  _data = data;
194  _bitIndex = bitIdx;
195  _left = left;
196  _right = right;
197  }
198 
199  //------------------------------------------------------------------------
201  //------------------------------------------------------------------------
202  ValueType & GetData()
203  {
204  return(_data);
205  }
206 
207  //------------------------------------------------------------------------
209  //------------------------------------------------------------------------
210  bool SetData(const ValueType & data)
211  {
212  _data = data;
213  return(true);
214  }
215 
216  //------------------------------------------------------------------------
218  //------------------------------------------------------------------------
219  KeyType GetKey() const
220  {
221  return(_key);
222  }
223 
224  //------------------------------------------------------------------------
226  //------------------------------------------------------------------------
228  {
229  return(_left);
230  }
231 
232  //------------------------------------------------------------------------
234  //------------------------------------------------------------------------
236  {
237  return(_right);
238  }
239 
240  //------------------------------------------------------------------------
242  //------------------------------------------------------------------------
243  uint32_t StreamedLength() const
244  {
245  return(IO::StreamedLength(_key) + IO::StreamedLength(_data));
246  }
247 
248  //------------------------------------------------------------------------
250  //------------------------------------------------------------------------
251  bool operator == (const PatriciaNode<KeyType,ValueType> & n) const
252  {
253  return((_key == n._key) && (_data == n._data));
254  }
255 
256  private:
257  friend class Patricia<KeyType, ValueType, std::equal_to<KeyType> >;
258  int _bitIndex;
259  KeyType _key;
260  ValueType _data;
261  PatriciaNode<KeyType,ValueType> *_left;
262  PatriciaNode<KeyType,ValueType> *_right;
263  };
264 
265 
266  class __PatriciaIterator__
267  {};
268 
269  //------------------------------------------------------------------------
272  //------------------------------------------------------------------------
273  template <typename KeyType, typename ValueType,
274  typename KeyEqual = std::equal_to<KeyType> >
275  class Patricia
276  : public Readable, public Writable,
277  public GZReadable, public GZWritable,
278  public BZ2Readable, public BZ2Writable
279  {
280  public:
281  //------------------------------------------------------------------------
283  //------------------------------------------------------------------------
285  {
286  // Create the head of the structure. The head is never moved
287  // around in the trie (i.e. it always stays at the top of the structure).
288  // This prevents further complications having to do with node removal.
289  _head = new PatriciaNode<KeyType,ValueType>();
290  _size = 0;
291  }
292 
293  //------------------------------------------------------------------------
295  //------------------------------------------------------------------------
297  {
298  RecursiveRemove(_head);
299  delete(_head);
300  }
301 
302  //------------------------------------------------------------------------
304  //------------------------------------------------------------------------
305  uint32_t Size() const
306  {
307  return(_size);
308  }
309 
310  //------------------------------------------------------------------------
312  //------------------------------------------------------------------------
313  void Clear()
314  {
315  RecursiveRemove(_head);
316  _head->_left = _head;
317  _head->_right = _head;
318  }
319 
320  //------------------------------------------------------------------------
323  //------------------------------------------------------------------------
325  Insert(const KeyType & key, const ValueType & data)
326  {
327  // Start at the root of the trie
328  PatriciaNode<KeyType,ValueType> *prev = _head;
329  PatriciaNode<KeyType,ValueType> *last = _head->_right;
330 
331  // Navigate down the trie and look for the key
332  while (prev->_bitIndex < last->_bitIndex) {
333  prev = last;
334  last = (bit_get(key, last->_bitIndex) ? last->_right : last->_left);
335  }
336 
337  if (key_compare(key, last->_key))
338  return(last); // key is already in the trie
339 
340  // Find the first bit that does not match.
341  int i = BitFirstDifferent<KeyType>(key, last->_key);
342 
343  // Find the place in the trie to insert the new node
344  prev = _head;
345  last = prev->_right;
346  while ((prev->_bitIndex < last->_bitIndex) && (last->_bitIndex < i)) {
347  prev = last;
348  last = (bit_get(key, last->_bitIndex) ? last->_right : last->_left);
349  }
350 
351  // create new node
354  node->Initialize(key, data, i,
355  (bit_get(key, i) ? last : node),
356  (bit_get(key, i) ? node : last));
357 
358  // Rewire the parent node's branch
359  if (bit_get(key, prev->_bitIndex))
360  prev->_right = node;
361  else
362  prev->_left = node;
363 
364  _size += 1;
365 
366  return(node);
367  }
368 
369  //------------------------------------------------------------------------
373  //------------------------------------------------------------------------
374  bool Lookup(const KeyType & key, ValueType & value) const
375  {
376  bool rc = false;
377  PatriciaNode<KeyType,ValueType> *node = LookupNode(key);
378  if (node) {
379  value = node->_data;
380  rc = true;
381  }
382  return(rc);
383  }
384 
385  //------------------------------------------------------------------------
388  //------------------------------------------------------------------------
389  PatriciaNode<KeyType,ValueType> * LookupNode(const KeyType & key) const
390  {
391  // Traverse the Patricia (downward) until we find an upward link.
392  // If the node at the end of thu upward link has a key that exactly
393  // matches k, return the node. Else return 0.
394  PatriciaNode<KeyType,ValueType> *prev = _head;
395  PatriciaNode<KeyType,ValueType> *last = _head->_right;
396 
397  while (prev->_bitIndex < last->_bitIndex) {
398  prev = last;
399  last = (bit_get(key, last->_bitIndex) ? last->_right : last->_left);
400  }
401 
402  if (key_compare(key, last->_key))
403  return(last);
404  else
405  return(0);
406  }
407 
409  LongestMatchNode(const KeyType & key) const
410  {
411  // Traverse the Patricia (downward) until we find an upward link.
412  // If the node at the end of thu upward link has a key that exactly
413  // matches k, return the node. Else return 0.
414  PatriciaNode<KeyType,ValueType> *prev = _head;
415  PatriciaNode<KeyType,ValueType> *last = _head->_right;
416  PatriciaNode<KeyType,ValueType> *save = _head;
417 
418  while (prev->_bitIndex < last->_bitIndex) {
419  if (IsMatch<KeyType>(prev->_key, key))
420  save = prev;
421  prev = last;
422  if (IsMatch<KeyType>(prev->_key, key))
423  save = prev;
424  last = (bit_get(key, last->_bitIndex) ? last->_right : last->_left);
425  }
426 
427  if (IsMatch<KeyType>(last->_key, key))
428  return(last);
429  else if (save != _head)
430  return(save);
431  else
432  return(0);
433  }
434 
435  //------------------------------------------------------------------------
437  //------------------------------------------------------------------------
439  LongestMatchNode2(const KeyType & key) const
440  {
441  // Traverse the Patricia (downward) until we find an upward link.
442  // If the node at the end of thu upward link has a key that exactly
443  // matches k, return the node. Else return 0.
444  PatriciaNode<KeyType,ValueType> *prev = _head;
445  PatriciaNode<KeyType,ValueType> *last = _head->_right;
446 
447  // last = (bit_get(key, prev->_bitIndex) ? last->_right : last->_left);
448 
449  // Navigate down the trie and look for the key
450  while (prev->_bitIndex < last->_bitIndex) {
451  prev = last;
452  last = (bit_get(key, last->_bitIndex) ? last->_right : last->_left);
453  }
454 
455  if (key_compare(key, last->_key))
456  return(last); // key is already in the trie
457 
458  // RecursivePrint(last);
459 
460  std::cerr << "last->left: " << last->_left->_key
461  << " last->_right: " << last->_right->_key
462  << std::endl;
463 
464  // Find the first bit that does not match.
465  int i = BitFirstDifferent<KeyType>(key, last->_key);
466 
467  // Find the place in the trie to insert the new node
468  // prev = _head;
469  last = prev->_right;
470  last = (bit_get(key, prev->_bitIndex) ? last->_right : last->_left);
471  while ((prev->_bitIndex < last->_bitIndex) && (last->_bitIndex < i)) {
472  std::cerr << "prev: " << prev->_key << " last: " << last->_key
473  << std::endl;
474  prev = last;
475  last = (bit_get(key, last->_bitIndex) ? last->_right : last->_left);
476  }
477  std::cerr << "last->left: " << last->_left->_key
478  << " last->_right: " << last->_right->_key
479  << std::endl;
480 
481  if (IsMatch<KeyType>(last->_key, key))
482  return(last);
483  else if (prev != _head)
484  return(prev);
485  else
486  return(0);
487  }
488 
489  //------------------------------------------------------------------------
492  //------------------------------------------------------------------------
493  bool Delete(const KeyType & key)
494  {
497 
498  // Start at the root
501 
502  // Navigate down the tree and look for the key
503  while (p->_bitIndex < t->_bitIndex) {
504  pp = p;
505  p = t;
506  t = bit_get(key, t->_bitIndex) ? t->_right : t->_left;
507  }
508 
509  /*
510  int i;
511  do {
512  i = t->_bitIndex;
513  pp = p;
514  p = t;
515  t = bit_get(key, t->_bitIndex) ? t->_right : t->_left;
516  } while (i < t->_bitIndex);
517  */
518 
519  if (! key_compare(key, t->_key)) {
520  // key not found
521  return(false);
522  }
523 
524  // Copy p's key to t
525  if (t != p)
526  key_copy(p, t);
527 
528  if ((p->_left->_bitIndex > p->_bitIndex) ||
529  (p->_right->_bitIndex > p->_bitIndex)) {
530 
531  // There is at least one downward edge
532 
533  if (p != t) {
534  // Look for a new (intermediate) key
535  KeyType newkey = p->_key;
536 
538  x = bit_get(newkey, p->_bitIndex) ? p->_right : p->_left;
539 
540  while (lp->_bitIndex < x->_bitIndex) {
541  lp = x;
542  x = bit_get(newkey, x->_bitIndex) ? x->_right : x->_left;
543  }
544 
545  // If the intermediate key was not found, we have a problem..
546  if (! key_compare(newkey, x->_key)) {
547  return(false); // The key could not be found!
548  }
549 
550  // Rewire the leaf (lp) to point to t
551  if (bit_get(newkey, lp->_bitIndex))
552  lp->_right = t;
553  else
554  lp->_left = t;
555 
556  }
557 
558  // Rewire the parent to point to the real child of p
559  if (pp != p) {
561  bit_get(key, p->_bitIndex) ? p->_left : p->_right;
562  if (bit_get(key, pp->_bitIndex))
563  pp->_right = ch;
564  else
565  pp->_left = ch;
566  }
567 
568  }
569  else {
570  // Both edges (left, right) are pointing upwards or to the
571  // node (self-edges).
572 
573  // Rewire the parent
574  if (pp != p) {
575  if (bit_get(key, pp->_bitIndex))
576  pp->_right = (((p->_left == p->_right) && (p->_left == p)) ?
577  pp : ((p->_left == p) ? p->_right : p->_left));
578  else
579  pp->_left = (((p->_left == p->_right) && (p->_left == p)) ?
580  pp : ((p->_left == p) ? p->_right : p->_left));
581  }
582  }
583 
584  // Deallocate p (no longer needed)
585  delete(p);
586  p = 0;
587 
588  _size -= 1;
589 
590  // Success!
591  return(true);
592  }
593 
594  //------------------------------------------------------------------------
596  //------------------------------------------------------------------------
597  void RecursivePrint() const
598  {
599  RecursivePrint(_head);
600  }
601 
602  //------------------------------------------------------------------------
604  //------------------------------------------------------------------------
605  uint32_t StreamedLength() const
606  {
607  uint32_t rc = IO::StreamedLength(_size);
608  RecursiveStreamedLength(_head, rc);
609  return(rc);
610  }
611 
612  //------------------------------------------------------------------------
614  //------------------------------------------------------------------------
615  std::istream & Read(std::istream & is)
616  {
617  Clear();
618  if (is) {
619  uint32_t numEntries;
620  if (IO::Read(is, numEntries)) {
621  for (uint32_t i = 0; i < numEntries; ++i) {
622  KeyType key;
623  if (IO::Read(is, key)) {
624  ValueType value;
625  if (! IO::Read(is, value))
626  break;
627  Insert(key, value);
628  }
629  else {
630  break;
631  }
632  }
633  }
634  }
635  return(is);
636  }
637 
638  //------------------------------------------------------------------------
640  //------------------------------------------------------------------------
641  std::ostream & Write(std::ostream & os) const
642  {
643  if (os) {
644  if (IO::Write(os, _size)) {
645  RecursiveWrite(_head, os);
646  }
647  }
648  return(os);
649  }
650 
651  //------------------------------------------------------------------------
653  //------------------------------------------------------------------------
654  ssize_t Read(int fd)
655  {
656  Clear();
657  ssize_t totalBytes = 0;
658  if (fd >= 0) {
659  uint32_t numEntries;
660  uint32_t bytesRead = IO::Read(fd, numEntries);
661  if (bytesRead <= 0)
662  return(-1);
663  totalBytes = bytesRead;
664  for (uint32_t i = 0; i < numEntries; ++i) {
665  KeyType key;
666  bytesRead = IO::Read(fd, key);
667  if (bytesRead > 0) {
668  totalBytes += bytesRead;
669  ValueType value;
670  bytesRead = IO::Read(fd, value);
671  if (bytesRead > 0) {
672  totalBytes += bytesRead;
673  }
674  else {
675  return(-1);
676  }
677  Insert(key, value);
678  }
679  else {
680  return(-1);
681  }
682  }
683  }
684  return(totalBytes);
685  }
686 
687  //------------------------------------------------------------------------
689  //------------------------------------------------------------------------
690  ssize_t Write(int fd) const
691  {
692  ssize_t totalBytes = 0;
693  if (fd >= 0) {
694  ssize_t bytesWritten = IO::Write(fd, _size);
695  if (bytesWritten > 0) {
696  totalBytes += bytesWritten;
697  if (_size > 0) {
698  bytesWritten = RecursiveWrite(_head, fd);
699  if (bytesWritten > 0) {
700  totalBytes += bytesWritten;
701  }
702  else {
703  return(-1);
704  }
705  }
706  }
707  else {
708  return(-1);
709  }
710  }
711  return(totalBytes);
712  }
713 
714  //------------------------------------------------------------------------
716  //------------------------------------------------------------------------
717  size_t Read(FILE * f)
718  {
719  assert("Patricia::Read(FILE *)" == 0);
720  return(0);
721  }
722 
723  //------------------------------------------------------------------------
725  //------------------------------------------------------------------------
726  size_t Write(FILE * f) const
727  {
728  assert("Patricia::Write(FILE *)" == 0);
729  return(0);
730  }
731 
732  //------------------------------------------------------------------------
734  //------------------------------------------------------------------------
735  int Read(gzFile gzf)
736  {
737  assert("Patricia::Read(gzFile)" == 0);
738  return(-1);
739  }
740 
741  //------------------------------------------------------------------------
743  //------------------------------------------------------------------------
744  int Write(gzFile gzf) const
745  {
746  assert("Patricia::Write(gzFile)" == 0);
747  return(-1);
748  }
749 
750  //------------------------------------------------------------------------
752  //------------------------------------------------------------------------
753  int BZRead(BZFILE *bzf)
754  {
755  assert("Patricia::BZRead(BZFILE *)" == 0);
756  return(-1);
757  }
758 
759  //------------------------------------------------------------------------
761  //------------------------------------------------------------------------
762  int BZWrite(BZFILE *bzf) const
763  {
764  assert("Patricia::BZWrite(BZFILE *)" == 0);
765  return(-1);
766  }
767 
768  bool operator == (const Patricia<KeyType,ValueType> & pt) const
769  {
770  if (_size != pt._size)
771  return(false);
772  return(RecursiveEqual(_head, pt));
773  }
774 
775  private:
776  bool RecursiveEqual(PatriciaNode<KeyType,ValueType> *root,
777  const Patricia<KeyType,ValueType> & pt) const
778  {
779  bool rc = true;
780  PatriciaNode<KeyType,ValueType> *l = root->_left;
781  PatriciaNode<KeyType,ValueType> *r = root->_right;
782  // check the left branch
783  if ((l->_bitIndex >= root->_bitIndex) && (l != root) && (l != _head)) {
784  if (! RecursiveEqual(l, pt)) {
785  return(false);
786  }
787  }
788 
789  // check the right branch
790  if ((r->_bitIndex >= root->_bitIndex) && (r != root) && (r != _head)) {
791  if (! RecursiveEqual(r, pt)) {
792  return(false);
793  }
794  }
795 
796  if (root != _head) {
797  if (! pt.LookupNode(root->GetKey())) {
798  return(false);
799  }
800  }
801 
802  return(true);
803  }
804 
805  //------------------------------------------------------------------------
807  //------------------------------------------------------------------------
808  void RecursivePrint(PatriciaNode<KeyType,ValueType> * root) const
809  {
810  PatriciaNode<KeyType,ValueType> *l = root->_left;
811  PatriciaNode<KeyType,ValueType> *r = root->_right;
812 
813  // Print the right branch
814  if ((r->_bitIndex > root->_bitIndex) && (r != root) && (r != _head))
815  RecursivePrint(r);
816 
817  // Print the left branch
818  if ((l->_bitIndex > root->_bitIndex) && (l != root) && (l != _head))
819  RecursivePrint(l);
820 
821  // Print the root
822  std::cout << root->_key << " " << root->_data << std::endl;
823  }
824 
825  //------------------------------------------------------------------------
827  //------------------------------------------------------------------------
828  void RecursiveStreamedLength(PatriciaNode<KeyType,ValueType> * root,
829  uint32_t & len) const
830  {
831  PatriciaNode<KeyType,ValueType> *l = root->_left;
832  PatriciaNode<KeyType,ValueType> *r = root->_right;
833 
834  // count the left branch
835  if ( (l->_bitIndex >= root->_bitIndex) && (l != root) && (l != _head) )
836  RecursiveStreamedLength(l, len);
837 
838  // count the right branch
839  if ( (r->_bitIndex >= root->_bitIndex) && (r != root) && (r != _head) )
840  RecursiveStreamedLength(r, len);
841 
842  // count the root
843  len += root->StreamedLength();
844  }
845 
846  //------------------------------------------------------------------------
848  //------------------------------------------------------------------------
849  std::ostream & RecursiveWrite(PatriciaNode<KeyType,ValueType> * root,
850  std::ostream & os) const
851  {
852  if (os) {
853  PatriciaNode<KeyType,ValueType> *l = root->_left;
854  PatriciaNode<KeyType,ValueType> *r = root->_right;
855 
856  // write the left branch
857  if ((l->_bitIndex >= root->_bitIndex) && (l != root) && (l != _head))
858  if (! RecursiveWrite(l, os))
859  return(os);
860 
861  // write the right branch
862  if ((r->_bitIndex >= root->_bitIndex) && (r != root) && (r != _head))
863  if (! RecursiveWrite(r, os))
864  return(os);
865 
866  // write the root
867  if (IO::Write(os, root->_key))
868  IO::Write(os, root->_data);
869  }
870  return(os);
871  }
872 
873  //------------------------------------------------------------------------
875  //------------------------------------------------------------------------
876  ssize_t
877  RecursiveWrite(PatriciaNode<KeyType,ValueType> * root, int fd) const
878  {
879  ssize_t rc = 0;
880 
881  if (fd >= 0) {
882  PatriciaNode<KeyType,ValueType> *l = root->_left;
883  PatriciaNode<KeyType,ValueType> *r = root->_right;
884 
885  // write the left branch
886  if ((l->_bitIndex >= root->_bitIndex) && (l != root) && (l != _head)) {
887  ssize_t bytesWritten = RecursiveWrite(l, fd);
888  if (bytesWritten < 0)
889  return(-1);
890  rc += bytesWritten;
891  }
892 
893  // write the right branch
894  if ((r->_bitIndex >= root->_bitIndex) && (r != root) && (r != _head)) {
895  ssize_t bytesWritten = RecursiveWrite(r, fd);
896  if (bytesWritten < 0)
897  return(-1);
898  rc += bytesWritten;
899  }
900 
901  // write the root
902  ssize_t bytesWritten = IO::Write(fd, root->_key);
903  if (bytesWritten <= 0)
904  return(-1);
905  rc += bytesWritten;
906  bytesWritten = IO::Write(fd, root->_data);
907  if (bytesWritten <= 0)
908  return(-1);
909  rc += bytesWritten;
910  }
911  return(rc);
912  }
913 
914  //------------------------------------------------------------------------
916  //------------------------------------------------------------------------
917  void RecursiveRemove(PatriciaNode<KeyType,ValueType> *node)
918  {
919  PatriciaNode<KeyType,ValueType> *l = node->_left;
920  PatriciaNode<KeyType,ValueType> *r = node->_right;
921 
922  // remove the left branch
923  if (l
924  && (l->_bitIndex >= node->_bitIndex)
925  && (l != node)
926  && (l != _head)) {
927  RecursiveRemove(l);
928  }
929 
930  // remove the right branch
931  if (r
932  && (r->_bitIndex >= node->_bitIndex)
933  && (r != node)
934  && (r != _head)) {
935  RecursiveRemove(r);
936  }
937 
938  // remove the node
939  if (node && (node != _head)) {
940  // delete(node);
941  node = 0;
942  }
943  }
944 
945  //------------------------------------------------------------------------
947  //------------------------------------------------------------------------
948  inline int bit_get(const KeyType & k, int n) const
949  {
950  int rc = 2; // psuedo-value
951  if (n >= 0)
952  rc = GetBit<KeyType>(k, n);
953  return(rc);
954  }
955 
956  //------------------------------------------------------------------------
958  //------------------------------------------------------------------------
959  inline int bit_first_different(const KeyType & k1, const KeyType & k2)
960  {
961  return(BitFirstDifferent<KeyType>(k1, k2));
962  }
963 
964  //------------------------------------------------------------------------
966  //------------------------------------------------------------------------
967  void key_copy(PatriciaNode<KeyType,ValueType> *src,
969  {
970  if (src == dest)
971  return;
972 
973  // Copy the key from src to dest
974  dest->_key = src->_key;
975 
976  // Copy the data from src to dest
977  dest->_data = src->_data;
978 
979  // How about the bit index?
980  // dest->_bitIndex = src->_bitIndex;
981  }
982 
983  KeyEqual key_compare;
985  uint32_t _size;
986  };
987 
988 
989 } // namespace Dwm
990 
991 
992 #endif // _PATRICIA_HH_
993 
994 //---------------------------- emacs settings -----------------------------
995 // Local Variables:
996 // mode: C++/la
997 // tab-width: 2
998 // indent-tabs-mode: nil
999 // c-basic-offset: 2
1000 // End:
1001 //-------------------------------------------------------------------------
PatriciaNode()
Constructor.
Definition: DwmPatricia.hh:126
This class is a pure virtual class, defining an interface for classes that can write their contents t...
Definition: DwmGZWritable.hh:57
Dwm::Writable pure virtual class definition.
int BZWrite(BZFILE *bzf) const
NOT YET IMPLEMENTED.
Definition: DwmPatricia.hh:762
PatriciaNode< KeyType, ValueType > * LongestMatchNode2(const KeyType &key) const
DOESN&#39;T WORK PROPERLY.
Definition: DwmPatricia.hh:439
Dwm::BZ2Readable pure virtual class definition.
size_t Write(FILE *f) const
NOT YET IMPLEMENTED.
Definition: DwmPatricia.hh:726
PatriciaNode< KeyType, ValueType > * GetRight()
Returns the right branch.
Definition: DwmPatricia.hh:235
uint32_t StreamedLength() const
Returns the number of bytes that should be written if one of the Write() members is called...
Definition: DwmPatricia.hh:605
Dwm::GZReadable pure virtual class definition.
Dwm::Readable pure virtual class definition.
ssize_t Write(int fd) const
Write to a file descriptor.
Definition: DwmPatricia.hh:690
void Initialize(const KeyType &key, const ValueType &data, int bitIdx, PatriciaNode< KeyType, ValueType > *left, PatriciaNode< KeyType, ValueType > *right)
Initialize this node with the given data.
Definition: DwmPatricia.hh:186
std::ostream & Write(std::ostream &os) const
Write to an ostream. Return the ostream.
Definition: DwmPatricia.hh:641
ssize_t Read(int fd)
Read from a file descriptor.
Definition: DwmPatricia.hh:654
This class is a pure virtual class, defining an interface for classes that can read their contents fr...
Definition: DwmBZ2Readable.hh:57
A node in a Patricia trie.
Definition: DwmPatricia.hh:120
Pre-declare the Patricia class template.
Definition: DwmPatricia.hh:113
~PatriciaNode()
Destructor.
Definition: DwmPatricia.hh:179
PatriciaNode< KeyType, ValueType > * GetLeft()
Returns the left branch.
Definition: DwmPatricia.hh:227
static std::ostream & Write(std::ostream &os, char c)
Writes c to os. Returns os.
int Write(gzFile gzf) const
NOT YET IMPLEMENTED.
Definition: DwmPatricia.hh:744
Dwm::BZ2Writable pure virtual class definition.
int Read(gzFile gzf)
NOT YET IMPLEMENTED.
Definition: DwmPatricia.hh:735
static std::istream & Read(std::istream &is, char &c)
Reads c from is. Returns is.
bool Lookup(const KeyType &key, ValueType &value) const
Searches for the given key.
Definition: DwmPatricia.hh:374
Definition: DwmBZ2IO.hh:67
Patricia()
Constructor.
Definition: DwmPatricia.hh:284
This class is a pure virtual class, defining an interface for classes that can read their contents fr...
Definition: DwmGZReadable.hh:57
PatriciaNode(const KeyType &key, const ValueType &data, int bitIdx, PatriciaNode< KeyType, ValueType > *left, PatriciaNode< KeyType, ValueType > *right)
Constructor.
Definition: DwmPatricia.hh:169
Dwm::IO class definition.
std::istream & Read(std::istream &is)
Read from an istream. Return the istream.
Definition: DwmPatricia.hh:615
~Patricia()
Destructor.
Definition: DwmPatricia.hh:296
This class defines an interface for classes that can write their contents to an ostream, file descriptor or FILE pointer.
Definition: DwmWritable.hh:58
bool Delete(const KeyType &key)
Remove the node containing the given key.
Definition: DwmPatricia.hh:493
static uint32_t StreamedLength(char c)
Returns the number of bytes that would be written if we called Write() for a char.
Definition: DwmIO.hh:92
This class is a pure virtual class, defining an interface for classes that can write their contents t...
Definition: DwmBZ2Writable.hh:57
PatriciaNode< KeyType, ValueType > * Insert(const KeyType &key, const ValueType &data)
Inserts a new (key, data) pair in the Patricia trie, and returns the new node.
Definition: DwmPatricia.hh:325
Dwm::GZWritable pure virtual class definition.
This class defines an interface for classes that can read their contents from an istream, file descriptor or FILE pointer.
Definition: DwmReadable.hh:58
ValueType & GetData()
Returns the data field.
Definition: DwmPatricia.hh:202
PatriciaNode< KeyType, ValueType > * LookupNode(const KeyType &key) const
Search for the given key, and returns the node that contains it (or NULL).
Definition: DwmPatricia.hh:389
int BZRead(BZFILE *bzf)
NOT YET IMPLEMENTED.
Definition: DwmPatricia.hh:753
bool SetData(const ValueType &data)
Sets the data field.
Definition: DwmPatricia.hh:210
size_t Read(FILE *f)
NOT YET IMPLEMENTED.
Definition: DwmPatricia.hh:717
KeyType GetKey() const
Returns the key field.
Definition: DwmPatricia.hh:219