Use sg_ifstream to load the timezone database into a buffer, and access the database from that buffer. This prevents opening and closing the files too often and allows for wide character paths on Windows.
This commit is contained in:
Executable → Regular
+48
-34
@@ -35,10 +35,11 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <simgear/io/iostreams/sgstream.hxx>
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
#include <simgear/misc/strutils.hxx>
|
#include <simgear/misc/strutils.hxx>
|
||||||
|
#include <simgear/io/sg_file.hxx>
|
||||||
|
|
||||||
#include "zonedetect.h"
|
|
||||||
#include "timezone.h"
|
#include "timezone.h"
|
||||||
|
|
||||||
SGTimeZone::SGTimeZone(const SGGeod& geod, char* cc, char* desc) :
|
SGTimeZone::SGTimeZone(const SGGeod& geod, char* cc, char* desc) :
|
||||||
@@ -134,10 +135,24 @@ SGTimeZone::SGTimeZone(const SGTimeZone& other)
|
|||||||
|
|
||||||
/********* Member functions for SGTimeZoneContainer class ********/
|
/********* Member functions for SGTimeZoneContainer class ********/
|
||||||
|
|
||||||
SGTimeZoneContainer::SGTimeZoneContainer(const char *filename) :
|
SGTimeZoneContainer::SGTimeZoneContainer(const char *filename)
|
||||||
tzdb_file(filename)
|
|
||||||
{
|
{
|
||||||
if (tzdb_file.find("zone.tab") != std::string::npos)
|
std::string tzdb_file = filename;
|
||||||
|
if (tzdb_file.find("zone.tab") == std::string::npos)
|
||||||
|
{
|
||||||
|
SGPath path(filename);
|
||||||
|
sg_ifstream tzdb_file(path, std::ios::in);
|
||||||
|
if ( !tzdb_file.is_open() ) {
|
||||||
|
throw sg_io_exception("cannot open timezone file", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
tzdb_buffer = tzdb_file.read_all();
|
||||||
|
cd = ZDOpenDatabaseFromMemory((void*)tzdb_buffer.c_str(), tzdb_buffer.size());
|
||||||
|
if (!cd) {
|
||||||
|
throw sg_io_exception("timezone database read error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // zone.tab is in filename
|
||||||
{
|
{
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
#if defined(SG_WINDOWS)
|
#if defined(SG_WINDOWS)
|
||||||
@@ -188,6 +203,10 @@ SGTimeZoneContainer::~SGTimeZoneContainer()
|
|||||||
delete *it;
|
delete *it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (cd)
|
||||||
|
{
|
||||||
|
ZDCloseDatabase(cd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SGTimeZone* SGTimeZoneContainer::getNearest(const SGGeod& ref) const
|
SGTimeZone* SGTimeZoneContainer::getNearest(const SGGeod& ref) const
|
||||||
@@ -208,43 +227,38 @@ SGTimeZone* SGTimeZoneContainer::getNearest(const SGGeod& ref) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!tzdb_file.empty())
|
else if (cd) // timezone16.bin
|
||||||
{
|
{
|
||||||
ZoneDetect *const cd = ZDOpenDatabase(tzdb_file.c_str());
|
char *CountryAlpha2 = nullptr;
|
||||||
if (cd)
|
char *TimezoneIdPrefix = nullptr;
|
||||||
{
|
char *TimezoneId = nullptr;
|
||||||
char *CountryAlpha2 = nullptr;
|
|
||||||
char *TimezoneIdPrefix = nullptr;
|
|
||||||
char *TimezoneId = nullptr;
|
|
||||||
|
|
||||||
float safezone = 0;
|
float safezone = 0;
|
||||||
float lat = ref.getLatitudeDeg();
|
float lat = ref.getLatitudeDeg();
|
||||||
float lon = ref.getLongitudeDeg();
|
float lon = ref.getLongitudeDeg();
|
||||||
ZoneDetectResult *results = ZDLookup(cd, lat, lon, &safezone);
|
ZoneDetectResult *results = ZDLookup(cd, lat, lon, &safezone);
|
||||||
if (results && results[0].data)
|
if (results && results[0].data)
|
||||||
|
{
|
||||||
|
for(unsigned i=0; i<results[0].numFields; ++i)
|
||||||
{
|
{
|
||||||
for(unsigned i=0; i<results[0].numFields; ++i)
|
if(results[0].fieldNames[i] && results[0].data[i])
|
||||||
{
|
{
|
||||||
if(results[0].fieldNames[i] && results[0].data[i])
|
std::string fieldName = results[0].fieldNames[i];
|
||||||
{
|
if (fieldName == "CountryAlpha2") {
|
||||||
std::string fieldName = results[0].fieldNames[i];
|
CountryAlpha2 = results[0].data[i];
|
||||||
if (fieldName == "CountryAlpha2") {
|
} else if (fieldName == "TimezoneIdPrefix") {
|
||||||
CountryAlpha2 = results[0].data[i];
|
TimezoneIdPrefix = results[0].data[i];
|
||||||
} else if (fieldName == "TimezoneIdPrefix") {
|
} else if (fieldName == "TimezoneId") {
|
||||||
TimezoneIdPrefix = results[0].data[i];
|
TimezoneId = results[0].data[i];
|
||||||
} else if (fieldName == "TimezoneId") {
|
|
||||||
TimezoneId = results[0].data[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string desc;
|
|
||||||
desc = TimezoneIdPrefix;
|
|
||||||
desc += TimezoneId;
|
|
||||||
|
|
||||||
match = new SGTimeZone(ref, CountryAlpha2, (char*)desc.c_str());
|
|
||||||
}
|
}
|
||||||
ZDCloseDatabase(cd);
|
|
||||||
|
std::string desc;
|
||||||
|
desc = TimezoneIdPrefix;
|
||||||
|
desc += TimezoneId;
|
||||||
|
|
||||||
|
match = new SGTimeZone(ref, CountryAlpha2, (char*)desc.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
#include <simgear/math/SGMath.hxx>
|
#include <simgear/math/SGMath.hxx>
|
||||||
#include <simgear/math/SGGeod.hxx>
|
#include <simgear/math/SGGeod.hxx>
|
||||||
|
|
||||||
|
#include "zonedetect.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SGTimeZone stores the timezone centerpoint,
|
* SGTimeZone stores the timezone centerpoint,
|
||||||
* as well as the countrycode and the timezone descriptor. The latter is
|
* as well as the countrycode and the timezone descriptor. The latter is
|
||||||
@@ -97,7 +99,8 @@ public:
|
|||||||
SGTimeZone* getNearest(const SGGeod& ref) const;
|
SGTimeZone* getNearest(const SGGeod& ref) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string tzdb_file;
|
ZoneDetect *cd = nullptr;
|
||||||
|
std::string tzdb_buffer;
|
||||||
|
|
||||||
// zone.tab related
|
// zone.tab related
|
||||||
bool is_zone_tab = false;
|
bool is_zone_tab = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user