]> git.ipfire.org Git - people/ms/libloc.git/blob - src/country.c
country: Include compat.h to build on other arches
[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/compat.h>
23 #include <loc/country.h>
24 #include <loc/private.h>
25
26 struct loc_country {
27 struct loc_ctx* ctx;
28 int refcount;
29
30 char* code;
31 char* continent_code;
32
33 char* name;
34 };
35
36 LOC_EXPORT int loc_country_new(struct loc_ctx* ctx, struct loc_country** country, const char* country_code) {
37 struct loc_country* c = calloc(1, sizeof(*c));
38 if (!c)
39 return -ENOMEM;
40
41 c->ctx = loc_ref(ctx);
42 c->refcount = 1;
43
44 c->code = strdup(country_code);
45
46 DEBUG(c->ctx, "Country %s allocated at %p\n", c->code, c);
47 *country = c;
48
49 return 0;
50 }
51
52 LOC_EXPORT struct loc_country* loc_country_ref(struct loc_country* country) {
53 country->refcount++;
54
55 return country;
56 }
57
58 static void loc_country_free(struct loc_country* country) {
59 DEBUG(country->ctx, "Releasing country %s %p\n", country->code, country);
60
61 if (country->code)
62 free(country->code);
63
64 if (country->continent_code)
65 free(country->continent_code);
66
67 if (country->name)
68 free(country->name);
69
70 loc_unref(country->ctx);
71 free(country);
72 }
73
74 LOC_EXPORT struct loc_country* loc_country_unref(struct loc_country* country) {
75 if (--country->refcount > 0)
76 return NULL;
77
78 loc_country_free(country);
79
80 return NULL;
81 }
82
83 LOC_EXPORT const char* loc_country_get_code(struct loc_country* country) {
84 return country->code;
85 }
86
87 LOC_EXPORT const char* loc_country_get_continent_code(struct loc_country* country) {
88 return country->continent_code;
89 }
90
91 LOC_EXPORT int loc_country_set_continent_code(struct loc_country* country, const char* continent_code) {
92 // XXX validate input
93
94 // Free previous value
95 if (country->continent_code)
96 free(country->continent_code);
97
98 country->continent_code = strdup(continent_code);
99
100 return 0;
101 }
102
103 LOC_EXPORT const char* loc_country_get_name(struct loc_country* country) {
104 return country->name;
105 }
106
107 LOC_EXPORT int loc_country_set_name(struct loc_country* country, const char* name) {
108 if (country->name)
109 free(country->name);
110
111 if (name)
112 country->name = strdup(name);
113
114 return 0;
115 }
116
117 LOC_EXPORT int loc_country_cmp(struct loc_country* country1, struct loc_country* country2) {
118 return strcmp(country1->code, country2->code);
119 }
120
121 int loc_country_new_from_database_v0(struct loc_ctx* ctx, struct loc_stringpool* pool,
122 struct loc_country** country, const struct loc_database_country_v0* dbobj) {
123 char buffer[3];
124
125 // Read country code
126 loc_country_code_copy(buffer, dbobj->code);
127
128 // Create a new country object
129 int r = loc_country_new(ctx, country, buffer);
130 if (r)
131 return r;
132
133 // Continent Code
134 loc_country_code_copy(buffer, dbobj->continent_code);
135
136 r = loc_country_set_continent_code(*country, buffer);
137 if (r)
138 goto FAIL;
139
140 // Set name
141 const char* name = loc_stringpool_get(pool, be32toh(dbobj->name));
142 if (name) {
143 r = loc_country_set_name(*country, name);
144 if (r)
145 goto FAIL;
146 }
147
148 return 0;
149
150 FAIL:
151 loc_country_unref(*country);
152 return r;
153 }
154
155 int loc_country_to_database_v0(struct loc_country* country,
156 struct loc_stringpool* pool, struct loc_database_country_v0* dbobj) {
157 // Add country code
158 for (unsigned int i = 0; i < 2; i++) {
159 dbobj->code[i] = country->code[i] ? country->code[i] : '\0';
160 }
161
162 // Add continent code
163 if (country->continent_code) {
164 for (unsigned int i = 0; i < 2; i++) {
165 dbobj->continent_code[i] = country->continent_code[i] ? country->continent_code[i] : '\0';
166 }
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 }