File Coverage

blib/lib/URL/Encode/PP.pm
Criterion Covered Total %
statement 78 79 98.7
branch 20 36 55.5
condition 7 14 50.0
subroutine 16 16 100.0
pod 0 8 0.0
total 121 153 79.0


line stmt bran cond sub pod time code
1             package URL::Encode::PP;
2              
3 2     2   82389 use strict;
  2         6  
  2         80  
4 2     2   12 use warnings;
  2         4  
  2         62  
5              
6 2     2   12 use Carp qw[];
  2         15  
  2         159  
7              
8             BEGIN {
9 2     2   4 our $VERSION = '0.03';
10 2         7 our @EXPORT_OK = qw[ url_encode
11             url_encode_utf8
12             url_decode
13             url_decode_utf8
14             url_params_each
15             url_params_flat
16             url_params_mixed
17             url_params_multi ];
18 2         10 require Exporter;
19 2         293 *import = \&Exporter::import;
20             }
21              
22             my (%DecodeMap, %EncodeMap);
23             BEGIN {
24 2     2   7 for my $ord (0..255) {
25 512         838 my $chr = pack 'C', $ord;
26 512         825 my $hex = sprintf '%.2X', $ord;
27 512         3173 $DecodeMap{lc $hex} = $chr;
28 512         948 $DecodeMap{uc $hex} = $chr;
29 512         11320 $DecodeMap{sprintf '%X%x', $ord >> 4, $ord & 15} = $chr;
30 512         1028 $DecodeMap{sprintf '%x%X', $ord >> 4, $ord & 15} = $chr;
31 512         1532 $EncodeMap{$chr} = '%' . $hex;
32             }
33 2         2085 $EncodeMap{"\x20"} = '+';
34             }
35              
36             sub url_decode {
37 196 50   196 0 81542 @_ == 1 || Carp::croak(q/Usage: url_decode(octets)/);
38 196         269 my ($s) = @_;
39 196 50       533 utf8::downgrade($s, 1)
40             or Carp::croak(q/Wide character in octet string/);
41 196         341 $s =~ y/+/\x20/;
42 196         1364 $s =~ s/%([0-9A-Za-z]{2})/$DecodeMap{$1}/gs;
43 196         921 return $s;
44             }
45              
46             sub url_decode_utf8 {
47 1 50   1 0 6 @_ == 1 || Carp::croak(q/Usage: url_decode_utf8(octets)/);
48 1         4 my $s = &url_decode;
49 1 50       6 utf8::decode($s)
50             or Carp::croak(q/Malformed UTF-8 in URL-decoded octets/);
51 1         5 return $s;
52             }
53              
54             sub url_encode {
55 195 50   195 0 85821 @_ == 1 || Carp::croak(q/Usage: url_encode(octets)/);
56 195         262 my ($s) = @_;
57 195 50       545 utf8::downgrade($s, 1)
58             or Carp::croak(q/Wide character in octet string/);
59 195         1367 $s =~ s/([^0-9A-Za-z_.~-])/$EncodeMap{$1}/gs;
60 195         971 return $s;
61             }
62              
63             sub url_encode_utf8 {
64 1 50   1 0 715 @_ == 1 || Carp::croak(q/Usage: url_encode_utf8(string)/);
65 1         3 my ($s) = @_;
66 1         4 utf8::encode($s);
67 1         4 return url_encode($s);
68             }
69              
70             sub url_params_each {
71 69 50 66 69 0 1181 @_ == 2 || @_ == 3 || Carp::croak(q/Usage: url_params_each(octets, callback [, utf8])/);
72 69         154 my ($s, $callback, $utf8) = @_;
73              
74 69 50       197 utf8::downgrade($s, 1)
75             or Carp::croak(q/Wide character in octet string/);
76              
77 69         299 foreach my $pair (split /[&;]/, $s, -1) {
78 130         2661 my ($k, $v) = split '=', $pair, 2;
79 130 100       270 $k = '' unless defined $k;
80 130 100       281 for ($k, defined $v ? $v : ()) {
81 184         210 y/+/\x20/;
82 184         263 s/%([0-9a-fA-F]{2})/$DecodeMap{$1}/gs;
83 184 50       454 if ($utf8) {
84 0 0       0 utf8::decode($_)
85             or Carp::croak("Malformed UTF-8 in URL-decoded octets");
86             }
87             }
88 130         285 $callback->($k, $v);
89             }
90             }
91              
92             sub url_params_flat {
93 20 50 33 20 0 13833 @_ == 1 || @_ == 2 || Carp::croak(q/Usage: url_params_flat(octets [, utf8])/);
94 20         30 my @p;
95             my $callback = sub {
96 33     33   50 my ($k, $v) = @_;
97 33         102 push @p, $k, $v;
98 20         104 };
99 20         65 url_params_each($_[0], $callback, $_[1]);
100 20         155 return \@p;
101             }
102              
103             sub url_params_mixed {
104 24 50 33 24 0 19193 @_ == 1 || @_ == 2 || Carp::croak(q/Usage: url_params_mixed(octets [, utf8])/);
105 24         114 my %p;
106             my $callback = sub {
107 47     47   71 my ($k, $v) = @_;
108 47 100       96 if (exists $p{$k}) {
109 14         26 for ($p{$k}) {
110 14 50       64 $_ = [$_] unless ref $_ eq 'ARRAY';
111 14         58 push @$_, $v;
112             }
113             }
114             else {
115 33         104 $p{$k} = $v;
116             }
117 24         116 };
118 24         78 url_params_each($_[0], $callback, $_[1]);
119 24         212 return \%p;
120             }
121              
122             sub url_params_multi {
123 24 50 33 24 0 22462 @_ == 1 || @_ == 2 || Carp::croak(q/Usage: url_params_multi(octets [, utf8])/);
124 24         40 my %p;
125             my $callback = sub {
126 47     47   81 my ($k, $v) = @_;
127 47   100     51 push @{ $p{$k} ||= [] }, $v;
  47         289  
128 24         117 };
129 24         79 url_params_each($_[0], $callback, $_[1]);
130 24         188 return \%p;
131             }
132              
133             1;
134