From 4491d606df34c44efda47b6d17b605262f17e182 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 21 Jun 2018 12:55:12 -0700 Subject: Export of internal Abseil changes. -- 70f43a482d7d4ae4a255f17ca02b0106653dd600 by Shaindel Schwartz : Internal change PiperOrigin-RevId: 201571193 -- 93e6e9c2e683158be49d9dd1f5cb1a91d0c0f556 by Abseil Team : Internal change. PiperOrigin-RevId: 201567108 -- fbd8ee94fbe9f2448e5adf5e88706f9c8216048f by Juemin Yang : str_format release PiperOrigin-RevId: 201565129 -- 387faa301555a8a888c4429df52734aa806dca46 by Abseil Team : Adds a defaulted allocator parameter to the size_type constructor of InlinedVector PiperOrigin-RevId: 201558711 -- 39b15ea2c68d7129d70cbde7e71af900032595ec by Matt Calabrese : Update the variant implementation to eliminate unnecessary checking on alternative access when the index is known or required to be correct. PiperOrigin-RevId: 201529535 -- adab77f1f7bb363aa534297f22aae2b0f08889ea by Abseil Team : Import of CCTZ from GitHub. PiperOrigin-RevId: 201458388 -- a701dc0ba62e3cadf0de14203415b91df4ee8151 by Greg Falcon : Internal cleanup PiperOrigin-RevId: 201394836 -- 8a7191410b8f440fdfa27f722ff05e451502ab61 by Abseil Team : Import of CCTZ from GitHub. PiperOrigin-RevId: 201369269 GitOrigin-RevId: 70f43a482d7d4ae4a255f17ca02b0106653dd600 Change-Id: I8ab073b30b4e27405a3b6da2c826bb4f3f0b9af6 --- absl/time/internal/cctz/src/time_zone_libc.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'absl/time/internal/cctz/src/time_zone_libc.cc') diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc index b0b56a52..1d727bde 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/absl/time/internal/cctz/src/time_zone_libc.cc @@ -91,7 +91,7 @@ TimeZoneLibC::TimeZoneLibC(const std::string& name) : local_(name == "localtime") {} time_zone::absolute_lookup TimeZoneLibC::BreakTime( - const time_point& tp) const { + const time_point& tp) const { time_zone::absolute_lookup al; std::time_t t = ToUnixSeconds(tp); std::tm tm; @@ -143,11 +143,11 @@ std::string TimeZoneLibC::Description() const { return local_ ? "localtime" : "UTC"; } -bool TimeZoneLibC::NextTransition(time_point* tp) const { +bool TimeZoneLibC::NextTransition(time_point* tp) const { return false; } -bool TimeZoneLibC::PrevTransition(time_point* tp) const { +bool TimeZoneLibC::PrevTransition(time_point* tp) const { return false; } -- cgit v1.2.3 From 134496a31d8b324f762de3bee9a002658c984456 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 29 Jun 2018 14:00:35 -0700 Subject: Export of internal Abseil changes. -- aa9e2bff92652605b8244677058be787c872f99c by Abseil Team : Import of CCTZ from GitHub. PiperOrigin-RevId: 202702969 -- d26c857c203589892a84bc44d789f2a15a60f234 by Abseil Team : Cleans up the FixedArray code (formatting, renames, etc) without changing the functionality PiperOrigin-RevId: 202538159 GitOrigin-RevId: aa9e2bff92652605b8244677058be787c872f99c Change-Id: I6561257232c6cc8e1cbf51d7e26bae5f8760551e --- absl/container/fixed_array.h | 233 ++++++++++----------- absl/time/internal/cctz/include/cctz/time_zone.h | 77 ++++++- .../internal/cctz/include/cctz/zone_info_source.h | 5 + absl/time/internal/cctz/src/cctz_benchmark.cc | 14 +- absl/time/internal/cctz/src/time_zone_format.cc | 3 + .../internal/cctz/src/time_zone_format_test.cc | 25 ++- absl/time/internal/cctz/src/time_zone_if.h | 8 +- absl/time/internal/cctz/src/time_zone_impl.cc | 9 - absl/time/internal/cctz/src/time_zone_impl.h | 38 ++-- absl/time/internal/cctz/src/time_zone_info.cc | 74 ++++--- absl/time/internal/cctz/src/time_zone_info.h | 8 +- absl/time/internal/cctz/src/time_zone_libc.cc | 16 +- absl/time/internal/cctz/src/time_zone_libc.h | 7 +- absl/time/internal/cctz/src/time_zone_lookup.cc | 33 ++- .../internal/cctz/src/time_zone_lookup_test.cc | 155 ++++++++++---- absl/time/internal/cctz/src/zone_info_source.cc | 1 + 16 files changed, 448 insertions(+), 258 deletions(-) (limited to 'absl/time/internal/cctz/src/time_zone_libc.cc') diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h index 990b65dd..62600df0 100644 --- a/absl/container/fixed_array.h +++ b/absl/container/fixed_array.h @@ -1,4 +1,4 @@ -// Copyright 2017 The Abseil Authors. +// Copyright 2018 The Abseil Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -57,13 +57,13 @@ constexpr static auto kFixedArrayUseDefault = static_cast(-1); // FixedArray // ----------------------------------------------------------------------------- // -// A `FixedArray` provides a run-time fixed-size array, allocating small arrays -// inline for efficiency and correctness. +// A `FixedArray` provides a run-time fixed-size array, allocating a small array +// inline for efficiency. // // Most users should not specify an `inline_elements` argument and let -// `FixedArray<>` automatically determine the number of elements +// `FixedArray` automatically determine the number of elements // to store inline based on `sizeof(T)`. If `inline_elements` is specified, the -// `FixedArray<>` implementation will inline arrays of +// `FixedArray` implementation will use inline storage for arrays with a // length <= `inline_elements`. // // Note that a `FixedArray` constructed with a `size_type` argument will @@ -84,15 +84,12 @@ class FixedArray { // std::iterator_traits isn't guaranteed to be SFINAE-friendly until C++17, // but this seems to be mostly pedantic. - template - using EnableIfForwardIterator = typename std::enable_if< - std::is_convertible< - typename std::iterator_traits::iterator_category, - std::forward_iterator_tag>::value, - int>::type; + template + using EnableIfForwardIterator = absl::enable_if_t::iterator_category, + std::forward_iterator_tag>::value>; public: - // For playing nicely with stl: using value_type = T; using iterator = T*; using const_iterator = const T*; @@ -114,40 +111,38 @@ class FixedArray { : FixedArray(other.begin(), other.end()) {} FixedArray(FixedArray&& other) noexcept( - // clang-format off - absl::allocator_is_nothrow>::value && - // clang-format on - std::is_nothrow_move_constructible::value) + absl::conjunction>, + std::is_nothrow_move_constructible>::value) : FixedArray(std::make_move_iterator(other.begin()), std::make_move_iterator(other.end())) {} // Creates an array object that can store `n` elements. // Note that trivially constructible elements will be uninitialized. - explicit FixedArray(size_type n) : rep_(n) { - absl::memory_internal::uninitialized_default_construct_n(rep_.begin(), + explicit FixedArray(size_type n) : storage_(n) { + absl::memory_internal::uninitialized_default_construct_n(storage_.begin(), size()); } // Creates an array initialized with `n` copies of `val`. - FixedArray(size_type n, const value_type& val) : rep_(n) { + FixedArray(size_type n, const value_type& val) : storage_(n) { std::uninitialized_fill_n(data(), size(), val); } // Creates an array initialized with the elements from the input // range. The array's size will always be `std::distance(first, last)`. - // REQUIRES: Iter must be a forward_iterator or better. - template = 0> - FixedArray(Iter first, Iter last) : rep_(std::distance(first, last)) { + // REQUIRES: Iterator must be a forward_iterator or better. + template * = nullptr> + FixedArray(Iterator first, Iterator last) + : storage_(std::distance(first, last)) { std::uninitialized_copy(first, last, data()); } - // Creates the array from an initializer_list. - FixedArray(std::initializer_list init_list) + FixedArray(std::initializer_list init_list) : FixedArray(init_list.begin(), init_list.end()) {} ~FixedArray() noexcept { - for (Holder* cur = rep_.begin(); cur != rep_.end(); ++cur) { - cur->~Holder(); + for (const StorageElement& cur : storage_) { + cur.~StorageElement(); } } @@ -159,7 +154,7 @@ class FixedArray { // FixedArray::size() // // Returns the length of the fixed array. - size_type size() const { return rep_.size(); } + size_type size() const { return storage_.size(); } // FixedArray::max_size() // @@ -184,12 +179,12 @@ class FixedArray { // // Returns a const T* pointer to elements of the `FixedArray`. This pointer // can be used to access (but not modify) the contained elements. - const_pointer data() const { return AsValue(rep_.begin()); } + const_pointer data() const { return AsValueType(storage_.begin()); } // Overload of FixedArray::data() to return a T* pointer to elements of the // fixed array. This pointer can be used to access and modify the contained // elements. - pointer data() { return AsValue(rep_.begin()); } + pointer data() { return AsValueType(storage_.begin()); } // FixedArray::operator[] // @@ -309,7 +304,7 @@ class FixedArray { // FixedArray::fill() // // Assigns the given `value` to all elements in the fixed array. - void fill(const T& value) { std::fill(begin(), end(), value); } + void fill(const value_type& val) { std::fill(begin(), end(), val); } // Relational operators. Equality operators are elementwise using // `operator==`, while order operators order FixedArrays lexicographically. @@ -339,18 +334,18 @@ class FixedArray { } private: - // Holder + // StorageElement // - // Wrapper for holding elements of type T for both the case where T is a - // C-style array type and the general case where it is not. This is needed for - // construction and destruction of the entire array regardless of how many - // dimensions it has. + // For FixedArrays with a C-style-array value_type, StorageElement is a POD + // wrapper struct called StorageElementWrapper that holds the value_type + // instance inside. This is needed for construction and destruction of the + // entire array regardless of how many dimensions it has. For all other cases, + // StorageElement is just an alias of value_type. // - // Maintainer's Note: The simpler solution would be to simply wrap T in a - // struct whether it's an array or not: 'struct Holder { T v; };', but - // that causes some paranoid diagnostics to misfire about uses of data(), - // believing that 'data()' (aka '&rep_.begin().v') is a pointer to a single - // element, rather than the packed array that it really is. + // Maintainer's Note: The simpler solution would be to simply wrap value_type + // in a struct whether it's an array or not. That causes some paranoid + // diagnostics to misfire, believing that 'data()' returns a pointer to a + // single element, rather than the packed array that it really is. // e.g.: // // FixedArray buf(1); @@ -362,115 +357,95 @@ class FixedArray { template , size_t InnerN = std::extent::value> - struct ArrayHolder { + struct StorageElementWrapper { InnerT array[InnerN]; }; - using Holder = absl::conditional_t::value, - ArrayHolder, value_type>; + using StorageElement = + absl::conditional_t::value, + StorageElementWrapper, value_type>; - static_assert(sizeof(Holder) == sizeof(value_type), ""); - static_assert(alignof(Holder) == alignof(value_type), ""); - - static pointer AsValue(pointer ptr) { return ptr; } - static pointer AsValue(ArrayHolder* ptr) { + static pointer AsValueType(pointer ptr) { return ptr; } + static pointer AsValueType(StorageElementWrapper* ptr) { return std::addressof(ptr->array); } - // InlineSpace - // - // Allocate some space, not an array of elements of type T, so that we can - // skip calling the T constructors and destructors for space we never use. - // How many elements should we store inline? - // a. If not specified, use a default of kInlineBytesDefault bytes (This is - // currently 256 bytes, which seems small enough to not cause stack overflow - // or unnecessary stack pollution, while still allowing stack allocation for - // reasonably long character arrays). - // b. Never use 0 length arrays (not ISO C++) - // - template - class InlineSpace { - public: - Holder* data() { return reinterpret_cast(space_.data()); } - void AnnotateConstruct(size_t n) const { Annotate(n, true); } - void AnnotateDestruct(size_t n) const { Annotate(n, false); } + static_assert(sizeof(StorageElement) == sizeof(value_type), ""); + static_assert(alignof(StorageElement) == alignof(value_type), ""); - private: -#ifndef ADDRESS_SANITIZER - void Annotate(size_t, bool) const { } -#else - void Annotate(size_t n, bool creating) const { - if (!n) return; - const void* bot = &left_redzone_; - const void* beg = space_.data(); - const void* end = space_.data() + n; - const void* top = &right_redzone_ + 1; - // args: (beg, end, old_mid, new_mid) - if (creating) { - ANNOTATE_CONTIGUOUS_CONTAINER(beg, top, top, end); - ANNOTATE_CONTIGUOUS_CONTAINER(bot, beg, beg, bot); - } else { - ANNOTATE_CONTIGUOUS_CONTAINER(beg, top, end, top); - ANNOTATE_CONTIGUOUS_CONTAINER(bot, beg, bot, beg); - } + struct NonEmptyInlinedStorage { + using StorageElementBuffer = + absl::aligned_storage_t; + StorageElement* data() { + return reinterpret_cast(inlined_storage_.data()); } + +#ifdef ADDRESS_SANITIZER + void* RedzoneBegin() { return &redzone_begin_; } + void* RedzoneEnd() { return &redzone_end_ + 1; } #endif // ADDRESS_SANITIZER - using Buffer = - typename std::aligned_storage::type; + void AnnotateConstruct(size_t); + void AnnotateDestruct(size_t); - ADDRESS_SANITIZER_REDZONE(left_redzone_); - std::array space_; - ADDRESS_SANITIZER_REDZONE(right_redzone_); + ADDRESS_SANITIZER_REDZONE(redzone_begin_); + std::array inlined_storage_; + ADDRESS_SANITIZER_REDZONE(redzone_end_); }; - // specialization when N = 0. - template - class InlineSpace<0, U> { - public: - Holder* data() { return nullptr; } - void AnnotateConstruct(size_t) const {} - void AnnotateDestruct(size_t) const {} + struct EmptyInlinedStorage { + StorageElement* data() { return nullptr; } + void AnnotateConstruct(size_t) {} + void AnnotateDestruct(size_t) {} }; - // Rep + using InlinedStorage = + absl::conditional_t; + + // Storage // - // An instance of Rep manages the inline and out-of-line memory for FixedArray + // An instance of Storage manages the inline and out-of-line memory for + // instances of FixedArray. This guarantees that even when construction of + // individual elements fails in the FixedArray constructor body, the + // destructor for Storage will still be called and out-of-line memory will be + // properly deallocated. // - class Rep : public InlineSpace { + class Storage : public InlinedStorage { public: - explicit Rep(size_type n) : n_(n), p_(MakeHolder(n)) {} - - ~Rep() noexcept { - if (IsAllocated(size())) { - std::allocator().deallocate(p_, n_); - } else { + explicit Storage(size_type n) : data_(CreateStorage(n)), size_(n) {} + ~Storage() noexcept { + if (UsingInlinedStorage(size())) { this->AnnotateDestruct(size()); + } else { + std::allocator().deallocate(begin(), size()); } } - Holder* begin() const { return p_; } - Holder* end() const { return p_ + n_; } - size_type size() const { return n_; } + + size_type size() const { return size_; } + StorageElement* begin() const { return data_; } + StorageElement* end() const { return begin() + size(); } private: - Holder* MakeHolder(size_type n) { - if (IsAllocated(n)) { - return std::allocator().allocate(n); - } else { + static bool UsingInlinedStorage(size_type n) { + return n <= inline_elements; + } + + StorageElement* CreateStorage(size_type n) { + if (UsingInlinedStorage(n)) { this->AnnotateConstruct(n); - return this->data(); + return InlinedStorage::data(); + } else { + return std::allocator().allocate(n); } } - bool IsAllocated(size_type n) const { return n > inline_elements; } - - const size_type n_; - Holder* const p_; + StorageElement* const data_; + const size_type size_; }; - - // Data members - Rep rep_; + const Storage storage_; }; template @@ -479,5 +454,25 @@ constexpr size_t FixedArray::inline_elements; template constexpr size_t FixedArray::kInlineBytesDefault; +template +void FixedArray::NonEmptyInlinedStorage::AnnotateConstruct(size_t n) { +#ifdef ADDRESS_SANITIZER + if (!n) return; + ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(), data() + n); + ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(), RedzoneBegin()); +#endif // ADDRESS_SANITIZER + static_cast(n); // Mark used when not in asan mode +} + +template +void FixedArray::NonEmptyInlinedStorage::AnnotateDestruct(size_t n) { +#ifdef ADDRESS_SANITIZER + if (!n) return; + ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n, RedzoneEnd()); + ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(), data()); +#endif // ADDRESS_SANITIZER + static_cast(n); // Mark used when not in asan mode +} + } // namespace absl #endif // ABSL_CONTAINER_FIXED_ARRAY_H_ diff --git a/absl/time/internal/cctz/include/cctz/time_zone.h b/absl/time/internal/cctz/include/cctz/time_zone.h index 55804ba6..0b9764ea 100644 --- a/absl/time/internal/cctz/include/cctz/time_zone.h +++ b/absl/time/internal/cctz/include/cctz/time_zone.h @@ -119,7 +119,7 @@ class time_zone { // of the given civil-time argument, and the pre, trans, and post // members will give the absolute time answers using the pre-transition // offset, the transition point itself, and the post-transition offset, - // respectively (all three times are equal if kind == UNIQUE). If any + // respectively (all three times are equal if kind == UNIQUE). If any // of these three absolute times is outside the representable range of a // time_point the field is set to its maximum/minimum value. // @@ -159,17 +159,79 @@ class time_zone { }; civil_lookup lookup(const civil_second& cs) const; + // Finds the time of the next/previous offset change in this time zone. + // + // By definition, next_transition(tp, &trans) returns false when tp has + // its maximum value, and prev_transition(tp, &trans) returns false + // when tp has its minimum value. If the zone has no transitions, the + // result will also be false no matter what the argument. + // + // Otherwise, when tp has its minimum value, next_transition(tp, &trans) + // returns true and sets trans to the first recorded transition. Chains + // of calls to next_transition()/prev_transition() will eventually return + // false, but it is unspecified exactly when next_transition(tp, &trans) + // jumps to false, or what time is set by prev_transition(tp, &trans) for + // a very distant tp. + // + // Note: Enumeration of time-zone transitions is for informational purposes + // only. Modern time-related code should not care about when offset changes + // occur. + // + // Example: + // cctz::time_zone nyc; + // if (!cctz::load_time_zone("America/New_York", &nyc)) { ... } + // const auto now = std::chrono::system_clock::now(); + // auto tp = cctz::time_point::min(); + // cctz::time_zone::civil_transition trans; + // while (tp <= now && nyc.next_transition(tp, &trans)) { + // // transition: trans.from -> trans.to + // tp = nyc.lookup(trans.to).trans; + // } + struct civil_transition { + civil_second from; // the civil time we jump from + civil_second to; // the civil time we jump to + }; + bool next_transition(const time_point& tp, + civil_transition* trans) const; + template + bool next_transition(const time_point& tp, + civil_transition* trans) const { + return next_transition(detail::split_seconds(tp).first, trans); + } + bool prev_transition(const time_point& tp, + civil_transition* trans) const; + template + bool prev_transition(const time_point& tp, + civil_transition* trans) const { + return prev_transition(detail::split_seconds(tp).first, trans); + } + + // version() and description() provide additional information about the + // time zone. The content of each of the returned strings is unspecified, + // however, when the IANA Time Zone Database is the underlying data source + // the version() std::string will be in the familar form (e.g, "2018e") or + // empty when unavailable. + // + // Note: These functions are for informational or testing purposes only. + std::string version() const; // empty when unknown + std::string description() const; + + // Relational operators. + friend bool operator==(time_zone lhs, time_zone rhs) { + return &lhs.effective_impl() == &rhs.effective_impl(); + } + friend bool operator!=(time_zone lhs, time_zone rhs) { + return !(lhs == rhs); + } + class Impl; private: explicit time_zone(const Impl* impl) : impl_(impl) {} + const Impl& effective_impl() const; // handles implicit UTC const Impl* impl_; }; -// Relational operators. -bool operator==(time_zone lhs, time_zone rhs); -inline bool operator!=(time_zone lhs, time_zone rhs) { return !(lhs == rhs); } - // Loads the named time zone. May perform I/O on the initial load. // If the name is invalid, or some other kind of error occurs, returns // false and "*tz" is set to the UTC time zone. @@ -184,6 +246,7 @@ time_zone utc_time_zone(); time_zone fixed_time_zone(const seconds& offset); // Returns a time zone representing the local time zone. Falls back to UTC. +// Note: local_time_zone.name() may only be something like "localtime". time_zone local_time_zone(); // Returns the civil time (cctz::civil_second) within the given time zone at @@ -227,7 +290,7 @@ bool parse(const std::string&, const std::string&, const time_zone&, // - %E*f - Fractional seconds with full precision (a literal '*') // - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999) // -// Note that %E0S behaves like %S, and %E0f produces no characters. In +// Note that %E0S behaves like %S, and %E0f produces no characters. In // contrast %E*f always produces at least one digit, which may be '0'. // // Note that %Y produces as many characters as it takes to fully render the @@ -254,7 +317,7 @@ inline std::string format(const std::string& fmt, const time_point& tp, // Parses an input std::string according to the provided format std::string and // returns the corresponding time_point. Uses strftime()-like formatting // options, with the same extensions as cctz::format(), but with the -// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez +// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez // and %E*z also accept the same inputs. // // %Y consumes as many numeric characters as it can, so the matching data diff --git a/absl/time/internal/cctz/include/cctz/zone_info_source.h b/absl/time/internal/cctz/include/cctz/zone_info_source.h index 4d9d8f87..20a76979 100644 --- a/absl/time/internal/cctz/include/cctz/zone_info_source.h +++ b/absl/time/internal/cctz/include/cctz/zone_info_source.h @@ -31,6 +31,11 @@ class ZoneInfoSource { virtual std::size_t Read(void* ptr, std::size_t size) = 0; // like fread() virtual int Skip(std::size_t offset) = 0; // like fseek() + + // Until the zoneinfo data supports versioning information, we provide + // a way for a ZoneInfoSource to indicate it out-of-band. The default + // implementation returns an empty std::string. + virtual std::string Version() const; }; } // namespace cctz diff --git a/absl/time/internal/cctz/src/cctz_benchmark.cc b/absl/time/internal/cctz/src/cctz_benchmark.cc index f13cb4ee..c97df78c 100644 --- a/absl/time/internal/cctz/src/cctz_benchmark.cc +++ b/absl/time/internal/cctz/src/cctz_benchmark.cc @@ -754,23 +754,21 @@ void BM_Zone_LoadAllTimeZonesCached(benchmark::State& state) { } BENCHMARK(BM_Zone_LoadAllTimeZonesCached); -void BM_Zone_TimeZoneImplGetImplicit(benchmark::State& state) { +void BM_Zone_TimeZoneEqualityImplicit(benchmark::State& state) { cctz::time_zone tz; // implicit UTC - cctz::time_zone::Impl::get(tz); while (state.KeepRunning()) { - cctz::time_zone::Impl::get(tz); + benchmark::DoNotOptimize(tz == tz); } } -BENCHMARK(BM_Zone_TimeZoneImplGetImplicit); +BENCHMARK(BM_Zone_TimeZoneEqualityImplicit); -void BM_Zone_TimeZoneImplGetExplicit(benchmark::State& state) { +void BM_Zone_TimeZoneEqualityExplicit(benchmark::State& state) { cctz::time_zone tz = cctz::utc_time_zone(); // explicit UTC - cctz::time_zone::Impl::get(tz); while (state.KeepRunning()) { - cctz::time_zone::Impl::get(tz); + benchmark::DoNotOptimize(tz == tz); } } -BENCHMARK(BM_Zone_TimeZoneImplGetExplicit); +BENCHMARK(BM_Zone_TimeZoneEqualityExplicit); void BM_Zone_UTCTimeZone(benchmark::State& state) { cctz::time_zone tz; diff --git a/absl/time/internal/cctz/src/time_zone_format.cc b/absl/time/internal/cctz/src/time_zone_format.cc index 592ab7d3..1b023848 100644 --- a/absl/time/internal/cctz/src/time_zone_format.cc +++ b/absl/time/internal/cctz/src/time_zone_format.cc @@ -141,6 +141,9 @@ char* Format02d(char* ep, int v) { // Formats a UTC offset, like +00:00. char* FormatOffset(char* ep, int offset, const char* mode) { + // TODO: Follow the RFC3339 "Unknown Local Offset Convention" and + // generate a "negative zero" when we're formatting a zero offset + // as the result of a failed load_time_zone(). char sign = '+'; if (offset < 0) { offset = -offset; // bounded by 24h so no overflow diff --git a/absl/time/internal/cctz/src/time_zone_format_test.cc b/absl/time/internal/cctz/src/time_zone_format_test.cc index 33c23984..a90dda76 100644 --- a/absl/time/internal/cctz/src/time_zone_format_test.cc +++ b/absl/time/internal/cctz/src/time_zone_format_test.cc @@ -64,6 +64,17 @@ void TestFormatSpecifier(time_point tp, time_zone tz, const std::string& fmt, EXPECT_EQ("xxx " + ans + " yyy", format("xxx " + fmt + " yyy", tp, tz)); } +// These tests sometimes run on platforms that have zoneinfo data so old +// that the transition we are attempting to check does not exist, most +// notably Android emulators. Fortunately, AndroidZoneInfoSource supports +// time_zone::version() so, in cases where we've learned that it matters, +// we can make the check conditionally. +int VersionCmp(time_zone tz, const std::string& target) { + std::string version = tz.version(); + if (version.empty() && !target.empty()) return 1; // unknown > known + return version.compare(target); +} + } // namespace // @@ -453,8 +464,8 @@ TEST(Format, ExtendedSecondOffset) { EXPECT_TRUE(load_time_zone("America/New_York", &tz)); tp = convert(civil_second(1883, 11, 18, 16, 59, 59), utc); if (tz.lookup(tp).offset == -5 * 60 * 60) { - // We're likely dealing with zoneinfo that doesn't support really old - // timestamps, so America/New_York never looks to be on local mean time. + // It looks like the tzdata is only 32 bit (probably macOS), + // which bottoms out at 1901-12-13T20:45:52+00:00. } else { TestFormatSpecifier(tp, tz, "%E*z", "-04:56:02"); TestFormatSpecifier(tp, tz, "%Ez", "-04:56"); @@ -464,12 +475,10 @@ TEST(Format, ExtendedSecondOffset) { EXPECT_TRUE(load_time_zone("Europe/Moscow", &tz)); tp = convert(civil_second(1919, 6, 30, 23, 59, 59), utc); -#if defined(__ANDROID__) && __ANDROID_API__ < 25 - // Only Android 'N'.1 and beyond have this tz2016g transition. -#else - TestFormatSpecifier(tp, tz, "%E*z", "+04:31:19"); - TestFormatSpecifier(tp, tz, "%Ez", "+04:31"); -#endif + if (VersionCmp(tz, "2016g") >= 0) { + TestFormatSpecifier(tp, tz, "%E*z", "+04:31:19"); + TestFormatSpecifier(tp, tz, "%Ez", "+04:31"); + } tp += chrono::seconds(1); TestFormatSpecifier(tp, tz, "%E*z", "+04:00:00"); } diff --git a/absl/time/internal/cctz/src/time_zone_if.h b/absl/time/internal/cctz/src/time_zone_if.h index f10972ae..e4bd3866 100644 --- a/absl/time/internal/cctz/src/time_zone_if.h +++ b/absl/time/internal/cctz/src/time_zone_if.h @@ -41,9 +41,13 @@ class TimeZoneIf { virtual time_zone::civil_lookup MakeTime( const civil_second& cs) const = 0; + virtual bool NextTransition(const time_point& tp, + time_zone::civil_transition* trans) const = 0; + virtual bool PrevTransition(const time_point& tp, + time_zone::civil_transition* trans) const = 0; + + virtual std::string Version() const = 0; virtual std::string Description() const = 0; - virtual bool NextTransition(time_point* tp) const = 0; - virtual bool PrevTransition(time_point* tp) const = 0; protected: TimeZoneIf() {} diff --git a/absl/time/internal/cctz/src/time_zone_impl.cc b/absl/time/internal/cctz/src/time_zone_impl.cc index eb96c7ef..3062ccd3 100644 --- a/absl/time/internal/cctz/src/time_zone_impl.cc +++ b/absl/time/internal/cctz/src/time_zone_impl.cc @@ -83,15 +83,6 @@ bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) { return impl != utc_impl; } -const time_zone::Impl& time_zone::Impl::get(const time_zone& tz) { - if (tz.impl_ == nullptr) { - // Dereferencing an implicit-UTC time_zone is expected to be - // rare, so we don't mind paying a small synchronization cost. - return *UTCImpl(); - } - return *tz.impl_; -} - void time_zone::Impl::ClearTimeZoneMapTestOnly() { std::lock_guard lock(time_zone_mutex); if (time_zone_map != nullptr) { diff --git a/absl/time/internal/cctz/src/time_zone_impl.h b/absl/time/internal/cctz/src/time_zone_impl.h index fef7f226..14965ef5 100644 --- a/absl/time/internal/cctz/src/time_zone_impl.h +++ b/absl/time/internal/cctz/src/time_zone_impl.h @@ -37,15 +37,15 @@ class time_zone::Impl { // some other kind of error occurs. Note that loading "UTC" never fails. static bool LoadTimeZone(const std::string& name, time_zone* tz); - // Dereferences the time_zone to obtain its Impl. - static const time_zone::Impl& get(const time_zone& tz); - // Clears the map of cached time zones. Primarily for use in benchmarks // that gauge the performance of loading/parsing the time-zone data. static void ClearTimeZoneMapTestOnly(); // The primary key is the time-zone ID (e.g., "America/New_York"). - const std::string& name() const { return name_; } + const std::string& Name() const { + // TODO: It would nice if the zoneinfo data included the zone name. + return name_; + } // Breaks a time_point down to civil-time components in this time zone. time_zone::absolute_lookup BreakTime(const time_point& tp) const { @@ -59,28 +59,22 @@ class time_zone::Impl { return zone_->MakeTime(cs); } - // Returns an implementation-specific description of this time zone. - std::string Description() const { return zone_->Description(); } - // Finds the time of the next/previous offset change in this time zone. - // - // By definition, NextTransition(&tp) returns false when tp has its - // maximum value, and PrevTransition(&tp) returns false when tp has its - // mimimum value. If the zone has no transitions, the result will also - // be false no matter what the argument. - // - // Otherwise, when tp has its mimimum value, NextTransition(&tp) returns - // true and sets tp to the first recorded transition. Chains of calls - // to NextTransition()/PrevTransition() will eventually return false, - // but it is unspecified exactly when NextTransition(&tp) jumps to false, - // or what time is set by PrevTransition(&tp) for a very distant tp. - bool NextTransition(time_point* tp) const { - return zone_->NextTransition(tp); + bool NextTransition(const time_point& tp, + time_zone::civil_transition* trans) const { + return zone_->NextTransition(tp, trans); } - bool PrevTransition(time_point* tp) const { - return zone_->PrevTransition(tp); + bool PrevTransition(const time_point& tp, + time_zone::civil_transition* trans) const { + return zone_->PrevTransition(tp, trans); } + // Returns an implementation-defined version std::string for this time zone. + std::string Version() const { return zone_->Version(); } + + // Returns an implementation-defined description of this time zone. + std::string Description() const { return zone_->Description(); } + private: explicit Impl(const std::string& name); static const Impl* UTCImpl(); diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc index cdd11810..bf73635d 100644 --- a/absl/time/internal/cctz/src/time_zone_info.cc +++ b/absl/time/internal/cctz/src/time_zone_info.cc @@ -186,14 +186,13 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) { tt.is_dst = false; tt.abbr_index = 0; - // We temporarily add some redundant, contemporary (2012 through 2021) + // We temporarily add some redundant, contemporary (2013 through 2023) // transitions for performance reasons. See TimeZoneInfo::LocalTime(). // TODO: Fix the performance issue and remove the extra transitions. transitions_.clear(); transitions_.reserve(12); for (const std::int_fast64_t unix_time : { -(1LL << 59), // BIG_BANG - 1325376000LL, // 2012-01-01T00:00:00+00:00 1356998400LL, // 2013-01-01T00:00:00+00:00 1388534400LL, // 2014-01-01T00:00:00+00:00 1420070400LL, // 2015-01-01T00:00:00+00:00 @@ -203,6 +202,8 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) { 1546300800LL, // 2019-01-01T00:00:00+00:00 1577836800LL, // 2020-01-01T00:00:00+00:00 1609459200LL, // 2021-01-01T00:00:00+00:00 + 1640995200LL, // 2022-01-01T00:00:00+00:00 + 1672531200LL, // 2023-01-01T00:00:00+00:00 2147483647LL, // 2^31 - 1 }) { Transition& tr(*transitions_.emplace(transitions_.end())); @@ -519,6 +520,13 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { // We don't check for EOF so that we're forwards compatible. + // If we did not find version information during the standard loading + // process (as of tzh_version '3' that is unsupported), then ask the + // ZoneInfoSource for any out-of-bound version std::string it may be privy to. + if (version_.empty()) { + version_ = zip->Version(); + } + // Trim redundant transitions. zic may have added these to work around // differences between the glibc and reference implementations (see // zic.c:dontmerge) and the Qt library (see zic.c:WORK_AROUND_QTBUG_53071). @@ -605,6 +613,10 @@ class FileZoneInfoSource : public ZoneInfoSource { if (rc == 0) len_ -= offset; return rc; } + std::string Version() const override { + // TODO: It would nice if the zoneinfo data included the tzdb version. + return std::string(); + } protected: explicit FileZoneInfoSource( @@ -654,14 +666,15 @@ std::unique_ptr FileZoneInfoSource::Open( return std::unique_ptr(new FileZoneInfoSource(fp, length)); } -#if defined(__ANDROID__) class AndroidZoneInfoSource : public FileZoneInfoSource { public: static std::unique_ptr Open(const std::string& name); + std::string Version() const override { return version_; } private: - explicit AndroidZoneInfoSource(FILE* fp, std::size_t len) - : FileZoneInfoSource(fp, len) {} + explicit AndroidZoneInfoSource(FILE* fp, std::size_t len, const char* vers) + : FileZoneInfoSource(fp, len), version_(vers) {} + std::string version_; }; std::unique_ptr AndroidZoneInfoSource::Open( @@ -669,6 +682,7 @@ std::unique_ptr AndroidZoneInfoSource::Open( // Use of the "file:" prefix is intended for testing purposes only. if (name.compare(0, 5, "file:") == 0) return Open(name.substr(5)); +#if defined(__ANDROID__) // See Android's libc/tzcode/bionic.cpp for additional information. for (const char* tzdata : {"/data/misc/zoneinfo/current/tzdata", "/system/usr/share/zoneinfo/tzdata"}) { @@ -678,6 +692,7 @@ std::unique_ptr AndroidZoneInfoSource::Open( char hbuf[24]; // covers header.zonetab_offset too if (fread(hbuf, 1, sizeof(hbuf), fp.get()) != sizeof(hbuf)) continue; if (strncmp(hbuf, "tzdata", 6) != 0) continue; + const char* vers = (hbuf[11] == '\0') ? hbuf + 6 : ""; const std::int_fast32_t index_offset = Decode32(hbuf + 12); const std::int_fast32_t data_offset = Decode32(hbuf + 16); if (index_offset < 0 || data_offset < index_offset) continue; @@ -698,13 +713,13 @@ std::unique_ptr AndroidZoneInfoSource::Open( if (strcmp(name.c_str(), ebuf) == 0) { if (fseek(fp.get(), static_cast(start), SEEK_SET) != 0) break; return std::unique_ptr(new AndroidZoneInfoSource( - fp.release(), static_cast(length))); + fp.release(), static_cast(length), vers)); } } } +#endif // __ANDROID__ return nullptr; } -#endif } // namespace @@ -722,9 +737,7 @@ bool TimeZoneInfo::Load(const std::string& name) { auto zip = cctz_extension::zone_info_source_factory( name, [](const std::string& name) -> std::unique_ptr { if (auto zip = FileZoneInfoSource::Open(name)) return zip; -#if defined(__ANDROID__) if (auto zip = AndroidZoneInfoSource::Open(name)) return zip; -#endif return nullptr; }); return zip != nullptr && Load(name, zip.get()); @@ -885,17 +898,20 @@ time_zone::civil_lookup TimeZoneInfo::MakeTime(const civil_second& cs) const { return MakeUnique(tr->unix_time + (cs - tr->civil_sec)); } +std::string TimeZoneInfo::Version() const { + return version_; +} + std::string TimeZoneInfo::Description() const { std::ostringstream oss; - // TODO: It would nice if the zoneinfo data included the zone name. - // TODO: It would nice if the zoneinfo data included the tzdb version. oss << "#trans=" << transitions_.size(); oss << " #types=" << transition_types_.size(); oss << " spec='" << future_spec_ << "'"; return oss.str(); } -bool TimeZoneInfo::NextTransition(time_point* tp) const { +bool TimeZoneInfo::NextTransition(const time_point& tp, + time_zone::civil_transition* trans) const { if (transitions_.empty()) return false; const Transition* begin = &transitions_[0]; const Transition* end = begin + transitions_.size(); @@ -904,22 +920,24 @@ bool TimeZoneInfo::NextTransition(time_point* tp) const { // really a sentinel, not a transition. See tz/zic.c. ++begin; } - std::int_fast64_t unix_time = ToUnixSeconds(*tp); + std::int_fast64_t unix_time = ToUnixSeconds(tp); const Transition target = { unix_time }; const Transition* tr = std::upper_bound(begin, end, target, Transition::ByUnixTime()); - if (tr != begin) { // skip no-op transitions - for (; tr != end; ++tr) { - if (!EquivTransitions(tr[-1].type_index, tr[0].type_index)) break; - } + for (; tr != end; ++tr) { // skip no-op transitions + std::uint_fast8_t prev_type_index = + (tr == begin) ? default_transition_type_ : tr[-1].type_index; + if (!EquivTransitions(prev_type_index, tr[0].type_index)) break; } // When tr == end we return false, ignoring future_spec_. if (tr == end) return false; - *tp = FromUnixSeconds(tr->unix_time); + trans->from = tr->prev_civil_sec + 1; + trans->to = tr->civil_sec; return true; } -bool TimeZoneInfo::PrevTransition(time_point* tp) const { +bool TimeZoneInfo::PrevTransition(const time_point& tp, + time_zone::civil_transition* trans) const { if (transitions_.empty()) return false; const Transition* begin = &transitions_[0]; const Transition* end = begin + transitions_.size(); @@ -928,11 +946,12 @@ bool TimeZoneInfo::PrevTransition(time_point* tp) const { // really a sentinel, not a transition. See tz/zic.c. ++begin; } - std::int_fast64_t unix_time = ToUnixSeconds(*tp); - if (FromUnixSeconds(unix_time) != *tp) { + std::int_fast64_t unix_time = ToUnixSeconds(tp); + if (FromUnixSeconds(unix_time) != tp) { if (unix_time == std::numeric_limits::max()) { if (end == begin) return false; // Ignore future_spec_. - *tp = FromUnixSeconds((--end)->unix_time); + trans->from = (--end)->prev_civil_sec + 1; + trans->to = end->civil_sec; return true; } unix_time += 1; // ceils @@ -940,14 +959,15 @@ bool TimeZoneInfo::PrevTransition(time_point* tp) const { const Transition target = { unix_time }; const Transition* tr = std::lower_bound(begin, end, target, Transition::ByUnixTime()); - if (tr != begin) { // skip no-op transitions - for (; tr - 1 != begin; --tr) { - if (!EquivTransitions(tr[-2].type_index, tr[-1].type_index)) break; - } + for (; tr != begin; --tr) { // skip no-op transitions + std::uint_fast8_t prev_type_index = + (tr - 1 == begin) ? default_transition_type_ : tr[-2].type_index; + if (!EquivTransitions(prev_type_index, tr[-1].type_index)) break; } // When tr == end we return the "last" transition, ignoring future_spec_. if (tr == begin) return false; - *tp = FromUnixSeconds((--tr)->unix_time); + trans->from = (--tr)->prev_civil_sec + 1; + trans->to = tr->civil_sec; return true; } diff --git a/absl/time/internal/cctz/src/time_zone_info.h b/absl/time/internal/cctz/src/time_zone_info.h index d28443e2..958e9b6b 100644 --- a/absl/time/internal/cctz/src/time_zone_info.h +++ b/absl/time/internal/cctz/src/time_zone_info.h @@ -74,9 +74,12 @@ class TimeZoneInfo : public TimeZoneIf { const time_point& tp) const override; time_zone::civil_lookup MakeTime( const civil_second& cs) const override; + bool NextTransition(const time_point& tp, + time_zone::civil_transition* trans) const override; + bool PrevTransition(const time_point& tp, + time_zone::civil_transition* trans) const override; + std::string Version() const override; std::string Description() const override; - bool NextTransition(time_point* tp) const override; - bool PrevTransition(time_point* tp) const override; private: struct Header { // counts of: @@ -114,6 +117,7 @@ class TimeZoneInfo : public TimeZoneIf { std::uint_fast8_t default_transition_type_; // for before first transition std::string abbreviations_; // all the NUL-terminated abbreviations + std::string version_; // the tzdata version if available std::string future_spec_; // for after the last zic transition bool extended_; // future_spec_ was used to generate transitions year_t last_year_; // the final year of the generated transitions diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc index 1d727bde..074c8d0a 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/absl/time/internal/cctz/src/time_zone_libc.cc @@ -139,16 +139,22 @@ time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const { return cl; } -std::string TimeZoneLibC::Description() const { - return local_ ? "localtime" : "UTC"; +bool TimeZoneLibC::NextTransition(const time_point& tp, + time_zone::civil_transition* trans) const { + return false; } -bool TimeZoneLibC::NextTransition(time_point* tp) const { +bool TimeZoneLibC::PrevTransition(const time_point& tp, + time_zone::civil_transition* trans) const { return false; } -bool TimeZoneLibC::PrevTransition(time_point* tp) const { - return false; +std::string TimeZoneLibC::Version() const { + return std::string(); // unknown +} + +std::string TimeZoneLibC::Description() const { + return local_ ? "localtime" : "UTC"; } } // namespace cctz diff --git a/absl/time/internal/cctz/src/time_zone_libc.h b/absl/time/internal/cctz/src/time_zone_libc.h index 4c64cd34..4e40c61a 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.h +++ b/absl/time/internal/cctz/src/time_zone_libc.h @@ -35,9 +35,12 @@ class TimeZoneLibC : public TimeZoneIf { const time_point& tp) const override; time_zone::civil_lookup MakeTime( const civil_second& cs) const override; + bool NextTransition(const time_point& tp, + time_zone::civil_transition* trans) const override; + bool PrevTransition(const time_point& tp, + time_zone::civil_transition* trans) const override; + std::string Version() const override; std::string Description() const override; - bool NextTransition(time_point* tp) const override; - bool PrevTransition(time_point* tp) const override; private: const bool local_; // localtime or UTC diff --git a/absl/time/internal/cctz/src/time_zone_lookup.cc b/absl/time/internal/cctz/src/time_zone_lookup.cc index 2f6cd98b..f2d151e4 100644 --- a/absl/time/internal/cctz/src/time_zone_lookup.cc +++ b/absl/time/internal/cctz/src/time_zone_lookup.cc @@ -61,20 +61,43 @@ int __system_property_get(const char* name, char* value) { #endif std::string time_zone::name() const { - return time_zone::Impl::get(*this).name(); + return effective_impl().Name(); } time_zone::absolute_lookup time_zone::lookup( const time_point& tp) const { - return time_zone::Impl::get(*this).BreakTime(tp); + return effective_impl().BreakTime(tp); } time_zone::civil_lookup time_zone::lookup(const civil_second& cs) const { - return time_zone::Impl::get(*this).MakeTime(cs); + return effective_impl().MakeTime(cs); } -bool operator==(time_zone lhs, time_zone rhs) { - return &time_zone::Impl::get(lhs) == &time_zone::Impl::get(rhs); +bool time_zone::next_transition(const time_point& tp, + civil_transition* trans) const { + return effective_impl().NextTransition(tp, trans); +} + +bool time_zone::prev_transition(const time_point& tp, + civil_transition* trans) const { + return effective_impl().PrevTransition(tp, trans); +} + +std::string time_zone::version() const { + return effective_impl().Version(); +} + +std::string time_zone::description() const { + return effective_impl().Description(); +} + +const time_zone::Impl& time_zone::effective_impl() const { + if (impl_ == nullptr) { + // Dereferencing an implicit-UTC time_zone is expected to be + // rare, so we don't mind paying a small synchronization cost. + return *time_zone::Impl::UTC().impl_; + } + return *impl_; } bool load_time_zone(const std::string& name, time_zone* tz) { diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc index cd9fc236..551292fb 100644 --- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc +++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc @@ -651,6 +651,17 @@ time_zone LoadZone(const std::string& name) { /* EXPECT_STREQ(zone, al.abbr); */ \ } while (0) +// These tests sometimes run on platforms that have zoneinfo data so old +// that the transition we are attempting to check does not exist, most +// notably Android emulators. Fortunately, AndroidZoneInfoSource supports +// time_zone::version() so, in cases where we've learned that it matters, +// we can make the check conditionally. +int VersionCmp(time_zone tz, const std::string& target) { + std::string version = tz.version(); + if (version.empty() && !target.empty()) return 1; // unknown > known + return version.compare(target); +} + } // namespace TEST(TimeZones, LoadZonesConcurrently) { @@ -981,6 +992,69 @@ TEST(MakeTime, SysSecondsLimits) { EXPECT_EQ(time_point::min(), tp); } +TEST(NextTransition, UTC) { + const auto tz = utc_time_zone(); + time_zone::civil_transition trans; + + auto tp = time_point::min(); + EXPECT_FALSE(tz.next_transition(tp, &trans)); + + tp = time_point::max(); + EXPECT_FALSE(tz.next_transition(tp, &trans)); +} + +TEST(PrevTransition, UTC) { + const auto tz = utc_time_zone(); + time_zone::civil_transition trans; + + auto tp = time_point::max(); + EXPECT_FALSE(tz.prev_transition(tp, &trans)); + + tp = time_point::min(); + EXPECT_FALSE(tz.prev_transition(tp, &trans)); +} + +TEST(NextTransition, AmericaNewYork) { + const auto tz = LoadZone("America/New_York"); + time_zone::civil_transition trans; + + auto tp = convert(civil_second(2018, 6, 30, 0, 0, 0), tz); + EXPECT_TRUE(tz.next_transition(tp, &trans)); + EXPECT_EQ(civil_second(2018, 11, 4, 2, 0, 0), trans.from); + EXPECT_EQ(civil_second(2018, 11, 4, 1, 0, 0), trans.to); + + tp = time_point::max(); + EXPECT_FALSE(tz.next_transition(tp, &trans)); + + tp = time_point::min(); + EXPECT_TRUE(tz.next_transition(tp, &trans)); + if (trans.from == civil_second(1918, 3, 31, 2, 0, 0)) { + // It looks like the tzdata is only 32 bit (probably macOS), + // which bottoms out at 1901-12-13T20:45:52+00:00. + EXPECT_EQ(civil_second(1918, 3, 31, 3, 0, 0), trans.to); + } else { + EXPECT_EQ(civil_second(1883, 11, 18, 12, 3, 58), trans.from); + EXPECT_EQ(civil_second(1883, 11, 18, 12, 0, 0), trans.to); + } +} + +TEST(PrevTransition, AmericaNewYork) { + const auto tz = LoadZone("America/New_York"); + time_zone::civil_transition trans; + + auto tp = convert(civil_second(2018, 6, 30, 0, 0, 0), tz); + EXPECT_TRUE(tz.prev_transition(tp, &trans)); + EXPECT_EQ(civil_second(2018, 3, 11, 2, 0, 0), trans.from); + EXPECT_EQ(civil_second(2018, 3, 11, 3, 0, 0), trans.to); + + tp = time_point::min(); + EXPECT_FALSE(tz.prev_transition(tp, &trans)); + + tp = time_point::max(); + EXPECT_TRUE(tz.prev_transition(tp, &trans)); + // We have a transition but we don't know which one. +} + TEST(TimeZoneEdgeCase, AmericaNewYork) { const time_zone tz = LoadZone("America/New_York"); @@ -1104,35 +1178,31 @@ TEST(TimeZoneEdgeCase, PacificApia) { TEST(TimeZoneEdgeCase, AfricaCairo) { const time_zone tz = LoadZone("Africa/Cairo"); -#if defined(__ANDROID__) && __ANDROID_API__ < 21 - // Only Android 'L' and beyond have this tz2014c transition. -#else - // An interesting case of midnight not existing. - // - // 1400191199 == Thu, 15 May 2014 23:59:59 +0200 (EET) - // 1400191200 == Fri, 16 May 2014 01:00:00 +0300 (EEST) - auto tp = convert(civil_second(2014, 5, 15, 23, 59, 59), tz); - ExpectTime(tp, tz, 2014, 5, 15, 23, 59, 59, 2 * 3600, false, "EET"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 2014, 5, 16, 1, 0, 0, 3 * 3600, true, "EEST"); -#endif + if (VersionCmp(tz, "2014c") >= 0) { + // An interesting case of midnight not existing. + // + // 1400191199 == Thu, 15 May 2014 23:59:59 +0200 (EET) + // 1400191200 == Fri, 16 May 2014 01:00:00 +0300 (EEST) + auto tp = convert(civil_second(2014, 5, 15, 23, 59, 59), tz); + ExpectTime(tp, tz, 2014, 5, 15, 23, 59, 59, 2 * 3600, false, "EET"); + tp += absl::time_internal::cctz::seconds(1); + ExpectTime(tp, tz, 2014, 5, 16, 1, 0, 0, 3 * 3600, true, "EEST"); + } } TEST(TimeZoneEdgeCase, AfricaMonrovia) { const time_zone tz = LoadZone("Africa/Monrovia"); -#if defined(__ANDROID__) && __ANDROID_API__ < 26 - // Only Android 'O' and beyond have this tz2017b transition. -#else - // Strange offset change -00:44:30 -> +00:00:00 (non-DST) - // - // 63593069 == Thu, 6 Jan 1972 23:59:59 -0044 (MMT) - // 63593070 == Fri, 7 Jan 1972 00:44:30 +0000 (GMT) - auto tp = convert(civil_second(1972, 1, 6, 23, 59, 59), tz); - ExpectTime(tp, tz, 1972, 1, 6, 23, 59, 59, -44.5 * 60, false, "MMT"); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 1972, 1, 7, 0, 44, 30, 0 * 60, false, "GMT"); -#endif + if (VersionCmp(tz, "2017b") >= 0) { + // Strange offset change -00:44:30 -> +00:00:00 (non-DST) + // + // 63593069 == Thu, 6 Jan 1972 23:59:59 -0044 (MMT) + // 63593070 == Fri, 7 Jan 1972 00:44:30 +0000 (GMT) + auto tp = convert(civil_second(1972, 1, 6, 23, 59, 59), tz); + ExpectTime(tp, tz, 1972, 1, 6, 23, 59, 59, -44.5 * 60, false, "MMT"); + tp += absl::time_internal::cctz::seconds(1); + ExpectTime(tp, tz, 1972, 1, 7, 0, 44, 30, 0 * 60, false, "GMT"); + } } TEST(TimeZoneEdgeCase, AmericaJamaica) { @@ -1144,28 +1214,29 @@ TEST(TimeZoneEdgeCase, AmericaJamaica) { const time_zone tz = LoadZone("America/Jamaica"); // Before the first transition. - auto tp = convert(civil_second(1889, 12, 31, 0, 0, 0), tz); -#if AMERICA_JAMAICA_PRE_1913_OFFSET_FIX - // Commit 907241e: Fix off-by-1 error for Jamaica and T&C before 1913. - // Until that commit has made its way into a full release we avoid the - // expectations on the -18430 offset below. TODO: Uncomment these. - ExpectTime(tp, tz, 1889, 12, 31, 0, 0, 0, -18430, false, - tz.lookup(tp).abbr); - - // Over the first (abbreviation-change only) transition. - // -2524503170 == Tue, 31 Dec 1889 23:59:59 -0507 (LMT) - // -2524503169 == Wed, 1 Jan 1890 00:00:00 -0507 (KMT) - tp = convert(civil_second(1889, 12, 31, 23, 59, 59), tz); - ExpectTime(tp, tz, 1889, 12, 31, 23, 59, 59, -18430, false, - tz.lookup(tp).abbr); - tp += absl::time_internal::cctz::seconds(1); - ExpectTime(tp, tz, 1890, 1, 1, 0, 0, 0, -18430, false, "KMT"); -#endif + if (!tz.version().empty() && VersionCmp(tz, "2018d") >= 0) { + // We avoid the expectations on the -18430 offset below unless we are + // certain we have commit 907241e (Fix off-by-1 error for Jamaica and + // T&C before 1913) from 2018d. TODO: Remove the "version() not empty" + // part when 2018d is generally available from /usr/share/zoneinfo. + auto tp = convert(civil_second(1889, 12, 31, 0, 0, 0), tz); + ExpectTime(tp, tz, 1889, 12, 31, 0, 0, 0, -18430, false, + tz.lookup(tp).abbr); + + // Over the first (abbreviation-change only) transition. + // -2524503170 == Tue, 31 Dec 1889 23:59:59 -0507 (LMT) + // -2524503169 == Wed, 1 Jan 1890 00:00:00 -0507 (KMT) + tp = convert(civil_second(1889, 12, 31, 23, 59, 59), tz); + ExpectTime(tp, tz, 1889, 12, 31, 23, 59, 59, -18430, false, + tz.lookup(tp).abbr); + tp += absl::time_internal::cctz::seconds(1); + ExpectTime(tp, tz, 1890, 1, 1, 0, 0, 0, -18430, false, "KMT"); + } // Over the last (DST) transition. // 436341599 == Sun, 30 Oct 1983 01:59:59 -0400 (EDT) // 436341600 == Sun, 30 Oct 1983 01:00:00 -0500 (EST) - tp = convert(civil_second(1983, 10, 30, 1, 59, 59), tz); + auto tp = convert(civil_second(1983, 10, 30, 1, 59, 59), tz); ExpectTime(tp, tz, 1983, 10, 30, 1, 59, 59, -4 * 3600, true, "EDT"); tp += absl::time_internal::cctz::seconds(1); ExpectTime(tp, tz, 1983, 10, 30, 1, 0, 0, -5 * 3600, false, "EST"); diff --git a/absl/time/internal/cctz/src/zone_info_source.cc b/absl/time/internal/cctz/src/zone_info_source.cc index ee7500b6..bf2d2d2d 100644 --- a/absl/time/internal/cctz/src/zone_info_source.cc +++ b/absl/time/internal/cctz/src/zone_info_source.cc @@ -20,6 +20,7 @@ namespace cctz { // Defined out-of-line to avoid emitting a weak vtable in all TUs. ZoneInfoSource::~ZoneInfoSource() {} +std::string ZoneInfoSource::Version() const { return std::string(); } } // namespace cctz } // namespace time_internal -- cgit v1.2.3 From a00bdd176d66ef0b417d9576052a19091fbdf891 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 12 Oct 2018 06:53:34 -0700 Subject: Export of internal Abseil changes. -- fa894a667a3bebbe479539c8d5e829beebf36c27 by Abseil Team : Import of CCTZ from GitHub. PiperOrigin-RevId: 216855907 -- 59e0a42fa9045eb164573b82ce625248bd9999f3 by Jon Cohen : Some edits to the documentation for absl::Hash as I was reading through it. Itemized changes: * implement -> implements for grammar * Fix an incomplete sentence * specify *any* type T as opposed to *a* type T ? this is just the language I tend to see for these sorts of concepts in math and makes it more clear that we?re talking about a set of all types T satisfying these constraints * add arguments to comine() and combine_contiguous() ? this was mostly because for hash_continuous there was a reference to `size` elements without any mention of what `size` was. PiperOrigin-RevId: 216766923 -- c2a744d0f70ec5a079c22502b7a7ca72805a29dc by Shaindel Schwartz : Remove unneeded include. PiperOrigin-RevId: 216703710 -- ad22fc4e3d236f7bd354b61e0fa37ea524a7cf5e by Shaindel Schwartz : Fix typos. PiperOrigin-RevId: 216699071 GitOrigin-RevId: fa894a667a3bebbe479539c8d5e829beebf36c27 Change-Id: I35c8d8be66043aad9f17bbb867e69acb770bd1b0 --- absl/container/flat_hash_map_test.cc | 2 +- absl/container/internal/hash_policy_traits.h | 2 +- absl/container/internal/raw_hash_set.h | 2 +- absl/container/internal/raw_hash_set_test.cc | 2 +- absl/hash/hash.h | 10 +++++----- absl/time/civil_time.h | 1 - absl/time/internal/cctz/src/time_zone_libc.cc | 2 +- absl/time/internal/cctz/src/time_zone_lookup_test.cc | 10 ++++++++++ 8 files changed, 20 insertions(+), 11 deletions(-) (limited to 'absl/time/internal/cctz/src/time_zone_libc.cc') diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc index 10a781ff..2c6f2515 100644 --- a/absl/container/flat_hash_map_test.cc +++ b/absl/container/flat_hash_map_test.cc @@ -94,7 +94,7 @@ TEST(FlatHashMap, IteratesMsan) { } } -// Demonstration of the "Lazy Key" pattern. This uses heterogenous insert to +// Demonstration of the "Lazy Key" pattern. This uses heterogeneous insert to // avoid creating expensive key elements when the item is already present in the // map. struct LazyInt { diff --git a/absl/container/internal/hash_policy_traits.h b/absl/container/internal/hash_policy_traits.h index 029e47e1..ace50a6c 100644 --- a/absl/container/internal/hash_policy_traits.h +++ b/absl/container/internal/hash_policy_traits.h @@ -84,7 +84,7 @@ struct hash_policy_traits { } // Transfers the `old_slot` to `new_slot`. Any memory allocated by the - // allocator inside `old_slot` to `new_slot` can be transfered. + // allocator inside `old_slot` to `new_slot` can be transferred. // // OPTIONAL: defaults to: // diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index 70da90f7..40bdb71b 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -662,7 +662,7 @@ class raw_hash_set { allocator_type>::template rebind_traits::const_pointer; // Alias used for heterogeneous lookup functions. - // `key_arg` evaluates to `K` when the functors are tranparent and to + // `key_arg` evaluates to `K` when the functors are transparent and to // `key_type` otherwise. It permits template argument deduction on `K` for the // transparent case. template diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index 90917b70..f48578eb 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -687,7 +687,7 @@ TEST(Table, RehashWithNoResize) { Modulo1000HashTable t; // Adding the same length (and the same hash) strings // to have at least kMinFullGroups groups - // with Group::kWidth collisions. Then feel upto MaxDensitySize; + // with Group::kWidth collisions. Then fill up to MaxDensitySize; const size_t kMinFullGroups = 7; std::vector keys; for (size_t i = 0; i < MaxDensitySize(Group::kWidth * kMinFullGroups); ++i) { diff --git a/absl/hash/hash.h b/absl/hash/hash.h index c7ba4c2b..8cbb19e2 100644 --- a/absl/hash/hash.h +++ b/absl/hash/hash.h @@ -25,8 +25,8 @@ // * `AbslHashValue`, an extension point that allows you to extend types to // support Abseil hashing without requiring you to define a hashing // algorithm. -// * `HashState`, a type-erased class which implement the manipulation of the -// hash state (H) itself. containing member functions `combine()` and +// * `HashState`, a type-erased class which implements the manipulation of the +// hash state (H) itself, contains member functions `combine()` and // `combine_contiguous()`, which you can use to contribute to an existing // hash state when hashing your types. // @@ -69,7 +69,7 @@ namespace absl { // `absl::Hash` // ----------------------------------------------------------------------------- // -// `absl::Hash` is a convenient general-purpose hash functor for a type `T` +// `absl::Hash` is a convenient general-purpose hash functor for any type `T` // satisfying any of the following conditions (in order): // // * T is an arithmetic or pointer type @@ -142,7 +142,7 @@ namespace absl { // // The "hash state" concept contains two member functions for mixing hash state: // -// * `H::combine()` +// * `H::combine(state, values...)` // // Combines an arbitrary number of values into a hash state, returning the // updated state. Note that the existing hash state is move-only and must be @@ -160,7 +160,7 @@ namespace absl { // state = H::combine(std::move(state), value2); // state = H::combine(std::move(state), value3); // -// * `H::combine_contiguous()` +// * `H::combine_contiguous(state, data, size)` // // Combines a contiguous array of `size` elements into a hash state, // returning the updated state. Note that the existing hash state is diff --git a/absl/time/civil_time.h b/absl/time/civil_time.h index a1f55305..f6f76cd6 100644 --- a/absl/time/civil_time.h +++ b/absl/time/civil_time.h @@ -73,7 +73,6 @@ #include -#include "absl/base/port.h" // Needed for string vs std::string #include "absl/strings/string_view.h" #include "absl/time/internal/cctz/include/cctz/civil_time.h" diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc index 074c8d0a..e35fa18b 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/absl/time/internal/cctz/src/time_zone_libc.cc @@ -111,7 +111,7 @@ time_zone::absolute_lookup TimeZoneLibC::BreakTime( al.offset = 0; al.abbr = "UTC"; } - al.cs = civil_second(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + al.cs = civil_second(tm.tm_year + year_t{1900}, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); al.is_dst = tm.tm_isdst > 0; return al; diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc index 551292fb..280c96b4 100644 --- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc +++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc @@ -990,6 +990,16 @@ TEST(MakeTime, SysSecondsLimits) { EXPECT_EQ(time_point::min(), tp); tp = convert(civil_second::min(), west); EXPECT_EQ(time_point::min(), tp); + + // Checks that "tm_year + 1900", as used by the "libc" implementation, + // can produce year values beyond the range on an int without overflow. +#if defined(_WIN32) || defined(_WIN64) + // localtime_s() and gmtime_s() don't believe in years past 3000. +#else + const time_zone libc_utc = LoadZone("libc:UTC"); + tp = convert(civil_year(year_t{2147483648}), libc_utc); + EXPECT_EQ("2147483648-01-01T00:00:00+00:00", format(RFC3339, tp, libc_utc)); +#endif } TEST(NextTransition, UTC) { -- cgit v1.2.3 From 7b46e1d31a6b08b1c6da2a13e7b151a20446fa07 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 13 Nov 2018 13:22:00 -0800 Subject: Export of internal Abseil changes. -- 07575526242a8e1275ac4223a3d2822795f46569 by CJ Johnson : Comment cleanup on InlinedVector PiperOrigin-RevId: 221322176 -- 49a5e643f85e34d53c41f5e6cc33357c55c9115d by Matt Kulukundis : Internal cleanup PiperOrigin-RevId: 221309185 -- bb35be87ec9c74244b7d902e7e7d2d33ab139d76 by Abseil Team : Fix typo in comment. PiperOrigin-RevId: 221145354 -- afd4d7c106919708004e06aeea068a57c28aec44 by Derek Mauro : Update the debugging log message in CallOnceImpl() PiperOrigin-RevId: 221103254 -- 0b9dace8b88113777bf26a6d38f9bc0bcaf053a1 by Abseil Team : Workaround an MSVC 2015 bug in compile-time initialization. PiperOrigin-RevId: 220871483 -- ea0a3854511ed26beab827e5a5113766b334db86 by Marek Gilbert : Fix ABSL_HAVE_THREAD_LOCAL when compiling for iOS 8 with Xcode 10. Xcode 10 has moved the check for thread_local to a link time, so clang reports __has_feature(cxx_thread_local) but then linking fails with messages like this: ld: targeted OS version does not support use of thread local variables PiperOrigin-RevId: 220815885 -- 485b6876c158c3dcf37eb32d7e512242d5d4ecc6 by Greg Falcon : Make the absl::c_set_xxxx() algorithms refuse to compile when passed an unordered collection from std:: or absl::. These algorithms operate on sorted sequences; passing an unordered container to them is nearly certainly a bug. This change is technically an API break, but it only breaks incorrect code. We could try to be more clever and detect unordered collections from other libraries, but false positives will break legal code, and this would constitute an API break Abseil cannot afford. PiperOrigin-RevId: 220794190 -- c47cff7f9cc70a4c1604eee0131af552f40e46d6 by Jon Cohen : MSVC 2017's STL throws a Structured Exception (not a C++ exception, essentially equivalent to SIGSEGV) when variant::emplace calls a throwing constructor when using the debug multithreaded MSVC runtime DLL. This manifests in dbg mode in Bazel builds. Disable tests which trigger this bug. It's impossible to specifically pull out MSVC 2017 -dbg modes because there's no way for Bazel to know when version of MSVC is being used -- you tell Bazel the directory where the MSVC tools live, not which version of MSVC tools to use. Thus the best we can do is switch on _DEBUG, which is set whenever the debug runtime is selected with the /MDd build flag, as in Bazel -dbg modes. See https://msdn.microsoft.com/en-us/library/b0084kay.aspx ctrl-f "_DEBUG" PiperOrigin-RevId: 220706161 -- 43993d4af309d92f4ebff38391dcc245f154ecc7 by Shaindel Schwartz : Internal change PiperOrigin-RevId: 220688429 -- 2448802972dcc261af153af464f2b022ef54a2a9 by Abseil Team : Speed up operator* for uint128 in WIN64. PiperOrigin-RevId: 220678790 -- 7b376403dd05ba10152fb52e40b29d8af79b58bb by Abseil Team : Import of CCTZ from GitHub. PiperOrigin-RevId: 220654834 -- ae08af58111c3f838b8d4de25f501c3559c86002 by Abseil Team : CMake: Add absl_cc_test function PiperOrigin-RevId: 220603940 GitOrigin-RevId: 07575526242a8e1275ac4223a3d2822795f46569 Change-Id: Iba7f53eb394c8a9de564582a976793f9bb0596d9 --- CMake/AbseilHelpers.cmake | 83 ++++++++- absl/algorithm/container.h | 78 +++++++- absl/base/call_once.h | 8 +- absl/base/config.h | 24 ++- absl/container/BUILD.bazel | 4 + absl/container/flat_hash_map.h | 12 ++ absl/container/flat_hash_set.h | 12 ++ absl/container/inlined_vector.h | 41 +++-- absl/container/internal/hash_generator_testing.cc | 8 +- absl/container/internal/hash_generator_testing.h | 8 +- absl/container/node_hash_map.h | 14 +- absl/container/node_hash_set.h | 11 ++ absl/numeric/int128.h | 11 ++ absl/synchronization/lifetime_test.cc | 15 +- absl/synchronization/notification.cc | 1 + absl/time/duration_test.cc | 11 ++ absl/time/internal/cctz/src/time_zone_libc.cc | 200 +++++++++++++++++---- .../internal/cctz/src/time_zone_lookup_test.cc | 100 ++++++++++- absl/time/time.h | 18 +- absl/types/BUILD.bazel | 1 + absl/types/variant_exception_safety_test.cc | 6 + absl/types/variant_test.cc | 9 +- 22 files changed, 564 insertions(+), 111 deletions(-) (limited to 'absl/time/internal/cctz/src/time_zone_libc.cc') diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake index d4870365..3b9148ea 100644 --- a/CMake/AbseilHelpers.cmake +++ b/CMake/AbseilHelpers.cmake @@ -62,7 +62,6 @@ function(absl_library) endif() endfunction() -# # CMake function to imitate Bazel's cc_library rule. # # Parameters: @@ -77,14 +76,13 @@ endfunction() # TESTONLY: When added, this target will only be built if user passes -DABSL_RUN_TESTS=ON to CMake. # # Note: -# # By default, absl_cc_library will always create a library named absl_internal_${NAME}, # which means other targets can only depend this library as absl_internal_${NAME}, not ${NAME}. # This is to reduce namespace pollution. # # absl_cc_library( # NAME -# awesome_lib +# awesome # HDRS # "a.h" # SRCS @@ -96,7 +94,7 @@ endfunction() # SRCS # "b.cc" # DEPS -# absl_internal_awesome_lib # not "awesome_lib"! +# absl_internal_awesome # not "awesome"! # ) # # If PUBLIC is set, absl_cc_library will instead create a target named @@ -112,7 +110,6 @@ endfunction() # User can then use the library as absl::main_lib (although absl_main_lib is defined too). # # TODO: Implement "ALWAYSLINK" - function(absl_cc_library) cmake_parse_arguments(ABSL_CC_LIB "DISABLE_INSTALL;PUBLIC;TESTONLY" @@ -153,7 +150,8 @@ function(absl_cc_library) else() # Generating header-only library add_library(${_NAME} INTERFACE) - target_include_directories(${_NAME} INTERFACE ${ABSL_COMMON_INCLUDE_DIRS}) + target_include_directories(${_NAME} + INTERFACE ${ABSL_COMMON_INCLUDE_DIRS}) target_link_libraries(${_NAME} INTERFACE ${ABSL_CC_LIB_DEPS} ${ABSL_CC_LIB_LINKOPTS} ) @@ -166,6 +164,78 @@ function(absl_cc_library) endif() endfunction() +# absl_cc_test() +# +# CMake function to imitate Bazel's cc_test rule. +# +# Parameters: +# NAME: name of target (see Usage below) +# SRCS: List of source files for the binary +# DEPS: List of other libraries to be linked in to the binary targets +# COPTS: List of private compile options +# DEFINES: List of public defines +# LINKOPTS: List of link options +# +# Note: +# By default, absl_cc_test will always create a binary named absl_${NAME}. +# This will also add it to ctest list as absl_${NAME}. +# +# Usage: +# absl_cc_library( +# NAME +# awesome +# HDRS +# "a.h" +# SRCS +# "a.cc" +# PUBLIC +# ) +# +# absl_cc_test( +# NAME +# awesome_test +# SRCS +# "awesome_test.cc" +# DEPS +# absl::awesome +# gmock +# gtest_main +# ) +function(absl_cc_test) + if(NOT ABSL_RUN_TESTS) + return() + endif() + + cmake_parse_arguments(ABSL_CC_TEST + "" + "NAME" + "SRCS;COPTS;DEFINES;LINKOPTS;DEPS" + ${ARGN} + ) + + set(_NAME "absl_${ABSL_CC_TEST_NAME}") + add_executable(${_NAME} "") + target_sources(${_NAME} PRIVATE ${ABSL_CC_TEST_SRCS}) + target_include_directories(${_NAME} + PUBLIC ${ABSL_COMMON_INCLUDE_DIRS} + PRIVATE ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS} + ) + target_compile_definitions(${_NAME} + PUBLIC ${ABSL_CC_TEST_DEFINES} + ) + target_compile_options(${_NAME} + PRIVATE ${ABSL_CC_TEST_COPTS} + ) + target_link_libraries(${_NAME} + PUBLIC ${ABSL_CC_TEST_DEPS} + PRIVATE ${ABSL_CC_TEST_LINKOPTS} + ) + # Add all Abseil targets to a a folder in the IDE for organization. + set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}) + + add_test(NAME ${_NAME} COMMAND ${_NAME}) +endfunction() + # # header only virtual target creation # @@ -211,7 +281,6 @@ function(absl_header_library) endfunction() - # # create an abseil unit_test and add it to the executed test list # diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h index 53ab1568..6d5f6630 100644 --- a/absl/algorithm/container.h +++ b/absl/algorithm/container.h @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include #include @@ -54,7 +56,6 @@ #include "absl/meta/type_traits.h" namespace absl { - namespace container_algorithm_internal { // NOTE: it is important to defer to ADL lookup for building with C++ modules, @@ -101,6 +102,17 @@ ContainerIter c_begin(C& c) { return begin(c); } template ContainerIter c_end(C& c) { return end(c); } +template +struct IsUnorderedContainer : std::false_type {}; + +template +struct IsUnorderedContainer< + std::unordered_map> : std::true_type {}; + +template +struct IsUnorderedContainer> + : std::true_type {}; + } // namespace container_algorithm_internal // PUBLIC API @@ -1154,7 +1166,13 @@ bool c_includes(const C1& c1, const C2& c2, Compare&& comp) { // Container-based version of the `std::set_union()` function // to return an iterator containing the union of two containers; duplicate // values are not copied into the output. -template +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output) { return std::set_union(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), @@ -1164,7 +1182,13 @@ OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output) { // Overload of c_set_union() for performing a merge using a `comp` other than // `operator<`. -template +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output, Compare&& comp) { return std::set_union(container_algorithm_internal::c_begin(c1), @@ -1178,7 +1202,13 @@ OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output, // // Container-based version of the `std::set_intersection()` function // to return an iterator containing the intersection of two containers. -template +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> OutputIterator c_set_intersection(const C1& c1, const C2& c2, OutputIterator output) { return std::set_intersection(container_algorithm_internal::c_begin(c1), @@ -1189,7 +1219,13 @@ OutputIterator c_set_intersection(const C1& c1, const C2& c2, // Overload of c_set_intersection() for performing a merge using a `comp` other // than `operator<`. -template +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> OutputIterator c_set_intersection(const C1& c1, const C2& c2, OutputIterator output, Compare&& comp) { return std::set_intersection(container_algorithm_internal::c_begin(c1), @@ -1204,7 +1240,13 @@ OutputIterator c_set_intersection(const C1& c1, const C2& c2, // Container-based version of the `std::set_difference()` function // to return an iterator containing elements present in the first container but // not in the second. -template +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> OutputIterator c_set_difference(const C1& c1, const C2& c2, OutputIterator output) { return std::set_difference(container_algorithm_internal::c_begin(c1), @@ -1215,7 +1257,13 @@ OutputIterator c_set_difference(const C1& c1, const C2& c2, // Overload of c_set_difference() for performing a merge using a `comp` other // than `operator<`. -template +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> OutputIterator c_set_difference(const C1& c1, const C2& c2, OutputIterator output, Compare&& comp) { return std::set_difference(container_algorithm_internal::c_begin(c1), @@ -1230,7 +1278,13 @@ OutputIterator c_set_difference(const C1& c1, const C2& c2, // Container-based version of the `std::set_symmetric_difference()` // function to return an iterator containing elements present in either one // container or the other, but not both. -template +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2, OutputIterator output) { return std::set_symmetric_difference( @@ -1242,7 +1296,13 @@ OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2, // Overload of c_set_symmetric_difference() for performing a merge using a // `comp` other than `operator<`. -template +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2, OutputIterator output, Compare&& comp) { diff --git a/absl/base/call_once.h b/absl/base/call_once.h index 532ee2e3..f6c8ebb2 100644 --- a/absl/base/call_once.h +++ b/absl/base/call_once.h @@ -150,12 +150,8 @@ void CallOnceImpl(std::atomic* control, old_control != kOnceRunning && old_control != kOnceWaiter && old_control != kOnceDone) { - ABSL_RAW_LOG( - FATAL, - "Unexpected value for control word: %lx. Either the control word " - "has non-static storage duration (where GoogleOnceDynamic might " - "be appropriate), or there's been a memory corruption.", - static_cast(old_control)); // NOLINT + ABSL_RAW_LOG(FATAL, "Unexpected value for control word: 0x%lx", + static_cast(old_control)); // NOLINT } } #endif // NDEBUG diff --git a/absl/base/config.h b/absl/base/config.h index d4eb7d0c..e3edb2bf 100644 --- a/absl/base/config.h +++ b/absl/base/config.h @@ -139,12 +139,18 @@ #ifdef ABSL_HAVE_THREAD_LOCAL #error ABSL_HAVE_THREAD_LOCAL cannot be directly set #elif defined(__APPLE__) -// Notes: Xcode's clang did not support `thread_local` until version -// 8, and even then not for all iOS < 9.0. Also, Xcode 9.3 started disallowing -// `thread_local` for 32-bit iOS simulator targeting iOS 9.x. -// `__has_feature` is only supported by Clang so it has be inside +// Notes: +// * Xcode's clang did not support `thread_local` until version 8, and +// even then not for all iOS < 9.0. +// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator +// targeting iOS 9.x. +// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time +// making __has_feature unreliable there. +// +// Otherwise, `__has_feature` is only supported by Clang so it has be inside // `defined(__APPLE__)` check. -#if __has_feature(cxx_thread_local) +#if __has_feature(cxx_thread_local) && \ + !(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0) #define ABSL_HAVE_THREAD_LOCAL 1 #endif #else // !defined(__APPLE__) @@ -423,4 +429,12 @@ #define ABSL_HAVE_STD_STRING_VIEW 1 #endif +// In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION +// SEH exception from emplace for variant when constructing the +// struct can throw. This defeats some of variant_test and +// variant_exception_safety_test. +#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_DEBUG) +#define ABSL_INTERNAL_MSVC_2017_DBG_MODE +#endif + #endif // ABSL_BASE_CONFIG_H_ diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel index d75f8916..afc869f4 100644 --- a/absl/container/BUILD.bazel +++ b/absl/container/BUILD.bazel @@ -212,6 +212,7 @@ cc_library( ":container_memory", ":hash_function_defaults", ":raw_hash_map", + "//absl/algorithm:container", "//absl/memory", ], ) @@ -240,6 +241,7 @@ cc_library( ":container_memory", ":hash_function_defaults", ":raw_hash_set", + "//absl/algorithm:container", "//absl/base:core_headers", "//absl/memory", ], @@ -271,6 +273,7 @@ cc_library( ":hash_function_defaults", ":node_hash_policy", ":raw_hash_map", + "//absl/algorithm:container", "//absl/memory", ], ) @@ -299,6 +302,7 @@ cc_library( ":hash_function_defaults", ":node_hash_policy", ":raw_hash_set", + "//absl/algorithm:container", "//absl/memory", ], ) diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h index de632be2..7bc21380 100644 --- a/absl/container/flat_hash_map.h +++ b/absl/container/flat_hash_map.h @@ -35,6 +35,7 @@ #include #include +#include "absl/algorithm/container.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export #include "absl/container/internal/raw_hash_map.h" // IWYU pragma: export @@ -564,5 +565,16 @@ struct FlatHashMapPolicy { }; } // namespace container_internal + +namespace container_algorithm_internal { + +// Specialization of trait in absl/algorithm/container.h +template +struct IsUnorderedContainer< + absl::flat_hash_map> : std::true_type {}; + +} // namespace container_algorithm_internal + } // namespace absl + #endif // ABSL_CONTAINER_FLAT_HASH_MAP_H_ diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h index a2584d66..f7c1acaa 100644 --- a/absl/container/flat_hash_set.h +++ b/absl/container/flat_hash_set.h @@ -32,6 +32,7 @@ #include #include +#include "absl/algorithm/container.h" #include "absl/base/macros.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export @@ -475,5 +476,16 @@ struct FlatHashSetPolicy { static size_t space_used(const T*) { return 0; } }; } // namespace container_internal + +namespace container_algorithm_internal { + +// Specialization of trait in absl/algorithm/container.h +template +struct IsUnorderedContainer> + : std::true_type {}; + +} // namespace container_algorithm_internal + } // namespace absl + #endif // ABSL_CONTAINER_FLAT_HASH_SET_H_ diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index ea8cb02b..642dae6c 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -20,17 +20,17 @@ // vector" which behaves in an equivalent fashion to a `std::vector`, except // that storage for small sequences of the vector are provided inline without // requiring any heap allocation. - -// An `absl::InlinedVector` specifies the size N at which to inline as one -// of its template parameters. Vectors of length <= N are provided inline. -// Typically N is very small (e.g., 4) so that sequences that are expected to be -// short do not require allocations. - -// An `absl::InlinedVector` does not usually require a specific allocator; if +// +// An `absl::InlinedVector` specifies the default capacity `N` as one of +// its template parameters. Instances where `size() <= N` hold contained +// elements in inline space. Typically `N` is very small so that sequences that +// are expected to be short do not require allocations. +// +// An `absl::InlinedVector` does not usually require a specific allocator. If // the inlined vector grows beyond its initial constraints, it will need to -// allocate (as any normal `std::vector` would) and it will generally use the -// default allocator in that case; optionally, a custom allocator may be -// specified using an `absl::InlinedVector` construction. +// allocate (as any normal `std::vector` would). This is usually performed with +// the default allocator (defined as `std::allocator`). Optionally, a custom +// allocator type may be specified as `A` in `absl::InlinedVector`. #ifndef ABSL_CONTAINER_INLINED_VECTOR_H_ #define ABSL_CONTAINER_INLINED_VECTOR_H_ @@ -61,8 +61,8 @@ namespace absl { // An `absl::InlinedVector` is designed to be a drop-in replacement for // `std::vector` for use cases where the vector's size is sufficiently small // that it can be inlined. If the inlined vector does grow beyond its estimated -// size, it will trigger an initial allocation on the heap, and will behave as a -// `std:vector`. The API of the `absl::InlinedVector` within this file is +// capacity, it will trigger an initial allocation on the heap, and will behave +// as a `std:vector`. The API of the `absl::InlinedVector` within this file is // designed to cover the same API footprint as covered by `std::vector`. template > class InlinedVector { @@ -101,7 +101,6 @@ class InlinedVector { using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - // --------------------------------------------------------------------------- // InlinedVector Constructors and Destructor // --------------------------------------------------------------------------- @@ -135,11 +134,12 @@ class InlinedVector { AppendRange(init_list.begin(), init_list.end()); } - // Creates and initialize with the elements [`first`, `last`). + // Creates an inlined vector with elements constructed from the provided + // Iterator range [`first`, `last`). // // NOTE: The `enable_if` prevents ambiguous interpretation between a call to - // this constructor with two integral arguments and a call to the preceding - // `InlinedVector(n, v)` constructor. + // this constructor with two integral arguments and a call to the above + // `InlinedVector(size_type, const_reference)` constructor. template * = nullptr> InlinedVector(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()) @@ -153,11 +153,11 @@ class InlinedVector { // Creates a copy of `other` but with a specified allocator. InlinedVector(const InlinedVector& other, const allocator_type& alloc); - // Creates an inlined vector with the contents of `other`. + // Creates an inlined vector by moving in the contents of `other`. // // NOTE: This move constructor does not allocate and only moves the underlying // objects, so its `noexcept` specification depends on whether moving the - // underlying objects can throw or not. We assume + // underlying objects can throw or not. We assume: // a) move constructors should only throw due to allocation failure and // b) if `value_type`'s move constructor allocates, it uses the same // allocation function as the `InlinedVector`'s allocator, so the move @@ -167,9 +167,9 @@ class InlinedVector { absl::allocator_is_nothrow::value || std::is_nothrow_move_constructible::value); - // Creates an inlined vector with the contents of `other`. + // Creates an inlined vector by moving in the contents of `other`. // - // NOTE: This move constructor allocates and also moves the underlying + // NOTE: This move constructor allocates and subsequently moves the underlying // objects, so its `noexcept` specification depends on whether the allocation // can throw and whether moving the underlying objects can throw. Based on the // same assumptions as above, the `noexcept` specification is dominated by @@ -180,7 +180,6 @@ class InlinedVector { ~InlinedVector() { clear(); } - // --------------------------------------------------------------------------- // InlinedVector Member Accessors // --------------------------------------------------------------------------- diff --git a/absl/container/internal/hash_generator_testing.cc b/absl/container/internal/hash_generator_testing.cc index 0d6a9df1..e0fefbff 100644 --- a/absl/container/internal/hash_generator_testing.cc +++ b/absl/container/internal/hash_generator_testing.cc @@ -39,9 +39,9 @@ class RandomDeviceSeedSeq { } // namespace -std::mt19937_64* GetThreadLocalRng() { +std::mt19937_64* GetSharedRng() { RandomDeviceSeedSeq seed_seq; - thread_local auto* rng = new std::mt19937_64(seed_seq); + static auto* rng = new std::mt19937_64(seed_seq); return rng; } @@ -51,7 +51,7 @@ std::string Generator::operator()() const { std::string res; res.resize(32); std::generate(res.begin(), res.end(), - [&]() { return chars(*GetThreadLocalRng()); }); + [&]() { return chars(*GetSharedRng()); }); return res; } @@ -63,7 +63,7 @@ absl::string_view Generator::operator()() const { auto& res = arena->back(); res.resize(32); std::generate(res.begin(), res.end(), - [&]() { return chars(*GetThreadLocalRng()); }); + [&]() { return chars(*GetSharedRng()); }); return res; } diff --git a/absl/container/internal/hash_generator_testing.h b/absl/container/internal/hash_generator_testing.h index 50d77102..6521efe8 100644 --- a/absl/container/internal/hash_generator_testing.h +++ b/absl/container/internal/hash_generator_testing.h @@ -43,7 +43,7 @@ struct IsMap> : std::true_type {}; } // namespace generator_internal -std::mt19937_64* GetThreadLocalRng(); +std::mt19937_64* GetSharedRng(); enum Enum { kEnumEmpty, @@ -66,7 +66,7 @@ template struct Generator::value>::type> { T operator()() const { std::uniform_int_distribution dist; - return dist(*GetThreadLocalRng()); + return dist(*GetSharedRng()); } }; @@ -76,7 +76,7 @@ struct Generator { std::uniform_int_distribution::type> dist; while (true) { - auto variate = dist(*GetThreadLocalRng()); + auto variate = dist(*GetSharedRng()); if (variate != kEnumEmpty && variate != kEnumDeleted) return static_cast(variate); } @@ -90,7 +90,7 @@ struct Generator { typename std::underlying_type::type> dist; while (true) { - EnumClass variate = static_cast(dist(*GetThreadLocalRng())); + EnumClass variate = static_cast(dist(*GetSharedRng())); if (variate != EnumClass::kEmpty && variate != EnumClass::kDeleted) return static_cast(variate); } diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h index 00710e52..18d3f28f 100644 --- a/absl/container/node_hash_map.h +++ b/absl/container/node_hash_map.h @@ -40,6 +40,7 @@ #include #include +#include "absl/algorithm/container.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export #include "absl/container/internal/node_hash_policy.h" @@ -91,7 +92,7 @@ class NodeHashMapPolicy; // std::string search_key = "b"; // auto result = ducks.find(search_key); // if (result != ducks.end()) { -// std::cout << "Result: " << search_key->second << std::endl; +// std::cout << "Result: " << result->second << std::endl; // } template , @@ -566,5 +567,16 @@ class NodeHashMapPolicy static const Value& value(const value_type* elem) { return elem->second; } }; } // namespace container_internal + +namespace container_algorithm_internal { + +// Specialization of trait in absl/algorithm/container.h +template +struct IsUnorderedContainer< + absl::node_hash_map> : std::true_type {}; + +} // namespace container_algorithm_internal + } // namespace absl + #endif // ABSL_CONTAINER_NODE_HASH_MAP_H_ diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h index 813fdeff..e0897c99 100644 --- a/absl/container/node_hash_set.h +++ b/absl/container/node_hash_set.h @@ -37,6 +37,7 @@ #include +#include "absl/algorithm/container.h" #include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export #include "absl/container/internal/node_hash_policy.h" #include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export @@ -475,5 +476,15 @@ struct NodeHashSetPolicy static size_t element_space_used(const T*) { return sizeof(T); } }; } // namespace container_internal + +namespace container_algorithm_internal { + +// Specialization of trait in absl/algorithm/container.h +template +struct IsUnorderedContainer> + : std::true_type {}; + +} // namespace container_algorithm_internal } // namespace absl + #endif // ABSL_CONTAINER_NODE_HASH_SET_H_ diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h index 5d14a4a8..9c2e00f6 100644 --- a/absl/numeric/int128.h +++ b/absl/numeric/int128.h @@ -37,6 +37,11 @@ #include "absl/base/macros.h" #include "absl/base/port.h" +#if defined(_MSC_VER) && defined(_WIN64) +#include +#pragma intrinsic(_umul128) +#endif // defined(_MSC_VER) && defined(_WIN64) + namespace absl { @@ -661,6 +666,12 @@ inline uint128 operator*(uint128 lhs, uint128 rhs) { // can be used for uint128 storage. return static_cast(lhs) * static_cast(rhs); +#elif defined(_MSC_VER) && defined(_WIN64) + uint64_t carry; + uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry); + return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) + + Uint128High64(lhs) * Uint128Low64(rhs) + carry, + low); #else // ABSL_HAVE_INTRINSIC128 uint64_t a32 = Uint128Low64(lhs) >> 32; uint64_t a00 = Uint128Low64(lhs) & 0xffffffff; diff --git a/absl/synchronization/lifetime_test.cc b/absl/synchronization/lifetime_test.cc index 90c9009b..b7360c29 100644 --- a/absl/synchronization/lifetime_test.cc +++ b/absl/synchronization/lifetime_test.cc @@ -72,23 +72,19 @@ void ThreadTwo(absl::Mutex* mutex, absl::CondVar* condvar, // Launch thread 1 and thread 2, and block on their completion. // If any of 'mutex', 'condvar', or 'notification' is nullptr, use a locally // constructed instance instead. -void RunTests(absl::Mutex* mutex, absl::CondVar* condvar, - absl::Notification* notification) { +void RunTests(absl::Mutex* mutex, absl::CondVar* condvar) { absl::Mutex default_mutex; absl::CondVar default_condvar; - absl::Notification default_notification; + absl::Notification notification; if (!mutex) { mutex = &default_mutex; } if (!condvar) { condvar = &default_condvar; } - if (!notification) { - notification = &default_notification; - } bool state = false; - std::thread thread_one(ThreadOne, mutex, condvar, notification, &state); - std::thread thread_two(ThreadTwo, mutex, condvar, notification, &state); + std::thread thread_one(ThreadOne, mutex, condvar, ¬ification, &state); + std::thread thread_two(ThreadTwo, mutex, condvar, ¬ification, &state); thread_one.join(); thread_two.join(); } @@ -96,8 +92,7 @@ void RunTests(absl::Mutex* mutex, absl::CondVar* condvar, void TestLocals() { absl::Mutex mutex; absl::CondVar condvar; - absl::Notification notification; - RunTests(&mutex, &condvar, ¬ification); + RunTests(&mutex, &condvar); } // Global variables during start and termination diff --git a/absl/synchronization/notification.cc b/absl/synchronization/notification.cc index ed8cc906..cdcbc134 100644 --- a/absl/synchronization/notification.cc +++ b/absl/synchronization/notification.cc @@ -22,6 +22,7 @@ #include "absl/time/time.h" namespace absl { + void Notification::Notify() { MutexLock l(&this->mutex_); diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc index 7ae25dc6..775da91e 100644 --- a/absl/time/duration_test.cc +++ b/absl/time/duration_test.cc @@ -56,6 +56,17 @@ MATCHER_P(TimevalMatcher, tv, "") { return false; } +TEST(Duration, ConstExpr) { + constexpr absl::Duration d0 = absl::ZeroDuration(); + static_assert(d0 == absl::ZeroDuration(), "ZeroDuration()"); + constexpr absl::Duration d1 = absl::Seconds(1); + static_assert(d1 == absl::Seconds(1), "Seconds(1)"); + static_assert(d1 != absl::ZeroDuration(), "Seconds(1)"); + constexpr absl::Duration d2 = absl::InfiniteDuration(); + static_assert(d2 == absl::InfiniteDuration(), "InfiniteDuration()"); + static_assert(d2 != absl::ZeroDuration(), "InfiniteDuration()"); +} + TEST(Duration, ValueSemantics) { // If this compiles, the test passes. constexpr absl::Duration a; // Default construction diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc index e35fa18b..6db519e1 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/absl/time/internal/cctz/src/time_zone_libc.cc @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -85,6 +86,76 @@ OffsetAbbr get_offset_abbr(const T& tm, decltype(&T::__tm_gmtoff) = nullptr, #endif // !defined(__tm_gmtoff) && !defined(__tm_zone) #endif +inline std::tm* gm_time(const std::time_t *timep, std::tm *result) { +#if defined(_WIN32) || defined(_WIN64) + return gmtime_s(result, timep) ? nullptr : result; +#else + return gmtime_r(timep, result); +#endif +} + +inline std::tm* local_time(const std::time_t *timep, std::tm *result) { +#if defined(_WIN32) || defined(_WIN64) + return localtime_s(result, timep) ? nullptr : result; +#else + return localtime_r(timep, result); +#endif +} + +// Converts a civil second and "dst" flag into a time_t and UTC offset. +// Returns false if time_t cannot represent the requested civil second. +// Caller must have already checked that cs.year() will fit into a tm_year. +bool make_time(const civil_second& cs, int is_dst, std::time_t* t, int* off) { + std::tm tm; + tm.tm_year = static_cast(cs.year() - year_t{1900}); + tm.tm_mon = cs.month() - 1; + tm.tm_mday = cs.day(); + tm.tm_hour = cs.hour(); + tm.tm_min = cs.minute(); + tm.tm_sec = cs.second(); + tm.tm_isdst = is_dst; + *t = std::mktime(&tm); + if (*t == std::time_t{-1}) { + std::tm tm2; + const std::tm* tmp = local_time(t, &tm2); + if (tmp == nullptr || tmp->tm_year != tm.tm_year || + tmp->tm_mon != tm.tm_mon || tmp->tm_mday != tm.tm_mday || + tmp->tm_hour != tm.tm_hour || tmp->tm_min != tm.tm_min || + tmp->tm_sec != tm.tm_sec) { + // A true error (not just one second before the epoch). + return false; + } + } + *off = get_offset_abbr(tm).first; + return true; +} + +// Find the least time_t in [lo:hi] where local time matches offset, given: +// (1) lo doesn't match, (2) hi does, and (3) there is only one transition. +std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) { + std::tm tm; + while (lo + 1 != hi) { + const std::time_t mid = lo + (hi - lo) / 2; + if (std::tm* tmp = local_time(&mid, &tm)) { + if (get_offset_abbr(*tmp).first == offset) { + hi = mid; + } else { + lo = mid; + } + } else { + // If std::tm cannot hold some result we resort to a linear search, + // ignoring all failed conversions. Slow, but never really happens. + while (++lo != hi) { + if (std::tm* tmp = local_time(&lo, &tm)) { + if (get_offset_abbr(*tmp).first == offset) break; + } + } + return lo; + } + } + return hi; +} + } // namespace TimeZoneLibC::TimeZoneLibC(const std::string& name) @@ -93,50 +164,107 @@ TimeZoneLibC::TimeZoneLibC(const std::string& name) time_zone::absolute_lookup TimeZoneLibC::BreakTime( const time_point& tp) const { time_zone::absolute_lookup al; - std::time_t t = ToUnixSeconds(tp); + al.offset = 0; + al.is_dst = false; + al.abbr = "-00"; + + const std::int_fast64_t s = ToUnixSeconds(tp); + + // If std::time_t cannot hold the input we saturate the output. + if (s < std::numeric_limits::min()) { + al.cs = civil_second::min(); + return al; + } + if (s > std::numeric_limits::max()) { + al.cs = civil_second::max(); + return al; + } + + const std::time_t t = static_cast(s); std::tm tm; - if (local_) { -#if defined(_WIN32) || defined(_WIN64) - localtime_s(&tm, &t); -#else - localtime_r(&t, &tm); -#endif - std::tie(al.offset, al.abbr) = get_offset_abbr(tm); - } else { -#if defined(_WIN32) || defined(_WIN64) - gmtime_s(&tm, &t); -#else - gmtime_r(&t, &tm); -#endif - al.offset = 0; - al.abbr = "UTC"; + std::tm* tmp = local_ ? local_time(&t, &tm) : gm_time(&t, &tm); + + // If std::tm cannot hold the result we saturate the output. + if (tmp == nullptr) { + al.cs = (s < 0) ? civil_second::min() : civil_second::max(); + return al; } - al.cs = civil_second(tm.tm_year + year_t{1900}, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); - al.is_dst = tm.tm_isdst > 0; + + const year_t year = tmp->tm_year + year_t{1900}; + al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + std::tie(al.offset, al.abbr) = get_offset_abbr(*tmp); + if (!local_) al.abbr = "UTC"; // as expected by cctz + al.is_dst = tmp->tm_isdst > 0; return al; } time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const { - time_zone::civil_lookup cl; - std::time_t t; - if (local_) { - // Does not handle SKIPPED/AMBIGUOUS or huge years. - std::tm tm; - tm.tm_year = static_cast(cs.year() - 1900); - tm.tm_mon = cs.month() - 1; - tm.tm_mday = cs.day(); - tm.tm_hour = cs.hour(); - tm.tm_min = cs.minute(); - tm.tm_sec = cs.second(); - tm.tm_isdst = -1; - t = std::mktime(&tm); + if (!local_) { + // If time_point cannot hold the result we saturate. + static const civil_second min_tp_cs = + civil_second() + ToUnixSeconds(time_point::min()); + static const civil_second max_tp_cs = + civil_second() + ToUnixSeconds(time_point::max()); + const time_point tp = + (cs < min_tp_cs) + ? time_point::min() + : (cs > max_tp_cs) ? time_point::max() + : FromUnixSeconds(cs - civil_second()); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; + } + + // If tm_year cannot hold the requested year we saturate the result. + if (cs.year() < 0) { + if (cs.year() < std::numeric_limits::min() + year_t{1900}) { + const time_point tp = time_point::min(); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; + } } else { - t = cs - civil_second(); + if (cs.year() - year_t{1900} > std::numeric_limits::max()) { + const time_point tp = time_point::max(); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; + } + } + + // We probe with "is_dst" values of 0 and 1 to try to distinguish unique + // civil seconds from skipped or repeated ones. This is not always possible + // however, as the "dst" flag does not change over some offset transitions. + // We are also subject to the vagaries of mktime() implementations. + std::time_t t0, t1; + int offset0, offset1; + if (make_time(cs, 0, &t0, &offset0) && make_time(cs, 1, &t1, &offset1)) { + if (t0 == t1) { + // The civil time was singular (pre == trans == post). + const time_point tp = FromUnixSeconds(t0); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; + } + + if (t0 > t1) { + std::swap(t0, t1); + std::swap(offset0, offset1); + } + const std::time_t tt = find_trans(t0, t1, offset1); + const time_point trans = FromUnixSeconds(tt); + + if (offset0 < offset1) { + // The civil time did not exist (pre >= trans > post). + const time_point pre = FromUnixSeconds(t1); + const time_point post = FromUnixSeconds(t0); + return {time_zone::civil_lookup::SKIPPED, pre, trans, post}; + } + + // The civil time was ambiguous (pre < trans <= post). + const time_point pre = FromUnixSeconds(t0); + const time_point post = FromUnixSeconds(t1); + return {time_zone::civil_lookup::REPEATED, pre, trans, post}; } - cl.kind = time_zone::civil_lookup::UNIQUE; - cl.pre = cl.trans = cl.post = FromUnixSeconds(t); - return cl; + + // make_time() failed somehow so we saturate the result. + const time_point tp = (cs < civil_second()) + ? time_point::min() + : time_point::max(); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; } bool TimeZoneLibC::NextTransition(const time_point& tp, diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc index f28e7f85..e84b9469 100644 --- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc +++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc @@ -16,7 +16,9 @@ #include #include +#include #include +#include #include #include #include @@ -925,7 +927,7 @@ TEST(MakeTime, Normalization) { EXPECT_EQ(tp, convert(civil_second(2009, 2, 13, 18, 30, 90), tz)); // second } -// NOTE: Run this with --copt=-ftrapv to detect overflow problems. +// NOTE: Run this with -ftrapv to detect overflow problems. TEST(MakeTime, SysSecondsLimits) { const char RFC3339[] = "%Y-%m-%dT%H:%M:%S%Ez"; const time_zone utc = utc_time_zone(); @@ -991,19 +993,107 @@ TEST(MakeTime, SysSecondsLimits) { tp = convert(civil_second::min(), west); EXPECT_EQ(time_point::min(), tp); + // Some similar checks for the "libc" time-zone implementation. if (sizeof(std::time_t) >= 8) { // Checks that "tm_year + 1900", as used by the "libc" implementation, // can produce year values beyond the range on an int without overflow. #if defined(_WIN32) || defined(_WIN64) - // localtime_s() and gmtime_s() don't believe in years past 3000. + // localtime_s() and gmtime_s() don't believe in years outside [1970:3000]. #else - const time_zone libc_utc = LoadZone("libc:UTC"); - tp = convert(civil_year(year_t{2147483648}), libc_utc); - EXPECT_EQ("2147483648-01-01T00:00:00+00:00", format(RFC3339, tp, libc_utc)); + const time_zone utc = LoadZone("libc:UTC"); + const year_t max_tm_year = year_t{std::numeric_limits::max()} + 1900; + tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), utc); + EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, utc)); + const year_t min_tm_year = year_t{std::numeric_limits::min()} + 1900; + tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), utc); + EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, utc)); #endif } } +TEST(MakeTime, LocalTimeLibC) { + // Checks that cctz and libc agree on transition points in [1970:2037]. + // + // We limit this test case to environments where: + // 1) we know how to change the time zone used by localtime()/mktime(), + // 2) cctz and localtime()/mktime() will use similar-enough tzdata, and + // 3) we have some idea about how mktime() behaves during transitions. +#if defined(__linux__) + const char* const ep = getenv("TZ"); + std::string tz_name = (ep != nullptr) ? ep : ""; + for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) { + ASSERT_EQ(0, setenv("TZ", *np, 1)); // change what "localtime" means + const auto zi = local_time_zone(); + const auto lc = LoadZone("libc:localtime"); + time_zone::civil_transition trans; + for (auto tp = zi.lookup(civil_second()).trans; + zi.next_transition(tp, &trans); + tp = zi.lookup(trans.to).trans) { + const auto fcl = zi.lookup(trans.from); + const auto tcl = zi.lookup(trans.to); + civil_second cs; // compare cs in zi and lc + if (fcl.kind == time_zone::civil_lookup::UNIQUE) { + if (tcl.kind == time_zone::civil_lookup::UNIQUE) { + // Both unique; must be an is_dst or abbr change. + ASSERT_EQ(trans.from, trans.to); + const auto trans = fcl.trans; + const auto tal = zi.lookup(trans); + const auto tprev = trans - absl::time_internal::cctz::seconds(1); + const auto pal = zi.lookup(tprev); + if (pal.is_dst == tal.is_dst) { + ASSERT_STRNE(pal.abbr, tal.abbr); + } + continue; + } + ASSERT_EQ(time_zone::civil_lookup::REPEATED, tcl.kind); + cs = trans.to; + } else { + ASSERT_EQ(time_zone::civil_lookup::UNIQUE, tcl.kind); + ASSERT_EQ(time_zone::civil_lookup::SKIPPED, fcl.kind); + cs = trans.from; + } + if (cs.year() > 2037) break; // limit test time (and to 32-bit time_t) + const auto cl_zi = zi.lookup(cs); + if (zi.lookup(cl_zi.pre).is_dst == zi.lookup(cl_zi.post).is_dst) { + // The "libc" implementation cannot correctly classify transitions + // that don't change the "tm_isdst" flag. In Europe/Volgograd, for + // example, there is a SKIPPED transition from +03 to +04 with dst=F + // on both sides ... + // 1540681199 = 2018-10-28 01:59:59 +03:00:00 [dst=F off=10800] + // 1540681200 = 2018-10-28 03:00:00 +04:00:00 [dst=F off=14400] + // but std::mktime(2018-10-28 02:00:00, tm_isdst=0) fails, unlike, + // say, the similar Europe/Chisinau transition from +02 to +03 ... + // 1521935999 = 2018-03-25 01:59:59 +02:00:00 [dst=F off=7200] + // 1521936000 = 2018-03-25 03:00:00 +03:00:00 [dst=T off=10800] + // where std::mktime(2018-03-25 02:00:00, tm_isdst=0) succeeds and + // returns 1521936000. + continue; + } + if (cs == civil_second(2037, 10, 4, 2, 0, 0)) { + const std::string tzname = *np; + if (tzname == "Africa/Casablanca" || tzname == "Africa/El_Aaiun") { + // The "libc" implementation gets this transition wrong (at least + // until 2018g when it was removed), returning an offset of 3600 + // instead of 0. TODO: Revert this when 2018g is ubiquitous. + continue; + } + } + const auto cl_lc = lc.lookup(cs); + SCOPED_TRACE(testing::Message() << "For " << cs << " in " << *np); + EXPECT_EQ(cl_zi.kind, cl_lc.kind); + EXPECT_EQ(cl_zi.pre, cl_lc.pre); + EXPECT_EQ(cl_zi.trans, cl_lc.trans); + EXPECT_EQ(cl_zi.post, cl_lc.post); + } + } + if (ep == nullptr) { + ASSERT_EQ(0, unsetenv("TZ")); + } else { + ASSERT_EQ(0, setenv("TZ", tz_name.c_str(), 1)); + } +#endif +} + TEST(NextTransition, UTC) { const auto tz = utc_time_zone(); time_zone::civil_transition trans; diff --git a/absl/time/time.h b/absl/time/time.h index e9e989cb..de12e560 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -153,6 +153,16 @@ class Duration { // Value semantics. constexpr Duration() : rep_hi_(0), rep_lo_(0) {} // zero-length duration + // Copyable. +#if !defined(__clang__) && defined(_MSC_VER) && _MSC_VER < 1910 + // Explicitly defining the constexpr copy constructor avoids an MSVC bug. + constexpr Duration(const Duration& d) + : rep_hi_(d.rep_hi_), rep_lo_(d.rep_lo_) {} +#else + constexpr Duration(const Duration& d) = default; +#endif + Duration& operator=(const Duration& d) = default; + // Compound assignment operators. Duration& operator+=(Duration d); Duration& operator-=(Duration d); @@ -584,7 +594,11 @@ class Time { // absl::Time t = absl::Now(); // absl::Time t = absl::TimeFromTimeval(tv); // absl::Time t = absl::InfinitePast(); - constexpr Time() {} + constexpr Time() = default; + + // Copyable. + constexpr Time(const Time& t) = default; + Time& operator=(const Time& t) = default; // Assignment operators. Time& operator+=(Duration d) { @@ -826,6 +840,8 @@ class TimeZone { public: explicit TimeZone(time_internal::cctz::time_zone tz) : cz_(tz) {} TimeZone() = default; // UTC, but prefer UTCTimeZone() to be explicit. + + // Copyable. TimeZone(const TimeZone&) = default; TimeZone& operator=(const TimeZone&) = default; diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel index 43899ca7..d56fea6e 100644 --- a/absl/types/BUILD.bazel +++ b/absl/types/BUILD.bazel @@ -287,6 +287,7 @@ cc_test( linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS, deps = [ ":variant", + "//absl/base:config", "//absl/base:exception_safety_testing", "//absl/memory", "@com_google_googletest//:gtest_main", diff --git a/absl/types/variant_exception_safety_test.cc b/absl/types/variant_exception_safety_test.cc index 58436f07..82425dbd 100644 --- a/absl/types/variant_exception_safety_test.cc +++ b/absl/types/variant_exception_safety_test.cc @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + #include "absl/types/variant.h" #include @@ -20,8 +21,11 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/base/config.h" #include "absl/base/internal/exception_safety_testing.h" #include "absl/memory/memory.h" +// See comment in absl/base/config.h +#if !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) namespace absl { namespace { @@ -506,3 +510,5 @@ TEST(VariantExceptionSafetyTest, Swap) { } // namespace } // namespace absl + +#endif // !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc index 626d5e61..f47f3a72 100644 --- a/absl/types/variant_test.cc +++ b/absl/types/variant_test.cc @@ -559,9 +559,14 @@ TEST(VariantTest, TestDtor) { } #ifdef ABSL_HAVE_EXCEPTIONS - +// See comment in absl/base/config.h +#if defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) +TEST(VariantTest, DISABLED_TestDtorValuelessByException) +#else // Test destruction when in the valueless_by_exception state. -TEST(VariantTest, TestDtorValuelessByException) { +TEST(VariantTest, TestDtorValuelessByException) +#endif +{ int counter = 0; IncrementInDtor counter_adjuster(&counter); -- cgit v1.2.3 From 540e2537b92cd4abfae6ceddfe24304345461f32 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 28 Jan 2019 12:10:41 -0800 Subject: Export of internal Abseil changes. -- 8c420997e7a08b9e7e24afa32d6e37cb2bfa2c12 by Abseil Team : Import of CCTZ from GitHub. PiperOrigin-RevId: 231265916 -- f52b9e201698b315c23ebaa6c8ec97362048d9b8 by CJ Johnson : inlined_capacity() => GetInlinedCapacity() Originally I intended inlined_capacity() to be moved from the private to public part of the API eventually so I named it appropriately and punted on publicizing it until later. After it was found to cause an issue on some platforms, I decided there was no reason to grow the API of the type just for a pretty function name. Thus, this change brings its name to be of the same format as the rest of the Abseil team's naming convention. PiperOrigin-RevId: 231248856 -- 04e700ea1aad12cdb6a1ed29e183c59d97a47ccd by Abseil Team : Merge https://github.com/abseil/abseil-cpp/pull/255 PiperOrigin-RevId: 231240011 -- 4f2c2212c98093194c73572995e7770b58c9b9a0 by CJ Johnson : Adds identifiers to the AbslHashValue(...) forward declaration bringing it in line with the format of the other forward declarations while keeping it on one line. PiperOrigin-RevId: 231231932 -- 68923d6c9289eb523126638f25d95916456125cf by CJ Johnson : Remove bad calls to assert(...) that do not make sense PiperOrigin-RevId: 231214093 -- a2a0b59b7dc2c39aca979ff6e474b9e170ab96b6 by CJ Johnson : Switch to trailing return type syntax for non-member functions of InlinedVector PiperOrigin-RevId: 230975981 GitOrigin-RevId: 8c420997e7a08b9e7e24afa32d6e37cb2bfa2c12 Change-Id: Ibbad7f27b596801bc770b440afed8d5e9e89ff8d --- absl/container/inlined_vector.h | 65 ++++++++++++------------- absl/time/internal/cctz/src/time_zone_format.cc | 2 +- absl/time/internal/cctz/src/time_zone_info.cc | 4 +- absl/time/internal/cctz/src/time_zone_libc.cc | 8 +-- 4 files changed, 38 insertions(+), 41 deletions(-) (limited to 'absl/time/internal/cctz/src/time_zone_libc.cc') diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index 6c67862e..e0f1714c 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -67,7 +67,7 @@ namespace absl { template > class InlinedVector { static_assert(N > 0, "InlinedVector requires inline capacity greater than 0"); - constexpr static typename A::size_type inlined_capacity() { + constexpr static typename A::size_type GetInlinedCapacity() { return static_cast(N); } @@ -275,12 +275,12 @@ class InlinedVector { // Returns the number of elements that can be stored in the inlined vector // without requiring a reallocation of underlying memory. // - // NOTE: For most inlined vectors, `capacity()` should equal - // `inlined_capacity()`. For inlined vectors which exceed this capacity, they + // NOTE: For most inlined vectors, `capacity()` should equal the template + // parameter `N`. For inlined vectors which exceed this capacity, they // will no longer be inlined and `capacity()` will equal its capacity on the // allocated heap. size_type capacity() const noexcept { - return allocated() ? allocation().capacity() : inlined_capacity(); + return allocated() ? allocation().capacity() : GetInlinedCapacity(); } // `InlinedVector::data()` @@ -667,12 +667,9 @@ class InlinedVector { template reference emplace_back(Args&&... args) { size_type s = size(); - assert(s <= capacity()); if (ABSL_PREDICT_FALSE(s == capacity())) { return GrowAndEmplaceBack(std::forward(args)...); } - assert(s < capacity()); - pointer space; if (allocated()) { tag().set_allocated_size(s + 1); @@ -790,19 +787,19 @@ class InlinedVector { // `InlinedVector::shrink_to_fit()` // // Reduces memory usage by freeing unused memory. After this call, calls to - // `capacity()` will be equal to `(std::max)(inlined_capacity(), size())`. + // `capacity()` will be equal to `(std::max)(GetInlinedCapacity(), size())`. // - // If `size() <= inlined_capacity()` and the elements are currently stored on - // the heap, they will be moved to the inlined storage and the heap memory + // If `size() <= GetInlinedCapacity()` and the elements are currently stored + // on the heap, they will be moved to the inlined storage and the heap memory // will be deallocated. // - // If `size() > inlined_capacity()` and `size() < capacity()` the elements + // If `size() > GetInlinedCapacity()` and `size() < capacity()` the elements // will be moved to a smaller heap allocation. void shrink_to_fit() { const auto s = size(); if (ABSL_PREDICT_FALSE(!allocated() || s == capacity())) return; - if (s <= inlined_capacity()) { + if (s <= GetInlinedCapacity()) { // Move the elements to the inlined storage. // We have to do this using a temporary, because `inlined_storage` and // `allocation_storage` are in a union field. @@ -833,7 +830,7 @@ class InlinedVector { private: template - friend H AbslHashValue(H, const InlinedVector& vector); + friend auto AbslHashValue(H h, const InlinedVector& v) -> H; // Holds whether the vector is allocated or not in the lowest bit and the size // in the high bits: @@ -984,7 +981,7 @@ class InlinedVector { const size_type s = size(); assert(s <= capacity()); - size_type target = (std::max)(inlined_capacity(), s + delta); + size_type target = (std::max)(GetInlinedCapacity(), s + delta); // Compute new capacity by repeatedly doubling current capacity // TODO(psrc): Check and avoid overflow? @@ -1087,7 +1084,7 @@ class InlinedVector { } void InitAssign(size_type n) { - if (n > inlined_capacity()) { + if (n > GetInlinedCapacity()) { Allocation new_allocation(allocator(), n); init_allocation(new_allocation); UninitializedFill(allocated_space(), allocated_space() + n); @@ -1099,7 +1096,7 @@ class InlinedVector { } void InitAssign(size_type n, const_reference v) { - if (n > inlined_capacity()) { + if (n > GetInlinedCapacity()) { Allocation new_allocation(allocator(), n); init_allocation(new_allocation); UninitializedFill(allocated_space(), allocated_space() + n, v); @@ -1323,8 +1320,8 @@ class InlinedVector { // Swaps the contents of two inlined vectors. This convenience function // simply calls `InlinedVector::swap()`. template -void swap(InlinedVector& a, - InlinedVector& b) noexcept(noexcept(a.swap(b))) { +auto swap(InlinedVector& a, + InlinedVector& b) noexcept(noexcept(a.swap(b))) -> void { a.swap(b); } @@ -1332,8 +1329,8 @@ void swap(InlinedVector& a, // // Tests the equivalency of the contents of two inlined vectors. template -bool operator==(const InlinedVector& a, - const InlinedVector& b) { +auto operator==(const InlinedVector& a, + const InlinedVector& b) -> bool { return absl::equal(a.begin(), a.end(), b.begin(), b.end()); } @@ -1341,8 +1338,8 @@ bool operator==(const InlinedVector& a, // // Tests the inequality of the contents of two inlined vectors. template -bool operator!=(const InlinedVector& a, - const InlinedVector& b) { +auto operator!=(const InlinedVector& a, + const InlinedVector& b) -> bool { return !(a == b); } @@ -1351,8 +1348,8 @@ bool operator!=(const InlinedVector& a, // Tests whether the contents of one inlined vector are less than the contents // of another through a lexicographical comparison operation. template -bool operator<(const InlinedVector& a, - const InlinedVector& b) { +auto operator<(const InlinedVector& a, const InlinedVector& b) + -> bool { return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); } @@ -1361,8 +1358,8 @@ bool operator<(const InlinedVector& a, // Tests whether the contents of one inlined vector are greater than the // contents of another through a lexicographical comparison operation. template -bool operator>(const InlinedVector& a, - const InlinedVector& b) { +auto operator>(const InlinedVector& a, const InlinedVector& b) + -> bool { return b < a; } @@ -1371,8 +1368,8 @@ bool operator>(const InlinedVector& a, // Tests whether the contents of one inlined vector are less than or equal to // the contents of another through a lexicographical comparison operation. template -bool operator<=(const InlinedVector& a, - const InlinedVector& b) { +auto operator<=(const InlinedVector& a, + const InlinedVector& b) -> bool { return !(b < a); } @@ -1381,8 +1378,8 @@ bool operator<=(const InlinedVector& a, // Tests whether the contents of one inlined vector are greater than or equal to // the contents of another through a lexicographical comparison operation. template -bool operator>=(const InlinedVector& a, - const InlinedVector& b) { +auto operator>=(const InlinedVector& a, + const InlinedVector& b) -> bool { return !(a < b); } @@ -1391,10 +1388,10 @@ bool operator>=(const InlinedVector& a, // Provides `absl::Hash` support for inlined vectors. You do not normally call // this function directly. template -H AbslHashValue(H hash, const InlinedVector& vector) { - auto p = vector.data(); - auto n = vector.size(); - return H::combine(H::combine_contiguous(std::move(hash), p, n), n); +auto AbslHashValue(H h, const InlinedVector& v) -> H { + auto p = v.data(); + auto n = v.size(); + return H::combine(H::combine_contiguous(std::move(h), p, n), n); } // ----------------------------------------------------------------------------- diff --git a/absl/time/internal/cctz/src/time_zone_format.cc b/absl/time/internal/cctz/src/time_zone_format.cc index aad52c27..a5c72df8 100644 --- a/absl/time/internal/cctz/src/time_zone_format.cc +++ b/absl/time/internal/cctz/src/time_zone_format.cc @@ -13,7 +13,7 @@ // limitations under the License. #if !defined(HAS_STRPTIME) -# if !defined(_MSC_VER) +# if !defined(_MSC_VER) && !defined(__MINGW32__) # define HAS_STRPTIME 1 // assume everyone has strptime() except windows # endif #endif diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc index 2cb358d0..6aa80ff6 100644 --- a/absl/time/internal/cctz/src/time_zone_info.cc +++ b/absl/time/internal/cctz/src/time_zone_info.cc @@ -921,7 +921,7 @@ bool TimeZoneInfo::NextTransition(const time_point& tp, ++begin; } std::int_fast64_t unix_time = ToUnixSeconds(tp); - const Transition target = { unix_time }; + const Transition target = {unix_time, 0, civil_second(), civil_second()}; const Transition* tr = std::upper_bound(begin, end, target, Transition::ByUnixTime()); for (; tr != end; ++tr) { // skip no-op transitions @@ -956,7 +956,7 @@ bool TimeZoneInfo::PrevTransition(const time_point& tp, } unix_time += 1; // ceils } - const Transition target = { unix_time }; + const Transition target = {unix_time, 0, civil_second(), civil_second()}; const Transition* tr = std::lower_bound(begin, end, target, Transition::ByUnixTime()); for (; tr != begin; --tr) { // skip no-op transitions diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc index 6db519e1..28291708 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/absl/time/internal/cctz/src/time_zone_libc.cc @@ -267,13 +267,13 @@ time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const { return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; } -bool TimeZoneLibC::NextTransition(const time_point& tp, - time_zone::civil_transition* trans) const { +bool TimeZoneLibC::NextTransition(const time_point&, + time_zone::civil_transition*) const { return false; } -bool TimeZoneLibC::PrevTransition(const time_point& tp, - time_zone::civil_transition* trans) const { +bool TimeZoneLibC::PrevTransition(const time_point&, + time_zone::civil_transition*) const { return false; } -- cgit v1.2.3 From 256be563447a315f2a7993ec669460ba475fa86a Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 12 Mar 2019 11:39:15 -0700 Subject: Export of internal Abseil changes. -- 00d42e3d5433aaf29c2ed293520b2ba178ae8bdb by Greg Falcon : Import of CCTZ from GitHub. PiperOrigin-RevId: 238061818 -- 867a7ca318fac2991ea9a4107dbae3cc9fbf974a by Abseil Team : Added a IWYU export pragma when including a standard header for the purpose of aliasing its symbols. PiperOrigin-RevId: 238022277 -- 17047745058f2f151cd986ea9f649512542d3876 by Matt Armstrong : Clarify the comment discouraging WrapUnique(x) calls. PiperOrigin-RevId: 237873803 -- 3dcb2e4968243d33ca0ce53280c445df50f4a7ec by Samuel Benzaquen : Workaround clang bug https://bugs.llvm.org/show_bug.cgi?id=38289 PiperOrigin-RevId: 237873551 -- f348d2dc7087a990cbdfb95aa51fd7ff478ae40e by Samuel Benzaquen : Reduce minimum capacity to 1. This reduces memory usage for small tables. A flat_hash_set of 1 element goes from 92 bytes to 24. A flat_hash_set of 1 element goes from 512 bytes to 56. PiperOrigin-RevId: 237859811 -- 9c8125be5e4e5d22a7bb62bdec8c323338385c1b by Jon Cohen : Bump to CMake 3.5. This is the oldest modern cmake being included by default in most popular OS distributions according to https://repology.org/project/cmake/versions. Specifically, Ubuntu LTS 16.04 uses cmake 3.5 (https://packages.ubuntu.com/xenial/cmake) PiperOrigin-RevId: 237859345 -- 07638d672e0a4dced986a62750cfd8318ed36ffa by Derek Mauro : Import of CCTZ from GitHub. PiperOrigin-RevId: 237714597 GitOrigin-RevId: 00d42e3d5433aaf29c2ed293520b2ba178ae8bdb Change-Id: I5faecc45add4a5a774d4f9baf06e5519091f2ccc --- CMakeLists.txt | 9 +- absl/container/flat_hash_map_test.cc | 1 + absl/container/internal/raw_hash_set.h | 46 +++++--- absl/container/internal/raw_hash_set_test.cc | 125 ++++++++++----------- absl/memory/memory.h | 15 +-- absl/numeric/int128.cc | 22 ++++ absl/numeric/int128_test.cc | 14 +++ absl/strings/string_view.h | 2 +- absl/time/internal/cctz/BUILD.bazel | 2 +- absl/time/internal/cctz/include/cctz/civil_time.h | 2 +- .../internal/cctz/include/cctz/civil_time_detail.h | 2 +- absl/time/internal/cctz/include/cctz/time_zone.h | 4 +- .../internal/cctz/include/cctz/zone_info_source.h | 2 +- absl/time/internal/cctz/src/cctz_benchmark.cc | 2 +- absl/time/internal/cctz/src/civil_time_detail.cc | 2 +- absl/time/internal/cctz/src/civil_time_test.cc | 2 +- absl/time/internal/cctz/src/time_zone_fixed.cc | 2 +- absl/time/internal/cctz/src/time_zone_fixed.h | 2 +- absl/time/internal/cctz/src/time_zone_format.cc | 2 +- .../internal/cctz/src/time_zone_format_test.cc | 2 +- absl/time/internal/cctz/src/time_zone_if.cc | 2 +- absl/time/internal/cctz/src/time_zone_if.h | 2 +- absl/time/internal/cctz/src/time_zone_impl.cc | 2 +- absl/time/internal/cctz/src/time_zone_impl.h | 2 +- absl/time/internal/cctz/src/time_zone_info.cc | 4 +- absl/time/internal/cctz/src/time_zone_info.h | 2 +- absl/time/internal/cctz/src/time_zone_libc.cc | 2 +- absl/time/internal/cctz/src/time_zone_libc.h | 2 +- absl/time/internal/cctz/src/time_zone_lookup.cc | 14 ++- .../internal/cctz/src/time_zone_lookup_test.cc | 2 +- absl/time/internal/cctz/src/time_zone_posix.cc | 2 +- absl/time/internal/cctz/src/time_zone_posix.h | 2 +- absl/time/internal/cctz/src/zone_info_source.cc | 2 +- .../internal/cctz/testdata/zoneinfo/iso3166.tab | 2 +- absl/types/any.h | 2 +- absl/types/optional.h | 2 +- absl/types/variant.h | 2 +- 37 files changed, 180 insertions(+), 128 deletions(-) (limited to 'absl/time/internal/cctz/src/time_zone_libc.cc') diff --git a/CMakeLists.txt b/CMakeLists.txt index a56d238b..571e48c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,9 +14,12 @@ # limitations under the License. # -# We require 3.0 for modern, target-based CMake. We require 3.1 for the use of -# CXX_STANDARD in our targets. -cmake_minimum_required(VERSION 3.1) +# Most widely used distributions have cmake 3.5 or greater available as of March +# 2019. A notable exception is RHEL-7 (CentOS7). You can install a current +# version of CMake by first installing Extra Packages for Enterprise Linux +# (https://fedoraproject.org/wiki/EPEL#Extra_Packages_for_Enterprise_Linux_.28EPEL.29) +# and then issuing `yum install cmake3` on the command line. +cmake_minimum_required(VERSION 3.5) # Compiler id for Apple Clang is now AppleClang. if (POLICY CMP0025) diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc index 562305e4..bae5c15d 100644 --- a/absl/container/flat_hash_map_test.cc +++ b/absl/container/flat_hash_map_test.cc @@ -141,6 +141,7 @@ TEST(FlatHashMap, LazyKeyPattern) { int conversions = 0; int hashes = 0; flat_hash_map m(0, Hash{&hashes}); + m.reserve(3); m[LazyInt(1, &conversions)] = 1; EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 1))); diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index c4f198bb..85e33344 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -446,9 +446,7 @@ using Group = GroupPortableImpl; template class raw_hash_set; -inline bool IsValidCapacity(size_t n) { - return ((n + 1) & n) == 0 && n >= Group::kWidth - 1; -} +inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; } // PRECONDITION: // IsValidCapacity(capacity) @@ -470,13 +468,9 @@ inline void ConvertDeletedToEmptyAndFullToDeleted( ctrl[capacity] = kSentinel; } -// Rounds up the capacity to the next power of 2 minus 1 and ensures it is -// greater or equal to Group::kWidth - 1. +// Rounds up the capacity to the next power of 2 minus 1, with a minimum of 1. inline size_t NormalizeCapacity(size_t n) { - constexpr size_t kMinCapacity = Group::kWidth - 1; - return n <= kMinCapacity - ? kMinCapacity - : (std::numeric_limits::max)() >> LeadingZeros(n); + return n ? ~size_t{} >> LeadingZeros(n) : 1; } // We use 7/8th as maximum load factor. @@ -1507,6 +1501,7 @@ class raw_hash_set { void drop_deletes_without_resize() ABSL_ATTRIBUTE_NOINLINE { assert(IsValidCapacity(capacity_)); + assert(!is_small()); // Algorithm: // - mark all DELETED slots as EMPTY // - mark all FULL slots as DELETED @@ -1572,7 +1567,7 @@ class raw_hash_set { void rehash_and_grow_if_necessary() { if (capacity_ == 0) { - resize(Group::kWidth - 1); + resize(1); } else if (size() <= CapacityToGrowth(capacity()) / 2) { // Squash DELETED without growing if there is enough capacity. drop_deletes_without_resize(); @@ -1619,17 +1614,15 @@ class raw_hash_set { auto mask = g.MatchEmptyOrDeleted(); if (mask) { #if !defined(NDEBUG) - // We want to force small tables to have random entries too, so - // in debug build we will randomly insert in either the front or back of + // We want to add entropy even when ASLR is not enabled. + // In debug build we will randomly insert in either the front or back of // the group. // TODO(kfm,sbenza): revisit after we do unconditional mixing - if (ShouldInsertBackwards(hash, ctrl_)) + if (!is_small() && ShouldInsertBackwards(hash, ctrl_)) { return {seq.offset(mask.HighestBitSet()), seq.index()}; - else - return {seq.offset(mask.LowestBitSet()), seq.index()}; -#else - return {seq.offset(mask.LowestBitSet()), seq.index()}; + } #endif + return {seq.offset(mask.LowestBitSet()), seq.index()}; } assert(seq.index() < capacity_ && "full table!"); seq.next(); @@ -1732,11 +1725,28 @@ class raw_hash_set { } ctrl_[i] = h; - ctrl_[((i - Group::kWidth) & capacity_) + Group::kWidth] = h; + ctrl_[((i - Group::kWidth) & capacity_) + 1 + + ((Group::kWidth - 1) & capacity_)] = h; } size_t& growth_left() { return settings_.template get<0>(); } + // The representation of the object has two modes: + // - small: For capacities < kWidth-1 + // - large: For the rest. + // + // Differences: + // - In small mode we are able to use the whole capacity. The extra control + // bytes give us at least one "empty" control byte to stop the iteration. + // This is important to make 1 a valid capacity. + // + // - In small mode only the first `capacity()` control bytes after the + // sentinel are valid. The rest contain dummy kEmpty values that do not + // represent a real slot. This is important to take into account on + // find_first_non_full(), where we never try ShouldInsertBackwards() for + // small tables. + bool is_small() const { return capacity_ < Group::kWidth - 1; } + hasher& hash_ref() { return settings_.template get<1>(); } const hasher& hash_ref() const { return settings_.template get<1>(); } key_equal& eq_ref() { return settings_.template get<2>(); } diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index b684571f..db0bb823 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -55,13 +55,16 @@ using ::testing::Pair; using ::testing::UnorderedElementsAre; TEST(Util, NormalizeCapacity) { - constexpr size_t kMinCapacity = Group::kWidth - 1; - EXPECT_EQ(kMinCapacity, NormalizeCapacity(0)); - EXPECT_EQ(kMinCapacity, NormalizeCapacity(1)); - EXPECT_EQ(kMinCapacity, NormalizeCapacity(2)); - EXPECT_EQ(kMinCapacity, NormalizeCapacity(kMinCapacity)); - EXPECT_EQ(kMinCapacity * 2 + 1, NormalizeCapacity(kMinCapacity + 1)); - EXPECT_EQ(kMinCapacity * 2 + 1, NormalizeCapacity(kMinCapacity + 2)); + EXPECT_EQ(1, NormalizeCapacity(0)); + EXPECT_EQ(1, NormalizeCapacity(1)); + EXPECT_EQ(3, NormalizeCapacity(2)); + EXPECT_EQ(3, NormalizeCapacity(3)); + EXPECT_EQ(7, NormalizeCapacity(4)); + EXPECT_EQ(7, NormalizeCapacity(7)); + EXPECT_EQ(15, NormalizeCapacity(8)); + EXPECT_EQ(15, NormalizeCapacity(15)); + EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 1)); + EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 2)); } TEST(Util, GrowthAndCapacity) { @@ -72,10 +75,7 @@ TEST(Util, GrowthAndCapacity) { size_t capacity = NormalizeCapacity(GrowthToLowerboundCapacity(growth)); // The capacity is large enough for `growth` EXPECT_THAT(CapacityToGrowth(capacity), Ge(growth)); - if (growth < Group::kWidth - 1) { - // Fits in one group, that is the minimum capacity. - EXPECT_EQ(capacity, Group::kWidth - 1); - } else { + if (growth != 0 && capacity > 1) { // There is no smaller capacity that works. EXPECT_THAT(CapacityToGrowth(capacity / 2), Lt(growth)); } @@ -814,7 +814,7 @@ TEST(Table, EnsureNonQuadraticAsInRust) { TEST(Table, ClearBug) { IntTable t; constexpr size_t capacity = container_internal::Group::kWidth - 1; - constexpr size_t max_size = capacity / 2; + constexpr size_t max_size = capacity / 2 + 1; for (size_t i = 0; i < max_size; ++i) { t.insert(i); } @@ -1741,80 +1741,74 @@ TEST(Nodes, ExtractInsert) { EXPECT_FALSE(node); } -StringTable MakeSimpleTable(size_t size) { - StringTable t; - for (size_t i = 0; i < size; ++i) t.emplace(std::string(1, 'A' + i), ""); +IntTable MakeSimpleTable(size_t size) { + IntTable t; + while (t.size() < size) t.insert(t.size()); return t; } -std::string OrderOfIteration(const StringTable& t) { - std::string order; - for (auto& p : t) order += p.first; - return order; +std::vector OrderOfIteration(const IntTable& t) { + return {t.begin(), t.end()}; } +// These IterationOrderChanges tests depend on non-deterministic behavior. +// We are injecting non-determinism from the pointer of the table, but do so in +// a way that only the page matters. We have to retry enough times to make sure +// we are touching different memory pages to cause the ordering to change. +// We also need to keep the old tables around to avoid getting the same memory +// blocks over and over. TEST(Table, IterationOrderChangesByInstance) { - // Needs to be more than kWidth elements to be able to affect order. - const StringTable reference = MakeSimpleTable(20); - - // Since order is non-deterministic we can't just try once and verify. - // We'll try until we find that order changed. It should not take many tries - // for that. - // Important: we have to keep the old tables around. Otherwise tcmalloc will - // just give us the same blocks and we would be doing the same order again. - std::vector garbage; - for (int i = 0; i < 10; ++i) { - auto trial = MakeSimpleTable(20); - if (OrderOfIteration(trial) != OrderOfIteration(reference)) { - // We are done. - return; + for (size_t size : {2, 6, 12, 20}) { + const auto reference_table = MakeSimpleTable(size); + const auto reference = OrderOfIteration(reference_table); + + std::vector tables; + bool found_difference = false; + for (int i = 0; !found_difference && i < 500; ++i) { + tables.push_back(MakeSimpleTable(size)); + found_difference = OrderOfIteration(tables.back()) != reference; + } + if (!found_difference) { + FAIL() + << "Iteration order remained the same across many attempts with size " + << size; } - garbage.push_back(std::move(trial)); } - FAIL(); } TEST(Table, IterationOrderChangesOnRehash) { - // Since order is non-deterministic we can't just try once and verify. - // We'll try until we find that order changed. It should not take many tries - // for that. - // Important: we have to keep the old tables around. Otherwise tcmalloc will - // just give us the same blocks and we would be doing the same order again. - std::vector garbage; - for (int i = 0; i < 10; ++i) { - // Needs to be more than kWidth elements to be able to affect order. - StringTable t = MakeSimpleTable(20); - const std::string reference = OrderOfIteration(t); + std::vector garbage; + for (int i = 0; i < 500; ++i) { + auto t = MakeSimpleTable(20); + const auto reference = OrderOfIteration(t); // Force rehash to the same size. t.rehash(0); - std::string trial = OrderOfIteration(t); + auto trial = OrderOfIteration(t); if (trial != reference) { // We are done. return; } garbage.push_back(std::move(t)); } - FAIL(); + FAIL() << "Iteration order remained the same across many attempts."; } -TEST(Table, IterationOrderChangesForSmallTables) { - // Since order is non-deterministic we can't just try once and verify. - // We'll try until we find that order changed. - // Important: we have to keep the old tables around. Otherwise tcmalloc will - // just give us the same blocks and we would be doing the same order again. - StringTable reference_table = MakeSimpleTable(5); - const std::string reference = OrderOfIteration(reference_table); - std::vector garbage; - for (int i = 0; i < 50; ++i) { - StringTable t = MakeSimpleTable(5); - std::string trial = OrderOfIteration(t); - if (trial != reference) { - // We are done. - return; - } - garbage.push_back(std::move(t)); - } - FAIL() << "Iteration order remained the same across many attempts."; +// Verify that pointers are invalidated as soon as a second element is inserted. +// This prevents dependency on pointer stability on small tables. +TEST(Table, UnstablePointers) { + IntTable table; + + const auto addr = [&](int i) { + return reinterpret_cast(&*table.find(i)); + }; + + table.insert(0); + const uintptr_t old_ptr = addr(0); + + // This causes a rehash. + table.insert(1); + + EXPECT_NE(old_ptr, addr(0)); } // Confirm that we assert if we try to erase() end(). @@ -1857,6 +1851,7 @@ TEST(RawHashSamplerTest, Sample) { #ifdef ADDRESS_SANITIZER TEST(Sanitizer, PoisoningUnused) { IntTable t; + t.reserve(5); // Insert something to force an allocation. int64_t& v1 = *t.insert(0).first; diff --git a/absl/memory/memory.h b/absl/memory/memory.h index a0d0714f..5a4a1a1d 100644 --- a/absl/memory/memory.h +++ b/absl/memory/memory.h @@ -47,19 +47,14 @@ namespace absl { // X* NewX(int, int); // auto x = WrapUnique(NewX(1, 2)); // 'x' is std::unique_ptr. // -// The purpose of WrapUnique is to automatically deduce the pointer type. If you -// wish to make the type explicit, for readability reasons or because you prefer -// to use a base-class pointer rather than a derived one, just use +// Do not call WrapUnique with an explicit type, as in +// `WrapUnique(NewX(1, 2))`. The purpose of WrapUnique is to automatically +// deduce the pointer type. If you wish to make the type explicit, just use // `std::unique_ptr` directly. // -// Example: -// X* Factory(int, int); -// auto x = std::unique_ptr(Factory(1, 2)); +// auto x = std::unique_ptr(NewX(1, 2)); // - or - -// std::unique_ptr x(Factory(1, 2)); -// -// This has the added advantage of working whether Factory returns a raw -// pointer or a `std::unique_ptr`. +// std::unique_ptr x(NewX(1, 2)); // // While `absl::WrapUnique` is useful for capturing the output of a raw // pointer factory, prefer 'absl::make_unique(args...)' over diff --git a/absl/numeric/int128.cc b/absl/numeric/int128.cc index 33f528ce..93b62c52 100644 --- a/absl/numeric/int128.cc +++ b/absl/numeric/int128.cc @@ -123,6 +123,28 @@ uint128 MakeUint128FromFloat(T v) { return MakeUint128(0, static_cast(v)); } + +#if defined(__clang__) && !defined(__SSE3__) +// Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289 +// Casting from long double to uint64_t is miscompiled and drops bits. +// It is more work, so only use when we need the workaround. +uint128 MakeUint128FromFloat(long double v) { + // Go 50 bits at a time, that fits in a double + static_assert(std::numeric_limits::digits >= 50, ""); + static_assert(std::numeric_limits::digits <= 150, ""); + // Undefined behavior if v is not finite or cannot fit into uint128. + assert(std::isfinite(v) && v > -1 && v < std::ldexp(1.0L, 128)); + + v = std::ldexp(v, -100); + uint64_t w0 = static_cast(static_cast(std::trunc(v))); + v = std::ldexp(v - static_cast(w0), 50); + uint64_t w1 = static_cast(static_cast(std::trunc(v))); + v = std::ldexp(v - static_cast(w1), 50); + uint64_t w2 = static_cast(static_cast(std::trunc(v))); + return (static_cast(w0) << 100) | (static_cast(w1) << 50) | + static_cast(w2); +} +#endif // __clang__ && !__SSE3__ } // namespace uint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {} diff --git a/absl/numeric/int128_test.cc b/absl/numeric/int128_test.cc index 216ec50c..5e1b5ec3 100644 --- a/absl/numeric/int128_test.cc +++ b/absl/numeric/int128_test.cc @@ -271,6 +271,20 @@ TEST(Uint128, ConversionTests) { EXPECT_EQ(static_cast(round_to_zero), 0); EXPECT_EQ(static_cast(round_to_five), 5); EXPECT_EQ(static_cast(round_to_nine), 9); + + absl::uint128 highest_precision_in_long_double = + ~absl::uint128{} >> (128 - std::numeric_limits::digits); + EXPECT_EQ(highest_precision_in_long_double, + static_cast( + static_cast(highest_precision_in_long_double))); + // Apply a mask just to make sure all the bits are the right place. + const absl::uint128 arbitrary_mask = + absl::MakeUint128(0xa29f622677ded751, 0xf8ca66add076f468); + EXPECT_EQ(highest_precision_in_long_double & arbitrary_mask, + static_cast(static_cast( + highest_precision_in_long_double & arbitrary_mask))); + + EXPECT_EQ(static_cast(-0.1L), 0); } TEST(Uint128, OperatorAssignReturnRef) { diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h index 524dbebb..bd894e1d 100644 --- a/absl/strings/string_view.h +++ b/absl/strings/string_view.h @@ -32,7 +32,7 @@ #ifdef ABSL_HAVE_STD_STRING_VIEW -#include +#include // IWYU pragma: export namespace absl { using std::string_view; diff --git a/absl/time/internal/cctz/BUILD.bazel b/absl/time/internal/cctz/BUILD.bazel index 1fb33c20..903499be 100644 --- a/absl/time/internal/cctz/BUILD.bazel +++ b/absl/time/internal/cctz/BUILD.bazel @@ -4,7 +4,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/include/cctz/civil_time.h b/absl/time/internal/cctz/include/cctz/civil_time.h index 0842fa4a..f844182b 100644 --- a/absl/time/internal/cctz/include/cctz/civil_time.h +++ b/absl/time/internal/cctz/include/cctz/civil_time.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/include/cctz/civil_time_detail.h b/absl/time/internal/cctz/include/cctz/civil_time_detail.h index 1c5d0970..a5923f13 100644 --- a/absl/time/internal/cctz/include/cctz/civil_time_detail.h +++ b/absl/time/internal/cctz/include/cctz/civil_time_detail.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/include/cctz/time_zone.h b/absl/time/internal/cctz/include/cctz/time_zone.h index f28dad17..ef6c4ba1 100644 --- a/absl/time/internal/cctz/include/cctz/time_zone.h +++ b/absl/time/internal/cctz/include/cctz/time_zone.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -72,7 +72,7 @@ split_seconds(const time_point& tp) { // // See also: // - http://www.iana.org/time-zones -// - http://en.wikipedia.org/wiki/Zoneinfo +// - https://en.wikipedia.org/wiki/Zoneinfo class time_zone { public: time_zone() : time_zone(nullptr) {} // Equivalent to UTC diff --git a/absl/time/internal/cctz/include/cctz/zone_info_source.h b/absl/time/internal/cctz/include/cctz/zone_info_source.h index 20a76979..2b898d18 100644 --- a/absl/time/internal/cctz/include/cctz/zone_info_source.h +++ b/absl/time/internal/cctz/include/cctz/zone_info_source.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/cctz_benchmark.cc b/absl/time/internal/cctz/src/cctz_benchmark.cc index a00f47bf..445366ea 100644 --- a/absl/time/internal/cctz/src/cctz_benchmark.cc +++ b/absl/time/internal/cctz/src/cctz_benchmark.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/civil_time_detail.cc b/absl/time/internal/cctz/src/civil_time_detail.cc index 780d5c96..cb40b6bc 100644 --- a/absl/time/internal/cctz/src/civil_time_detail.cc +++ b/absl/time/internal/cctz/src/civil_time_detail.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/civil_time_test.cc b/absl/time/internal/cctz/src/civil_time_test.cc index faffde47..e590ee30 100644 --- a/absl/time/internal/cctz/src/civil_time_test.cc +++ b/absl/time/internal/cctz/src/civil_time_test.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/time_zone_fixed.cc b/absl/time/internal/cctz/src/time_zone_fixed.cc index db9a475a..81ece72b 100644 --- a/absl/time/internal/cctz/src/time_zone_fixed.cc +++ b/absl/time/internal/cctz/src/time_zone_fixed.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/time_zone_fixed.h b/absl/time/internal/cctz/src/time_zone_fixed.h index 489b857d..9c1f5e7d 100644 --- a/absl/time/internal/cctz/src/time_zone_fixed.h +++ b/absl/time/internal/cctz/src/time_zone_fixed.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/time_zone_format.cc b/absl/time/internal/cctz/src/time_zone_format.cc index a5c72df8..25850980 100644 --- a/absl/time/internal/cctz/src/time_zone_format.cc +++ b/absl/time/internal/cctz/src/time_zone_format.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/time_zone_format_test.cc b/absl/time/internal/cctz/src/time_zone_format_test.cc index b99e1c63..705ccdcd 100644 --- a/absl/time/internal/cctz/src/time_zone_format_test.cc +++ b/absl/time/internal/cctz/src/time_zone_format_test.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/time_zone_if.cc b/absl/time/internal/cctz/src/time_zone_if.cc index 380834a1..09aaee5f 100644 --- a/absl/time/internal/cctz/src/time_zone_if.cc +++ b/absl/time/internal/cctz/src/time_zone_if.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/time_zone_if.h b/absl/time/internal/cctz/src/time_zone_if.h index e4bd3866..d000b7a5 100644 --- a/absl/time/internal/cctz/src/time_zone_if.h +++ b/absl/time/internal/cctz/src/time_zone_if.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/time_zone_impl.cc b/absl/time/internal/cctz/src/time_zone_impl.cc index 3062ccd3..3cbc6746 100644 --- a/absl/time/internal/cctz/src/time_zone_impl.cc +++ b/absl/time/internal/cctz/src/time_zone_impl.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/time_zone_impl.h b/absl/time/internal/cctz/src/time_zone_impl.h index 14965ef5..b73fad9b 100644 --- a/absl/time/internal/cctz/src/time_zone_impl.h +++ b/absl/time/internal/cctz/src/time_zone_impl.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc index 6aa80ff6..50f7de54 100644 --- a/absl/time/internal/cctz/src/time_zone_info.cc +++ b/absl/time/internal/cctz/src/time_zone_info.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -25,7 +25,7 @@ // a grain of salt. // // For more information see tzfile(5), http://www.iana.org/time-zones, or -// http://en.wikipedia.org/wiki/Zoneinfo. +// https://en.wikipedia.org/wiki/Zoneinfo. // // Note that we assume the proleptic Gregorian calendar and 60-second // minutes throughout. diff --git a/absl/time/internal/cctz/src/time_zone_info.h b/absl/time/internal/cctz/src/time_zone_info.h index 958e9b6b..bff639f4 100644 --- a/absl/time/internal/cctz/src/time_zone_info.h +++ b/absl/time/internal/cctz/src/time_zone_info.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc index 28291708..3ab1623c 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/absl/time/internal/cctz/src/time_zone_libc.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/time_zone_libc.h b/absl/time/internal/cctz/src/time_zone_libc.h index 4e40c61a..0d18e9a7 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.h +++ b/absl/time/internal/cctz/src/time_zone_libc.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/time_zone_lookup.cc b/absl/time/internal/cctz/src/time_zone_lookup.cc index f2d151e4..4a68c7d5 100644 --- a/absl/time/internal/cctz/src/time_zone_lookup.cc +++ b/absl/time/internal/cctz/src/time_zone_lookup.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -20,6 +20,11 @@ #include #endif #endif + +#if defined(__APPLE__) +#include +#endif + #include #include #include @@ -121,6 +126,11 @@ time_zone local_time_zone() { char* tz_env = nullptr; #if defined(_MSC_VER) _dupenv_s(&tz_env, nullptr, "TZ"); +#elif defined(__APPLE__) + CFTimeZoneRef system_time_zone = CFTimeZoneCopySystem(); + CFStringRef tz_name = CFTimeZoneGetName(system_time_zone); + tz_env = strdup(CFStringGetCStringPtr(tz_name, CFStringGetSystemEncoding())); + CFRelease(system_time_zone); #else tz_env = std::getenv("TZ"); #endif @@ -153,6 +163,8 @@ time_zone local_time_zone() { #if defined(_MSC_VER) free(localtime_env); free(tz_env); +#elif defined(__APPLE__) + free(tz_env); #endif time_zone tz; diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc index 2e49e48c..8068e2fc 100644 --- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc +++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/time_zone_posix.cc b/absl/time/internal/cctz/src/time_zone_posix.cc index 75ad8bcb..993901ac 100644 --- a/absl/time/internal/cctz/src/time_zone_posix.cc +++ b/absl/time/internal/cctz/src/time_zone_posix.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/time_zone_posix.h b/absl/time/internal/cctz/src/time_zone_posix.h index ef2a8c16..6a60022f 100644 --- a/absl/time/internal/cctz/src/time_zone_posix.h +++ b/absl/time/internal/cctz/src/time_zone_posix.h @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/src/zone_info_source.cc b/absl/time/internal/cctz/src/zone_info_source.cc index 1bc16aec..13248462 100644 --- a/absl/time/internal/cctz/src/zone_info_source.cc +++ b/absl/time/internal/cctz/src/zone_info_source.cc @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab b/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab index c2e0f8ea..4e4a5c3d 100644 --- a/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab +++ b/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab @@ -10,7 +10,7 @@ # # 1. ISO 3166-1 alpha-2 country code, current as of # ISO 3166-1 N905 (2016-11-15). See: Updates on ISO 3166-1 -# http://isotc.iso.org/livelink/livelink/Open/16944257 +# https://isotc.iso.org/livelink/livelink/Open/16944257 # 2. The usual English name for the coded region, # chosen so that alphabetic sorting of subsets produces helpful lists. # This is not the same as the English name in the ISO 3166 tables. diff --git a/absl/types/any.h b/absl/types/any.h index e750f485..f3a32812 100644 --- a/absl/types/any.h +++ b/absl/types/any.h @@ -58,7 +58,7 @@ #ifdef ABSL_HAVE_STD_ANY -#include +#include // IWYU pragma: export namespace absl { using std::any; diff --git a/absl/types/optional.h b/absl/types/optional.h index 0c1213f4..a86dea92 100644 --- a/absl/types/optional.h +++ b/absl/types/optional.h @@ -40,7 +40,7 @@ #ifdef ABSL_HAVE_STD_OPTIONAL -#include +#include // IWYU pragma: export namespace absl { using std::bad_optional_access; diff --git a/absl/types/variant.h b/absl/types/variant.h index 9652e3b9..8d8b5dbd 100644 --- a/absl/types/variant.h +++ b/absl/types/variant.h @@ -47,7 +47,7 @@ #ifdef ABSL_HAVE_STD_VARIANT -#include +#include // IWYU pragma: export namespace absl { using std::bad_variant_access; -- cgit v1.2.3 From 361cb8a9db2f2130442389fd80593255be26d681 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 10 Jun 2019 01:57:44 -0700 Subject: Export of internal Abseil changes. -- 4a21ad4ffa957d28b770de8717289fab7410f567 by Gennadiy Rozental : Internal cleanup PiperOrigin-RevId: 252366381 -- b6b0f25439549c54f1537a16625be1fecd3c7d8c by Xiaoyi Zhang : Fix C4245 compiler warning of visual studio. This allows using abseil headers in code requiring strict warning settings. This is an import of https://github.com/abseil/abseil-cpp/pull/321. PiperOrigin-RevId: 252101240 -- 0543b7861b658a5a665298e1d868e29968ff7b27 by CJ Johnson : Adds new benchmarks for the constructors of InlinedVector PiperOrigin-RevId: 251905349 -- c65a08507917e9f8f6450b8beb235fe1426d7954 by CJ Johnson : Updates the InlinedVector BatchedBenchmark abstractions to 1) provide the index of the instance back to the prepare and test functions so that callers may perform extra work on local state with a unique per-instance ID and 2) reduce the number of manually written calls to BENCHMARK_TEMPLATE. PiperOrigin-RevId: 251895546 -- 99a1ae2d786b80096172f6e018711e15c0c750b9 by Samuel Benzaquen : Fix ambiguous construction problem in absl::variant<> to make in line with std::variant. ImaginaryFun is hiding duplicate objects instead of causing ambiguity. Add a second unique argument to make sure all overloads exist in the final overload set. PiperOrigin-RevId: 251860694 -- b54d0a12673be6ebb6e77e24a556ce9b758b3a7e by Abseil Team : Import of CCTZ from GitHub. PiperOrigin-RevId: 251739183 -- f51b115e0dc3fc9a9c9c20b33a1f27027a700d48 by Abseil Team : Import of CCTZ from GitHub. PiperOrigin-RevId: 251686812 -- 30e868049282dc6a6fc77d923ca7d2a5d35a1658 by Xiaoyi Zhang : Import of CCTZ from GitHub. PiperOrigin-RevId: 251652119 GitOrigin-RevId: 4a21ad4ffa957d28b770de8717289fab7410f567 Change-Id: I7171cb613793fa90e0eb0143b65ec8264a2a84db --- absl/container/inlined_vector_benchmark.cc | 110 ++++++++++++++++++++-- absl/flags/internal/flag.h | 2 +- absl/flags/marshalling.h | 9 +- absl/time/internal/cctz/include/cctz/civil_time.h | 4 +- absl/time/internal/cctz/src/civil_time_test.cc | 2 +- absl/time/internal/cctz/src/time_zone_info.cc | 3 +- absl/time/internal/cctz/src/time_zone_libc.cc | 95 +++++++++++-------- absl/time/internal/cctz/src/zone_info_source.cc | 18 ++-- absl/types/internal/variant.h | 12 ++- absl/types/variant_test.cc | 5 + 10 files changed, 182 insertions(+), 78 deletions(-) (limited to 'absl/time/internal/cctz/src/time_zone_libc.cc') diff --git a/absl/container/inlined_vector_benchmark.cc b/absl/container/inlined_vector_benchmark.cc index b57fc1de..a8368d41 100644 --- a/absl/container/inlined_vector_benchmark.cc +++ b/absl/container/inlined_vector_benchmark.cc @@ -379,6 +379,10 @@ constexpr size_t kLargeSize = kInlinedCapacity * 2; constexpr size_t kSmallSize = kInlinedCapacity / 2; constexpr size_t kBatchSize = 100; +#define ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_FunctionTemplate, T) \ + BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kLargeSize); \ + BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kSmallSize) + template using InlVec = absl::InlinedVector; @@ -420,29 +424,115 @@ void BatchedBenchmark(benchmark::State& state, PrepareVecFn prepare_vec, while (state.KeepRunningBatch(kBatchSize)) { // Prepare batch state.PauseTiming(); - for (auto& vec : vector_batch) { - prepare_vec(&vec); + for (size_t i = 0; i < kBatchSize; ++i) { + prepare_vec(vector_batch.data() + i, i); } benchmark::DoNotOptimize(vector_batch); state.ResumeTiming(); // Test batch - for (auto& vec : vector_batch) { - test_vec(&vec); + for (size_t i = 0; i < kBatchSize; ++i) { + test_vec(vector_batch.data() + i, i); } } } +template +void BM_ConstructFromSize(benchmark::State& state) { + using VecT = InlVec; + auto size = ToSize; + BatchedBenchmark( + state, + /* prepare_vec = */ [](InlVec* vec, size_t) { vec->~VecT(); }, + /* test_vec = */ + [&](void* ptr, size_t) { + benchmark::DoNotOptimize(size); + ::new (ptr) VecT(size); + }); +} +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSize, TrivialType); +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSize, NontrivialType); + +template +void BM_ConstructFromSizeRef(benchmark::State& state) { + using VecT = InlVec; + auto size = ToSize; + auto ref = T(); + BatchedBenchmark( + state, + /* prepare_vec = */ [](InlVec* vec, size_t) { vec->~VecT(); }, + /* test_vec = */ + [&](void* ptr, size_t) { + benchmark::DoNotOptimize(size); + benchmark::DoNotOptimize(ref); + ::new (ptr) VecT(size, ref); + }); +} +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSizeRef, TrivialType); +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSizeRef, NontrivialType); + +template +void BM_ConstructFromRange(benchmark::State& state) { + using VecT = InlVec; + std::array arr{}; + BatchedBenchmark( + state, + /* prepare_vec = */ [](InlVec* vec, size_t) { vec->~VecT(); }, + /* test_vec = */ + [&](void* ptr, size_t) { + benchmark::DoNotOptimize(arr); + ::new (ptr) VecT(arr.begin(), arr.end()); + }); +} +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromRange, TrivialType); +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromRange, NontrivialType); + +template +void BM_ConstructFromCopy(benchmark::State& state) { + using VecT = InlVec; + VecT other_vec(ToSize); + BatchedBenchmark( + state, + /* prepare_vec = */ + [](InlVec* vec, size_t) { vec->~VecT(); }, + /* test_vec = */ + [&](void* ptr, size_t) { + benchmark::DoNotOptimize(other_vec); + ::new (ptr) VecT(other_vec); + }); +} +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromCopy, TrivialType); +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromCopy, NontrivialType); + +template +void BM_ConstructFromMove(benchmark::State& state) { + using VecT = InlVec; + std::array vector_batch{}; + BatchedBenchmark( + state, + /* prepare_vec = */ + [&](InlVec* vec, size_t i) { + vector_batch[i].clear(); + vector_batch[i].resize(ToSize); + vec->~VecT(); + }, + /* test_vec = */ + [&](void* ptr, size_t i) { + benchmark::DoNotOptimize(vector_batch[i]); + ::new (ptr) VecT(std::move(vector_batch[i])); + }); +} +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromMove, TrivialType); +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromMove, NontrivialType); + template void BM_Clear(benchmark::State& state) { BatchedBenchmark( state, - /* prepare_vec = */ [](InlVec* vec) { vec->resize(FromSize); }, - /* test_vec = */ [](InlVec* vec) { vec->clear(); }); + /* prepare_vec = */ [](InlVec* vec, size_t) { vec->resize(FromSize); }, + /* test_vec = */ [](InlVec* vec, size_t) { vec->clear(); }); } -BENCHMARK_TEMPLATE(BM_Clear, TrivialType, kLargeSize); -BENCHMARK_TEMPLATE(BM_Clear, TrivialType, kSmallSize); -BENCHMARK_TEMPLATE(BM_Clear, NontrivialType, kLargeSize); -BENCHMARK_TEMPLATE(BM_Clear, NontrivialType, kSmallSize); +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_Clear, TrivialType); +ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_Clear, NontrivialType); } // namespace diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index 6402866f..9b32f467 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -56,7 +56,7 @@ class Flag { // forward declared types. // auto IsCopyConstructible(const T& v) -> decltype(T(v)); // auto HasAbslParseFlag(absl::string_view in, T* dst, std::string* err) - // -> decltype(AbslParseFlag(in, dst, GlobalStringADLGuard(err))); + // -> decltype(AbslParseFlag(in, dst, err)); // auto HasAbslUnparseFlag(const T& v) -> decltype(AbslUnparseFlag(v)); }; diff --git a/absl/flags/marshalling.h b/absl/flags/marshalling.h index 669cf452..7eb75cde 100644 --- a/absl/flags/marshalling.h +++ b/absl/flags/marshalling.h @@ -185,18 +185,11 @@ bool AbslParseFlag(absl::string_view, double*, std::string*); bool AbslParseFlag(absl::string_view, std::string*, std::string*); bool AbslParseFlag(absl::string_view, std::vector*, std::string*); -struct GlobalStringADLGuard { - explicit GlobalStringADLGuard(std::string* p) : ptr(p) {} - operator std::string*() { return ptr; } // NOLINT - std::string* ptr; -}; - template bool InvokeParseFlag(absl::string_view input, T* dst, std::string* err) { // Comment on next line provides a good compiler error message if T // does not have AbslParseFlag(absl::string_view, T*, std::string*). - return AbslParseFlag( // Is T missing AbslParseFlag? - input, dst, GlobalStringADLGuard(err)); + return AbslParseFlag(input, dst, err); // Is T missing AbslParseFlag? } // Strings and std:: containers do not have the same overload resolution diff --git a/absl/time/internal/cctz/include/cctz/civil_time.h b/absl/time/internal/cctz/include/cctz/civil_time.h index f844182b..aa578ee3 100644 --- a/absl/time/internal/cctz/include/cctz/civil_time.h +++ b/absl/time/internal/cctz/include/cctz/civil_time.h @@ -306,9 +306,9 @@ using detail::get_weekday; // // civil_day d = ... // // Gets the following Thursday if d is not already Thursday -// civil_day thurs1 = prev_weekday(d, weekday::thursday) + 7; +// civil_day thurs1 = next_weekday(d - 1, weekday::thursday); // // Gets the previous Thursday if d is not already Thursday -// civil_day thurs2 = next_weekday(d, weekday::thursday) - 7; +// civil_day thurs2 = prev_weekday(d + 1, weekday::thursday); // using detail::next_weekday; using detail::prev_weekday; diff --git a/absl/time/internal/cctz/src/civil_time_test.cc b/absl/time/internal/cctz/src/civil_time_test.cc index dc7e5a1d..b1f46f12 100644 --- a/absl/time/internal/cctz/src/civil_time_test.cc +++ b/absl/time/internal/cctz/src/civil_time_test.cc @@ -1035,7 +1035,7 @@ TEST(CivilTime, LeapYears) { TEST(CivilTime, FirstThursdayInMonth) { const civil_day nov1(2014, 11, 1); - const civil_day thursday = prev_weekday(nov1, weekday::thursday) + 7; + const civil_day thursday = next_weekday(nov1 - 1, weekday::thursday); EXPECT_EQ("2014-11-06", Format(thursday)); // Bonus: Date of Thanksgiving in the United States diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc index 50f7de54..184bd434 100644 --- a/absl/time/internal/cctz/src/time_zone_info.cc +++ b/absl/time/internal/cctz/src/time_zone_info.cc @@ -682,7 +682,6 @@ std::unique_ptr AndroidZoneInfoSource::Open( // Use of the "file:" prefix is intended for testing purposes only. if (name.compare(0, 5, "file:") == 0) return Open(name.substr(5)); -#if defined(__ANDROID__) // See Android's libc/tzcode/bionic.cpp for additional information. for (const char* tzdata : {"/data/misc/zoneinfo/current/tzdata", "/system/usr/share/zoneinfo/tzdata"}) { @@ -717,7 +716,7 @@ std::unique_ptr AndroidZoneInfoSource::Open( } } } -#endif // __ANDROID__ + return nullptr; } diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc index 3ab1623c..6095e764 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/absl/time/internal/cctz/src/time_zone_libc.cc @@ -21,7 +21,6 @@ #include #include #include -#include #include #include "absl/time/internal/cctz/include/cctz/civil_time.h" @@ -33,57 +32,75 @@ namespace cctz { namespace { -// .first is seconds east of UTC; .second is the time-zone abbreviation. -using OffsetAbbr = std::pair; - -// Defines a function that can be called as follows: -// -// std::tm tm = ...; -// OffsetAbbr off_abbr = get_offset_abbr(tm); -// #if defined(_WIN32) || defined(_WIN64) // Uses the globals: '_timezone', '_dstbias' and '_tzname'. -OffsetAbbr get_offset_abbr(const std::tm& tm) { +auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + _dstbias) { const bool is_dst = tm.tm_isdst > 0; - const int off = _timezone + (is_dst ? _dstbias : 0); - const char* abbr = _tzname[is_dst]; - return {off, abbr}; + return _timezone + (is_dst ? _dstbias : 0); +} +auto tm_zone(const std::tm& tm) -> decltype(_tzname[0]) { + const bool is_dst = tm.tm_isdst > 0; + return _tzname[is_dst]; } #elif defined(__sun) // Uses the globals: 'timezone', 'altzone' and 'tzname'. -OffsetAbbr get_offset_abbr(const std::tm& tm) { +auto tm_gmtoff(const std::tm& tm) -> decltype(timezone) { const bool is_dst = tm.tm_isdst > 0; - const int off = is_dst ? altzone : timezone; - const char* abbr = tzname[is_dst]; - return {off, abbr}; + return is_dst ? altzone : timezone; +} +auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) { + const bool is_dst = tm.tm_isdst > 0; + return tzname[is_dst]; } #elif defined(__native_client__) || defined(__myriad2__) || \ defined(__EMSCRIPTEN__) // Uses the globals: 'timezone' and 'tzname'. -OffsetAbbr get_offset_abbr(const std::tm& tm) { +auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + 0) { + const bool is_dst = tm.tm_isdst > 0; + return _timezone + (is_dst ? 60 * 60 : 0); +} +auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) { const bool is_dst = tm.tm_isdst > 0; - const int off = _timezone + (is_dst ? 60 * 60 : 0); - const char* abbr = tzname[is_dst]; - return {off, abbr}; + return tzname[is_dst]; +} +#else +// Adapt to different spellings of the struct std::tm extension fields. +#if defined(tm_gmtoff) +auto tm_gmtoff(const std::tm& tm) -> decltype(tm.tm_gmtoff) { + return tm.tm_gmtoff; +} +#elif defined(__tm_gmtoff) +auto tm_gmtoff(const std::tm& tm) -> decltype(tm.__tm_gmtoff) { + return tm.__tm_gmtoff; +} +#else +template +auto tm_gmtoff(const T& tm) -> decltype(tm.tm_gmtoff) { + return tm.tm_gmtoff; +} +template +auto tm_gmtoff(const T& tm) -> decltype(tm.__tm_gmtoff) { + return tm.__tm_gmtoff; +} +#endif // tm_gmtoff +#if defined(tm_zone) +auto tm_zone(const std::tm& tm) -> decltype(tm.tm_zone) { + return tm.tm_zone; +} +#elif defined(__tm_zone) +auto tm_zone(const std::tm& tm) -> decltype(tm.__tm_zone) { + return tm.__tm_zone; } #else -// -// Returns an OffsetAbbr using std::tm fields with various spellings. -// -#if !defined(tm_gmtoff) && !defined(tm_zone) template -OffsetAbbr get_offset_abbr(const T& tm, decltype(&T::tm_gmtoff) = nullptr, - decltype(&T::tm_zone) = nullptr) { - return {tm.tm_gmtoff, tm.tm_zone}; +auto tm_zone(const T& tm) -> decltype(tm.tm_zone) { + return tm.tm_zone; } -#endif // !defined(tm_gmtoff) && !defined(tm_zone) -#if !defined(__tm_gmtoff) && !defined(__tm_zone) template -OffsetAbbr get_offset_abbr(const T& tm, decltype(&T::__tm_gmtoff) = nullptr, - decltype(&T::__tm_zone) = nullptr) { - return {tm.__tm_gmtoff, tm.__tm_zone}; +auto tm_zone(const T& tm) -> decltype(tm.__tm_zone) { + return tm.__tm_zone; } -#endif // !defined(__tm_gmtoff) && !defined(__tm_zone) +#endif // tm_zone #endif inline std::tm* gm_time(const std::time_t *timep, std::tm *result) { @@ -126,7 +143,7 @@ bool make_time(const civil_second& cs, int is_dst, std::time_t* t, int* off) { return false; } } - *off = get_offset_abbr(tm).first; + *off = static_cast(tm_gmtoff(tm)); return true; } @@ -137,7 +154,7 @@ std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) { while (lo + 1 != hi) { const std::time_t mid = lo + (hi - lo) / 2; if (std::tm* tmp = local_time(&mid, &tm)) { - if (get_offset_abbr(*tmp).first == offset) { + if (tm_gmtoff(*tmp) == offset) { hi = mid; } else { lo = mid; @@ -147,7 +164,7 @@ std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) { // ignoring all failed conversions. Slow, but never really happens. while (++lo != hi) { if (std::tm* tmp = local_time(&lo, &tm)) { - if (get_offset_abbr(*tmp).first == offset) break; + if (tm_gmtoff(*tmp) == offset) break; } } return lo; @@ -193,8 +210,8 @@ time_zone::absolute_lookup TimeZoneLibC::BreakTime( const year_t year = tmp->tm_year + year_t{1900}; al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); - std::tie(al.offset, al.abbr) = get_offset_abbr(*tmp); - if (!local_) al.abbr = "UTC"; // as expected by cctz + al.offset = static_cast(tm_gmtoff(*tmp)); + al.abbr = local_ ? tm_zone(*tmp) : "UTC"; // as expected by cctz al.is_dst = tmp->tm_isdst > 0; return al; } diff --git a/absl/time/internal/cctz/src/zone_info_source.cc b/absl/time/internal/cctz/src/zone_info_source.cc index 13248462..42f50c5e 100644 --- a/absl/time/internal/cctz/src/zone_info_source.cc +++ b/absl/time/internal/cctz/src/zone_info_source.cc @@ -46,7 +46,13 @@ std::unique_ptr DefaultFactory( // A "weak" definition for cctz_extension::zone_info_source_factory. // The user may override this with their own "strong" definition (see // zone_info_source.h). -#if defined(_MSC_VER) +#if !defined(__has_attribute) +#define __has_attribute(x) 0 +#endif +#if __has_attribute(weak) || defined(__GNUC__) +ZoneInfoSourceFactory zone_info_source_factory + __attribute__((weak)) = DefaultFactory; +#elif defined(_MSC_VER) && !defined(_LIBCPP_VERSION) extern ZoneInfoSourceFactory zone_info_source_factory; extern ZoneInfoSourceFactory default_factory; ZoneInfoSourceFactory default_factory = DefaultFactory; @@ -60,19 +66,11 @@ ZoneInfoSourceFactory default_factory = DefaultFactory; "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZEA=?default_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZEA") #else #error Unsupported MSVC platform -#endif -#else // _MSC_VER -#if !defined(__has_attribute) -#define __has_attribute(x) 0 -#endif -#if __has_attribute(weak) || defined(__GNUC__) -ZoneInfoSourceFactory zone_info_source_factory - __attribute__((weak)) = DefaultFactory; +#endif // _M_ #else // Make it a "strong" definition if we have no other choice. ZoneInfoSourceFactory zone_info_source_factory = DefaultFactory; #endif -#endif // _MSC_VER } // namespace cctz_extension } // namespace time_internal diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h index 5ca66e29..85201b4a 100644 --- a/absl/types/internal/variant.h +++ b/absl/types/internal/variant.h @@ -837,8 +837,8 @@ struct ImaginaryFun, I> : ImaginaryFun, I + 1> { // NOTE: const& and && are used instead of by-value due to lack of guaranteed // move elision of C++17. This may have other minor differences, but tests // pass. - static SizeT Run(const H&); - static SizeT Run(H&&); + static SizeT Run(const H&, SizeT); + static SizeT Run(H&&, SizeT); }; // The following metafunctions are used in constructor and assignment @@ -860,7 +860,8 @@ struct ConversionIsPossibleImpl : std::false_type {}; template struct ConversionIsPossibleImpl< - Variant, T, void_t::Run(std::declval()))>> + Variant, T, + void_t::Run(std::declval(), {}))>> : std::true_type {}; template @@ -868,8 +869,9 @@ struct ConversionIsPossible : ConversionIsPossibleImpl::type {}; template struct IndexOfConstructedType< - Variant, T, void_t::Run(std::declval()))>> - : decltype(ImaginaryFun::Run(std::declval())) {}; + Variant, T, + void_t::Run(std::declval(), {}))>> + : decltype(ImaginaryFun::Run(std::declval(), {})) {}; template struct ContainsVariantNPos diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc index b9c98118..d7024827 100644 --- a/absl/types/variant_test.cc +++ b/absl/types/variant_test.cc @@ -460,6 +460,11 @@ TYPED_TEST(VariantTypesTest, TestValueCtor) { EXPECT_EQ(value.value, mutable_valptr->value); } +TEST(VariantTest, AmbiguousValueConstructor) { + EXPECT_FALSE((std::is_convertible>::value)); + EXPECT_FALSE((std::is_constructible, int>::value)); +} + TEST(VariantTest, InPlaceType) { using Var = variant>; -- cgit v1.2.3 From bf86cfe165ef7d70dfe68f0b8fc0c018bc79a577 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Sat, 14 Dec 2019 08:24:07 -0800 Subject: Export of internal Abseil changes -- 20b3acaff75d05315f272747956b01405adccafb by Greg Falcon : Re-import of CCTZ from GitHub, with new ABSL_NAMESPACE_ transform applied. PiperOrigin-RevId: 285564474 -- 4d9e3fcabcea33c8b0b69f094ad2eddc0fa19557 by Derek Mauro : Moves the disabling of a warning to before the function begins. MSVC apparently requires this for warnings in the range 4700-4999. https://docs.microsoft.com/en-us/cpp/preprocessor/warning?redirectedfrom=MSDN&view=vs-2019 PiperOrigin-RevId: 285516232 -- 4a060cbeda76e89693c50276ae5b62cbf0fff39a by Derek Mauro : MSVC: Fixes uniform_real_distribution_test in opt mode Disables a constant arithmetic overflow warning in a test that tests the behavior on overflow. This should be tested because a user might have this warning disabled. PiperOrigin-RevId: 285452242 -- 548ab2f4cbe59bd6f6bf493af4f9ea765c4fa949 by Andy Soffer : Release absl::bind_front, a C++11-compliant work-alike type for the C++20 std::bind_front. PiperOrigin-RevId: 285247872 GitOrigin-RevId: 20b3acaff75d05315f272747956b01405adccafb Change-Id: I00fe45939246cba9bfc7be375d67787d2eb57cd3 --- absl/functional/BUILD.bazel | 26 + absl/functional/bind_front.h | 152 +++ absl/functional/bind_front_test.cc | 231 ++++ absl/functional/internal/front_binder.h | 95 ++ absl/random/uniform_real_distribution_test.cc | 7 + absl/time/internal/cctz/BUILD.bazel | 10 +- absl/time/internal/cctz/include/cctz/civil_time.h | 3 + .../internal/cctz/include/cctz/civil_time_detail.h | 62 +- absl/time/internal/cctz/include/cctz/time_zone.h | 21 +- .../internal/cctz/include/cctz/zone_info_source.h | 12 +- absl/time/internal/cctz/src/cctz_benchmark.cc | 1188 ++++++++++--------- absl/time/internal/cctz/src/civil_time_detail.cc | 4 + absl/time/internal/cctz/src/civil_time_test.cc | 21 +- absl/time/internal/cctz/src/time_zone_fixed.cc | 10 +- absl/time/internal/cctz/src/time_zone_fixed.h | 3 + absl/time/internal/cctz/src/time_zone_format.cc | 27 +- .../internal/cctz/src/time_zone_format_test.cc | 39 +- absl/time/internal/cctz/src/time_zone_if.cc | 4 + absl/time/internal/cctz/src/time_zone_if.h | 12 +- absl/time/internal/cctz/src/time_zone_impl.cc | 7 +- absl/time/internal/cctz/src/time_zone_impl.h | 3 + absl/time/internal/cctz/src/time_zone_info.cc | 93 +- absl/time/internal/cctz/src/time_zone_info.h | 10 +- absl/time/internal/cctz/src/time_zone_libc.cc | 23 +- absl/time/internal/cctz/src/time_zone_libc.h | 6 +- absl/time/internal/cctz/src/time_zone_lookup.cc | 12 +- .../internal/cctz/src/time_zone_lookup_test.cc | 1244 ++++++++++---------- absl/time/internal/cctz/src/time_zone_posix.cc | 4 + absl/time/internal/cctz/src/time_zone_posix.h | 4 + absl/time/internal/cctz/src/tzfile.h | 45 +- absl/time/internal/cctz/src/zone_info_source.cc | 15 +- 31 files changed, 1972 insertions(+), 1421 deletions(-) create mode 100644 absl/functional/bind_front.h create mode 100644 absl/functional/bind_front_test.cc create mode 100644 absl/functional/internal/front_binder.h (limited to 'absl/time/internal/cctz/src/time_zone_libc.cc') diff --git a/absl/functional/BUILD.bazel b/absl/functional/BUILD.bazel index 0a7b588e..432546ce 100644 --- a/absl/functional/BUILD.bazel +++ b/absl/functional/BUILD.bazel @@ -26,6 +26,32 @@ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) # Apache 2.0 +cc_library( + name = "bind_front", + srcs = ["internal/front_binder.h"], + hdrs = ["bind_front.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + "//absl/base:base_internal", + "//absl/container:compressed_tuple", + "//absl/meta:type_traits", + "//absl/utility", + ], +) + +cc_test( + name = "bind_front_test", + srcs = ["bind_front_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":bind_front", + "//absl/memory", + "@com_google_googletest//:gtest_main", + ], +) + cc_library( name = "function_ref", srcs = ["internal/function_ref.h"], diff --git a/absl/functional/bind_front.h b/absl/functional/bind_front.h new file mode 100644 index 00000000..4c61d0ec --- /dev/null +++ b/absl/functional/bind_front.h @@ -0,0 +1,152 @@ +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// `absl::bind_front()` returns a functor by binding a number of arguments to +// the front of a provided functor, allowing you to avoid known problems with +// `std::bind()`. It is a form of partial function application +// https://en.wikipedia.org/wiki/Partial_application. +// +// Like `std::bind()` it is implicitly convertible to `std::function`. In +// particular, it may be used as a simpler replacement for `std::bind()` in most +// cases, as it does not require placeholders to be specified. More +// importantly, it provides more reliable correctness guarantees than +// `std::bind()`. +// +// absl::bind_front(a...) can be seen as storing the results of +// std::make_tuple(a...). +// +// Example: Binding a free function. +// +// int Minus(int a, int b) { return a - b; } +// +// assert(absl::bind_front(Minus)(3, 2) == 3 - 2); +// assert(absl::bind_front(Minus, 3)(2) == 3 - 2); +// assert(absl::bind_front(Minus, 3, 2)() == 3 - 2); +// +// Example: Binding a member function. +// +// struct Math { +// int Double(int a) const { return 2 * a; } +// }; +// +// Math math; +// +// assert(absl::bind_front(&Math::Double)(&math, 3) == 2 * 3); +// // Stores a pointer to math inside the functor. +// assert(absl::bind_front(&Math::Double, &math)(3) == 2 * 3); +// // Stores a copy of math inside the functor. +// assert(absl::bind_front(&Math::Double, math)(3) == 2 * 3); +// // Stores std::unique_ptr inside the functor. +// assert(absl::bind_front(&Math::Double, +// std::unique_ptr(new Math))(3) == 2 * 3); +// +// Example: Using `absl::bind_front()`, instead of `std::bind()`, with +// `std::function`. +// +// class FileReader { +// public: +// void ReadFileAsync(const std::string& filename, std::string* content, +// const std::function& done) { +// // Calls Executor::Schedule(std::function). +// Executor::DefaultExecutor()->Schedule( +// absl::bind_front(&FileReader::BlockingRead, this, +// filename, content, done)); +// } +// +// private: +// void BlockingRead(const std::string& filename, std::string* content, +// const std::function& done) { +// CHECK_OK(file::GetContents(filename, content, {})); +// done(); +// } +// }; +// +// `absl::bind_front()` stores bound arguments explicitly using the type passed +// rather than implicitly based on the type accepted by its functor. +// +// Example: Binding arguments explicitly. +// +// void LogStringView(absl::string_view sv) { +// LOG(INFO) << sv; +// } +// +// Executor* e = Executor::DefaultExecutor(); +// std::string s = "hello"; +// absl::string_view sv = s; +// +// // absl::bind_front(LogStringView, arg) makes a copy of arg and stores it. +// e->Schedule(absl::bind_front(LogStringView, sv)); // ERROR: dangling +// // string_view. +// +// e->Schedule(absl::bind_front(LogStringView, s)); // OK: stores a copy of +// // s. +// +// To store some of the arguments passed to `absl::bind_front()` by reference, +// use std::ref()` and `std::cref()`. +// +// Example: Storing some of the bound arguments by reference. +// +// class Service { +// public: +// void Serve(const Request& req, std::function* done) { +// // The request protocol buffer won't be deleted until done is called. +// // It's safe to store a reference to it inside the functor. +// Executor::DefaultExecutor()->Schedule( +// absl::bind_front(&Service::BlockingServe, this, std::cref(req), +// done)); +// } +// +// private: +// void BlockingServe(const Request& req, std::function* done); +// }; +// +// Example: Storing bound arguments by reference. +// +// void Print(const string& a, const string& b) { LOG(INFO) << a << b; } +// +// std::string hi = "Hello, "; +// std::vector names = {"Chuk", "Gek"}; +// // Doesn't copy hi. +// for_each(names.begin(), names.end(), +// absl::bind_front(Print, std::ref(hi))); +// +// // DO NOT DO THIS: the functor may outlive "hi", resulting in +// // dangling references. +// foo->DoInFuture(absl::bind_front(Print, std::ref(hi), "Guest")); // BAD! +// auto f = absl::bind_front(Print, std::ref(hi), "Guest"); // BAD! + +#ifndef ABSL_FUNCTIONAL_BIND_FRONT_H_ +#define ABSL_FUNCTIONAL_BIND_FRONT_H_ + +#include "absl/functional/internal/front_binder.h" +#include "absl/utility/utility.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +// Binds the first N arguments of an invocable object and stores them by value, +// except types of std::reference_wrapper which are 'unwound' and stored by +// reference. +template +constexpr functional_internal::bind_front_t bind_front( + F&& func, BoundArgs&&... args) { + return functional_internal::bind_front_t( + absl::in_place, absl::forward(func), + absl::forward(args)...); +} + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_FUNCTIONAL_BIND_FRONT_H_ diff --git a/absl/functional/bind_front_test.cc b/absl/functional/bind_front_test.cc new file mode 100644 index 00000000..4801a81c --- /dev/null +++ b/absl/functional/bind_front_test.cc @@ -0,0 +1,231 @@ +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/functional/bind_front.h" + +#include + +#include +#include +#include + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "absl/memory/memory.h" + +namespace { + +char CharAt(const char* s, size_t index) { return s[index]; } + +TEST(BindTest, Basics) { + EXPECT_EQ('C', absl::bind_front(CharAt)("ABC", 2)); + EXPECT_EQ('C', absl::bind_front(CharAt, "ABC")(2)); + EXPECT_EQ('C', absl::bind_front(CharAt, "ABC", 2)()); +} + +TEST(BindTest, Lambda) { + auto lambda = [](int x, int y, int z) { return x + y + z; }; + EXPECT_EQ(6, absl::bind_front(lambda)(1, 2, 3)); + EXPECT_EQ(6, absl::bind_front(lambda, 1)(2, 3)); + EXPECT_EQ(6, absl::bind_front(lambda, 1, 2)(3)); + EXPECT_EQ(6, absl::bind_front(lambda, 1, 2, 3)()); +} + +struct Functor { + std::string operator()() & { return "&"; } + std::string operator()() const& { return "const&"; } + std::string operator()() && { return "&&"; } + std::string operator()() const&& { return "const&&"; } +}; + +TEST(BindTest, PerfectForwardingOfBoundArgs) { + auto f = absl::bind_front(Functor()); + const auto& cf = f; + EXPECT_EQ("&", f()); + EXPECT_EQ("const&", cf()); + EXPECT_EQ("&&", std::move(f)()); + EXPECT_EQ("const&&", std::move(cf)()); +} + +struct ArgDescribe { + std::string operator()(int&) const { return "&"; } // NOLINT + std::string operator()(const int&) const { return "const&"; } // NOLINT + std::string operator()(int&&) const { return "&&"; } + std::string operator()(const int&&) const { return "const&&"; } +}; + +TEST(BindTest, PerfectForwardingOfFreeArgs) { + ArgDescribe f; + int i; + EXPECT_EQ("&", absl::bind_front(f)(static_cast(i))); + EXPECT_EQ("const&", absl::bind_front(f)(static_cast(i))); + EXPECT_EQ("&&", absl::bind_front(f)(static_cast(i))); + EXPECT_EQ("const&&", absl::bind_front(f)(static_cast(i))); +} + +struct NonCopyableFunctor { + NonCopyableFunctor() = default; + NonCopyableFunctor(const NonCopyableFunctor&) = delete; + NonCopyableFunctor& operator=(const NonCopyableFunctor&) = delete; + const NonCopyableFunctor* operator()() const { return this; } +}; + +TEST(BindTest, RefToFunctor) { + // It won't copy/move the functor and use the original object. + NonCopyableFunctor ncf; + auto bound_ncf = absl::bind_front(std::ref(ncf)); + auto bound_ncf_copy = bound_ncf; + EXPECT_EQ(&ncf, bound_ncf_copy()); +} + +struct Struct { + std::string value; +}; + +TEST(BindTest, StoreByCopy) { + Struct s = {"hello"}; + auto f = absl::bind_front(&Struct::value, s); + auto g = f; + EXPECT_EQ("hello", f()); + EXPECT_EQ("hello", g()); + EXPECT_NE(&s.value, &f()); + EXPECT_NE(&s.value, &g()); + EXPECT_NE(&g(), &f()); +} + +struct NonCopyable { + explicit NonCopyable(const std::string& s) : value(s) {} + NonCopyable(const NonCopyable&) = delete; + NonCopyable& operator=(const NonCopyable&) = delete; + + std::string value; +}; + +const std::string& GetNonCopyableValue(const NonCopyable& n) { return n.value; } + +TEST(BindTest, StoreByRef) { + NonCopyable s("hello"); + auto f = absl::bind_front(&GetNonCopyableValue, std::ref(s)); + EXPECT_EQ("hello", f()); + EXPECT_EQ(&s.value, &f()); + auto g = std::move(f); // NOLINT + EXPECT_EQ("hello", g()); + EXPECT_EQ(&s.value, &g()); + s.value = "goodbye"; + EXPECT_EQ("goodbye", g()); +} + +TEST(BindTest, StoreByCRef) { + NonCopyable s("hello"); + auto f = absl::bind_front(&GetNonCopyableValue, std::cref(s)); + EXPECT_EQ("hello", f()); + EXPECT_EQ(&s.value, &f()); + auto g = std::move(f); // NOLINT + EXPECT_EQ("hello", g()); + EXPECT_EQ(&s.value, &g()); + s.value = "goodbye"; + EXPECT_EQ("goodbye", g()); +} + +const std::string& GetNonCopyableValueByWrapper( + std::reference_wrapper n) { + return n.get().value; +} + +TEST(BindTest, StoreByRefInvokeByWrapper) { + NonCopyable s("hello"); + auto f = absl::bind_front(GetNonCopyableValueByWrapper, std::ref(s)); + EXPECT_EQ("hello", f()); + EXPECT_EQ(&s.value, &f()); + auto g = std::move(f); + EXPECT_EQ("hello", g()); + EXPECT_EQ(&s.value, &g()); + s.value = "goodbye"; + EXPECT_EQ("goodbye", g()); +} + +TEST(BindTest, StoreByPointer) { + NonCopyable s("hello"); + auto f = absl::bind_front(&NonCopyable::value, &s); + EXPECT_EQ("hello", f()); + EXPECT_EQ(&s.value, &f()); + auto g = std::move(f); + EXPECT_EQ("hello", g()); + EXPECT_EQ(&s.value, &g()); +} + +int Sink(std::unique_ptr p) { + return *p; +} + +std::unique_ptr Factory(int n) { return absl::make_unique(n); } + +TEST(BindTest, NonCopyableArg) { + EXPECT_EQ(42, absl::bind_front(Sink)(absl::make_unique(42))); + EXPECT_EQ(42, absl::bind_front(Sink, absl::make_unique(42))()); +} + +TEST(BindTest, NonCopyableResult) { + EXPECT_THAT(absl::bind_front(Factory)(42), ::testing::Pointee(42)); + EXPECT_THAT(absl::bind_front(Factory, 42)(), ::testing::Pointee(42)); +} + +// is_copy_constructible> is true but an attempt to +// instantiate the copy constructor leads to a compile error. This is similar +// to how standard containers behave. +template +struct FalseCopyable { + FalseCopyable() {} + FalseCopyable(const FalseCopyable& other) : m(other.m) {} + FalseCopyable(FalseCopyable&& other) : m(std::move(other.m)) {} + T m; +}; + +int GetMember(FalseCopyable> x) { return *x.m; } + +TEST(BindTest, WrappedMoveOnly) { + FalseCopyable> x; + x.m = absl::make_unique(42); + auto f = absl::bind_front(&GetMember, std::move(x)); + EXPECT_EQ(42, std::move(f)()); +} + +int Plus(int a, int b) { return a + b; } + +TEST(BindTest, ConstExpr) { + constexpr auto f = absl::bind_front(CharAt); + EXPECT_EQ(f("ABC", 1), 'B'); + static constexpr int five = 5; + constexpr auto plus5 = absl::bind_front(Plus, five); + EXPECT_EQ(plus5(1), 6); + + // There seems to be a bug in MSVC dealing constexpr construction of + // char[]. Notice 'plus5' above; 'int' works just fine. +#if !(defined(_MSC_VER) && _MSC_VER < 1910) + static constexpr char data[] = "DEF"; + constexpr auto g = absl::bind_front(CharAt, data); + EXPECT_EQ(g(1), 'E'); +#endif +} + +struct ManglingCall { + int operator()(int, double, std::string) const { return 0; } +}; + +TEST(BindTest, Mangling) { + // We just want to generate a particular instantiation to see its mangling. + absl::bind_front(ManglingCall{}, 1, 3.3)("A"); +} + +} // namespace diff --git a/absl/functional/internal/front_binder.h b/absl/functional/internal/front_binder.h new file mode 100644 index 00000000..a4d95da4 --- /dev/null +++ b/absl/functional/internal/front_binder.h @@ -0,0 +1,95 @@ +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Implementation details for `absl::bind_front()`. + +#ifndef ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_ +#define ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_ + +#include +#include +#include + +#include "absl/base/internal/invoke.h" +#include "absl/container/internal/compressed_tuple.h" +#include "absl/meta/type_traits.h" +#include "absl/utility/utility.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace functional_internal { + +// Invoke the method, expanding the tuple of bound arguments. +template +R Apply(Tuple&& bound, absl::index_sequence, Args&&... free) { + return base_internal::Invoke( + absl::forward(bound).template get()..., + absl::forward(free)...); +} + +template +class FrontBinder { + using BoundArgsT = absl::container_internal::CompressedTuple; + using Idx = absl::make_index_sequence; + + BoundArgsT bound_args_; + + public: + template + constexpr explicit FrontBinder(absl::in_place_t, Ts&&... ts) + : bound_args_(absl::forward(ts)...) {} + + template > + R operator()(FreeArgs&&... free_args) & { + return functional_internal::Apply(bound_args_, Idx(), + absl::forward(free_args)...); + } + + template > + R operator()(FreeArgs&&... free_args) const& { + return functional_internal::Apply(bound_args_, Idx(), + absl::forward(free_args)...); + } + + template > + R operator()(FreeArgs&&... free_args) && { + // This overload is called when *this is an rvalue. If some of the bound + // arguments are stored by value or rvalue reference, we move them. + return functional_internal::Apply(absl::move(bound_args_), Idx(), + absl::forward(free_args)...); + } + + template > + R operator()(FreeArgs&&... free_args) const&& { + // This overload is called when *this is an rvalue. If some of the bound + // arguments are stored by value or rvalue reference, we move them. + return functional_internal::Apply(absl::move(bound_args_), Idx(), + absl::forward(free_args)...); + } +}; + +template +using bind_front_t = FrontBinder, absl::decay_t...>; + +} // namespace functional_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_ diff --git a/absl/random/uniform_real_distribution_test.cc b/absl/random/uniform_real_distribution_test.cc index 9f14d1c5..a56374a6 100644 --- a/absl/random/uniform_real_distribution_test.cc +++ b/absl/random/uniform_real_distribution_test.cc @@ -161,6 +161,10 @@ TYPED_TEST(UniformRealDistributionTest, ParamSerializeTest) { } } +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4756) // Constant arithmetic overflow. +#endif TYPED_TEST(UniformRealDistributionTest, ViolatesPreconditionsDeathTest) { #if GTEST_HAS_DEATH_TEST // Hi < Lo @@ -195,6 +199,9 @@ TYPED_TEST(UniformRealDistributionTest, ViolatesPreconditionsDeathTest) { } #endif // NDEBUG } +#ifdef _MSC_VER +#pragma warning(pop) // warning(disable:4756) +#endif TYPED_TEST(UniformRealDistributionTest, TestMoments) { constexpr int kSize = 1000000; diff --git a/absl/time/internal/cctz/BUILD.bazel b/absl/time/internal/cctz/BUILD.bazel index 9fceffe2..5ad0f036 100644 --- a/absl/time/internal/cctz/BUILD.bazel +++ b/absl/time/internal/cctz/BUILD.bazel @@ -42,6 +42,7 @@ cc_library( ], textual_hdrs = ["include/cctz/civil_time_detail.h"], visibility = ["//visibility:public"], + deps = ["//absl/base:config"], ) cc_library( @@ -78,7 +79,10 @@ cc_library( "//conditions:default": [], }), visibility = ["//visibility:public"], - deps = [":civil_time"], + deps = [ + ":civil_time", + "//absl/base:config", + ], ) ### tests @@ -89,6 +93,7 @@ cc_test( srcs = ["src/civil_time_test.cc"], deps = [ ":civil_time", + "//absl/base:config", "@com_google_googletest//:gtest_main", ], ) @@ -106,6 +111,7 @@ cc_test( deps = [ ":civil_time", ":time_zone", + "//absl/base:config", "@com_google_googletest//:gtest_main", ], ) @@ -124,6 +130,7 @@ cc_test( deps = [ ":civil_time", ":time_zone", + "//absl/base:config", "@com_google_googletest//:gtest_main", ], ) @@ -144,6 +151,7 @@ cc_test( deps = [ ":civil_time", ":time_zone", + "//absl/base:config", "@com_github_google_benchmark//:benchmark_main", ], ) diff --git a/absl/time/internal/cctz/include/cctz/civil_time.h b/absl/time/internal/cctz/include/cctz/civil_time.h index 19b311bb..d47ff86f 100644 --- a/absl/time/internal/cctz/include/cctz/civil_time.h +++ b/absl/time/internal/cctz/include/cctz/civil_time.h @@ -15,9 +15,11 @@ #ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ #define ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ +#include "absl/base/config.h" #include "absl/time/internal/cctz/include/cctz/civil_time_detail.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -324,6 +326,7 @@ using detail::get_yearday; } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ diff --git a/absl/time/internal/cctz/include/cctz/civil_time_detail.h b/absl/time/internal/cctz/include/cctz/civil_time_detail.h index 433078a7..4cde96f1 100644 --- a/absl/time/internal/cctz/include/cctz/civil_time_detail.h +++ b/absl/time/internal/cctz/include/cctz/civil_time_detail.h @@ -20,6 +20,8 @@ #include #include +#include "absl/base/config.h" + // Disable constexpr support unless we are in C++14 mode. #if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) #define CONSTEXPR_D constexpr // data @@ -32,6 +34,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -53,8 +56,8 @@ using second_t = std::int_fast8_t; // [0:59] // Normalized civil-time fields: Y-M-D HH:MM:SS. struct fields { - CONSTEXPR_M fields(year_t year, month_t month, day_t day, - hour_t hour, minute_t minute, second_t second) + CONSTEXPR_M fields(year_t year, month_t month, day_t day, hour_t hour, + minute_t minute, second_t second) : y(year), m(month), d(day), hh(hour), mm(minute), ss(second) {} std::int_least64_t y; std::int_least8_t m; @@ -101,8 +104,8 @@ CONSTEXPR_F int days_per_month(year_t y, month_t m) noexcept { return k_days_per_month[m] + (m == 2 && is_leap_year(y)); } -CONSTEXPR_F fields n_day(year_t y, month_t m, diff_t d, diff_t cd, - hour_t hh, minute_t mm, second_t ss) noexcept { +CONSTEXPR_F fields n_day(year_t y, month_t m, diff_t d, diff_t cd, hour_t hh, + minute_t mm, second_t ss) noexcept { y += (cd / 146097) * 400; cd %= 146097; if (cd < 0) { @@ -152,8 +155,8 @@ CONSTEXPR_F fields n_day(year_t y, month_t m, diff_t d, diff_t cd, } return fields(y, m, static_cast(d), hh, mm, ss); } -CONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd, - hour_t hh, minute_t mm, second_t ss) noexcept { +CONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd, hour_t hh, + minute_t mm, second_t ss) noexcept { if (m != 12) { y += m / 12; m %= 12; @@ -164,8 +167,8 @@ CONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd, } return n_day(y, static_cast(m), d, cd, hh, mm, ss); } -CONSTEXPR_F fields n_hour(year_t y, diff_t m, diff_t d, diff_t cd, - diff_t hh, minute_t mm, second_t ss) noexcept { +CONSTEXPR_F fields n_hour(year_t y, diff_t m, diff_t d, diff_t cd, diff_t hh, + minute_t mm, second_t ss) noexcept { cd += hh / 24; hh %= 24; if (hh < 0) { @@ -264,8 +267,8 @@ CONSTEXPR_F diff_t ymd_ord(year_t y, month_t m, day_t d) noexcept { // yet the difference between two such extreme values may actually be // small, so we take a little care to avoid overflow when possible by // exploiting the 146097-day cycle. -CONSTEXPR_F diff_t day_difference(year_t y1, month_t m1, day_t d1, - year_t y2, month_t m2, day_t d2) noexcept { +CONSTEXPR_F diff_t day_difference(year_t y1, month_t m1, day_t d1, year_t y2, + month_t m2, day_t d2) noexcept { const diff_t a_c4_off = y1 % 400; const diff_t b_c4_off = y2 % 400; diff_t c4_diff = (y1 - a_c4_off) - (y2 - b_c4_off); @@ -305,9 +308,7 @@ CONSTEXPR_F diff_t difference(second_tag, fields f1, fields f2) noexcept { //////////////////////////////////////////////////////////////////////// // Aligns the (normalized) fields struct to the indicated field. -CONSTEXPR_F fields align(second_tag, fields f) noexcept { - return f; -} +CONSTEXPR_F fields align(second_tag, fields f) noexcept { return f; } CONSTEXPR_F fields align(minute_tag, fields f) noexcept { return fields{f.y, f.m, f.d, f.hh, f.mm, 0}; } @@ -386,11 +387,11 @@ class civil_time { : civil_time(ct.f_) {} // Factories for the maximum/minimum representable civil_time. - static CONSTEXPR_F civil_time (max)() { + static CONSTEXPR_F civil_time(max)() { const auto max_year = (std::numeric_limits::max)(); return civil_time(max_year, 12, 31, 23, 59, 59); } - static CONSTEXPR_F civil_time (min)() { + static CONSTEXPR_F civil_time(min)() { const auto min_year = (std::numeric_limits::min)(); return civil_time(min_year, 1, 1, 0, 0, 0); } @@ -416,17 +417,13 @@ class civil_time { } return *this; } - CONSTEXPR_M civil_time& operator++() noexcept { - return *this += 1; - } + CONSTEXPR_M civil_time& operator++() noexcept { return *this += 1; } CONSTEXPR_M civil_time operator++(int) noexcept { const civil_time a = *this; ++*this; return a; } - CONSTEXPR_M civil_time& operator--() noexcept { - return *this -= 1; - } + CONSTEXPR_M civil_time& operator--() noexcept { return *this -= 1; } CONSTEXPR_M civil_time operator--(int) noexcept { const civil_time a = *this; --*this; @@ -483,17 +480,17 @@ using civil_second = civil_time; template CONSTEXPR_F bool operator<(const civil_time& lhs, const civil_time& rhs) noexcept { - return (lhs.year() < rhs.year() || - (lhs.year() == rhs.year() && - (lhs.month() < rhs.month() || - (lhs.month() == rhs.month() && - (lhs.day() < rhs.day() || - (lhs.day() == rhs.day() && - (lhs.hour() < rhs.hour() || - (lhs.hour() == rhs.hour() && - (lhs.minute() < rhs.minute() || - (lhs.minute() == rhs.minute() && - (lhs.second() < rhs.second()))))))))))); + return ( + lhs.year() < rhs.year() || + (lhs.year() == rhs.year() && + (lhs.month() < rhs.month() || + (lhs.month() == rhs.month() && + (lhs.day() < rhs.day() || (lhs.day() == rhs.day() && + (lhs.hour() < rhs.hour() || + (lhs.hour() == rhs.hour() && + (lhs.minute() < rhs.minute() || + (lhs.minute() == rhs.minute() && + (lhs.second() < rhs.second()))))))))))); } template CONSTEXPR_F bool operator<=(const civil_time& lhs, @@ -615,6 +612,7 @@ std::ostream& operator<<(std::ostream& os, weekday wd); } // namespace detail } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl #undef CONSTEXPR_M diff --git a/absl/time/internal/cctz/include/cctz/time_zone.h b/absl/time/internal/cctz/include/cctz/time_zone.h index ef6c4ba1..d05147a1 100644 --- a/absl/time/internal/cctz/include/cctz/time_zone.h +++ b/absl/time/internal/cctz/include/cctz/time_zone.h @@ -25,9 +25,11 @@ #include #include +#include "absl/base/config.h" #include "absl/time/internal/cctz/include/cctz/civil_time.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -39,8 +41,8 @@ using sys_seconds = seconds; // Deprecated. Use cctz::seconds instead. namespace detail { template -inline std::pair, D> -split_seconds(const time_point& tp) { +inline std::pair, D> split_seconds( + const time_point& tp) { auto sec = std::chrono::time_point_cast(tp); auto sub = tp - sec; if (sub.count() < 0) { @@ -49,8 +51,8 @@ split_seconds(const time_point& tp) { } return {sec, std::chrono::duration_cast(sub)}; } -inline std::pair, seconds> -split_seconds(const time_point& tp) { +inline std::pair, seconds> split_seconds( + const time_point& tp) { return {tp, seconds::zero()}; } } // namespace detail @@ -194,15 +196,13 @@ class time_zone { bool next_transition(const time_point& tp, civil_transition* trans) const; template - bool next_transition(const time_point& tp, - civil_transition* trans) const { + bool next_transition(const time_point& tp, civil_transition* trans) const { return next_transition(detail::split_seconds(tp).first, trans); } bool prev_transition(const time_point& tp, civil_transition* trans) const; template - bool prev_transition(const time_point& tp, - civil_transition* trans) const { + bool prev_transition(const time_point& tp, civil_transition* trans) const { return prev_transition(detail::split_seconds(tp).first, trans); } @@ -220,9 +220,7 @@ class time_zone { friend bool operator==(time_zone lhs, time_zone rhs) { return &lhs.effective_impl() == &rhs.effective_impl(); } - friend bool operator!=(time_zone lhs, time_zone rhs) { - return !(lhs == rhs); - } + friend bool operator!=(time_zone lhs, time_zone rhs) { return !(lhs == rhs); } template friend H AbslHashValue(H h, time_zone tz) { @@ -380,6 +378,7 @@ inline bool parse(const std::string& fmt, const std::string& input, } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_ diff --git a/absl/time/internal/cctz/include/cctz/zone_info_source.h b/absl/time/internal/cctz/include/cctz/zone_info_source.h index 2b898d18..912b44ba 100644 --- a/absl/time/internal/cctz/include/cctz/zone_info_source.h +++ b/absl/time/internal/cctz/include/cctz/zone_info_source.h @@ -20,7 +20,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -30,7 +33,7 @@ class ZoneInfoSource { virtual ~ZoneInfoSource(); virtual std::size_t Read(void* ptr, std::size_t size) = 0; // like fread() - virtual int Skip(std::size_t offset) = 0; // like fseek() + virtual int Skip(std::size_t offset) = 0; // like fseek() // Until the zoneinfo data supports versioning information, we provide // a way for a ZoneInfoSource to indicate it out-of-band. The default @@ -40,9 +43,11 @@ class ZoneInfoSource { } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz_extension { @@ -52,8 +57,8 @@ namespace cctz_extension { using ZoneInfoSourceFactory = std::unique_ptr (*)( const std::string&, - const std::function( - const std::string&)>&); + const std::function(const std::string&)>&); // The user can control the mapping of zone names to zoneinfo data by // providing a definition for cctz_extension::zone_info_source_factory. @@ -91,6 +96,7 @@ extern ZoneInfoSourceFactory zone_info_source_factory; } // namespace cctz_extension } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_ diff --git a/absl/time/internal/cctz/src/cctz_benchmark.cc b/absl/time/internal/cctz/src/cctz_benchmark.cc index a40f504e..d30a644e 100644 --- a/absl/time/internal/cctz/src/cctz_benchmark.cc +++ b/absl/time/internal/cctz/src/cctz_benchmark.cc @@ -105,601 +105,599 @@ const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z"; // A list of known time-zone names. // TODO: Refactor with src/time_zone_lookup_test.cc. -const char* const kTimeZoneNames[] = { - "Africa/Abidjan", - "Africa/Accra", - "Africa/Addis_Ababa", - "Africa/Algiers", - "Africa/Asmara", - "Africa/Asmera", - "Africa/Bamako", - "Africa/Bangui", - "Africa/Banjul", - "Africa/Bissau", - "Africa/Blantyre", - "Africa/Brazzaville", - "Africa/Bujumbura", - "Africa/Cairo", - "Africa/Casablanca", - "Africa/Ceuta", - "Africa/Conakry", - "Africa/Dakar", - "Africa/Dar_es_Salaam", - "Africa/Djibouti", - "Africa/Douala", - "Africa/El_Aaiun", - "Africa/Freetown", - "Africa/Gaborone", - "Africa/Harare", - "Africa/Johannesburg", - "Africa/Juba", - "Africa/Kampala", - "Africa/Khartoum", - "Africa/Kigali", - "Africa/Kinshasa", - "Africa/Lagos", - "Africa/Libreville", - "Africa/Lome", - "Africa/Luanda", - "Africa/Lubumbashi", - "Africa/Lusaka", - "Africa/Malabo", - "Africa/Maputo", - "Africa/Maseru", - "Africa/Mbabane", - "Africa/Mogadishu", - "Africa/Monrovia", - "Africa/Nairobi", - "Africa/Ndjamena", - "Africa/Niamey", - "Africa/Nouakchott", - "Africa/Ouagadougou", - "Africa/Porto-Novo", - "Africa/Sao_Tome", - "Africa/Timbuktu", - "Africa/Tripoli", - "Africa/Tunis", - "Africa/Windhoek", - "America/Adak", - "America/Anchorage", - "America/Anguilla", - "America/Antigua", - "America/Araguaina", - "America/Argentina/Buenos_Aires", - "America/Argentina/Catamarca", - "America/Argentina/ComodRivadavia", - "America/Argentina/Cordoba", - "America/Argentina/Jujuy", - "America/Argentina/La_Rioja", - "America/Argentina/Mendoza", - "America/Argentina/Rio_Gallegos", - "America/Argentina/Salta", - "America/Argentina/San_Juan", - "America/Argentina/San_Luis", - "America/Argentina/Tucuman", - "America/Argentina/Ushuaia", - "America/Aruba", - "America/Asuncion", - "America/Atikokan", - "America/Atka", - "America/Bahia", - "America/Bahia_Banderas", - "America/Barbados", - "America/Belem", - "America/Belize", - "America/Blanc-Sablon", - "America/Boa_Vista", - "America/Bogota", - "America/Boise", - "America/Buenos_Aires", - "America/Cambridge_Bay", - "America/Campo_Grande", - "America/Cancun", - "America/Caracas", - "America/Catamarca", - "America/Cayenne", - "America/Cayman", - "America/Chicago", - "America/Chihuahua", - "America/Coral_Harbour", - "America/Cordoba", - "America/Costa_Rica", - "America/Creston", - "America/Cuiaba", - "America/Curacao", - "America/Danmarkshavn", - "America/Dawson", - "America/Dawson_Creek", - "America/Denver", - "America/Detroit", - "America/Dominica", - "America/Edmonton", - "America/Eirunepe", - "America/El_Salvador", - "America/Ensenada", - "America/Fort_Nelson", - "America/Fort_Wayne", - "America/Fortaleza", - "America/Glace_Bay", - "America/Godthab", - "America/Goose_Bay", - "America/Grand_Turk", - "America/Grenada", - "America/Guadeloupe", - "America/Guatemala", - "America/Guayaquil", - "America/Guyana", - "America/Halifax", - "America/Havana", - "America/Hermosillo", - "America/Indiana/Indianapolis", - "America/Indiana/Knox", - "America/Indiana/Marengo", - "America/Indiana/Petersburg", - "America/Indiana/Tell_City", - "America/Indiana/Vevay", - "America/Indiana/Vincennes", - "America/Indiana/Winamac", - "America/Indianapolis", - "America/Inuvik", - "America/Iqaluit", - "America/Jamaica", - "America/Jujuy", - "America/Juneau", - "America/Kentucky/Louisville", - "America/Kentucky/Monticello", - "America/Knox_IN", - "America/Kralendijk", - "America/La_Paz", - "America/Lima", - "America/Los_Angeles", - "America/Louisville", - "America/Lower_Princes", - "America/Maceio", - "America/Managua", - "America/Manaus", - "America/Marigot", - "America/Martinique", - "America/Matamoros", - "America/Mazatlan", - "America/Mendoza", - "America/Menominee", - "America/Merida", - "America/Metlakatla", - "America/Mexico_City", - "America/Miquelon", - "America/Moncton", - "America/Monterrey", - "America/Montevideo", - "America/Montreal", - "America/Montserrat", - "America/Nassau", - "America/New_York", - "America/Nipigon", - "America/Nome", - "America/Noronha", - "America/North_Dakota/Beulah", - "America/North_Dakota/Center", - "America/North_Dakota/New_Salem", - "America/Ojinaga", - "America/Panama", - "America/Pangnirtung", - "America/Paramaribo", - "America/Phoenix", - "America/Port-au-Prince", - "America/Port_of_Spain", - "America/Porto_Acre", - "America/Porto_Velho", - "America/Puerto_Rico", - "America/Punta_Arenas", - "America/Rainy_River", - "America/Rankin_Inlet", - "America/Recife", - "America/Regina", - "America/Resolute", - "America/Rio_Branco", - "America/Rosario", - "America/Santa_Isabel", - "America/Santarem", - "America/Santiago", - "America/Santo_Domingo", - "America/Sao_Paulo", - "America/Scoresbysund", - "America/Shiprock", - "America/Sitka", - "America/St_Barthelemy", - "America/St_Johns", - "America/St_Kitts", - "America/St_Lucia", - "America/St_Thomas", - "America/St_Vincent", - "America/Swift_Current", - "America/Tegucigalpa", - "America/Thule", - "America/Thunder_Bay", - "America/Tijuana", - "America/Toronto", - "America/Tortola", - "America/Vancouver", - "America/Virgin", - "America/Whitehorse", - "America/Winnipeg", - "America/Yakutat", - "America/Yellowknife", - "Antarctica/Casey", - "Antarctica/Davis", - "Antarctica/DumontDUrville", - "Antarctica/Macquarie", - "Antarctica/Mawson", - "Antarctica/McMurdo", - "Antarctica/Palmer", - "Antarctica/Rothera", - "Antarctica/South_Pole", - "Antarctica/Syowa", - "Antarctica/Troll", - "Antarctica/Vostok", - "Arctic/Longyearbyen", - "Asia/Aden", - "Asia/Almaty", - "Asia/Amman", - "Asia/Anadyr", - "Asia/Aqtau", - "Asia/Aqtobe", - "Asia/Ashgabat", - "Asia/Ashkhabad", - "Asia/Atyrau", - "Asia/Baghdad", - "Asia/Bahrain", - "Asia/Baku", - "Asia/Bangkok", - "Asia/Barnaul", - "Asia/Beirut", - "Asia/Bishkek", - "Asia/Brunei", - "Asia/Calcutta", - "Asia/Chita", - "Asia/Choibalsan", - "Asia/Chongqing", - "Asia/Chungking", - "Asia/Colombo", - "Asia/Dacca", - "Asia/Damascus", - "Asia/Dhaka", - "Asia/Dili", - "Asia/Dubai", - "Asia/Dushanbe", - "Asia/Famagusta", - "Asia/Gaza", - "Asia/Harbin", - "Asia/Hebron", - "Asia/Ho_Chi_Minh", - "Asia/Hong_Kong", - "Asia/Hovd", - "Asia/Irkutsk", - "Asia/Istanbul", - "Asia/Jakarta", - "Asia/Jayapura", - "Asia/Jerusalem", - "Asia/Kabul", - "Asia/Kamchatka", - "Asia/Karachi", - "Asia/Kashgar", - "Asia/Kathmandu", - "Asia/Katmandu", - "Asia/Khandyga", - "Asia/Kolkata", - "Asia/Krasnoyarsk", - "Asia/Kuala_Lumpur", - "Asia/Kuching", - "Asia/Kuwait", - "Asia/Macao", - "Asia/Macau", - "Asia/Magadan", - "Asia/Makassar", - "Asia/Manila", - "Asia/Muscat", - "Asia/Nicosia", - "Asia/Novokuznetsk", - "Asia/Novosibirsk", - "Asia/Omsk", - "Asia/Oral", - "Asia/Phnom_Penh", - "Asia/Pontianak", - "Asia/Pyongyang", - "Asia/Qatar", - "Asia/Qostanay", - "Asia/Qyzylorda", - "Asia/Rangoon", - "Asia/Riyadh", - "Asia/Saigon", - "Asia/Sakhalin", - "Asia/Samarkand", - "Asia/Seoul", - "Asia/Shanghai", - "Asia/Singapore", - "Asia/Srednekolymsk", - "Asia/Taipei", - "Asia/Tashkent", - "Asia/Tbilisi", - "Asia/Tehran", - "Asia/Tel_Aviv", - "Asia/Thimbu", - "Asia/Thimphu", - "Asia/Tokyo", - "Asia/Tomsk", - "Asia/Ujung_Pandang", - "Asia/Ulaanbaatar", - "Asia/Ulan_Bator", - "Asia/Urumqi", - "Asia/Ust-Nera", - "Asia/Vientiane", - "Asia/Vladivostok", - "Asia/Yakutsk", - "Asia/Yangon", - "Asia/Yekaterinburg", - "Asia/Yerevan", - "Atlantic/Azores", - "Atlantic/Bermuda", - "Atlantic/Canary", - "Atlantic/Cape_Verde", - "Atlantic/Faeroe", - "Atlantic/Faroe", - "Atlantic/Jan_Mayen", - "Atlantic/Madeira", - "Atlantic/Reykjavik", - "Atlantic/South_Georgia", - "Atlantic/St_Helena", - "Atlantic/Stanley", - "Australia/ACT", - "Australia/Adelaide", - "Australia/Brisbane", - "Australia/Broken_Hill", - "Australia/Canberra", - "Australia/Currie", - "Australia/Darwin", - "Australia/Eucla", - "Australia/Hobart", - "Australia/LHI", - "Australia/Lindeman", - "Australia/Lord_Howe", - "Australia/Melbourne", - "Australia/NSW", - "Australia/North", - "Australia/Perth", - "Australia/Queensland", - "Australia/South", - "Australia/Sydney", - "Australia/Tasmania", - "Australia/Victoria", - "Australia/West", - "Australia/Yancowinna", - "Brazil/Acre", - "Brazil/DeNoronha", - "Brazil/East", - "Brazil/West", - "CET", - "CST6CDT", - "Canada/Atlantic", - "Canada/Central", - "Canada/Eastern", - "Canada/Mountain", - "Canada/Newfoundland", - "Canada/Pacific", - "Canada/Saskatchewan", - "Canada/Yukon", - "Chile/Continental", - "Chile/EasterIsland", - "Cuba", - "EET", - "EST", - "EST5EDT", - "Egypt", - "Eire", - "Etc/GMT", - "Etc/GMT+0", - "Etc/GMT+1", - "Etc/GMT+10", - "Etc/GMT+11", - "Etc/GMT+12", - "Etc/GMT+2", - "Etc/GMT+3", - "Etc/GMT+4", - "Etc/GMT+5", - "Etc/GMT+6", - "Etc/GMT+7", - "Etc/GMT+8", - "Etc/GMT+9", - "Etc/GMT-0", - "Etc/GMT-1", - "Etc/GMT-10", - "Etc/GMT-11", - "Etc/GMT-12", - "Etc/GMT-13", - "Etc/GMT-14", - "Etc/GMT-2", - "Etc/GMT-3", - "Etc/GMT-4", - "Etc/GMT-5", - "Etc/GMT-6", - "Etc/GMT-7", - "Etc/GMT-8", - "Etc/GMT-9", - "Etc/GMT0", - "Etc/Greenwich", - "Etc/UCT", - "Etc/UTC", - "Etc/Universal", - "Etc/Zulu", - "Europe/Amsterdam", - "Europe/Andorra", - "Europe/Astrakhan", - "Europe/Athens", - "Europe/Belfast", - "Europe/Belgrade", - "Europe/Berlin", - "Europe/Bratislava", - "Europe/Brussels", - "Europe/Bucharest", - "Europe/Budapest", - "Europe/Busingen", - "Europe/Chisinau", - "Europe/Copenhagen", - "Europe/Dublin", - "Europe/Gibraltar", - "Europe/Guernsey", - "Europe/Helsinki", - "Europe/Isle_of_Man", - "Europe/Istanbul", - "Europe/Jersey", - "Europe/Kaliningrad", - "Europe/Kiev", - "Europe/Kirov", - "Europe/Lisbon", - "Europe/Ljubljana", - "Europe/London", - "Europe/Luxembourg", - "Europe/Madrid", - "Europe/Malta", - "Europe/Mariehamn", - "Europe/Minsk", - "Europe/Monaco", - "Europe/Moscow", - "Europe/Nicosia", - "Europe/Oslo", - "Europe/Paris", - "Europe/Podgorica", - "Europe/Prague", - "Europe/Riga", - "Europe/Rome", - "Europe/Samara", - "Europe/San_Marino", - "Europe/Sarajevo", - "Europe/Saratov", - "Europe/Simferopol", - "Europe/Skopje", - "Europe/Sofia", - "Europe/Stockholm", - "Europe/Tallinn", - "Europe/Tirane", - "Europe/Tiraspol", - "Europe/Ulyanovsk", - "Europe/Uzhgorod", - "Europe/Vaduz", - "Europe/Vatican", - "Europe/Vienna", - "Europe/Vilnius", - "Europe/Volgograd", - "Europe/Warsaw", - "Europe/Zagreb", - "Europe/Zaporozhye", - "Europe/Zurich", - "GB", - "GB-Eire", - "GMT", - "GMT+0", - "GMT-0", - "GMT0", - "Greenwich", - "HST", - "Hongkong", - "Iceland", - "Indian/Antananarivo", - "Indian/Chagos", - "Indian/Christmas", - "Indian/Cocos", - "Indian/Comoro", - "Indian/Kerguelen", - "Indian/Mahe", - "Indian/Maldives", - "Indian/Mauritius", - "Indian/Mayotte", - "Indian/Reunion", - "Iran", - "Israel", - "Jamaica", - "Japan", - "Kwajalein", - "Libya", - "MET", - "MST", - "MST7MDT", - "Mexico/BajaNorte", - "Mexico/BajaSur", - "Mexico/General", - "NZ", - "NZ-CHAT", - "Navajo", - "PRC", - "PST8PDT", - "Pacific/Apia", - "Pacific/Auckland", - "Pacific/Bougainville", - "Pacific/Chatham", - "Pacific/Chuuk", - "Pacific/Easter", - "Pacific/Efate", - "Pacific/Enderbury", - "Pacific/Fakaofo", - "Pacific/Fiji", - "Pacific/Funafuti", - "Pacific/Galapagos", - "Pacific/Gambier", - "Pacific/Guadalcanal", - "Pacific/Guam", - "Pacific/Honolulu", - "Pacific/Johnston", - "Pacific/Kiritimati", - "Pacific/Kosrae", - "Pacific/Kwajalein", - "Pacific/Majuro", - "Pacific/Marquesas", - "Pacific/Midway", - "Pacific/Nauru", - "Pacific/Niue", - "Pacific/Norfolk", - "Pacific/Noumea", - "Pacific/Pago_Pago", - "Pacific/Palau", - "Pacific/Pitcairn", - "Pacific/Pohnpei", - "Pacific/Ponape", - "Pacific/Port_Moresby", - "Pacific/Rarotonga", - "Pacific/Saipan", - "Pacific/Samoa", - "Pacific/Tahiti", - "Pacific/Tarawa", - "Pacific/Tongatapu", - "Pacific/Truk", - "Pacific/Wake", - "Pacific/Wallis", - "Pacific/Yap", - "Poland", - "Portugal", - "ROC", - "ROK", - "Singapore", - "Turkey", - "UCT", - "US/Alaska", - "US/Aleutian", - "US/Arizona", - "US/Central", - "US/East-Indiana", - "US/Eastern", - "US/Hawaii", - "US/Indiana-Starke", - "US/Michigan", - "US/Mountain", - "US/Pacific", - "US/Samoa", - "UTC", - "Universal", - "W-SU", - "WET", - "Zulu", - nullptr -}; +const char* const kTimeZoneNames[] = {"Africa/Abidjan", + "Africa/Accra", + "Africa/Addis_Ababa", + "Africa/Algiers", + "Africa/Asmara", + "Africa/Asmera", + "Africa/Bamako", + "Africa/Bangui", + "Africa/Banjul", + "Africa/Bissau", + "Africa/Blantyre", + "Africa/Brazzaville", + "Africa/Bujumbura", + "Africa/Cairo", + "Africa/Casablanca", + "Africa/Ceuta", + "Africa/Conakry", + "Africa/Dakar", + "Africa/Dar_es_Salaam", + "Africa/Djibouti", + "Africa/Douala", + "Africa/El_Aaiun", + "Africa/Freetown", + "Africa/Gaborone", + "Africa/Harare", + "Africa/Johannesburg", + "Africa/Juba", + "Africa/Kampala", + "Africa/Khartoum", + "Africa/Kigali", + "Africa/Kinshasa", + "Africa/Lagos", + "Africa/Libreville", + "Africa/Lome", + "Africa/Luanda", + "Africa/Lubumbashi", + "Africa/Lusaka", + "Africa/Malabo", + "Africa/Maputo", + "Africa/Maseru", + "Africa/Mbabane", + "Africa/Mogadishu", + "Africa/Monrovia", + "Africa/Nairobi", + "Africa/Ndjamena", + "Africa/Niamey", + "Africa/Nouakchott", + "Africa/Ouagadougou", + "Africa/Porto-Novo", + "Africa/Sao_Tome", + "Africa/Timbuktu", + "Africa/Tripoli", + "Africa/Tunis", + "Africa/Windhoek", + "America/Adak", + "America/Anchorage", + "America/Anguilla", + "America/Antigua", + "America/Araguaina", + "America/Argentina/Buenos_Aires", + "America/Argentina/Catamarca", + "America/Argentina/ComodRivadavia", + "America/Argentina/Cordoba", + "America/Argentina/Jujuy", + "America/Argentina/La_Rioja", + "America/Argentina/Mendoza", + "America/Argentina/Rio_Gallegos", + "America/Argentina/Salta", + "America/Argentina/San_Juan", + "America/Argentina/San_Luis", + "America/Argentina/Tucuman", + "America/Argentina/Ushuaia", + "America/Aruba", + "America/Asuncion", + "America/Atikokan", + "America/Atka", + "America/Bahia", + "America/Bahia_Banderas", + "America/Barbados", + "America/Belem", + "America/Belize", + "America/Blanc-Sablon", + "America/Boa_Vista", + "America/Bogota", + "America/Boise", + "America/Buenos_Aires", + "America/Cambridge_Bay", + "America/Campo_Grande", + "America/Cancun", + "America/Caracas", + "America/Catamarca", + "America/Cayenne", + "America/Cayman", + "America/Chicago", + "America/Chihuahua", + "America/Coral_Harbour", + "America/Cordoba", + "America/Costa_Rica", + "America/Creston", + "America/Cuiaba", + "America/Curacao", + "America/Danmarkshavn", + "America/Dawson", + "America/Dawson_Creek", + "America/Denver", + "America/Detroit", + "America/Dominica", + "America/Edmonton", + "America/Eirunepe", + "America/El_Salvador", + "America/Ensenada", + "America/Fort_Nelson", + "America/Fort_Wayne", + "America/Fortaleza", + "America/Glace_Bay", + "America/Godthab", + "America/Goose_Bay", + "America/Grand_Turk", + "America/Grenada", + "America/Guadeloupe", + "America/Guatemala", + "America/Guayaquil", + "America/Guyana", + "America/Halifax", + "America/Havana", + "America/Hermosillo", + "America/Indiana/Indianapolis", + "America/Indiana/Knox", + "America/Indiana/Marengo", + "America/Indiana/Petersburg", + "America/Indiana/Tell_City", + "America/Indiana/Vevay", + "America/Indiana/Vincennes", + "America/Indiana/Winamac", + "America/Indianapolis", + "America/Inuvik", + "America/Iqaluit", + "America/Jamaica", + "America/Jujuy", + "America/Juneau", + "America/Kentucky/Louisville", + "America/Kentucky/Monticello", + "America/Knox_IN", + "America/Kralendijk", + "America/La_Paz", + "America/Lima", + "America/Los_Angeles", + "America/Louisville", + "America/Lower_Princes", + "America/Maceio", + "America/Managua", + "America/Manaus", + "America/Marigot", + "America/Martinique", + "America/Matamoros", + "America/Mazatlan", + "America/Mendoza", + "America/Menominee", + "America/Merida", + "America/Metlakatla", + "America/Mexico_City", + "America/Miquelon", + "America/Moncton", + "America/Monterrey", + "America/Montevideo", + "America/Montreal", + "America/Montserrat", + "America/Nassau", + "America/New_York", + "America/Nipigon", + "America/Nome", + "America/Noronha", + "America/North_Dakota/Beulah", + "America/North_Dakota/Center", + "America/North_Dakota/New_Salem", + "America/Ojinaga", + "America/Panama", + "America/Pangnirtung", + "America/Paramaribo", + "America/Phoenix", + "America/Port-au-Prince", + "America/Port_of_Spain", + "America/Porto_Acre", + "America/Porto_Velho", + "America/Puerto_Rico", + "America/Punta_Arenas", + "America/Rainy_River", + "America/Rankin_Inlet", + "America/Recife", + "America/Regina", + "America/Resolute", + "America/Rio_Branco", + "America/Rosario", + "America/Santa_Isabel", + "America/Santarem", + "America/Santiago", + "America/Santo_Domingo", + "America/Sao_Paulo", + "America/Scoresbysund", + "America/Shiprock", + "America/Sitka", + "America/St_Barthelemy", + "America/St_Johns", + "America/St_Kitts", + "America/St_Lucia", + "America/St_Thomas", + "America/St_Vincent", + "America/Swift_Current", + "America/Tegucigalpa", + "America/Thule", + "America/Thunder_Bay", + "America/Tijuana", + "America/Toronto", + "America/Tortola", + "America/Vancouver", + "America/Virgin", + "America/Whitehorse", + "America/Winnipeg", + "America/Yakutat", + "America/Yellowknife", + "Antarctica/Casey", + "Antarctica/Davis", + "Antarctica/DumontDUrville", + "Antarctica/Macquarie", + "Antarctica/Mawson", + "Antarctica/McMurdo", + "Antarctica/Palmer", + "Antarctica/Rothera", + "Antarctica/South_Pole", + "Antarctica/Syowa", + "Antarctica/Troll", + "Antarctica/Vostok", + "Arctic/Longyearbyen", + "Asia/Aden", + "Asia/Almaty", + "Asia/Amman", + "Asia/Anadyr", + "Asia/Aqtau", + "Asia/Aqtobe", + "Asia/Ashgabat", + "Asia/Ashkhabad", + "Asia/Atyrau", + "Asia/Baghdad", + "Asia/Bahrain", + "Asia/Baku", + "Asia/Bangkok", + "Asia/Barnaul", + "Asia/Beirut", + "Asia/Bishkek", + "Asia/Brunei", + "Asia/Calcutta", + "Asia/Chita", + "Asia/Choibalsan", + "Asia/Chongqing", + "Asia/Chungking", + "Asia/Colombo", + "Asia/Dacca", + "Asia/Damascus", + "Asia/Dhaka", + "Asia/Dili", + "Asia/Dubai", + "Asia/Dushanbe", + "Asia/Famagusta", + "Asia/Gaza", + "Asia/Harbin", + "Asia/Hebron", + "Asia/Ho_Chi_Minh", + "Asia/Hong_Kong", + "Asia/Hovd", + "Asia/Irkutsk", + "Asia/Istanbul", + "Asia/Jakarta", + "Asia/Jayapura", + "Asia/Jerusalem", + "Asia/Kabul", + "Asia/Kamchatka", + "Asia/Karachi", + "Asia/Kashgar", + "Asia/Kathmandu", + "Asia/Katmandu", + "Asia/Khandyga", + "Asia/Kolkata", + "Asia/Krasnoyarsk", + "Asia/Kuala_Lumpur", + "Asia/Kuching", + "Asia/Kuwait", + "Asia/Macao", + "Asia/Macau", + "Asia/Magadan", + "Asia/Makassar", + "Asia/Manila", + "Asia/Muscat", + "Asia/Nicosia", + "Asia/Novokuznetsk", + "Asia/Novosibirsk", + "Asia/Omsk", + "Asia/Oral", + "Asia/Phnom_Penh", + "Asia/Pontianak", + "Asia/Pyongyang", + "Asia/Qatar", + "Asia/Qostanay", + "Asia/Qyzylorda", + "Asia/Rangoon", + "Asia/Riyadh", + "Asia/Saigon", + "Asia/Sakhalin", + "Asia/Samarkand", + "Asia/Seoul", + "Asia/Shanghai", + "Asia/Singapore", + "Asia/Srednekolymsk", + "Asia/Taipei", + "Asia/Tashkent", + "Asia/Tbilisi", + "Asia/Tehran", + "Asia/Tel_Aviv", + "Asia/Thimbu", + "Asia/Thimphu", + "Asia/Tokyo", + "Asia/Tomsk", + "Asia/Ujung_Pandang", + "Asia/Ulaanbaatar", + "Asia/Ulan_Bator", + "Asia/Urumqi", + "Asia/Ust-Nera", + "Asia/Vientiane", + "Asia/Vladivostok", + "Asia/Yakutsk", + "Asia/Yangon", + "Asia/Yekaterinburg", + "Asia/Yerevan", + "Atlantic/Azores", + "Atlantic/Bermuda", + "Atlantic/Canary", + "Atlantic/Cape_Verde", + "Atlantic/Faeroe", + "Atlantic/Faroe", + "Atlantic/Jan_Mayen", + "Atlantic/Madeira", + "Atlantic/Reykjavik", + "Atlantic/South_Georgia", + "Atlantic/St_Helena", + "Atlantic/Stanley", + "Australia/ACT", + "Australia/Adelaide", + "Australia/Brisbane", + "Australia/Broken_Hill", + "Australia/Canberra", + "Australia/Currie", + "Australia/Darwin", + "Australia/Eucla", + "Australia/Hobart", + "Australia/LHI", + "Australia/Lindeman", + "Australia/Lord_Howe", + "Australia/Melbourne", + "Australia/NSW", + "Australia/North", + "Australia/Perth", + "Australia/Queensland", + "Australia/South", + "Australia/Sydney", + "Australia/Tasmania", + "Australia/Victoria", + "Australia/West", + "Australia/Yancowinna", + "Brazil/Acre", + "Brazil/DeNoronha", + "Brazil/East", + "Brazil/West", + "CET", + "CST6CDT", + "Canada/Atlantic", + "Canada/Central", + "Canada/Eastern", + "Canada/Mountain", + "Canada/Newfoundland", + "Canada/Pacific", + "Canada/Saskatchewan", + "Canada/Yukon", + "Chile/Continental", + "Chile/EasterIsland", + "Cuba", + "EET", + "EST", + "EST5EDT", + "Egypt", + "Eire", + "Etc/GMT", + "Etc/GMT+0", + "Etc/GMT+1", + "Etc/GMT+10", + "Etc/GMT+11", + "Etc/GMT+12", + "Etc/GMT+2", + "Etc/GMT+3", + "Etc/GMT+4", + "Etc/GMT+5", + "Etc/GMT+6", + "Etc/GMT+7", + "Etc/GMT+8", + "Etc/GMT+9", + "Etc/GMT-0", + "Etc/GMT-1", + "Etc/GMT-10", + "Etc/GMT-11", + "Etc/GMT-12", + "Etc/GMT-13", + "Etc/GMT-14", + "Etc/GMT-2", + "Etc/GMT-3", + "Etc/GMT-4", + "Etc/GMT-5", + "Etc/GMT-6", + "Etc/GMT-7", + "Etc/GMT-8", + "Etc/GMT-9", + "Etc/GMT0", + "Etc/Greenwich", + "Etc/UCT", + "Etc/UTC", + "Etc/Universal", + "Etc/Zulu", + "Europe/Amsterdam", + "Europe/Andorra", + "Europe/Astrakhan", + "Europe/Athens", + "Europe/Belfast", + "Europe/Belgrade", + "Europe/Berlin", + "Europe/Bratislava", + "Europe/Brussels", + "Europe/Bucharest", + "Europe/Budapest", + "Europe/Busingen", + "Europe/Chisinau", + "Europe/Copenhagen", + "Europe/Dublin", + "Europe/Gibraltar", + "Europe/Guernsey", + "Europe/Helsinki", + "Europe/Isle_of_Man", + "Europe/Istanbul", + "Europe/Jersey", + "Europe/Kaliningrad", + "Europe/Kiev", + "Europe/Kirov", + "Europe/Lisbon", + "Europe/Ljubljana", + "Europe/London", + "Europe/Luxembourg", + "Europe/Madrid", + "Europe/Malta", + "Europe/Mariehamn", + "Europe/Minsk", + "Europe/Monaco", + "Europe/Moscow", + "Europe/Nicosia", + "Europe/Oslo", + "Europe/Paris", + "Europe/Podgorica", + "Europe/Prague", + "Europe/Riga", + "Europe/Rome", + "Europe/Samara", + "Europe/San_Marino", + "Europe/Sarajevo", + "Europe/Saratov", + "Europe/Simferopol", + "Europe/Skopje", + "Europe/Sofia", + "Europe/Stockholm", + "Europe/Tallinn", + "Europe/Tirane", + "Europe/Tiraspol", + "Europe/Ulyanovsk", + "Europe/Uzhgorod", + "Europe/Vaduz", + "Europe/Vatican", + "Europe/Vienna", + "Europe/Vilnius", + "Europe/Volgograd", + "Europe/Warsaw", + "Europe/Zagreb", + "Europe/Zaporozhye", + "Europe/Zurich", + "GB", + "GB-Eire", + "GMT", + "GMT+0", + "GMT-0", + "GMT0", + "Greenwich", + "HST", + "Hongkong", + "Iceland", + "Indian/Antananarivo", + "Indian/Chagos", + "Indian/Christmas", + "Indian/Cocos", + "Indian/Comoro", + "Indian/Kerguelen", + "Indian/Mahe", + "Indian/Maldives", + "Indian/Mauritius", + "Indian/Mayotte", + "Indian/Reunion", + "Iran", + "Israel", + "Jamaica", + "Japan", + "Kwajalein", + "Libya", + "MET", + "MST", + "MST7MDT", + "Mexico/BajaNorte", + "Mexico/BajaSur", + "Mexico/General", + "NZ", + "NZ-CHAT", + "Navajo", + "PRC", + "PST8PDT", + "Pacific/Apia", + "Pacific/Auckland", + "Pacific/Bougainville", + "Pacific/Chatham", + "Pacific/Chuuk", + "Pacific/Easter", + "Pacific/Efate", + "Pacific/Enderbury", + "Pacific/Fakaofo", + "Pacific/Fiji", + "Pacific/Funafuti", + "Pacific/Galapagos", + "Pacific/Gambier", + "Pacific/Guadalcanal", + "Pacific/Guam", + "Pacific/Honolulu", + "Pacific/Johnston", + "Pacific/Kiritimati", + "Pacific/Kosrae", + "Pacific/Kwajalein", + "Pacific/Majuro", + "Pacific/Marquesas", + "Pacific/Midway", + "Pacific/Nauru", + "Pacific/Niue", + "Pacific/Norfolk", + "Pacific/Noumea", + "Pacific/Pago_Pago", + "Pacific/Palau", + "Pacific/Pitcairn", + "Pacific/Pohnpei", + "Pacific/Ponape", + "Pacific/Port_Moresby", + "Pacific/Rarotonga", + "Pacific/Saipan", + "Pacific/Samoa", + "Pacific/Tahiti", + "Pacific/Tarawa", + "Pacific/Tongatapu", + "Pacific/Truk", + "Pacific/Wake", + "Pacific/Wallis", + "Pacific/Yap", + "Poland", + "Portugal", + "ROC", + "ROK", + "Singapore", + "Turkey", + "UCT", + "US/Alaska", + "US/Aleutian", + "US/Arizona", + "US/Central", + "US/East-Indiana", + "US/Eastern", + "US/Hawaii", + "US/Indiana-Starke", + "US/Michigan", + "US/Mountain", + "US/Pacific", + "US/Samoa", + "UTC", + "Universal", + "W-SU", + "WET", + "Zulu", + nullptr}; std::vector AllTimeZoneNames() { std::vector names; diff --git a/absl/time/internal/cctz/src/civil_time_detail.cc b/absl/time/internal/cctz/src/civil_time_detail.cc index cb40b6bc..0b07e397 100644 --- a/absl/time/internal/cctz/src/civil_time_detail.cc +++ b/absl/time/internal/cctz/src/civil_time_detail.cc @@ -18,7 +18,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { namespace detail { @@ -87,4 +90,5 @@ std::ostream& operator<<(std::ostream& os, weekday wd) { } // namespace detail } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/cctz/src/civil_time_test.cc b/absl/time/internal/cctz/src/civil_time_test.cc index 10a5ffe5..be894d70 100644 --- a/absl/time/internal/cctz/src/civil_time_test.cc +++ b/absl/time/internal/cctz/src/civil_time_test.cc @@ -21,8 +21,10 @@ #include #include "gtest/gtest.h" +#include "absl/base/config.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -1014,19 +1016,13 @@ TEST(CivilTime, LeapYears) { int day; } leap_day; // The date of the day after Feb 28. } kLeapYearTable[]{ - {1900, 365, {3, 1}}, - {1999, 365, {3, 1}}, + {1900, 365, {3, 1}}, {1999, 365, {3, 1}}, {2000, 366, {2, 29}}, // leap year - {2001, 365, {3, 1}}, - {2002, 365, {3, 1}}, - {2003, 365, {3, 1}}, - {2004, 366, {2, 29}}, // leap year - {2005, 365, {3, 1}}, - {2006, 365, {3, 1}}, - {2007, 365, {3, 1}}, - {2008, 366, {2, 29}}, // leap year - {2009, 365, {3, 1}}, - {2100, 365, {3, 1}}, + {2001, 365, {3, 1}}, {2002, 365, {3, 1}}, + {2003, 365, {3, 1}}, {2004, 366, {2, 29}}, // leap year + {2005, 365, {3, 1}}, {2006, 365, {3, 1}}, + {2007, 365, {3, 1}}, {2008, 366, {2, 29}}, // leap year + {2009, 365, {3, 1}}, {2100, 365, {3, 1}}, }; for (const auto& e : kLeapYearTable) { @@ -1056,4 +1052,5 @@ TEST(CivilTime, FirstThursdayInMonth) { } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/cctz/src/time_zone_fixed.cc b/absl/time/internal/cctz/src/time_zone_fixed.cc index b0d159a2..a342e37d 100644 --- a/absl/time/internal/cctz/src/time_zone_fixed.cc +++ b/absl/time/internal/cctz/src/time_zone_fixed.cc @@ -20,7 +20,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -59,11 +62,9 @@ bool FixedOffsetFromName(const std::string& name, seconds* offset) { const char* const ep = kFixedZonePrefix + prefix_len; if (name.size() != prefix_len + 9) // +99:99:99 return false; - if (!std::equal(kFixedZonePrefix, ep, name.begin())) - return false; + if (!std::equal(kFixedZonePrefix, ep, name.begin())) return false; const char* np = name.data() + prefix_len; - if (np[0] != '+' && np[0] != '-') - return false; + if (np[0] != '+' && np[0] != '-') return false; if (np[3] != ':' || np[6] != ':') // see note below about large offsets return false; @@ -135,4 +136,5 @@ std::string FixedOffsetToAbbr(const seconds& offset) { } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/cctz/src/time_zone_fixed.h b/absl/time/internal/cctz/src/time_zone_fixed.h index 9c1f5e7d..e74a0bbd 100644 --- a/absl/time/internal/cctz/src/time_zone_fixed.h +++ b/absl/time/internal/cctz/src/time_zone_fixed.h @@ -17,9 +17,11 @@ #include +#include "absl/base/config.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -44,6 +46,7 @@ std::string FixedOffsetToAbbr(const seconds& offset); } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_ diff --git a/absl/time/internal/cctz/src/time_zone_format.cc b/absl/time/internal/cctz/src/time_zone_format.cc index 84e280b1..950b23a1 100644 --- a/absl/time/internal/cctz/src/time_zone_format.cc +++ b/absl/time/internal/cctz/src/time_zone_format.cc @@ -13,17 +13,18 @@ // limitations under the License. #if !defined(HAS_STRPTIME) -# if !defined(_MSC_VER) && !defined(__MINGW32__) -# define HAS_STRPTIME 1 // assume everyone has strptime() except windows -# endif +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#define HAS_STRPTIME 1 // assume everyone has strptime() except windows +#endif #endif #if defined(HAS_STRPTIME) && HAS_STRPTIME -# if !defined(_XOPEN_SOURCE) -# define _XOPEN_SOURCE // Definedness suffices for strptime. -# endif +#if !defined(_XOPEN_SOURCE) +#define _XOPEN_SOURCE // Definedness suffices for strptime. +#endif #endif +#include "absl/base/config.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h" // Include time.h directly since, by C++ standards, ctime doesn't have to @@ -48,6 +49,7 @@ #include "time_zone_if.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { namespace detail { @@ -502,8 +504,9 @@ std::string format(const std::string& format, const time_point& tp, bp = ep; if (n > 0) { if (n > kDigits10_64) n = kDigits10_64; - bp = Format64(bp, n, (n > 15) ? fs.count() * kExp10[n - 15] - : fs.count() / kExp10[15 - n]); + bp = Format64(bp, n, + (n > 15) ? fs.count() * kExp10[n - 15] + : fs.count() / kExp10[15 - n]); if (*np == 'S') *--bp = '.'; } if (*np == 'S') bp = Format02d(bp, al.cs.second()); @@ -720,10 +723,9 @@ bool parse(const std::string& format, const std::string& input, data = ParseZone(data, &zone); continue; case 's': - data = ParseInt(data, 0, - std::numeric_limits::min(), - std::numeric_limits::max(), - &percent_s); + data = + ParseInt(data, 0, std::numeric_limits::min(), + std::numeric_limits::max(), &percent_s); if (data != nullptr) saw_percent_s = true; continue; case ':': @@ -916,4 +918,5 @@ bool parse(const std::string& format, const std::string& input, } // namespace detail } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/cctz/src/time_zone_format_test.cc b/absl/time/internal/cctz/src/time_zone_format_test.cc index 705ccdcd..de75629a 100644 --- a/absl/time/internal/cctz/src/time_zone_format_test.cc +++ b/absl/time/internal/cctz/src/time_zone_format_test.cc @@ -12,20 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "absl/time/internal/cctz/include/cctz/time_zone.h" - #include #include #include #include -#include "absl/time/internal/cctz/include/cctz/civil_time.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/base/config.h" +#include "absl/time/internal/cctz/include/cctz/civil_time.h" +#include "absl/time/internal/cctz/include/cctz/time_zone.h" namespace chrono = std::chrono; namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -48,10 +49,10 @@ namespace { } while (0) const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez"; -const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez"; +const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez"; const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z"; -const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z"; +const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z"; // A helper that tests the given format specifier by itself, and with leading // and trailing characters. For example: TestFormatSpecifier(tp, "%a", "Thu"). @@ -88,8 +89,11 @@ TEST(Format, TimePointResolution) { format(kFmt, chrono::time_point_cast(t0), utc)); EXPECT_EQ("03:04:05", format(kFmt, chrono::time_point_cast(t0), utc)); - EXPECT_EQ("03:04:05", - format(kFmt, chrono::time_point_cast(t0), utc)); + EXPECT_EQ( + "03:04:05", + format(kFmt, + chrono::time_point_cast(t0), + utc)); EXPECT_EQ("03:04:00", format(kFmt, chrono::time_point_cast(t0), utc)); EXPECT_EQ("03:00:00", @@ -110,12 +114,10 @@ TEST(Format, TimePointExtendedResolution) { EXPECT_EQ( "12:34:56.012345678901234", detail::format(kFmt, tp, detail::femtoseconds(12345678901234), utc)); - EXPECT_EQ( - "12:34:56.001234567890123", - detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc)); - EXPECT_EQ( - "12:34:56.000123456789012", - detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc)); + EXPECT_EQ("12:34:56.001234567890123", + detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc)); + EXPECT_EQ("12:34:56.000123456789012", + detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc)); EXPECT_EQ("12:34:56.000000000000123", detail::format(kFmt, tp, detail::femtoseconds(123), utc)); @@ -1416,8 +1418,8 @@ TEST(Parse, MaxRange) { parse(RFC3339_sec, "-292277022657-01-27T08:29:51+01:00", utc, &tp)); // tests max/min civil-second overflow - EXPECT_FALSE(parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01", - utc, &tp)); + EXPECT_FALSE( + parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01", utc, &tp)); EXPECT_FALSE(parse(RFC3339_sec, "-9223372036854775808-01-01T00:00:00+00:01", utc, &tp)); @@ -1474,7 +1476,8 @@ TEST(FormatParse, RoundTrip) { TEST(FormatParse, RoundTripDistantFuture) { const time_zone utc = utc_time_zone(); - const time_point in = time_point::max(); + const time_point in = + time_point::max(); const std::string s = format(RFC3339_full, in, utc); time_point out; EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s; @@ -1483,7 +1486,8 @@ TEST(FormatParse, RoundTripDistantFuture) { TEST(FormatParse, RoundTripDistantPast) { const time_zone utc = utc_time_zone(); - const time_point in = time_point::min(); + const time_point in = + time_point::min(); const std::string s = format(RFC3339_full, in, utc); time_point out; EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s; @@ -1492,4 +1496,5 @@ TEST(FormatParse, RoundTripDistantPast) { } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/cctz/src/time_zone_if.cc b/absl/time/internal/cctz/src/time_zone_if.cc index 09aaee5f..0319b2f9 100644 --- a/absl/time/internal/cctz/src/time_zone_if.cc +++ b/absl/time/internal/cctz/src/time_zone_if.cc @@ -13,10 +13,13 @@ // limitations under the License. #include "time_zone_if.h" + +#include "absl/base/config.h" #include "time_zone_info.h" #include "time_zone_libc.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -38,4 +41,5 @@ TimeZoneIf::~TimeZoneIf() {} } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/cctz/src/time_zone_if.h b/absl/time/internal/cctz/src/time_zone_if.h index d000b7a5..32c0891c 100644 --- a/absl/time/internal/cctz/src/time_zone_if.h +++ b/absl/time/internal/cctz/src/time_zone_if.h @@ -20,10 +20,12 @@ #include #include +#include "absl/base/config.h" #include "absl/time/internal/cctz/include/cctz/civil_time.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -38,8 +40,7 @@ class TimeZoneIf { virtual time_zone::absolute_lookup BreakTime( const time_point& tp) const = 0; - virtual time_zone::civil_lookup MakeTime( - const civil_second& cs) const = 0; + virtual time_zone::civil_lookup MakeTime(const civil_second& cs) const = 0; virtual bool NextTransition(const time_point& tp, time_zone::civil_transition* trans) const = 0; @@ -58,15 +59,18 @@ class TimeZoneIf { // Unix clock are second aligned, but not that they share an epoch. inline std::int_fast64_t ToUnixSeconds(const time_point& tp) { return (tp - std::chrono::time_point_cast( - std::chrono::system_clock::from_time_t(0))).count(); + std::chrono::system_clock::from_time_t(0))) + .count(); } inline time_point FromUnixSeconds(std::int_fast64_t t) { return std::chrono::time_point_cast( - std::chrono::system_clock::from_time_t(0)) + seconds(t); + std::chrono::system_clock::from_time_t(0)) + + seconds(t); } } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_ diff --git a/absl/time/internal/cctz/src/time_zone_impl.cc b/absl/time/internal/cctz/src/time_zone_impl.cc index a241e951..030ae0e1 100644 --- a/absl/time/internal/cctz/src/time_zone_impl.cc +++ b/absl/time/internal/cctz/src/time_zone_impl.cc @@ -20,9 +20,11 @@ #include #include +#include "absl/base/config.h" #include "time_zone_fixed.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -43,9 +45,7 @@ std::mutex& TimeZoneMutex() { } // namespace -time_zone time_zone::Impl::UTC() { - return time_zone(UTCImpl()); -} +time_zone time_zone::Impl::UTC() { return time_zone(UTCImpl()); } bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) { const time_zone::Impl* const utc_impl = UTCImpl(); @@ -117,4 +117,5 @@ const time_zone::Impl* time_zone::Impl::UTCImpl() { } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/cctz/src/time_zone_impl.h b/absl/time/internal/cctz/src/time_zone_impl.h index b73fad9b..69806c10 100644 --- a/absl/time/internal/cctz/src/time_zone_impl.h +++ b/absl/time/internal/cctz/src/time_zone_impl.h @@ -18,12 +18,14 @@ #include #include +#include "absl/base/config.h" #include "absl/time/internal/cctz/include/cctz/civil_time.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h" #include "time_zone_if.h" #include "time_zone_info.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -85,6 +87,7 @@ class time_zone::Impl { } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_ diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc index d3e1ae29..971542d0 100644 --- a/absl/time/internal/cctz/src/time_zone_info.cc +++ b/absl/time/internal/cctz/src/time_zone_info.cc @@ -45,11 +45,13 @@ #include #include +#include "absl/base/config.h" #include "absl/time/internal/cctz/include/cctz/civil_time.h" #include "time_zone_fixed.h" #include "time_zone_posix.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -65,8 +67,8 @@ const std::int_least32_t kDaysPerYear[2] = {365, 366}; // The day offsets of the beginning of each (1-based) month in non-leap and // leap years respectively (e.g., 335 days before December in a leap year). const std::int_least16_t kMonthOffsets[2][1 + 12 + 1] = { - {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, - {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}, + {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, + {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}, }; // We reject leap-second encoded zoneinfo and so assume 60-second minutes. @@ -77,8 +79,8 @@ const std::int_least64_t kSecsPer400Years = 146097LL * kSecsPerDay; // Like kDaysPerYear[] but scaled up by a factor of kSecsPerDay. const std::int_least32_t kSecsPerYear[2] = { - 365 * kSecsPerDay, - 366 * kSecsPerDay, + 365 * kSecsPerDay, + 366 * kSecsPerDay, }; // Single-byte, unsigned numeric values are encoded directly. @@ -172,8 +174,8 @@ inline time_zone::civil_lookup MakeRepeated(const Transition& tr, } inline civil_second YearShift(const civil_second& cs, year_t shift) { - return civil_second(cs.year() + shift, cs.month(), cs.day(), - cs.hour(), cs.minute(), cs.second()); + return civil_second(cs.year() + shift, cs.month(), cs.day(), cs.hour(), + cs.minute(), cs.second()); } } // namespace @@ -216,7 +218,7 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) { default_transition_type_ = 0; abbreviations_ = FixedOffsetToAbbr(offset); abbreviations_.append(1, '\0'); // add NUL - future_spec_.clear(); // never needed for a fixed-offset zone + future_spec_.clear(); // never needed for a fixed-offset zone extended_ = false; tt.civil_max = LocalTime(seconds::max().count(), tt).cs; @@ -393,31 +395,24 @@ void TimeZoneInfo::ExtendTransitions(const std::string& name, bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { // Read and validate the header. tzhead tzh; - if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) - return false; + if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false; if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0) return false; Header hdr; - if (!hdr.Build(tzh)) - return false; + if (!hdr.Build(tzh)) return false; std::size_t time_len = 4; if (tzh.tzh_version[0] != '\0') { // Skip the 4-byte data. - if (zip->Skip(hdr.DataLength(time_len)) != 0) - return false; + if (zip->Skip(hdr.DataLength(time_len)) != 0) return false; // Read and validate the header for the 8-byte data. - if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) - return false; + if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false; if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0) return false; - if (tzh.tzh_version[0] == '\0') - return false; - if (!hdr.Build(tzh)) - return false; + if (tzh.tzh_version[0] == '\0') return false; + if (!hdr.Build(tzh)) return false; time_len = 8; } - if (hdr.typecnt == 0) - return false; + if (hdr.typecnt == 0) return false; if (hdr.leapcnt != 0) { // This code assumes 60-second minutes so we do not want // the leap-second encoded zoneinfo. We could reverse the @@ -425,16 +420,13 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { // so currently we simply reject such data. return false; } - if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt) - return false; - if (hdr.ttisutcnt != 0 && hdr.ttisutcnt != hdr.typecnt) - return false; + if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt) return false; + if (hdr.ttisutcnt != 0 && hdr.ttisutcnt != hdr.typecnt) return false; // Read the data into a local buffer. std::size_t len = hdr.DataLength(time_len); std::vector tbuf(len); - if (zip->Read(tbuf.data(), len) != len) - return false; + if (zip->Read(tbuf.data(), len) != len) return false; const char* bp = tbuf.data(); // Decode and validate the transitions. @@ -452,10 +444,8 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { bool seen_type_0 = false; for (std::size_t i = 0; i != hdr.timecnt; ++i) { transitions_[i].type_index = Decode8(bp++); - if (transitions_[i].type_index >= hdr.typecnt) - return false; - if (transitions_[i].type_index == 0) - seen_type_0 = true; + if (transitions_[i].type_index >= hdr.typecnt) return false; + if (transitions_[i].type_index == 0) seen_type_0 = true; } // Decode and validate the transition types. @@ -469,8 +459,7 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { bp += 4; transition_types_[i].is_dst = (Decode8(bp++) != 0); transition_types_[i].abbr_index = Decode8(bp++); - if (transition_types_[i].abbr_index >= hdr.charcnt) - return false; + if (transition_types_[i].abbr_index >= hdr.charcnt) return false; } // Determine the before-first-transition type. @@ -479,13 +468,10 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { std::uint_fast8_t index = 0; if (transition_types_[0].is_dst) { index = transitions_[0].type_index; - while (index != 0 && transition_types_[index].is_dst) - --index; + while (index != 0 && transition_types_[index].is_dst) --index; } - while (index != hdr.typecnt && transition_types_[index].is_dst) - ++index; - if (index != hdr.typecnt) - default_transition_type_ = index; + while (index != hdr.typecnt && transition_types_[index].is_dst) ++index; + if (index != hdr.typecnt) default_transition_type_ = index; } // Copy all the abbreviations. @@ -509,11 +495,9 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { unsigned char ch; // all non-EOF results are positive return (azip->Read(&ch, 1) == 1) ? ch : EOF; }; - if (get_char(zip) != '\n') - return false; + if (get_char(zip) != '\n') return false; for (int c = get_char(zip); c != '\n'; c = get_char(zip)) { - if (c == EOF) - return false; + if (c == EOF) return false; future_spec_.push_back(static_cast(c)); } } @@ -624,7 +608,7 @@ class FileZoneInfoSource : public ZoneInfoSource { : fp_(fp, fclose), len_(len) {} private: - std::unique_ptr fp_; + std::unique_ptr fp_; std::size_t len_; }; @@ -748,13 +732,13 @@ time_zone::absolute_lookup TimeZoneInfo::LocalTime( // A civil time in "+offset" looks like (time+offset) in UTC. // Note: We perform two additions in the civil_second domain to // sidestep the chance of overflow in (unix_time + tt.utc_offset). - return {(civil_second() + unix_time) + tt.utc_offset, - tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]}; + return {(civil_second() + unix_time) + tt.utc_offset, tt.utc_offset, + tt.is_dst, &abbreviations_[tt.abbr_index]}; } // BreakTime() translation for a particular transition. -time_zone::absolute_lookup TimeZoneInfo::LocalTime( - std::int_fast64_t unix_time, const Transition& tr) const { +time_zone::absolute_lookup TimeZoneInfo::LocalTime(std::int_fast64_t unix_time, + const Transition& tr) const { const TransitionType& tt = transition_types_[tr.type_index]; // Note: (unix_time - tr.unix_time) will never overflow as we // have ensured that there is always a "nearby" transition. @@ -897,9 +881,7 @@ time_zone::civil_lookup TimeZoneInfo::MakeTime(const civil_second& cs) const { return MakeUnique(tr->unix_time + (cs - tr->civil_sec)); } -std::string TimeZoneInfo::Version() const { - return version_; -} +std::string TimeZoneInfo::Version() const { return version_; } std::string TimeZoneInfo::Description() const { std::ostringstream oss; @@ -921,8 +903,8 @@ bool TimeZoneInfo::NextTransition(const time_point& tp, } std::int_fast64_t unix_time = ToUnixSeconds(tp); const Transition target = {unix_time, 0, civil_second(), civil_second()}; - const Transition* tr = std::upper_bound(begin, end, target, - Transition::ByUnixTime()); + const Transition* tr = + std::upper_bound(begin, end, target, Transition::ByUnixTime()); for (; tr != end; ++tr) { // skip no-op transitions std::uint_fast8_t prev_type_index = (tr == begin) ? default_transition_type_ : tr[-1].type_index; @@ -956,8 +938,8 @@ bool TimeZoneInfo::PrevTransition(const time_point& tp, unix_time += 1; // ceils } const Transition target = {unix_time, 0, civil_second(), civil_second()}; - const Transition* tr = std::lower_bound(begin, end, target, - Transition::ByUnixTime()); + const Transition* tr = + std::lower_bound(begin, end, target, Transition::ByUnixTime()); for (; tr != begin; --tr) { // skip no-op transitions std::uint_fast8_t prev_type_index = (tr - 1 == begin) ? default_transition_type_ : tr[-2].type_index; @@ -972,4 +954,5 @@ bool TimeZoneInfo::PrevTransition(const time_point& tp, } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/cctz/src/time_zone_info.h b/absl/time/internal/cctz/src/time_zone_info.h index 81cd402f..2a10c06c 100644 --- a/absl/time/internal/cctz/src/time_zone_info.h +++ b/absl/time/internal/cctz/src/time_zone_info.h @@ -21,6 +21,7 @@ #include #include +#include "absl/base/config.h" #include "absl/time/internal/cctz/include/cctz/civil_time.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h" #include "absl/time/internal/cctz/include/cctz/zone_info_source.h" @@ -28,6 +29,7 @@ #include "tzfile.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -72,8 +74,7 @@ class TimeZoneInfo : public TimeZoneIf { // TimeZoneIf implementations. time_zone::absolute_lookup BreakTime( const time_point& tp) const override; - time_zone::civil_lookup MakeTime( - const civil_second& cs) const override; + time_zone::civil_lookup MakeTime(const civil_second& cs) const override; bool NextTransition(const time_point& tp, time_zone::civil_transition* trans) const override; bool PrevTransition(const time_point& tp, @@ -82,7 +83,7 @@ class TimeZoneInfo : public TimeZoneIf { std::string Description() const override; private: - struct Header { // counts of: + struct Header { // counts of: std::size_t timecnt; // transition times std::size_t typecnt; // transition types std::size_t charcnt; // zone abbreviation characters @@ -114,7 +115,7 @@ class TimeZoneInfo : public TimeZoneIf { std::vector transitions_; // ordered by unix_time and civil_sec std::vector transition_types_; // distinct transition types - std::uint_fast8_t default_transition_type_; // for before first transition + std::uint_fast8_t default_transition_type_; // for before first transition std::string abbreviations_; // all the NUL-terminated abbreviations std::string version_; // the tzdata version if available @@ -131,6 +132,7 @@ class TimeZoneInfo : public TimeZoneIf { } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc index 6095e764..47cf84c6 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/absl/time/internal/cctz/src/time_zone_libc.cc @@ -23,10 +23,12 @@ #include #include +#include "absl/base/config.h" #include "absl/time/internal/cctz/include/cctz/civil_time.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -84,9 +86,7 @@ auto tm_gmtoff(const T& tm) -> decltype(tm.__tm_gmtoff) { } #endif // tm_gmtoff #if defined(tm_zone) -auto tm_zone(const std::tm& tm) -> decltype(tm.tm_zone) { - return tm.tm_zone; -} +auto tm_zone(const std::tm& tm) -> decltype(tm.tm_zone) { return tm.tm_zone; } #elif defined(__tm_zone) auto tm_zone(const std::tm& tm) -> decltype(tm.__tm_zone) { return tm.__tm_zone; @@ -103,19 +103,19 @@ auto tm_zone(const T& tm) -> decltype(tm.__tm_zone) { #endif // tm_zone #endif -inline std::tm* gm_time(const std::time_t *timep, std::tm *result) { +inline std::tm* gm_time(const std::time_t* timep, std::tm* result) { #if defined(_WIN32) || defined(_WIN64) - return gmtime_s(result, timep) ? nullptr : result; + return gmtime_s(result, timep) ? nullptr : result; #else - return gmtime_r(timep, result); + return gmtime_r(timep, result); #endif } -inline std::tm* local_time(const std::time_t *timep, std::tm *result) { +inline std::tm* local_time(const std::time_t* timep, std::tm* result) { #if defined(_WIN32) || defined(_WIN64) - return localtime_s(result, timep) ? nullptr : result; + return localtime_s(result, timep) ? nullptr : result; #else - return localtime_r(timep, result); + return localtime_r(timep, result); #endif } @@ -208,8 +208,8 @@ time_zone::absolute_lookup TimeZoneLibC::BreakTime( } const year_t year = tmp->tm_year + year_t{1900}; - al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, + tmp->tm_min, tmp->tm_sec); al.offset = static_cast(tm_gmtoff(*tmp)); al.abbr = local_ ? tm_zone(*tmp) : "UTC"; // as expected by cctz al.is_dst = tmp->tm_isdst > 0; @@ -304,4 +304,5 @@ std::string TimeZoneLibC::Description() const { } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/cctz/src/time_zone_libc.h b/absl/time/internal/cctz/src/time_zone_libc.h index 0d18e9a7..1da9039a 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.h +++ b/absl/time/internal/cctz/src/time_zone_libc.h @@ -17,9 +17,11 @@ #include +#include "absl/base/config.h" #include "time_zone_if.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -33,8 +35,7 @@ class TimeZoneLibC : public TimeZoneIf { // TimeZoneIf implementations. time_zone::absolute_lookup BreakTime( const time_point& tp) const override; - time_zone::civil_lookup MakeTime( - const civil_second& cs) const override; + time_zone::civil_lookup MakeTime(const civil_second& cs) const override; bool NextTransition(const time_point& tp, time_zone::civil_transition* trans) const override; bool PrevTransition(const time_point& tp, @@ -48,6 +49,7 @@ class TimeZoneLibC : public TimeZoneIf { } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_ diff --git a/absl/time/internal/cctz/src/time_zone_lookup.cc b/absl/time/internal/cctz/src/time_zone_lookup.cc index 3c53dd1a..efdea64b 100644 --- a/absl/time/internal/cctz/src/time_zone_lookup.cc +++ b/absl/time/internal/cctz/src/time_zone_lookup.cc @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "absl/base/config.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h" #if defined(__ANDROID__) @@ -23,6 +24,7 @@ #if defined(__APPLE__) #include + #include #endif @@ -34,6 +36,7 @@ #include "time_zone_impl.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -66,9 +69,7 @@ int __system_property_get(const char* name, char* value) { } // namespace #endif -std::string time_zone::name() const { - return effective_impl().Name(); -} +std::string time_zone::name() const { return effective_impl().Name(); } time_zone::absolute_lookup time_zone::lookup( const time_point& tp) const { @@ -89,9 +90,7 @@ bool time_zone::prev_transition(const time_point& tp, return effective_impl().PrevTransition(tp, trans); } -std::string time_zone::version() const { - return effective_impl().Version(); -} +std::string time_zone::version() const { return effective_impl().Version(); } std::string time_zone::description() const { return effective_impl().Description(); @@ -184,4 +183,5 @@ time_zone local_time_zone() { } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc index 42dd6d55..227b1278 100644 --- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc +++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "absl/time/internal/cctz/include/cctz/time_zone.h" - #include #include #include @@ -23,613 +21,614 @@ #include #include -#include "absl/time/internal/cctz/include/cctz/civil_time.h" #include "gtest/gtest.h" +#include "absl/base/config.h" +#include "absl/time/internal/cctz/include/cctz/civil_time.h" +#include "absl/time/internal/cctz/include/cctz/time_zone.h" namespace chrono = std::chrono; namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { namespace { // A list of known time-zone names. -const char* const kTimeZoneNames[] = { - "Africa/Abidjan", - "Africa/Accra", - "Africa/Addis_Ababa", - "Africa/Algiers", - "Africa/Asmara", - "Africa/Asmera", - "Africa/Bamako", - "Africa/Bangui", - "Africa/Banjul", - "Africa/Bissau", - "Africa/Blantyre", - "Africa/Brazzaville", - "Africa/Bujumbura", - "Africa/Cairo", - "Africa/Casablanca", - "Africa/Ceuta", - "Africa/Conakry", - "Africa/Dakar", - "Africa/Dar_es_Salaam", - "Africa/Djibouti", - "Africa/Douala", - "Africa/El_Aaiun", - "Africa/Freetown", - "Africa/Gaborone", - "Africa/Harare", - "Africa/Johannesburg", - "Africa/Juba", - "Africa/Kampala", - "Africa/Khartoum", - "Africa/Kigali", - "Africa/Kinshasa", - "Africa/Lagos", - "Africa/Libreville", - "Africa/Lome", - "Africa/Luanda", - "Africa/Lubumbashi", - "Africa/Lusaka", - "Africa/Malabo", - "Africa/Maputo", - "Africa/Maseru", - "Africa/Mbabane", - "Africa/Mogadishu", - "Africa/Monrovia", - "Africa/Nairobi", - "Africa/Ndjamena", - "Africa/Niamey", - "Africa/Nouakchott", - "Africa/Ouagadougou", - "Africa/Porto-Novo", - "Africa/Sao_Tome", - "Africa/Timbuktu", - "Africa/Tripoli", - "Africa/Tunis", - "Africa/Windhoek", - "America/Adak", - "America/Anchorage", - "America/Anguilla", - "America/Antigua", - "America/Araguaina", - "America/Argentina/Buenos_Aires", - "America/Argentina/Catamarca", - "America/Argentina/ComodRivadavia", - "America/Argentina/Cordoba", - "America/Argentina/Jujuy", - "America/Argentina/La_Rioja", - "America/Argentina/Mendoza", - "America/Argentina/Rio_Gallegos", - "America/Argentina/Salta", - "America/Argentina/San_Juan", - "America/Argentina/San_Luis", - "America/Argentina/Tucuman", - "America/Argentina/Ushuaia", - "America/Aruba", - "America/Asuncion", - "America/Atikokan", - "America/Atka", - "America/Bahia", - "America/Bahia_Banderas", - "America/Barbados", - "America/Belem", - "America/Belize", - "America/Blanc-Sablon", - "America/Boa_Vista", - "America/Bogota", - "America/Boise", - "America/Buenos_Aires", - "America/Cambridge_Bay", - "America/Campo_Grande", - "America/Cancun", - "America/Caracas", - "America/Catamarca", - "America/Cayenne", - "America/Cayman", - "America/Chicago", - "America/Chihuahua", - "America/Coral_Harbour", - "America/Cordoba", - "America/Costa_Rica", - "America/Creston", - "America/Cuiaba", - "America/Curacao", - "America/Danmarkshavn", - "America/Dawson", - "America/Dawson_Creek", - "America/Denver", - "America/Detroit", - "America/Dominica", - "America/Edmonton", - "America/Eirunepe", - "America/El_Salvador", - "America/Ensenada", - "America/Fort_Nelson", - "America/Fort_Wayne", - "America/Fortaleza", - "America/Glace_Bay", - "America/Godthab", - "America/Goose_Bay", - "America/Grand_Turk", - "America/Grenada", - "America/Guadeloupe", - "America/Guatemala", - "America/Guayaquil", - "America/Guyana", - "America/Halifax", - "America/Havana", - "America/Hermosillo", - "America/Indiana/Indianapolis", - "America/Indiana/Knox", - "America/Indiana/Marengo", - "America/Indiana/Petersburg", - "America/Indiana/Tell_City", - "America/Indiana/Vevay", - "America/Indiana/Vincennes", - "America/Indiana/Winamac", - "America/Indianapolis", - "America/Inuvik", - "America/Iqaluit", - "America/Jamaica", - "America/Jujuy", - "America/Juneau", - "America/Kentucky/Louisville", - "America/Kentucky/Monticello", - "America/Knox_IN", - "America/Kralendijk", - "America/La_Paz", - "America/Lima", - "America/Los_Angeles", - "America/Louisville", - "America/Lower_Princes", - "America/Maceio", - "America/Managua", - "America/Manaus", - "America/Marigot", - "America/Martinique", - "America/Matamoros", - "America/Mazatlan", - "America/Mendoza", - "America/Menominee", - "America/Merida", - "America/Metlakatla", - "America/Mexico_City", - "America/Miquelon", - "America/Moncton", - "America/Monterrey", - "America/Montevideo", - "America/Montreal", - "America/Montserrat", - "America/Nassau", - "America/New_York", - "America/Nipigon", - "America/Nome", - "America/Noronha", - "America/North_Dakota/Beulah", - "America/North_Dakota/Center", - "America/North_Dakota/New_Salem", - "America/Ojinaga", - "America/Panama", - "America/Pangnirtung", - "America/Paramaribo", - "America/Phoenix", - "America/Port-au-Prince", - "America/Port_of_Spain", - "America/Porto_Acre", - "America/Porto_Velho", - "America/Puerto_Rico", - "America/Punta_Arenas", - "America/Rainy_River", - "America/Rankin_Inlet", - "America/Recife", - "America/Regina", - "America/Resolute", - "America/Rio_Branco", - "America/Rosario", - "America/Santa_Isabel", - "America/Santarem", - "America/Santiago", - "America/Santo_Domingo", - "America/Sao_Paulo", - "America/Scoresbysund", - "America/Shiprock", - "America/Sitka", - "America/St_Barthelemy", - "America/St_Johns", - "America/St_Kitts", - "America/St_Lucia", - "America/St_Thomas", - "America/St_Vincent", - "America/Swift_Current", - "America/Tegucigalpa", - "America/Thule", - "America/Thunder_Bay", - "America/Tijuana", - "America/Toronto", - "America/Tortola", - "America/Vancouver", - "America/Virgin", - "America/Whitehorse", - "America/Winnipeg", - "America/Yakutat", - "America/Yellowknife", - "Antarctica/Casey", - "Antarctica/Davis", - "Antarctica/DumontDUrville", - "Antarctica/Macquarie", - "Antarctica/Mawson", - "Antarctica/McMurdo", - "Antarctica/Palmer", - "Antarctica/Rothera", - "Antarctica/South_Pole", - "Antarctica/Syowa", - "Antarctica/Troll", - "Antarctica/Vostok", - "Arctic/Longyearbyen", - "Asia/Aden", - "Asia/Almaty", - "Asia/Amman", - "Asia/Anadyr", - "Asia/Aqtau", - "Asia/Aqtobe", - "Asia/Ashgabat", - "Asia/Ashkhabad", - "Asia/Atyrau", - "Asia/Baghdad", - "Asia/Bahrain", - "Asia/Baku", - "Asia/Bangkok", - "Asia/Barnaul", - "Asia/Beirut", - "Asia/Bishkek", - "Asia/Brunei", - "Asia/Calcutta", - "Asia/Chita", - "Asia/Choibalsan", - "Asia/Chongqing", - "Asia/Chungking", - "Asia/Colombo", - "Asia/Dacca", - "Asia/Damascus", - "Asia/Dhaka", - "Asia/Dili", - "Asia/Dubai", - "Asia/Dushanbe", - "Asia/Famagusta", - "Asia/Gaza", - "Asia/Harbin", - "Asia/Hebron", - "Asia/Ho_Chi_Minh", - "Asia/Hong_Kong", - "Asia/Hovd", - "Asia/Irkutsk", - "Asia/Istanbul", - "Asia/Jakarta", - "Asia/Jayapura", - "Asia/Jerusalem", - "Asia/Kabul", - "Asia/Kamchatka", - "Asia/Karachi", - "Asia/Kashgar", - "Asia/Kathmandu", - "Asia/Katmandu", - "Asia/Khandyga", - "Asia/Kolkata", - "Asia/Krasnoyarsk", - "Asia/Kuala_Lumpur", - "Asia/Kuching", - "Asia/Kuwait", - "Asia/Macao", - "Asia/Macau", - "Asia/Magadan", - "Asia/Makassar", - "Asia/Manila", - "Asia/Muscat", - "Asia/Nicosia", - "Asia/Novokuznetsk", - "Asia/Novosibirsk", - "Asia/Omsk", - "Asia/Oral", - "Asia/Phnom_Penh", - "Asia/Pontianak", - "Asia/Pyongyang", - "Asia/Qatar", - "Asia/Qostanay", - "Asia/Qyzylorda", - "Asia/Rangoon", - "Asia/Riyadh", - "Asia/Saigon", - "Asia/Sakhalin", - "Asia/Samarkand", - "Asia/Seoul", - "Asia/Shanghai", - "Asia/Singapore", - "Asia/Srednekolymsk", - "Asia/Taipei", - "Asia/Tashkent", - "Asia/Tbilisi", - "Asia/Tehran", - "Asia/Tel_Aviv", - "Asia/Thimbu", - "Asia/Thimphu", - "Asia/Tokyo", - "Asia/Tomsk", - "Asia/Ujung_Pandang", - "Asia/Ulaanbaatar", - "Asia/Ulan_Bator", - "Asia/Urumqi", - "Asia/Ust-Nera", - "Asia/Vientiane", - "Asia/Vladivostok", - "Asia/Yakutsk", - "Asia/Yangon", - "Asia/Yekaterinburg", - "Asia/Yerevan", - "Atlantic/Azores", - "Atlantic/Bermuda", - "Atlantic/Canary", - "Atlantic/Cape_Verde", - "Atlantic/Faeroe", - "Atlantic/Faroe", - "Atlantic/Jan_Mayen", - "Atlantic/Madeira", - "Atlantic/Reykjavik", - "Atlantic/South_Georgia", - "Atlantic/St_Helena", - "Atlantic/Stanley", - "Australia/ACT", - "Australia/Adelaide", - "Australia/Brisbane", - "Australia/Broken_Hill", - "Australia/Canberra", - "Australia/Currie", - "Australia/Darwin", - "Australia/Eucla", - "Australia/Hobart", - "Australia/LHI", - "Australia/Lindeman", - "Australia/Lord_Howe", - "Australia/Melbourne", - "Australia/NSW", - "Australia/North", - "Australia/Perth", - "Australia/Queensland", - "Australia/South", - "Australia/Sydney", - "Australia/Tasmania", - "Australia/Victoria", - "Australia/West", - "Australia/Yancowinna", - "Brazil/Acre", - "Brazil/DeNoronha", - "Brazil/East", - "Brazil/West", - "CET", - "CST6CDT", - "Canada/Atlantic", - "Canada/Central", - "Canada/Eastern", - "Canada/Mountain", - "Canada/Newfoundland", - "Canada/Pacific", - "Canada/Saskatchewan", - "Canada/Yukon", - "Chile/Continental", - "Chile/EasterIsland", - "Cuba", - "EET", - "EST", - "EST5EDT", - "Egypt", - "Eire", - "Etc/GMT", - "Etc/GMT+0", - "Etc/GMT+1", - "Etc/GMT+10", - "Etc/GMT+11", - "Etc/GMT+12", - "Etc/GMT+2", - "Etc/GMT+3", - "Etc/GMT+4", - "Etc/GMT+5", - "Etc/GMT+6", - "Etc/GMT+7", - "Etc/GMT+8", - "Etc/GMT+9", - "Etc/GMT-0", - "Etc/GMT-1", - "Etc/GMT-10", - "Etc/GMT-11", - "Etc/GMT-12", - "Etc/GMT-13", - "Etc/GMT-14", - "Etc/GMT-2", - "Etc/GMT-3", - "Etc/GMT-4", - "Etc/GMT-5", - "Etc/GMT-6", - "Etc/GMT-7", - "Etc/GMT-8", - "Etc/GMT-9", - "Etc/GMT0", - "Etc/Greenwich", - "Etc/UCT", - "Etc/UTC", - "Etc/Universal", - "Etc/Zulu", - "Europe/Amsterdam", - "Europe/Andorra", - "Europe/Astrakhan", - "Europe/Athens", - "Europe/Belfast", - "Europe/Belgrade", - "Europe/Berlin", - "Europe/Bratislava", - "Europe/Brussels", - "Europe/Bucharest", - "Europe/Budapest", - "Europe/Busingen", - "Europe/Chisinau", - "Europe/Copenhagen", - "Europe/Dublin", - "Europe/Gibraltar", - "Europe/Guernsey", - "Europe/Helsinki", - "Europe/Isle_of_Man", - "Europe/Istanbul", - "Europe/Jersey", - "Europe/Kaliningrad", - "Europe/Kiev", - "Europe/Kirov", - "Europe/Lisbon", - "Europe/Ljubljana", - "Europe/London", - "Europe/Luxembourg", - "Europe/Madrid", - "Europe/Malta", - "Europe/Mariehamn", - "Europe/Minsk", - "Europe/Monaco", - "Europe/Moscow", - "Europe/Nicosia", - "Europe/Oslo", - "Europe/Paris", - "Europe/Podgorica", - "Europe/Prague", - "Europe/Riga", - "Europe/Rome", - "Europe/Samara", - "Europe/San_Marino", - "Europe/Sarajevo", - "Europe/Saratov", - "Europe/Simferopol", - "Europe/Skopje", - "Europe/Sofia", - "Europe/Stockholm", - "Europe/Tallinn", - "Europe/Tirane", - "Europe/Tiraspol", - "Europe/Ulyanovsk", - "Europe/Uzhgorod", - "Europe/Vaduz", - "Europe/Vatican", - "Europe/Vienna", - "Europe/Vilnius", - "Europe/Volgograd", - "Europe/Warsaw", - "Europe/Zagreb", - "Europe/Zaporozhye", - "Europe/Zurich", - "GB", - "GB-Eire", - "GMT", - "GMT+0", - "GMT-0", - "GMT0", - "Greenwich", - "HST", - "Hongkong", - "Iceland", - "Indian/Antananarivo", - "Indian/Chagos", - "Indian/Christmas", - "Indian/Cocos", - "Indian/Comoro", - "Indian/Kerguelen", - "Indian/Mahe", - "Indian/Maldives", - "Indian/Mauritius", - "Indian/Mayotte", - "Indian/Reunion", - "Iran", - "Israel", - "Jamaica", - "Japan", - "Kwajalein", - "Libya", - "MET", - "MST", - "MST7MDT", - "Mexico/BajaNorte", - "Mexico/BajaSur", - "Mexico/General", - "NZ", - "NZ-CHAT", - "Navajo", - "PRC", - "PST8PDT", - "Pacific/Apia", - "Pacific/Auckland", - "Pacific/Bougainville", - "Pacific/Chatham", - "Pacific/Chuuk", - "Pacific/Easter", - "Pacific/Efate", - "Pacific/Enderbury", - "Pacific/Fakaofo", - "Pacific/Fiji", - "Pacific/Funafuti", - "Pacific/Galapagos", - "Pacific/Gambier", - "Pacific/Guadalcanal", - "Pacific/Guam", - "Pacific/Honolulu", - "Pacific/Johnston", - "Pacific/Kiritimati", - "Pacific/Kosrae", - "Pacific/Kwajalein", - "Pacific/Majuro", - "Pacific/Marquesas", - "Pacific/Midway", - "Pacific/Nauru", - "Pacific/Niue", - "Pacific/Norfolk", - "Pacific/Noumea", - "Pacific/Pago_Pago", - "Pacific/Palau", - "Pacific/Pitcairn", - "Pacific/Pohnpei", - "Pacific/Ponape", - "Pacific/Port_Moresby", - "Pacific/Rarotonga", - "Pacific/Saipan", - "Pacific/Samoa", - "Pacific/Tahiti", - "Pacific/Tarawa", - "Pacific/Tongatapu", - "Pacific/Truk", - "Pacific/Wake", - "Pacific/Wallis", - "Pacific/Yap", - "Poland", - "Portugal", - "ROC", - "ROK", - "Singapore", - "Turkey", - "UCT", - "US/Alaska", - "US/Aleutian", - "US/Arizona", - "US/Central", - "US/East-Indiana", - "US/Eastern", - "US/Hawaii", - "US/Indiana-Starke", - "US/Michigan", - "US/Mountain", - "US/Pacific", - "US/Samoa", - "UTC", - "Universal", - "W-SU", - "WET", - "Zulu", - nullptr -}; +const char* const kTimeZoneNames[] = {"Africa/Abidjan", + "Africa/Accra", + "Africa/Addis_Ababa", + "Africa/Algiers", + "Africa/Asmara", + "Africa/Asmera", + "Africa/Bamako", + "Africa/Bangui", + "Africa/Banjul", + "Africa/Bissau", + "Africa/Blantyre", + "Africa/Brazzaville", + "Africa/Bujumbura", + "Africa/Cairo", + "Africa/Casablanca", + "Africa/Ceuta", + "Africa/Conakry", + "Africa/Dakar", + "Africa/Dar_es_Salaam", + "Africa/Djibouti", + "Africa/Douala", + "Africa/El_Aaiun", + "Africa/Freetown", + "Africa/Gaborone", + "Africa/Harare", + "Africa/Johannesburg", + "Africa/Juba", + "Africa/Kampala", + "Africa/Khartoum", + "Africa/Kigali", + "Africa/Kinshasa", + "Africa/Lagos", + "Africa/Libreville", + "Africa/Lome", + "Africa/Luanda", + "Africa/Lubumbashi", + "Africa/Lusaka", + "Africa/Malabo", + "Africa/Maputo", + "Africa/Maseru", + "Africa/Mbabane", + "Africa/Mogadishu", + "Africa/Monrovia", + "Africa/Nairobi", + "Africa/Ndjamena", + "Africa/Niamey", + "Africa/Nouakchott", + "Africa/Ouagadougou", + "Africa/Porto-Novo", + "Africa/Sao_Tome", + "Africa/Timbuktu", + "Africa/Tripoli", + "Africa/Tunis", + "Africa/Windhoek", + "America/Adak", + "America/Anchorage", + "America/Anguilla", + "America/Antigua", + "America/Araguaina", + "America/Argentina/Buenos_Aires", + "America/Argentina/Catamarca", + "America/Argentina/ComodRivadavia", + "America/Argentina/Cordoba", + "America/Argentina/Jujuy", + "America/Argentina/La_Rioja", + "America/Argentina/Mendoza", + "America/Argentina/Rio_Gallegos", + "America/Argentina/Salta", + "America/Argentina/San_Juan", + "America/Argentina/San_Luis", + "America/Argentina/Tucuman", + "America/Argentina/Ushuaia", + "America/Aruba", + "America/Asuncion", + "America/Atikokan", + "America/Atka", + "America/Bahia", + "America/Bahia_Banderas", + "America/Barbados", + "America/Belem", + "America/Belize", + "America/Blanc-Sablon", + "America/Boa_Vista", + "America/Bogota", + "America/Boise", + "America/Buenos_Aires", + "America/Cambridge_Bay", + "America/Campo_Grande", + "America/Cancun", + "America/Caracas", + "America/Catamarca", + "America/Cayenne", + "America/Cayman", + "America/Chicago", + "America/Chihuahua", + "America/Coral_Harbour", + "America/Cordoba", + "America/Costa_Rica", + "America/Creston", + "America/Cuiaba", + "America/Curacao", + "America/Danmarkshavn", + "America/Dawson", + "America/Dawson_Creek", + "America/Denver", + "America/Detroit", + "America/Dominica", + "America/Edmonton", + "America/Eirunepe", + "America/El_Salvador", + "America/Ensenada", + "America/Fort_Nelson", + "America/Fort_Wayne", + "America/Fortaleza", + "America/Glace_Bay", + "America/Godthab", + "America/Goose_Bay", + "America/Grand_Turk", + "America/Grenada", + "America/Guadeloupe", + "America/Guatemala", + "America/Guayaquil", + "America/Guyana", + "America/Halifax", + "America/Havana", + "America/Hermosillo", + "America/Indiana/Indianapolis", + "America/Indiana/Knox", + "America/Indiana/Marengo", + "America/Indiana/Petersburg", + "America/Indiana/Tell_City", + "America/Indiana/Vevay", + "America/Indiana/Vincennes", + "America/Indiana/Winamac", + "America/Indianapolis", + "America/Inuvik", + "America/Iqaluit", + "America/Jamaica", + "America/Jujuy", + "America/Juneau", + "America/Kentucky/Louisville", + "America/Kentucky/Monticello", + "America/Knox_IN", + "America/Kralendijk", + "America/La_Paz", + "America/Lima", + "America/Los_Angeles", + "America/Louisville", + "America/Lower_Princes", + "America/Maceio", + "America/Managua", + "America/Manaus", + "America/Marigot", + "America/Martinique", + "America/Matamoros", + "America/Mazatlan", + "America/Mendoza", + "America/Menominee", + "America/Merida", + "America/Metlakatla", + "America/Mexico_City", + "America/Miquelon", + "America/Moncton", + "America/Monterrey", + "America/Montevideo", + "America/Montreal", + "America/Montserrat", + "America/Nassau", + "America/New_York", + "America/Nipigon", + "America/Nome", + "America/Noronha", + "America/North_Dakota/Beulah", + "America/North_Dakota/Center", + "America/North_Dakota/New_Salem", + "America/Ojinaga", + "America/Panama", + "America/Pangnirtung", + "America/Paramaribo", + "America/Phoenix", + "America/Port-au-Prince", + "America/Port_of_Spain", + "America/Porto_Acre", + "America/Porto_Velho", + "America/Puerto_Rico", + "America/Punta_Arenas", + "America/Rainy_River", + "America/Rankin_Inlet", + "America/Recife", + "America/Regina", + "America/Resolute", + "America/Rio_Branco", + "America/Rosario", + "America/Santa_Isabel", + "America/Santarem", + "America/Santiago", + "America/Santo_Domingo", + "America/Sao_Paulo", + "America/Scoresbysund", + "America/Shiprock", + "America/Sitka", + "America/St_Barthelemy", + "America/St_Johns", + "America/St_Kitts", + "America/St_Lucia", + "America/St_Thomas", + "America/St_Vincent", + "America/Swift_Current", + "America/Tegucigalpa", + "America/Thule", + "America/Thunder_Bay", + "America/Tijuana", + "America/Toronto", + "America/Tortola", + "America/Vancouver", + "America/Virgin", + "America/Whitehorse", + "America/Winnipeg", + "America/Yakutat", + "America/Yellowknife", + "Antarctica/Casey", + "Antarctica/Davis", + "Antarctica/DumontDUrville", + "Antarctica/Macquarie", + "Antarctica/Mawson", + "Antarctica/McMurdo", + "Antarctica/Palmer", + "Antarctica/Rothera", + "Antarctica/South_Pole", + "Antarctica/Syowa", + "Antarctica/Troll", + "Antarctica/Vostok", + "Arctic/Longyearbyen", + "Asia/Aden", + "Asia/Almaty", + "Asia/Amman", + "Asia/Anadyr", + "Asia/Aqtau", + "Asia/Aqtobe", + "Asia/Ashgabat", + "Asia/Ashkhabad", + "Asia/Atyrau", + "Asia/Baghdad", + "Asia/Bahrain", + "Asia/Baku", + "Asia/Bangkok", + "Asia/Barnaul", + "Asia/Beirut", + "Asia/Bishkek", + "Asia/Brunei", + "Asia/Calcutta", + "Asia/Chita", + "Asia/Choibalsan", + "Asia/Chongqing", + "Asia/Chungking", + "Asia/Colombo", + "Asia/Dacca", + "Asia/Damascus", + "Asia/Dhaka", + "Asia/Dili", + "Asia/Dubai", + "Asia/Dushanbe", + "Asia/Famagusta", + "Asia/Gaza", + "Asia/Harbin", + "Asia/Hebron", + "Asia/Ho_Chi_Minh", + "Asia/Hong_Kong", + "Asia/Hovd", + "Asia/Irkutsk", + "Asia/Istanbul", + "Asia/Jakarta", + "Asia/Jayapura", + "Asia/Jerusalem", + "Asia/Kabul", + "Asia/Kamchatka", + "Asia/Karachi", + "Asia/Kashgar", + "Asia/Kathmandu", + "Asia/Katmandu", + "Asia/Khandyga", + "Asia/Kolkata", + "Asia/Krasnoyarsk", + "Asia/Kuala_Lumpur", + "Asia/Kuching", + "Asia/Kuwait", + "Asia/Macao", + "Asia/Macau", + "Asia/Magadan", + "Asia/Makassar", + "Asia/Manila", + "Asia/Muscat", + "Asia/Nicosia", + "Asia/Novokuznetsk", + "Asia/Novosibirsk", + "Asia/Omsk", + "Asia/Oral", + "Asia/Phnom_Penh", + "Asia/Pontianak", + "Asia/Pyongyang", + "Asia/Qatar", + "Asia/Qostanay", + "Asia/Qyzylorda", + "Asia/Rangoon", + "Asia/Riyadh", + "Asia/Saigon", + "Asia/Sakhalin", + "Asia/Samarkand", + "Asia/Seoul", + "Asia/Shanghai", + "Asia/Singapore", + "Asia/Srednekolymsk", + "Asia/Taipei", + "Asia/Tashkent", + "Asia/Tbilisi", + "Asia/Tehran", + "Asia/Tel_Aviv", + "Asia/Thimbu", + "Asia/Thimphu", + "Asia/Tokyo", + "Asia/Tomsk", + "Asia/Ujung_Pandang", + "Asia/Ulaanbaatar", + "Asia/Ulan_Bator", + "Asia/Urumqi", + "Asia/Ust-Nera", + "Asia/Vientiane", + "Asia/Vladivostok", + "Asia/Yakutsk", + "Asia/Yangon", + "Asia/Yekaterinburg", + "Asia/Yerevan", + "Atlantic/Azores", + "Atlantic/Bermuda", + "Atlantic/Canary", + "Atlantic/Cape_Verde", + "Atlantic/Faeroe", + "Atlantic/Faroe", + "Atlantic/Jan_Mayen", + "Atlantic/Madeira", + "Atlantic/Reykjavik", + "Atlantic/South_Georgia", + "Atlantic/St_Helena", + "Atlantic/Stanley", + "Australia/ACT", + "Australia/Adelaide", + "Australia/Brisbane", + "Australia/Broken_Hill", + "Australia/Canberra", + "Australia/Currie", + "Australia/Darwin", + "Australia/Eucla", + "Australia/Hobart", + "Australia/LHI", + "Australia/Lindeman", + "Australia/Lord_Howe", + "Australia/Melbourne", + "Australia/NSW", + "Australia/North", + "Australia/Perth", + "Australia/Queensland", + "Australia/South", + "Australia/Sydney", + "Australia/Tasmania", + "Australia/Victoria", + "Australia/West", + "Australia/Yancowinna", + "Brazil/Acre", + "Brazil/DeNoronha", + "Brazil/East", + "Brazil/West", + "CET", + "CST6CDT", + "Canada/Atlantic", + "Canada/Central", + "Canada/Eastern", + "Canada/Mountain", + "Canada/Newfoundland", + "Canada/Pacific", + "Canada/Saskatchewan", + "Canada/Yukon", + "Chile/Continental", + "Chile/EasterIsland", + "Cuba", + "EET", + "EST", + "EST5EDT", + "Egypt", + "Eire", + "Etc/GMT", + "Etc/GMT+0", + "Etc/GMT+1", + "Etc/GMT+10", + "Etc/GMT+11", + "Etc/GMT+12", + "Etc/GMT+2", + "Etc/GMT+3", + "Etc/GMT+4", + "Etc/GMT+5", + "Etc/GMT+6", + "Etc/GMT+7", + "Etc/GMT+8", + "Etc/GMT+9", + "Etc/GMT-0", + "Etc/GMT-1", + "Etc/GMT-10", + "Etc/GMT-11", + "Etc/GMT-12", + "Etc/GMT-13", + "Etc/GMT-14", + "Etc/GMT-2", + "Etc/GMT-3", + "Etc/GMT-4", + "Etc/GMT-5", + "Etc/GMT-6", + "Etc/GMT-7", + "Etc/GMT-8", + "Etc/GMT-9", + "Etc/GMT0", + "Etc/Greenwich", + "Etc/UCT", + "Etc/UTC", + "Etc/Universal", + "Etc/Zulu", + "Europe/Amsterdam", + "Europe/Andorra", + "Europe/Astrakhan", + "Europe/Athens", + "Europe/Belfast", + "Europe/Belgrade", + "Europe/Berlin", + "Europe/Bratislava", + "Europe/Brussels", + "Europe/Bucharest", + "Europe/Budapest", + "Europe/Busingen", + "Europe/Chisinau", + "Europe/Copenhagen", + "Europe/Dublin", + "Europe/Gibraltar", + "Europe/Guernsey", + "Europe/Helsinki", + "Europe/Isle_of_Man", + "Europe/Istanbul", + "Europe/Jersey", + "Europe/Kaliningrad", + "Europe/Kiev", + "Europe/Kirov", + "Europe/Lisbon", + "Europe/Ljubljana", + "Europe/London", + "Europe/Luxembourg", + "Europe/Madrid", + "Europe/Malta", + "Europe/Mariehamn", + "Europe/Minsk", + "Europe/Monaco", + "Europe/Moscow", + "Europe/Nicosia", + "Europe/Oslo", + "Europe/Paris", + "Europe/Podgorica", + "Europe/Prague", + "Europe/Riga", + "Europe/Rome", + "Europe/Samara", + "Europe/San_Marino", + "Europe/Sarajevo", + "Europe/Saratov", + "Europe/Simferopol", + "Europe/Skopje", + "Europe/Sofia", + "Europe/Stockholm", + "Europe/Tallinn", + "Europe/Tirane", + "Europe/Tiraspol", + "Europe/Ulyanovsk", + "Europe/Uzhgorod", + "Europe/Vaduz", + "Europe/Vatican", + "Europe/Vienna", + "Europe/Vilnius", + "Europe/Volgograd", + "Europe/Warsaw", + "Europe/Zagreb", + "Europe/Zaporozhye", + "Europe/Zurich", + "GB", + "GB-Eire", + "GMT", + "GMT+0", + "GMT-0", + "GMT0", + "Greenwich", + "HST", + "Hongkong", + "Iceland", + "Indian/Antananarivo", + "Indian/Chagos", + "Indian/Christmas", + "Indian/Cocos", + "Indian/Comoro", + "Indian/Kerguelen", + "Indian/Mahe", + "Indian/Maldives", + "Indian/Mauritius", + "Indian/Mayotte", + "Indian/Reunion", + "Iran", + "Israel", + "Jamaica", + "Japan", + "Kwajalein", + "Libya", + "MET", + "MST", + "MST7MDT", + "Mexico/BajaNorte", + "Mexico/BajaSur", + "Mexico/General", + "NZ", + "NZ-CHAT", + "Navajo", + "PRC", + "PST8PDT", + "Pacific/Apia", + "Pacific/Auckland", + "Pacific/Bougainville", + "Pacific/Chatham", + "Pacific/Chuuk", + "Pacific/Easter", + "Pacific/Efate", + "Pacific/Enderbury", + "Pacific/Fakaofo", + "Pacific/Fiji", + "Pacific/Funafuti", + "Pacific/Galapagos", + "Pacific/Gambier", + "Pacific/Guadalcanal", + "Pacific/Guam", + "Pacific/Honolulu", + "Pacific/Johnston", + "Pacific/Kiritimati", + "Pacific/Kosrae", + "Pacific/Kwajalein", + "Pacific/Majuro", + "Pacific/Marquesas", + "Pacific/Midway", + "Pacific/Nauru", + "Pacific/Niue", + "Pacific/Norfolk", + "Pacific/Noumea", + "Pacific/Pago_Pago", + "Pacific/Palau", + "Pacific/Pitcairn", + "Pacific/Pohnpei", + "Pacific/Ponape", + "Pacific/Port_Moresby", + "Pacific/Rarotonga", + "Pacific/Saipan", + "Pacific/Samoa", + "Pacific/Tahiti", + "Pacific/Tarawa", + "Pacific/Tongatapu", + "Pacific/Truk", + "Pacific/Wake", + "Pacific/Wallis", + "Pacific/Yap", + "Poland", + "Portugal", + "ROC", + "ROK", + "Singapore", + "Turkey", + "UCT", + "US/Alaska", + "US/Aleutian", + "US/Arizona", + "US/Central", + "US/East-Indiana", + "US/Eastern", + "US/Hawaii", + "US/Indiana-Starke", + "US/Michigan", + "US/Mountain", + "US/Pacific", + "US/Samoa", + "UTC", + "Universal", + "W-SU", + "WET", + "Zulu", + nullptr}; // Helper to return a loaded time zone by value (UTC on error). time_zone LoadZone(const std::string& name) { @@ -724,7 +723,8 @@ TEST(TimeZone, NamedTimeZones) { EXPECT_EQ("America/New_York", nyc.name()); const time_zone syd = LoadZone("Australia/Sydney"); EXPECT_EQ("Australia/Sydney", syd.name()); - const time_zone fixed0 = fixed_time_zone(absl::time_internal::cctz::seconds::zero()); + const time_zone fixed0 = + fixed_time_zone(absl::time_internal::cctz::seconds::zero()); EXPECT_EQ("UTC", fixed0.name()); const time_zone fixed_pos = fixed_time_zone( chrono::hours(3) + chrono::minutes(25) + chrono::seconds(45)); @@ -767,7 +767,8 @@ TEST(TimeZone, Equality) { EXPECT_EQ(implicit_utc, explicit_utc); EXPECT_EQ(implicit_utc.name(), explicit_utc.name()); - const time_zone fixed_zero = fixed_time_zone(absl::time_internal::cctz::seconds::zero()); + const time_zone fixed_zero = + fixed_time_zone(absl::time_internal::cctz::seconds::zero()); EXPECT_EQ(fixed_zero, LoadZone(fixed_zero.name())); EXPECT_EQ(fixed_zero, explicit_utc); @@ -806,8 +807,8 @@ TEST(TimeZone, Equality) { TEST(StdChronoTimePoint, TimeTAlignment) { // Ensures that the Unix epoch and the system clock epoch are an integral // number of seconds apart. This simplifies conversions to/from time_t. - auto diff = chrono::system_clock::time_point() - - chrono::system_clock::from_time_t(0); + auto diff = + chrono::system_clock::time_point() - chrono::system_clock::from_time_t(0); EXPECT_EQ(chrono::system_clock::time_point::duration::zero(), diff % chrono::seconds(1)); } @@ -816,20 +817,20 @@ TEST(BreakTime, TimePointResolution) { const time_zone utc = utc_time_zone(); const auto t0 = chrono::system_clock::from_time_t(0); - ExpectTime(chrono::time_point_cast(t0), utc, - 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - ExpectTime(chrono::time_point_cast(t0), utc, - 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - ExpectTime(chrono::time_point_cast(t0), utc, - 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - ExpectTime(chrono::time_point_cast(t0), utc, - 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - ExpectTime(chrono::time_point_cast(t0), utc, - 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - ExpectTime(chrono::time_point_cast(t0), utc, - 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); - ExpectTime(chrono::time_point_cast(t0), utc, - 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); + ExpectTime(chrono::time_point_cast(t0), utc, 1970, 1, 1, + 0, 0, 0, 0, false, "UTC"); + ExpectTime(chrono::time_point_cast(t0), utc, 1970, 1, 1, + 0, 0, 0, 0, false, "UTC"); + ExpectTime(chrono::time_point_cast(t0), utc, 1970, 1, 1, + 0, 0, 0, 0, false, "UTC"); + ExpectTime(chrono::time_point_cast(t0), utc, 1970, 1, 1, 0, + 0, 0, 0, false, "UTC"); + ExpectTime(chrono::time_point_cast(t0), + utc, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); + ExpectTime(chrono::time_point_cast(t0), utc, 1970, 1, 1, 0, + 0, 0, 0, false, "UTC"); + ExpectTime(chrono::time_point_cast(t0), utc, 1970, 1, 1, 0, 0, + 0, 0, false, "UTC"); } TEST(BreakTime, LocalTimeInUTC) { @@ -911,9 +912,8 @@ TEST(MakeTime, TimePointResolution) { chrono::time_point_cast( convert(civil_second(2015, 1, 2, 3, 4, 5), utc)); EXPECT_EQ("04:00", format("%M:%E*S", tp_m, utc)); - const time_point tp_h = - chrono::time_point_cast( - convert(civil_second(2015, 1, 2, 3, 4, 5), utc)); + const time_point tp_h = chrono::time_point_cast( + convert(civil_second(2015, 1, 2, 3, 4, 5), utc)); EXPECT_EQ("00:00", format("%M:%E*S", tp_h, utc)); } @@ -932,7 +932,7 @@ TEST(MakeTime, Normalization) { // NOTE: Run this with -ftrapv to detect overflow problems. TEST(MakeTime, SysSecondsLimits) { - const char RFC3339[] = "%Y-%m-%dT%H:%M:%S%Ez"; + const char RFC3339[] = "%Y-%m-%dT%H:%M:%S%Ez"; const time_zone utc = utc_time_zone(); const time_zone east = fixed_time_zone(chrono::hours(14)); const time_zone west = fixed_time_zone(-chrono::hours(14)); @@ -1030,8 +1030,7 @@ TEST(MakeTime, LocalTimeLibC) { const auto lc = LoadZone("libc:localtime"); time_zone::civil_transition trans; for (auto tp = zi.lookup(civil_second()).trans; - zi.next_transition(tp, &trans); - tp = zi.lookup(trans.to).trans) { + zi.next_transition(tp, &trans); tp = zi.lookup(trans.to).trans) { const auto fcl = zi.lookup(trans.from); const auto tcl = zi.lookup(trans.to); civil_second cs; // compare cs in zi and lc @@ -1433,4 +1432,5 @@ TEST(TimeZoneEdgeCase, UTC5DigitYear) { } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/cctz/src/time_zone_posix.cc b/absl/time/internal/cctz/src/time_zone_posix.cc index 038740e1..5cdd09e8 100644 --- a/absl/time/internal/cctz/src/time_zone_posix.cc +++ b/absl/time/internal/cctz/src/time_zone_posix.cc @@ -19,7 +19,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -152,4 +155,5 @@ bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res) { } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/cctz/src/time_zone_posix.h b/absl/time/internal/cctz/src/time_zone_posix.h index 6a60022f..0cf29055 100644 --- a/absl/time/internal/cctz/src/time_zone_posix.h +++ b/absl/time/internal/cctz/src/time_zone_posix.h @@ -55,7 +55,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -123,6 +126,7 @@ bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res); } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_ diff --git a/absl/time/internal/cctz/src/tzfile.h b/absl/time/internal/cctz/src/tzfile.h index 51b1f1f3..1ed55e0f 100644 --- a/absl/time/internal/cctz/src/tzfile.h +++ b/absl/time/internal/cctz/src/tzfile.h @@ -22,36 +22,35 @@ */ #ifndef TZDIR -#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */ -#endif /* !defined TZDIR */ +#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */ +#endif /* !defined TZDIR */ #ifndef TZDEFAULT -#define TZDEFAULT "/etc/localtime" +#define TZDEFAULT "/etc/localtime" #endif /* !defined TZDEFAULT */ #ifndef TZDEFRULES -#define TZDEFRULES "posixrules" +#define TZDEFRULES "posixrules" #endif /* !defined TZDEFRULES */ - /* See Internet RFC 8536 for more details about the following format. */ /* ** Each file begins with. . . */ -#define TZ_MAGIC "TZif" +#define TZ_MAGIC "TZif" struct tzhead { - char tzh_magic[4]; /* TZ_MAGIC */ - char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */ - char tzh_reserved[15]; /* reserved; must be zero */ - char tzh_ttisutcnt[4]; /* coded number of trans. time flags */ - char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ - char tzh_leapcnt[4]; /* coded number of leap seconds */ - char tzh_timecnt[4]; /* coded number of transition times */ - char tzh_typecnt[4]; /* coded number of local time types */ - char tzh_charcnt[4]; /* coded number of abbr. chars */ + char tzh_magic[4]; /* TZ_MAGIC */ + char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */ + char tzh_reserved[15]; /* reserved; must be zero */ + char tzh_ttisutcnt[4]; /* coded number of trans. time flags */ + char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ + char tzh_leapcnt[4]; /* coded number of leap seconds */ + char tzh_timecnt[4]; /* coded number of transition times */ + char tzh_typecnt[4]; /* coded number of local time types */ + char tzh_charcnt[4]; /* coded number of abbr. chars */ }; /* @@ -103,21 +102,21 @@ struct tzhead { */ #ifndef TZ_MAX_TIMES -#define TZ_MAX_TIMES 2000 +#define TZ_MAX_TIMES 2000 #endif /* !defined TZ_MAX_TIMES */ #ifndef TZ_MAX_TYPES /* This must be at least 17 for Europe/Samara and Europe/Vilnius. */ -#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ -#endif /* !defined TZ_MAX_TYPES */ +#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ +#endif /* !defined TZ_MAX_TYPES */ #ifndef TZ_MAX_CHARS -#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ - /* (limited by what unsigned chars can hold) */ -#endif /* !defined TZ_MAX_CHARS */ +#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ + /* (limited by what unsigned chars can hold) */ +#endif /* !defined TZ_MAX_CHARS */ #ifndef TZ_MAX_LEAPS -#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ -#endif /* !defined TZ_MAX_LEAPS */ +#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ +#endif /* !defined TZ_MAX_LEAPS */ #endif /* !defined TZFILE_H */ diff --git a/absl/time/internal/cctz/src/zone_info_source.cc b/absl/time/internal/cctz/src/zone_info_source.cc index d5758efa..619ac1fb 100644 --- a/absl/time/internal/cctz/src/zone_info_source.cc +++ b/absl/time/internal/cctz/src/zone_info_source.cc @@ -14,7 +14,10 @@ #include "absl/time/internal/cctz/include/cctz/zone_info_source.h" +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz { @@ -24,9 +27,11 @@ std::string ZoneInfoSource::Version() const { return std::string(); } } // namespace cctz } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz_extension { @@ -36,8 +41,9 @@ namespace { // defers to the fallback factory. std::unique_ptr DefaultFactory( const std::string& name, - const std::function( - const std::string& name)>& fallback_factory) { + const std::function< + std::unique_ptr( + const std::string& name)>& fallback_factory) { return fallback_factory(name); } @@ -53,8 +59,8 @@ std::unique_ptr DefaultFactory( // Windows linker cannot handle that. Nor does the MinGW compiler know how to // pass "#pragma comment(linker, ...)" to the Windows linker. #if (__has_attribute(weak) || defined(__GNUC__)) && !defined(__MINGW32__) -ZoneInfoSourceFactory zone_info_source_factory - __attribute__((weak)) = DefaultFactory; +ZoneInfoSourceFactory zone_info_source_factory __attribute__((weak)) = + DefaultFactory; #elif defined(_MSC_VER) && !defined(__MINGW32__) && !defined(_LIBCPP_VERSION) extern ZoneInfoSourceFactory zone_info_source_factory; extern ZoneInfoSourceFactory default_factory; @@ -77,4 +83,5 @@ ZoneInfoSourceFactory zone_info_source_factory = DefaultFactory; } // namespace cctz_extension } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl -- cgit v1.2.3 From d5269a8b6dbe7836049417d0ff2c88b8363cc1fc Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 9 Jul 2020 08:13:12 -0700 Subject: Export of internal Abseil changes -- 4833151c207fac9f57a735efe6d5db4c83368415 by Gennadiy Rozental : Import of CCTZ from GitHub. PiperOrigin-RevId: 320398694 -- a1becb36b223230f0a45f204a5fb33b83d2deffe by Gennadiy Rozental : Update CMakeLists.txt Import of https://github.com/abseil/abseil-cpp/pull/737 PiperOrigin-RevId: 320391906 -- b529c45856fe7a3447f1f3259286d57e13b1f292 by Abseil Team : Improves a comment about use of absl::Condition. PiperOrigin-RevId: 320384329 -- c7b1dacda2739c10dc1ccbfb56b07ed7fe2464a4 by Laramie Leavitt : Improve FastUniformBits performance for std::minstd_rand. The rejection algorithm was too pessimistic before, and not in line with the [rand.adapt.ibits]. Specifically, when sampling from an URBG with a non power of 2 range, FastUniformBits constructed a rejection threshold with a power-of-2 range that was too restrictive. For example, minstd_rand has a range of [1, 2147483646], which has a range of 2145386495, or about 30.999 bits. Before FastUniformBits rejected values between 1<<30 and 2145386495, which includes approximately 50% of the generated values. However, since a minimum of 3 calls are required to generate a full 64-bit value from an entropy pool of 30.9 bits, the correct value for rejection sampling is the range value which masks 21 (0x7fe00000) or 22 bits and rejects values greater than that. This reduces the probability of rejecting a sample to about 0.1% NOTE: Abseil random does not guarantee sequence stability over time, and this is expected to change sequences in some cases. PiperOrigin-RevId: 320285836 -- 15800a39557a07dd52e0add66a0ab67aed00590b by Gennadiy Rozental : Internal change. PiperOrigin-RevId: 320220913 -- ef39348360873f6d19669755fe0b5d09a945a501 by Gennadiy Rozental : Internal change PiperOrigin-RevId: 320181729 -- 4f9f6ef8034a24da1832e4c838c72f80fc2ea062 by Gennadiy Rozental : Internal change PiperOrigin-RevId: 320176084 -- 6bfc8008462801657d231585bd5c37fc18bb25b6 by Gennadiy Rozental : Internal change PiperOrigin-RevId: 320176070 -- b35b055ab1f41e6056031ff0641cabab23530027 by Abseil Team : Disabling using header module as well as building one for randen_hwaes_impl PiperOrigin-RevId: 320024299 GitOrigin-RevId: 4833151c207fac9f57a735efe6d5db4c83368415 Change-Id: I9cf102dbf46ed07752a508b7cda3ab3858857d0d --- CMake/AbseilHelpers.cmake | 4 +- CMake/AbseilInstallDirs.cmake | 4 +- absl/container/inlined_vector.h | 2 +- absl/flags/reflection.cc | 12 - absl/random/internal/BUILD.bazel | 9 +- absl/random/internal/fast_uniform_bits.h | 202 ++++++------- absl/random/internal/fast_uniform_bits_test.cc | 318 ++++++++++++--------- absl/synchronization/mutex.h | 5 + absl/time/internal/cctz/src/time_zone_format.cc | 22 +- .../internal/cctz/src/time_zone_format_test.cc | 5 + absl/time/internal/cctz/src/time_zone_libc.cc | 9 +- absl/time/internal/cctz/src/tzfile.h | 8 +- absl/types/CMakeLists.txt | 2 +- 13 files changed, 340 insertions(+), 262 deletions(-) (limited to 'absl/time/internal/cctz/src/time_zone_libc.cc') diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake index 86ff9eba..8b2925c5 100644 --- a/CMake/AbseilHelpers.cmake +++ b/CMake/AbseilHelpers.cmake @@ -23,7 +23,9 @@ include(AbseilInstallDirs) # project that sets # set_property(GLOBAL PROPERTY USE_FOLDERS ON) # For example, Visual Studio supports folders. -set(ABSL_IDE_FOLDER Abseil) +if(NOT DEFINED ABSL_IDE_FOLDER) + set(ABSL_IDE_FOLDER Abseil) +endif() # absl_cc_library() # diff --git a/CMake/AbseilInstallDirs.cmake b/CMake/AbseilInstallDirs.cmake index b67272f8..6fc914b6 100644 --- a/CMake/AbseilInstallDirs.cmake +++ b/CMake/AbseilInstallDirs.cmake @@ -10,11 +10,11 @@ if(absl_VERSION) set(ABSL_SUBDIR "${PROJECT_NAME}_${PROJECT_VERSION}") set(ABSL_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}/${ABSL_SUBDIR}") set(ABSL_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${ABSL_SUBDIR}") - set(ABSL_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/{ABSL_SUBDIR}") + set(ABSL_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/${ABSL_SUBDIR}") set(ABSL_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}/${ABSL_SUBDIR}") else() set(ABSL_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}") set(ABSL_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") set(ABSL_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}") set(ABSL_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}") -endif() \ No newline at end of file +endif() diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index f18dd4c7..90bb96e8 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -64,7 +64,7 @@ ABSL_NAMESPACE_BEGIN // `std::vector` for use cases where the vector's size is sufficiently small // that it can be inlined. If the inlined vector does grow beyond its estimated // capacity, it will trigger an initial allocation on the heap, and will behave -// as a `std:vector`. The API of the `absl::InlinedVector` within this file is +// as a `std::vector`. The API of the `absl::InlinedVector` within this file is // designed to cover the same API footprint as covered by `std::vector`. template > class InlinedVector { diff --git a/absl/flags/reflection.cc b/absl/flags/reflection.cc index 02b7c06a..1b025835 100644 --- a/absl/flags/reflection.cc +++ b/absl/flags/reflection.cc @@ -58,10 +58,6 @@ class FlagRegistry { // Will emit a warning if a 'retired' flag is specified. CommandLineFlag* FindFlagLocked(absl::string_view name); - // Returns the retired flag object for the specified name, or nullptr if not - // found or not retired. Does not emit a warning. - CommandLineFlag* FindRetiredFlagLocked(absl::string_view name); - static FlagRegistry& GlobalRegistry(); // returns a singleton registry private: @@ -88,14 +84,6 @@ CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) { if (i == flags_.end()) { return nullptr; } - return i->second; -} - -CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) { - FlagConstIterator i = flags_.find(name); - if (i == flags_.end() || !i->second->IsRetired()) { - return nullptr; - } return i->second; } diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel index d81477ff..a0eba5e8 100644 --- a/absl/random/internal/BUILD.bazel +++ b/absl/random/internal/BUILD.bazel @@ -59,7 +59,10 @@ cc_library( ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, - deps = ["//absl/base:config"], + deps = [ + "//absl/base:config", + "//absl/meta:type_traits", + ], ) cc_library( @@ -319,10 +322,6 @@ cc_library( "//absl:windows": [], "//conditions:default": ["-Wno-pass-failed"], }), - # copts in RANDEN_HWAES_COPTS can make this target unusable as a module - # leading to a Clang diagnostic. Furthermore, it only has a private header - # anyway and thus there wouldn't be any gain from using it as a module. - features = ["-header_modules"], linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":platform", diff --git a/absl/random/internal/fast_uniform_bits.h b/absl/random/internal/fast_uniform_bits.h index f13c8729..425aaf7d 100644 --- a/absl/random/internal/fast_uniform_bits.h +++ b/absl/random/internal/fast_uniform_bits.h @@ -21,6 +21,7 @@ #include #include "absl/base/config.h" +#include "absl/meta/type_traits.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -38,28 +39,17 @@ constexpr bool IsPowerOfTwoOrZero(UIntType n) { template constexpr typename URBG::result_type RangeSize() { using result_type = typename URBG::result_type; + static_assert((URBG::max)() != (URBG::min)(), "URBG range cannot be 0."); return ((URBG::max)() == (std::numeric_limits::max)() && (URBG::min)() == std::numeric_limits::lowest()) ? result_type{0} - : (URBG::max)() - (URBG::min)() + result_type{1}; -} - -template -constexpr UIntType LargestPowerOfTwoLessThanOrEqualTo(UIntType n) { - return n < 2 ? n : 2 * LargestPowerOfTwoLessThanOrEqualTo(n / 2); -} - -// Given a URBG generating values in the closed interval [Lo, Hi], returns the -// largest power of two less than or equal to `Hi - Lo + 1`. -template -constexpr typename URBG::result_type PowerOfTwoSubRangeSize() { - return LargestPowerOfTwoLessThanOrEqualTo(RangeSize()); + : ((URBG::max)() - (URBG::min)() + result_type{1}); } // Computes the floor of the log. (i.e., std::floor(std::log2(N)); template constexpr UIntType IntegerLog2(UIntType n) { - return (n <= 1) ? 0 : 1 + IntegerLog2(n / 2); + return (n <= 1) ? 0 : 1 + IntegerLog2(n >> 1); } // Returns the number of bits of randomness returned through @@ -68,18 +58,23 @@ template constexpr size_t NumBits() { return RangeSize() == 0 ? std::numeric_limits::digits - : IntegerLog2(PowerOfTwoSubRangeSize()); + : IntegerLog2(RangeSize()); } // Given a shift value `n`, constructs a mask with exactly the low `n` bits set. // If `n == 0`, all bits are set. template -constexpr UIntType MaskFromShift(UIntType n) { +constexpr UIntType MaskFromShift(size_t n) { return ((n % std::numeric_limits::digits) == 0) ? ~UIntType{0} : (UIntType{1} << n) - UIntType{1}; } +// Tags used to dispatch FastUniformBits::generate to the simple or more complex +// entropy extraction algorithm. +struct SimplifiedLoopTag {}; +struct RejectionLoopTag {}; + // FastUniformBits implements a fast path to acquire uniform independent bits // from a type which conforms to the [rand.req.urbg] concept. // Parameterized by: @@ -107,50 +102,16 @@ class FastUniformBits { "Class-template FastUniformBits<> must be parameterized using " "an unsigned type."); - // PowerOfTwoVariate() generates a single random variate, always returning a - // value in the half-open interval `[0, PowerOfTwoSubRangeSize())`. If - // the URBG already generates values in a power-of-two range, the generator - // itself is used. Otherwise, we use rejection sampling on the largest - // possible power-of-two-sized subrange. - struct PowerOfTwoTag {}; - struct RejectionSamplingTag {}; - template - static typename URBG::result_type PowerOfTwoVariate( - URBG& g) { // NOLINT(runtime/references) - using tag = - typename std::conditional()), - PowerOfTwoTag, RejectionSamplingTag>::type; - return PowerOfTwoVariate(g, tag{}); - } - - template - static typename URBG::result_type PowerOfTwoVariate( - URBG& g, // NOLINT(runtime/references) - PowerOfTwoTag) { - return g() - (URBG::min)(); - } - - template - static typename URBG::result_type PowerOfTwoVariate( - URBG& g, // NOLINT(runtime/references) - RejectionSamplingTag) { - // Use rejection sampling to ensure uniformity across the range. - typename URBG::result_type u; - do { - u = g() - (URBG::min)(); - } while (u >= PowerOfTwoSubRangeSize()); - return u; - } - // Generate() generates a random value, dispatched on whether - // the underlying URBG must loop over multiple calls or not. + // the underlying URBG must use rejection sampling to generate a value, + // or whether a simplified loop will suffice. template result_type Generate(URBG& g, // NOLINT(runtime/references) - std::true_type /* avoid_looping */); + SimplifiedLoopTag); template result_type Generate(URBG& g, // NOLINT(runtime/references) - std::false_type /* avoid_looping */); + RejectionLoopTag); }; template @@ -162,31 +123,47 @@ FastUniformBits::operator()(URBG& g) { // NOLINT(runtime/references) // Y = (2 ^ kRange) - 1 static_assert((URBG::max)() > (URBG::min)(), "URBG::max and URBG::min may not be equal."); - using urbg_result_type = typename URBG::result_type; - constexpr urbg_result_type kRangeMask = - RangeSize() == 0 - ? (std::numeric_limits::max)() - : static_cast(PowerOfTwoSubRangeSize() - 1); - return Generate(g, std::integral_constant= (max)())>{}); + + using tag = absl::conditional_t()), + SimplifiedLoopTag, RejectionLoopTag>; + return Generate(g, tag{}); } template template typename FastUniformBits::result_type FastUniformBits::Generate(URBG& g, // NOLINT(runtime/references) - std::true_type /* avoid_looping */) { - // The width of the result_type is less than than the width of the random bits - // provided by URBG. Thus, generate a single value and then simply mask off - // the required bits. + SimplifiedLoopTag) { + // The simplified version of FastUniformBits works only on URBGs that have + // a range that is a power of 2. In this case we simply loop and shift without + // attempting to balance the bits across calls. + static_assert(IsPowerOfTwoOrZero(RangeSize()), + "incorrect Generate tag for URBG instance"); + + static constexpr size_t kResultBits = + std::numeric_limits::digits; + static constexpr size_t kUrbgBits = NumBits(); + static constexpr size_t kIters = + (kResultBits / kUrbgBits) + (kResultBits % kUrbgBits != 0); + static constexpr size_t kShift = (kIters == 1) ? 0 : kUrbgBits; + static constexpr auto kMin = (URBG::min)(); - return PowerOfTwoVariate(g) & (max)(); + result_type r = static_cast(g() - kMin); + for (size_t n = 1; n < kIters; ++n) { + r = (r << kShift) + static_cast(g() - kMin); + } + return r; } template template typename FastUniformBits::result_type FastUniformBits::Generate(URBG& g, // NOLINT(runtime/references) - std::false_type /* avoid_looping */) { + RejectionLoopTag) { + static_assert(!IsPowerOfTwoOrZero(RangeSize()), + "incorrect Generate tag for URBG instance"); + using urbg_result_type = typename URBG::result_type; + // See [rand.adapt.ibits] for more details on the constants calculated below. // // It is preferable to use roughly the same number of bits from each generator @@ -199,21 +176,44 @@ FastUniformBits::Generate(URBG& g, // NOLINT(runtime/references) // `kSmallIters` and `kLargeIters` times respectively such // that // - // `kTotalWidth == kSmallIters * kSmallWidth - // + kLargeIters * kLargeWidth` + // `kResultBits == kSmallIters * kSmallBits + // + kLargeIters * kLargeBits` // - // where `kTotalWidth` is the total number of bits in `result_type`. + // where `kResultBits` is the total number of bits in `result_type`. // - constexpr size_t kTotalWidth = std::numeric_limits::digits; - constexpr size_t kUrbgWidth = NumBits(); - constexpr size_t kTotalIters = - kTotalWidth / kUrbgWidth + (kTotalWidth % kUrbgWidth != 0); - constexpr size_t kSmallWidth = kTotalWidth / kTotalIters; - constexpr size_t kLargeWidth = kSmallWidth + 1; + static constexpr size_t kResultBits = + std::numeric_limits::digits; // w + static constexpr urbg_result_type kUrbgRange = RangeSize(); // R + static constexpr size_t kUrbgBits = NumBits(); // m + + // compute the initial estimate of the bits used. + // [rand.adapt.ibits] 2 (c) + static constexpr size_t kA = // ceil(w/m) + (kResultBits / kUrbgBits) + ((kResultBits % kUrbgBits) != 0); // n' + + static constexpr size_t kABits = kResultBits / kA; // w0' + static constexpr urbg_result_type kARejection = + ((kUrbgRange >> kABits) << kABits); // y0' + + // refine the selection to reduce the rejection frequency. + static constexpr size_t kTotalIters = + ((kUrbgRange - kARejection) <= (kARejection / kA)) ? kA : (kA + 1); // n + + // [rand.adapt.ibits] 2 (b) + static constexpr size_t kSmallIters = + kTotalIters - (kResultBits % kTotalIters); // n0 + static constexpr size_t kSmallBits = kResultBits / kTotalIters; // w0 + static constexpr urbg_result_type kSmallRejection = + ((kUrbgRange >> kSmallBits) << kSmallBits); // y0 + + static constexpr size_t kLargeBits = kSmallBits + 1; // w0+1 + static constexpr urbg_result_type kLargeRejection = + ((kUrbgRange >> kLargeBits) << kLargeBits); // y1 + // - // Because `kLargeWidth == kSmallWidth + 1`, it follows that + // Because `kLargeBits == kSmallBits + 1`, it follows that // - // `kTotalWidth == kTotalIters * kSmallWidth + kLargeIters` + // `kResultBits == kSmallIters * kSmallBits + kLargeIters` // // and therefore // @@ -224,36 +224,40 @@ FastUniformBits::Generate(URBG& g, // NOLINT(runtime/references) // mentioned above, if the URBG width is a divisor of `kTotalWidth`, then // there would be no need for any large iterations (i.e., one loop would // suffice), and indeed, in this case, `kLargeIters` would be zero. - constexpr size_t kLargeIters = kTotalWidth % kSmallWidth; - constexpr size_t kSmallIters = - (kTotalWidth - (kLargeWidth * kLargeIters)) / kSmallWidth; + static_assert(kResultBits == kSmallIters * kSmallBits + + (kTotalIters - kSmallIters) * kLargeBits, + "Error in looping constant calculations."); - static_assert( - kTotalWidth == kSmallIters * kSmallWidth + kLargeIters * kLargeWidth, - "Error in looping constant calculations."); + // The small shift is essentially small bits, but due to the potential + // of generating a smaller result_type from a larger urbg type, the actual + // shift might be 0. + static constexpr size_t kSmallShift = kSmallBits % kResultBits; + static constexpr auto kSmallMask = + MaskFromShift(kSmallShift); + static constexpr size_t kLargeShift = kLargeBits % kResultBits; + static constexpr auto kLargeMask = + MaskFromShift(kLargeShift); - result_type s = 0; + static constexpr auto kMin = (URBG::min)(); - constexpr size_t kSmallShift = kSmallWidth % kTotalWidth; - constexpr result_type kSmallMask = MaskFromShift(result_type{kSmallShift}); + result_type s = 0; for (size_t n = 0; n < kSmallIters; ++n) { - s = (s << kSmallShift) + - (static_cast(PowerOfTwoVariate(g)) & kSmallMask); - } + urbg_result_type v; + do { + v = g() - kMin; + } while (v >= kSmallRejection); - constexpr size_t kLargeShift = kLargeWidth % kTotalWidth; - constexpr result_type kLargeMask = MaskFromShift(result_type{kLargeShift}); - for (size_t n = 0; n < kLargeIters; ++n) { - s = (s << kLargeShift) + - (static_cast(PowerOfTwoVariate(g)) & kLargeMask); + s = (s << kSmallShift) + static_cast(v & kSmallMask); } - static_assert( - kLargeShift == kSmallShift + 1 || - (kLargeShift == 0 && - kSmallShift == std::numeric_limits::digits - 1), - "Error in looping constant calculations"); + for (size_t n = kSmallIters; n < kTotalIters; ++n) { + urbg_result_type v; + do { + v = g() - kMin; + } while (v >= kLargeRejection); + s = (s << kLargeShift) + static_cast(v & kLargeMask); + } return s; } diff --git a/absl/random/internal/fast_uniform_bits_test.cc b/absl/random/internal/fast_uniform_bits_test.cc index f5b837e5..cee702df 100644 --- a/absl/random/internal/fast_uniform_bits_test.cc +++ b/absl/random/internal/fast_uniform_bits_test.cc @@ -34,8 +34,8 @@ TYPED_TEST(FastUniformBitsTypedTest, BasicTest) { using Limits = std::numeric_limits; using FastBits = FastUniformBits; - EXPECT_EQ(0, FastBits::min()); - EXPECT_EQ(Limits::max(), FastBits::max()); + EXPECT_EQ(0, (FastBits::min)()); + EXPECT_EQ((Limits::max)(), (FastBits::max)()); constexpr int kIters = 10000; std::random_device rd; @@ -43,8 +43,8 @@ TYPED_TEST(FastUniformBitsTypedTest, BasicTest) { FastBits fast; for (int i = 0; i < kIters; i++) { const auto v = fast(gen); - EXPECT_LE(v, FastBits::max()); - EXPECT_GE(v, FastBits::min()); + EXPECT_LE(v, (FastBits::max)()); + EXPECT_GE(v, (FastBits::min)()); } } @@ -52,21 +52,26 @@ template struct FakeUrbg { using result_type = UIntType; + FakeUrbg() = default; + explicit FakeUrbg(bool r) : reject(r) {} + static constexpr result_type(max)() { return Hi; } static constexpr result_type(min)() { return Lo; } - result_type operator()() { return Val; } -}; + result_type operator()() { + // when reject is set, return Hi half the time. + return ((++calls % 2) == 1 && reject) ? Hi : Val; + } -using UrngOddbits = FakeUrbg; -using Urng4bits = FakeUrbg; -using Urng31bits = FakeUrbg; -using Urng32bits = FakeUrbg; + bool reject = false; + size_t calls = 0; +}; TEST(FastUniformBitsTest, IsPowerOfTwoOrZero) { EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{0})); EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{1})); EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{2})); EXPECT_FALSE(IsPowerOfTwoOrZero(uint8_t{3})); + EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{4})); EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{16})); EXPECT_FALSE(IsPowerOfTwoOrZero(uint8_t{17})); EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits::max)())); @@ -75,6 +80,7 @@ TEST(FastUniformBitsTest, IsPowerOfTwoOrZero) { EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{1})); EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{2})); EXPECT_FALSE(IsPowerOfTwoOrZero(uint16_t{3})); + EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{4})); EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{16})); EXPECT_FALSE(IsPowerOfTwoOrZero(uint16_t{17})); EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits::max)())); @@ -91,181 +97,237 @@ TEST(FastUniformBitsTest, IsPowerOfTwoOrZero) { EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{1})); EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{2})); EXPECT_FALSE(IsPowerOfTwoOrZero(uint64_t{3})); + EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{4})); EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{64})); EXPECT_FALSE(IsPowerOfTwoOrZero(uint64_t{17})); EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits::max)())); } TEST(FastUniformBitsTest, IntegerLog2) { - EXPECT_EQ(IntegerLog2(uint16_t{0}), 0); - EXPECT_EQ(IntegerLog2(uint16_t{1}), 0); - EXPECT_EQ(IntegerLog2(uint16_t{2}), 1); - EXPECT_EQ(IntegerLog2(uint16_t{3}), 1); - EXPECT_EQ(IntegerLog2(uint16_t{4}), 2); - EXPECT_EQ(IntegerLog2(uint16_t{5}), 2); - EXPECT_EQ(IntegerLog2(std::numeric_limits::max()), 63); + EXPECT_EQ(0, IntegerLog2(uint16_t{0})); + EXPECT_EQ(0, IntegerLog2(uint16_t{1})); + EXPECT_EQ(1, IntegerLog2(uint16_t{2})); + EXPECT_EQ(1, IntegerLog2(uint16_t{3})); + EXPECT_EQ(2, IntegerLog2(uint16_t{4})); + EXPECT_EQ(2, IntegerLog2(uint16_t{5})); + EXPECT_EQ(2, IntegerLog2(uint16_t{7})); + EXPECT_EQ(3, IntegerLog2(uint16_t{8})); + EXPECT_EQ(63, IntegerLog2((std::numeric_limits::max)())); } TEST(FastUniformBitsTest, RangeSize) { - EXPECT_EQ((RangeSize>()), 4); - EXPECT_EQ((RangeSize>()), 1); - EXPECT_EQ((RangeSize>()), 4); - EXPECT_EQ((RangeSize>()), 5); - EXPECT_EQ((RangeSize>()), 9); + EXPECT_EQ(2, (RangeSize>())); + EXPECT_EQ(3, (RangeSize>())); + EXPECT_EQ(4, (RangeSize>())); + // EXPECT_EQ(0, (RangeSize>())); + EXPECT_EQ(4, (RangeSize>())); + EXPECT_EQ(5, (RangeSize>())); + EXPECT_EQ(9, (RangeSize>())); EXPECT_EQ( - (RangeSize::max()>>()), - 0); - - EXPECT_EQ((RangeSize>()), 4); - EXPECT_EQ((RangeSize>()), 1); - EXPECT_EQ((RangeSize>()), 4); - EXPECT_EQ((RangeSize>()), 5); - EXPECT_EQ((RangeSize>()), 18); - EXPECT_EQ((RangeSize< - FakeUrbg::max()>>()), - 0); - - EXPECT_EQ((RangeSize>()), 4); - EXPECT_EQ((RangeSize>()), 1); - EXPECT_EQ((RangeSize>()), 4); - EXPECT_EQ((RangeSize>()), 5); - EXPECT_EQ((RangeSize>()), 18); - EXPECT_EQ((RangeSize>()), 0); - EXPECT_EQ((RangeSize>()), 0xffffffff); - EXPECT_EQ((RangeSize>()), 0xfffffffe); - EXPECT_EQ((RangeSize>()), 0xfffffffd); - EXPECT_EQ((RangeSize< - FakeUrbg::max()>>()), - 0); - - EXPECT_EQ((RangeSize>()), 4); - EXPECT_EQ((RangeSize>()), 1); - EXPECT_EQ((RangeSize>()), 4); - EXPECT_EQ((RangeSize>()), 5); - EXPECT_EQ((RangeSize>()), 18); - EXPECT_EQ((RangeSize>()), 0x100000000ull); - EXPECT_EQ((RangeSize>()), 0xffffffffull); - EXPECT_EQ((RangeSize>()), 0xfffffffeull); - EXPECT_EQ((RangeSize>()), 0xfffffffdull); - EXPECT_EQ((RangeSize>()), 0ull); - EXPECT_EQ((RangeSize>()), - 0xffffffffffffffffull); - EXPECT_EQ((RangeSize>()), - 0xfffffffffffffffeull); - EXPECT_EQ((RangeSize>()), - 0xfffffffffffffffdull); - EXPECT_EQ((RangeSize< - FakeUrbg::max()>>()), - 0); -} + 0, (RangeSize< + FakeUrbg::max)()>>())); -TEST(FastUniformBitsTest, PowerOfTwoSubRangeSize) { - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 4); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 1); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 4); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 4); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 8); - EXPECT_EQ((PowerOfTwoSubRangeSize< - FakeUrbg::max()>>()), - 0); - - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 4); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 1); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 4); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 4); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 16); - EXPECT_EQ((PowerOfTwoSubRangeSize< - FakeUrbg::max()>>()), - 0); - - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 4); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 1); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 4); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 4); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 16); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 0); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), - 0x80000000); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), - 0x80000000); - EXPECT_EQ((PowerOfTwoSubRangeSize< - FakeUrbg::max()>>()), - 0); - - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 4); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 1); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 4); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 4); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), 16); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), - 0x100000000ull); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), - 0x80000000ull); - EXPECT_EQ((PowerOfTwoSubRangeSize>()), - 0x80000000ull); + EXPECT_EQ(4, (RangeSize>())); + EXPECT_EQ(4, (RangeSize>())); + EXPECT_EQ(5, (RangeSize>())); + EXPECT_EQ(18, (RangeSize>())); EXPECT_EQ( - (PowerOfTwoSubRangeSize>()), - 0); + 0, (RangeSize< + FakeUrbg::max)()>>())); + + EXPECT_EQ(4, (RangeSize>())); + EXPECT_EQ(4, (RangeSize>())); + EXPECT_EQ(5, (RangeSize>())); + EXPECT_EQ(18, (RangeSize>())); + EXPECT_EQ(0, (RangeSize>())); + EXPECT_EQ(0xffffffff, (RangeSize>())); + EXPECT_EQ(0xfffffffe, (RangeSize>())); + EXPECT_EQ(0xfffffffd, (RangeSize>())); EXPECT_EQ( - (PowerOfTwoSubRangeSize>()), - 0x8000000000000000ull); + 0, (RangeSize< + FakeUrbg::max)()>>())); + + EXPECT_EQ(4, (RangeSize>())); + EXPECT_EQ(4, (RangeSize>())); + EXPECT_EQ(5, (RangeSize>())); + EXPECT_EQ(18, (RangeSize>())); + EXPECT_EQ(0x100000000, (RangeSize>())); + EXPECT_EQ(0xffffffff, (RangeSize>())); + EXPECT_EQ(0xfffffffe, (RangeSize>())); + EXPECT_EQ(0xfffffffd, (RangeSize>())); + EXPECT_EQ(0, (RangeSize>())); + EXPECT_EQ(0xffffffffffffffff, + (RangeSize>())); + EXPECT_EQ(0xfffffffffffffffe, + (RangeSize>())); + EXPECT_EQ(0xfffffffffffffffd, + (RangeSize>())); EXPECT_EQ( - (PowerOfTwoSubRangeSize>()), - 0x8000000000000000ull); - EXPECT_EQ((PowerOfTwoSubRangeSize< - FakeUrbg::max()>>()), - 0); + 0, (RangeSize< + FakeUrbg::max)()>>())); } -TEST(FastUniformBitsTest, Urng4_VariousOutputs) { +// The constants need to be choosen so that an infinite rejection loop doesn't +// happen... +using Urng1_5bit = FakeUrbg; // ~1.5 bits (range 3) +using Urng4bits = FakeUrbg; +using Urng22bits = FakeUrbg; +using Urng31bits = FakeUrbg; // ~31.9 bits +using Urng32bits = FakeUrbg; +using Urng33bits = + FakeUrbg; // ~32.9 bits +using Urng63bits = FakeUrbg; // ~63.9 bits +using Urng64bits = + FakeUrbg; + +TEST(FastUniformBitsTest, OutputsUpTo32Bits) { // Tests that how values are composed; the single-bit deltas should be spread // across each invocation. + Urng1_5bit urng1_5; Urng4bits urng4; + Urng22bits urng22; Urng31bits urng31; Urng32bits urng32; + Urng33bits urng33; + Urng63bits urng63; + Urng64bits urng64; // 8-bit types { FastUniformBits fast8; + EXPECT_EQ(0x0, fast8(urng1_5)); EXPECT_EQ(0x11, fast8(urng4)); + EXPECT_EQ(0x20, fast8(urng22)); EXPECT_EQ(0x2, fast8(urng31)); EXPECT_EQ(0x1, fast8(urng32)); + EXPECT_EQ(0x32, fast8(urng33)); + EXPECT_EQ(0x77, fast8(urng63)); + EXPECT_EQ(0xa9, fast8(urng64)); } // 16-bit types { FastUniformBits fast16; + EXPECT_EQ(0x0, fast16(urng1_5)); EXPECT_EQ(0x1111, fast16(urng4)); - EXPECT_EQ(0xf02, fast16(urng31)); - EXPECT_EQ(0xf01, fast16(urng32)); + EXPECT_EQ(0x1020, fast16(urng22)); + EXPECT_EQ(0x0f02, fast16(urng31)); + EXPECT_EQ(0x0f01, fast16(urng32)); + EXPECT_EQ(0x1032, fast16(urng33)); + EXPECT_EQ(0x5677, fast16(urng63)); + EXPECT_EQ(0xcba9, fast16(urng64)); } // 32-bit types { FastUniformBits fast32; + EXPECT_EQ(0x0, fast32(urng1_5)); EXPECT_EQ(0x11111111, fast32(urng4)); + EXPECT_EQ(0x08301020, fast32(urng22)); EXPECT_EQ(0x0f020f02, fast32(urng31)); EXPECT_EQ(0x74010f01, fast32(urng32)); + EXPECT_EQ(0x13301032, fast32(urng33)); + EXPECT_EQ(0x12345677, fast32(urng63)); + EXPECT_EQ(0x0fedcba9, fast32(urng64)); } +} + +TEST(FastUniformBitsTest, Outputs64Bits) { + // Tests that how values are composed; the single-bit deltas should be spread + // across each invocation. + FastUniformBits fast64; - // 64-bit types { - FastUniformBits fast64; + FakeUrbg urng0; + FakeUrbg urng1; + Urng4bits urng4; + Urng22bits urng22; + Urng31bits urng31; + Urng32bits urng32; + Urng33bits urng33; + Urng63bits urng63; + Urng64bits urng64; + + // somewhat degenerate cases only create a single bit. + EXPECT_EQ(0x0, fast64(urng0)); + EXPECT_EQ(64, urng0.calls); + EXPECT_EQ(0xffffffffffffffff, fast64(urng1)); + EXPECT_EQ(64, urng1.calls); + + // less degenerate cases. EXPECT_EQ(0x1111111111111111, fast64(urng4)); + EXPECT_EQ(16, urng4.calls); + EXPECT_EQ(0x01020c0408301020, fast64(urng22)); + EXPECT_EQ(3, urng22.calls); EXPECT_EQ(0x387811c3c0870f02, fast64(urng31)); + EXPECT_EQ(3, urng31.calls); EXPECT_EQ(0x74010f0174010f01, fast64(urng32)); + EXPECT_EQ(2, urng32.calls); + EXPECT_EQ(0x808194040cb01032, fast64(urng33)); + EXPECT_EQ(3, urng33.calls); + EXPECT_EQ(0x1234567712345677, fast64(urng63)); + EXPECT_EQ(2, urng63.calls); + EXPECT_EQ(0x123456780fedcba9, fast64(urng64)); + EXPECT_EQ(1, urng64.calls); + } + + // The 1.5 bit case is somewhat interesting in that the algorithm refinement + // causes one extra small sample. Comments here reference the names used in + // [rand.adapt.ibits] that correspond to this case. + { + Urng1_5bit urng1_5; + + // w = 64 + // R = 3 + // m = 1 + // n' = 64 + // w0' = 1 + // y0' = 2 + // n = (1 <= 0) > 64 : 65 = 65 + // n0 = 65 - (64%65) = 1 + // n1 = 64 + // w0 = 0 + // y0 = 3 + // w1 = 1 + // y1 = 2 + EXPECT_EQ(0x0, fast64(urng1_5)); + EXPECT_EQ(65, urng1_5.calls); + } + + // Validate rejections for non-power-of-2 cases. + { + Urng1_5bit urng1_5(true); + Urng31bits urng31(true); + Urng33bits urng33(true); + Urng63bits urng63(true); + + // For 1.5 bits, there would be 1+2*64, except the first + // value was accepted and shifted off the end. + EXPECT_EQ(0, fast64(urng1_5)); + EXPECT_EQ(128, urng1_5.calls); + EXPECT_EQ(0x387811c3c0870f02, fast64(urng31)); + EXPECT_EQ(6, urng31.calls); + EXPECT_EQ(0x808194040cb01032, fast64(urng33)); + EXPECT_EQ(6, urng33.calls); + EXPECT_EQ(0x1234567712345677, fast64(urng63)); + EXPECT_EQ(4, urng63.calls); } } TEST(FastUniformBitsTest, URBG32bitRegression) { // Validate with deterministic 32-bit std::minstd_rand // to ensure that operator() performs as expected. + + EXPECT_EQ(2147483646, RangeSize()); + EXPECT_EQ(30, IntegerLog2(RangeSize())); + std::minstd_rand gen(1); FastUniformBits fast64; - EXPECT_EQ(0x05e47095f847c122ull, fast64(gen)); - EXPECT_EQ(0x8f82c1ba30b64d22ull, fast64(gen)); - EXPECT_EQ(0x3b971a3558155039ull, fast64(gen)); + EXPECT_EQ(0x05e47095f8791f45, fast64(gen)); + EXPECT_EQ(0x028be17e3c07c122, fast64(gen)); + EXPECT_EQ(0x55d2847c1626e8c2, fast64(gen)); } } // namespace diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h index 876698ca..52401fe3 100644 --- a/absl/synchronization/mutex.h +++ b/absl/synchronization/mutex.h @@ -685,6 +685,11 @@ class Condition { // return processed_ >= current; // }; // mu_.Await(Condition(&reached)); + // + // NOTE: never use "mu_.AssertHeld()" instead of "mu_.AssertReadHeld()" in the + // lambda as it may be called when the mutex is being unlocked from a scope + // holding only a reader lock, which will make the assertion not fulfilled and + // crash the binary. // See class comment for performance advice. In particular, if there // might be more than one waiter for the same condition, make sure diff --git a/absl/time/internal/cctz/src/time_zone_format.cc b/absl/time/internal/cctz/src/time_zone_format.cc index 2e02233c..d8cb0474 100644 --- a/absl/time/internal/cctz/src/time_zone_format.cc +++ b/absl/time/internal/cctz/src/time_zone_format.cc @@ -654,14 +654,23 @@ const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) { } // Sets year, tm_mon and tm_mday given the year, week_num, and tm_wday, -// and the day on which weeks are defined to start. -void FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) { +// and the day on which weeks are defined to start. Returns false if year +// would need to move outside its bounds. +bool FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) { const civil_year y(*year % 400); civil_day cd = prev_weekday(y, week_start); // week 0 cd = next_weekday(cd - 1, FromTmWday(tm->tm_wday)) + (week_num * 7); - *year += cd.year() - y.year(); + if (const year_t shift = cd.year() - y.year()) { + if (shift > 0) { + if (*year > std::numeric_limits::max() - shift) return false; + } else { + if (*year < std::numeric_limits::min() - shift) return false; + } + *year += shift; + } tm->tm_mon = cd.month() - 1; tm->tm_mday = cd.day(); + return true; } } // namespace @@ -965,7 +974,12 @@ bool parse(const std::string& format, const std::string& input, } // Compute year, tm.tm_mon and tm.tm_mday if we parsed a week number. - if (week_num != -1) FromWeek(week_num, week_start, &year, &tm); + if (week_num != -1) { + if (!FromWeek(week_num, week_start, &year, &tm)) { + if (err != nullptr) *err = "Out-of-range field"; + return false; + } + } const int month = tm.tm_mon + 1; civil_second cs(year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); diff --git a/absl/time/internal/cctz/src/time_zone_format_test.cc b/absl/time/internal/cctz/src/time_zone_format_test.cc index e625a839..a11f93e2 100644 --- a/absl/time/internal/cctz/src/time_zone_format_test.cc +++ b/absl/time/internal/cctz/src/time_zone_format_test.cc @@ -1481,6 +1481,11 @@ TEST(Parse, WeekYearShift) { EXPECT_EQ(exp, tp); EXPECT_TRUE(parse("%Y-%W-%w", "2020-52-5", utc, &tp)); EXPECT_EQ(exp, tp); + + // Slipping into the previous/following calendar years should fail when + // we're already at the extremes. + EXPECT_FALSE(parse("%Y-%U-%u", "-9223372036854775808-0-7", utc, &tp)); + EXPECT_FALSE(parse("%Y-%U-%u", "9223372036854775807-53-7", utc, &tp)); } TEST(Parse, MaxRange) { diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc index 47cf84c6..3fcc75bd 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/absl/time/internal/cctz/src/time_zone_libc.cc @@ -223,11 +223,10 @@ time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const { civil_second() + ToUnixSeconds(time_point::min()); static const civil_second max_tp_cs = civil_second() + ToUnixSeconds(time_point::max()); - const time_point tp = - (cs < min_tp_cs) - ? time_point::min() - : (cs > max_tp_cs) ? time_point::max() - : FromUnixSeconds(cs - civil_second()); + const time_point tp = (cs < min_tp_cs) ? time_point::min() + : (cs > max_tp_cs) + ? time_point::max() + : FromUnixSeconds(cs - civil_second()); return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; } diff --git a/absl/time/internal/cctz/src/tzfile.h b/absl/time/internal/cctz/src/tzfile.h index 269fa36c..659f84cf 100644 --- a/absl/time/internal/cctz/src/tzfile.h +++ b/absl/time/internal/cctz/src/tzfile.h @@ -108,15 +108,15 @@ struct tzhead { #ifndef TZ_MAX_TYPES /* This must be at least 17 for Europe/Samara and Europe/Vilnius. */ #define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ -#endif /* !defined TZ_MAX_TYPES */ +#endif /* !defined TZ_MAX_TYPES */ #ifndef TZ_MAX_CHARS #define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ - /* (limited by what unsigned chars can hold) */ -#endif /* !defined TZ_MAX_CHARS */ +/* (limited by what unsigned chars can hold) */ +#endif /* !defined TZ_MAX_CHARS */ #ifndef TZ_MAX_LEAPS #define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ -#endif /* !defined TZ_MAX_LEAPS */ +#endif /* !defined TZ_MAX_LEAPS */ #endif /* !defined TZFILE_H */ diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt index 0dc0d2c7..3f99ad8a 100644 --- a/absl/types/CMakeLists.txt +++ b/absl/types/CMakeLists.txt @@ -259,7 +259,7 @@ absl_cc_library( absl::strings absl::utility gmock_main - PUBLIC + TESTONLY ) absl_cc_test( -- cgit v1.2.3 From f72cc3516a2b79575f852d125b5324f29e63d91e Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 6 Aug 2020 18:17:40 -0700 Subject: Export of internal Abseil changes -- 880e4ea366ff27f2b5b0c2f693f05424a1e47fbf by Derek Mauro : Import of CCTZ from GitHub. PiperOrigin-RevId: 325351285 GitOrigin-RevId: 880e4ea366ff27f2b5b0c2f693f05424a1e47fbf Change-Id: I9003e713eff7315f4d38ca5c88efe6151bc26ac4 --- absl/time/internal/cctz/src/time_zone_libc.cc | 6 ++++-- absl/time/internal/cctz/src/time_zone_lookup_test.cc | 10 +++++----- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'absl/time/internal/cctz/src/time_zone_libc.cc') diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc index 3fcc75bd..a14982a9 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/absl/time/internal/cctz/src/time_zone_libc.cc @@ -153,7 +153,8 @@ std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) { std::tm tm; while (lo + 1 != hi) { const std::time_t mid = lo + (hi - lo) / 2; - if (std::tm* tmp = local_time(&mid, &tm)) { + std::tm* tmp = local_time(&mid, &tm); + if (tmp != nullptr) { if (tm_gmtoff(*tmp) == offset) { hi = mid; } else { @@ -163,7 +164,8 @@ std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) { // If std::tm cannot hold some result we resort to a linear search, // ignoring all failed conversions. Slow, but never really happens. while (++lo != hi) { - if (std::tm* tmp = local_time(&lo, &tm)) { + tmp = local_time(&lo, &tm); + if (tmp != nullptr) { if (tm_gmtoff(*tmp) == offset) break; } } diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc index 8f7ab154..53641bfe 100644 --- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc +++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc @@ -1004,13 +1004,13 @@ TEST(MakeTime, SysSecondsLimits) { #if defined(_WIN32) || defined(_WIN64) // localtime_s() and gmtime_s() don't believe in years outside [1970:3000]. #else - const time_zone utc = LoadZone("libc:UTC"); + const time_zone cut = LoadZone("libc:UTC"); const year_t max_tm_year = year_t{std::numeric_limits::max()} + 1900; - tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), utc); - EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, utc)); + tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), cut); + EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, cut)); const year_t min_tm_year = year_t{std::numeric_limits::min()} + 1900; - tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), utc); - EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, utc)); + tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), cut); + EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, cut)); #endif } } -- cgit v1.2.3 From 0bbebc85cd8dbd382b10698b3cefe9a01e88e76f Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 13 Nov 2020 08:47:54 -0800 Subject: Export of internal Abseil changes -- a1b28d83d60f96e14487f093566f12ba07f92732 by Mark Barolak : Import of CCTZ from GitHub. PiperOrigin-RevId: 342270204 -- 3d99c08b7e2ee23050f64965f09881b54821cdd0 by Mark Barolak : Fix a Windows DLL breakage that is causing all sub-libraries to be compiled as DLL dependencies instead of stand-alone DLLs. See https://github.com/abseil/abseil-cpp/issues/796 for the bug report. Import of https://github.com/abseil/abseil-cpp/pull/797 PiperOrigin-RevId: 341892182 GitOrigin-RevId: a1b28d83d60f96e14487f093566f12ba07f92732 Change-Id: I7d70f07492bfa9b657ec280a4f005c1ee893594c --- CMake/AbseilHelpers.cmake | 6 +++++- absl/time/internal/cctz/src/time_zone_libc.cc | 8 +++++++- absl/time/internal/cctz/src/tzfile.h | 8 ++++---- 3 files changed, 16 insertions(+), 6 deletions(-) (limited to 'absl/time/internal/cctz/src/time_zone_libc.cc') diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake index c8060709..e85deba8 100644 --- a/CMake/AbseilHelpers.cmake +++ b/CMake/AbseilHelpers.cmake @@ -122,7 +122,11 @@ function(absl_cc_library) # 4. "static" -- This target does not depend on the DLL and should be built # statically. if (${ABSL_BUILD_DLL}) - absl_internal_dll_contains(TARGET ${_NAME} OUTPUT _in_dll) + if(ABSL_ENABLE_INSTALL) + absl_internal_dll_contains(TARGET ${_NAME} OUTPUT _in_dll) + else() + absl_internal_dll_contains(TARGET ${ABSL_CC_LIB_NAME} OUTPUT _in_dll) + endif() if (${_in_dll}) # This target should be replaced by the DLL set(_build_type "dll") diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc index a14982a9..887dd097 100644 --- a/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/absl/time/internal/cctz/src/time_zone_libc.cc @@ -27,6 +27,12 @@ #include "absl/time/internal/cctz/include/cctz/civil_time.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h" +#if defined(_AIX) +extern "C" { +extern long altzone; +} +#endif + namespace absl { ABSL_NAMESPACE_BEGIN namespace time_internal { @@ -44,7 +50,7 @@ auto tm_zone(const std::tm& tm) -> decltype(_tzname[0]) { const bool is_dst = tm.tm_isdst > 0; return _tzname[is_dst]; } -#elif defined(__sun) +#elif defined(__sun) || defined(_AIX) // Uses the globals: 'timezone', 'altzone' and 'tzname'. auto tm_gmtoff(const std::tm& tm) -> decltype(timezone) { const bool is_dst = tm.tm_isdst > 0; diff --git a/absl/time/internal/cctz/src/tzfile.h b/absl/time/internal/cctz/src/tzfile.h index 659f84cf..269fa36c 100644 --- a/absl/time/internal/cctz/src/tzfile.h +++ b/absl/time/internal/cctz/src/tzfile.h @@ -108,15 +108,15 @@ struct tzhead { #ifndef TZ_MAX_TYPES /* This must be at least 17 for Europe/Samara and Europe/Vilnius. */ #define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ -#endif /* !defined TZ_MAX_TYPES */ +#endif /* !defined TZ_MAX_TYPES */ #ifndef TZ_MAX_CHARS #define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ -/* (limited by what unsigned chars can hold) */ -#endif /* !defined TZ_MAX_CHARS */ + /* (limited by what unsigned chars can hold) */ +#endif /* !defined TZ_MAX_CHARS */ #ifndef TZ_MAX_LEAPS #define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ -#endif /* !defined TZ_MAX_LEAPS */ +#endif /* !defined TZ_MAX_LEAPS */ #endif /* !defined TZFILE_H */ -- cgit v1.2.3