File Coverage

blib/lib/Locale/Codes.pm
Criterion Covered Total %
statement 367 376 98.6
branch 230 240 96.6
condition 49 54 90.7
subroutine 25 26 100.0
pod 19 19 100.0
total 690 715 97.4


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