-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Country class to query country information and Region class to…
… lookup the ISO 3166-2 subdivision code for country code and region name
- Loading branch information
1 parent
85a0a11
commit 4c9b230
Showing
4 changed files
with
345 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
package ip2location | ||
|
||
import ( | ||
"encoding/csv" | ||
"errors" | ||
"os" | ||
) | ||
|
||
// The CountryInfoRecord struct stores all of the available | ||
// country info found in the country information CSV file. | ||
type CountryInfoRecord struct { | ||
Country_code string | ||
Country_name string | ||
Country_alpha3_code string | ||
Country_numeric_code string | ||
Capital string | ||
Country_demonym string | ||
Total_area string | ||
Population string | ||
Idd_code string | ||
Currency_code string | ||
Currency_name string | ||
Currency_symbol string | ||
Lang_code string | ||
Lang_name string | ||
Cctld string | ||
} | ||
|
||
// The CI struct is the main object used to read the country information CSV. | ||
type CI struct { | ||
resultsArr []CountryInfoRecord | ||
resultsMap map[string]CountryInfoRecord | ||
} | ||
|
||
// OpenCountryInfo initializes with the path to the country information CSV file. | ||
func OpenCountryInfo(csvFile string) (*CI, error) { | ||
var ci = &CI{} | ||
|
||
_, err := os.Stat(csvFile) | ||
if os.IsNotExist(err) { | ||
return nil, errors.New("The CSV file '" + csvFile + "' is not found.") | ||
} | ||
|
||
f, err := os.Open(csvFile) | ||
if err != nil { | ||
return nil, errors.New("Unable to read '" + csvFile + "'.") | ||
} | ||
|
||
defer f.Close() | ||
|
||
csvReader := csv.NewReader(f) | ||
data, err := csvReader.ReadAll() | ||
if err != nil { | ||
return nil, errors.New("Unable to read '" + csvFile + "'.") | ||
} | ||
|
||
ci.resultsMap = make(map[string]CountryInfoRecord) | ||
var headerArr []string | ||
|
||
for i, line := range data { | ||
if i == 0 { // headers | ||
for _, field := range line { | ||
headerArr = append(headerArr, field) | ||
} | ||
} else { | ||
var rec CountryInfoRecord | ||
for j, field := range line { | ||
switch headerArr[j] { | ||
case "country_code": | ||
rec.Country_code = field | ||
case "country_name": | ||
rec.Country_name = field | ||
case "country_alpha3_code": | ||
rec.Country_alpha3_code = field | ||
case "country_numeric_code": | ||
rec.Country_numeric_code = field | ||
case "capital": | ||
rec.Capital = field | ||
case "country_demonym": | ||
rec.Country_demonym = field | ||
case "total_area": | ||
rec.Total_area = field | ||
case "population": | ||
rec.Population = field | ||
case "idd_code": | ||
rec.Idd_code = field | ||
case "currency_code": | ||
rec.Currency_code = field | ||
case "currency_name": | ||
rec.Currency_name = field | ||
case "currency_symbol": | ||
rec.Currency_symbol = field | ||
case "lang_code": | ||
rec.Lang_code = field | ||
case "lang_name": | ||
rec.Lang_name = field | ||
case "cctld": | ||
rec.Cctld = field | ||
} | ||
} | ||
if rec.Country_code == "" { | ||
return nil, errors.New("Invalid country information CSV file.") | ||
} | ||
ci.resultsArr = append(ci.resultsArr, rec) | ||
ci.resultsMap[rec.Country_code] = rec | ||
} | ||
} | ||
return ci, nil | ||
} | ||
|
||
// GetCountryInfo returns the country information for the specified country or all countries if not specified | ||
func (c *CI) GetCountryInfo(countryCode ...string) ([]CountryInfoRecord, error) { | ||
if len(c.resultsArr) == 0 { | ||
return nil, errors.New("No record available.") | ||
} | ||
|
||
if len(countryCode) == 1 { | ||
cc := countryCode[0] | ||
if rec, ok := c.resultsMap[cc]; ok { | ||
var x []CountryInfoRecord | ||
x = append(x, rec) | ||
return x, nil // return record | ||
} else { | ||
return nil, errors.New("No record found.") | ||
} | ||
} else { | ||
return c.resultsArr, nil // return all countries | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package ip2location | ||
|
||
import ( | ||
"encoding/csv" | ||
"errors" | ||
"os" | ||
"strings" | ||
) | ||
|
||
// The RegionInfoRecord struct stores all of the available | ||
// region info found in the region information CSV file. | ||
type RegionInfoRecord struct { | ||
Country_code string | ||
Name string | ||
Code string | ||
} | ||
|
||
// The RI struct is the main object used to read the region information CSV. | ||
type RI struct { | ||
resultsMap map[string][]RegionInfoRecord | ||
} | ||
|
||
// OpenRegionInfo initializes with the path to the region information CSV file. | ||
func OpenRegionInfo(csvFile string) (*RI, error) { | ||
var ri = &RI{} | ||
|
||
_, err := os.Stat(csvFile) | ||
if os.IsNotExist(err) { | ||
return nil, errors.New("The CSV file '" + csvFile + "' is not found.") | ||
} | ||
|
||
f, err := os.Open(csvFile) | ||
if err != nil { | ||
return nil, errors.New("Unable to read '" + csvFile + "'.") | ||
} | ||
|
||
defer f.Close() | ||
|
||
csvReader := csv.NewReader(f) | ||
data, err := csvReader.ReadAll() | ||
if err != nil { | ||
return nil, errors.New("Unable to read '" + csvFile + "'.") | ||
} | ||
|
||
ri.resultsMap = make(map[string][]RegionInfoRecord) | ||
var headerArr []string | ||
var resultsArr []RegionInfoRecord | ||
|
||
for i, line := range data { | ||
if i == 0 { // headers | ||
for _, field := range line { | ||
headerArr = append(headerArr, field) | ||
} | ||
} else { | ||
var rec RegionInfoRecord | ||
for j, field := range line { | ||
switch headerArr[j] { | ||
case "country_code": | ||
rec.Country_code = field | ||
case "subdivision_name": | ||
rec.Name = field | ||
case "code": | ||
rec.Code = field | ||
} | ||
} | ||
if rec.Name == "" { | ||
return nil, errors.New("Invalid region information CSV file.") | ||
} | ||
resultsArr = append(resultsArr, rec) | ||
} | ||
} | ||
for _, elem := range resultsArr { | ||
if _, ok := ri.resultsMap[elem.Country_code]; !ok { | ||
var arr []RegionInfoRecord | ||
ri.resultsMap[elem.Country_code] = arr | ||
} | ||
ri.resultsMap[elem.Country_code] = append(ri.resultsMap[elem.Country_code], elem) | ||
} | ||
return ri, nil | ||
} | ||
|
||
// GetRegionCode returns the region code for the specified country and region name | ||
func (r *RI) GetRegionCode(countryCode string, regionName string) (string, error) { | ||
if len(r.resultsMap) == 0 { | ||
return "", errors.New("No record available.") | ||
} | ||
|
||
if arr, ok := r.resultsMap[countryCode]; ok { | ||
for _, elem := range arr { | ||
if strings.ToUpper(elem.Name) == strings.ToUpper(regionName) { | ||
return elem.Code, nil | ||
} | ||
} | ||
} | ||
return "", errors.New("No record found.") | ||
} |