File Coverage

blib/lib/String/Incremental/Char.pm
Criterion Covered Total %
statement 98 99 98.9
branch 28 28 100.0
condition n/a
subroutine 20 20 100.0
pod 6 7 85.7
total 152 154 98.7


line stmt bran cond sub pod time code
1             package String::Incremental::Char;
2 21     21   210452 use 5.008005;
  21         327  
  21         914  
3 21     21   116 use warnings;
  21         41  
  21         1979  
4 21     21   5410 use Mouse;
  21         265025  
  21         163  
5 21     21   15892 use Data::Validator;
  21         16877  
  21         743  
6 21     21   8785 use MouseX::Types::Mouse qw( Bool Int );
  21         21085  
  21         187  
7 21     21   19838 use String::Incremental::Types qw( Char CharOrderStr CharOrderArrayRef is_CharOrderStr );
  21         47  
  21         232  
8 21     21   33733 use Try::Tiny;
  21         41029  
  21         2987  
9              
10             use overload (
11             '""' => \&as_string,
12             '++' => \&increment,
13             '--' => \&decrement,
14 76     76   1868 '=' => sub { $_[0] },
15 21     21   51476 );
  21         26078  
  21         390  
16              
17             has 'order' => ( is => 'ro', isa => CharOrderArrayRef );
18             has 'upper' => ( is => 'ro', isa => __PACKAGE__, predicate => 'has_upper' );
19             has '__i' => ( is => 'rw', isa => Int );
20             has '__size' => ( is => 'ro', isa => Int );
21              
22             sub BUILDARGS {
23 127     127 1 130055 my ($class, %args) = @_;
24 127         584 my $v = Data::Validator->new(
25             order => { isa => CharOrderStr|CharOrderArrayRef },
26             upper => { isa => __PACKAGE__, optional => 1 },
27             set => { isa => Char, optional => 1 },
28             __i => { isa => Int, default => 0 }, # for internal use
29             );
30 127         40947 %args = %{$v->validate( \%args )};
  127         461  
31              
32 121 100       5137 if ( is_CharOrderStr( $args{order} ) ) {
33 111         617 $args{order} = [ split //, $args{order} ];
34             }
35              
36             %args = (
37 121         819 %args,
38 121         456 __size => 0 + @{$args{order}},
39             );
40              
41 121 100       514 if ( $args{__i} >= $args{__size} ) {
42 2         3 my $msg = '__i: should be less than size of "order"';
43 2         40 die $msg;
44             }
45              
46 119         1437 return \%args;
47             }
48              
49             sub BUILD {
50 119     119 1 244 my ($self, $args) = @_;
51 119 100       624 if ( exists $args->{set} ) {
52 3         12 $self->set( $args->{set} );
53             }
54             }
55              
56             sub as_string {
57 426     426 1 5457 my ($self) = @_;
58 426         2477 return $self->order->[ $self->__i ];
59             }
60              
61             sub set {
62 20     20 1 1482 my ($self, $ch, $opts) = @_;
63 20         91 my $v_opts = Data::Validator->new(
64             test => { isa => Bool, default => 0 },
65             );
66 20 100       1303 $opts = $v_opts->validate( %{$opts || {}} );
  20         156  
67              
68 19 100       584 unless ( defined $ch ) {
69 1         19 die 'value to set must be specified';
70             }
71 18 100       94 unless ( $ch =~ /^.$/ ) {
72 1         17 die 'must be specified as a character';
73             }
74 17         34 my ($i, $found) = ( 0, 0 );
75 17         25 for ( @{$self->order} ) {
  17         71  
76 45 100       99 if ( $_ eq $ch ) {
77 14         21 $found = 1;
78 14         25 last;
79             }
80 31         41 $i++;
81             }
82 17 100       52 unless ( $found ) {
83 3         82 my $msg = srintf( '"%s" is not in order', $ch );
84 0         0 die $msg;
85             }
86 14 100       41 unless ( $opts->{test} ) {
87 12         152 $self->__i( $i );
88             }
89 14         1061 return "$self";
90             }
91              
92             sub increment {
93 73     73 1 110 my ($self) = @_;
94 73         78 my ($i_try, $ch);
95 73         165 $i_try = $self->__i + 1;
96              
97 73 100       222 if ( $i_try >= $self->__size ) {
98 26 100       84 if ( $self->has_upper() ) {
99 19         51 my $upper = $self->upper;
100             try {
101 19     19   1151 $upper->increment();
102 12         24 $i_try = 0;
103             } catch {
104 7     7   78 my ($msg) = @_;
105 7         56 die $msg;
106 19         212 };
107             }
108             else {
109 7         33 my $msg = 'cannot increment';
110 7         69 die $msg;
111             }
112             }
113              
114 59         307 $self->__i( $i_try );
115 59         116 return $self->as_string();
116             }
117              
118             sub decrement {
119 59     59 1 94 my ($self) = @_;
120 59         87 my ($i_try, $ch);
121 59         148 $i_try = $self->__i - 1;
122              
123 59 100       151 if ( $i_try < 0 ) {
124 19 100       65 if ( $self->has_upper() ) {
125 14         40 my $upper = $self->upper;
126             try {
127 14     14   844 $upper->decrement();
128 9         33 $i_try = $self->__size - 1;
129             } catch {
130 5     5   57 my ($msg) = @_;
131 5         37 die $msg;
132 14         152 };
133             }
134             else {
135 5         10 my $msg = 'cannot decrement';
136 5         42 die $msg;
137             }
138             }
139              
140 49         271 $self->__i( $i_try );
141 49         108 return $self->as_string();
142             }
143              
144             sub re {
145 137     137 0 207 my ($self) = @_;
146 576         609 my $re = join '', map {
147 137         447 my $i = $_;
148             # ref: http://search.cpan.org/perldoc?perlrecharclass#Special_Characters_Inside_a_Bracketed_Character_Class
149 576 100       1888 ( $i =~ m/[\\\^\-\[\]]/ ) ? "\\${i}" : $i;
150 137         164 } @{$self->order};
151 137         1709 return qr/[$re]/;
152             }
153              
154             __PACKAGE__->meta->make_immutable();
155             __END__