File Coverage

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


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