File Coverage

blib/lib/TOML.pm
Criterion Covered Total %
statement 60 65 92.3
branch 14 18 77.7
condition 2 3 66.6
subroutine 12 12 100.0
pod 2 3 66.6
total 90 101 89.1


line stmt bran cond sub pod time code
1             package TOML;
2              
3             # -------------------------------------------------------------------
4             # TOML - Parser for Tom's Obvious, Minimal Language.
5             #
6             # Copyright (C) 2013 Darren Chamberlain
7             # -------------------------------------------------------------------
8              
9 2     2   18931 use 5.008005;
  2         5  
10 2     2   8 use strict;
  2         2  
  2         35  
11 2     2   12 use warnings;
  2         2  
  2         69  
12 2     2   8 use Exporter 'import';
  2         2  
  2         109  
13              
14             our ($VERSION, @EXPORT, @_NAMESPACE, $PARSER);
15              
16 2     2   7 use B;
  2         1  
  2         79  
17 2     2   8 use Carp qw(croak);
  2         3  
  2         83  
18 2     2   819 use TOML::Parser 0.03;
  2         32443  
  2         1066  
19              
20             $VERSION = "0.97";
21             @EXPORT = qw(from_toml to_toml);
22             $PARSER = TOML::Parser->new(inflate_boolean => sub { $_[0] });
23              
24             sub to_toml {
25 15     15 1 4631 my $stuff = shift;
26 15         27 local @_NAMESPACE = ();
27 15         24 _to_toml($stuff);
28             }
29              
30             sub _to_toml {
31 27     27   22 my ($stuff) = @_;
32              
33 27 50       45 if (ref $stuff eq 'HASH') {
34 27         22 my $res = '';
35 27         71 my @keys = sort keys %$stuff;
36 27         26 for my $key (grep { ref $stuff->{$_} ne 'HASH' } @keys) {
  44         76  
37 32         29 my $val = $stuff->{$key};
38 32         40 $res .= "$key = " . _serialize($val) . "\n";
39             }
40 27         28 for my $key (grep { ref $stuff->{$_} eq 'HASH' } @keys) {
  44         63  
41 12         26 my $val = $stuff->{$key};
42 12         18 local @_NAMESPACE = (@_NAMESPACE, $key);
43 12         33 $res .= sprintf("[%s]\n", join(".", @_NAMESPACE));
44 12         21 $res .= _to_toml($val);
45             }
46 27         68 return $res;
47             } else {
48 0         0 croak("You cannot convert non-HashRef values to TOML");
49             }
50             }
51              
52             sub _serialize {
53 47     47   39 my $value = shift;
54 47         82 my $b_obj = B::svref_2object(\$value);
55 47         100 my $flags = $b_obj->FLAGS;
56              
57 47 100 66     118 return $value
58             if $flags & ( B::SVp_IOK | B::SVp_NOK ) and !( $flags & B::SVp_POK ); # SvTYPE is IV or NV?
59              
60 41         29 my $type = ref($value);
61 41 100       53 if (!$type) {
    100          
    50          
62 33         33 return string_to_json($value);
63             } elsif ($type eq 'ARRAY') {
64 6         7 return sprintf('[%s]', join(", ", map { _serialize($_) } @$value));
  15         23  
65             } elsif ($type eq 'SCALAR') {
66 2 50       4 if (defined $$value) {
67 2 100       8 if ($$value eq '0') {
    50          
68 1         3 return 'false';
69             } elsif ($$value eq '1') {
70 1         4 return 'true';
71             } else {
72 0         0 croak("cannot encode reference to scalar");
73             }
74             }
75 0         0 croak("cannot encode reference to scalar");
76             }
77 0         0 croak("Bad type in to_toml: $type");
78             }
79              
80             my %esc = (
81             "\n" => '\n',
82             "\r" => '\r',
83             "\t" => '\t',
84             "\f" => '\f',
85             "\b" => '\b',
86             "\"" => '\"',
87             "\\" => '\\\\',
88             "\'" => '\\\'',
89             );
90             sub string_to_json {
91 33     33 0 29 my ($arg) = @_;
92              
93 33         45 $arg =~ s/([\x22\x5c\n\r\t\f\b])/$esc{$1}/g;
94 33         22 $arg =~ s/([\x00-\x08\x0b\x0e-\x1f])/'\\u00' . unpack('H2', $1)/eg;
  0         0  
95              
96 33         108 return '"' . $arg . '"';
97             }
98              
99             sub from_toml {
100 7     7 1 6 my $string = shift;
101 7         7 local $@;
102 7         9 my $toml = eval { $PARSER->parse($string) };
  7         19  
103 7 100       6117 return wantarray ? ($toml, $@) : $toml;
104             }
105              
106             1;
107              
108             __END__