Add preliminary contest country file support

pull/2/head
Stelios Bounanos 2008-12-10 22:48:53 +00:00
rodzic eef48e7b68
commit f7fee0bfbd
3 zmienionych plików z 204 dodań i 0 usunięć

Wyświetl plik

@ -162,6 +162,7 @@ fldigi_SOURCES += \
include/cw.h \
include/debug.h \
include/digiscope.h \
include/dxcc.h \
include/thor.h \
include/thorvaricode.h \
include/dominoex.h \
@ -287,6 +288,7 @@ fldigi_SOURCES += \
misc/ascii.cxx \
misc/configuration.cxx \
misc/debug.cxx \
misc/dxcc.cxx \
misc/flstring.c \
misc/icons.cxx \
misc/log.cxx \

20
src/include/dxcc.h 100644
Wyświetl plik

@ -0,0 +1,20 @@
#ifndef DXCC_H_
#define DXCC_H_
struct dxcc {
const char* country;
int cq_zone;
int itu_zone;
char continent[3];
float latitude;
float longitude;
float gmt_offset;
dxcc(const char* cn = "", int cq = 0, int itu = 0, const char* ct = "",
float lat = 0.0f, float lon = 0.0f, float tz = 0.0f);
};
bool dxcc_open(const char* filename);
void dxcc_close(void);
const dxcc* dxcc_lookup(const char* callsign);
#endif // DXCC_H_

182
src/misc/dxcc.cxx 100644
Wyświetl plik

@ -0,0 +1,182 @@
#include <config.h>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <string>
#include <list>
#include <map>
#include <algorithm>
#include "dxcc.h"
#include "debug.h"
using namespace std;
dxcc::dxcc(const char* cn, int cq, int itu, const char* ct, float lat, float lon, float tz)
: country(cn), cq_zone(cq), itu_zone(itu), latitude(lat), longitude(lon), gmt_offset(tz)
{
if (*ct) {
continent[0] = ct[0];
continent[1] = ct[1];
}
continent[2] = '\0';
}
typedef map<string, dxcc*> dxcc_map;
static dxcc_map* cmap = 0;
static list<string>* cnames = 0;
static void add_prefix(string& prefix, dxcc* entry);
bool dxcc_open(const char* filename)
{
dxcc_close();
ifstream in(filename);
if (!in) {
LOG_WARN("Could not read contest country file \"%s\"", filename);
return false;
}
cmap = new dxcc_map;
cnames = new list<string>;
dxcc* entry;
string record;
unsigned nrec = 0;
while (getline(in, record, ';')) {
istringstream is(record);
entry = new dxcc;
nrec++;
// read country name
cnames->resize(cnames->size() + 1);
getline(is, cnames->back(), ':');
entry->country = cnames->back().c_str();
// cq zone
(is >> entry->cq_zone).ignore();
// itu zone
(is >> entry->itu_zone).ignore();
// continent
(is >> ws).get(entry->continent, 3).ignore();
// latitude
(is >> entry->latitude).ignore();
// longitude
(is >> entry->longitude).ignore();
// gmt offset
(is >> entry->gmt_offset).ignore(256, '\n');
// prefixes and exceptions
int c;
string prefix;
while ((c = is.peek()) == ' ' || c == '\r' || c == '\n') {
is >> ws;
if (is.peek() == '=')
is.ignore();
while (getline(is, prefix, ',')) {
add_prefix(prefix, entry);
if ((c = is.peek()) == '\r' || c == '\n')
break;
else if (c == '=')
is.ignore();
}
}
in >> ws; // cr/lf after ';'
}
LOG_INFO("Loaded %zu prefixes for %u countries", cmap->size(), nrec);
return true;
}
void dxcc_close(void)
{
delete cnames;
cnames = 0;
delete cmap;
cmap = 0;
}
const dxcc* dxcc_lookup(const char* callsign)
{
if (!cmap)
return NULL;
string sstr;
sstr.resize(strlen(callsign));
transform(callsign, callsign + sstr.length(), sstr.begin(), static_cast<int (*)(int)>(toupper));
dxcc_map::const_iterator entry;
size_t len = sstr.length();
do {
sstr.resize(len--);
if ((entry = cmap->find(sstr)) != cmap->end())
return entry->second;
} while (len);
return NULL;
}
static void add_prefix(string& prefix, dxcc* entry)
{
static dxcc_map::iterator prev_entry = cmap->begin();
string::size_type i = prefix.find_first_of("([<{");
if (likely(i == string::npos)) {
prev_entry = cmap->insert(prev_entry, make_pair(prefix, entry));
return;
}
string::size_type j = i, first = i;
do {
entry = new struct dxcc(*entry);
switch (prefix[i++]) { // increment i past opening bracket
case '(':
if ((j = prefix.find(')', i)) == string::npos) {
delete entry;
return;
}
prefix[j] = '\0';
entry->cq_zone = atoi(prefix.data() + i);
break;
case '[':
if ((j = prefix.find(']', i)) == string::npos) {
delete entry;
return;
}
prefix[j] = '\0';
entry->itu_zone = atoi(prefix.data() + i);
break;
case '<':
if ((j = prefix.find('/', i)) == string::npos) {
delete entry;
return;
}
prefix[j] = '\0';
entry->latitude = atof(prefix.data() + i);
if ((j = prefix.find('>', j)) == string::npos) {
delete entry;
return;
}
prefix[j] = '\0';
entry->longitude = atof(prefix.data() + i);
break;
case '{':
if ((j = prefix.find('}', i)) == string::npos) {
delete entry;
return;
}
memcpy(entry->continent, prefix.data() + i, 2);
break;
}
} while ((i = prefix.find_first_of("([<{", j)) != string::npos);
prefix.erase(first);
prev_entry = cmap->insert(prev_entry, make_pair(prefix, entry));
}