This is an automated email from the ASF dual-hosted git repository.
kou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new 718415030f GH-43095: [C++] Update bundled vendor/datetime to support
for building with libc++ and C++20 (#43094)
718415030f is described below
commit 718415030f8ebcad14bc3fa10906beca6526c5e9
Author: ben-freist <[email protected]>
AuthorDate: Fri Jul 12 22:40:04 2024 +0200
GH-43095: [C++] Update bundled vendor/datetime to support for building with
libc++ and C++20 (#43094)
### Rationale for this change
We can't build with libc++ and C++20:
CMake command line:
```bash
cmake -DARROW_ENABLE_THREADING=OFF \
-DARROW_JEMALLOC=OFF \
-DCMAKE_CXX_STANDARD=20 \
-DCXX_ONLY_FLAGS="-stdlib=libc++" \
-DCMAKE_TOOLCHAIN_FILE=toolchain.cmake --preset ninja-debug-minimal
../cpp/
```
Error log:
```
In file included from
~/.conan2/p/b/arrowe39f77e638649/b/src/cpp/src/arrow/vendored/datetime/tz.cpp:90:
~/.conan2/p/b/arrowe39f77e638649/b/src/cpp/src/arrow/vendored/datetime/tz_private.h:295:12:
error: use of overloaded operator '<<' is ambiguous (with operand types
'std::ostream' (aka 'basic_ostream<char>') and 'const sys_seconds' (aka 'const
time_point<std::chrono::system_clock, std::chrono::duration<long long,
std::ratio<1, 1>>>'))
295 | os << t.timepoint << "Z ";
| ~~ ^ ~~~~~~~~~~~
/usr/lib/llvm-17/bin/../include/c++/v1/__chrono/ostream.h:46:1: note:
candidate function [with _CharT = char, _Traits = std::char_traits<char>,
_Duration = std::chrono::duration<long long>]
46 | operator<<(basic_ostream<_CharT, _Traits>& __os, const
sys_time<_Duration> __tp) {
| ^
~/.conan2/p/b/arrowe39f77e638649/b/src/cpp/src/arrow/vendored/datetime/date.h:4214:1:
note: candidate function [with CharT = char, Traits = std::char_traits<char>,
Duration = std::chrono::duration<long long>]
4214 | operator<<(std::basic_ostream<CharT, Traits>& os, const
sys_time<Duration>& tp)
```
### What changes are included in this PR?
Update the bundled vendor/datetime because the upstream has changes for
this case:
https://github.com/HowardHinnant/date/pull/827
### Are these changes tested?
### Are there any user-facing changes?
* GitHub Issue: #43095
Authored-by: Benjamin Freist <[email protected]>
Signed-off-by: Sutou Kouhei <[email protected]>
---
cpp/src/arrow/vendored/datetime/README.md | 2 +-
cpp/src/arrow/vendored/datetime/date.h | 27 +++++---
cpp/src/arrow/vendored/datetime/tz.cpp | 95 +++++++++++++++++++++++++---
cpp/src/arrow/vendored/datetime/tz.h | 4 +-
cpp/src/arrow/vendored/datetime/tz_private.h | 3 +-
5 files changed, 108 insertions(+), 23 deletions(-)
diff --git a/cpp/src/arrow/vendored/datetime/README.md
b/cpp/src/arrow/vendored/datetime/README.md
index 0dd663c5e5..5a0993b7b4 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 fd2569c6de..75e2624296 100644
--- a/cpp/src/arrow/vendored/datetime/date.h
+++ b/cpp/src/arrow/vendored/datetime/date.h
@@ -4230,7 +4230,7 @@ inline
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const local_time<Duration>&
ut)
{
- return (os << sys_time<Duration>{ut.time_since_epoch()});
+ return (date::operator<<(os, sys_time<Duration>{ut.time_since_epoch()}));
}
namespace detail
@@ -6353,7 +6353,10 @@ read_signed(std::basic_istream<CharT, Traits>& is,
unsigned m = 1, unsigned M =
if (('0' <= c && c <= '9') || c == '-' || c == '+')
{
if (c == '-' || c == '+')
+ {
(void)is.get();
+ --M;
+ }
auto x = static_cast<int>(read_unsigned(is, std::max(m, 1u), M));
if (!is.fail())
{
@@ -6526,7 +6529,14 @@ read(std::basic_istream<CharT, Traits>& is, int a0,
Args&& ...args)
*e++ = static_cast<CharT>(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 +6602,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const
CharT* fmt,
CONSTDATA int not_a_year = numeric_limits<short>::min();
CONSTDATA int not_a_2digit_year = 100;
- CONSTDATA int not_a_century = not_a_year / 100;
+ CONSTDATA int not_a_century = numeric_limits<int>::min();
CONSTDATA int not_a_month = 0;
CONSTDATA int not_a_day = 0;
CONSTDATA int not_a_hour = numeric_limits<int>::min();
@@ -7519,7 +7529,12 @@ from_stream(std::basic_istream<CharT, Traits>& is, const
CharT* fmt,
{
auto c = static_cast<char>(Traits::to_char_type(ic));
if (c == '-')
+ {
neg = true;
+ (void)is.get();
+ }
+ else if (c == '+')
+ (void)is.get();
}
if (modified == CharT{})
{
@@ -7735,9 +7750,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const
CharT* fmt,
year_month_day ymd_trial = sys_days(year{Y}/January/Sunday[1])
+
weeks{U-1} +
(weekday{static_cast<unsigned>(wd)}
- Sunday);
- if (Y == not_a_year)
- Y = static_cast<int>(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<int>(static_cast<unsigned>(ymd_trial.month()));
@@ -7754,9 +7767,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const
CharT* fmt,
year_month_day ymd_trial = sys_days(year{Y}/January/Monday[1])
+
weeks{W-1} +
(weekday{static_cast<unsigned>(wd)}
- Monday);
- if (Y == not_a_year)
- Y = static_cast<int>(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<int>(static_cast<unsigned>(ymd_trial.month()));
diff --git a/cpp/src/arrow/vendored/datetime/tz.cpp
b/cpp/src/arrow/vendored/datetime/tz.cpp
index e94c1bc8ae..44c627775f 100644
--- a/cpp/src/arrow/vendored/datetime/tz.cpp
+++ b/cpp/src/arrow/vendored/datetime/tz.cpp
@@ -96,6 +96,10 @@
# define TARGET_OS_SIMULATOR 0
#endif
+#if defined(ANDROID) || defined(__ANDROID__)
+#include <sys/system_properties.h>
+#endif
+
#if USE_OS_TZDB
# include <dirent.h>
#endif
@@ -2709,7 +2713,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 +2739,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 +3720,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 +3788,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 +3815,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 +4101,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.
}
{
diff --git a/cpp/src/arrow/vendored/datetime/tz.h
b/cpp/src/arrow/vendored/datetime/tz.h
index 467db6d199..df6d1a851a 100644
--- a/cpp/src/arrow/vendored/datetime/tz.h
+++ b/cpp/src/arrow/vendored/datetime/tz.h
@@ -239,8 +239,8 @@ nonexistent_local_time::make_msg(local_time<Duration> 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();
}
diff --git a/cpp/src/arrow/vendored/datetime/tz_private.h
b/cpp/src/arrow/vendored/datetime/tz_private.h
index 6b7a91493e..a6bb8fd30a 100644
--- a/cpp/src/arrow/vendored/datetime/tz_private.h
+++ b/cpp/src/arrow/vendored/datetime/tz_private.h
@@ -291,8 +291,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);