This is my attempt to implement various ISO standards in Ada.
This is not the Ada Standard Library (which is defined by Ada Auth) but rather things like ISO 3166 (Country Codes), ISO 4217 (Currency Codes), or ISO 639 (Language Codes).
Current standards implemented:
Coming Soon:
- ISO.Languages (ISO 639)
With Alire
Be sure that you're using the latest community index:
alr index --update-all
To download and build:
alr get --build iso
To include it as a dependency in your Alire project:
alr with iso
If you don't use Alire, you can just download the ads
and adb
files under /src
and include them in your project.
You can also read the full API documentation which has been generated with ROBODoc.
This is a full lookup table for the ISO 3166-1 country records in Ada. In the future, I would like to include iso-3166-2 and iso-3166-3 in this. If that would be useful to you, then read the section below under "Contribute". Full API Here.
Provided is an enumerated data type called Country_Keys
comprised of C_
followed by a Country Code. That country key is stored in a Country
object:
type Country_Key is (
C_AF, -- Afghanistan
C_AL, -- Albania
C_DZ, -- Algeria
-- . . .
C_ZZ -- Undefined
);
-- The ISO_3166_1 country to be referenced.
type Country is tagged record
Key : Country_Key := C_ZZ;
end record;
There's also an array type with a positive index for this object:
type Country_List is array (Positive range <>) of Country;
The Country
object has the following member functions / methods:
function Name (This : Country) return String;
function Alpha2 (This : Country) return Alpha2_Code;
function Alpha3 (This : Country) return Alpha3_Code;
function Numeric (This : Country) return Numeric_Code;
function Country_Code (This : Country) return Ada.Locales.Country_Code;
Since these are member functions, you can simply access them via the dot-operator:
My_Country : Country := (C_US);
My_Name : String := My_Country.Name; -- "United States of America (The)"
Alpha2_Code
and Alpha3_Code
are subtypes of String
, and Numeric_Code
is a subtype of Natural
. Each are restricted to the only possible values defined by the standard and "ZZ"
, "ZZZ"
, and 0
respectively for an Undefined country:
subtype Alpha2_Code is String (1 .. 2)
with Dynamic_Predicate => Alpha2_Code in
"AF" | "AL" | "DZ" | ... | "ZZ";
subtype Alpha3_Code is String (1 .. 3)
with Dynamic_Predicate => Alpha3_Code in
"AFG" | "ALB" | "DZA" | ... | "ZZZ";
subtype Numeric_Code is Natural
with Dynamic_Predicate => Numeric_Code in
004 | 008 | 012 | ... | 0;
There are several functions that return this object, depending on what item you're using to look it up:
with ISO.Countries; use ISO.Countries;
with Ada.Locales;
declare
-- All of these will return the USA country.
USA : constant Country := From_Alpha2 ("US"); -- Country Code
AUS : constant Country := From_Alpha3 ("AUS"); -- Country Code3
BIH : constant Country := From_Numeric (070); -- Numeric
ATA : constant Country := From_Numeric ("010"); -- Numeric String
-- Get more information from Ada.Locales country code.
Local_Country : Country := From_Country_Code (Ada.Locales.Country¨);
begin
Assert (USA.Name = "United States of America (the)");
Assert (AUS.Name = "Australia");
Assert (BIH.Name = "Bosnia and Herzegovina");
Assert (ATA.Name = "Antarctica");
end;
There's also an array that can contain all of the countries. It must be initiated with the function Init_Countries
. The index is an item of Country_Key
:
with ISO.Countries; use ISO.Countries;
with Ada.Text_IO; use Ada.Text_IO;
declare
A : constant All_Countries := Init_Countries;
begin
Put_Line (A (C_US).Name);
for X of A loop
Put_Line (X.Name);
Put_Line (X.Alpha2);
end loop;
end;
This is a full lookup table for ISO 4217, both list one (current Currencies) and list three (previous currencies). Full API Here.
Provided is an enumerated data type called Currency_Keys
comprised of C_
followed by a Currency Code. That code key is stored in a Currency
object:
type Currency_Key is (
C_NLG, -- Netherlands Guilder
C_BMD, -- Bermudian Dollar
--- . . .
C_ZZZ -- Unknown
);
-- The ISO 4217 currency to be referenced.
type Currency is tagged record
Key : Currency_Key := C_ZZZ;
end record;
There's also an array type with a positive index for this object:
type Currency_List is array (Positive range <>) of Currency;
The Currency
object has the following member functions / methods:
function Name (This : Currency) return String;
function Code (This : Currency) return Alphabetic_Code;
function Numeric (This : Currency) return Numeric_Code;
function Unit (This : Currency) return Minor_Unit;
function Symbol (This : Currency) return Wide_Wide_String;
function Symbol (This : Currency) return String;
function Is_Fund (This : Currency) return Boolean;
function Is_Historic (This : Currency) return Boolean;
function Withdraw_Date (This : Currency) return String;
function Withdraw_Dates (This : Currency) return String;
function Historic_Names (This : Currency) return String;
function Historic_Numerics (This : Currency) return String;
function Historic_Entities (This : Currency) return String;
function Historic_Records (This : Currency) return String;
function Entities (This : Currency) return Countries.Country_List;
Since these are member functions, you can simply access them via the dot-operator:
My_Currency : Currency := (C_USD);
My_Name : String := My_Country.Name; -- "US Dollar"
Alphabetic_Code
is a subtype of String
, Numeric_Code
and Minor_Unit
are subtypes of Natural. Each are restricted to the only possible values defined by the standard and "ZZZ"
, and 0
respectively for an Undefined country:
subtype Alphabetic_Code is String (1 .. 3)
with Dynamic_Predicate => Alphabetic_Code in
"NLG" | "BMD" | "VES" | ... | "ZZZ";
subtype Numeric_Code is Natural
with Dynamic_Predicate => Numeric_Code in
528 | 060 | 928 | ... | 0;
subtype Minor_Unit is Natural range 0 .. 4;
There are several functions that return this object, depending on what item you're using to look it up:
with ISO.Currencies; use ISO.Currencies;
with ISO.Countries;
declare
-- All of these will return the USA country.
USD : constant Currency := From_Code ("USD"); -- Currency Code
AUD : constant Currency := From_Numeric (036); -- Numeric Code
GBP : constant Currency := From_Numeric ("826"); -- Numeric String
begin
Assert (USD.Name = "US Dollar");
Assert (AUD.Name = "Australian Dollar");
Assert (GBP.Name = "Pound Sterling");
end;
You can retrieve every currency associated with a country using the From_Countries
function:
with ISO.Currencies; use ISO.Currencies;
with ISO.Countries;
SLV : constant Countries.Country := (C_SV); -- El Salvador
My_Currencies : constant Currency_List := From_Country(SLV); -- This returns both USD and SVC
There's also an array that can contain all of the currencies. It must be initiated with the function Init_Currencies
. The index is an item of Currency_Key
:
with ISO.Currencies; use ISO.Currencies;
with Ada.Text_IO; use Ada.Text_IO;
declare
A : constant All_Currencies := Init_Currencies;
begin
Put_Line (A (C_USD).Name);
for X of A loop
Put_Line (X.Name);
Put_Line (X.Code);
end loop;
end;
You can retrieve the symbol for each currency by calling the Symbol
function. If a symbol is known, it will return that symbol either as a string or wide_wide_string; if it's unknown, then it will return the universal currency symbol, ¤
:
with ISO.Currencies; use ISO.Currencies;
with Ada.Text_IO; use Ada.Text_IO;
declare
Value : Natural := 1337;
My_Currency : Currency := (C_USD); -- This is retrieved at some point.
begin
Put_Line ("The price is: " & My_Currency.Symbol & Value'Image);
end;
You can also retrieve historic countries by country code, but not by numeric. There are several functions to reference the historic information, usually as a semi-colon separated list. If I even get access to ISO 3166-2 and ISO 3166-3, I can handle these lists more gracefully.
The source files are currently being generated by another app written in Ada, but you don't need to run it in order to use this library, as I've already generated it.
If you want to generate the source files yourself, this is how:
- Consolidating the reference files
- For Countries:
- Visit the Country Code Search
- Be sure to set the page length to 300 to catch everything.
- Paste the table into a CSV
- REMOVE the French Short Name, column B.
- Verify the CSV Has the following headers in this exact order:
English short name,Alpha-2 code,Alpha-3 code,Numeric
- Save the CSV in the
generator/files
folder ascountries.csv
.
- For Currencies:
- Visit the ISO 4217 Standards Website
- Download the ISO standard in XML format. Specifically
list-one.xml
andlist-three.xml
- Rename
list-one.xml
ascurrencies.xml
- Rename
list-three.xml
ascurrencies-historic.xml
- Rename
- Save these two renamed xml files in
generator/files
- If you have an update for currency symbols, I am manually maintaining this in
currencies-symbols.csv
. So just edit that file.
- NOTE: Ensure that country codes have already been downloaded. The generator relies on them.
- For Countries:
- Build the generate app
cd generate
alr build
- Run the generate app
bin/generate
- The source files will be stored in the
generate/output
directory.
- Copy the source files to
ada_iso/src
(notgenerate/src
!) folder.
- Country Codes:
- Currency Codes:
- Currency Symbols:
If someone would like to give me 300 CHF (however much that is in USD) every time a new version of the Country Codes Collection is made available, I'll be happy to start using XML dumps like in the iso4217 library.
If the Country Codes Collection contains iso-3166-2 and iso-3166-3, I can start including those to build a more complete list. NOTE: I probably won't be able to share the XML files if this happens, but I can still provide the generator once written.