2 # Copyright (C) 2001 Canon Research Centre Europe (CRE).
3 # Copyright (C) 2002-2009 Neil Bowers
4 # Copyright (c) 2010-2010 Sullivan Beck
5 # This program is free software; you can redistribute it and/or modify it
6 # under the same terms as Perl itself.
14 #=======================================================================
15 # Public Global Variables
16 #=======================================================================
18 # This module is not called directly... %Data is filled in by the
21 use vars qw($VERSION %Data);
23 # $Data{ TYPE }{ code2id }{ CODESET } { CODE } = [ ID, I ]
24 # { id2code }{ CODESET } { ID } = CODE
25 # { id2names }{ ID } = [ NAME, NAME, ... ]
26 # { alias2id }{ NAME } = [ ID, I ]
27 # { id } = FIRST_UNUSED_ID
28 # { codealias }{ CODESET } { ALIAS } = CODE
32 #=======================================================================
34 # _code2name ( TYPE,CODE,CODESET )
36 #=======================================================================
39 my($type,$code,$codeset) = @_;
41 $code = $Data{$type}{'codealias'}{$codeset}{$code}
42 if (exists $Data{$type}{'codealias'}{$codeset}{$code});
44 if (exists $Data{$type}{'code2id'}{$codeset} &&
45 exists $Data{$type}{'code2id'}{$codeset}{$code}) {
46 my ($id,$i) = @{ $Data{$type}{'code2id'}{$codeset}{$code} };
47 my $name = $Data{$type}{'id2names'}{$id}[$i];
50 #---------------------------------------------------------------
52 #---------------------------------------------------------------
57 #=======================================================================
59 # _name2code ( TYPE,NAME,CODESET )
61 #=======================================================================
64 my($type,$name,$codeset) = @_;
65 $name = "" if (! $name);
68 if (exists $Data{$type}{'alias2id'}{$name}) {
69 my $id = $Data{$type}{'alias2id'}{$name}[0];
70 if (exists $Data{$type}{'id2code'}{$codeset}{$id}) {
71 return $Data{$type}{'id2code'}{$codeset}{$id};
75 #---------------------------------------------------------------
77 #---------------------------------------------------------------
81 #=======================================================================
83 # _code2code ( TYPE,CODE,CODESET )
85 #=======================================================================
88 my($type,$code,$inset,$outset) = @_;
90 my $name = _code2name($type,$code,$inset);
91 my $outcode = _name2code($type,$name,$outset);
95 #=======================================================================
97 # _all_codes ( TYPE,CODESET )
99 #=======================================================================
102 my($type,$codeset) = @_;
104 if (! exists $Data{$type}{'code2id'}{$codeset}) {
107 my @codes = keys %{ $Data{$type}{'code2id'}{$codeset} };
108 return (sort @codes);
111 #=======================================================================
113 # _all_names ( TYPE,CODESET )
115 #=======================================================================
118 my($type,$codeset) = @_;
120 my @codes = _all_codes($type,$codeset);
121 return () if (! @codes);
124 foreach my $code (@codes) {
125 my($id,$i) = @{ $Data{$type}{'code2id'}{$codeset}{$code} };
126 my $name = $Data{$type}{'id2names'}{$id}[$i];
129 return (sort @names);
132 #=======================================================================
134 # _rename ( TYPE,CODE,NAME,CODESET )
136 # Change the official name for a code. The original is retained
137 # as an alias, but the new name will be returned if you lookup the
140 #=======================================================================
143 my($type,$code,$new_name,$codeset,$nowarn) = @_;
146 carp "rename_$type(): unknown codeset\n" unless ($nowarn);
150 $code = $Data{$type}{'codealias'}{$codeset}{$code}
151 if (exists $Data{$type}{'codealias'}{$codeset}{$code});
153 # Check that $code exists in the codeset.
156 if (exists $Data{$type}{'code2id'}{$codeset}{$code}) {
157 $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
159 carp "rename_$type(): unknown code: $code\n" unless ($nowarn);
164 # 1. Renaming to a name which exists with a different ID
167 # 2. Renaming to a name which exists with the same ID
168 # Just change code2id (I value)
170 # 3. Renaming to a new name
172 # Change code2id (I value)
174 if (exists $Data{$type}{'alias2id'}{lc($new_name)}) {
175 # Existing name (case 1 and 2)
177 my ($new_id,$i) = @{ $Data{$type}{'alias2id'}{lc($new_name)} };
178 if ($new_id != $id) {
180 carp "rename_$type(): rename to an existing $type not allowed\n"
187 $Data{$type}{'code2id'}{$codeset}{$code}[1] = $i;
193 push @{ $Data{$type}{'id2names'}{$id} },$new_name;
194 my $i = $#{ $Data{$type}{'id2names'}{$id} };
195 $Data{$type}{'alias2id'}{lc($new_name)} = [ $id,$i ];
196 $Data{$type}{'code2id'}{$codeset}{$code}[1] = $i;
202 #=======================================================================
204 # _add_code ( TYPE,CODE,NAME,CODESET )
206 # Add a new code to the codeset. Both CODE and NAME must be
207 # unused in the code set.
209 #=======================================================================
212 my($type,$code,$name,$codeset,$nowarn) = @_;
215 carp "add_$type(): unknown codeset\n" unless ($nowarn);
219 # Check that $code is unused.
221 if (exists $Data{$type}{'code2id'}{$codeset}{$code} ||
222 exists $Data{$type}{'codealias'}{$codeset}{$code}) {
223 carp "add_$type(): code already in use: $code\n" unless ($nowarn);
227 # Check to see that $name is unused in this code set. If it is
228 # used (but not in this code set), we'll use that ID. Otherwise,
229 # we'll need to get the next available ID.
232 if (exists $Data{$type}{'alias2id'}{lc($name)}) {
233 ($id,$i) = @{ $Data{$type}{'alias2id'}{lc($name)} };
234 if (exists $Data{$type}{'id2code'}{$codeset}{$id}) {
235 carp "add_$type(): name already in use: $name\n" unless ($nowarn);
240 $id = $Data{$type}{'id'}++;
242 $Data{$type}{'alias2id'}{lc($name)} = [ $id,$i ];
243 $Data{$type}{'id2names'}{$id} = [ $name ];
248 $Data{$type}{'code2id'}{$codeset}{$code} = [ $id,$i ];
249 $Data{$type}{'id2code'}{$codeset}{$id} = $code;
254 #=======================================================================
256 # _delete_code ( TYPE,CODE,CODESET )
258 # Delete a code from the codeset.
260 #=======================================================================
263 my($type,$code,$codeset,$nowarn) = @_;
266 carp "delete_$type(): unknown codeset\n" unless ($nowarn);
270 $code = $Data{$type}{'codealias'}{$codeset}{$code}
271 if (exists $Data{$type}{'codealias'}{$codeset}{$code});
273 # Check that $code is valid.
275 if (! exists $Data{$type}{'code2id'}{$codeset}{$code}) {
276 carp "delete_$type(): code does not exist: $code\n" unless ($nowarn);
282 my $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
283 delete $Data{$type}{'code2id'}{$codeset}{$code};
284 delete $Data{$type}{'id2code'}{$codeset}{$id};
286 # Delete any aliases that are linked to this code
288 foreach my $alias (keys %{ $Data{$type}{'codealias'}{$codeset} }) {
289 next if ($Data{$type}{'codealias'}{$codeset}{$alias} ne $code);
290 delete $Data{$type}{'codealias'}{$codeset}{$alias};
293 # If this ID is not used in any other codeset, delete it completely.
295 foreach my $c (keys %{ $Data{$type}{'id2code'} }) {
296 return 1 if (exists $Data{$type}{'id2code'}{$c}{$id});
299 my @names = @{ $Data{$type}{'id2names'}{$id} };
300 delete $Data{$type}{'id2names'}{$id};
302 foreach my $name (@names) {
303 delete $Data{$type}{'alias2id'}{lc($name)};
309 #=======================================================================
311 # _add_alias ( TYPE,NAME,NEW_NAME )
313 # Add a new alias. NAME must exist, and NEW_NAME must be unused.
315 #=======================================================================
318 my($type,$name,$new_name,$nowarn) = @_;
320 # Check that $name is used and $new_name is new.
323 if (exists $Data{$type}{'alias2id'}{lc($name)}) {
324 $id = $Data{$type}{'alias2id'}{lc($name)}[0];
326 carp "add_${type}_alias(): name does not exist: $name\n" unless ($nowarn);
330 if (exists $Data{$type}{'alias2id'}{lc($new_name)}) {
331 carp "add_${type}_alias(): alias already in use: $new_name\n" unless ($nowarn);
337 push @{ $Data{$type}{'id2names'}{$id} },$new_name;
338 my $i = $#{ $Data{$type}{'id2names'}{$id} };
339 $Data{$type}{'alias2id'}{lc($new_name)} = [ $id,$i ];
344 #=======================================================================
346 # _delete_alias ( TYPE,NAME )
348 # This deletes a name from the list of names used by an element.
349 # NAME must be used, but must NOT be the only name in the list.
351 # Any id2name that references this name will be changed to
352 # refer to the first name in the list.
354 #=======================================================================
357 my($type,$name,$nowarn) = @_;
359 # Check that $name is used.
362 if (exists $Data{$type}{'alias2id'}{lc($name)}) {
363 ($id,$i) = @{ $Data{$type}{'alias2id'}{lc($name)} };
365 carp "delete_${type}_alias(): name does not exist: $name\n" unless ($nowarn);
369 my $n = $#{ $Data{$type}{'id2names'}{$id} };
371 carp "delete_${type}_alias(): only one name defined (use _delete_${type} instead)\n"
378 splice (@{ $Data{$type}{'id2names'}{$id} },$i,1);
379 delete $Data{$type}{'alias2id'}{lc($name)};
381 # Every element that refers to this ID:
384 # Decrement if I > $i
386 foreach my $codeset (keys %{ $Data{'code2id'} }) {
387 foreach my $code (keys %{ $Data{'code2id'}{$codeset} }) {
388 my($jd,$j) = @{ $Data{'code2id'}{$codeset}{$code} };
389 next if ($jd ne $id ||
392 $Data{'code2id'}{$codeset}{$code}[1] = 0;
394 $Data{'code2id'}{$codeset}{$code}[1]--;
402 #=======================================================================
404 # _rename_code ( TYPE,CODE,NEW_CODE,CODESET )
406 # Change the official code. The original is retained as an alias, but
407 # the new name will be returned if you lookup the code from name.
409 #=======================================================================
412 my($type,$code,$new_code,$codeset,$nowarn) = @_;
415 carp "rename_$type(): unknown codeset\n" unless ($nowarn);
419 $code = $Data{$type}{'codealias'}{$codeset}{$code}
420 if (exists $Data{$type}{'codealias'}{$codeset}{$code});
422 # Check that $code exists in the codeset.
424 if (! exists $Data{$type}{'code2id'}{$codeset}{$code}) {
425 carp "rename_$type(): unknown code: $code\n" unless ($nowarn);
430 # 1. Renaming code to an existing alias of this code:
431 # Make the alias real and the code an alias
433 # 2. Renaming code to some other existing alias:
436 # 3. Renaming code to some other code:
439 # 4. Renaming code to a new code:
440 # Make code into an alias
441 # Replace code with new_code.
443 if (exists $Data{$type}{'codealias'}{$codeset}{$new_code}) {
445 if ($Data{$type}{'codealias'}{$codeset}{$new_code} eq $code) {
448 delete $Data{$type}{'codealias'}{$codeset}{$new_code};
452 carp "rename_$type(): new code already in use: $new_code\n" unless ($nowarn);
456 } elsif (exists $Data{$type}{'code2id'}{$codeset}{$new_code}) {
458 carp "rename_$type(): new code already in use: $new_code\n" unless ($nowarn);
464 $Data{$type}{'codealias'}{$codeset}{$code} = $new_code;
466 my $id = $Data{$type}{'code2id'}{$codeset}{$code}[0];
467 $Data{$type}{'code2id'}{$codeset}{$new_code} = $Data{$type}{'code2id'}{$codeset}{$code};
468 delete $Data{$type}{'code2id'}{$codeset}{$code};
470 $Data{$type}{'id2code'}{$codeset}{$id} = $new_code;
475 #=======================================================================
477 # _add_code_alias ( TYPE,CODE,NEW_CODE,CODESET )
479 # Adds an alias for the code.
481 #=======================================================================
483 sub _add_code_alias {
484 my($type,$code,$new_code,$codeset,$nowarn) = @_;
487 carp "add_${type}_code_alias(): unknown codeset\n" unless ($nowarn);
491 $code = $Data{$type}{'codealias'}{$codeset}{$code}
492 if (exists $Data{$type}{'codealias'}{$codeset}{$code});
494 # Check that $code exists in the codeset and that $new_code
497 if (! exists $Data{$type}{'code2id'}{$codeset}{$code}) {
498 carp "add_${type}_code_alias(): unknown code: $code\n" unless ($nowarn);
502 if (exists $Data{$type}{'code2id'}{$codeset}{$new_code} ||
503 exists $Data{$type}{'codealias'}{$codeset}{$new_code}) {
504 carp "add_${type}_code_alias(): code already in use: $new_code\n" unless ($nowarn);
510 $Data{$type}{'codealias'}{$codeset}{$new_code} = $code;
515 #=======================================================================
517 # _delete_code_alias ( TYPE,CODE,CODESET )
519 # Deletes an alias for the code.
521 #=======================================================================
523 sub _delete_code_alias {
524 my($type,$code,$codeset,$nowarn) = @_;
527 carp "delete_${type}_code_alias(): unknown codeset\n" unless ($nowarn);
531 # Check that $code exists in the codeset as an alias.
533 if (! exists $Data{$type}{'codealias'}{$codeset}{$code}) {
534 carp "delete_${type}_code_alias(): no alias defined: $code\n" unless ($nowarn);
540 delete $Data{$type}{'codealias'}{$codeset}{$code};
545 #=======================================================================
547 # alias_code ( ALIAS => CODE [ , CODESET ] )
549 # Add an alias for an existing code. If the CODESET isn't specified,
550 # then we use the default (currently the alpha-2 codeset).
552 # Locale::Country::alias_code('uk' => 'gb');
554 #=======================================================================
558 # $nowarn = 1, pop if ($_[$#_] eq "nowarn");
561 # my $codeset = @_ > 0 ? shift : LOCALE_CODE_DEFAULT;
563 # return 0 if ($codeset !~ /^\d+$/);
565 # if ($codeset == LOCALE_CODE_ALPHA_2) {
566 # $codeset = "alpha2";
567 # $alias = lc($alias);
568 # } elsif ($codeset == LOCALE_CODE_ALPHA_3) {
569 # $codeset = "alpha3";
570 # $alias = lc($alias);
571 # } elsif ($codeset == LOCALE_CODE_FIPS) {
573 # $alias = uc($alias);
574 # } elsif ($codeset == LOCALE_CODE_NUMERIC) {
576 # return undef if ($alias =~ /\D/);
577 # $alias = sprintf("%.3d", $alias);
579 # carp "rename_country(): unknown codeset\n" unless ($nowarn);
583 # # Check that $code exists in the codeset.
586 # if (exists $Data{$type}{'code2id'}{$codeset}{$code}) {
587 # ($id,$i) = @{ $Data{$type}{'code2id'}{$codeset}{$code} };
589 # carp "alias_code: attempt to alias \"$alias\" to unknown country code \"$code\"\n"
595 # # The alias already exists.
599 # # Create a new entry in Code2CountryID
600 # # Replace the entiry in CountryID2Code
601 # # Regenerate %Codes
603 # if (exists $Data{$type}{'code2id'}{$codeset}{$alias}) {
604 # carp "alias_code: attempt to alias \"$alias\" which is already in use\n"
609 # $Data{$type}{'code2id'}{$codeset}{$alias} = [ $id, $i ];
610 # $Data{$type}{'id2names'}ID2Code{$codeset}{$id} = $alias;
612 # my @codes = keys %{ $Data{$type}{'code2id'}{$codeset} };
613 # $Locale::CountryCodes::Codes{$codeset} = [ sort @codes ];
621 # indent-tabs-mode: nil
622 # cperl-indent-level: 3
623 # cperl-continued-statement-offset: 2
624 # cperl-continued-brace-offset: 0
625 # cperl-brace-offset: 0
626 # cperl-brace-imaginary-offset: 0
627 # cperl-label-offset: -2