File Coverage

blib/lib/Data/ConversionChain.pm
Criterion Covered Total %
statement 15 106 14.1
branch 0 32 0.0
condition 0 6 0.0
subroutine 5 19 26.3
pod 14 14 100.0
total 34 177 19.2


line stmt bran cond sub pod time code
1             package Data::ConversionChain;
2              
3 1     1   25411 use 5.006;
  1         4  
  1         56  
4 1     1   17 use strict;
  1         2  
  1         39  
5 1     1   6 use warnings FATAL => 'all';
  1         6  
  1         79  
6              
7             # For the developers debugging - will be removed in later versions
8 1     1   1252 use Data::Dumper;
  1         10980  
  1         85  
9              
10             # Additional conversions
11 1     1   1709 use Digest::SHA qw(sha1 sha224 sha256 sha384 sha512 sha512224 sha512256);
  1         6986  
  1         1679  
12              
13             =head1 NAME
14              
15             Data::ConversionChain - Create permanent conversion chains
16              
17             =head1 VERSION
18              
19             Version 0.04
20              
21             =cut
22              
23             our $VERSION = '0.04';
24              
25             =head1 SYNOPSIS
26              
27             NOTE I created this module to assist me with another and found it so useful and different I decided to release it, I am still actively working on it and input is welcome, but be warned it is no where near complete.
28              
29             Data::ConversionChain Allows you to create data manipulation 'objects' for when you are working in a situation where you need to shift one type of data into another or adjust text in specific ways, it was mainly created because the owner hates pack, but it can be very useful for padding data binary/bytes/hex conversions and more.
30              
31             Here is a code snippet for converting a standard number into an equivlent that would be generated by a signed int32 in perl, the output will be returned in hex.
32              
33             use Data::ConversionChain;
34              
35             my $n2h = Data::ConversionChain->new(qw( i32s hex ));
36              
37             my $result = $n2h->proc('34243');
38              
39             # result = c3850000
40              
41             I will continue expanding this module including sha, md5 and the entire of pack's data types usable in what I class to be a far more friendly way.
42              
43             =head1 Callable functions
44              
45             =head2 new
46              
47             Create a new basic object.
48              
49             my $sha2hex = Data::ConversionChain->new(qw( sha256 hex ));
50              
51             =cut
52              
53             sub new {
54 0     0 1   my $class = shift;
55 0           my $conv = [@_];
56              
57 0 0         if (scalar(@{ $conv }) == 0) {
  0 0          
  0            
58             # Passed a blank new() make a template
59 0           $conv->[0] = { input => 'ascii', conversion => [], output => 'ascii' };
60             }
61             elsif (scalar(@{ $conv }) > 0) {
62 0 0         if (ref($conv->[0]) eq 'HASH') {
63             # Ok passed full struct
64 0           $conv = $conv->[0];
65             } else {
66             # Ok a conversion chain list
67 0           $conv = { input => 'ascii', conversion => $conv, output => 'ascii' };
68             }
69             }
70              
71             # warn Dumper($conv);
72              
73 0 0         if (!$conv->{input}) { $conv->{input} = 'ascii' }
  0            
74 0 0         if (!$conv->{output}) { $conv->{output} = 'ascii' }
  0            
75 0 0         if (!$conv->{conversion}) { $conv->{conversion} = [] }
  0            
76              
77 0           my $self = {
78             config => {
79             input => $conv->{input},
80             output => $conv->{output},
81             conversion => $conv->{conversion},
82             },
83             };
84              
85 0 0         if (ref($conv->{conversion}) eq 'ARRAY') {
86             # Ok this is a conversion chain... so lets create another object
87 0           my $head = shift @{ $conv->{conversion} };
  0            
88              
89             # Check for parameterized arguments
90 0           my $cmdbase = $head;
91 0 0         if ($head =~ m#^(.*?)\(#) { $cmdbase = $1 }
  0            
92              
93             # Keep the integrity of datatype incase of special conversions
94 0 0         if ( defined Data::ConversionChain->cmddat($self,$cmdbase) ) {
95 0 0         if ( my $datatype = Data::ConversionChain->cmddat($self,$cmdbase,'type') ) { $self->{config}->{datatype} = $datatype }
  0            
96 0           else { $self->{config}->{datatype} = $conv->{input} }
97             }
98 0           else { $self->{config}->{datatype} = $head }
99              
100 0           $self->{config}->{conversion} = $head;
101 0 0         if (scalar @{ $conv->{conversion} } > 0) {
  0            
102 0           $self->{config}->{output} = Data::ConversionChain->new({
103             input => $self->{config}->{datatype},
104             conversion => $conv->{conversion},
105             output => $conv->{output}
106             });
107             } else {
108 0           $self->{config}->{output} = $self->{config}->{datatype};
109             }
110             }
111              
112 0           bless $self, $class;
113             }
114              
115             =head2 proc
116              
117             Feed data into the filter and get the conversion returned.
118              
119             =cut
120              
121             sub proc {
122 0     0 1   my $self = shift;
123 0           my $data = shift;
124              
125 0           my $conversion = $self->{config}->{conversion};
126              
127 0           my $cmd = $conversion;
128 0           my @args = ();
129 0           my $proc = "";
130              
131 0 0         if ($conversion =~ m#^(.*?)\((.*?)\)#) {
132 0           $cmd = $1;
133 0           @args = split(/,/,$2);
134             }
135              
136 0 0         if ($self->cmddat($cmd,'ext')) {
137 0           $proc = &{ $self->cmddat($cmd,'sub') }($data,@args);
  0            
138             } else {
139 0           $proc = &{ $self->cmddat($cmd,'sub') }($self,$data,@args);
  0            
140             }
141              
142 0           return $self->output($proc);
143             # warn "Convert to: $newdata";
144             }
145              
146              
147             =head1 Datatype conversion filters
148              
149             Usable in new in formation of a conversion chain.
150              
151             =head2 i64u
152              
153             Convert an object into the equivalent of an unsigned int64.
154              
155             Requires: 1 argument
156              
157             =cut
158              
159             sub i64u {
160 0     0 1   my $self = shift;
161 0           my $data = shift;
162              
163 0           return pack('Q',$data);
164             }
165              
166             =head2 i64s
167              
168             Convert an object into the equivalent of an signed int64.
169              
170             Requires: 1 argument
171              
172             =cut
173              
174             sub i64s {
175 0     0 1   my $self = shift;
176 0           my $data = shift;
177              
178 0           return pack('q',$data);
179             }
180              
181             =head2 i32s
182              
183             Convert an object into the equivalent of an signed int32.
184              
185             Requires: 1 argument
186              
187             =cut
188              
189             sub i32s {
190 0     0 1   my $self = shift;
191 0           my $data = shift;
192              
193 0           return pack('l',$data);
194             }
195              
196             =head2 i32u
197              
198             Convert an object into the equivalent of an unsigned int32.
199              
200             Requires: 1 argument
201              
202             =cut
203              
204             sub i32u {
205 0     0 1   my $self = shift;
206 0           my $data = shift;
207              
208 0           return pack('V',$data);
209             }
210              
211             =head2 hex
212              
213             Convert data into hex.
214              
215             Requires: 0 arguments
216              
217             =cut
218              
219             sub hex {
220 0     0 1   my $self = shift;
221 0           my ($data) = @_;
222              
223 0           return unpack('H*',$data);
224             }
225              
226             =head2 sha1
227              
228             Required arguments: 0
229              
230             Convert data to sha1 (BYTES).
231              
232             =head2 sha256
233              
234             Required arguments: 0
235              
236             Convert data to sha256 (BYTES).
237              
238             =head2 sha384
239              
240             Required arguments: 0
241              
242             Convert data to sha384 (BYTES).
243              
244             =head2 sha512
245              
246             Required arguments: 0
247              
248             Convert data to sha512 (BYTES).
249              
250             =head2 sha512224
251              
252             Required arguments: 0
253              
254             Convert data to sha512224 (BYTES).
255              
256             =head2 sha512256
257              
258             Required arguments: 0
259              
260             Convert data to sha512256 (BYTES).
261              
262             =head1 Data manipulation filters
263              
264             =head2 pad_right
265              
266             Required arguments: 2
267              
268             Syntax: pad_right(LENGTH,PAD_CHARACTER)
269              
270             Pad the right hand side of the supplied data with ARG1 upto a length of ARG0.
271              
272             =cut
273              
274             sub pad_right {
275 0     0 1   my $self = shift;
276 0           my ($data,$length,$char) = @_;
277              
278 0           while(length($data) < $length) { $data .= $char }
  0            
279              
280 0           return $data;
281             }
282              
283             =head2 pad_left
284              
285             Required arguments: 2
286              
287             Syntax: pad_left(LENGTH,PAD_CHARACTER)
288              
289             Pad the left hand side of the supplied data with ARG1 upto a length of ARG0.
290              
291             =cut
292              
293             sub pad_left {
294 0     0 1   my $self = shift;
295 0           my ($data,$length,$char) = @_;
296              
297 0           while(length($data) < $length) { $data = $char.$data; }
  0            
298              
299 0           return $data;
300             }
301              
302             =head2 truncate_right
303              
304             Truncate text treating the right hand side of the data block as the start point.
305              
306             Required arguments: 1
307              
308             Syntax: truncate_right(10)
309              
310             =cut
311              
312             sub truncate_right {
313 0     0 1   my $self = shift;
314 0           my ($data,$length) = @_;
315              
316 0           return substr $data, (length($data) - $length);
317             }
318              
319             =head2 truncate_left
320              
321             Truncate text treating the left hand side of the data block as the start point.
322              
323             =cut
324              
325             sub truncate_left {
326 0     0 1   my $self = shift;
327 0           my ($data,$length) = @_;
328              
329 0           return substr $data, 0, $length;
330             }
331              
332             =head1 Internal callable functions
333              
334             These are used internally by the module, do not call them directly unless you have a very good reason!
335              
336             =head2 input
337              
338             Tell the object what it can expect on its input, this is very rarely required or used.
339              
340             =cut
341              
342 0     0 1   sub input {}
343              
344             =head2 output
345              
346             Send data through the output chain or return if the last object in the chain.
347              
348             =cut
349              
350             sub output {
351 0     0 1   my $self = shift;
352 0           my $data = shift;
353              
354 0 0         if ( ref($self->{config}->{output}) eq 'Data::ConversionChain' ) {
355 0           return $self->{config}->{output}->proc($data);
356             }
357              
358 0           return $data;
359             }
360              
361              
362             =head2 cmddat
363              
364             Receive information back or sub references for data types.
365              
366             =cut
367              
368             sub cmddat {
369 0     0 1   my $self = shift;
370 0           my ($cmd,$type) = @_;
371              
372 0           my $cmdset = {
373             pad_right => {
374             sub => \&pad_right,
375             type => "",
376             },
377             pad_left => {
378             sub => \&pad_left,
379             type => "",
380             },
381             truncate_left => {
382             sub => \&truncate_left,
383             type => "",
384             },
385             truncate_right => {
386             sub => \&truncate_right,
387             type => "",
388             },
389             md5 => {
390             sub => \&md5,
391             type => 'bytes',
392             },
393             hex => {
394             sub => \&hex,
395             type => 'hex',
396             },
397             i64s => {
398             sub => \&i64s,
399             type => 'bytes'
400             },
401             i64u => {
402             sub => \&i64u,
403             type => 'bytes',
404             },
405             i32s => {
406             sub => \&i32s,
407             type => 'bytes'
408             },
409             i32u => {
410             sub => \&i32u,
411             type => 'bytes',
412             },
413             sha1 => {
414             sub => \&sha1,
415             type => 'bytes',
416             ext => 1,
417             },
418             sha224 => {
419             sub => \&sha224,
420             type => 'bytes',
421             ext => 1,
422             },
423             sha256 => {
424             sub => \&sha256,
425             type => 'bytes',
426             ext => 1,
427             },
428             sha384 => {
429             sub => \&sha384,
430             type => 'bytes',
431             ext => 1,
432             },
433             sha512 => {
434             sub => \&sha512,
435             type => 'bytes',
436             ext => 1,
437             },
438             sha512224 => {
439             sub => \&sha512224,
440             type => 'bytes',
441             ext => 1,
442             },
443             sha512256 => {
444             sub => \&sha512256,
445             type => 'bytes',
446             ext => 1,
447             },
448             };
449              
450 0 0 0       return 1 if ( (!$type) && ($cmdset->{$cmd}) );
451 0 0 0       return 0 if ( (!$type) && (!$cmdset->{$cmd}) );
452              
453 0           return $cmdset->{$cmd}->{$type};
454             }
455              
456              
457             =head1 AUTHOR
458              
459             Paul G Webster, C<< >>
460              
461             =head1 BUGS
462              
463             Please report any bugs or feature requests to C, or through
464             the web interface at L. I will be notified, and then you'll
465             automatically be notified of progress on your bug as I make changes.
466              
467             =head1 SUPPORT
468              
469             You can find documentation for this module with the perldoc command.
470              
471             perldoc Data::ConversionChain
472              
473              
474             You can also look for information at:
475              
476             =over 4
477              
478             =item * RT: CPAN's request tracker (report bugs here)
479              
480             L
481              
482             =item * AnnoCPAN: Annotated CPAN documentation
483              
484             L
485              
486             =item * CPAN Ratings
487              
488             L
489              
490             =item * Search CPAN
491              
492             L
493              
494             =back
495              
496              
497             =head1 ACKNOWLEDGEMENTS
498              
499              
500             =head1 LICENSE AND COPYRIGHT
501              
502             Copyright 2014 Paul G Webster.
503              
504             This program is distributed under the (Revised) BSD License:
505             L
506              
507             Redistribution and use in source and binary forms, with or without
508             modification, are permitted provided that the following conditions
509             are met:
510              
511             * Redistributions of source code must retain the above copyright
512             notice, this list of conditions and the following disclaimer.
513              
514             * Redistributions in binary form must reproduce the above copyright
515             notice, this list of conditions and the following disclaimer in the
516             documentation and/or other materials provided with the distribution.
517              
518             * Neither the name of Paul G Webster's Organization
519             nor the names of its contributors may be used to endorse or promote
520             products derived from this software without specific prior written
521             permission.
522              
523             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
524             "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
525             LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
526             A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
527             OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
528             SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
529             LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
530             DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
531             THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
532             (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
533             OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
534              
535              
536             =cut
537              
538             1; # End of Data::ConversionChain
539