]> git.ipfire.org Git - people/ms/libloc.git/blob - src/country.c
6e9bfaaa98a8bdf63694a30f63eda33483793ddd
[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 const char* name = loc_stringpool_get(pool, be32toh(dbobj->name));
141 if (name) {
142 r = loc_country_set_name(*country, name);
143 if (r)
144 goto FAIL;
145 }
146
147 return 0;
148
149 FAIL:
150 loc_country_unref(*country);
151 return r;
152 }
153
154 int loc_country_to_database_v0(struct loc_country* country,
155 struct loc_stringpool* pool, struct loc_database_country_v0* dbobj) {
156 // Add country code
157 for (unsigned int i = 0; i < 2; i++) {
158 dbobj->code[i] = country->code[i] ? country->code[i] : '\0';
159 }
160
161 // Add continent code
162 for (unsigned int i = 0; i < 2; i++) {
163 dbobj->continent_code[i] = country->continent_code[i] ? country->continent_code[i] : '\0';
164 }
165
166 // Save the name string in the string pool
167 off_t name = loc_stringpool_add(pool, country->name ? country->name : "");
168 dbobj->name = htobe32(name);
169
170 return 0;
171 }