File Coverage

blib/lib/Tree/Trek.pm
Criterion Covered Total %
statement 76 82 92.6
branch 25 30 83.3
condition n/a
subroutine 19 19 100.0
pod 7 8 87.5
total 127 139 91.3


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -I/home/phil/perl/cpan/DataTableText/lib/
2             #-------------------------------------------------------------------------------
3             # Trek through a tree one character at a time.
4             # Philip R Brenan at appaapps dot com, Appa Apps Ltd Inc., 2021
5             #-------------------------------------------------------------------------------
6             # podDocumentation
7             package Tree::Trek;
8             our $VERSION = "20210424";
9 1     1   622 use warnings FATAL => qw(all);
  1         7  
  1         38  
10 1     1   5 use strict;
  1         2  
  1         33  
11 1     1   7 use Carp qw(confess cluck);
  1         1  
  1         90  
12 1     1   550 use Data::Dump qw(dump);
  1         7949  
  1         63  
13 1     1   4139 use Data::Table::Text qw(:all);
  1         143863  
  1         1888  
14 1     1   18 use feature qw(say current_sub);
  1         2  
  1         1058  
15              
16             my $debug = -e q(/home/phil/); # Developing
17              
18             #D1 Tree::Trek # Methods to create a trekkable tree.
19              
20             sub node(;$) # Create a new node
21 8     8 1 11 {my ($parent) = @_; # Optional parent
22 8         25 genHash(__PACKAGE__,
23             jumps => {}, # {character => node}
24             data => undef, # The data attached to this node
25             parent => $parent, # The node from whence we came
26             );
27             }
28              
29             sub put($$) # Add a key to the tree
30 16     16 1 54 {my ($tree, $key) = @_; # Tree, key
31              
32 16 100       128 return $tree unless $key; # Key is empty so we have found the desired node
33              
34 11         19 my $c = substr $key, 0, 1; # Next character of the key
35              
36 11 100       196 if (exists $tree->jumps->{$c}) # Jump through existing node
37 4         89 {return $tree->jumps->{$c}->put(substr $key, 1);
38             }
39             else # Create a new node and jump through it
40 7         43 {my $n = $tree->jumps->{$c} = node $tree;
41 7         448 return $n->put(substr $key, 1);
42             }
43             }
44              
45             sub key($) # Return the key of a node
46 16     16 1 29 {my ($node) = @_; # Node
47 16 100       300 if (my $p = $node->parent)
48 11         198 {for my $c(sort keys $p->jumps->%*)
49 15 100       288 {if ($p->jumps->{$c} == $node)
50 11         61 {return $p->key . $c;
51             }
52             }
53 0         0 confess "Child missing in parent"; # This should not happen
54             }
55             '' # The key of the root node
56 5         105 }
57              
58             sub find($$) # Find a key in a tree - return its node if such a node exists else undef
59 54     54 1 244 {my ($tree, $key) = @_; # Tree, key
60              
61 54 100       296 return $tree unless $key; # We have exhausted the key so this must be the node in question as long as it has no jumps
62              
63 38         74 my $c = substr $key, 0, 1;
64              
65 38 100       763 if (exists $tree->jumps->{$c}) # Continue search
66 31         589 {return $tree->jumps->{$c}->find(substr $key, 1);
67             }
68             undef # Not found
69 7         62 }
70              
71             sub delete($) # Remove a node from a tree
72 5     5 1 11 {my ($node) = @_; # Node to be removed
73              
74             my $clear = sub # Clear the parent's jumps if possible
75 8     8   54 {my ($child) = @_; # Child of parent
76 8 100       123 if (my $p = $child->parent)
77 7         130 {for my $c(keys $p->jumps->%*)
78 10 100       185 {if ($p->jumps->{$c} == $child)
79 7         132 {delete $p->jumps->{$c};
80             }
81             }
82 7 100       137 __SUB__->($p) unless keys $p->jumps->%*;
83             }
84 5         28 };
85              
86 5         94 $node->data = undef; # Clear data
87 5 100       89 $clear->($node) unless (keys $node->jumps->%*); # No jumps from this node and no data so we can clear it from the parent
88 5         62 $node
89             }
90              
91             sub count($) # Count the nodes addressed in the specified tree
92 34     34 1 134 {my ($node) = @_; # Node to be counted from
93 34 100       549 my $n = $node->data ? 1 : 0; # Count the nodes addressed in the specified tree
94 34         615 for my $c(keys $node->jumps->%*) # Each possible child
95 28         484 {$n += $node->jumps->{$c}->count; # Each child of the parent
96             }
97             $n # Count
98 34         114 }
99              
100             sub traverse($) # Traverse a tree returning an array of nodes
101 8     8 1 39 {my ($node) = @_; # Node to be counted from
102 8         11 my @n;
103 8 100       133 push @n, $node if $node->data;
104 8         152 for my $c(sort keys $node->jumps->%*) # Each possible child in key order
105 7         123 {push @n, $node->jumps->{$c}->traverse;
106             }
107             @n
108 8         32 }
109              
110             #d
111             #-------------------------------------------------------------------------------
112             # Export - eeee
113             #-------------------------------------------------------------------------------
114              
115 1     1   9 use Exporter qw(import);
  1         1  
  1         42  
