1 /*
2 * Tlf - contest logging program for amateur radio operators
3 * Copyright (C) 2011, 2013 Thomas Beierlein <tb@forth-ev.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include <glib.h>
26 #include <math.h>
27
28 #include "dxcc.h"
29
30
31 GPtrArray *dxcc;
32 GPtrArray *prefix;
33 bool have_exact_matches;
34
35 prefix_data dummy_pfx = {
36 "No Prefix",
37 0,
38 0,
39 0,
40 INFINITY,
41 INFINITY,
42 NULL,
43 INFINITY,
44 false
45 };
46
47
prefix_free(gpointer data)48 void prefix_free(gpointer data) {
49 prefix_data *pfx_data = data;
50
51 g_free(pfx_data -> pfx);
52 g_free(pfx_data -> continent);
53 g_free(pfx_data);
54 }
55
56
prefix_init(void)57 void prefix_init(void) {
58 if (prefix) {
59 g_ptr_array_free(prefix, TRUE);
60 }
61 prefix = g_ptr_array_new_with_free_func(prefix_free);
62 }
63
64 /* return number of entries in prefix array */
prefix_count(void)65 unsigned int prefix_count(void) {
66 return prefix->len;
67 }
68
69 /* give pointer to prefix struct at 'index' */
prefix_by_index(unsigned int index)70 prefix_data *prefix_by_index(unsigned int index) {
71 if (index >= prefix_count())
72 return &dummy_pfx;
73
74 return (prefix_data *)g_ptr_array_index(prefix, index);
75 }
76
77 /* add a new prefix description */
prefix_add(char * pfxstr)78 void prefix_add(char *pfxstr) {
79 gchar *loc;
80 gint last_index = dxcc_count() - 1;
81 dxcc_data *last_dx = dxcc_by_index(last_index);
82 prefix_data *new_prefix = g_new(prefix_data, 1);
83
84 if (*pfxstr == '=') {
85 new_prefix -> exact = true;
86 have_exact_matches = true;
87 pfxstr++;
88 } else
89 new_prefix -> exact = false;
90
91 loc = strchr(pfxstr, '~');
92 if (loc != NULL) {
93 new_prefix -> timezone = atof(loc + 1);
94 *loc = '\0';
95 }
96 else
97 new_prefix -> timezone = INFINITY;
98
99 loc = strchr(pfxstr, '{');
100 if (loc != NULL) {
101 new_prefix -> continent = g_strdup(loc + 1);
102 *loc = '\0';
103 loc = strchr(new_prefix -> continent, '}');
104 if (loc != NULL)
105 *loc = '\0';
106 }
107 else
108 new_prefix -> continent = NULL;
109
110 loc = strchr(pfxstr, '<');
111 if (loc != NULL) {
112 new_prefix -> lat = atof(loc + 1);
113 *loc = '\0';
114 if ((loc = strchr(loc, '/')) != NULL)
115 new_prefix -> lon = atof(loc + 1);
116 else
117 new_prefix -> lon = INFINITY;
118 }
119 else
120 new_prefix -> lat = new_prefix -> lon = INFINITY;
121
122 loc = strchr(pfxstr, '[');
123 if (loc != NULL) {
124 new_prefix -> itu = atoi(loc + 1);
125 *loc = '\0';
126 } else
127 new_prefix -> itu = last_dx -> itu;
128
129 loc = strchr(pfxstr, '(');
130 if (loc != NULL) {
131 new_prefix -> cq = atoi(loc + 1);
132 *loc = '\0';
133 } else
134 new_prefix -> cq = last_dx -> cq;
135
136 new_prefix -> pfx = g_strdup(pfxstr);
137 new_prefix -> dxcc_index = last_index;
138
139 g_ptr_array_add(prefix, new_prefix);
140 }
141
142
143
dxcc_free(gpointer data)144 void dxcc_free(gpointer data) {
145 dxcc_data *dxcc = data;
146
147 g_free(dxcc -> countryname);
148 g_free(dxcc -> continent);
149 g_free(dxcc -> pfx);
150 g_free(dxcc);
151 }
152
dxcc_init(void)153 void dxcc_init(void) {
154 if (dxcc) {
155 g_ptr_array_free(dxcc, TRUE);
156 }
157 dxcc = g_ptr_array_new_with_free_func(dxcc_free);
158 }
159
160 /* return number of entries in dxcc array */
dxcc_count(void)161 unsigned int dxcc_count(void) {
162 return dxcc->len;
163 }
164
165 /* give pointer to dxcc_data struct at 'index' */
dxcc_by_index(unsigned int index)166 dxcc_data *dxcc_by_index(unsigned int index) {
167 if (index >= dxcc_count())
168 index = 0;
169
170 return (dxcc_data *)g_ptr_array_index(dxcc, index);
171 }
172
dxcc_add(char * dxcc_line)173 void dxcc_add(char *dxcc_line) {
174 gchar **split;
175 gint item;
176 dxcc_data *new_dxcc = g_new(dxcc_data, 1);
177
178 /* split up the line */
179 split = g_strsplit(dxcc_line, ":", 9);
180
181 if (g_strv_length(split) < 8) { /* wrong syntax, ignore line */
182 g_strfreev(split);
183 g_free(new_dxcc);
184 return;
185 }
186
187 for (item = 0; item < 8; item++)
188 g_strstrip(split[item]);
189
190 new_dxcc -> countryname = g_strdup(split[0]);
191 new_dxcc -> cq = atoi(split[1]);
192 new_dxcc -> itu = atoi(split[2]);
193 new_dxcc -> continent = g_strdup(split[3]);
194 new_dxcc -> lat = atof(split[4]);
195 new_dxcc -> lon = atof(split[5]);
196 new_dxcc -> timezone = atof(split[6]);
197 if (*split[7] == '*') {
198 new_dxcc -> pfx = g_strdup(split[7] + 1);
199 new_dxcc -> starred = true;
200 } else {
201 new_dxcc -> pfx = g_strdup(split[7]);
202 new_dxcc -> starred = false;
203 }
204
205 g_strfreev(split);
206
207 g_ptr_array_add(dxcc, new_dxcc);
208 }
209
210 /** load cty database from filename */
load_ctydata(char * filename)211 int load_ctydata(char *filename) {
212 FILE *fd;
213 char buf[181] = "";
214 char *loc;
215
216 if ((fd = fopen(filename, "r")) == NULL)
217 return -1;
218
219 dxcc_init();
220 prefix_init();
221
222 // set default for empty country
223 dxcc_add("Not Specified : --: --: --: -00.00: 00.00: 0.0: :");
224
225 while (fgets(buf, sizeof(buf), fd) != NULL) {
226
227 g_strchomp(buf); /* drop CR and/or NL and */
228 if (*buf == '\0') /* ignore empty lines */
229 continue;
230
231 if (buf[0] != ' ') { // data line
232
233 dxcc_add(buf);
234
235 } else { // prefix line
236 loc = strtok(buf, " ,;");
237 while (loc != NULL) {
238
239 prefix_add(loc);
240
241 loc = strtok(NULL, " ,;");
242 }
243 }
244 }
245 fclose(fd);
246 return 0;
247 }
248
249
250