]> git.ipfire.org Git - people/ms/libloc.git/blob - src/country.c
Add a dictionary with countries to the database
[people/ms/libloc.git] / src / country.c
1 /*
2 libloc - A library to determine the location of someone on the Internet
3
4 Copyright (C) 2019 IPFire Development Team <info@ipfire.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15 */
16
17 #include <errno.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include <loc/libloc.h>
22 #include <loc/country.h>
23 #include <loc/private.h>
24
25 struct loc_country {
26 struct loc_ctx* ctx;
27 int refcount;
28
29 char* code;
30 char* continent_code;
31
32 char* name;
33 };
34
35 LOC_EXPORT int loc_country_new(struct loc_ctx* ctx, struct loc_country** country, const char* country_code) {
36 struct loc_country* c = calloc(1, sizeof(*c));
37 if (!c)
38 return -ENOMEM;
39
40 c->ctx = loc_ref(ctx);
41 c->refcount = 1;
42
43 c->code = strdup(country_code);
44
45 DEBUG(c->ctx, "Country %s allocated at %p\n", c->code, c);
46 *country = c;
47
48 return 0;
49 }
50
51 LOC_EXPORT struct loc_country* loc_country_ref(struct loc_country* country) {
52 country->refcount++;
53
54 return country;
55 }
56
57 static void loc_country_free(struct loc_country* country) {
58 DEBUG(country->ctx, "Releasing country %s %p\n", country->code, country);
59
60 if (country->code)
61 free(country->code);
62
63 if (country->continent_code)
64 free(country->continent_code);
65
66 if (country->name)
67 free(country->name);
68
69 loc_unref(country->ctx);
70 free(country);
71 }
72
73 LOC_EXPORT struct loc_country* loc_country_unref(struct loc_country* country) {
74 if (--country->refcount > 0)
75 return NULL;
76
77 loc_country_free(country);
78
79 return NULL;
80 }
81
82 LOC_EXPORT const char* loc_country_get_code(struct loc_country* country) {
83 return country->code;
84 }
85
86 LOC_EXPORT const char* loc_country_get_continent_code(struct loc_country* country) {
87 return country->continent_code;
88 }
89
90 LOC_EXPORT int loc_country_set_continent_code(struct loc_country* country, const char* continent_code) {
91 // XXX validate input
92
93 // Free previous value
94 if (country->continent_code)
95 free(country->continent_code);
96
97 country->continent_code = strdup(continent_code);
98
99 return 0;
100 }
101
102 LOC_EXPORT const char* loc_country_get_name(struct loc_country* country) {
103 return country->name;
104 }
105
106 LOC_EXPORT int loc_country_set_name(struct loc_country* country, const char* name) {
107 if (country->name)
108 free(country->name);
109
110 if (name)
111 country->name = strdup(name);
112
113 return 0;
114 }
115
116 int loc_country_cmp(struct loc_country* country1, struct loc_country* country2) {
117 return strcmp(country1->code, country2->code);
118 }
119
120 int loc_country_new_from_database_v0(struct loc_ctx* ctx, struct loc_stringpool* pool,
121 struct loc_country** country, const struct loc_database_country_v0* dbobj) {
122 char buffer[3];
123
124 // Read country code
125 loc_country_copy_code(buffer, dbobj->code);
126
127 // Create a new country object
128 int r = loc_country_new(ctx, country, buffer);
129 if (r)
130 return r;
131
132 // Continent Code
133 loc_country_copy_code(buffer, dbobj->continent_code);
134
135 r = loc_country_set_continent_code(*country, buffer);
136 if (r)
137 goto FAIL;
138
139 // Set name
140 #if 0
141 // XXX Reading from the stringpool makes test-country.c fail
142 const char* name = loc_stringpool_get(pool, be32toh(dbobj->name));
143 if (name) {
144 r = loc_country_set_name(*country, name);
145 if (r)
146 goto FAIL;
147 }
148 #endif
149
150 return 0;
151
152 FAIL:
153 loc_country_unref(*country);
154 return r;
155 }
156
157 int loc_country_to_database_v0(struct loc_country* country,
158 struct loc_stringpool* pool, struct loc_database_country_v0* dbobj) {
159 // Add country code
160 for (unsigned int i = 0; i < 2; i++) {
161 dbobj->code[i] = country->code[i] ? country->code[i] : '\0';
162 }
163
164 // Add continent code
165 for (unsigned int i = 0; i < 2; i++) {
166 dbobj->continent_code[i] = country->continent_code[i] ? country->continent_code[i] : '\0';
167 }
168
169 // Save the name string in the string pool
170 off_t name = loc_stringpool_add(pool, country->name ? country->name : "");
171 dbobj->name = htobe32(name);
172
173 return 0;
174 }