116              
117 1     1   12 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  1         3  
  1         349  
118              
119             @ISA = qw(Exporter);
120             @EXPORT = qw();
121             @EXPORT_OK = qw(
122             );
123             %EXPORT_TAGS = (all=>[@EXPORT, @EXPORT_OK]);
124              
125             # podDocumentation
126             =pod
127              
128             =encoding utf-8
129              
130             =head1 Name
131              
132             Tree::Trek - Trek through a tree one character at a time.
133              
134             =head1 Synopsis
135              
136             Create a trekkable tree and trek through it:
137              
138             my $n = node;
139              
140             $n->put("aa") ->data = "AA";
141             $n->put("ab") ->data = "AB";
142             $n->put("ba") ->data = "BA";
143             $n->put("bb") ->data = "BB";
144             $n->put("aaa")->data = "AAA";
145              
146             is_deeply [map {[$_->key, $_->data]} $n->traverse],
147             [["aa", "AA"],
148             ["aaa", "AAA"],
149             ["ab", "AB"],
150             ["ba", "BA"],
151             ["bb", "BB"]];
152              
153             =head1 Description
154              
155             Trek through a tree one character at a time.
156              
157              
158             Version "20210424".
159              
160              
161             The following sections describe the methods in each functional area of this
162             module. For an alphabetic listing of all methods by name see L.
163              
164              
165              
166             =head1 Tree::Trek
167              
168             Methods to create a trekkable tree.
169              
170             =head2 node($parent)
171              
172             Create a new node
173              
174             Parameter Description
175             1 $parent Optional parent
176              
177             B
178              
179              
180             if (1)
181            
182             {my $n = node; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
183              
184             $n->put("aa")->data = "AA";
185             $n->put("ab")->data = "AB";
186             $n->put("ba")->data = "BA";
187             $n->put("bb")->data = "BB";
188             $n->put("aaa")->data = "AAA";
189             is_deeply $n->count, 5;
190            
191             is_deeply $n->find("aa") ->data, "AA";
192             is_deeply $n->find("ab") ->data, "AB";
193             is_deeply $n->find("ba") ->data, "BA";
194             is_deeply $n->find("bb") ->data, "BB";
195             is_deeply $n->find("aaa")->data, "AAA";
196            
197             is_deeply [map {[$_->key, $_->data]} $n->traverse],
198             [["aa", "AA"],
199             ["aaa", "AAA"],
200             ["ab", "AB"],
201             ["ba", "BA"],
202             ["bb", "BB"]];
203            
204             ok $n->find("a");
205             ok !$n->find("a")->data;
206             ok $n->find("b");
207             ok !$n->find("b")->data;
208             ok !$n->find("c");
209            
210             ok $n->find("aa")->delete; ok $n->find("aa"); is_deeply $n->count, 4;
211             ok $n->find("ab")->delete; ok !$n->find("ab"); is_deeply $n->count, 3;
212             ok $n->find("ba")->delete; ok !$n->find("ba"); is_deeply $n->count, 2;
213             ok $n->find("bb")->delete; ok !$n->find("bb"); is_deeply $n->count, 1;
214            
215             ok $n->find("a");
216             ok !$n->find("b");
217            
218             ok $n->find("aaa")->delete; ok !$n->find("aaa"); is_deeply $n->count, 0;
219             ok !$n->find("a");
220             }
221            
222              
223             =head2 put($tree, $key)
224              
225             Add a key to the tree
226              
227             Parameter Description
228             1 $tree Tree
229             2 $key Key
230              
231             B
232              
233              
234             if (1)
235             {my $n = node;
236            
237             $n->put("aa")->data = "AA"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
238              
239            
240             $n->put("ab")->data = "AB"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
241              
242            
243             $n->put("ba")->data = "BA"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
244              
245            
246             $n->put("bb")->data = "BB"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
247              
248            
249             $n->put("aaa")->data = "AAA"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
250              
251             is_deeply $n->count, 5;
252            
253             is_deeply $n->find("aa") ->data, "AA";
254             is_deeply $n->find("ab") ->data, "AB";
255             is_deeply $n->find("ba") ->data, "BA";
256             is_deeply $n->find("bb") ->data, "BB";
257             is_deeply $n->find("aaa")->data, "AAA";
258            
259             is_deeply [map {[$_->key, $_->data]} $n->traverse],
260             [["aa", "AA"],
261             ["aaa", "AAA"],
262             ["ab", "AB"],
263             ["ba", "BA"],
264             ["bb", "BB"]];
265            
266             ok $n->find("a");
267             ok !$n->find("a")->data;
268             ok $n->find("b");
269             ok !$n->find("b")->data;
270             ok !$n->find("c");
271            
272             ok $n->find("aa")->delete; ok $n->find("aa"); is_deeply $n->count, 4;
273             ok $n->find("ab")->delete; ok !$n->find("ab"); is_deeply $n->count, 3;
274             ok $n->find("ba")->delete; ok !$n->find("ba"); is_deeply $n->count, 2;
275             ok $n->find("bb")->delete; ok !$n->find("bb"); is_deeply $n->count, 1;
276            
277             ok $n->find("a");
278             ok !$n->find("b");
279            
280             ok $n->find("aaa")->delete; ok !$n->find("aaa"); is_deeply $n->count, 0;
281             ok !$n->find("a");
282             }
283            
284              
285             =head2 key($node)
286              
287             Return the key of a node
288              
289             Parameter Description
290             1 $node Node
291              
292             B
293              
294              
295             if (1)
296             {my $n = node;
297             $n->put("aa")->data = "AA";
298             $n->put("ab")->data = "AB";
299             $n->put("ba")->data = "BA";
300             $n->put("bb")->data = "BB";
301             $n->put("aaa")->data = "AAA";
302             is_deeply $n->count, 5;
303            
304             is_deeply $n->find("aa") ->data, "AA";
305             is_deeply $n->find("ab") ->data, "AB";
306             is_deeply $n->find("ba") ->data, "BA";
307             is_deeply $n->find("bb") ->data, "BB";
308             is_deeply $n->find("aaa")->data, "AAA";
309            
310            
311             is_deeply [map {[$_->key, $_->data]} $n->traverse], # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
312              
313             [["aa", "AA"],
314             ["aaa", "AAA"],
315             ["ab", "AB"],
316             ["ba", "BA"],
317             ["bb", "BB"]];
318            
319             ok $n->find("a");
320             ok !$n->find("a")->data;
321             ok $n->find("b");
322             ok !$n->find("b")->data;
323             ok !$n->find("c");
324            
325             ok $n->find("aa")->delete; ok $n->find("aa"); is_deeply $n->count, 4;
326             ok $n->find("ab")->delete; ok !$n->find("ab"); is_deeply $n->count, 3;
327             ok $n->find("ba")->delete; ok !$n->find("ba"); is_deeply $n->count, 2;
328             ok $n->find("bb")->delete; ok !$n->find("bb"); is_deeply $n->count, 1;
329            
330             ok $n->find("a");
331             ok !$n->find("b");
332            
333             ok $n->find("aaa")->delete; ok !$n->find("aaa"); is_deeply $n->count, 0;
334             ok !$n->find("a");
335             }
336            
337              
338             =head2 find($tree, $key)
339              
340             Find a key in a tree - return its node if such a node exists else undef
341              
342             Parameter Description
343             1 $tree Tree
344             2 $key Key
345              
346             B
347              
348              
349             if (1)
350             {my $n = node;
351             $n->put("aa")->data = "AA";
352             $n->put("ab")->data = "AB";
353             $n->put("ba")->data = "BA";
354             $n->put("bb")->data = "BB";
355             $n->put("aaa")->data = "AAA";
356             is_deeply $n->count, 5;
357            
358            
359             is_deeply $n->find("aa") ->data, "AA"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
360              
361            
362             is_deeply $n->find("ab") ->data, "AB"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
363              
364            
365             is_deeply $n->find("ba") ->data, "BA"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
366              
367            
368             is_deeply $n->find("bb") ->data, "BB"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
369              
370            
371             is_deeply $n->find("aaa")->data, "AAA"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
372              
373            
374             is_deeply [map {[$_->key, $_->data]} $n->traverse],
375             [["aa", "AA"],
376             ["aaa", "AAA"],
377             ["ab", "AB"],
378             ["ba", "BA"],
379             ["bb", "BB"]];
380            
381            
382             ok $n->find("a"); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
383              
384            
385             ok !$n->find("a")->data; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
386              
387            
388             ok $n->find("b"); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
389              
390            
391             ok !$n->find("b")->data; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
392              
393            
394             ok !$n->find("c"); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
395              
396            
397            
398             ok $n->find("aa")->delete; ok $n->find("aa"); is_deeply $n->count, 4; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
399              
400            
401             ok $n->find("ab")->delete; ok !$n->find("ab"); is_deeply $n->count, 3; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
402              
403            
404             ok $n->find("ba")->delete; ok !$n->find("ba"); is_deeply $n->count, 2; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
405              
406            
407             ok $n->find("bb")->delete; ok !$n->find("bb"); is_deeply $n->count, 1; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
408              
409            
410            
411             ok $n->find("a"); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
412              
413            
414             ok !$n->find("b"); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
415              
416            
417            
418             ok $n->find("aaa")->delete; ok !$n->find("aaa"); is_deeply $n->count, 0; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
419              
420            
421             ok !$n->find("a"); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
422              
423             }
424            
425              
426             =head2 delete($node)
427              
428             Remove a node from a tree
429              
430             Parameter Description
431             1 $node Node to be removed
432              
433             B
434              
435              
436             if (1)
437             {my $n = node;
438             $n->put("aa")->data = "AA";
439             $n->put("ab")->data = "AB";
440             $n->put("ba")->data = "BA";
441             $n->put("bb")->data = "BB";
442             $n->put("aaa")->data = "AAA";
443             is_deeply $n->count, 5;
444            
445             is_deeply $n->find("aa") ->data, "AA";
446             is_deeply $n->find("ab") ->data, "AB";
447             is_deeply $n->find("ba") ->data, "BA";
448             is_deeply $n->find("bb") ->data, "BB";
449             is_deeply $n->find("aaa")->data, "AAA";
450            
451             is_deeply [map {[$_->key, $_->data]} $n->traverse],
452             [["aa", "AA"],
453             ["aaa", "AAA"],
454             ["ab", "AB"],
455             ["ba", "BA"],
456             ["bb", "BB"]];
457            
458             ok $n->find("a");
459             ok !$n->find("a")->data;
460             ok $n->find("b");
461             ok !$n->find("b")->data;
462             ok !$n->find("c");
463            
464            
465             ok $n->find("aa")->delete; ok $n->find("aa"); is_deeply $n->count, 4; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
466              
467            
468             ok $n->find("ab")->delete; ok !$n->find("ab"); is_deeply $n->count, 3; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
469              
470            
471             ok $n->find("ba")->delete; ok !$n->find("ba"); is_deeply $n->count, 2; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
472              
473            
474             ok $n->find("bb")->delete; ok !$n->find("bb"); is_deeply $n->count, 1; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
475              
476            
477             ok $n->find("a");
478             ok !$n->find("b");
479            
480            
481             ok $n->find("aaa")->delete; ok !$n->find("aaa"); is_deeply $n->count, 0; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
482              
483             ok !$n->find("a");
484             }
485            
486              
487             =head2 count($node)
488              
489             Count the nodes addressed in the specified tree
490              
491             Parameter Description
492             1 $node Node to be counted from
493              
494             B
495              
496              
497             if (1)
498             {my $n = node;
499             $n->put("aa")->data = "AA";
500             $n->put("ab")->data = "AB";
501             $n->put("ba")->data = "BA";
502             $n->put("bb")->data = "BB";
503             $n->put("aaa")->data = "AAA";
504            
505             is_deeply $n->count, 5; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
506              
507            
508             is_deeply $n->find("aa") ->data, "AA";
509             is_deeply $n->find("ab") ->data, "AB";
510             is_deeply $n->find("ba") ->data, "BA";
511             is_deeply $n->find("bb") ->data, "BB";
512             is_deeply $n->find("aaa")->data, "AAA";
513            
514             is_deeply [map {[$_->key, $_->data]} $n->traverse],
515             [["aa", "AA"],
516             ["aaa", "AAA"],
517             ["ab", "AB"],
518             ["ba", "BA"],
519             ["bb", "BB"]];
520            
521             ok $n->find("a");
522             ok !$n->find("a")->data;
523             ok $n->find("b");
524             ok !$n->find("b")->data;
525             ok !$n->find("c");
526            
527            
528             ok $n->find("aa")->delete; ok $n->find("aa"); is_deeply $n->count, 4; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
529              
530            
531             ok $n->find("ab")->delete; ok !$n->find("ab"); is_deeply $n->count, 3; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
532              
533            
534             ok $n->find("ba")->delete; ok !$n->find("ba"); is_deeply $n->count, 2; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
535              
536            
537             ok $n->find("bb")->delete; ok !$n->find("bb"); is_deeply $n->count, 1; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
538              
539            
540             ok $n->find("a");
541             ok !$n->find("b");
542            
543            
544             ok $n->find("aaa")->delete; ok !$n->find("aaa"); is_deeply $n->count, 0; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
545              
546             ok !$n->find("a");
547             }
548            
549              
550             =head2 traverse($node)
551              
552             Traverse a tree returning an array of nodes
553              
554             Parameter Description
555             1 $node Node to be counted from
556              
557             B
558              
559              
560             if (1)
561             {my $n = node;
562             $n->put("aa")->data = "AA";
563             $n->put("ab")->data = "AB";
564             $n->put("ba")->data = "BA";
565             $n->put("bb")->data = "BB";
566             $n->put("aaa")->data = "AAA";
567             is_deeply $n->count, 5;
568            
569             is_deeply $n->find("aa") ->data, "AA";
570             is_deeply $n->find("ab") ->data, "AB";
571             is_deeply $n->find("ba") ->data, "BA";
572             is_deeply $n->find("bb") ->data, "BB";
573             is_deeply $n->find("aaa")->data, "AAA";
574            
575            
576             is_deeply [map {[$_->key, $_->data]} $n->traverse], # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
577              
578             [["aa", "AA"],
579             ["aaa", "AAA"],
580             ["ab", "AB"],
581             ["ba", "BA"],
582             ["bb", "BB"]];
583            
584             ok $n->find("a");
585             ok !$n->find("a")->data;
586             ok $n->find("b");
587             ok !$n->find("b")->data;
588             ok !$n->find("c");
589            
590             ok $n->find("aa")->delete; ok $n->find("aa"); is_deeply $n->count, 4;
591             ok $n->find("ab")->delete; ok !$n->find("ab"); is_deeply $n->count, 3;
592             ok $n->find("ba")->delete; ok !$n->find("ba"); is_deeply $n->count, 2;
593             ok $n->find("bb")->delete; ok !$n->find("bb"); is_deeply $n->count, 1;
594            
595             ok $n->find("a");
596             ok !$n->find("b");
597            
598             ok $n->find("aaa")->delete; ok !$n->find("aaa"); is_deeply $n->count, 0;
599             ok !$n->find("a");
600             }
601            
602              
603              
604             =head1 Index
605              
606              
607             1 L - Count the nodes addressed in the specified tree
608              
609             2 L - Remove a node from a tree
610              
611             3 L - Find a key in a tree - return its node if such a node exists else undef
612              
613             4 L - Return the key of a node
614              
615             5 L - Create a new node
616              
617             6 L - Add a key to the tree
618              
619             7 L - Traverse a tree returning an array of nodes
620              
621             =head1 Installation
622              
623             This module is written in 100% Pure Perl and, thus, it is easy to read,
624             comprehend, use, modify and install via B:
625              
626             sudo cpan install Tree::Trek
627              
628             =head1 Author
629              
630             L
631              
632             L
633              
634             =head1 Copyright
635              
636             Copyright (c) 2016-2021 Philip R Brenan.
637              
638             This module is free software. It may be used, redistributed and/or modified
639             under the same terms as Perl itself.
640              
641             =cut
642              
643              
644              
645             # Tests and documentation
646              
647             sub test
648 1     1 0 88 {my $p = __PACKAGE__;
649 1         9 binmode($_, ":utf8") for *STDOUT, *STDERR;
650 1 50       67 return if eval "eof(${p}::DATA)";
651 0           my $s = eval "join('', <${p}::DATA>)";
652 0 0         $@ and die $@;
653 0           eval $s;
654 0 0         $@ and die $@;
655 0           1
656             }
657              
658             test unless caller;
659              
660             1;
661             # podDocumentation
662             #__DATA__
663 1     1   9 use Time::HiRes qw(time);
  1         2  
  1         18  
