File Coverage

blib/lib/Locale/Codes.pm
Criterion Covered Total %
statement 367 376 98.6
branch 229 240 96.2
condition 50 57 87.7
subroutine 25 26 100.0
pod 19 19 100.0
total 690 718 97.0


line stmt bran cond sub pod time code
1             package Locale::Codes;
2             # Copyright (C) 2001 Canon Research Centre Europe (CRE).
3             # Copyright (C) 2002-2009 Neil Bowers
4             # Copyright (c) 2010-2026 Sullivan Beck
5             # This program is free software; you can redistribute it and/or modify it
6             # under the same terms as Perl itself.
7              
8             ###############################################################################
9              
10 19     19   1125177 use strict;
  19         26  
  19         579  
11 19     19   66 use warnings;
  19         23  
  19         894  
12             require 5.006;
13              
14 19     19   94 use Carp;
  19         24  
  19         1552  
15 19     19   106 use if $] >= 5.027007, 'deprecate';
  19         49  
  19         3201  
16 19     19   14247 use Locale::Codes::Constants;
  19         50  
  19         3808  
17              
18             our($VERSION);
19             $VERSION='3.88';
20              
21 19     19   99 use Exporter qw(import);
  19         23  
  19         76835  
22             our(@EXPORT_OK,%EXPORT_TAGS);
23             @EXPORT_OK = @Locale::Codes::Constants::CONSTANTS;
24             %EXPORT_TAGS = ( 'constants' => [ @EXPORT_OK ] );
25              
26             ###############################################################################
27             # GLOBAL DATA
28             ###############################################################################
29             # All of the data is stored in a couple global variables. They are filled
30             # in by requiring the appropriate TYPE_Codes and TYPE_Retired modules.
31              
32             our(%Data,%Retired);
33              
34             # $Data{ TYPE }{ code2id }{ CODESET } { CODE } = [ ID, I ]
35             # { id2code }{ CODESET } { ID } = CODE
36             # { id2names }{ ID } = [ NAME, NAME, ... ]
37             # { alias2id }{ NAME } = [ ID, I ]
38             # { id } = FIRST_UNUSED_ID
39             # { codealias }{ CODESET } { ALIAS } = CODE
40             #
41             # $Retired{ TYPE }{ CODESET }{ code }{ CODE } = NAME
42             # { name }{ lc(NAME) } = [CODE,NAME]
43              
44             ###############################################################################
45             # METHODS
46             ###############################################################################
47              
48             sub new {
49 32     32 1 249451 my($class,$type,$codeset,$show_errors) = @_;
50 32 100       142 my $self = { 'type' => '',
51             'codeset' => '',
52             'err' => (defined($show_errors) ? $show_errors : 1),
53             };
54              
55 32         71 bless $self,$class;
56              
57 32 100       113 $self->type($type) if ($type);
58 32 100       64 $self->codeset($codeset) if ($codeset);
59 32         95 return $self;
60             }
61              
62             sub show_errors {
63 65     65 1 1873 my($self,$val) = @_;
64 65         97 $$self{'err'} = $val;
65 65         123 return $val;
66             }
67              
68             sub type {
69 30     30 1 1060 my($self,$type) = @_;
70              
71 30 100       111 if (! exists $ALL_CODESETS{$type}) {
72 2 100       206 carp "ERROR: type: invalid argument: $type\n" if ($$self{'err'});
73 2         18 return 1;
74             }
75              
76 28         55 my $label = $ALL_CODESETS{$type}{'module'};
77 28         1568 eval "require Locale::Codes::${label}_Codes";
78             # uncoverable branch true
79 28 50       3533 if ($@) {
80             # uncoverable statement
81 0         0 croak "ERROR: type: unable to load module: ${label}_Codes\n";
82             }
83 28         6402 eval "require Locale::Codes::${label}_Retired";
84             # uncoverable branch true
85 28 50       169 if ($@) {
86             # uncoverable statement
87 0         0 croak "ERROR: type: unable to load module: ${label}_Retired\n";
88             }
89              
90 28         172 $$self{'type'} = $type;
91 28         69 $$self{'codeset'} = $ALL_CODESETS{$type}{'default'};
92              
93 28         60 return 0;
94             }
95              
96             sub codeset {
97 4     4 1 280 my($self,$codeset) = @_;
98              
99 4         6 my $type = $$self{'type'};
100 4 100       9 if (! exists $ALL_CODESETS{$type}{'codesets'}{$codeset}) {
101 2 100       94 carp "ERROR: codeset: invalid argument: $codeset\n" if ($$self{'err'});
102 2         9 return 1;
103             }
104              
105 2         3 $$self{'codeset'} = $codeset;
106 2         3 return 0;
107             }
108              
109             sub version {
110             # uncoverable subroutine
111             # uncoverable statement
112 0     0 1 0 my($self) = @_;
113             # uncoverable statement
114 0         0 return $VERSION;
115             }
116              
117             ###############################################################################
118              
119             # This is used to validate a codeset and/or code. It will also format
120             # a code for that codeset.
121             #
122             # (ERR,RET_CODE,RET_CODESET) = $o->_code([CODE [,CODESET]])
123             #
124             # If CODE is empty/undef, only the codeset will be validated
125             # and RET_CODE will be empty.
126             #
127             # If CODE is passed in, it will be returned formatted correctly
128             # for the codeset.
129             #
130             # ERR will be 0 or 1.
131             #
132             # If $no_check_code is 1, then the code will not be validated (i.e.
133             # it doesn't already have to exist). This will be useful for adding
134             # a new code.
135             #
136             sub _code {
137 1273     1273   3082 my($self,$code,$codeset,$no_check_code) = @_;
138 1273 100       1817 $code = '' if (! defined($code));
139 1273 100       1928 $codeset = lc($codeset) if (defined($codeset));
140              
141 1273 100       1918 if (! $$self{'type'}) {
142             carp "ERROR: _code: no type set for Locale::Codes object\n"
143 2 100       77 if ($$self{'err'});
144 2         9 return (1);
145             }
146 1271         1373 my $type = $$self{'type'};
147 1271 100 100     2501 if ($codeset && ! exists $ALL_CODESETS{$type}{'codesets'}{$codeset}) {
148             carp "ERROR: _code: invalid codeset provided: $codeset\n"
149 39 100       3951 if ($$self{'err'});
150 39         136 return (1);
151             }
152              
153             # If no codeset was passed in, return the codeset specified.
154              
155 1232 100 100     2557 $codeset = $$self{'codeset'} if (! defined($codeset) || $codeset eq '');
156 1232 100       2277 return (0,'',$codeset) if ($code eq '');
157              
158             # Determine the properties of the codeset
159              
160 808         788 my($op,@args) = @{ $ALL_CODESETS{$type}{'codesets'}{$codeset} };
  808         1561  
161              
162 808 100       1362 if ($op eq 'lc') {
163 671         807 $code = lc($code);
164             }
165              
166 808 100       1285 if ($op eq 'uc') {
167 69         1145 $code = uc($code);
168             }
169              
170 808 100       1160 if ($op eq 'ucfirst') {
171 30         43 $code = ucfirst(lc($code));
172             }
173              
174 808 100       1136 if ($op eq 'numeric') {
175 38 100       169 if ($code =~ /^\d+$/) {
176 30         37 my $l = $args[0];
177 30         108 $code = sprintf("%.${l}d", $code);
178              
179             } else {
180 8 100       580 carp "ERROR: _code: invalid numeric code: $code\n" if ($$self{'err'});
181 8         33 return (1);
182             }
183             }
184              
185             # Determine if the code is in the codeset.
186              
187 800 100 100     3171 if (! $no_check_code &&
      100        
      100        
188             ! exists $Data{$type}{'code2id'}{$codeset}{$code} &&
189             ! exists $Retired{$type}{$codeset}{'code'}{$code} &&
190             ! exists $Data{$type}{'codealias'}{$codeset}{$code}) {
191             carp "ERROR: _code: code not in codeset: $code [$codeset]\n"
192 152 100       14662 if ($$self{'err'});
193 152         720 return (1);
194             }
195              
196 648         1671 return (0,$code,$codeset);
197             }
198              
199             ###############################################################################
200              
201             # $name = $o->code2name(CODE [,CODESET] [,'retired'])
202             # @name = $o->code2names(CODE, [,CODESET])
203             # $code = $o->name2code(NAME [,CODESET] [,'retired'])
204             #
205             # Returns the name associated with the CODE (or vice versa).
206             #
207             sub code2name {
208 479     479 1 15079 my($self,@args) = @_;
209 479         578 my $retired = 0;
210 479 100 100     2078 if (@args && defined($args[$#args]) && lc($args[$#args]) eq 'retired') {
      100        
211 9         13 pop(@args);
212 9         14 $retired = 1;
213             }
214              
215 479 100       892 if (! $$self{'type'}) {
216 2 100       76 carp "ERROR: code2name: no type set for Locale::Codes object\n" if ($$self{'err'});
217 2         9 return undef;
218             }
219 477         598 my $type = $$self{'type'};
220              
221 477         760 my ($err,$code,$codeset) = $self->_code(@args);
222 477 100 100     1432 return undef if ($err || ! $code);
223              
224             $code = $Data{$type}{'codealias'}{$codeset}{$code}
225 411 100       805 if (exists $Data{$type}{'codealias'}{$codeset}{$code});
226              
227 411 100 66     744 if (exists $Data{$type}{'code2id'}{$codeset}{$code}) {
    100          
228 390         472 my ($id,$i) = @{ $Data{$type}{'code2id'}{$codeset}{$code} };
  390         827  
229 390         894 my $name = $Data{$type}{'id2names'}{$id}[$i];
230 390         1480 return $name;
231              
232             } elsif ($retired && exists $Retired{$type}{$codeset}{'code'}{$code}) {
233 3         12 return $Retired{$type}{$codeset}{'code'}{$code};
234             }
235              
236 18         113 return undef;
237             }
238              
239             sub name2code {
240 320     320 1 273663 my($self,$name,@args) = @_;
241 320 100       630 return undef if (! $name);
242 302         407 $name = lc($name);
243              
244 302         308 my $retired = 0;
245 302 100 66     818 if (@args && defined($args[$#args]) && lc($args[$#args]) eq 'retired') {
      100        
246 6         8 pop(@args);
247 6         8 $retired = 1;
248             }
249              
250 302 100       510 if (! $$self{'type'}) {
251 2 100       73 carp "ERROR: name2code: no type set for Locale::Codes object\n" if ($$self{'err'});
252 2         9 return undef;
253             }
254 300         377 my $type = $$self{'type'};
255              
256 300         479 my ($err,$tmp,$codeset) = $self->_code('',@args);
257 300 100       520 return undef if ($err);
258              
259 297 100 66     808 if (exists $Data{$type}{'alias2id'}{$name}) {
    100          
260 264         480 my $id = $Data{$type}{'alias2id'}{$name}[0];
261 264 100       595 if (exists $Data{$type}{'id2code'}{$codeset}{$id}) {
262 252         652 return $Data{$type}{'id2code'}{$codeset}{$id};
263             }
264              
265             } elsif ($retired && exists $Retired{$type}{$codeset}{'name'}{$name}) {
266 3         10 return $Retired{$type}{$codeset}{'name'}{$name}[0];
267             }
268              
269 42         86 return undef;
270             }
271              
272             # $code = $o->code2code(CODE,CODESET2)
273             # $code = $o->code2code(CODE,CODESET1,CODESET2)
274             #
275             # Changes the code in the CODESET1 (or the current codeset) to another
276             # codeset (CODESET2)
277             #
278             sub code2code {
279 68     68 1 2859 my($self,@args) = @_;
280              
281 68 100       138 if (! $$self{'type'}) {
282             carp "ERROR: code2code: no type set for Locale::Codes object\n"
283 2 100       61 if ($$self{'err'});
284 2         6 return undef;
285             }
286 66         93 my $type = $$self{'type'};
287              
288 66         79 my($code,$codeset1,$codeset2,$err);
289              
290 66 100       203 if (@args == 2) {
    100          
291 3         5 ($code,$codeset2) = @args;
292 3         9 ($err,$code,$codeset1) = $self->_code($code);
293 3 50       10 return undef if ($err);
294              
295             } elsif (@args == 3) {
296 60         107 ($code,$codeset1,$codeset2) = @args;
297 60         166 ($err,$code) = $self->_code($code,$codeset1);
298 60 100       166 return undef if ($err);
299 48         82 ($err) = $self->_code('',$codeset2);
300 48 50       201 return undef if ($err);
301             }
302              
303 54         109 my $name = $self->code2name($code,$codeset1);
304 54         110 my $out = $self->name2code($name,$codeset2);
305 54         214 return $out;
306             }
307              
308             sub code2names {
309 3     3 1 133 my($self,@args) = @_;
310              
311 3 50       11 if (! $$self{'type'}) {
312             carp "ERROR: code2named: no type set for Locale::Codes object\n"
313 0 0       0 if ($$self{'err'});
314 0         0 return undef;
315             }
316 3         6 my $type = $$self{'type'};
317              
318 3         8 my ($err,$code,$codeset) = $self->_code(@args);
319             return undef if ($err ||
320             ! $code ||
321 3 50 33     23 ! exists $Data{$type}{'code2id'}{$codeset}{$code});
      33        
322              
323 3         6 my $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
324 3         4 my @name = @{ $Data{$type}{'id2names'}{$id} };
  3         11  
325 3         21 return @name;
326             }
327             ###############################################################################
328              
329             # @codes = $o->all_codes([CODESET] [,'retired']);
330             # @names = $o->all_names([CODESET] [,'retired']);
331             #
332             # Returns all codes/names in the specified codeset, including retired
333             # ones if the option is given.
334              
335             sub all_codes {
336 47     47 1 1508 my($self,@args) = @_;
337 47         101 my $retired = 0;
338 47 100 100     205 if (@args && lc($args[$#args]) eq 'retired') {
339 3         4 pop(@args);
340 3         7 $retired = 1;
341             }
342              
343 47 100       102 if (! $$self{'type'}) {
344 2 100       62 carp "ERROR: all_codes: no type set for Locale::Codes object\n" if ($$self{'err'});
345 2         7 return ();
346             }
347 45         75 my $type = $$self{'type'};
348              
349 45         122 my ($err,$tmp,$codeset) = $self->_code('',@args);
350 45 100       127 return () if ($err);
351              
352 42         63 my @codes = keys %{ $Data{$type}{'code2id'}{$codeset} };
  42         1064  
353 42 100       155 push(@codes,keys %{ $Retired{$type}{$codeset}{'code'} }) if ($retired);
  3         43  
354 42         3247 return (sort @codes);
355             }
356              
357             sub all_names {
358 26     26 1 57290 my($self,@args) = @_;
359 26         40 my $retired = 0;
360 26 100 100     208 if (@args && lc($args[$#args]) eq 'retired') {
361 3         5 pop(@args);
362 3         6 $retired = 1;
363             }
364              
365 26 100       80 if (! $$self{'type'}) {
366 2 100       104 carp "ERROR: all_names: no type set for Locale::Codes object\n" if ($$self{'err'});
367 2         9 return ();
368             }
369 24         82 my $type = $$self{'type'};
370              
371 24         88 my ($err,$tmp,$codeset) = $self->_code('',@args);
372 24 100       86 return () if ($err);
373              
374 21         63 my @codes = $self->all_codes($codeset);
375 21         48 my @names;
376              
377 21         45 foreach my $code (@codes) {
378 4242         3621 my($id,$i) = @{ $Data{$type}{'code2id'}{$codeset}{$code} };
  4242         6033  
379 4242         6056 my $name = $Data{$type}{'id2names'}{$id}[$i];
380 4242         5017 push(@names,$name);
381             }
382 21 100       69 if ($retired) {
383 3         7 foreach my $lc (keys %{ $Retired{$type}{$codeset}{'name'} }) {
  3         42  
384 156         200 my $name = $Retired{$type}{$codeset}{'name'}{$lc}[1];
385 156         152 push @names,$name;
386             }
387             }
388 21         1910 return (sort @names);
389             }
390              
391             ###############################################################################
392              
393             # $flag = $o->rename_code (CODE,NEW_NAME [,CODESET])
394             #
395             # Change the official name for a code. The original is retained
396             # as an alias, but the new name will be returned if you lookup the
397             # name from code.
398             #
399             # Returns 1 on success.
400             #
401             sub rename_code {
402 54     54 1 2580 my($self,$code,$new_name,$codeset) = @_;
403              
404 54 100       195 if (! $$self{'type'}) {
405 2 100       103 carp "ERROR: rename_code: no type set for Locale::Codes object\n" if ($$self{'err'});
406 2         9 return 0;
407             }
408 52         85 my $type = $$self{'type'};
409              
410             # Make sure $code/$codeset are both valid
411              
412 52         188 my($err,$c,$cs) = $self->_code($code,$codeset);
413 52 100       160 if ($err) {
414             carp "ERROR: rename_code: unknown code/codeset: $code [$codeset]\n"
415 32 100       3019 if ($$self{'err'});
416 32         269 return 0;
417             }
418 20         34 ($code,$codeset) = ($c,$cs);
419              
420             # Cases:
421             # 1. Renaming to a name which exists with a different ID
422             # Error
423             #
424             # 2. Renaming to a name which exists with the same ID
425             # Just change code2id (I value)
426             #
427             # 3. Renaming to a new name
428             # Create a new alias
429             # Change code2id (I value)
430              
431 20         41 my $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
432              
433 20 100       73 if (exists $Data{$type}{'alias2id'}{lc($new_name)}) {
434             # Existing name (case 1 and 2)
435              
436 11         16 my ($new_id,$i) = @{ $Data{$type}{'alias2id'}{lc($new_name)} };
  11         44  
437 11 100       40 if ($new_id != $id) {
438             # Case 1
439             carp "ERROR: rename_code: rename to an existing name not allowed\n"
440 8 100       672 if ($$self{'err'});
441 8         48 return 0;
442             }
443              
444             # Case 2
445              
446 3         8 $Data{$type}{'code2id'}{$codeset}{$code}[1] = $i;
447              
448             } else {
449              
450             # Case 3
451              
452 9         14 push @{ $Data{$type}{'id2names'}{$id} },$new_name;
  9         34  
453 9         15 my $i = $#{ $Data{$type}{'id2names'}{$id} };
  9         22  
454 9         30 $Data{$type}{'alias2id'}{lc($new_name)} = [ $id,$i ];
455 9         22 $Data{$type}{'code2id'}{$codeset}{$code}[1] = $i;
456             }
457              
458 12         48 return 1;
459             }
460              
461             ###############################################################################
462              
463             # $flag = $o->add_code (CODE,NAME [,CODESET])
464             #
465             # Add a new code to the codeset. Both CODE and NAME must be
466             # unused in the code set.
467             #
468             sub add_code {
469 62     62 1 2963 my($self,$code,$name,$codeset) = @_;
470              
471 62 100       151 if (! $$self{'type'}) {
472 2 100       104 carp "ERROR: add_code: no type set for Locale::Codes object\n" if ($$self{'err'});
473 2         8 return 0;
474             }
475 60         82 my $type = $$self{'type'};
476              
477             # Make sure that $codeset is valid.
478              
479 60         187 my($err,$c,$cs) = $self->_code($code,$codeset,1);
480 60 100       132 if ($err) {
481 5 100       258 carp "ERROR: add_code: unknown codeset: $codeset\n" if ($$self{'err'});
482 5         23 return 0;
483             }
484 55         100 ($code,$codeset) = ($c,$cs);
485              
486             # Check that $code is unused.
487              
488 55 100 100     291 if (exists $Data{$type}{'code2id'}{$codeset}{$code} ||
489             exists $Data{$type}{'codealias'}{$codeset}{$code}) {
490 8 100       617 carp "ERROR: add_code: code already in use as alias: $code\n" if ($$self{'err'});
491 8         47 return 0;
492             }
493              
494             # Check to see that $name is unused in this code set. If it is
495             # used (but not in this code set), we'll use that ID. Otherwise,
496             # we'll need to get the next available ID.
497              
498 47         72 my ($id,$i);
499 47 100       227 if (exists $Data{$type}{'alias2id'}{lc($name)}) {
500 14         18 ($id,$i) = @{ $Data{$type}{'alias2id'}{lc($name)} };
  14         35  
501 14 100       41 if (exists $Data{$type}{'id2code'}{$codeset}{$id}) {
502 5 100       308 carp "ERROR: add_code: name already in use: $name\n" if ($$self{'err'});
503 5         25 return 0;
504             }
505              
506             } else {
507 33         78 $id = $Data{$type}{'id'}++;
508 33         47 $i = 0;
509 33         100 $Data{$type}{'alias2id'}{lc($name)} = [ $id,$i ];
510 33         101 $Data{$type}{'id2names'}{$id} = [ $name ];
511             }
512              
513             # Add the new code
514              
515 42         147 $Data{$type}{'code2id'}{$codeset}{$code} = [ $id,$i ];
516 42         97 $Data{$type}{'id2code'}{$codeset}{$id} = $code;
517              
518 42         192 return 1;
519             }
520              
521             ###############################################################################
522              
523             # $flag = $o->delete_code (CODE [,CODESET])
524             #
525             # Delete a code from the codeset.
526             #
527             sub delete_code {
528 34     34 1 1662 my($self,$code,$codeset) = @_;
529              
530 34 100       91 if (! $$self{'type'}) {
531 2 100       83 carp "ERROR: delete_code: no type set for Locale::Codes object\n" if ($$self{'err'});
532 2         8 return 0;
533             }
534 32         57 my $type = $$self{'type'};
535              
536             # Make sure $code/$codeset are both valid
537              
538 32         77 my($err,$c,$cs) = $self->_code($code,$codeset);
539 32 100       83 if ($err) {
540             carp "ERROR: delete_code: Unknown code/codeset: $code [$codeset]\n"
541 8 100       498 if ($$self{'err'});
542 8         44 return 0;
543             }
544 24         53 ($code,$codeset) = ($c,$cs);
545              
546             # Delete active codes
547              
548 24 50       65 if (exists $Data{$type}{'code2id'}{$codeset}{$code}) {
549              
550 24         55 my $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
551 24         61 delete $Data{$type}{'code2id'}{$codeset}{$code};
552 24         64 delete $Data{$type}{'id2code'}{$codeset}{$id};
553              
554             # Delete any aliases that are linked to this code
555              
556 24         33 foreach my $alias (keys %{ $Data{$type}{'codealias'}{$codeset} }) {
  24         93  
557 12 100       32 next if ($Data{$type}{'codealias'}{$codeset}{$alias} ne $code);
558 3         9 delete $Data{$type}{'codealias'}{$codeset}{$alias};
559             }
560              
561             # If this ID is used in any other codesets, we will leave all of the
562             # names in place. Otherwise, we'll delete them.
563              
564 24         43 my $inuse = 0;
565 24         64 foreach my $cs (keys %{ $Data{$type}{'id2code'} }) {
  24         82  
566 60 100       168 $inuse = 1, last if (exists $Data{$type}{'id2code'}{$cs}{$id});
567             }
568              
569 24 100       104 if (! $inuse) {
570 18         30 my @names = @{ $Data{$type}{'id2names'}{$id} };
  18         115  
571 18         42 delete $Data{$type}{'id2names'}{$id};
572              
573 18         39 foreach my $name (@names) {
574 18         131 delete $Data{$type}{'alias2id'}{lc($name)};
575             }
576             }
577             }
578              
579             # Delete retired codes
580              
581 24 50       87 if (exists $Retired{$type}{$codeset}{'code'}{$code}) {
582 0         0 my $name = $Retired{$type}{$codeset}{'code'}{$code};
583 0         0 delete $Retired{$type}{$codeset}{'code'}{$code};
584 0         0 delete $Retired{$type}{$codeset}{'name'}{lc($name)};
585             }
586              
587 24         102 return 1;
588             }
589              
590             ###############################################################################
591              
592             # $flag = $o->add_alias (NAME,NEW_NAME)
593             #
594             # Add a new alias. NAME must exist, and NEW_NAME must be unused.
595             #
596             sub add_alias {
597 40     40 1 1960 my($self,$name,$new_name) = @_;
598              
599 40 100       101 if (! $$self{'type'}) {
600 2 100       101 carp "ERROR: add_alias: no type set for Locale::Codes object\n" if ($$self{'err'});
601 2         7 return 0;
602             }
603 38         93 my $type = $$self{'type'};
604              
605             # Check that $name is used and $new_name is new.
606              
607 38         101 my($id);
608 38 100       130 if (exists $Data{$type}{'alias2id'}{lc($name)}) {
609 17         40 $id = $Data{$type}{'alias2id'}{lc($name)}[0];
610             } else {
611 21 100       1915 carp "ERROR: add_alias: name does not exist: $name\n" if ($$self{'err'});
612 21         115 return 0;
613             }
614              
615 17 100       46 if (exists $Data{$type}{'alias2id'}{lc($new_name)}) {
616 4 50       300 carp "ERROR: add_alias: alias already in use: $new_name\n" if ($$self{'err'});
617 4         21 return 0;
618             }
619              
620             # Add the new alias
621              
622 13         18 push @{ $Data{$type}{'id2names'}{$id} },$new_name;
  13         42  
623 13         15 my $i = $#{ $Data{$type}{'id2names'}{$id} };
  13         25  
624 13         36 $Data{$type}{'alias2id'}{lc($new_name)} = [ $id,$i ];
625              
626 13         45 return 1;
627             }
628              
629             ###############################################################################
630              
631             # $flag = $o->delete_alias (NAME)
632             #
633             # This deletes a name from the list of names used by an element.
634             # NAME must be used, but must NOT be the only name in the list.
635             #
636             # Any id2name that references this name will be changed to
637             # refer to the first name in the list.
638             #
639             sub delete_alias {
640 39     39 1 1975 my($self,$name) = @_;
641              
642 39 100       139 if (! $$self{'type'}) {
643 2 100       80 carp "ERROR: delete_alias: no type set for Locale::Codes object\n" if ($$self{'err'});
644 2         8 return 0;
645             }
646 37         58 my $type = $$self{'type'};
647              
648             # Check that $name is used.
649              
650 37         53 my($id,$i);
651 37 100       159 if (exists $Data{$type}{'alias2id'}{lc($name)}) {
652 17         21 ($id,$i) = @{ $Data{$type}{'alias2id'}{lc($name)} };
  17         67  
653             } else {
654 20 100       1740 carp "ERROR: delete_alias: name does not exist: $name\n" if ($$self{'err'});
655 20         167 return 0;
656             }
657              
658 17         28 my $n = $#{ $Data{$type}{'id2names'}{$id} } + 1;
  17         46  
659 17 100       30 if ($n == 1) {
660             carp "ERROR: delete_alias: only one name defined (use delete_code instead)\n"
661 5 100       362 if ($$self{'err'});
662 5         24 return 0;
663             }
664              
665             # Delete the alias.
666              
667 12         14 splice (@{ $Data{$type}{'id2names'}{$id} },$i,1);
  12         32  
668 12         31 delete $Data{$type}{'alias2id'}{lc($name)};
669              
670             # Every element that refers to this ID:
671             # Ignore if I < $i
672             # Set to 0 if I = $i
673             # Decrement if I > $i
674              
675 12         14 foreach my $codeset (keys %{ $Data{$type}{'code2id'} }) {
  12         40  
676 108         106 foreach my $code (keys %{ $Data{$type}{'code2id'}{$codeset} }) {
  108         3058  
677 28581         23277 my($jd,$j) = @{ $Data{$type}{'code2id'}{$codeset}{$code} };
  28581         37975  
678 28581 100 100     39315 next if ($jd ne $id ||
679             $j < $i);
680 12 100       30 if ($i == $j) {
681 6         17 $Data{$type}{'code2id'}{$codeset}{$code}[1] = 0;
682             } else {
683 6         13 $Data{$type}{'code2id'}{$codeset}{$code}[1]--;
684             }
685             }
686             }
687              
688 12         122 return 1;
689             }
690              
691             ###############################################################################
692              
693             # $flag = $o->replace_code (CODE,NEW_CODE [,CODESET])
694             #
695             # Change the official code. The original is retained as an alias, but
696             # the new code will be returned if do a name2code lookup.
697             #
698             sub replace_code {
699 44     44 1 2235 my($self,$code,$new_code,$codeset) = @_;
700              
701 44 100       111 if (! $$self{'type'}) {
702 2 100       92 carp "ERROR: replace_code: no type set for Locale::Codes object\n" if ($$self{'err'});
703 2         8 return 0;
704             }
705 42         60 my $type = $$self{'type'};
706              
707             # Make sure $code/$codeset are both valid (and that $new_code is the
708             # correct format)
709              
710 42         116 my($err,$c,$cs) = $self->_code($code,$codeset);
711 42 100       108 if ($err) {
712             carp "ERROR: replace_code: Unknown code/codeset: $code [$codeset]\n"
713 23 100       1943 if ($$self{'err'});
714 23         141 return 0;
715             }
716 19         28 ($code,$codeset) = ($c,$cs);
717              
718 19         30 ($err,$new_code,$codeset) = $self->_code($new_code,$codeset,1);
719              
720             # Cases:
721             # 1. Renaming code to an existing alias of this code:
722             # Make the alias real and the code an alias
723             #
724             # 2. Renaming code to some other existing alias:
725             # Error
726             #
727             # 3. Renaming code to some other code:
728             # Error (
729             #
730             # 4. Renaming code to a new code:
731             # Make code into an alias
732             # Replace code with new_code.
733              
734 19 100       57 if (exists $Data{$type}{'codealias'}{$codeset}{$new_code}) {
    100          
735             # Cases 1 and 2
736 8 100       24 if ($Data{$type}{'codealias'}{$codeset}{$new_code} eq $code) {
737             # Case 1
738              
739 3         10 delete $Data{$type}{'codealias'}{$codeset}{$new_code};
740              
741             } else {
742             # Case 2
743             carp "ERROR: replace_code: new code already in use as alias: $new_code\n"
744 5 100       318 if ($$self{'err'});
745 5         25 return 0;
746             }
747              
748             } elsif (exists $Data{$type}{'code2id'}{$codeset}{$new_code}) {
749             # Case 3
750             carp "ERROR: replace_code: new code already in use: $new_code\n"
751 5 100       359 if ($$self{'err'});
752 5         39 return 0;
753             }
754              
755             # Cases 1 and 4
756              
757 9         19 $Data{$type}{'codealias'}{$codeset}{$code} = $new_code;
758              
759 9         19 my $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
760             $Data{$type}{'code2id'}{$codeset}{$new_code} =
761 9         23 $Data{$type}{'code2id'}{$codeset}{$code};
762 9         16 delete $Data{$type}{'code2id'}{$codeset}{$code};
763              
764 9         17 $Data{$type}{'id2code'}{$codeset}{$id} = $new_code;
765              
766 9         33 return 1;
767             }
768              
769             ###############################################################################
770              
771             # $flag = $o->add_code_alias (CODE,NEW_CODE [,CODESET])
772             #
773             # Adds an alias for the code.
774             #
775             sub add_code_alias {
776 44     44 1 2333 my($self,$code,$new_code,$codeset) = @_;
777              
778 44 100       125 if (! $$self{'type'}) {
779 2 100       79 carp "ERROR: add_code_alias: no type set for Locale::Codes object\n" if ($$self{'err'});
780 2         9 return 0;
781             }
782 42         96 my $type = $$self{'type'};
783              
784             # Make sure $code/$codeset are both valid and that the new code is
785             # properly formatted.
786              
787 42         93 my($err,$c,$cs) = $self->_code($code,$codeset);
788 42 100       101 if ($err) {
789             carp "ERROR: add_code_alias: unknown code/codeset: $code [$codeset]\n"
790 23 100       1698 if ($$self{'err'});
791 23         140 return 0;
792             }
793 19         27 ($code,$codeset) = ($c,$cs);
794              
795 19         32 ($err,$new_code,$cs) = $self->_code($new_code,$codeset,1);
796              
797             # Check that $new_code does not exist.
798              
799 19 100 100     70 if (exists $Data{$type}{'code2id'}{$codeset}{$new_code} ||
800             exists $Data{$type}{'codealias'}{$codeset}{$new_code}) {
801 8 100       601 carp "ERROR: add_code_alias: code already in use: $new_code\n" if ($$self{'err'});
802 8         41 return 0;
803             }
804              
805             # Add the alias
806              
807 11         23 $Data{$type}{'codealias'}{$codeset}{$new_code} = $code;
808              
809 11         36 return 1;
810             }
811              
812             ###############################################################################
813              
814             # $flag = $o->delete_code_alias (ALIAS [,CODESET])
815             #
816             # Deletes an alias for the code.
817             #
818             sub delete_code_alias {
819 36     36 1 1866 my($self,$code,$codeset) = @_;
820              
821 36 100       100 if (! $$self{'type'}) {
822 2 100       70 carp "ERROR: delete_code_alias: no type set for Locale::Codes object\n" if ($$self{'err'});
823 2         8 return 0;
824             }
825 34         70 my $type = $$self{'type'};
826              
827             # Make sure $code/$codeset are both valid
828              
829 34         95 my($err,$c,$cs) = $self->_code($code,$codeset);
830 34 100       88 if ($err) {
831             carp "ERROR: delete_code_alias: unknown code/codeset: $code [$codeset]\n"
832 23 100       1858 if ($$self{'err'});
833 23         146 return 0;
834             }
835 11         19 ($code,$codeset) = ($c,$cs);
836              
837             # Check that $code exists in the codeset as an alias.
838              
839 11 100       29 if (! exists $Data{$type}{'codealias'}{$codeset}{$code}) {
840 5 100       372 carp "ERROR: delete_code_alias: no alias defined: $code\n" if ($$self{'err'});
841 5         27 return 0;
842             }
843              
844             # Delete the alias
845              
846 6         15 delete $Data{$type}{'codealias'}{$codeset}{$code};
847              
848 6         23 return 1;
849             }
850              
851             1;
852             # Local Variables:
853             # mode: cperl
854             # indent-tabs-mode: nil
855             # cperl-indent-level: 3
856             # cperl-continued-statement-offset: 2
857             # cperl-continued-brace-offset: 0
858             # cperl-brace-offset: 0
859             # cperl-brace-imaginary-offset: 0
860             # cperl-label-offset: 0
861             # End: