From 07ada69385ae79642df871e8d1a0a06e1996ea4e Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Fri, 14 Jul 2017 21:04:00 -0400 Subject: [PATCH] Expose a list * Existing API always accesses the front of the list. * Add locate_zone and current_zone member functions to TZ_DB. * reload_tzdb() pushes a new database to the front of the list. * get_tzdb_list() exposes the list&. --- tz.cpp | 62 +++++++++++++++++++++++++++++++++++++++------------------- tz.h | 5 +++++ 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/tz.cpp b/tz.cpp index 9502b9b..04974f5 100644 --- a/tz.cpp +++ b/tz.cpp @@ -96,6 +96,7 @@ #include #include #include +#include #include #if USE_OS_TZDB # include @@ -319,11 +320,21 @@ struct undocumented {explicit undocumented() = default;}; static_assert(min_year <= max_year, "Configuration error"); #endif +static TZ_DB init_tzdb(); + static -TZ_DB& -access_tzdb() +std::list +create_tzdb() { - static TZ_DB tz_db; + std::list tz_db; + tz_db.push_back(init_tzdb()); + return tz_db; +} + +std::list& +get_tzdb_list() +{ + static std::list tz_db = create_tzdb(); return tz_db; } @@ -1846,7 +1857,7 @@ time_zone::load_data(std::istream& inf, auto infos = load_ttinfo(inf, tzh_typecnt); auto abbrev = load_abbreviations(inf, tzh_charcnt); #if !MISSING_LEAP_SECONDS - auto& leap_seconds = access_tzdb().leaps; + auto& leap_seconds = get_tzdb_list().front().leaps; if (leap_seconds.empty() && tzh_leapcnt > 0) leap_seconds = load_leaps(inf, tzh_leapcnt); #endif @@ -1914,7 +1925,7 @@ time_zone::init_impl() #if !MISSING_LEAP_SECONDS if (tzh_leapcnt > 0) { - auto& leap_seconds = access_tzdb().leaps; + auto& leap_seconds = get_tzdb_list().front().leaps; auto itr = leap_seconds.begin(); auto l = itr->date(); seconds leap_count{0}; @@ -3318,11 +3329,12 @@ const TZ_DB& reload_tzdb() { #if AUTO_DOWNLOAD - auto const& v = access_tzdb().version; + auto const& v = get_tzdb_list().front().version; if (!v.empty() && v == remote_version()) - return access_tzdb(); + return get_tzdb_list().front(); #endif // AUTO_DOWNLOAD - return access_tzdb() = init_tzdb(); + get_tzdb_list().push_front(init_tzdb()); + return get_tzdb_list().front(); } #endif // !USE_OS_TZDB @@ -3330,35 +3342,33 @@ reload_tzdb() const TZ_DB& get_tzdb() { - static const TZ_DB& ref = access_tzdb() = init_tzdb(); - return ref; + return get_tzdb_list().front(); } const time_zone* -locate_zone(const std::string& tz_name) +TZ_DB::locate_zone(const std::string& tz_name) const { - const auto& db = get_tzdb(); - auto zi = std::lower_bound(db.zones.begin(), db.zones.end(), tz_name, + auto zi = std::lower_bound(zones.begin(), zones.end(), tz_name, [](const time_zone& z, const std::string& nm) { return z.name() < nm; }); - if (zi == db.zones.end() || zi->name() != tz_name) + if (zi == zones.end() || zi->name() != tz_name) { #if !USE_OS_TZDB - auto li = std::lower_bound(db.links.begin(), db.links.end(), tz_name, + auto li = std::lower_bound(links.begin(), links.end(), tz_name, [](const link& z, const std::string& nm) { return z.name() < nm; }); - if (li != db.links.end() && li->name() == tz_name) + if (li != links.end() && li->name() == tz_name) { - zi = std::lower_bound(db.zones.begin(), db.zones.end(), li->target(), + zi = std::lower_bound(zones.begin(), zones.end(), li->target(), [](const time_zone& z, const std::string& nm) { return z.name() < nm; }); - if (zi != db.zones.end() && zi->name() == li->target()) + if (zi != zones.end() && zi->name() == li->target()) return &*zi; } #endif // !USE_OS_TZDB @@ -3367,6 +3377,12 @@ locate_zone(const std::string& tz_name) return &*zi; } +const time_zone* +locate_zone(const std::string& tz_name) +{ + return get_tzdb().locate_zone(tz_name); +} + #if USE_OS_TZDB std::ostream& @@ -3467,7 +3483,7 @@ getTimeZoneKeyName() } const time_zone* -current_zone() +TZ_DB::current_zone() const { std::string win_tzid = getTimeZoneKeyName(); std::string standard_tzid; @@ -3485,7 +3501,7 @@ current_zone() #else // !_WIN32 const time_zone* -current_zone() +TZ_DB::current_zone() const { // On some OS's a file called /etc/localtime may // exist and it may be either a real file @@ -3556,6 +3572,12 @@ current_zone() #endif // !_WIN32 +const time_zone* +current_zone() +{ + return get_tzdb().current_zone(); +} + } // namespace date #if defined(__GNUC__) && __GNUC__ < 5 diff --git a/tz.h b/tz.h index 256676a..f9347d2 100644 --- a/tz.h +++ b/tz.h @@ -105,6 +105,7 @@ static_assert(HAS_REMOTE_API == 0 ? AUTO_DOWNLOAD == 0 : true, #include #include #include +#include #include #include #include @@ -832,12 +833,16 @@ struct TZ_DB return *this; } #endif // defined(_MSC_VER) && (_MSC_VER < 1900) + + const time_zone* locate_zone(const std::string& tz_name) const; + const time_zone* current_zone() const; }; DATE_API std::ostream& operator<<(std::ostream& os, const TZ_DB& db); DATE_API const TZ_DB& get_tzdb(); +DATE_API std::list& get_tzdb_list(); #if !USE_OS_TZDB