File Coverage

blib/lib/Geography/Countries.pm
Criterion Covered Total %
statement 62 65 95.3
branch 14 18 77.7
condition 2 2 100.0
subroutine 18 21 85.7
pod 5 6 83.3
total 101 112 90.1


line stmt bran cond sub pod time code
1             package Geography::Countries;
2              
3 1     1   771 use 5.006;
  1         4  
  1         42  
4              
5 1     1   6 use strict;
  1         2  
  1         34  
6 1     1   5 use warnings;
  1         14  
  1         35  
7 1     1   4 no warnings 'syntax';
  1         2  
  1         42  
8              
9 1     1   4 use Exporter ();
  1         1  
  1         118  
10              
11             our @ISA = qw /Exporter/;
12             our @EXPORT = qw /country/;
13             our @EXPORT_OK = qw /code2 code3 numcode countries
14             CNT_I_CODE2 CNT_I_CODE3 CNT_I_NUMCODE CNT_I_COUNTRY
15             CNT_I_FLAG
16             CNT_F_REGULAR CNT_F_OLD CNT_F_REGION CNT_F_ANY/;
17             our %EXPORT_TAGS = (LISTS => [qw /code2 code3 numcode countries/],
18             INDICES => [qw /CNT_I_CODE2 CNT_I_CODE3 CNT_I_NUMCODE
19             CNT_I_COUNTRY CNT_I_FLAG/],
20             FLAGS => [qw /CNT_F_REGULAR CNT_F_OLD
21             CNT_F_REGION CNT_F_ANY/],);
22              
23             our $VERSION = '2009041301';
24              
25              
26 1     1   4 use constant CNT_I_CODE2 => 0;
  1         6  
  1         83  
27 1     1   4 use constant CNT_I_CODE3 => 1;
  1         2  
  1         55  
28 1     1   5 use constant CNT_I_NUMCODE => 2;
  1         1  
  1         41  
29 1     1   5 use constant CNT_I_COUNTRY => 3;
  1         1  
  1         47  
30 1     1   4 use constant CNT_I_FLAG => 4;
  1         1  
  1         48  
31              
32 1     1   4 use constant CNT_F_REGULAR => 0x01;
  1         2  
  1         39  
33 1     1   4 use constant CNT_F_OLD => 0x02;
  1         1  
  1         36  
34 1     1   4 use constant CNT_F_REGION => 0x04;
  1         1  
  1         64  
35 1     1   8 use constant CNT_F_ANY => CNT_F_REGULAR | CNT_F_OLD | CNT_F_REGION;
  1         2  
  1         1045  
36              
37             my (%info, @code2, @code3, @numcode, @countries);
38              
39             sub norm ($) {
40 761     761 0 801 my $query = shift;
41 761 50       1106 die "Illegal argument to norm\n" unless defined $query;
42 761 100       1637 return sprintf "%03d" => $query unless $query =~ /\D/;
43 757         910 $query = lc $query;
44 757         1111 $query =~ s/\s+//g;
45              
46 757         3793 $query;
47             }
48              
49 1     1   1331 binmode (DATA, ':encoding(iso-8859-1)') if $] >= 5.008;
  1         13  
  1         6  
