File Coverage

blib/lib/Data/Crumbr/Util.pm
Criterion Covered Total %
statement 41 45 91.1
branch 22 28 78.5
condition 7 12 58.3
subroutine 11 11 100.0
pod 3 3 100.0
total 84 99 84.8


line stmt bran cond sub pod time code
1             package Data::Crumbr::Util;
2             $Data::Crumbr::Util::VERSION = '0.1.2';
3             # ABSTRACT: utility functions for Data::Crumbr
4 6     6   44 use strict;
  6         12  
  6         231  
5 6     6   30 use Carp;
  6         12  
  6         372  
6 6     6   37 use Scalar::Util qw< reftype blessed >;
  6         22  
  6         751  
7              
8             sub json_leaf_encoder {
9 10     10 1 63 require B;
10 10         33 return \&_json_leaf_encode;
11             }
12              
13             {
14             my $slash_escaped;
15              
16             BEGIN {
17 6     6   3469 $slash_escaped = {
18             0x22 => '"',
19             0x5C => "\\",
20             0x2F => '/',
21             0x08 => 'b',
22             0x0C => 'f',
23             0x0A => 'n',
24             0x0D => 'r',
25             0x09 => 't',
26             };
27             } ## end BEGIN
28              
29             sub _json_leaf_encode {
30 101 50   101   496 return 'null' unless defined $_[0];
31              
32 101         159 my $reftype = ref($_[0]);
33 101 100       196 return '[]' if $reftype eq 'ARRAY';
34 96 100       154 return '{}' if $reftype eq 'HASH';
35 91 100       176 return (${$_[0]} ? 'true' : 'false')
  8 100       35  
36             if $reftype eq 'SCALAR';
37              
38 83 100       220 if (my $package = blessed($_[0])) {
39 2         5 my $reftype = reftype($_[0]);
40 2 100 33     15 return (${$_[0]} ? 'true' : 'false')
  2 50       38  
41             if ($reftype eq 'SCALAR') && ($package =~ /bool/mxsi);
42             }
43              
44 81 50       156 croak "unsupported ref type $reftype" if $reftype;
45              
46 81         107 my $number_flags = B::SVp_IOK() | B::SVp_NOK();
47 81 50 66     632 return $_[0]
      66        
48             if (B::svref_2object(\$_[0])->FLAGS() & $number_flags)
49             && 0 + $_[0] eq $_[0]
50             && $_[0] * 0 == 0;
51              
52             my $string = join '', map {
53 56         279 my $cp = ord($_);
  245         337  
54              
55 245 50 66     828 if (exists $slash_escaped->{$cp}) {
    100          
    50          
56 0         0 "\\$slash_escaped->{$cp}";
57             }
58             elsif ($cp >= 32 && $cp < 128) { # ASCII
59 233         485 $_;
60             }
61             elsif ($cp < 0x10000) { # controls & BML
62 12         58 sprintf "\\u%4.4X", $cp;
63             }
64             else { # beyond BML
65 0         0 my $hi = ($cp - 0x10000) / 0x400 + 0xD800;
66 0         0 my $lo = ($cp - 0x10000) % 0x400 + 0xDC00;
67 0         0 sprintf "\\u%4.4X\\u%4.4X", $hi, $lo;
68             }
69             } split //, $_[0];
70 56         271 return qq<"> . $string . qq<">;
71             } ## end sub _json_leaf_encode
72             }
73              
74             sub uri_encoder {
75 3     3 1 1703 require Encode;
76 3         31014 return \&_uri_encoder;
77             }
78              
79             {
80             my %is_unreserved;
81              
82             BEGIN {
83 6     6   121 my @u = ('a' .. 'z', 'A' .. 'Z', '0' .. '9', qw< - _ . ~ >);
84 6         41 %is_unreserved = map { $_ => 1 } @u;
  396         1943  
85             }
86              
87             sub _uri_encoder {
88 57     57   854 my $octets = Encode::encode('UTF-8', $_[0], Encode::FB_CROAK());
89             return join '',
90 57 100       2947 map { $is_unreserved{$_} ? $_ : sprintf('%%%2.2X', ord $_); }
  204         564  
91             split //, $octets;
92             } ## end sub _uri_encoder
93             }
94              
95             sub id_encoder {
96 6     6 1 72 return sub { $_[0] };
  6     6   28  
97             }
98              
99             1;
100              
101             __END__
102              
103             =pod
104              
105             =encoding utf-8
106              
107             =head1 NAME
108              
109             Data::Crumbr::Util - utility functions for Data::Crumbr
110              
111             =head1 VERSION
112              
113             version 0.1.2
114              
115             =head1 DESCRIPTION
116              
117             Utility functions for Data::Crumbr.
118              
119             =head2 INTERFACE
120              
121             =over
122              
123             =item B<< id_encoder >>
124              
125             my $encoder = id_encoder();
126              
127             trivial encoding function that just returns its first argument (i.e. no
128             real encoding is performed).
129              
130             =item B<< json_leaf_encoder >>
131              
132             my $encoder = json_leaf_encoder();
133              
134             encoding function that returns a JSON-compliant value, only for leaf
135             values. It works on:
136              
137             =over
138              
139             =item *
140              
141             plain strings, returned after JSON encoding (e.g. tranformation of
142             newlines, etc.)
143              
144             =item *
145              
146             empty array references, in which case string C<[]> is returned
147              
148             =item *
149              
150             empty hash references, in which case string C<{}> is returned
151              
152             =item *
153              
154             null values, in which case string C<null> is returned
155              
156             =back
157              
158             =item B<< uri_encoder >>
159              
160             my $encoder = uri_encoder();
161              
162             encoding function that then encodes strings according to URI encoding
163             (i.e. percent-encoding).
164              
165             =back
166              
167             =head1 AUTHOR
168              
169             Flavio Poletti <polettix@cpan.org>
170              
171             =head1 COPYRIGHT AND LICENSE
172              
173             Copyright (C) 2015 by Flavio Poletti <polettix@cpan.org>
174              
175             This module is free software. You can redistribute it and/or
176             modify it under the terms of the Artistic License 2.0.
177              
178             This program is distributed in the hope that it will be useful,
179             but without any warranty; without even the implied warranty of
180             merchantability or fitness for a particular purpose.
181              
182             =cut