diff --git a/simgear/timing/sg_time.cxx b/simgear/timing/sg_time.cxx index 01b9fac2..f354967c 100644 --- a/simgear/timing/sg_time.cxx +++ b/simgear/timing/sg_time.cxx @@ -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(); } } diff --git a/simgear/timing/sg_time.hxx b/simgear/timing/sg_time.hxx index cbfd2b8e..df12d04e 100644 --- a/simgear/timing/sg_time.hxx +++ b/simgear/timing/sg_time.hxx @@ -28,10 +28,6 @@ #define _SG_TIME_HXX -#ifndef __cplusplus -# error This library requires C++ -#endif - #include diff --git a/simgear/timing/timezone.cxx b/simgear/timing/timezone.cxx index 4a07864d..06fc6ce9 100644 --- a/simgear/timing/timezone.cxx +++ b/simgear/timing/timezone.cxx @@ -26,9 +26,7 @@ * ************************************************************************/ -#ifdef HAVE_CONFIG_H -# include -#endif +#include #include #include @@ -39,9 +37,14 @@ #include #include #include +#include #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); + } } + + ZoneDetect *cd = nullptr; + std::string tzdb_buffer; - 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"); + // zone.tab related + bool is_zone_tab = false; + using TZVec = std::vector; + 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 #include +#include #include #include -#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; - - // zone.tab related - bool is_zone_tab = false; - typedef std::vector TZVec; - TZVec zones; + class SGTimeZoneContainerPrivate; + + std::unique_ptr d; }; diff --git a/simgear/timing/zonedetect.h b/simgear/timing/zonedetect.h index 710cb5a9..d783e546 100644 --- a/simgear/timing/zonedetect.h +++ b/simgear/timing/zonedetect.h @@ -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,