664 1     1   1029 use Test::More;
  1         68655  
  1         8  
665              
666             my $localTest = ((caller(1))[0]//'Tree::Trek') eq "Tree::Trek"; # Local testing mode
667              
668             Test::More->builder->output("/dev/null") if $localTest; # Reduce number of confirmation messages during testing
669              
670             if ($^O =~ m(bsd|linux)i) # Supported systems
671             {plan tests => 30;
672             }
673             else
674             {plan skip_all =>qq(Not supported on: $^O);
675             }
676              
677             my $start = time; # Tests
678              
679             #goto latest;
680              
681             if (1) #Tnode #Tput #Tfind #Tcount #Ttraverse #Tdelete #Tkey
682             {my $n = node;
683             $n->put("aa")->data = "AA";
684             $n->put("ab")->data = "AB";
685             $n->put("ba")->data = "BA";
686             $n->put("bb")->data = "BB";
687             $n->put("aaa")->data = "AAA";
688             is_deeply $n->count, 5;
689              
690             is_deeply $n->find("aa") ->data, "AA";
691             is_deeply $n->find("ab") ->data, "AB";
692             is_deeply $n->find("ba") ->data, "BA";
693             is_deeply $n->find("bb") ->data, "BB";
694             is_deeply $n->find("aaa")->data, "AAA";
695              
696             is_deeply [map {[$_->key, $_->data]} $n->traverse],
697             [["aa", "AA"],
698             ["aaa", "AAA"],
699             ["ab", "AB"],
700             ["ba", "BA"],
701             ["bb", "BB"]];
702              
703             ok $n->find("a");
704             ok !$n->find("a")->data;
705             ok $n->find("b");
706             ok !$n->find("b")->data;
707             ok !$n->find("c");
708              
709             ok $n->find("aa")->delete; ok $n->find("aa"); is_deeply $n->count, 4;
710             ok $n->find("ab")->delete; ok !$n->find("ab"); is_deeply $n->count, 3;
711             ok $n->find("ba")->delete; ok !$n->find("ba"); is_deeply $n->count, 2;
712             ok $n->find("bb")->delete; ok !$n->find("bb"); is_deeply $n->count, 1;
713              
714             ok $n->find("a");
715             ok !$n->find("b");
716              
717             ok $n->find("aaa")->delete; ok !$n->find("aaa"); is_deeply $n->count, 0;
718             ok !$n->find("a");
719             }
720              
721             lll "Finished:", time - $start;