File Coverage

blib/lib/Locale/Codes.pm
Criterion Covered Total %
statement 367 376 98.6
branch 229 240 96.2
condition 49 54 90.7
subroutine 25 26 100.0
pod 19 19 100.0
total 689 715 97.3


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   53254 use strict;
  19         49  
  19         554  
11 19     19   93 use warnings;
  19         35  
  19         561  
12             require 5.006;
13              
14 19     19   98 use Carp;
  19         34  
  19         1410  
15 19     19   5265 use if $] >= 5.027007, 'deprecate';
  19         133  
  19         229  
16 19     19   8779 use Locale::Codes::Constants;
  19         45  
  19         4006  
17              
18             our($VERSION);
19             $VERSION='3.76';
20              
21 19     19   134 use Exporter qw(import);
  19         35  
  19         94187  
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 92753 my($class,$type,$codeset,$show_errors) = @_;
50 32 100       159 my $self = { 'type' => '',
51             'codeset' => '',
52             'err' => (defined($show_errors) ? $show_errors : 1),
53             };
54              
55 32         75 bless $self,$class;
56              
57 32 100       153 $self->type($type) if ($type);
58 32 100       98 $self->codeset($codeset) if ($codeset);
59 32         121 return $self;
60             }
61              
62             sub show_errors {
63 65     65 1 2671 my($self,$val) = @_;
64 65         136 $$self{'err'} = $val;
65 65         160 return $val;
66             }
67              
68             sub type {
69 30     30 1 1584 my($self,$type) = @_;
70              
71 30 100       108 if (! exists $ALL_CODESETS{$type}) {
72 2 100       222 carp "ERROR: type: invalid argument: $type\n" if ($$self{'err'});
73 2         74 return 1;
74             }
75              
76 28         63 my $label = $ALL_CODESETS{$type}{'module'};
77 28         1597 eval "require Locale::Codes::${label}_Codes";
78             # uncoverable branch true
79 28 50       949 if ($@) {
80             # uncoverable statement
81 0         0 croak "ERROR: type: unable to load module: ${label}_Codes\n";
82             }
83 28         2272 eval "require Locale::Codes::${label}_Retired";
84             # uncoverable branch true
85 28 50       170 if ($@) {
86             # uncoverable statement
87 0         0 croak "ERROR: type: unable to load module: ${label}_Retired\n";
88             }
89              
90 28         192 $$self{'type'} = $type;
91 28         85 $$self{'codeset'} = $ALL_CODESETS{$type}{'default'};
92              
93 28         104 return 0;
94             }
95              
96             sub codeset {
97 4     4 1 368 my($self,$codeset) = @_;
98              
99 4         8 my $type = $$self{'type'};
100 4 100       15 if (! exists $ALL_CODESETS{$type}{'codesets'}{$codeset}) {
101 2 100       85 carp "ERROR: codeset: invalid argument: $codeset\n" if ($$self{'err'});
102 2         46 return 1;
103             }
104              
105 2         4 $$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 1279     1279   4048 my($self,$code,$codeset,$no_check_code) = @_;
138 1279 100       2507 $code = '' if (! defined($code));
139 1279 100       2622 $codeset = lc($codeset) if (defined($codeset));
140              
141 1279 100       2283 if (! $$self{'type'}) {
142             carp "ERROR: _code: no type set for Locale::Codes object\n"
143 2 100       85 if ($$self{'err'});
144 2         37 return (1);
145             }
146 1277         1736 my $type = $$self{'type'};
147 1277 100 100     3497 if ($codeset && ! exists $ALL_CODESETS{$type}{'codesets'}{$codeset}) {
148             carp "ERROR: _code: invalid codeset provided: $codeset\n"
149 39 100       3873 if ($$self{'err'});
150 39         1547 return (1);
151             }
152              
153             # If no codeset was passed in, return the codeset specified.
154              
155 1238 100 100     3192 $codeset = $$self{'codeset'} if (! defined($codeset) || $codeset eq '');
156 1238 100       2895 return (0,'',$codeset) if ($code eq '');
157              
158             # Determine the properties of the codeset
159              
160 811         1133 my($op,@args) = @{ $ALL_CODESETS{$type}{'codesets'}{$codeset} };
  811         1889  
161              
162 811 100       1738 if ($op eq 'lc') {
163 671         1013 $code = lc($code);
164             }
165              
166 811 100       1555 if ($op eq 'uc') {
167 72         117 $code = uc($code);
168             }
169              
170 811 100       1537 if ($op eq 'ucfirst') {
171 30         74 $code = ucfirst(lc($code));
172             }
173              
174 811 100       1487 if ($op eq 'numeric') {
175 38 100       215 if ($code =~ /^\d+$/) {
176 30         54 my $l = $args[0];
177 30         170 $code = sprintf("%.${l}d", $code);
178              
179             } else {
180 8 100       587 carp "ERROR: _code: invalid numeric code: $code\n" if ($$self{'err'});
181 8         275 return (1);
182             }
183             }
184              
185             # Determine if the code is in the codeset.
186              
187 803 100 100     3950 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       14071 if ($$self{'err'});
193 152         5876 return (1);
194             }
195              
196 651         1994 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 31720 my($self,@args) = @_;
209 482         699 my $retired = 0;
210 482 100 100     2945 if (@args && defined($args[$#args]) && lc($args[$#args]) eq 'retired') {
      100        
211 9         16 pop(@args);
212 9         20 $retired = 1;
213             }
214              
215 482 100       1221 if (! $$self{'type'}) {
216 2 100       75 carp "ERROR: code2name: no type set for Locale::Codes object\n" if ($$self{'err'});
217 2         46 return undef;
218             }
219 480         747 my $type = $$self{'type'};
220              
221 480         963 my ($err,$code,$codeset) = $self->_code(@args);
222 480 100 100     1792 return undef if ($err || ! $code);
223              
224             $code = $Data{$type}{'codealias'}{$codeset}{$code}
225 414 100       976 if (exists $Data{$type}{'codealias'}{$codeset}{$code});
226              
227 414 100 66     945 if (exists $Data{$type}{'code2id'}{$codeset}{$code}) {
    100          
228 393         516 my ($id,$i) = @{ $Data{$type}{'code2id'}{$codeset}{$code} };
  393         1012  
229 393         1060 my $name = $Data{$type}{'id2names'}{$id}[$i];
230 393         2061 return $name;
231              
232             } elsif ($retired && exists $Retired{$type}{$codeset}{'code'}{$code}) {
233 3         20 return $Retired{$type}{$codeset}{'code'}{$code};
234             }
235              
236 18         107 return undef;
237             }
238              
239             sub name2code {
240 323     323 1 250695 my($self,$name,@args) = @_;
241 323 100       779 return undef if (! $name);
242 305         588 $name = lc($name);
243              
244 305         432 my $retired = 0;
245 305 100 66     1086 if (@args && defined($args[$#args]) && lc($args[$#args]) eq 'retired') {
      100        
246 6         15 pop(@args);
247 6         13 $retired = 1;
248             }
249              
250 305 100       750 if (! $$self{'type'}) {
251 2 100       67 carp "ERROR: name2code: no type set for Locale::Codes object\n" if ($$self{'err'});
252 2         43 return undef;
253             }
254 303         459 my $type = $$self{'type'};
255              
256 303         642 my ($err,$tmp,$codeset) = $self->_code('',@args);
257 303 100       694 return undef if ($err);
258              
259 300 100 66     993 if (exists $Data{$type}{'alias2id'}{$name}) {
    100          
260 267         663 my $id = $Data{$type}{'alias2id'}{$name}[0];
261 267 100       833 if (exists $Data{$type}{'id2code'}{$codeset}{$id}) {
262 255         888 return $Data{$type}{'id2code'}{$codeset}{$id};
263             }
264              
265             } elsif ($retired && exists $Retired{$type}{$codeset}{'name'}{$name}) {
266 3         16 return $Retired{$type}{$codeset}{'name'}{$name}[0];
267             }
268              
269 42         102 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 4897 my($self,@args) = @_;
280              
281 68 100       247 if (! $$self{'type'}) {
282             carp "ERROR: code2code: no type set for Locale::Codes object\n"
283 2 100       69 if ($$self{'err'});
284 2         34 return undef;
285             }
286 66         123 my $type = $$self{'type'};
287              
288 66         112 my($code,$codeset1,$codeset2,$err);
289              
290 66 100       249 if (@args == 2) {
    100          
291 3         17 ($code,$codeset2) = @args;
292 3         14 ($err,$code,$codeset1) = $self->_code($code);
293 3 50       16 return undef if ($err);
294              
295             } elsif (@args == 3) {
296 60         139 ($code,$codeset1,$codeset2) = @args;
297 60         167 ($err,$code) = $self->_code($code,$codeset1);
298 60 100       182 return undef if ($err);
299 48         130 ($err) = $self->_code('',$codeset2);
300 48 50       138 return undef if ($err);
301             }
302              
303 54         141 my $name = $self->code2name($code,$codeset1);
304 54         148 my $out = $self->name2code($name,$codeset2);
305 54         181 return $out;
306             }
307              
308             sub code2names {
309 3     3 1 209 my($self,@args) = @_;
310              
311 3 50       16 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         11 my $type = $$self{'type'};
317              
318 3         13 my ($err,$code,$codeset) = $self->_code(@args);
319 3 50 33     39 return undef if ($err || ! $code);
320              
321 3         14 my $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
322 3         11 my @name = @{ $Data{$type}{'id2names'}{$id} };
  3         14  
323 3         31 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 2945 my($self,@args) = @_;
335 47         85 my $retired = 0;
336 47 100 100     238 if (@args && lc($args[$#args]) eq 'retired') {
337 3         8 pop(@args);
338 3         10 $retired = 1;
339             }
340              
341 47 100       183 if (! $$self{'type'}) {
342 2 100       66 carp "ERROR: all_codes: no type set for Locale::Codes object\n" if ($$self{'err'});
343 2         33 return ();
344             }
345 45         95 my $type = $$self{'type'};
346              
347 45         129 my ($err,$tmp,$codeset) = $self->_code('',@args);
348 45 100       134 return () if ($err);
349              
350 42         70 my @codes = keys %{ $Data{$type}{'code2id'}{$codeset} };
  42         1089  
351 42 100       153 push(@codes,keys %{ $Retired{$type}{$codeset}{'code'} }) if ($retired);
  3         80  
352 42         3136 return (sort @codes);
353             }
354              
355             sub all_names {
356 26     26 1 54138 my($self,@args) = @_;
357 26         51 my $retired = 0;
358 26 100 100     145 if (@args && lc($args[$#args]) eq 'retired') {
359 3         10 pop(@args);
360 3         6 $retired = 1;
361             }
362              
363 26 100       109 if (! $$self{'type'}) {
364 2 100       74 carp "ERROR: all_names: no type set for Locale::Codes object\n" if ($$self{'err'});
365 2         35 return ();
366             }
367 24         57 my $type = $$self{'type'};
368              
369 24         96 my ($err,$tmp,$codeset) = $self->_code('',@args);
370 24 100       98 return () if ($err);
371              
372 21         99 my @codes = $self->all_codes($codeset);
373 21         62 my @names;
374              
375 21         66 foreach my $code (@codes) {
376 4165         4819 my($id,$i) = @{ $Data{$type}{'code2id'}{$codeset}{$code} };
  4165         7937  
377 4165         7809 my $name = $Data{$type}{'id2names'}{$id}[$i];
378 4165         6847 push(@names,$name);
379             }
380 21 100       95 if ($retired) {
381 3         32 foreach my $lc (keys %{ $Retired{$type}{$codeset}{'name'} }) {
  3         65  
382 156         394 my $name = $Retired{$type}{$codeset}{'name'}{$lc}[1];
383 156         279 push @names,$name;
384             }
385             }
386 21         2101 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 5093 my($self,$code,$new_name,$codeset) = @_;
401              
402 54 100       189 if (! $$self{'type'}) {
403 2 100       120 carp "ERROR: rename_code: no type set for Locale::Codes object\n" if ($$self{'err'});
404 2         52 return 0;
405             }
406 52         95 my $type = $$self{'type'};
407              
408             # Make sure $code/$codeset are both valid
409              
410 52         196 my($err,$c,$cs) = $self->_code($code,$codeset);
411 52 100       171 if ($err) {
412             carp "ERROR: rename_code: unknown code/codeset: $code [$codeset]\n"
413 32 100       2551 if ($$self{'err'});
414 32         1288 return 0;
415             }
416 20         70 ($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         59 my $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
430              
431 20 100       104 if (exists $Data{$type}{'alias2id'}{lc($new_name)}) {
432             # Existing name (case 1 and 2)
433              
434 11         21 my ($new_id,$i) = @{ $Data{$type}{'alias2id'}{lc($new_name)} };
  11         49  
435 11 100       81 if ($new_id != $id) {
436             # Case 1
437             carp "ERROR: rename_code: rename to an existing name not allowed\n"
438 8 100       593 if ($$self{'err'});
439 8         342 return 0;
440             }
441              
442             # Case 2
443              
444 3         14 $Data{$type}{'code2id'}{$codeset}{$code}[1] = $i;
445              
446             } else {
447              
448             # Case 3
449              
450 9         24 push @{ $Data{$type}{'id2names'}{$id} },$new_name;
  9         43  
451 9         22 my $i = $#{ $Data{$type}{'id2names'}{$id} };
  9         35  
452 9         37 $Data{$type}{'alias2id'}{lc($new_name)} = [ $id,$i ];
453 9         31 $Data{$type}{'code2id'}{$codeset}{$code}[1] = $i;
454             }
455              
456 12         82 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 4930 my($self,$code,$name,$codeset) = @_;
468              
469 62 100       207 if (! $$self{'type'}) {
470 2 100       71 carp "ERROR: add_code: no type set for Locale::Codes object\n" if ($$self{'err'});
471 2         49 return 0;
472             }
473 60         123 my $type = $$self{'type'};
474              
475             # Make sure that $codeset is valid.
476              
477 60         178 my($err,$c,$cs) = $self->_code($code,$codeset,1);
478 60 100       224 if ($err) {
479 5 100       343 carp "ERROR: add_code: unknown codeset: $codeset\n" if ($$self{'err'});
480 5         163 return 0;
481             }
482 55         129 ($code,$codeset) = ($c,$cs);
483              
484             # Check that $code is unused.
485              
486 55 100 100     384 if (exists $Data{$type}{'code2id'}{$codeset}{$code} ||
487             exists $Data{$type}{'codealias'}{$codeset}{$code}) {
488 8 100       542 carp "ERROR: add_code: code already in use as alias: $code\n" if ($$self{'err'});
489 8         286 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         110 my ($id,$i);
497 47 100       191 if (exists $Data{$type}{'alias2id'}{lc($name)}) {
498 14         23 ($id,$i) = @{ $Data{$type}{'alias2id'}{lc($name)} };
  14         50  
499 14 100       61 if (exists $Data{$type}{'id2code'}{$codeset}{$id}) {
500 5 100       328 carp "ERROR: add_code: name already in use: $name\n" if ($$self{'err'});
501 5         172 return 0;
502             }
503              
504             } else {
505 33         110 $id = $Data{$type}{'id'}++;
506 33         62 $i = 0;
507 33         148 $Data{$type}{'alias2id'}{lc($name)} = [ $id,$i ];
508 33         153 $Data{$type}{'id2names'}{$id} = [ $name ];
509             }
510              
511             # Add the new code
512              
513 42         146 $Data{$type}{'code2id'}{$codeset}{$code} = [ $id,$i ];
514 42         142 $Data{$type}{'id2code'}{$codeset}{$id} = $code;
515              
516 42         298 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 2886 my($self,$code,$codeset) = @_;
527              
528 34 100       129 if (! $$self{'type'}) {
529 2 100       68 carp "ERROR: delete_code: no type set for Locale::Codes object\n" if ($$self{'err'});
530 2         45 return 0;
531             }
532 32         69 my $type = $$self{'type'};
533              
534             # Make sure $code/$codeset are both valid
535              
536 32         106 my($err,$c,$cs) = $self->_code($code,$codeset);
537 32 100       115 if ($err) {
538             carp "ERROR: delete_code: Unknown code/codeset: $code [$codeset]\n"
539 8 100       545 if ($$self{'err'});
540 8         339 return 0;
541             }
542 24         81 ($code,$codeset) = ($c,$cs);
543              
544             # Delete active codes
545              
546 24 50       88 if (exists $Data{$type}{'code2id'}{$codeset}{$code}) {
547              
548 24         72 my $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
549 24         80 delete $Data{$type}{'code2id'}{$codeset}{$code};
550 24         65 delete $Data{$type}{'id2code'}{$codeset}{$id};
551              
552             # Delete any aliases that are linked to this code
553              
554 24         53 foreach my $alias (keys %{ $Data{$type}{'codealias'}{$codeset} }) {
  24         117  
555 12 100       45 next if ($Data{$type}{'codealias'}{$codeset}{$alias} ne $code);
556 3         10 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         72 my $inuse = 0;
563 24         44 foreach my $cs (keys %{ $Data{$type}{'id2code'} }) {
  24         108  
564 62 100       213 $inuse = 1, last if (exists $Data{$type}{'id2code'}{$cs}{$id});
565             }
566              
567 24 100       85 if (! $inuse) {
568 18         36 my @names = @{ $Data{$type}{'id2names'}{$id} };
  18         90  
569 18         62 delete $Data{$type}{'id2names'}{$id};
570              
571 18         61 foreach my $name (@names) {
572 18         93 delete $Data{$type}{'alias2id'}{lc($name)};
573             }
574             }
575             }
576              
577             # Delete retired codes
578              
579 24 50       106 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         151 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 3764 my($self,$name,$new_name) = @_;
596              
597 40 100       147 if (! $$self{'type'}) {
598 2 100       77 carp "ERROR: add_alias: no type set for Locale::Codes object\n" if ($$self{'err'});
599 2         49 return 0;
600             }
601 38         74 my $type = $$self{'type'};
602              
603             # Check that $name is used and $new_name is new.
604              
605 38         66 my($id);
606 38 100       168 if (exists $Data{$type}{'alias2id'}{lc($name)}) {
607 17         53 $id = $Data{$type}{'alias2id'}{lc($name)}[0];
608             } else {
609 21 100       1610 carp "ERROR: add_alias: name does not exist: $name\n" if ($$self{'err'});
610 21         846 return 0;
611             }
612              
613 17 100       59 if (exists $Data{$type}{'alias2id'}{lc($new_name)}) {
614 4 50       296 carp "ERROR: add_alias: alias already in use: $new_name\n" if ($$self{'err'});
615 4         184 return 0;
616             }
617              
618             # Add the new alias
619              
620 13         22 push @{ $Data{$type}{'id2names'}{$id} },$new_name;
  13         49  
621 13         24 my $i = $#{ $Data{$type}{'id2names'}{$id} };
  13         43  
622 13         207 $Data{$type}{'alias2id'}{lc($new_name)} = [ $id,$i ];
623              
624 13         86 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 3261 my($self,$name) = @_;
639              
640 39 100       134 if (! $$self{'type'}) {
641 2 100       74 carp "ERROR: delete_alias: no type set for Locale::Codes object\n" if ($$self{'err'});
642 2         45 return 0;
643             }
644 37         93 my $type = $$self{'type'};
645              
646             # Check that $name is used.
647              
648 37         82 my($id,$i);
649 37 100       195 if (exists $Data{$type}{'alias2id'}{lc($name)}) {
650 17         27 ($id,$i) = @{ $Data{$type}{'alias2id'}{lc($name)} };
  17         56  
651             } else {
652 20 100       1546 carp "ERROR: delete_alias: name does not exist: $name\n" if ($$self{'err'});
653 20         855 return 0;
654             }
655              
656 17         59 my $n = $#{ $Data{$type}{'id2names'}{$id} } + 1;
  17         97  
657 17 100       53 if ($n == 1) {
658             carp "ERROR: delete_alias: only one name defined (use delete_code instead)\n"
659 5 100       385 if ($$self{'err'});
660 5         172 return 0;
661             }
662              
663             # Delete the alias.
664              
665 12         18 splice (@{ $Data{$type}{'id2names'}{$id} },$i,1);
  12         36  
666 12         45 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         21 foreach my $codeset (keys %{ $Data{$type}{'code2id'} }) {
  12         58  
674 108         152 foreach my $code (keys %{ $Data{$type}{'code2id'}{$codeset} }) {
  108         3375  
675 27789         31126 my($jd,$j) = @{ $Data{$type}{'code2id'}{$codeset}{$code} };
  27789         52857  
676 27789 100 100     52776 next if ($jd ne $id ||
677             $j < $i);
678 12 100       44 if ($i == $j) {
679 6         21 $Data{$type}{'code2id'}{$codeset}{$code}[1] = 0;
680             } else {
681 6         18 $Data{$type}{'code2id'}{$codeset}{$code}[1]--;
682             }
683             }
684             }
685              
686 12         149 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 3740 my($self,$code,$new_code,$codeset) = @_;
698              
699 44 100       146 if (! $$self{'type'}) {
700 2 100       69 carp "ERROR: replace_code: no type set for Locale::Codes object\n" if ($$self{'err'});
701 2         48 return 0;
702             }
703 42         87 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         121 my($err,$c,$cs) = $self->_code($code,$codeset);
709 42 100       149 if ($err) {
710             carp "ERROR: replace_code: Unknown code/codeset: $code [$codeset]\n"
711 23 100       1759 if ($$self{'err'});
712 23         867 return 0;
713             }
714 19         44 ($code,$codeset) = ($c,$cs);
715              
716 19         46 ($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       96 if (exists $Data{$type}{'codealias'}{$codeset}{$new_code}) {
    100          
733             # Cases 1 and 2
734 8 100       37 if ($Data{$type}{'codealias'}{$codeset}{$new_code} eq $code) {
735             # Case 1
736              
737 3         11 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       304 if ($$self{'err'});
743 5         168 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       308 if ($$self{'err'});
750 5         170 return 0;
751             }
752              
753             # Cases 1 and 4
754              
755 9         24 $Data{$type}{'codealias'}{$codeset}{$code} = $new_code;
756              
757 9         28 my $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
758             $Data{$type}{'code2id'}{$codeset}{$new_code} =
759 9         27 $Data{$type}{'code2id'}{$codeset}{$code};
760 9         23 delete $Data{$type}{'code2id'}{$codeset}{$code};
761              
762 9         27 $Data{$type}{'id2code'}{$codeset}{$id} = $new_code;
763              
764 9         55 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 3726 my($self,$code,$new_code,$codeset) = @_;
775              
776 44 100       173 if (! $$self{'type'}) {
777 2 100       72 carp "ERROR: add_code_alias: no type set for Locale::Codes object\n" if ($$self{'err'});
778 2         49 return 0;
779             }
780 42         95 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         128 my($err,$c,$cs) = $self->_code($code,$codeset);
786 42 100       161 if ($err) {
787             carp "ERROR: add_code_alias: unknown code/codeset: $code [$codeset]\n"
788 23 100       1733 if ($$self{'err'});
789 23         862 return 0;
790             }
791 19         157 ($code,$codeset) = ($c,$cs);
792              
793 19         153 ($err,$new_code,$cs) = $self->_code($new_code,$codeset,1);
794              
795             # Check that $new_code does not exist.
796              
797 19 100 100     99 if (exists $Data{$type}{'code2id'}{$codeset}{$new_code} ||
798             exists $Data{$type}{'codealias'}{$codeset}{$new_code}) {
799 8 100       521 carp "ERROR: add_code_alias: code already in use: $new_code\n" if ($$self{'err'});
800 8         280 return 0;
801             }
802              
803             # Add the alias
804              
805 11         38 $Data{$type}{'codealias'}{$codeset}{$new_code} = $code;
806              
807 11         63 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 3154 my($self,$code,$codeset) = @_;
818              
819 36 100       140 if (! $$self{'type'}) {
820 2 100       69 carp "ERROR: delete_code_alias: no type set for Locale::Codes object\n" if ($$self{'err'});
821 2         41 return 0;
822             }
823 34         185 my $type = $$self{'type'};
824              
825             # Make sure $code/$codeset are both valid
826              
827 34         168 my($err,$c,$cs) = $self->_code($code,$codeset);
828 34 100       225 if ($err) {
829             carp "ERROR: delete_code_alias: unknown code/codeset: $code [$codeset]\n"
830 23 100       1743 if ($$self{'err'});
831 23         797 return 0;
832             }
833 11         31 ($code,$codeset) = ($c,$cs);
834              
835             # Check that $code exists in the codeset as an alias.
836              
837 11 100       40 if (! exists $Data{$type}{'codealias'}{$codeset}{$code}) {
838 5 100       320 carp "ERROR: delete_code_alias: no alias defined: $code\n" if ($$self{'err'});
839 5         159 return 0;
840             }
841              
842             # Delete the alias
843              
844 6         21 delete $Data{$type}{'codealias'}{$codeset}{$code};
845              
846 6         34 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: