File Coverage

blib/lib/Text/PRN/Slurp.pm
Criterion Covered Total %
statement 89 96 92.7
branch 22 38 57.8
condition 4 8 50.0
subroutine 14 14 100.0
pod 4 4 100.0
total 133 160 83.1


line stmt bran cond sub pod time code
1             package Text::PRN::Slurp;
2              
3 2     2   138207 use strict;
  2         13  
  2         60  
4 2     2   11 use warnings;
  2         5  
  2         60  
5              
6 2     2   923 use IO::File;
  2         17277  
  2         242  
7 2     2   1020 use IO::Scalar;
  2         12433  
  2         155  
8 2     2   1179 use Data::Dumper;
  2         13750  
  2         129  
9             =head1 NAME
10              
11             Text::PRN::Slurp - Parse and read .PRN File Extension
12              
13             =head1 VERSION
14              
15             Version 1.05
16              
17             =cut
18              
19 2     2   40 use vars qw/$VERSION/;
  2         5  
  2         1829  
20              
21             $VERSION = 1.05;
22              
23              
24             =head1 SYNOPSIS
25              
26             PRN, short name for Printable, is used as the file extension for files padded with space characters.
27              
28             use Text::PRN::Slurp;
29              
30             my $slurp = Text::PRN::Slurp->new->load(
31             'file' => $file,
32             'file_headers' => [ q{A}, q{B}, q{C}, q{D} ]
33             );
34              
35             =head1 USAGE
36              
37             use Text::PRN::Slurp;
38              
39             my $data = Text::PRN::Slurp->load(file => $filename ,file_headers => ['A','B','C'] [,%options]);
40             my $data = Text::PRN::Slurp->load(filehandle => $filehandle ,file_headers => ['A','B','C'] [,%options]);
41             my $data = Text::PRN::Slurp->load(string => $string ,file_headers => ['A','B','C'] [,%options]);
42              
43             =head1 EXPORT
44              
45             =head2 new
46              
47             Constructors method
48              
49             =cut
50              
51             sub new {
52 3     3 1 2332 my ( $class ) = @_;
53 3         17 return bless { 'options' => {} }, $class;
54             }
55              
56             =head2 load
57              
58             my $data = Text::PRN::Slurp->load(file => $filename ,file_headers => ['A','B','C']);
59             my $data = Text::PRN::Slurp->load(filehandle => $filehandle ,file_headers => ['A','B','C']);
60              
61             Returns an arrayref of hashrefs. Its fields are used as the keys for each of the hashes.
62              
63             =cut
64              
65             sub load {
66 2     2 1 8 my ( $self, %opt ) = @_;
67              
68 2         6 my %default = ( binary => 1 );
69 2         9 %opt = (%default, %opt);
70              
71 2 50       8 if ( !defined $opt{'file_headers'} ) {
72 0         0 die "File headers is needed to parse file";
73             }
74 2 50       8 if ( ref $opt{'file_headers'} ne 'ARRAY' ) {
75 0         0 die "File headers needed to be an array";
76             }
77              
78 2 0 33     11 if ( !defined $opt{'filehandle'} &&
      33        
79             !defined $opt{'file'} &&
80             !defined $opt{'string'}
81             ) {
82 0         0 die "Need either a file, filehandle or string to work with";
83             }
84              
85 2         4 my $io;
86 2 50       6 if ( defined $opt{'filehandle'} ) {
87 0         0 $io = $opt{'filehandle'};
88 0         0 delete $opt{'filehandle'};
89             }
90              
91 2 50       6 if ( defined $opt{'file'} ) {
92 2         13 $io = new IO::File;
93 2 50   1   142 open( $io, '<:encoding(UTF-8)', $opt{'file'} )
  1         6  
  1         2  
  1         5  
94             or die "Could not open $opt{file} $!";
95 2         11218 delete $opt{'file'};
96             }
97              
98 2 50       19 if ( defined $opt{'string'} ) {
99 0         0 $io = IO::Scalar->new( \$opt{'string'} );
100 0         0 delete $opt{'string'};
101             }
102              
103 2         10 $self->{'options'} = \%opt;
104              
105 2         7 return $self->_from_io_handler($io,\%opt);
106             }
107              
108             sub _from_io_handler {
109 2     2   6 my ( $self, $io, $opt_ref ) = @_;
110              
111 2 50       6 die "File headers not found" unless $self->file_headers;
112              
113             ## Assume first row is heading
114 2         52 my $first_row = <$io>;
115 2         28 $self->_parse_header( $first_row );
116              
117 2 50       7 die "File headers not matching" unless $self->columns_map;
118              
119 2         3 my @file_data_as_array;
120 2         10 while ( my $row = <$io> ) {
121 10         25 push @file_data_as_array, $self->_parse_row( $row );
122             }
123              
124 2         46 return \@file_data_as_array;
125             }
126              
127             sub _parse_header {
128 2     2   8 my ( $self, $row ) = @_;
129              
130 2         9 chomp $row;
131 2         3 my @file_header = @{ $self->file_headers };
  2         6  
132              
133 2         4 my %col_length_map;
134 2         6 foreach my $col_heading ( @file_header ) {
135 7         85 $row =~m{($col_heading\s+)}i;
136 7 100       34 $row =~m{($col_heading\s?)}i if not $1;
137              
138 7 100       30 warn q{Columns doesn't seems to be matching} unless $1;
139 7 100       92 next unless $1;
140              
141 6         11 my $table_column = $1;
142 6         13 my $table_column_length = length $table_column;
143             # remove leading and trailing spaces
144 6         29 $table_column =~s{^\s+|\s+$}{}g;
145 6         24 $col_length_map{ $table_column } = $table_column_length;
146             }
147 2         25 $self->{'options'}->{'col_length_map'} = \%col_length_map;
148 2         7 return 1;
149             }
150              
151             sub _parse_row {
152 10     10   30 my ( $self, $row ) = @_;
153              
154 10         25 chomp $row;
155 10         15 my @file_header = @{ $self->file_headers };
  10         19  
156 10         18 my $col_length_map = $self->columns_map;
157 10         16 my $string_offset = 0;
158 10         13 my %extracted_row_data;
159              
160 10         19 foreach my $col ( @file_header ) {
161 35   100     76 my $col_length = $col_length_map->{ $col } || 0;
162 35 100       60 next unless $col_length;
163              
164 30         80 my $col_data = substr $row, $string_offset, $col_length;
165             # remove leading and trailing spaces
166 30         157 $col_data =~s{^\s+|\s+$}{}g;
167 30         88 $extracted_row_data{ $col } = $col_data;
168 30         67 $string_offset += $col_length;
169             }
170 10         76 return \%extracted_row_data;
171             }
172              
173             =head2 file_headers
174              
175             Returns an arrayref of file headers
176              
177             =cut
178              
179             sub file_headers {
180 14     14 1 22 my ( $self ) = @_;
181 14 50       31 return unless $self->{'options'};
182 14 50       36 return unless ref $self->{'options'} eq 'HASH';
183 14         39 return $self->{'options'}->{'file_headers'};
184             }
185              
186             =head2 columns_map
187              
188             Returns an hashref of file headers with string offset
189              
190             =cut
191              
192             sub columns_map {
193 12     12 1 22 my ( $self ) = @_;
194 12 50       25 return unless $self->{'options'};
195 12 50       24 return unless ref $self->{'options'} eq 'HASH';
196              
197 12         18 my $col_length_map = $self->{'options'}->{'col_length_map'};
198 12 50       22 return unless $col_length_map;
199 12 50       26 return unless scalar keys %$col_length_map;
200 12         20 return $col_length_map;
201             }
202              
203             =head1 AUTHOR
204              
205             Rakesh Kumar Shardiwal, C<< >>
206              
207             =head1 BUGS
208              
209             Please report any bugs or feature requests to C, or through
210             the web interface at L. I will be notified, and then you'll
211             automatically be notified of progress on your bug as I make changes.
212              
213             =head1 SUPPORT
214              
215             You can find documentation for this module with the perldoc command.
216              
217             perldoc Text::PRN::Slurp
218              
219              
220             You can also look for information at:
221              
222             =over 4
223              
224             =item * RT: CPAN's request tracker (report bugs here)
225              
226             L
227              
228             =item * AnnoCPAN: Annotated CPAN documentation
229              
230             L
231              
232             =item * CPAN Ratings
233              
234             L
235              
236             =item * Search CPAN
237              
238             L
239              
240             =back
241              
242              
243             =head1 ACKNOWLEDGEMENTS
244              
245              
246             =head1 LICENSE AND COPYRIGHT
247              
248             Copyright 2016 Rakesh Kumar Shardiwal.
249              
250             This program is free software; you can redistribute it and/or modify it
251             under the terms of the the Artistic License (2.0). You may obtain a
252             copy of the full license at:
253              
254             L
255              
256             Any use, modification, and distribution of the Standard or Modified
257             Versions is governed by this Artistic License. By using, modifying or
258             distributing the Package, you accept this license. Do not use, modify,
259             or distribute the Package, if you do not accept this license.
260              
261             If your Modified Version has been derived from a Modified Version made
262             by someone other than you, you are nevertheless required to ensure that
263             your Modified Version complies with the requirements of this license.
264              
265             This license does not grant you the right to use any trademark, service
266             mark, tradename, or logo of the Copyright Holder.
267              
268             This license includes the non-exclusive, worldwide, free-of-charge
269             patent license to make, have made, use, offer to sell, sell, import and
270             otherwise transfer the Package with respect to any patent claims
271             licensable by the Copyright Holder that are necessarily infringed by the
272             Package. If you institute patent litigation (including a cross-claim or
273             counterclaim) against any party alleging that the Package constitutes
274             direct or contributory patent infringement, then this Artistic License
275             to you shall terminate on the date that such litigation is filed.
276              
277             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
278             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
279             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
280             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
281             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
282             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
283             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
284             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
285              
286              
287             =cut
288              
289             1; # End of Text::PRN::Slurp