Make SGTimeZoneCOntainer using a pimpl
Keeps zonedetect data private to SimGear
This commit is contained in:
parent
4a1809b566
commit
feaac37705
@ -83,21 +83,21 @@ void SGTime::init( const SGGeod& location, const SGPath& root, time_t init_time
|
||||
|
||||
if ( !root.isNull()) {
|
||||
if (!static_tzContainer.get()) {
|
||||
SGPath zone( root );
|
||||
zone.append( "timezone16.bin" );
|
||||
SG_LOG( SG_EVENT, SG_INFO, "Reading timezone info from: " << zone );
|
||||
std::string zs = zone.utf8Str();
|
||||
static_tzContainer.reset(new SGTimeZoneContainer( zs.c_str() ));
|
||||
const auto zonePath = root / "timezone16.bin";
|
||||
SG_LOG( SG_EVENT, SG_INFO, "Reading timezone info from: " << zonePath );
|
||||
static_tzContainer.reset(new SGTimeZoneContainer(zonePath));
|
||||
}
|
||||
|
||||
SGTimeZone* nearestTz = static_tzContainer->getNearest(location);
|
||||
|
||||
SGPath name( root );
|
||||
name.append( nearestTz->getDescription() );
|
||||
zonename = name.utf8Str();
|
||||
SG_LOG( SG_EVENT, SG_DEBUG, "Using zonename = " << zonename );
|
||||
if (nearestTz) {
|
||||
SGPath name = root / nearestTz->getDescription();
|
||||
zonename = name.utf8Str();
|
||||
SG_LOG( SG_EVENT, SG_DEBUG, "Using zonename = " << zonename );
|
||||
} else {
|
||||
zonename.clear();
|
||||
}
|
||||
} else {
|
||||
zonename.erase();
|
||||
zonename.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,10 +28,6 @@
|
||||
#define _SG_TIME_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
|
@ -26,9 +26,7 @@
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
#include <simgear_config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
@ -39,9 +37,14 @@
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/misc/strutils.hxx>
|
||||
#include <simgear/io/sg_file.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#include "timezone.h"
|
||||
|
||||
#include "zonedetect.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
SGTimeZone::SGTimeZone(const SGGeod& geod, char* cc, char* desc) :
|
||||
centerpoint(SGVec3d::fromGeod(geod))
|
||||
{
|
||||
@ -135,35 +138,56 @@ SGTimeZone::SGTimeZone(const SGTimeZone& other)
|
||||
|
||||
/********* Member functions for SGTimeZoneContainer class ********/
|
||||
|
||||
SGTimeZoneContainer::SGTimeZoneContainer(const char *filename)
|
||||
class SGTimeZoneContainer::SGTimeZoneContainerPrivate
|
||||
{
|
||||
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);
|
||||
public:
|
||||
~SGTimeZoneContainerPrivate()
|
||||
{
|
||||
for (auto z : zones) {
|
||||
delete z;
|
||||
}
|
||||
|
||||
if (cd) {
|
||||
ZDCloseDatabase(cd);
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
ZoneDetect *cd = nullptr;
|
||||
std::string tzdb_buffer;
|
||||
|
||||
// zone.tab related
|
||||
bool is_zone_tab = false;
|
||||
using TZVec = std::vector<SGTimeZone*>;
|
||||
TZVec zones;
|
||||
};
|
||||
|
||||
SGTimeZoneContainer::SGTimeZoneContainer(const SGPath& path) :
|
||||
d(new SGTimeZoneContainerPrivate)
|
||||
{
|
||||
if (path.file() != "zone.tab") {
|
||||
sg_ifstream tzdb_file(path, std::ios::in);
|
||||
if ( !tzdb_file.is_open() ) {
|
||||
throw sg_io_exception("cannot open timezone file", path);
|
||||
}
|
||||
|
||||
d->tzdb_buffer = tzdb_file.read_all();
|
||||
d->cd = ZDOpenDatabaseFromMemory((void*) d->tzdb_buffer.data(), d->tzdb_buffer.size());
|
||||
if (!d->cd) {
|
||||
throw sg_io_exception("timezone database read error");
|
||||
}
|
||||
}
|
||||
}
|
||||
else // zone.tab is in filename
|
||||
{
|
||||
char buffer[256];
|
||||
#if defined(SG_WINDOWS)
|
||||
const std::wstring wfile = simgear::strutils::convertUtf8ToWString(filename);
|
||||
const std::wstring wfile = path.wstr();
|
||||
FILE* infile = _wfopen(wfile.c_str(), L"rb");
|
||||
#else
|
||||
FILE* infile = fopen(filename, "rb");
|
||||
const auto s = path.utf8Str();
|
||||
FILE* infile = fopen(s.c_str(), "rb");
|
||||
#endif
|
||||
if (!(infile)) {
|
||||
std::string e = "Unable to open time zone file '";
|
||||
throw sg_exception(e + filename + '\'');
|
||||
throw sg_exception("Unable to open time zone file", "", sg_location{path});
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
@ -181,7 +205,7 @@ SGTimeZoneContainer::SGTimeZoneContainer(const char *filename)
|
||||
}
|
||||
}
|
||||
if (buffer[0]) {
|
||||
zones.push_back(new SGTimeZone(buffer));
|
||||
d->zones.push_back(new SGTimeZone(buffer));
|
||||
}
|
||||
}
|
||||
if ( errno ) {
|
||||
@ -190,44 +214,33 @@ SGTimeZoneContainer::SGTimeZoneContainer(const char *filename)
|
||||
}
|
||||
|
||||
fclose(infile);
|
||||
is_zone_tab = true;
|
||||
d->is_zone_tab = true;
|
||||
}
|
||||
}
|
||||
|
||||
SGTimeZoneContainer::~SGTimeZoneContainer()
|
||||
{
|
||||
if (is_zone_tab)
|
||||
{
|
||||
TZVec::iterator it = zones.begin();
|
||||
for (; it != zones.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
else if (cd)
|
||||
{
|
||||
ZDCloseDatabase(cd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SGTimeZone* SGTimeZoneContainer::getNearest(const SGGeod& ref) const
|
||||
{
|
||||
SGTimeZone* match = NULL;
|
||||
|
||||
if (is_zone_tab)
|
||||
if (d->is_zone_tab)
|
||||
{
|
||||
SGVec3d refCart(SGVec3d::fromGeod(ref));
|
||||
double minDist2 = HUGE_VAL;
|
||||
|
||||
TZVec::const_iterator it = zones.begin();
|
||||
for (; it != zones.end(); ++it) {
|
||||
double d2 = distSqr((*it)->cartCenterpoint(), refCart);
|
||||
for (auto z : d->zones) {
|
||||
double d2 = distSqr(z->cartCenterpoint(), refCart);
|
||||
if (d2 < minDist2) {
|
||||
match = *it;
|
||||
match = z;
|
||||
minDist2 = d2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cd) // timezone16.bin
|
||||
else if (d->cd) // timezone16.bin
|
||||
{
|
||||
char *CountryAlpha2 = nullptr;
|
||||
char *TimezoneIdPrefix = nullptr;
|
||||
@ -236,7 +249,7 @@ SGTimeZone* SGTimeZoneContainer::getNearest(const SGGeod& ref) const
|
||||
float safezone = 0;
|
||||
float lat = ref.getLatitudeDeg();
|
||||
float lon = ref.getLongitudeDeg();
|
||||
ZoneDetectResult *results = ZDLookup(cd, lat, lon, &safezone);
|
||||
ZoneDetectResult *results = ZDLookup(d->cd, lat, lon, &safezone);
|
||||
if (results && results[0].data)
|
||||
{
|
||||
for(unsigned i=0; i<results[0].numFields; ++i)
|
||||
@ -254,10 +267,7 @@ SGTimeZone* SGTimeZoneContainer::getNearest(const SGGeod& ref) const
|
||||
}
|
||||
}
|
||||
|
||||
std::string desc;
|
||||
desc = TimezoneIdPrefix;
|
||||
desc += TimezoneId;
|
||||
|
||||
const auto desc = string{TimezoneIdPrefix} + string{TimezoneId};
|
||||
match = new SGTimeZone(ref, CountryAlpha2, (char*)desc.c_str());
|
||||
}
|
||||
}
|
||||
|
@ -29,18 +29,18 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/math/SGGeod.hxx>
|
||||
|
||||
#include "zonedetect.h"
|
||||
|
||||
/**
|
||||
* SGTimeZone stores the timezone centerpoint,
|
||||
* as well as the countrycode and the timezone descriptor. The latter is
|
||||
* used in order to get the local time.
|
||||
*
|
||||
*/
|
||||
class SGPath;
|
||||
|
||||
class SGTimeZone
|
||||
{
|
||||
@ -93,19 +93,15 @@ public:
|
||||
class SGTimeZoneContainer
|
||||
{
|
||||
public:
|
||||
SGTimeZoneContainer(const char *filename);
|
||||
~SGTimeZoneContainer();
|
||||
SGTimeZoneContainer(const SGPath& path);
|
||||
~SGTimeZoneContainer();
|
||||
|
||||
SGTimeZone* getNearest(const SGGeod& ref) const;
|
||||
|
||||
private:
|
||||
ZoneDetect *cd = nullptr;
|
||||
std::string tzdb_buffer;
|
||||
class SGTimeZoneContainerPrivate;
|
||||
|
||||
// zone.tab related
|
||||
bool is_zone_tab = false;
|
||||
typedef std::vector<SGTimeZone*> TZVec;
|
||||
TZVec zones;
|
||||
std::unique_ptr<SGTimeZoneContainerPrivate> d;
|
||||
};
|
||||
|
||||
|
||||
|
@ -30,13 +30,8 @@
|
||||
#ifndef INCL_ZONEDETECT_H_
|
||||
#define INCL_ZONEDETECT_H_
|
||||
|
||||
#if !defined(ZD_EXPORT)
|
||||
#if defined(_MSC_VER)
|
||||
#define ZD_EXPORT __declspec(dllimport)
|
||||
#else
|
||||
// defined to nothing, since we're linking these symbols statically
|
||||
#define ZD_EXPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
ZD_LOOKUP_IGNORE = -3,
|
||||
|
Loading…
Reference in New Issue
Block a user