Filename | /Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/Config/Tiny.pm |
Statements | Executed 37 statements in 820µs |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 78µs | 82µs | read_string | Config::Tiny::
1 | 1 | 1 | 28µs | 144µs | read | Config::Tiny::
1 | 1 | 1 | 18µs | 18µs | CORE:open (opcode) | Config::Tiny::
1 | 1 | 1 | 12µs | 23µs | BEGIN@5 | Config::Tiny::
1 | 1 | 1 | 11µs | 11µs | CORE:readline (opcode) | Config::Tiny::
1 | 1 | 1 | 10µs | 10µs | BEGIN@7 | Config::Tiny::
1 | 1 | 1 | 6µs | 6µs | CORE:close (opcode) | Config::Tiny::
7 | 1 | 1 | 4µs | 4µs | CORE:match (opcode) | Config::Tiny::
0 | 0 | 0 | 0s | 0s | _error | Config::Tiny::
0 | 0 | 0 | 0s | 0s | errstr | Config::Tiny::
0 | 0 | 0 | 0s | 0s | new | Config::Tiny::
0 | 0 | 0 | 0s | 0s | write | Config::Tiny::
0 | 0 | 0 | 0s | 0s | write_string | Config::Tiny::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Config::Tiny; | ||||
2 | |||||
3 | # If you thought Config::Simple was small... | ||||
4 | |||||
5 | 2 | 48µs | 2 | 35µs | # spent 23µs (12+12) within Config::Tiny::BEGIN@5 which was called:
# once (12µs+12µs) by Perl::Critic::UserProfile::BEGIN@17 at line 5 # spent 23µs making 1 call to Config::Tiny::BEGIN@5
# spent 12µs making 1 call to strict::import |
6 | 1 | 600ns | our $VERSION = '2.20'; # Also change version # in t/02.main.t. | ||
7 | # spent 10µs within Config::Tiny::BEGIN@7 which was called:
# once (10µs+0s) by Perl::Critic::UserProfile::BEGIN@17 at line 10 | ||||
8 | 1 | 6µs | require 5.008001; | ||
9 | 1 | 4µs | $Config::Tiny::errstr = ''; | ||
10 | 1 | 616µs | 1 | 10µs | } # spent 10µs making 1 call to Config::Tiny::BEGIN@7 |
11 | |||||
12 | # Create an empty object | ||||
13 | sub new { bless {}, shift } | ||||
14 | |||||
15 | # Create an object from a file | ||||
16 | # spent 144µs (28+116) within Config::Tiny::read which was called:
# once (28µs+116µs) by Perl::Critic::UserProfile::_load_profile_from_file at line 196 of Perl/Critic/UserProfile.pm | ||||
17 | 1 | 900ns | my $class = ref $_[0] ? ref shift : shift; | ||
18 | 1 | 500ns | my $file = shift or return $class->_error('No file name provided'); | ||
19 | |||||
20 | # Slurp in the file. | ||||
21 | |||||
22 | 1 | 100ns | my $encoding = shift; | ||
23 | 1 | 500ns | $encoding = $encoding ? "<:$encoding" : '<'; | ||
24 | 1 | 2µs | local $/ = undef; | ||
25 | |||||
26 | 1 | 24µs | 1 | 18µs | open( CFG, $encoding, $file ) or return $class->_error( "Failed to open file '$file' for reading: $!" ); # spent 18µs making 1 call to Config::Tiny::CORE:open |
27 | 1 | 16µs | 1 | 11µs | my $contents = <CFG>; # spent 11µs making 1 call to Config::Tiny::CORE:readline |
28 | 1 | 10µs | 1 | 6µs | close( CFG ); # spent 6µs making 1 call to Config::Tiny::CORE:close |
29 | |||||
30 | 1 | 400ns | return $class -> _error("Reading from '$file' returned undef") if (! defined $contents); | ||
31 | |||||
32 | 1 | 7µs | 1 | 82µs | return $class->read_string( $contents ); # spent 82µs making 1 call to Config::Tiny::read_string |
33 | } | ||||
34 | |||||
35 | # Create an object from a string | ||||
36 | # spent 82µs (78+4) within Config::Tiny::read_string which was called:
# once (78µs+4µs) by Config::Tiny::read at line 32 | ||||
37 | 1 | 800ns | my $class = ref $_[0] ? ref shift : shift; | ||
38 | 1 | 2µs | my $self = bless {}, $class; | ||
39 | 1 | 300ns | return undef unless defined $_[0]; | ||
40 | |||||
41 | # Parse the file | ||||
42 | 1 | 500ns | my $ns = '_'; | ||
43 | 1 | 200ns | my $counter = 0; | ||
44 | 1 | 57µs | foreach ( split /(?:\015{1,2}\012|\015|\012)/, shift ) { | ||
45 | 7 | 300ns | $counter++; | ||
46 | |||||
47 | # Skip comments and empty lines | ||||
48 | 7 | 17µs | 7 | 4µs | next if /^\s*(?:\#|\;|$)/; # spent 4µs making 7 calls to Config::Tiny::CORE:match, avg 586ns/call |
49 | |||||
50 | # Remove inline comments | ||||
51 | s/\s\;\s.+$//g; | ||||
52 | |||||
53 | # Handle section headers | ||||
54 | if ( /^\s*\[\s*(.+?)\s*\]\s*$/ ) { | ||||
55 | # Create the sub-hash if it doesn't exist. | ||||
56 | # Without this sections without keys will not | ||||
57 | # appear at all in the completed struct. | ||||
58 | $self->{$ns = $1} ||= {}; | ||||
59 | next; | ||||
60 | } | ||||
61 | |||||
62 | # Handle properties | ||||
63 | if ( /^\s*([^=]+?)\s*=\s*(.*?)\s*$/ ) { | ||||
64 | $self->{$ns}->{$1} = $2; | ||||
65 | next; | ||||
66 | } | ||||
67 | |||||
68 | return $self->_error( "Syntax error at line $counter: '$_'" ); | ||||
69 | } | ||||
70 | |||||
71 | 1 | 3µs | $self; | ||
72 | } | ||||
73 | |||||
74 | # Save an object to a file | ||||
75 | sub write { | ||||
76 | my $self = shift; | ||||
77 | my $file = shift or return $self->_error('No file name provided'); | ||||
78 | my $encoding = shift; | ||||
79 | $encoding = $encoding ? ">:$encoding" : '>'; | ||||
80 | |||||
81 | # Write it to the file | ||||
82 | my $string = $self->write_string; | ||||
83 | return undef unless defined $string; | ||||
84 | open( CFG, $encoding, $file ) or return $self->_error( | ||||
85 | "Failed to open file '$file' for writing: $!" | ||||
86 | ); | ||||
87 | print CFG $string; | ||||
88 | close CFG; | ||||
89 | |||||
90 | return 1; | ||||
91 | } | ||||
92 | |||||
93 | # Save an object to a string | ||||
94 | sub write_string { | ||||
95 | my $self = shift; | ||||
96 | |||||
97 | my $contents = ''; | ||||
98 | foreach my $section ( sort { (($b eq '_') <=> ($a eq '_')) || ($a cmp $b) } keys %$self ) { | ||||
99 | # Check for several known-bad situations with the section | ||||
100 | # 1. Leading whitespace | ||||
101 | # 2. Trailing whitespace | ||||
102 | # 3. Newlines in section name | ||||
103 | return $self->_error( | ||||
104 | "Illegal whitespace in section name '$section'" | ||||
105 | ) if $section =~ /(?:^\s|\n|\s$)/s; | ||||
106 | my $block = $self->{$section}; | ||||
107 | $contents .= "\n" if length $contents; | ||||
108 | $contents .= "[$section]\n" unless $section eq '_'; | ||||
109 | foreach my $property ( sort keys %$block ) { | ||||
110 | return $self->_error( | ||||
111 | "Illegal newlines in property '$section.$property'" | ||||
112 | ) if $block->{$property} =~ /(?:\012|\015)/s; | ||||
113 | $contents .= "$property=$block->{$property}\n"; | ||||
114 | } | ||||
115 | } | ||||
116 | |||||
117 | $contents; | ||||
118 | } | ||||
119 | |||||
120 | # Error handling | ||||
121 | sub errstr { $Config::Tiny::errstr } | ||||
122 | sub _error { $Config::Tiny::errstr = $_[1]; undef } | ||||
123 | |||||
124 | 1 | 2µs | 1; | ||
125 | |||||
126 | __END__ | ||||
# spent 6µs within Config::Tiny::CORE:close which was called:
# once (6µs+0s) by Config::Tiny::read at line 28 | |||||
# spent 4µs within Config::Tiny::CORE:match which was called 7 times, avg 586ns/call:
# 7 times (4µs+0s) by Config::Tiny::read_string at line 48, avg 586ns/call | |||||
# spent 18µs within Config::Tiny::CORE:open which was called:
# once (18µs+0s) by Config::Tiny::read at line 26 | |||||
# spent 11µs within Config::Tiny::CORE:readline which was called:
# once (11µs+0s) by Config::Tiny::read at line 27 |