File Coverage

blib/lib/Hash/KeyMorpher.pm
Criterion Covered Total %
statement 34 34 100.0
branch 9 10 90.0
condition n/a
subroutine 12 12 100.0
pod 7 7 100.0
total 62 63 98.4


line stmt bran cond sub pod time code
1             package Hash::KeyMorpher;
2              
3             =pod
4              
5             =head1 NAME
6              
7             Hash::KeyMorpher - Deep converter for naming conventions of hash keys
8              
9             =head1 DESCRIPTION
10              
11             Deeply change the nameing conventions for keys in hash structures, or simply change strings between naming conventions.
12             Converts to CamelCase, mixedCamel, delimited_string, UPPER, LOWER
13              
14              
15             =head1 SYNOPSYS
16              
17             use Hash::KeyMorpher; # import all, or
18             use Hash::KeyMorpher qw (key_morph to_camel to_mixed to_under to_delim); # import specific subs
19              
20             # To use the string converters:
21             $res = to_camel('my_string'); # MyString
22             $res = to_mixed('my_string'); # myString
23             $res = to_under('myString'); # my_string
24             $res = to_delim('myString','-'); # my-string
25              
26             # To morph keys in a hash, key_morph($hash,$method,$delim);
27             # method is one of camel,mixed,under,delim,upper,lower
28             $h1 = { 'level_one' => { 'LevelTwo' => 'foo' } };
29             $mixed = key_morph($h1,'mixed'); # { 'levelOne' => { 'levelTwo' => 'foo' } };
30             $delim = key_morph($h1,'delim','-'); # { 'level-one' => { 'level-two' => 'foo' } };
31            
32             # To morph acceccor keys
33             $obj = Hash::Accessor->new(qw /CamelCase mixedCase delim_str UPPER lower/);
34             $camel = key_morph($obj,'camel');
35            
36             =head1 EXPORT
37              
38             This module exports key_morph, to_camel, to_mixed, to_under and to_delim.
39             You will probably only need key_morph unless you really want the others.
40              
41              
42             =head1 FUNCTIONS
43              
44             =head2 _split_words($str)
45              
46             Splits a string into words, identifying boundaries using Capital Letters or Underscores etc.
47             This sub is not exported
48              
49             =head2 key_morph($hash,$method,$delim)
50              
51             $method can be one of (camel, mixed, delim, upper, lower).
52             $delim should be specified if using the delim method; by default its an empty string.
53              
54             =head2 to_camel($str)
55              
56             Convers string to CamelCase
57              
58             =head2 to_mixed($str)
59              
60             Convers string to mixedCamelCase
61              
62             =head2 to_under($str)
63              
64             Convers string to underscore_separated
65              
66             =head2 to_delim($str,$delim)
67              
68             Convers string to custom delimited-string (delimited by second parameter)
69              
70             =head2 to_upper($str)
71              
72             Returns the uppercase version of the rejoined string (removes undescores etc)
73              
74             =head2 to_lower($str)
75              
76             Returns the lowercase version of the rejoined string (removes undescores etc)
77              
78             =head1 AUTHOR AND SUPPORT
79              
80             Copyright (c) Michael Holloway 2013 , Emichael@thedarkwinter.comE
81              
82             =head1 COPYRIGHT
83              
84             Perl Arstistic License
85              
86             =cut
87              
88 3     3   30052 use 5.010;
  3         10  
  3         134  
89 3     3   19 use warnings;
  3         6  
  3         105  
90 3     3   17 use strict;
  3         10  
  3         552  
91             our $VERSION = '0.09';
92              
93 3     3   21 use base qw(Exporter);
  3         5  
  3         2666  
94             our @EXPORT = qw(to_mixed to_camel to_under to_delim key_morph);
95              
96             # warning, _split_words will return lower case! Should only be used internally which is why its not exported
97             sub _split_words {
98 68     68   119 my ($inp) = @_;
99 68         738 my @words = split( /(?<=[a-z])(?=[A-Z])|-|_/ , $inp);
100 68 100       237 return lc($words[0]) if $#words==0;
101 51         83 return map { lc } @words;
  110         340  
102             }
103              
104             # string converters
105 5     5 1 12 sub to_upper { return uc join '', _split_words(shift); }
106 5     5 1 8 sub to_lower { return lc join '', _split_words(shift); }
107 16     16 1 33 sub to_mixed { return lcfirst to_camel(shift); }
108 27     27 1 55 sub to_camel { return join('', map{ ucfirst $_ } _split_words(shift)); }
  49         211  
109 11     11 1 28 sub to_under { return lc(join('_', map { $_ } _split_words($_[0]))); }
  20         94  
110 13 100   13 1 47 sub to_delim { return lc(join( defined $_[1]?$_[1]:'', map { $_ } _split_words($_[0]))); }
  26         108  
111              
112             # recursively process hash
113             sub key_morph {
114 63     63 1 178 my ($inp,$sub,$delim) = @_;
115 63         285 my $disp = { upper => \&to_upper, lower => \&to_lower, mixed => \&to_mixed, camel => \&to_camel, under => \&to_under, delim => \&to_delim };
116 63 50       181 return $inp unless defined $disp->{$sub};
117            
118 63         87 my $r = ref($inp);
119             #print "$inp ($r)\n";
120 63 100       161 return {map { $disp->{$sub}->($_,$delim) => key_morph($inp->{$_},$sub,$delim); } keys %$inp} if ($r eq 'HASH');
  35         90  
121 35 100       73 return [ map key_morph($_,$sub,$delim), @$inp ] if ($r eq 'ARRAY');
122            
123 28         254 return $inp;
124             }
125              
126             1;