50              
51             my $flag;
52             my %flags = (
53             Regular => CNT_F_REGULAR,
54             Old => CNT_F_OLD,
55             Region => CNT_F_REGION,
56             );
57             while () {
58             chomp;
59             last if $_ eq '__END__';
60             s/#.*//;
61             next unless /\S/;
62             if (/^%%\s*(\S.*\S)\s*%%$/) {
63             $flag = $flags {$1} or
64             die "Found illegal flag ``$1'' while parsing __DATA__\n";
65             next;
66             }
67             my $code2 = substr $_, 0, 2; $code2 = undef if $code2 =~ /\s/;
68             my $code3 = substr $_, 3, 3; $code3 = undef if $code3 =~ /\s/;
69             my $numcode = substr $_, 7, 3; $numcode = undef if $numcode =~ /\s/;
70             my $country = substr $_, 11;
71              
72             push @code2 => $code2 if defined $code2;
73             push @code3 => $code3 if defined $code3;
74             push @numcode => $numcode if defined $numcode;
75             push @countries => $country;
76              
77             my $info = [$code2, $code3, $numcode, $country, $flag];
78              
79             $info {norm $code2} = $info if defined $code2 ;
80             $info {norm $code3} = $info if defined $code3 ;
81             $info {$numcode} = $info if defined $numcode;
82              
83             $info {norm $country} = $info;
84             }
85              
86             @code2 = sort @code2;
87             @code3 = sort @code3;
88             @numcode = sort @numcode;
89             @countries = sort @countries;
90              
91 0     0 1 0 sub code2 {@code2}
92 1     1 1 159 sub code3 {@code3}
93 0     0 1 0 sub numcode {@numcode}
94 0     0 1 0 sub countries {@countries}
95              
96              
97             sub country ($;$) {
98 9     9 1 162 my $sub = (caller (0)) [3];
99              
100 9 50       25 die "No arguments for $sub.\n" unless @_;
101 9 100       26 die "Too many arguments for $sub.\n" unless @_ <= 2;
102              
103 8         17 my ($query, $flags) = @_;
104              
105 8 50       17 die "Undefined argument for $sub.\n" unless defined $query;
106              
107 8   100     27 $flags ||= CNT_F_REGULAR;
108              
109 8 100       29 die "Illegal second argument to $sub.\n" if $flags =~ /\D/;
110              
111 7 50       16 my $info = $info {norm $query} or return;
112              
113 7 100       25 return unless $info -> [CNT_I_FLAG] & $flags;
114              
115 6 100       29 wantarray ? @$info : $info -> [CNT_I_COUNTRY];
116              
117             }
118              
119             1;
120              
121             =pod
122              
123             =head1 NAME
124              
125             Geography::Countries - 2-letter, 3-letter, and numerical codes for countries.
126              
127             =head1 SYNOPSIS
128              
129             use Geography::Countries;
130              
131             $country = country 'DE'; # 'Germany'
132             @list = country 666; # ('PM', 'SPM', 666,
133             # 'Saint Pierre and Miquelon', 1)
134              
135             =head1 DESCRIPTION
136              
137             This module maps country names, and their 2-letter, 3-letter and
138             numerical codes, as defined by the ISO-3166 maintenance agency [1],
139             and defined by the UNSD.
140              
141             =head2 The C subroutine.
142              
143             This subroutine is exported by default. It takes a 2-letter, 3-letter or
144             numerical code, or a country name as argument. In scalar context, it will
145             return the country name, in list context, it will return a list consisting
146             of the 2-letter code, the 3-letter code, the numerical code, the country
147             name, and a flag, which is explained below. Note that not all countries
148             have all 3 codes; if a code is unknown, the undefined value is returned.
149              
150             There are 3 categories of countries. The largest category are the
151             current countries. Then there is a small set of countries that no
152             longer exist. The final set consists of areas consisting of multiple
153             countries, like I. No 2-letter or 3-letter codes are available
154             for the second two sets. (ISO 3166-3 [3] defines 4 letter codes for the
155             set of countries that no longer exist, but the author of this module
156             was unable to get her hands on that standard.) By default, C
157             only returns countries from the first set, but this can be changed
158             by giving C an optional second argument.
159              
160             The module optionally exports the constants C,
161             C, C and C. These constants can also
162             be important all at once by using the tag C<:FLAGS>. C is just
163             the binary or of the three other flags. The second argument of C
164             should be the binary or of a subset of the flags C,
165             C, and C - if no, or a false, second argument is
166             given, C is assumed. If C is set, regular
167             (current) countries will be returned; if C is set, old,
168             no longer existing, countries will be returned, while C
169             is used in case a region (not necessarely) a country might be returned.
170             If C is used in list context, the fifth returned element is
171             one of C, C and C, indicating
172             whether the result is a regular country, an old country, or a region.
173              
174             In list context, C returns a 5 element list. To avoid having
175             to remember which element is in which index, the constants C,
176             C, C, C and C
177             can be imported. Those constants contain the indices of the 2-letter code,
178             the 3-letter code, the numerical code, the country, and the flag explained
179             above, respectively. All index constants can be imported by using the
180             C<:INDICES> tag.
181              
182             =head2 The C, C, C and C routines.
183              
184             All known 2-letter codes, 3-letter codes, numerical codes and country
185             names can be returned by the routines C, C, C and
186             C. None of these methods is exported by default; all need to
187             be imported if one wants to use them. The tag C<:LISTS> imports them
188             all. In scalar context, the number of known codes or countries is returned.
189              
190             =head1 REFERENCES
191              
192             The 2-letter codes come from the ISO 3166-1:1997 standard [2]. ISO 3166
193             bases its list of country names on the list of names published by
194             the United Nations. This list is published by the Statistical Division
195             of the United Nations [4]. The UNSD uses 3-letter codes, and numerical
196             codes [5]. The information about old countries [6] and regions [7] also
197             comes from the United Nations.
198              
199             In a few cases, there was a conflict between the way how the United
200             Nations spelled a name, and how ISO 3166 spells it. In most cases,
201             is was word order (for instance whether I should
202             preceed the name, or come after the name. A few cases had minor
203             spelling variations. In all such cases, the method in which the UN
204             spelled the name was choosen; ISO 3166 claims to take the names from
205             the UN, so we consider the UN authoritative.
206              
207             =over 4
208              
209             =item [1]
210              
211             ISO Maintenance Agency (ISO 3166/MA)
212             I.
213              
214             =item [2]
215              
216             I,
217             I,
218             7 September 1999.
219              
220             =item [3]
221              
222             ISO 3166-3, I.
223             I.
224              
225             =item [4]
226              
227             United Nations, Statistics Division.
228             I.
229              
230             =item [5]
231              
232             I.
233             I,
234             26 August 1999.
235              
236             =item [6]
237              
238             I.
239             I,
240             26 August 1999.
241              
242             =item [7]
243              
244             I.
245             I,
246             26 August 1999.
247              
248             =back
249              
250             =head1 BUGS
251              
252             Looking up information using country names is far from perfect.
253             Except for case and the amount of white space, the exact name as it
254             appears on the list has to be given. I will not return anything,
255             but I will.
256              
257             =head1 DEVELOPMENT
258            
259             The current sources of this module are found on github,
260             L<< git://github.com/Abigail/geography--countries.git >>.
261            
262             =head1 AUTHOR
263            
264             Abigail L<< mailto:geography-countries@abigail.be >>.
265            
266             =head1 COPYRIGHT and LICENSE
267            
268             Copyright (C) 1999, 2009 by Abigail
269            
270             Permission is hereby granted, free of charge, to any person obtaining a
271             copy of this software and associated documentation files (the "Software"),
272             to deal in the Software without restriction, including without limitation
273             the rights to use, copy, modify, merge, publish, distribute, sublicense,
274             and/or sell copies of the Software, and to permit persons to whom the
275             Software is furnished to do so, subject to the following conditions:
276              
277             The above copyright notice and this permission notice shall be included
278             in all copies or substantial portions of the Software.
279              
280             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
281             IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
282             FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
283             THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
284             WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
285             OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
286             THE SOFTWARE.
287              
288             =cut
289              
290             __DATA__