File Coverage

blib/lib/String/Incremental/FormatParser.pm
Criterion Covered Total %
statement 66 66 100.0
branch 24 24 100.0
condition n/a
subroutine 11 11 100.0
pod 1 1 100.0
total 102 102 100.0


line stmt bran cond sub pod time code
1             package String::Incremental::FormatParser;
2 15     15   74933 use 5.008005;
  15         51  
  15         624  
3 15     15   76 use warnings;
  15         27  
  15         369  
4 15     15   2326 use Mouse;
  15         9262890  
  15         96  
5 15     15   31650 use Data::Validator;
  15         96945  
  15         489  
6 15     15   19130 use String::Incremental::Char;
  15         1477  
  15         556  
7 15     15   17070 use String::Incremental::String;
  15         1508  
  15         535  
8 15     15   138 use MouseX::Types::Mouse qw( Str ArrayRef );
  15         30  
  15         69  
9 15     15   1255 use String::Incremental::Types qw( CharOrderStr CharOrderArrayRef is_CharOrderStr );
  15         113  
  15         111  
10              
11             has 'format' => ( is => 'ro', isa => Str );
12             has 'items' => ( is => 'ro', isa => ArrayRef );
13              
14             sub BUILDARGS {
15 48     48 1 9361 my ($class, @args) = @_;
16 48         155 return _parse( @args );
17             }
18              
19             sub _parse {
20 56     56   16366 my ($format, @rules) = @_;
21 56         176 my $pf = _parse_format( $format );
22              
23 134         190 my $mismatch = ( grep {
24 54         193 my $pos = $_->{pos};
25 134 100       558 defined $pos ? ( defined $rules[$pos] ? 0 : 1 ) : 0;
    100          
26 54 100       106 } @{$pf->{items}} ) ? 1 : 0;
27 54 100       164 if ( $mismatch ) {
28 3         7 my $msg = 'definition is mismatch: conversions v.s. rules';
29 3         74 die $msg;
30             }
31              
32 51         83 my @items;
33             my $char_upper;
34 51         75 for my $item ( @{$pf->{items}} ) {
  51         128  
35 125         287 my $class = "String::Incremental::$item->{type}";
36 125         421 my $obj;
37 125 100       370 if ( $item->{type} eq 'Char' ) {
38 79 100       827 $obj = $class->new(
39             order => $rules[ $item->{pos} ],
40             ( defined $char_upper ? ( upper => $char_upper ) : () ),
41             );
42 79         214 $char_upper = $obj;
43             }
44             else {
45 46 100       424 $obj = $class->new(
46             format => $item->{format},
47             value => ( defined $item->{pos} ? $rules[ $item->{pos} ] : '' ),
48             );
49             }
50 125         397 push @items, $obj;
51             }
52              
53             return +{
54 51         659 format => $pf->{format},
55             items => \@items,
56             };
57             }
58              
59             sub _parse_format {
60 61     61   11415 my ($format) = @_;
61 61 100       234 die 'no format is specified' unless defined $format;
62              
63 58         91 my ($format_rpl, @items);
64              
65 58         522 ($format_rpl = $format) =~ s{%(\d+)?=}{
66 56         159 my $n = $1;
67 56 100       185 $n = 1 unless defined $n;
68 56         475 join '', map '%s', (1..$n);
69             }gex;
70              
71 58         443 my @conv = $format =~ /(%(?:\d+(?:\.?\d+)?)?\S)/g;
72 58         108 my $pos = 0;
73 58         264 for my $conv ( @conv ) {
74 114         509 my ($dig, $type) = $conv =~ /%(\d+(?:\.?\d+)?)?(\S)/;
75 114 100       354 if ( $type eq '=' ) {
    100          
76 56 100       138 my $n = defined $dig ? $dig : 1;
77 56         179 for ( 1 .. $n ) {
78 93         363 push @items, +{ type => 'Char', pos => $pos };
79             }
80 56         196 $pos++;
81             }
82             elsif ( $type eq '%' ) {
83 13         69 push @items, +{ type => 'String', format => $conv, pos => undef };
84             }
85             else {
86 45         160 push @items, +{ type => 'String', format => $conv, pos => $pos };
87 45         104 $pos++;
88             }
89             }
90              
91             return +{
92 58         381 format => $format_rpl,
93             item_count => 0 + @items,
94             items => \@items,
95             };
96             }
97              
98             __PACKAGE__->meta->make_immutable();
99             __END__