File Coverage

blib/lib/CLDR/Number/Role/Base.pm
Criterion Covered Total %
statement 76 76 100.0
branch 28 30 93.3
condition 13 18 72.2
subroutine 14 14 100.0
pod n/a
total 131 138 94.9


line stmt bran cond sub pod time code
1             package CLDR::Number::Role::Base;
2              
3 18     18   731797 use v5.8.1;
  18         68  
4 18     18   96 use utf8;
  18         36  
  18         140  
5 18     18   403 use Carp;
  18         32  
  18         1284  
6 18     18   13215 use CLDR::Number::Data::Base;
  18         53  
  18         2155  
7 18     18   11024 use CLDR::Number::Data::System;
  18         42  
  18         540  
8              
9 18     18   96 use Moo::Role;
  18         309  
  18         200  
10              
11             # This role does not have a publicly supported interface and may change in
12             # backward incompatible ways in the future. Please use one of the documented
13             # classes instead.
14              
15             our $VERSION = '0.15';
16              
17             requires qw( BUILD );
18              
19             has version => (
20             is => 'ro',
21             default => $VERSION,
22             );
23              
24             has cldr_version => (
25             is => 'ro',
26             default => $CLDR::Number::Data::Base::CLDR_VERSION,
27             );
28              
29             has locale => (
30             is => 'rw',
31             trigger => 1,
32             );
33              
34             has default_locale => (
35             is => 'ro',
36             coerce => sub {
37             my ($locale) = @_;
38              
39             if (!defined $locale) {
40             carp 'default_locale is not defined';
41             }
42             elsif (!exists $CLDR::Number::Data::Base::DATA->{$locale}) {
43             carp "default_locale '$locale' is unknown";
44             }
45             else {
46             return $locale;
47             }
48              
49             return;
50             },
51             );
52              
53             has numbering_system => (
54             is => 'rw',
55             isa => sub {
56             carp 'numbering_system is not defined'
57             unless defined $_[0];
58             carp "numbering_system '$_[0]' is unknown"
59             unless exists $CLDR::Number::Data::System::DATA->{$_[0]};
60             },
61             coerce => sub { defined $_[0] ? lc $_[0] : $_[0] },
62             trigger => 1,
63             );
64              
65             # TODO: length NYI
66             has length => (
67             is => 'rw',
68             );
69              
70             has decimal_sign => (
71             is => 'rw',
72             );
73              
74             has group_sign => (
75             is => 'rw',
76             );
77              
78             has plus_sign => (
79             is => 'rw',
80             );
81              
82             has minus_sign => (
83             is => 'rw',
84             );
85              
86             has infinity => (
87             is => 'rw',
88             );
89              
90             has nan => (
91             is => 'rw',
92             );
93              
94             has _locale_inheritance => (
95             is => 'rw',
96             default => sub { [] },
97             );
98              
99             has _init_args => (
100             is => 'rw',
101             );
102              
103             around BUILDARGS => sub {
104             my ($orig, $class, @args) = @_;
105              
106             return $class->$orig(@args) if @args % 2;
107             return $class->$orig(@args, _init_args => {@args});
108             };
109              
110             before BUILD => sub {
111             my ($self) = @_;
112              
113             return if $self->_has_init_arg('locale');
114              
115             $self->_trigger_locale;
116             };
117              
118             after BUILD => sub {
119             my ($self) = @_;
120              
121             $self->_init_args({});
122             };
123              
124             sub _has_init_arg {
125 3193     3193   4362 my ($self, $arg) = @_;
126              
127 3193 50       8006 return unless $self->_init_args;
128 3193         15636 return exists $self->_init_args->{$arg};
129             }
130              
131             sub _set_unless_init_arg {
132 1372     1372   2158 my ($self, $attribute, $value) = @_;
133              
134 1372 100       2701 return if $self->_has_init_arg($attribute);
135              
136 1357         4504 $self->$attribute($value);
137             }
138              
139             sub _build_signs {
140 206     206   553 my ($self, @signs) = @_;
141              
142 206         401 for my $sign (@signs) {
143 1188         1422 my $attribute = $sign;
144              
145 1188 50       2306 next if $self->_has_init_arg($attribute);
146              
147 1188         3240 $sign =~ s{ _sign $ }{}x;
148              
149 1188         2407 $self->$attribute($self->_get_data(symbol => $sign));
150             }
151             }
152              
153             sub _trigger_locale {
154 194     194   27182 my ($self, $locale) = @_;
155 194         524 my ($lang, $script, $region, $ext) = _split_locale($locale);
156              
157 194 100 66     1057 if ($lang && exists $CLDR::Number::Data::Base::DATA->{$lang}) {
    100          
158 162         408 $self->_locale_inheritance(
159             _build_inheritance($lang, $script, $region, $ext)
160             );
161 162         425 $locale = $self->_locale_inheritance->[0];
162             }
163             elsif ($self->default_locale) {
164 2         6 $locale = $self->default_locale;
165 2         5 ($lang, $script, $region, $ext) = _split_locale($locale);
166 2         50 $self->_locale_inheritance(
167             _build_inheritance($lang, $script, $region, $ext)
168             );
169             }
170             else {
171 30         61 $locale = 'root';
172 30         137 $self->_locale_inheritance( [$locale] );
173             }
174              
175 194 100 100     594 if ($ext && $ext =~ m{ -nu- ( [^-]+ ) }x) {
176 4         18 $self->numbering_system($1);
177             }
178             else {
179 190         492 $self->_trigger_numbering_system;
180             }
181              
182 194         501 $self->{locale} = $locale;
183              
184 194         671 $self->_build_signs(qw{
185             decimal_sign group_sign plus_sign minus_sign infinity nan
186             });
187             }
188              
189             sub _trigger_numbering_system {
190 199     199   1059 my ($self, $system) = @_;
191              
192             return if defined $system
193 199 100 66     649 && exists $CLDR::Number::Data::System::DATA->{$system};
194              
195 191         541 $self->{numbering_system} = $self->_get_data(system => 'default');
196             }
197              
198             sub _split_locale {
199 237     237   380 my ($locale) = @_;
200              
201 237 100       572 return unless defined $locale;
202              
203 221         462 $locale = lc $locale;
204 221         442 $locale =~ tr{_}{-};
205              
206 221         1375 my ($lang, $script, $region, $ext) = $locale =~ m{ ^
207             ( [a-z]{2,3} ) # language
208             (?: - ( [a-z]{4} ) )? # script
209             (?: - ( [a-z]{2} | [0-9]{3} ) )? # country or region
210             (?: - ( u- .+ ) )? # extension
211             -? # trailing separator
212             $ }xi;
213              
214 221 100       579 $script = ucfirst $script if $script;
215 221 100       505 $region = uc $region if $region;
216              
217 221         718 return $lang, $script, $region, $ext;
218             }
219              
220             sub _build_inheritance {
221 205     205   339 my ($lang, $script, $region, $ext) = @_;
222 205         261 my @tree;
223              
224 205         1024 for my $subtags (
225             [$lang, $region, $ext],
226             [$lang, $script, $region],
227             [$lang, $script],
228             [$lang, $region],
229             [$lang],
230             ) {
231 974 100       1273 next if grep { !$_ } @$subtags;
  2194         4649  
232 290         563 my $locale = join '-', @$subtags;
233 290 100       762 next if !exists $CLDR::Number::Data::Base::DATA->{$locale};
234 246         447 push @tree, $locale;
235              
236 246 100       839 if (my $parent = $CLDR::Number::Data::Base::PARENT->{$locale}) {
237 41         49 push @tree, @{_build_inheritance(_split_locale($parent))};
  41         90  
238 41         102 last;
239             }
240             }
241              
242 205 100 100     1313 if (!@tree || $tree[-1] ne 'root') {
243 164         304 push @tree, 'root';
244             }
245              
246 205         721 return \@tree;
247             }
248              
249             sub _get_data {
250 1623     1623   2481 my ($self, $type, $key) = @_;
251 1623         1960 my $data = $CLDR::Number::Data::Base::DATA;
252              
253 1623         1789 for my $locale (@{$self->_locale_inheritance}) {
  1623         3518  
254             return $data->{$locale}{$type}{$key}
255             if exists $data->{$locale}
256             && exists $data->{$locale}{$type}
257 3270 100 33     26079 && exists $data->{$locale}{$type}{$key};
      66        
258             }
259              
260 85         1899 return undef;
261             }
262              
263             1;