File Coverage

blib/lib/Log/Report/Lexicon/POTcompact.pm
Criterion Covered Total %
statement 76 82 92.6
branch 39 50 78.0
condition 11 17 64.7
subroutine 15 17 88.2
pod 5 6 83.3
total 146 172 84.8


line stmt bran cond sub pod time code
1             # Copyrights 2007-2017 by [Mark Overmeer].
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 2.02.
5 6     6   610 use warnings;
  6         16  
  6         259  
6 6     6   41 use strict;
  6         15  
  6         249  
7              
8             package Log::Report::Lexicon::POTcompact;
9 6     6   137 use vars '$VERSION';
  6         18  
  6         402  
10             $VERSION = '1.09';
11              
12 6     6   49 use base 'Log::Report::Lexicon::Table';
  6         15  
  6         1553  
13              
14 6     6   47 use Log::Report 'log-report-lexicon';
  6         16  
  6         32  
15 6     6   1588 use Log::Report::Util qw/escape_chars unescape_chars/;
  6         15  
  6         377  
16              
17 6     6   43 use Encode qw/find_encoding/;
  6         14  
  6         8024  
18              
19             sub _unescape($$);
20             sub _escape($$);
21              
22              
23             sub read($@)
24 12     12 1 501 { my ($class, $fn, %args) = @_;
25              
26 12         25 my $self = bless {}, $class;
27              
28 12         18 my $charset = $args{charset};
29              
30             # Try to pick-up charset from the filename (which may contain a modifier)
31 12 50 66     53 $charset = $1
32             if !$charset && $fn =~ m!\.([\w-]+)(?:\@[^/\\]+)?\.po$!i;
33              
34 12         15 my $fh;
35 12 100       24 if($charset)
36 1 50   1   32 { open $fh, "<:encoding($charset):crlf", $fn
  1         5  
  1         2  
  1         6  
37             or fault __x"cannot read in {charset} from file {fn}"
38             , charset => $charset, fn => $fn;
39             }
40             else
41 11 50       338 { open $fh, '<:raw:crlf', $fn
42             or fault __x"cannot read from file {fn} (unknown charset)", fn=>$fn;
43             }
44              
45             # Speed!
46 12         866 my $msgctxt = '';
47 12         18 my ($last, $msgid, @msgstr);
48 12   50     69 my $index = $self->{index} ||= {};
49              
50             my $add = sub {
51 225 100   225   276 unless($charset)
52 11 50       15 { $msgid eq ''
53             or error __x"header not found for charset in {fn}", fn => $fn;
54 11 50       58 $charset = $msgstr[0] =~ m/^content-type:.*?charset=["']?([\w-]+)/mi
55             ? $1 : error __x"cannot detect charset in {fn}", fn => $fn;
56 11 50       34 my $enc = find_encoding($charset)
57             or error __x"unsupported charset {charset} in {fn}"
58             , charset => $charset, fn => $fn;
59              
60 11         2542 trace "auto-detected charset $charset for $fn";
61 11         270 $fh->binmode(":encoding($charset):crlf");
62              
63 11         973 $_ = $enc->decode($_) for @msgstr, $msgctxt;
64             }
65              
66 225 100       755 $index->{"$msgid#$msgctxt"} = @msgstr > 1 ? [@msgstr] : $msgstr[0];
67 225         373 ($msgctxt, $msgid, @msgstr) = ('');
68 12         58 };
69              
70             LINE:
71 12         279 while(my $line = $fh->getline)
72 1103 100       26969 { next if substr($line, 0, 1) eq '#';
73              
74 801 100       1692 if($line =~ m/^\s*$/) # blank line starts new
75 232 100       471 { $add->() if @msgstr;
76 232         3174 next LINE;
77             }
78              
79 569 50 66     2378 if($line =~ s/^msgctxt\s+//)
    100          
    100          
    100          
    100          
80 0         0 { $msgctxt = _unescape $line, $fn;
81 0         0 $last = \$msgctxt;
82             }
83             elsif($line =~ s/^msgid\s+//)
84 225         342 { $msgid = _unescape $line, $fn;
85 225         3947 $last = \$msgid;
86             }
87             elsif($line =~ s/^msgstr\[(\d+)\]\s*//)
88 4         7 { $last = \($msgstr[$1] = _unescape $line, $fn);
89             }
90             elsif($line =~ s/^msgstr\s+//)
91 224         301 { $msgstr[0] = _unescape $line, $fn;
92 224         3957 $last = \$msgstr[0];
93             }
94             elsif($last && $line =~ m/^\s*\"/)
95 115         192 { $$last .= _unescape $line, $fn;
96             }
97             }
98 12 100       286 $add->() if @msgstr; # don't forget the last
99              
100 12 50       96 close $fh
101             or failure __x"failed reading from file {fn}", fn => $fn;
102              
103 12         33 $self->{origcharset} = $charset;
104 12         19 $self->{filename} = $fn;
105 12         53 $self->setupPluralAlgorithm;
106 12         165 $self;
107             }
108              
109             #------------------
110              
111 0     0 1 0 sub filename() {shift->{filename}}
112 11     11 1 8785 sub originalCharset() {shift->{origcharset}}
113              
114             #------------------
115              
116 0     0 0 0 sub index() {shift->{index}}
117             # The index is a HASH with "$msg#$msgctxt" keys. If there is no
118             # $msgctxt, then there still is the #
119              
120              
121 26   50 26 1 165 sub msgid($) { $_[0]->{index}{$_[1].'#'.($_[2]//'')} }
122              
123              
124             # speed!!!
125             sub msgstr($;$$)
126 13     13 1 944 { my ($self, $msgid, $count, $ctxt) = @_;
127              
128 13   50     70 $ctxt //= '';
129 13 50       60 my $po = $self->{index}{"$msgid#$ctxt"}
130             or return undef;
131              
132 13 100       44 ref $po # no plurals defined
133             or return $po;
134              
135 9 50 50     241 $po->[$self->{algo}->($count // 1)] || $po->[$self->{algo}->(1)];
136             }
137              
138             #
139             ### internal helper routines, shared with ::PO.pm and ::POT.pm
140             #
141              
142             sub _unescape($$)
143 686 50   686   2014 { unless( $_[0] =~ m/^\s*\"(.*)\"\s*$/ )
144 0         0 { warning __x"string '{text}' not between quotes at {location}"
145             , text => $_[0], location => $_[1];
146 0         0 return $_[0];
147             }
148 686         1201 unescape_chars $1;
149             }
150              
151             sub _escape($$)
152 64 100 100 64   437 { my @escaped = map { '"' . escape_chars($_) . '"' }
  100         481  
153             defined $_[0] && length $_[0] ? split(/(?<=\n)/, $_[0]) : '';
154              
155 64 100       502 unshift @escaped, '""' if @escaped > 1;
156 64         213 join $_[1], @escaped;
157             }
158              
159             1;