From bfe0792aa46ac5b6ea5cfdd5a5c0b6cf41d04d82 Mon Sep 17 00:00:00 2001 From: Benjamin Freist Date: Thu, 11 Jul 2024 10:18:58 +0200 Subject: [PATCH] update vendored/datetime --- cpp/src/arrow/vendored/datetime/README.md | 2 +- cpp/src/arrow/vendored/datetime/date.h | 30 +++-- cpp/src/arrow/vendored/datetime/ios.h | 3 - cpp/src/arrow/vendored/datetime/ios.mm | 5 +- cpp/src/arrow/vendored/datetime/tz.cpp | 109 +++++++++++++++---- cpp/src/arrow/vendored/datetime/tz.h | 13 +-- cpp/src/arrow/vendored/datetime/tz_private.h | 6 +- 7 files changed, 113 insertions(+), 55 deletions(-) diff --git a/cpp/src/arrow/vendored/datetime/README.md b/cpp/src/arrow/vendored/datetime/README.md index 0dd663c5e5acc..5a0993b7b4336 100644 --- a/cpp/src/arrow/vendored/datetime/README.md +++ b/cpp/src/arrow/vendored/datetime/README.md @@ -17,7 +17,7 @@ copies or substantial portions of the Software. Sources for datetime are adapted from Howard Hinnant's date library (https://github.com/HowardHinnant/date). -Sources are taken from changeset cc4685a21e4a4fdae707ad1233c61bbaff241f93 +Sources are taken from changeset 1ead6715dec030d340a316c927c877a3c4e5a00c of the above project. The following changes are made: diff --git a/cpp/src/arrow/vendored/datetime/date.h b/cpp/src/arrow/vendored/datetime/date.h index fd2569c6de0f6..beb627e47433f 100644 --- a/cpp/src/arrow/vendored/datetime/date.h +++ b/cpp/src/arrow/vendored/datetime/date.h @@ -84,8 +84,6 @@ # pragma warning(disable : 4127) #endif -namespace arrow_vendored -{ namespace date { @@ -4230,7 +4228,7 @@ inline std::basic_ostream& operator<<(std::basic_ostream& os, const local_time& ut) { - return (os << sys_time{ut.time_since_epoch()}); + return (date::operator<<(os, sys_time{ut.time_since_epoch()})); } namespace detail @@ -6353,7 +6351,10 @@ read_signed(std::basic_istream& is, unsigned m = 1, unsigned M = if (('0' <= c && c <= '9') || c == '-' || c == '+') { if (c == '-' || c == '+') + { (void)is.get(); + --M; + } auto x = static_cast(read_unsigned(is, std::max(m, 1u), M)); if (!is.fail()) { @@ -6526,7 +6527,14 @@ read(std::basic_istream& is, int a0, Args&& ...args) *e++ = static_cast(CharT(u % 10) + CharT{'0'}); u /= 10; } while (u > 0); +#if defined(__GNUC__) && __GNUC__ >= 11 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif std::reverse(buf, e); +#if defined(__GNUC__) && __GNUC__ >= 11 +#pragma GCC diagnostic pop +#endif for (auto p = buf; p != e && is.rdstate() == std::ios::goodbit; ++p) read(is, *p); } @@ -6592,7 +6600,7 @@ from_stream(std::basic_istream& is, const CharT* fmt, CONSTDATA int not_a_year = numeric_limits::min(); CONSTDATA int not_a_2digit_year = 100; - CONSTDATA int not_a_century = not_a_year / 100; + CONSTDATA int not_a_century = numeric_limits::min(); CONSTDATA int not_a_month = 0; CONSTDATA int not_a_day = 0; CONSTDATA int not_a_hour = numeric_limits::min(); @@ -7519,7 +7527,12 @@ from_stream(std::basic_istream& is, const CharT* fmt, { auto c = static_cast(Traits::to_char_type(ic)); if (c == '-') + { neg = true; + (void)is.get(); + } + else if (c == '+') + (void)is.get(); } if (modified == CharT{}) { @@ -7735,9 +7748,7 @@ from_stream(std::basic_istream& is, const CharT* fmt, year_month_day ymd_trial = sys_days(year{Y}/January/Sunday[1]) + weeks{U-1} + (weekday{static_cast(wd)} - Sunday); - if (Y == not_a_year) - Y = static_cast(ymd_trial.year()); - else if (year{Y} != ymd_trial.year()) + if (year{Y} != ymd_trial.year()) goto broken; if (m == not_a_month) m = static_cast(static_cast(ymd_trial.month())); @@ -7754,9 +7765,7 @@ from_stream(std::basic_istream& is, const CharT* fmt, year_month_day ymd_trial = sys_days(year{Y}/January/Monday[1]) + weeks{W-1} + (weekday{static_cast(wd)} - Monday); - if (Y == not_a_year) - Y = static_cast(ymd_trial.year()); - else if (year{Y} != ymd_trial.year()) + if (year{Y} != ymd_trial.year()) goto broken; if (m == not_a_month) m = static_cast(static_cast(ymd_trial.month())); @@ -8224,7 +8233,6 @@ operator<<(std::basic_ostream& os, } } // namespace date -} // namespace arrow_vendored #ifdef _MSC_VER # pragma warning(pop) diff --git a/cpp/src/arrow/vendored/datetime/ios.h b/cpp/src/arrow/vendored/datetime/ios.h index acad28d13b558..a9f863653972c 100644 --- a/cpp/src/arrow/vendored/datetime/ios.h +++ b/cpp/src/arrow/vendored/datetime/ios.h @@ -32,8 +32,6 @@ # if TARGET_OS_IPHONE # include - namespace arrow_vendored - { namespace date { namespace iOSUtils @@ -44,7 +42,6 @@ } // namespace iOSUtils } // namespace date - } // namespace arrow_vendored # endif // TARGET_OS_IPHONE #else // !__APPLE__ diff --git a/cpp/src/arrow/vendored/datetime/ios.mm b/cpp/src/arrow/vendored/datetime/ios.mm index 22b7ce6c30bc2..9e5d800ee5756 100644 --- a/cpp/src/arrow/vendored/datetime/ios.mm +++ b/cpp/src/arrow/vendored/datetime/ios.mm @@ -22,7 +22,7 @@ // SOFTWARE. // -#include "ios.h" +#include "date/ios.h" #if TARGET_OS_IPHONE @@ -47,8 +47,6 @@ #define TAR_SIZE_POSITION 124 #define TAR_SIZE_SIZE 12 -namespace arrow_vendored -{ namespace date { namespace iOSUtils @@ -335,6 +333,5 @@ bool writeFile(const std::string &tzdataPath, const std::string &fileName, } // namespace iOSUtils } // namespace date -} // namespace arrow_vendored #endif // TARGET_OS_IPHONE diff --git a/cpp/src/arrow/vendored/datetime/tz.cpp b/cpp/src/arrow/vendored/datetime/tz.cpp index e94c1bc8ae682..82e4312d25e9a 100644 --- a/cpp/src/arrow/vendored/datetime/tz.cpp +++ b/cpp/src/arrow/vendored/datetime/tz.cpp @@ -30,10 +30,6 @@ // been invented (that would involve another several millennia of evolution). // We did not mean to shout. -// NOTE(ARROW): This is required so that symbols are properly exported from the DLL -#include "visibility.h" - - #ifdef _WIN32 // windows.h will be included directly and indirectly (e.g. by curl). // We need to define these macros to prevent windows.h bringing in @@ -87,15 +83,19 @@ # include #endif // _WIN32 -#include "tz_private.h" +#include "date/tz_private.h" #ifdef __APPLE__ -# include "ios.h" +# include "date/ios.h" #else # define TARGET_OS_IPHONE 0 # define TARGET_OS_SIMULATOR 0 #endif +#if defined(ANDROID) || defined(__ANDROID__) +#include +#endif + #if USE_OS_TZDB # include #endif @@ -118,7 +118,7 @@ #include #include -// unistd.h is used on some platforms as part of the means to get +// unistd.h is used on some platforms as part of the the means to get // the current time zone. On Win32 windows.h provides a means to do it. // gcc/mingw supports unistd.h on Win32 but MSVC does not. @@ -384,8 +384,7 @@ class file_streambuf }; #endif // !USE_OS_TZDB -namespace arrow_vendored -{ + namespace date { // +---------------------+ @@ -2709,7 +2708,8 @@ operator<<(std::ostream& os, const time_zone& z) os.width(8); os << s.format_ << " "; os << s.until_year_ << ' ' << s.until_date_; - os << " " << s.until_utc_ << " UTC"; + os << " "; + date::operator<<(os, s.until_utc_) << " UTC"; os << " " << s.until_std_ << " STD"; os << " " << s.until_loc_; os << " " << make_time(s.initial_save_); @@ -2734,8 +2734,7 @@ operator<<(std::ostream& os, const time_zone& z) std::ostream& operator<<(std::ostream& os, const leap_second& x) { - using namespace date; - return os << x.date_ << " +"; + return date::operator<<(os, x.date_) << " +"; } #if USE_OS_TZDB @@ -3716,6 +3715,67 @@ get_tzdb() return get_tzdb_list().front(); } +namespace { + +class recursion_limiter +{ + unsigned depth_ = 0; + unsigned limit_; + + class restore_recursion_depth; + +public: + recursion_limiter(recursion_limiter const&) = delete; + recursion_limiter& operator=(recursion_limiter const&) = delete; + + explicit constexpr recursion_limiter(unsigned limit) noexcept; + + restore_recursion_depth count(); +}; + +class recursion_limiter::restore_recursion_depth +{ + recursion_limiter* rc_; + +public: + ~restore_recursion_depth(); + restore_recursion_depth(restore_recursion_depth&&) = default; + + explicit restore_recursion_depth(recursion_limiter* rc) noexcept; +}; + +inline +recursion_limiter::restore_recursion_depth::~restore_recursion_depth() +{ + --(rc_->depth_); +} + +inline +recursion_limiter::restore_recursion_depth::restore_recursion_depth(recursion_limiter* rc) + noexcept + : rc_{rc} +{} + +inline +constexpr +recursion_limiter::recursion_limiter(unsigned limit) noexcept + : limit_{limit} +{ +} + +inline +recursion_limiter::restore_recursion_depth +recursion_limiter::count() +{ + ++depth_; + if (depth_ > limit_) + throw std::runtime_error("recursion limit of " + + std::to_string(limit_) + " exceeded"); + return restore_recursion_depth{this}; +} + +} // unnamed namespace + const time_zone* #if HAS_STRING_VIEW tzdb::locate_zone(std::string_view tz_name) const @@ -3723,6 +3783,10 @@ tzdb::locate_zone(std::string_view tz_name) const tzdb::locate_zone(const std::string& tz_name) const #endif { + // If a link-to-link chain exceeds this limit, give up + thread_local recursion_limiter rc{10}; + auto restore_count = rc.count(); + auto zi = std::lower_bound(zones.begin(), zones.end(), tz_name, #if HAS_STRING_VIEW [](const time_zone& z, const std::string_view& nm) @@ -3746,13 +3810,7 @@ tzdb::locate_zone(const std::string& tz_name) const }); if (li != links.end() && li->name() == tz_name) { - zi = std::lower_bound(zones.begin(), zones.end(), li->target(), - [](const time_zone& z, const std::string& nm) - { - return z.name() < nm; - }); - if (zi != zones.end() && zi->name() == li->target()) - return &*zi; + return locate_zone(li->target()); } #endif // !USE_OS_TZDB throw std::runtime_error(std::string(tz_name) + " not found in timezone database"); @@ -4038,6 +4096,18 @@ tzdb::current_zone() const if (!result.empty()) return locate_zone(result); #endif + // Fall through to try other means. + } + { + // On Android, it is not possible to use file based approach either, + // we have to ask the value of `persist.sys.timezone` system property +#if defined(ANDROID) || defined(__ANDROID__) + char sys_timezone[PROP_VALUE_MAX]; + if (__system_property_get("persist.sys.timezone", sys_timezone) > 0) + { + return locate_zone(sys_timezone); + } +#endif // defined(ANDROID) || defined(__ANDROID__) // Fall through to try other means. } { @@ -4072,7 +4142,6 @@ current_zone() } } // namespace date -} // namespace arrow_vendored #if defined(__GNUC__) && __GNUC__ < 5 # pragma GCC diagnostic pop diff --git a/cpp/src/arrow/vendored/datetime/tz.h b/cpp/src/arrow/vendored/datetime/tz.h index 467db6d199793..0f9f2c5bb1d6d 100644 --- a/cpp/src/arrow/vendored/datetime/tz.h +++ b/cpp/src/arrow/vendored/datetime/tz.h @@ -43,12 +43,6 @@ // required. On Windows, the names are never "Standard" so mapping is always required. // Technically any OS may use the mapping process but currently only Windows does use it. -// NOTE(ARROW): If this is not set, then the library will attempt to -// use libcurl to obtain a timezone database, and we probably do not want this. -#ifndef _WIN32 -#define USE_OS_TZDB 1 -#endif - #ifndef USE_OS_TZDB # define USE_OS_TZDB 0 #endif @@ -140,8 +134,6 @@ static_assert(HAS_REMOTE_API == 0 ? AUTO_DOWNLOAD == 0 : true, # endif #endif -namespace arrow_vendored -{ namespace date { @@ -239,8 +231,8 @@ nonexistent_local_time::make_msg(local_time tp, const local_info& i) << i.first.abbrev << " and\n" << local_seconds{i.second.begin.time_since_epoch()} + i.second.offset << ' ' << i.second.abbrev - << " which are both equivalent to\n" - << i.first.end << " UTC"; + << " which are both equivalent to\n"; + date::operator<<(os, i.first.end) << " UTC"; return os.str(); } @@ -2796,6 +2788,5 @@ to_gps_time(const tai_time& t) } } // namespace date -} // namespace arrow_vendored #endif // TZ_H diff --git a/cpp/src/arrow/vendored/datetime/tz_private.h b/cpp/src/arrow/vendored/datetime/tz_private.h index 6b7a91493e103..1a01f176ed88e 100644 --- a/cpp/src/arrow/vendored/datetime/tz_private.h +++ b/cpp/src/arrow/vendored/datetime/tz_private.h @@ -34,8 +34,6 @@ #include #endif -namespace arrow_vendored -{ namespace date { @@ -291,8 +289,7 @@ struct transition std::ostream& operator<<(std::ostream& os, const transition& t) { - using date::operator<<; - os << t.timepoint << "Z "; + date::operator<<(os, t.timepoint) << "Z "; if (t.info->offset >= std::chrono::seconds{0}) os << '+'; os << make_time(t.info->offset); @@ -310,7 +307,6 @@ struct transition } // namespace detail } // namespace date -} // namespace arrow_vendored #if defined(_MSC_VER) && (_MSC_VER < 1900) #include "tz.h"