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   55445 use strict;
  19         42  
  19         567  
11 19     19   91 use warnings;
  19         35  
  19         527  
12             require 5.006;
13              
14 19     19   105 use Carp;
  19         41  
  19         1284  
15 19     19   5988 use if $] >= 5.027007, 'deprecate';
  19         133  
  19         197  
16 19     19   9201 use Locale::Codes::Constants;
  19         50  
  19         4103  
17              
18             our($VERSION);
19             $VERSION='3.75';
20              
21 19     19   133 use Exporter qw(import);
  19         38  
  19         96068  
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 100073 my($class,$type,$codeset,$show_errors) = @_;
50 32 100       199 my $self = { 'type' => '',
51             'codeset' => '',
52             'err' => (defined($show_errors) ? $show_errors : 1),
53             };
54              
55 32         79 bless $self,$class;
56              
57 32 100       165 $self->type($type) if ($type);
58 32 100       110 $self->codeset($codeset) if ($codeset);
59 32         129 return $self;
60             }
61              
62             sub show_errors {
63 65     65 1 2737 my($self,$val) = @_;
64 65         131 $$self{'err'} = $val;
65 65         153 return $val;
66             }
67              
68             sub type {
69 30     30 1 1642 my($self,$type) = @_;
70              
71 30 100       130 if (! exists $ALL_CODESETS{$type}) {
72 2 100       258 carp "ERROR: type: invalid argument: $type\n" if ($$self{'err'});
73 2         95 return 1;
74             }
75              
76 28         66 my $label = $ALL_CODESETS{$type}{'module'};
77 28         1993 eval "require Locale::Codes::${label}_Codes";
78             # uncoverable branch true
79 28 50       950 if ($@) {
80             # uncoverable statement
81 0         0 croak "ERROR: type: unable to load module: ${label}_Codes\n";
82             }
83 28         2694 eval "require Locale::Codes::${label}_Retired";
84             # uncoverable branch true
85 28 50       175 if ($@) {
86             # uncoverable statement
87 0         0 croak "ERROR: type: unable to load module: ${label}_Retired\n";
88             }
89              
90 28         220 $$self{'type'} = $type;
91 28         86 $$self{'codeset'} = $ALL_CODESETS{$type}{'default'};
92              
93 28         77 return 0;
94             }
95              
96             sub codeset {
97 4     4 1 351 my($self,$codeset) = @_;
98              
99 4         6 my $type = $$self{'type'};
100 4 100       12 if (! exists $ALL_CODESETS{$type}{'codesets'}{$codeset}) {
101 2 100       85 carp "ERROR: codeset: invalid argument: $codeset\n" if ($$self{'err'});
102 2         44 return 1;
103             }
104              
105 2         5 $$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   4267 my($self,$code,$codeset,$no_check_code) = @_;
138 1279 100       2454 $code = '' if (! defined($code));
139 1279 100       2496 $codeset = lc($codeset) if (defined($codeset));
140              
141 1279 100       2367 if (! $$self{'type'}) {
142             carp "ERROR: _code: no type set for Locale::Codes object\n"
143 2 100       78 if ($$self{'err'});
144 2         36 return (1);
145             }
146 1277         1712 my $type = $$self{'type'};
147 1277 100 100     3341 if ($codeset && ! exists $ALL_CODESETS{$type}{'codesets'}{$codeset}) {
148             carp "ERROR: _code: invalid codeset provided: $codeset\n"
149 39 100       3506 if ($$self{'err'});
150 39         1582 return (1);
151             }
152              
153             # If no codeset was passed in, return the codeset specified.
154              
155 1238 100 100     3188 $codeset = $$self{'codeset'} if (! defined($codeset) || $codeset eq '');
156 1238 100       2729 return (0,'',$codeset) if ($code eq '');
157              
158             # Determine the properties of the codeset
159              
160 811         1062 my($op,@args) = @{ $ALL_CODESETS{$type}{'codesets'}{$codeset} };
  811         1820  
161              
162 811 100       1605 if ($op eq 'lc') {
163 671         1060 $code = lc($code);
164             }
165              
166 811 100       1438 if ($op eq 'uc') {
167 72         120 $code = uc($code);
168             }
169              
170 811 100       1419 if ($op eq 'ucfirst') {
171 30         68 $code = ucfirst(lc($code));
172             }
173              
174 811 100       1436 if ($op eq 'numeric') {
175 38 100       216 if ($code =~ /^\d+$/) {
176 30         60 my $l = $args[0];
177 30         173 $code = sprintf("%.${l}d", $code);
178              
179             } else {
180 8 100       546 carp "ERROR: _code: invalid numeric code: $code\n" if ($$self{'err'});
181 8         262 return (1);
182             }
183             }
184              
185             # Determine if the code is in the codeset.
186              
187 803 100 100     3817 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       13844 if ($$self{'err'});
193 152         6076 return (1);
194             }
195              
196 651         2066 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 25625 my($self,@args) = @_;
209 482         702 my $retired = 0;
210 482 100 100     2763 if (@args && defined($args[$#args]) && lc($args[$#args]) eq 'retired') {
      100        
211 9         18 pop(@args);
212 9         18 $retired = 1;
213             }
214              
215 482 100       1171 if (! $$self{'type'}) {
216 2 100       103 carp "ERROR: code2name: no type set for Locale::Codes object\n" if ($$self{'err'});
217 2         51 return undef;
218             }
219 480         743 my $type = $$self{'type'};
220              
221 480         1008 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       1044 if (exists $Data{$type}{'codealias'}{$codeset}{$code});
226              
227 414 100 66     928 if (exists $Data{$type}{'code2id'}{$codeset}{$code}) {
    100          
228 393         493 my ($id,$i) = @{ $Data{$type}{'code2id'}{$codeset}{$code} };
  393         997  
229 393         858 my $name = $Data{$type}{'id2names'}{$id}[$i];
230 393         2035 return $name;
231              
232             } elsif ($retired && exists $Retired{$type}{$codeset}{'code'}{$code}) {
233 3         22 return $Retired{$type}{$codeset}{'code'}{$code};
234             }
235              
236 18         105 return undef;
237             }
238              
239             sub name2code {
240 323     323 1 247887 my($self,$name,@args) = @_;
241 323 100       775 return undef if (! $name);
242 305         606 $name = lc($name);
243              
244 305         412 my $retired = 0;
245 305 100 66     1076 if (@args && defined($args[$#args]) && lc($args[$#args]) eq 'retired') {
      100        
246 6         19 pop(@args);
247 6         15 $retired = 1;
248             }
249              
250 305 100       721 if (! $$self{'type'}) {
251 2 100       79 carp "ERROR: name2code: no type set for Locale::Codes object\n" if ($$self{'err'});
252 2         63 return undef;
253             }
254 303         439 my $type = $$self{'type'};
255              
256 303         694 my ($err,$tmp,$codeset) = $self->_code('',@args);
257 303 100       724 return undef if ($err);
258              
259 300 100 66     1102 if (exists $Data{$type}{'alias2id'}{$name}) {
    100          
260 267         707 my $id = $Data{$type}{'alias2id'}{$name}[0];
261 267 100       839 if (exists $Data{$type}{'id2code'}{$codeset}{$id}) {
262 255         849 return $Data{$type}{'id2code'}{$codeset}{$id};
263             }
264              
265             } elsif ($retired && exists $Retired{$type}{$codeset}{'name'}{$name}) {
266 3         23 return $Retired{$type}{$codeset}{'name'}{$name}[0];
267             }
268              
269 42         99 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 4405 my($self,@args) = @_;
280              
281 68 100       224 if (! $$self{'type'}) {
282             carp "ERROR: code2code: no type set for Locale::Codes object\n"
283 2 100       77 if ($$self{'err'});
284 2         32 return undef;
285             }
286 66         109 my $type = $$self{'type'};
287              
288 66         138 my($code,$codeset1,$codeset2,$err);
289              
290 66 100       218 if (@args == 2) {
    100          
291 3         25 ($code,$codeset2) = @args;
292 3         11 ($err,$code,$codeset1) = $self->_code($code);
293 3 50       31 return undef if ($err);
294              
295             } elsif (@args == 3) {
296 60         141 ($code,$codeset1,$codeset2) = @args;
297 60         141 ($err,$code) = $self->_code($code,$codeset1);
298 60 100       189 return undef if ($err);
299 48         108 ($err) = $self->_code('',$codeset2);
300 48 50       171 return undef if ($err);
301             }
302              
303 54         140 my $name = $self->code2name($code,$codeset1);
304 54         149 my $out = $self->name2code($name,$codeset2);
305 54         173 return $out;
306             }
307              
308             sub code2names {
309 3     3 1 208 my($self,@args) = @_;
310              
311 3 50       27 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         10 my $type = $$self{'type'};
317              
318 3         13 my ($err,$code,$codeset) = $self->_code(@args);
319 3 50 33     31 return undef if ($err || ! $code);
320              
321 3         13 my $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
322 3         8 my @name = @{ $Data{$type}{'id2names'}{$id} };
  3         15  
323 3         27 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 2196 my($self,@args) = @_;
335 47         81 my $retired = 0;
336 47 100 100     238 if (@args && lc($args[$#args]) eq 'retired') {
337 3         8 pop(@args);
338 3         15 $retired = 1;
339             }
340              
341 47 100       140 if (! $$self{'type'}) {
342 2 100       65 carp "ERROR: all_codes: no type set for Locale::Codes object\n" if ($$self{'err'});
343 2         33 return ();
344             }
345 45         112 my $type = $$self{'type'};
346              
347 45         984 my ($err,$tmp,$codeset) = $self->_code('',@args);
348 45 100       135 return () if ($err);
349              
350 42         65 my @codes = keys %{ $Data{$type}{'code2id'}{$codeset} };
  42         1078  
351 42 100       136 push(@codes,keys %{ $Retired{$type}{$codeset}{'code'} }) if ($retired);
  3         70  
352 42         3133 return (sort @codes);
353             }
354              
355             sub all_names {
356 26     26 1 55458 my($self,@args) = @_;
357 26         60 my $retired = 0;
358 26 100 100     155 if (@args && lc($args[$#args]) eq 'retired') {
359 3         19 pop(@args);
360 3         6 $retired = 1;
361             }
362              
363 26 100       93 if (! $$self{'type'}) {
364 2 100       78 carp "ERROR: all_names: no type set for Locale::Codes object\n" if ($$self{'err'});
365 2         34 return ();
366             }
367 24         57 my $type = $$self{'type'};
368              
369 24         80 my ($err,$tmp,$codeset) = $self->_code('',@args);
370 24 100       78 return () if ($err);
371              
372 21         127 my @codes = $self->all_codes($codeset);
373 21         61 my @names;
374              
375 21         53 foreach my $code (@codes) {
376 4165         4602 my($id,$i) = @{ $Data{$type}{'code2id'}{$codeset}{$code} };
  4165         8059  
377 4165         7641 my $name = $Data{$type}{'id2names'}{$id}[$i];
378 4165         6280 push(@names,$name);
379             }
380 21 100       113 if ($retired) {
381 3         10 foreach my $lc (keys %{ $Retired{$type}{$codeset}{'name'} }) {
  3         55  
382 156         342 my $name = $Retired{$type}{$codeset}{'name'}{$lc}[1];
383 156         218 push @names,$name;
384             }
385             }
386 21         2123 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 4250 my($self,$code,$new_name,$codeset) = @_;
401              
402 54 100       183 if (! $$self{'type'}) {
403 2 100       68 carp "ERROR: rename_code: no type set for Locale::Codes object\n" if ($$self{'err'});
404 2         47 return 0;
405             }
406 52         103 my $type = $$self{'type'};
407              
408             # Make sure $code/$codeset are both valid
409              
410 52         127 my($err,$c,$cs) = $self->_code($code,$codeset);
411 52 100       157 if ($err) {
412             carp "ERROR: rename_code: unknown code/codeset: $code [$codeset]\n"
413 32 100       2649 if ($$self{'err'});
414 32         1239 return 0;
415             }
416 20         53 ($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         65 my $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
430              
431 20 100       99 if (exists $Data{$type}{'alias2id'}{lc($new_name)}) {
432             # Existing name (case 1 and 2)
433              
434 11         31 my ($new_id,$i) = @{ $Data{$type}{'alias2id'}{lc($new_name)} };
  11         58  
435 11 100       58 if ($new_id != $id) {
436             # Case 1
437             carp "ERROR: rename_code: rename to an existing name not allowed\n"
438 8 100       526 if ($$self{'err'});
439 8         360 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         29 push @{ $Data{$type}{'id2names'}{$id} },$new_name;
  9         50  
451 9         20 my $i = $#{ $Data{$type}{'id2names'}{$id} };
  9         31  
452 9         36 $Data{$type}{'alias2id'}{lc($new_name)} = [ $id,$i ];
453 9         28 $Data{$type}{'code2id'}{$codeset}{$code}[1] = $i;
454             }
455              
456 12         74 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 4759 my($self,$code,$name,$codeset) = @_;
468              
469 62 100       193 if (! $$self{'type'}) {
470 2 100       69 carp "ERROR: add_code: no type set for Locale::Codes object\n" if ($$self{'err'});
471 2         87 return 0;
472             }
473 60         116 my $type = $$self{'type'};
474              
475             # Make sure that $codeset is valid.
476              
477 60         156 my($err,$c,$cs) = $self->_code($code,$codeset,1);
478 60 100       230 if ($err) {
479 5 100       266 carp "ERROR: add_code: unknown codeset: $codeset\n" if ($$self{'err'});
480 5         166 return 0;
481             }
482 55         145 ($code,$codeset) = ($c,$cs);
483              
484             # Check that $code is unused.
485              
486 55 100 100     318 if (exists $Data{$type}{'code2id'}{$codeset}{$code} ||
487             exists $Data{$type}{'codealias'}{$codeset}{$code}) {
488 8 100       598 carp "ERROR: add_code: code already in use as alias: $code\n" if ($$self{'err'});
489 8         304 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         111 my ($id,$i);
497 47 100       202 if (exists $Data{$type}{'alias2id'}{lc($name)}) {
498 14         35 ($id,$i) = @{ $Data{$type}{'alias2id'}{lc($name)} };
  14         54  
499 14 100       51 if (exists $Data{$type}{'id2code'}{$codeset}{$id}) {
500 5 100       292 carp "ERROR: add_code: name already in use: $name\n" if ($$self{'err'});
501 5         174 return 0;
502             }
503              
504             } else {
505 33         115 $id = $Data{$type}{'id'}++;
506 33         57 $i = 0;
507 33         118 $Data{$type}{'alias2id'}{lc($name)} = [ $id,$i ];
508 33         101 $Data{$type}{'id2names'}{$id} = [ $name ];
509             }
510              
511             # Add the new code
512              
513 42         151 $Data{$type}{'code2id'}{$codeset}{$code} = [ $id,$i ];
514 42         124 $Data{$type}{'id2code'}{$codeset}{$id} = $code;
515              
516 42         256 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 2604 my($self,$code,$codeset) = @_;
527              
528 34 100       128 if (! $$self{'type'}) {
529 2 100       92 carp "ERROR: delete_code: no type set for Locale::Codes object\n" if ($$self{'err'});
530 2         46 return 0;
531             }
532 32         65 my $type = $$self{'type'};
533              
534             # Make sure $code/$codeset are both valid
535              
536 32         95 my($err,$c,$cs) = $self->_code($code,$codeset);
537 32 100       128 if ($err) {
538             carp "ERROR: delete_code: Unknown code/codeset: $code [$codeset]\n"
539 8 100       550 if ($$self{'err'});
540 8         262 return 0;
541             }
542 24         87 ($code,$codeset) = ($c,$cs);
543              
544             # Delete active codes
545              
546 24 50       119 if (exists $Data{$type}{'code2id'}{$codeset}{$code}) {
547              
548 24         67 my $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
549 24         91 delete $Data{$type}{'code2id'}{$codeset}{$code};
550 24         62 delete $Data{$type}{'id2code'}{$codeset}{$id};
551              
552             # Delete any aliases that are linked to this code
553              
554 24         59 foreach my $alias (keys %{ $Data{$type}{'codealias'}{$codeset} }) {
  24         122  
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         51 my $inuse = 0;
563 24         45 foreach my $cs (keys %{ $Data{$type}{'id2code'} }) {
  24         107  
564 66 100       194 $inuse = 1, last if (exists $Data{$type}{'id2code'}{$cs}{$id});
565             }
566              
567 24 100       98 if (! $inuse) {
568 18         33 my @names = @{ $Data{$type}{'id2names'}{$id} };
  18         78  
569 18         67 delete $Data{$type}{'id2names'}{$id};
570              
571 18         50 foreach my $name (@names) {
572 18         127 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         191 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 3213 my($self,$name,$new_name) = @_;
596              
597 40 100       125 if (! $$self{'type'}) {
598 2 100       75 carp "ERROR: add_alias: no type set for Locale::Codes object\n" if ($$self{'err'});
599 2         46 return 0;
600             }
601 38         106 my $type = $$self{'type'};
602              
603             # Check that $name is used and $new_name is new.
604              
605 38         57 my($id);
606 38 100       175 if (exists $Data{$type}{'alias2id'}{lc($name)}) {
607 17         51 $id = $Data{$type}{'alias2id'}{lc($name)}[0];
608             } else {
609 21 100       1625 carp "ERROR: add_alias: name does not exist: $name\n" if ($$self{'err'});
610 21         794 return 0;
611             }
612              
613 17 100       49 if (exists $Data{$type}{'alias2id'}{lc($new_name)}) {
614 4 50       298 carp "ERROR: add_alias: alias already in use: $new_name\n" if ($$self{'err'});
615 4         157 return 0;
616             }
617              
618             # Add the new alias
619              
620 13         23 push @{ $Data{$type}{'id2names'}{$id} },$new_name;
  13         47  
621 13         23 my $i = $#{ $Data{$type}{'id2names'}{$id} };
  13         29  
622 13         185 $Data{$type}{'alias2id'}{lc($new_name)} = [ $id,$i ];
623              
624 13         80 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 4202 my($self,$name) = @_;
639              
640 39 100       131 if (! $$self{'type'}) {
641 2 100       71 carp "ERROR: delete_alias: no type set for Locale::Codes object\n" if ($$self{'err'});
642 2         43 return 0;
643             }
644 37         70 my $type = $$self{'type'};
645              
646             # Check that $name is used.
647              
648 37         76 my($id,$i);
649 37 100       159 if (exists $Data{$type}{'alias2id'}{lc($name)}) {
650 17         33 ($id,$i) = @{ $Data{$type}{'alias2id'}{lc($name)} };
  17         72  
651             } else {
652 20 100       1531 carp "ERROR: delete_alias: name does not exist: $name\n" if ($$self{'err'});
653 20         827 return 0;
654             }
655              
656 17         70 my $n = $#{ $Data{$type}{'id2names'}{$id} } + 1;
  17         94  
657 17 100       55 if ($n == 1) {
658             carp "ERROR: delete_alias: only one name defined (use delete_code instead)\n"
659 5 100       322 if ($$self{'err'});
660 5         173 return 0;
661             }
662              
663             # Delete the alias.
664              
665 12         18 splice (@{ $Data{$type}{'id2names'}{$id} },$i,1);
  12         42  
666 12         41 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         16 foreach my $codeset (keys %{ $Data{$type}{'code2id'} }) {
  12         55  
674 108         145 foreach my $code (keys %{ $Data{$type}{'code2id'}{$codeset} }) {
  108         3108  
675 27789         30892 my($jd,$j) = @{ $Data{$type}{'code2id'}{$codeset}{$code} };
  27789         50230  
676 27789 100 100     53127 next if ($jd ne $id ||
677             $j < $i);
678 12 100       52 if ($i == $j) {
679 6         44 $Data{$type}{'code2id'}{$codeset}{$code}[1] = 0;
680             } else {
681 6         21 $Data{$type}{'code2id'}{$codeset}{$code}[1]--;
682             }
683             }
684             }
685              
686 12         168 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 3570 my($self,$code,$new_code,$codeset) = @_;
698              
699 44 100       138 if (! $$self{'type'}) {
700 2 100       72 carp "ERROR: replace_code: no type set for Locale::Codes object\n" if ($$self{'err'});
701 2         49 return 0;
702             }
703 42         82 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         117 my($err,$c,$cs) = $self->_code($code,$codeset);
709 42 100       144 if ($err) {
710             carp "ERROR: replace_code: Unknown code/codeset: $code [$codeset]\n"
711 23 100       1703 if ($$self{'err'});
712 23         839 return 0;
713             }
714 19         39 ($code,$codeset) = ($c,$cs);
715              
716 19         48 ($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       95 if (exists $Data{$type}{'codealias'}{$codeset}{$new_code}) {
    100          
733             # Cases 1 and 2
734 8 100       58 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       314 if ($$self{'err'});
743 5         171 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       307 if ($$self{'err'});
750 5         163 return 0;
751             }
752              
753             # Cases 1 and 4
754              
755 9         25 $Data{$type}{'codealias'}{$codeset}{$code} = $new_code;
756              
757 9         24 my $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
758             $Data{$type}{'code2id'}{$codeset}{$new_code} =
759 9         29 $Data{$type}{'code2id'}{$codeset}{$code};
760 9         35 delete $Data{$type}{'code2id'}{$codeset}{$code};
761              
762 9         36 $Data{$type}{'id2code'}{$codeset}{$id} = $new_code;
763              
764 9         69 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 3830 my($self,$code,$new_code,$codeset) = @_;
775              
776 44 100       146 if (! $$self{'type'}) {
777 2 100       69 carp "ERROR: add_code_alias: no type set for Locale::Codes object\n" if ($$self{'err'});
778 2         47 return 0;
779             }
780 42         84 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         140 my($err,$c,$cs) = $self->_code($code,$codeset);
786 42 100       139 if ($err) {
787             carp "ERROR: add_code_alias: unknown code/codeset: $code [$codeset]\n"
788 23 100       1634 if ($$self{'err'});
789 23         871 return 0;
790             }
791 19         136 ($code,$codeset) = ($c,$cs);
792              
793 19         110 ($err,$new_code,$cs) = $self->_code($new_code,$codeset,1);
794              
795             # Check that $new_code does not exist.
796              
797 19 100 100     119 if (exists $Data{$type}{'code2id'}{$codeset}{$new_code} ||
798             exists $Data{$type}{'codealias'}{$codeset}{$new_code}) {
799 8 100       518 carp "ERROR: add_code_alias: code already in use: $new_code\n" if ($$self{'err'});
800 8         314 return 0;
801             }
802              
803             # Add the alias
804              
805 11         37 $Data{$type}{'codealias'}{$codeset}{$new_code} = $code;
806              
807 11         59 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 3035 my($self,$code,$codeset) = @_;
818              
819 36 100       152 if (! $$self{'type'}) {
820 2 100       70 carp "ERROR: delete_code_alias: no type set for Locale::Codes object\n" if ($$self{'err'});
821 2         42 return 0;
822             }
823 34         164 my $type = $$self{'type'};
824              
825             # Make sure $code/$codeset are both valid
826              
827 34         178 my($err,$c,$cs) = $self->_code($code,$codeset);
828 34 100       211 if ($err) {
829             carp "ERROR: delete_code_alias: unknown code/codeset: $code [$codeset]\n"
830 23 100       1766 if ($$self{'err'});
831 23         808 return 0;
832             }
833 11         23 ($code,$codeset) = ($c,$cs);
834              
835             # Check that $code exists in the codeset as an alias.
836              
837 11 100       39 if (! exists $Data{$type}{'codealias'}{$codeset}{$code}) {
838 5 100       345 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         18 delete $Data{$type}{'codealias'}{$codeset}{$code};
845              
846 6         35 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: