This commit is contained in:
2025-08-21 11:37:17 +02:00
parent 1b90ce41e6
commit 3029bf661a
4 changed files with 152 additions and 37 deletions

View File

@@ -18,7 +18,7 @@ for i, country in all_countries {
// --- Example: Find a specific country (e.g., Belgium) ---
println('\n--- Searching for Belgium ---')
found := false
mut found := false
for country in all_countries {
if country.iso == 'BE' {
println('Found Belgium: ${country.str()}')
@@ -41,4 +41,10 @@ for country in all_countries {
println('Found ${eu_countries.len} European countries.')
// Optionally print them or process further
// --- Example: Using the helper function ---
println('\n--- Using helper function to find Japan ---')
japan := countries.find_country_by_iso('JP') or {
println('Error finding Japan: ${err}')
return
}
println('Found Japan: ${japan.str()}')

View File

@@ -0,0 +1,77 @@
# Countries Data Module
This module provides access to country information data, including ISO codes, country names, continents, currencies, and more. It parses country data from a built-in dataset and makes it available through a simple API.
## Purpose
The countries module allows you to:
- Load all country data from an embedded dataset
- Search for specific countries by ISO code
- Filter countries by continent or other attributes
- Access detailed information about countries including names, codes, currencies, and more
## Data Source
The country data is sourced from GeoNames (http://www.geonames.org), containing information about countries including:
- ISO country codes (2-letter, 3-letter, and numeric)
- Country names and capitals
- Continent information
- Currency codes and names
- Phone country codes
- Postal code formats and regex patterns
- Languages spoken
- Neighboring countries
- FIPS codes and equivalent FIPS codes
## Example Usage
```v
import freeflowuniverse.herolib.data.countries
// Get all countries
mut all_countries := countries.get_all_countries()!
println('Total countries loaded: ${all_countries.len}')
// Find a specific country by ISO code
japan := countries.find_country_by_iso('JP')!
println('Found Japan: ${japan.str()}')
// Filter countries by continent
mut eu_countries := []countries.Country{}
for country in all_countries {
if country.continent == 'EU' {
eu_countries << country
}
}
println('Found ${eu_countries.len} European countries.')
```
## Country Structure
Each country entry contains the following fields:
- `iso`: ISO 2-letter country code (e.g., "BE" for Belgium)
- `iso3`: ISO 3-letter country code (e.g., "BEL" for Belgium)
- `iso_numeric`: ISO numeric country code (e.g., "056" for Belgium)
- `fips`: FIPS country code
- `country_name`: Full country name
- `capital`: Country capital city
- `area_sqkm`: Area in square kilometers
- `population`: Population count
- `continent`: Continent code (e.g., "EU" for Europe, "NA" for North America)
- `tld`: Top-level domain (e.g., ".be" for Belgium)
- `currency_code`: Currency code (e.g., "EUR" for Euro)
- `currency_name`: Full currency name
- `phone`: Phone country code
- `postal_format`: Postal code format
- `postal_regex`: Postal code validation regex
- `languages`: Languages spoken in the country
- `geonameid`: GeoNames ID
- `neighbours`: Neighboring countries (ISO codes separated by commas)
- `equiv_fips_code`: Equivalent FIPS code
## Available Functions
- `get_all_countries()`: Returns a list of all countries in the dataset
- `find_country_by_iso(iso_code string)`: Finds and returns a country by its 2-letter ISO code

View File

@@ -1,67 +1,87 @@
module countries
import os
import strings
// --- Embed the data file content at compile time ---
// The path is relative to the location of this `module.v` file.
const embedded_country_data = $embed_file('data/countryInfo.txt')
// The path is relative to the location of this `factory.v` file.
// get_all_countries parses the country data embedded in the executable.
// It returns a list of Country structs.
pub fn get_all_countries() ![]Country {
mut countries_list := []Country{}
embedded_country_data := $embed_file('data/countryInfo.txt', .zlib).to_string()
// --- Parse the embedded string ---
// Use strings.split to split the text into lines
lines := embedded_country_data.split_into_lines()
mut found_header := false
for line in lines {
// --- Skip empty lines and comments ---
if line == '' || line.trim_space().starts_with('#') {
trimmed_line := line.trim_space()
if trimmed_line == '' || trimmed_line.starts_with('#') {
continue
}
// --- Identify and skip the header ---
// Check if this line looks like the header (contains key identifiers)
if !found_header && line.contains('ISO') && line.contains('Country') && line.contains('CurrencyCode') {
if !found_header && trimmed_line.contains('ISO') && trimmed_line.contains('Country') && trimmed_line.contains('CurrencyCode') {
found_header = true
continue // Skip the header line itself
}
// --- Process data lines ---
// Split the line by tab character
fields := line.split('\t')
// println("Processing line:${countries_list.len} ${line} ")
// --- Process data lines ---
// Use strings.split to split the line by tab character
fields := line.split_by_space()
// Ensure we have the expected number of fields (header indicates 19)
if fields.len < 19 {
// Handle potential parsing errors or incomplete lines
// println('Warning: Skipping line with insufficient fields (found ${fields.len}): "${line}"')
continue
}
// --- Create Country struct instance ---
// Map fields by index based on the header structure
// Map fields by index based on the header structure.
// Handle potential out-of-bounds or missing data gracefully using `or {}`.
// The last field might sometimes be empty or missing in the data, handle it
iso_field := fields[0] or { '' }
iso3_field := fields[1] or { '' }
iso_numeric_field := fields[2] or { '' }
fips_field := fields[3] or { '' }
country_name_field := fields[4] or { '' }
capital_field := fields[5] or { '' }
area_sqkm_field := fields[6] or { '' }
population_field := fields[7] or { '' }
continent_field := fields[8] or { '' }
tld_field := fields[9] or { '' }
currency_code_field := fields[10] or { '' }
currency_name_field := fields[11] or { '' }
phone_field := fields[12] or { '' }
postal_format_field := fields[13] or { '' }
postal_regex_field := fields[14] or { '' }
languages_field := fields[15] or { '' }
geonameid_field := fields[16] or { '' }
neighbours_field := fields[17] or { '' }
equiv_fips_code_field := fields[18] or { '' }
country := Country{
iso: fields[0].trim_space()
iso3: fields[1].trim_space()
iso_numeric: fields[2].trim_space()
fips: fields[3].trim_space()
country_name: fields[4].trim_space()
capital: fields[5].trim_space()
area_sqkm: fields[6].trim_space()
population: fields[7].trim_space()
continent: fields[8].trim_space()
tld: fields[9].trim_space()
currency_code: fields[10].trim_space()
currency_name: fields[11].trim_space()
phone: fields[12].trim_space()
postal_format: fields[13].trim_space()
postal_regex: fields[14].trim_space()
languages: fields[15].trim_space()
geonameid: fields[16].trim_space()
neighbours: fields[17].trim_space()
equiv_fips_code: fields[18].trim_space() // Handle potential trailing empty fields or newlines
iso: iso_field.trim_space()
iso3: iso3_field.trim_space()
iso_numeric: iso_numeric_field.trim_space()
fips: fips_field.trim_space()
country_name: country_name_field.trim_space()
capital: capital_field.trim_space()
area_sqkm: area_sqkm_field.trim_space()
population: population_field.trim_space()
continent: continent_field.trim_space()
tld: tld_field.trim_space()
currency_code: currency_code_field.trim_space()
currency_name: currency_name_field.trim_space()
phone: phone_field.trim_space()
postal_format: postal_format_field.trim_space()
postal_regex: postal_regex_field.trim_space()
languages: languages_field.trim_space()
geonameid: geonameid_field.trim_space()
neighbours: neighbours_field.trim_space()
equiv_fips_code: equiv_fips_code_field.trim_space()
}
// --- Append to list ---
@@ -70,3 +90,14 @@ pub fn get_all_countries() ![]Country {
return countries_list
}
// Optional: Helper function to find a country by ISO code
pub fn find_country_by_iso(iso_code string) !Country {
countries := get_all_countries()!
for country in countries {
if country.iso == iso_code {
return country
}
}
return error('Country with ISO code "${iso_code}" not found')
}

View File

@@ -2,6 +2,7 @@ module countries
// Country represents a country entry from countryInfo.txt
pub struct Country {
pub:
iso string // ISO
iso3 string // ISO3
iso_numeric string // ISO-Numeric