File Coverage

blib/lib/Tree/RB/XS.pm
Criterion Covered Total %
statement 52 56 92.8
branch 26 32 81.2
condition 18 31 58.0
subroutine 14 16 87.5
pod 4 4 100.0
total 114 139 82.0


line stmt bran cond sub pod time code
1             package Tree::RB::XS;
2             $Tree::RB::XS::VERSION = '0.07';
3             # VERSION
4             # ABSTRACT: Red/Black Tree implemented in C, with similar API to Tree::RB
5              
6 10     10   1899783 use strict;
  10         66  
  10         239  
7 10     10   47 use warnings;
  10         18  
  10         198  
8 10     10   37 use Carp;
  10         16  
  10         453  
9 10     10   46 use Scalar::Util ();
  10         17  
  10         416  
10             require XSLoader;
11             XSLoader::load('Tree::RB::XS', $Tree::RB::XS::VERSION);
12 10     10   47 use Exporter 'import';
  10         16  
  10         8961  
13             our @_key_types= qw( KEY_TYPE_ANY KEY_TYPE_INT KEY_TYPE_FLOAT KEY_TYPE_BSTR KEY_TYPE_USTR );
14             our @_cmp_enum= qw( CMP_PERL CMP_INT CMP_FLOAT CMP_MEMCMP CMP_UTF8 CMP_NUMSPLIT );
15             our @_lookup_modes= qw( GET_EQ GET_EQ_LAST GET_GT GET_LT GET_GE GET_LE GET_LE_LAST GET_NEXT GET_PREV
16             LUEQUAL LUGTEQ LULTEQ LUGREAT LULESS LUNEXT LUPREV );
17             our @EXPORT_OK= (@_key_types, @_cmp_enum, @_lookup_modes);
18             our %EXPORT_TAGS= (
19             key_type => \@_key_types,
20             cmp => \@_cmp_enum,
21             lookup => \@_lookup_modes,
22             get => \@_lookup_modes,
23             all => \@EXPORT_OK,
24             );
25              
26              
27             sub new {
28 45     45 1 3764898 my $class= shift;
29 45 50 33     395 my %options= @_ == 1 && ref $_[0] eq 'HASH'? %{$_[0]}
  0 50       0  
30             : @_ == 1? ( compare_fn => $_[0] )
31             : @_;
32 45         171 my $self= bless \%options, $class;
33 45         514 $self->_init_tree(delete $self->{key_type}, delete $self->{compare_fn});
34 45 100       164 $self->allow_duplicates(1) if delete $self->{allow_duplicates};
35 45 50       121 $self->compat_list_get(1) if delete $self->{compat_list_get};
36 45         122 $self;
37             }
38              
39              
40             *root= *root_node;
41             *min= *min_node;
42             *max= *max_node;
43             *nth= *nth_node;
44              
45              
46             sub iter {
47 118     118 1 4256 my ($self, $key_or_node, $mode)= @_;
48 118 50 66     235 $key_or_node= $self->get_node($key_or_node, @_ > 2? $mode : GET_GE())
    100          
49             if @_ > 1 && ref $key_or_node ne 'Tree::RB::XS::Node';
50 118   66     306 Tree::RB::XS::Iter->_new($key_or_node || $self, 1);
51             }
52              
53             sub rev_iter {
54 107     107 1 1661 my ($self, $key_or_node, $mode)= @_;
55 107 50 66     200 $key_or_node= $self->get_node($key_or_node, @_ > 2? $mode : GET_LE_LAST())
    100          
56             if @_ > 1 && ref $key_or_node ne 'Tree::RB::XS::Node';
57 107   66     238 Tree::RB::XS::Iter->_new($key_or_node || $self, -1);
58             }
59              
60              
61             *Tree::RB::XS::Node::min= *Tree::RB::XS::Node::left_leaf;
62             *Tree::RB::XS::Node::max= *Tree::RB::XS::Node::right_leaf;
63             *Tree::RB::XS::Node::successor= *Tree::RB::XS::Node::next;
64             *Tree::RB::XS::Node::predecessor= *Tree::RB::XS::Node::prev;
65              
66              
67             sub Tree::RB::XS::Node::strip {
68 1     1   16 my ($self, $cb)= @_;
69 1   33     10 my ($at, $next, $last)= (undef, $self->left_leaf || $self, $self->right_leaf || $self);
      33        
70 1         2 do {
71 3         8 $at= $next;
72 3         6 $next= $next->next;
73 3 100       9 if ($at != $self) {
74 2         6 $at->prune;
75 2 50       6 $cb->($at) if $cb;
76             }
77             } while ($at != $last);
78             }
79              
80             sub Tree::RB::XS::Node::as_lol {
81 3   33 3   24 my $self= $_[1] || $_[0];
82             [
83 3 100 50     41 $self->left? $self->left->as_lol : '*',
    100          
    100          
84             $self->right? $self->right->as_lol : '*',
85             ($self->color? 'R':'B').':'.($self->key||'')
86             ]
87             }
88              
89             sub Tree::RB::XS::Node::iter {
90 3     3   42 Tree::RB::XS::Iter->_new($_[0], 1);
91             }
92              
93             sub Tree::RB::XS::Node::rev_iter {
94 1     1   696 Tree::RB::XS::Iter->_new($_[0], -1);
95             }
96              
97              
98             # I can't figure out how to do the closure in XS yet
99             sub Tree::RB::XS::Iter::_new {
100 229     229   263 my $class= shift;
101 229         231 my ($self,$y);
102 229     0   576 $self= bless sub { Tree::XS::RB::Iter::next($y) }, $class;
  0         0  
103 229         475 Scalar::Util::weaken($y= $self);
104 229         893 $self->_init(@_);
105             }
106             sub Tree::RB::XS::Iter::clone {
107 0     0   0 my $self= shift;
108 0         0 ref($self)->_new($self);
109             }
110              
111              
112             *TIEHASH= *new;
113             *STORE= *put;
114             *CLEAR= *clear;
115              
116             sub hseek {
117 3     3 1 15407 my ($self, $key, $opts)= @_;
118 3 100 100     17 if (@_ == 2 && ref $key eq 'HASH') {
119 1         3 $opts= $key;
120 1         3 $key= $opts->{'-key'};
121             }
122 3   100     14 my $reverse= $opts && $opts->{'-reverse'} || 0;
123 3 100       23 my $node= defined $key? $self->get_node($key, $reverse? GET_LE_LAST() : GET_GE()) : undef;
    100          
124 3         20 $self->_set_hashiter($node, $reverse);
125             }
126              
127              
128             *LUEQUAL= *GET_EQ;
129             *LUGTEQ= *GET_GE;
130             *LUGTLT= *GET_LE;
131             *LUGREAT= *GET_GT;
132             *LULESS= *GET_LT;
133             *LUPREV= *GET_PREV;
134             *LUNEXT= *GET_NEXT;
135              
136              
137             1;
138              
139             __END__