Export of internal Abseil changes

--
20b3acaff75d05315f272747956b01405adccafb by Greg Falcon <gfalcon@google.com>:

Re-import of CCTZ from GitHub, with new ABSL_NAMESPACE_ transform applied.

PiperOrigin-RevId: 285564474

--
4d9e3fcabcea33c8b0b69f094ad2eddc0fa19557 by Derek Mauro <dmauro@google.com>:

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 <dmauro@google.com>:

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 <asoffer@google.com>:

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
This commit is contained in:
Abseil Team 2019-12-14 08:24:07 -08:00 committed by CJ Johnson
parent 12bc53e031
commit bf86cfe165
31 changed files with 1972 additions and 1421 deletions

View file

@ -26,6 +26,32 @@ package(default_visibility = ["//visibility:public"])
licenses(["notice"]) # Apache 2.0 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( cc_library(
name = "function_ref", name = "function_ref",
srcs = ["internal/function_ref.h"], srcs = ["internal/function_ref.h"],

View file

@ -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<Math> inside the functor.
// assert(absl::bind_front(&Math::Double,
// std::unique_ptr<Math>(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<void()>& done) {
// // Calls Executor::Schedule(std::function<void()>).
// 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<void()>& 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<void()>* 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<void()>* 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<std::string> 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 <class F, class... BoundArgs>
constexpr functional_internal::bind_front_t<F, BoundArgs...> bind_front(
F&& func, BoundArgs&&... args) {
return functional_internal::bind_front_t<F, BoundArgs...>(
absl::in_place, absl::forward<F>(func),
absl::forward<BoundArgs>(args)...);
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_FUNCTIONAL_BIND_FRONT_H_

View file

@ -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 <stddef.h>
#include <functional>
#include <memory>
#include <string>
#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<int&>(i)));
EXPECT_EQ("const&", absl::bind_front(f)(static_cast<const int&>(i)));
EXPECT_EQ("&&", absl::bind_front(f)(static_cast<int&&>(i)));
EXPECT_EQ("const&&", absl::bind_front(f)(static_cast<const int&&>(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<NonCopyable> 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<int> p) {
return *p;
}
std::unique_ptr<int> Factory(int n) { return absl::make_unique<int>(n); }
TEST(BindTest, NonCopyableArg) {
EXPECT_EQ(42, absl::bind_front(Sink)(absl::make_unique<int>(42)));
EXPECT_EQ(42, absl::bind_front(Sink, absl::make_unique<int>(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<FalseCopyable<unique_ptr<T>> is true but an attempt to
// instantiate the copy constructor leads to a compile error. This is similar
// to how standard containers behave.
template <class T>
struct FalseCopyable {
FalseCopyable() {}
FalseCopyable(const FalseCopyable& other) : m(other.m) {}
FalseCopyable(FalseCopyable&& other) : m(std::move(other.m)) {}
T m;
};
int GetMember(FalseCopyable<std::unique_ptr<int>> x) { return *x.m; }
TEST(BindTest, WrappedMoveOnly) {
FalseCopyable<std::unique_ptr<int>> x;
x.m = absl::make_unique<int>(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

View file

@ -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 <cstddef>
#include <type_traits>
#include <utility>
#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 <class R, class Tuple, size_t... Idx, class... Args>
R Apply(Tuple&& bound, absl::index_sequence<Idx...>, Args&&... free) {
return base_internal::Invoke(
absl::forward<Tuple>(bound).template get<Idx>()...,
absl::forward<Args>(free)...);
}
template <class F, class... BoundArgs>
class FrontBinder {
using BoundArgsT = absl::container_internal::CompressedTuple<F, BoundArgs...>;
using Idx = absl::make_index_sequence<sizeof...(BoundArgs) + 1>;
BoundArgsT bound_args_;
public:
template <class... Ts>
constexpr explicit FrontBinder(absl::in_place_t, Ts&&... ts)
: bound_args_(absl::forward<Ts>(ts)...) {}
template <class... FreeArgs,
class R = base_internal::InvokeT<F&, BoundArgs&..., FreeArgs&&...>>
R operator()(FreeArgs&&... free_args) & {
return functional_internal::Apply<R>(bound_args_, Idx(),
absl::forward<FreeArgs>(free_args)...);
}
template <class... FreeArgs,
class R = base_internal::InvokeT<const F&, const BoundArgs&...,
FreeArgs&&...>>
R operator()(FreeArgs&&... free_args) const& {
return functional_internal::Apply<R>(bound_args_, Idx(),
absl::forward<FreeArgs>(free_args)...);
}
template <class... FreeArgs, class R = base_internal::InvokeT<
F&&, BoundArgs&&..., FreeArgs&&...>>
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<R>(absl::move(bound_args_), Idx(),
absl::forward<FreeArgs>(free_args)...);
}
template <class... FreeArgs,
class R = base_internal::InvokeT<const F&&, const BoundArgs&&...,
FreeArgs&&...>>
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<R>(absl::move(bound_args_), Idx(),
absl::forward<FreeArgs>(free_args)...);
}
};
template <class F, class... BoundArgs>
using bind_front_t = FrontBinder<decay_t<F>, absl::decay_t<BoundArgs>...>;
} // namespace functional_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_

View file

@ -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) { TYPED_TEST(UniformRealDistributionTest, ViolatesPreconditionsDeathTest) {
#if GTEST_HAS_DEATH_TEST #if GTEST_HAS_DEATH_TEST
// Hi < Lo // Hi < Lo
@ -195,6 +199,9 @@ TYPED_TEST(UniformRealDistributionTest, ViolatesPreconditionsDeathTest) {
} }
#endif // NDEBUG #endif // NDEBUG
} }
#ifdef _MSC_VER
#pragma warning(pop) // warning(disable:4756)
#endif
TYPED_TEST(UniformRealDistributionTest, TestMoments) { TYPED_TEST(UniformRealDistributionTest, TestMoments) {
constexpr int kSize = 1000000; constexpr int kSize = 1000000;

View file

@ -42,6 +42,7 @@ cc_library(
], ],
textual_hdrs = ["include/cctz/civil_time_detail.h"], textual_hdrs = ["include/cctz/civil_time_detail.h"],
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = ["//absl/base:config"],
) )
cc_library( cc_library(
@ -78,7 +79,10 @@ cc_library(
"//conditions:default": [], "//conditions:default": [],
}), }),
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [":civil_time"], deps = [
":civil_time",
"//absl/base:config",
],
) )
### tests ### tests
@ -89,6 +93,7 @@ cc_test(
srcs = ["src/civil_time_test.cc"], srcs = ["src/civil_time_test.cc"],
deps = [ deps = [
":civil_time", ":civil_time",
"//absl/base:config",
"@com_google_googletest//:gtest_main", "@com_google_googletest//:gtest_main",
], ],
) )
@ -106,6 +111,7 @@ cc_test(
deps = [ deps = [
":civil_time", ":civil_time",
":time_zone", ":time_zone",
"//absl/base:config",
"@com_google_googletest//:gtest_main", "@com_google_googletest//:gtest_main",
], ],
) )
@ -124,6 +130,7 @@ cc_test(
deps = [ deps = [
":civil_time", ":civil_time",
":time_zone", ":time_zone",
"//absl/base:config",
"@com_google_googletest//:gtest_main", "@com_google_googletest//:gtest_main",
], ],
) )
@ -144,6 +151,7 @@ cc_test(
deps = [ deps = [
":civil_time", ":civil_time",
":time_zone", ":time_zone",
"//absl/base:config",
"@com_github_google_benchmark//:benchmark_main", "@com_github_google_benchmark//:benchmark_main",
], ],
) )

View file

@ -15,9 +15,11 @@
#ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ #ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_
#define 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" #include "absl/time/internal/cctz/include/cctz/civil_time_detail.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -324,6 +326,7 @@ using detail::get_yearday;
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ #endif // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_

View file

@ -20,6 +20,8 @@
#include <ostream> #include <ostream>
#include <type_traits> #include <type_traits>
#include "absl/base/config.h"
// Disable constexpr support unless we are in C++14 mode. // Disable constexpr support unless we are in C++14 mode.
#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) #if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910)
#define CONSTEXPR_D constexpr // data #define CONSTEXPR_D constexpr // data
@ -32,6 +34,7 @@
#endif #endif
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { 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. // Normalized civil-time fields: Y-M-D HH:MM:SS.
struct fields { struct fields {
CONSTEXPR_M fields(year_t year, month_t month, day_t day, CONSTEXPR_M fields(year_t year, month_t month, day_t day, hour_t hour,
hour_t hour, minute_t minute, second_t second) minute_t minute, second_t second)
: y(year), m(month), d(day), hh(hour), mm(minute), ss(second) {} : y(year), m(month), d(day), hh(hour), mm(minute), ss(second) {}
std::int_least64_t y; std::int_least64_t y;
std::int_least8_t m; 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)); 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, CONSTEXPR_F fields n_day(year_t y, month_t m, diff_t d, diff_t cd, hour_t hh,
hour_t hh, minute_t mm, second_t ss) noexcept { minute_t mm, second_t ss) noexcept {
y += (cd / 146097) * 400; y += (cd / 146097) * 400;
cd %= 146097; cd %= 146097;
if (cd < 0) { 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<day_t>(d), hh, mm, ss); return fields(y, m, static_cast<day_t>(d), hh, mm, ss);
} }
CONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd, CONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd, hour_t hh,
hour_t hh, minute_t mm, second_t ss) noexcept { minute_t mm, second_t ss) noexcept {
if (m != 12) { if (m != 12) {
y += m / 12; y += m / 12;
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<month_t>(m), d, cd, hh, mm, ss); return n_day(y, static_cast<month_t>(m), d, cd, hh, mm, ss);
} }
CONSTEXPR_F fields n_hour(year_t y, diff_t m, diff_t d, diff_t cd, CONSTEXPR_F fields n_hour(year_t y, diff_t m, diff_t d, diff_t cd, diff_t hh,
diff_t hh, minute_t mm, second_t ss) noexcept { minute_t mm, second_t ss) noexcept {
cd += hh / 24; cd += hh / 24;
hh %= 24; hh %= 24;
if (hh < 0) { 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 // yet the difference between two such extreme values may actually be
// small, so we take a little care to avoid overflow when possible by // small, so we take a little care to avoid overflow when possible by
// exploiting the 146097-day cycle. // exploiting the 146097-day cycle.
CONSTEXPR_F diff_t day_difference(year_t y1, month_t m1, day_t d1, CONSTEXPR_F diff_t day_difference(year_t y1, month_t m1, day_t d1, year_t y2,
year_t y2, month_t m2, day_t d2) noexcept { month_t m2, day_t d2) noexcept {
const diff_t a_c4_off = y1 % 400; const diff_t a_c4_off = y1 % 400;
const diff_t b_c4_off = y2 % 400; const diff_t b_c4_off = y2 % 400;
diff_t c4_diff = (y1 - a_c4_off) - (y2 - b_c4_off); 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. // Aligns the (normalized) fields struct to the indicated field.
CONSTEXPR_F fields align(second_tag, fields f) noexcept { CONSTEXPR_F fields align(second_tag, fields f) noexcept { return f; }
return f;
}
CONSTEXPR_F fields align(minute_tag, fields f) noexcept { CONSTEXPR_F fields align(minute_tag, fields f) noexcept {
return fields{f.y, f.m, f.d, f.hh, f.mm, 0}; return fields{f.y, f.m, f.d, f.hh, f.mm, 0};
} }
@ -386,11 +387,11 @@ class civil_time {
: civil_time(ct.f_) {} : civil_time(ct.f_) {}
// Factories for the maximum/minimum representable civil_time. // 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<std::int_least64_t>::max)(); const auto max_year = (std::numeric_limits<std::int_least64_t>::max)();
return civil_time(max_year, 12, 31, 23, 59, 59); 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<std::int_least64_t>::min)(); const auto min_year = (std::numeric_limits<std::int_least64_t>::min)();
return civil_time(min_year, 1, 1, 0, 0, 0); return civil_time(min_year, 1, 1, 0, 0, 0);
} }
@ -416,17 +417,13 @@ class civil_time {
} }
return *this; return *this;
} }
CONSTEXPR_M civil_time& operator++() noexcept { CONSTEXPR_M civil_time& operator++() noexcept { return *this += 1; }
return *this += 1;
}
CONSTEXPR_M civil_time operator++(int) noexcept { CONSTEXPR_M civil_time operator++(int) noexcept {
const civil_time a = *this; const civil_time a = *this;
++*this; ++*this;
return a; return a;
} }
CONSTEXPR_M civil_time& operator--() noexcept { CONSTEXPR_M civil_time& operator--() noexcept { return *this -= 1; }
return *this -= 1;
}
CONSTEXPR_M civil_time operator--(int) noexcept { CONSTEXPR_M civil_time operator--(int) noexcept {
const civil_time a = *this; const civil_time a = *this;
--*this; --*this;
@ -483,17 +480,17 @@ using civil_second = civil_time<second_tag>;
template <typename T1, typename T2> template <typename T1, typename T2>
CONSTEXPR_F bool operator<(const civil_time<T1>& lhs, CONSTEXPR_F bool operator<(const civil_time<T1>& lhs,
const civil_time<T2>& rhs) noexcept { const civil_time<T2>& rhs) noexcept {
return (lhs.year() < rhs.year() || return (
(lhs.year() == rhs.year() && lhs.year() < rhs.year() ||
(lhs.month() < rhs.month() || (lhs.year() == rhs.year() &&
(lhs.month() == rhs.month() && (lhs.month() < rhs.month() ||
(lhs.day() < rhs.day() || (lhs.month() == rhs.month() &&
(lhs.day() == rhs.day() && (lhs.day() < rhs.day() || (lhs.day() == rhs.day() &&
(lhs.hour() < rhs.hour() || (lhs.hour() < rhs.hour() ||
(lhs.hour() == rhs.hour() && (lhs.hour() == rhs.hour() &&
(lhs.minute() < rhs.minute() || (lhs.minute() < rhs.minute() ||
(lhs.minute() == rhs.minute() && (lhs.minute() == rhs.minute() &&
(lhs.second() < rhs.second()))))))))))); (lhs.second() < rhs.second())))))))))));
} }
template <typename T1, typename T2> template <typename T1, typename T2>
CONSTEXPR_F bool operator<=(const civil_time<T1>& lhs, CONSTEXPR_F bool operator<=(const civil_time<T1>& lhs,
@ -615,6 +612,7 @@ std::ostream& operator<<(std::ostream& os, weekday wd);
} // namespace detail } // namespace detail
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
#undef CONSTEXPR_M #undef CONSTEXPR_M

View file

@ -25,9 +25,11 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.h" #include "absl/time/internal/cctz/include/cctz/civil_time.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -39,8 +41,8 @@ using sys_seconds = seconds; // Deprecated. Use cctz::seconds instead.
namespace detail { namespace detail {
template <typename D> template <typename D>
inline std::pair<time_point<seconds>, D> inline std::pair<time_point<seconds>, D> split_seconds(
split_seconds(const time_point<D>& tp) { const time_point<D>& tp) {
auto sec = std::chrono::time_point_cast<seconds>(tp); auto sec = std::chrono::time_point_cast<seconds>(tp);
auto sub = tp - sec; auto sub = tp - sec;
if (sub.count() < 0) { if (sub.count() < 0) {
@ -49,8 +51,8 @@ split_seconds(const time_point<D>& tp) {
} }
return {sec, std::chrono::duration_cast<D>(sub)}; return {sec, std::chrono::duration_cast<D>(sub)};
} }
inline std::pair<time_point<seconds>, seconds> inline std::pair<time_point<seconds>, seconds> split_seconds(
split_seconds(const time_point<seconds>& tp) { const time_point<seconds>& tp) {
return {tp, seconds::zero()}; return {tp, seconds::zero()};
} }
} // namespace detail } // namespace detail
@ -194,15 +196,13 @@ class time_zone {
bool next_transition(const time_point<seconds>& tp, bool next_transition(const time_point<seconds>& tp,
civil_transition* trans) const; civil_transition* trans) const;
template <typename D> template <typename D>
bool next_transition(const time_point<D>& tp, bool next_transition(const time_point<D>& tp, civil_transition* trans) const {
civil_transition* trans) const {
return next_transition(detail::split_seconds(tp).first, trans); return next_transition(detail::split_seconds(tp).first, trans);
} }
bool prev_transition(const time_point<seconds>& tp, bool prev_transition(const time_point<seconds>& tp,
civil_transition* trans) const; civil_transition* trans) const;
template <typename D> template <typename D>
bool prev_transition(const time_point<D>& tp, bool prev_transition(const time_point<D>& tp, civil_transition* trans) const {
civil_transition* trans) const {
return prev_transition(detail::split_seconds(tp).first, trans); 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) { friend bool operator==(time_zone lhs, time_zone rhs) {
return &lhs.effective_impl() == &rhs.effective_impl(); return &lhs.effective_impl() == &rhs.effective_impl();
} }
friend bool operator!=(time_zone lhs, time_zone rhs) { friend bool operator!=(time_zone lhs, time_zone rhs) { return !(lhs == rhs); }
return !(lhs == rhs);
}
template <typename H> template <typename H>
friend H AbslHashValue(H h, time_zone tz) { 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 cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_ #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_

View file

@ -20,7 +20,10 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "absl/base/config.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -30,7 +33,7 @@ class ZoneInfoSource {
virtual ~ZoneInfoSource(); virtual ~ZoneInfoSource();
virtual std::size_t Read(void* ptr, std::size_t size) = 0; // like fread() 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 // Until the zoneinfo data supports versioning information, we provide
// a way for a ZoneInfoSource to indicate it out-of-band. The default // a way for a ZoneInfoSource to indicate it out-of-band. The default
@ -40,9 +43,11 @@ class ZoneInfoSource {
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz_extension { namespace cctz_extension {
@ -52,8 +57,8 @@ namespace cctz_extension {
using ZoneInfoSourceFactory = using ZoneInfoSourceFactory =
std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> (*)( std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> (*)(
const std::string&, const std::string&,
const std::function<std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource>( const std::function<std::unique_ptr<
const std::string&)>&); absl::time_internal::cctz::ZoneInfoSource>(const std::string&)>&);
// The user can control the mapping of zone names to zoneinfo data by // The user can control the mapping of zone names to zoneinfo data by
// providing a definition for cctz_extension::zone_info_source_factory. // providing a definition for cctz_extension::zone_info_source_factory.
@ -91,6 +96,7 @@ extern ZoneInfoSourceFactory zone_info_source_factory;
} // namespace cctz_extension } // namespace cctz_extension
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_ #endif // ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_

File diff suppressed because it is too large Load diff

View file

@ -18,7 +18,10 @@
#include <ostream> #include <ostream>
#include <sstream> #include <sstream>
#include "absl/base/config.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
namespace detail { namespace detail {
@ -87,4 +90,5 @@ std::ostream& operator<<(std::ostream& os, weekday wd) {
} // namespace detail } // namespace detail
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl

View file

@ -21,8 +21,10 @@
#include <type_traits> #include <type_traits>
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "absl/base/config.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -1014,19 +1016,13 @@ TEST(CivilTime, LeapYears) {
int day; int day;
} leap_day; // The date of the day after Feb 28. } leap_day; // The date of the day after Feb 28.
} kLeapYearTable[]{ } kLeapYearTable[]{
{1900, 365, {3, 1}}, {1900, 365, {3, 1}}, {1999, 365, {3, 1}},
{1999, 365, {3, 1}},
{2000, 366, {2, 29}}, // leap year {2000, 366, {2, 29}}, // leap year
{2001, 365, {3, 1}}, {2001, 365, {3, 1}}, {2002, 365, {3, 1}},
{2002, 365, {3, 1}}, {2003, 365, {3, 1}}, {2004, 366, {2, 29}}, // leap year
{2003, 365, {3, 1}}, {2005, 365, {3, 1}}, {2006, 365, {3, 1}},
{2004, 366, {2, 29}}, // leap year {2007, 365, {3, 1}}, {2008, 366, {2, 29}}, // leap year
{2005, 365, {3, 1}}, {2009, 365, {3, 1}}, {2100, 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) { for (const auto& e : kLeapYearTable) {
@ -1056,4 +1052,5 @@ TEST(CivilTime, FirstThursdayInMonth) {
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl

View file

@ -20,7 +20,10 @@
#include <cstring> #include <cstring>
#include <string> #include <string>
#include "absl/base/config.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -59,11 +62,9 @@ bool FixedOffsetFromName(const std::string& name, seconds* offset) {
const char* const ep = kFixedZonePrefix + prefix_len; const char* const ep = kFixedZonePrefix + prefix_len;
if (name.size() != prefix_len + 9) // <prefix>+99:99:99 if (name.size() != prefix_len + 9) // <prefix>+99:99:99
return false; return false;
if (!std::equal(kFixedZonePrefix, ep, name.begin())) if (!std::equal(kFixedZonePrefix, ep, name.begin())) return false;
return false;
const char* np = name.data() + prefix_len; const char* np = name.data() + prefix_len;
if (np[0] != '+' && np[0] != '-') if (np[0] != '+' && np[0] != '-') return false;
return false;
if (np[3] != ':' || np[6] != ':') // see note below about large offsets if (np[3] != ':' || np[6] != ':') // see note below about large offsets
return false; return false;
@ -135,4 +136,5 @@ std::string FixedOffsetToAbbr(const seconds& offset) {
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl

View file

@ -17,9 +17,11 @@
#include <string> #include <string>
#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -44,6 +46,7 @@ std::string FixedOffsetToAbbr(const seconds& offset);
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_ #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_

View file

@ -13,17 +13,18 @@
// limitations under the License. // limitations under the License.
#if !defined(HAS_STRPTIME) #if !defined(HAS_STRPTIME)
# if !defined(_MSC_VER) && !defined(__MINGW32__) #if !defined(_MSC_VER) && !defined(__MINGW32__)
# define HAS_STRPTIME 1 // assume everyone has strptime() except windows #define HAS_STRPTIME 1 // assume everyone has strptime() except windows
# endif #endif
#endif #endif
#if defined(HAS_STRPTIME) && HAS_STRPTIME #if defined(HAS_STRPTIME) && HAS_STRPTIME
# if !defined(_XOPEN_SOURCE) #if !defined(_XOPEN_SOURCE)
# define _XOPEN_SOURCE // Definedness suffices for strptime. #define _XOPEN_SOURCE // Definedness suffices for strptime.
# endif #endif
#endif #endif
#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h"
// Include time.h directly since, by C++ standards, ctime doesn't have to // Include time.h directly since, by C++ standards, ctime doesn't have to
@ -48,6 +49,7 @@
#include "time_zone_if.h" #include "time_zone_if.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
namespace detail { namespace detail {
@ -502,8 +504,9 @@ std::string format(const std::string& format, const time_point<seconds>& tp,
bp = ep; bp = ep;
if (n > 0) { if (n > 0) {
if (n > kDigits10_64) n = kDigits10_64; if (n > kDigits10_64) n = kDigits10_64;
bp = Format64(bp, n, (n > 15) ? fs.count() * kExp10[n - 15] bp = Format64(bp, n,
: fs.count() / kExp10[15 - n]); (n > 15) ? fs.count() * kExp10[n - 15]
: fs.count() / kExp10[15 - n]);
if (*np == 'S') *--bp = '.'; if (*np == 'S') *--bp = '.';
} }
if (*np == 'S') bp = Format02d(bp, al.cs.second()); 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); data = ParseZone(data, &zone);
continue; continue;
case 's': case 's':
data = ParseInt(data, 0, data =
std::numeric_limits<std::int_fast64_t>::min(), ParseInt(data, 0, std::numeric_limits<std::int_fast64_t>::min(),
std::numeric_limits<std::int_fast64_t>::max(), std::numeric_limits<std::int_fast64_t>::max(), &percent_s);
&percent_s);
if (data != nullptr) saw_percent_s = true; if (data != nullptr) saw_percent_s = true;
continue; continue;
case ':': case ':':
@ -916,4 +918,5 @@ bool parse(const std::string& format, const std::string& input,
} // namespace detail } // namespace detail
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl

View file

@ -12,20 +12,21 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
#include <chrono> #include <chrono>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include "absl/time/internal/cctz/include/cctz/civil_time.h"
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "gtest/gtest.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 chrono = std::chrono;
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -48,10 +49,10 @@ namespace {
} while (0) } while (0)
const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez"; 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_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 // A helper that tests the given format specifier by itself, and with leading
// and trailing characters. For example: TestFormatSpecifier(tp, "%a", "Thu"). // and trailing characters. For example: TestFormatSpecifier(tp, "%a", "Thu").
@ -88,8 +89,11 @@ TEST(Format, TimePointResolution) {
format(kFmt, chrono::time_point_cast<chrono::milliseconds>(t0), utc)); format(kFmt, chrono::time_point_cast<chrono::milliseconds>(t0), utc));
EXPECT_EQ("03:04:05", EXPECT_EQ("03:04:05",
format(kFmt, chrono::time_point_cast<chrono::seconds>(t0), utc)); format(kFmt, chrono::time_point_cast<chrono::seconds>(t0), utc));
EXPECT_EQ("03:04:05", EXPECT_EQ(
format(kFmt, chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0), utc)); "03:04:05",
format(kFmt,
chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0),
utc));
EXPECT_EQ("03:04:00", EXPECT_EQ("03:04:00",
format(kFmt, chrono::time_point_cast<chrono::minutes>(t0), utc)); format(kFmt, chrono::time_point_cast<chrono::minutes>(t0), utc));
EXPECT_EQ("03:00:00", EXPECT_EQ("03:00:00",
@ -110,12 +114,10 @@ TEST(Format, TimePointExtendedResolution) {
EXPECT_EQ( EXPECT_EQ(
"12:34:56.012345678901234", "12:34:56.012345678901234",
detail::format(kFmt, tp, detail::femtoseconds(12345678901234), utc)); detail::format(kFmt, tp, detail::femtoseconds(12345678901234), utc));
EXPECT_EQ( EXPECT_EQ("12:34:56.001234567890123",
"12:34:56.001234567890123", detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc));
detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc)); EXPECT_EQ("12:34:56.000123456789012",
EXPECT_EQ( detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc));
"12:34:56.000123456789012",
detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc));
EXPECT_EQ("12:34:56.000000000000123", EXPECT_EQ("12:34:56.000000000000123",
detail::format(kFmt, tp, detail::femtoseconds(123), utc)); 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)); parse(RFC3339_sec, "-292277022657-01-27T08:29:51+01:00", utc, &tp));
// tests max/min civil-second overflow // tests max/min civil-second overflow
EXPECT_FALSE(parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01", EXPECT_FALSE(
utc, &tp)); parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01", utc, &tp));
EXPECT_FALSE(parse(RFC3339_sec, "-9223372036854775808-01-01T00:00:00+00:01", EXPECT_FALSE(parse(RFC3339_sec, "-9223372036854775808-01-01T00:00:00+00:01",
utc, &tp)); utc, &tp));
@ -1474,7 +1476,8 @@ TEST(FormatParse, RoundTrip) {
TEST(FormatParse, RoundTripDistantFuture) { TEST(FormatParse, RoundTripDistantFuture) {
const time_zone utc = utc_time_zone(); const time_zone utc = utc_time_zone();
const time_point<absl::time_internal::cctz::seconds> in = time_point<absl::time_internal::cctz::seconds>::max(); const time_point<absl::time_internal::cctz::seconds> in =
time_point<absl::time_internal::cctz::seconds>::max();
const std::string s = format(RFC3339_full, in, utc); const std::string s = format(RFC3339_full, in, utc);
time_point<absl::time_internal::cctz::seconds> out; time_point<absl::time_internal::cctz::seconds> out;
EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s; EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;
@ -1483,7 +1486,8 @@ TEST(FormatParse, RoundTripDistantFuture) {
TEST(FormatParse, RoundTripDistantPast) { TEST(FormatParse, RoundTripDistantPast) {
const time_zone utc = utc_time_zone(); const time_zone utc = utc_time_zone();
const time_point<absl::time_internal::cctz::seconds> in = time_point<absl::time_internal::cctz::seconds>::min(); const time_point<absl::time_internal::cctz::seconds> in =
time_point<absl::time_internal::cctz::seconds>::min();
const std::string s = format(RFC3339_full, in, utc); const std::string s = format(RFC3339_full, in, utc);
time_point<absl::time_internal::cctz::seconds> out; time_point<absl::time_internal::cctz::seconds> out;
EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s; EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;
@ -1492,4 +1496,5 @@ TEST(FormatParse, RoundTripDistantPast) {
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl

View file

@ -13,10 +13,13 @@
// limitations under the License. // limitations under the License.
#include "time_zone_if.h" #include "time_zone_if.h"
#include "absl/base/config.h"
#include "time_zone_info.h" #include "time_zone_info.h"
#include "time_zone_libc.h" #include "time_zone_libc.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -38,4 +41,5 @@ TimeZoneIf::~TimeZoneIf() {}
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl

View file

@ -20,10 +20,12 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.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/time_zone.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -38,8 +40,7 @@ class TimeZoneIf {
virtual time_zone::absolute_lookup BreakTime( virtual time_zone::absolute_lookup BreakTime(
const time_point<seconds>& tp) const = 0; const time_point<seconds>& tp) const = 0;
virtual time_zone::civil_lookup MakeTime( virtual time_zone::civil_lookup MakeTime(const civil_second& cs) const = 0;
const civil_second& cs) const = 0;
virtual bool NextTransition(const time_point<seconds>& tp, virtual bool NextTransition(const time_point<seconds>& tp,
time_zone::civil_transition* trans) const = 0; 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. // Unix clock are second aligned, but not that they share an epoch.
inline std::int_fast64_t ToUnixSeconds(const time_point<seconds>& tp) { inline std::int_fast64_t ToUnixSeconds(const time_point<seconds>& tp) {
return (tp - std::chrono::time_point_cast<seconds>( return (tp - std::chrono::time_point_cast<seconds>(
std::chrono::system_clock::from_time_t(0))).count(); std::chrono::system_clock::from_time_t(0)))
.count();
} }
inline time_point<seconds> FromUnixSeconds(std::int_fast64_t t) { inline time_point<seconds> FromUnixSeconds(std::int_fast64_t t) {
return std::chrono::time_point_cast<seconds>( return std::chrono::time_point_cast<seconds>(
std::chrono::system_clock::from_time_t(0)) + seconds(t); std::chrono::system_clock::from_time_t(0)) +
seconds(t);
} }
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_ #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_

View file

@ -20,9 +20,11 @@
#include <unordered_map> #include <unordered_map>
#include <utility> #include <utility>
#include "absl/base/config.h"
#include "time_zone_fixed.h" #include "time_zone_fixed.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -43,9 +45,7 @@ std::mutex& TimeZoneMutex() {
} // namespace } // namespace
time_zone time_zone::Impl::UTC() { time_zone time_zone::Impl::UTC() { return time_zone(UTCImpl()); }
return time_zone(UTCImpl());
}
bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) { bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) {
const time_zone::Impl* const utc_impl = UTCImpl(); const time_zone::Impl* const utc_impl = UTCImpl();
@ -117,4 +117,5 @@ const time_zone::Impl* time_zone::Impl::UTCImpl() {
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl

View file

@ -18,12 +18,14 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.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/time_zone.h"
#include "time_zone_if.h" #include "time_zone_if.h"
#include "time_zone_info.h" #include "time_zone_info.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -85,6 +87,7 @@ class time_zone::Impl {
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_ #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_

View file

@ -45,11 +45,13 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.h" #include "absl/time/internal/cctz/include/cctz/civil_time.h"
#include "time_zone_fixed.h" #include "time_zone_fixed.h"
#include "time_zone_posix.h" #include "time_zone_posix.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { 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 // 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). // leap years respectively (e.g., 335 days before December in a leap year).
const std::int_least16_t kMonthOffsets[2][1 + 12 + 1] = { 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, 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, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366},
}; };
// We reject leap-second encoded zoneinfo and so assume 60-second minutes. // 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. // Like kDaysPerYear[] but scaled up by a factor of kSecsPerDay.
const std::int_least32_t kSecsPerYear[2] = { const std::int_least32_t kSecsPerYear[2] = {
365 * kSecsPerDay, 365 * kSecsPerDay,
366 * kSecsPerDay, 366 * kSecsPerDay,
}; };
// Single-byte, unsigned numeric values are encoded directly. // 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) { inline civil_second YearShift(const civil_second& cs, year_t shift) {
return civil_second(cs.year() + shift, cs.month(), cs.day(), return civil_second(cs.year() + shift, cs.month(), cs.day(), cs.hour(),
cs.hour(), cs.minute(), cs.second()); cs.minute(), cs.second());
} }
} // namespace } // namespace
@ -216,7 +218,7 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) {
default_transition_type_ = 0; default_transition_type_ = 0;
abbreviations_ = FixedOffsetToAbbr(offset); abbreviations_ = FixedOffsetToAbbr(offset);
abbreviations_.append(1, '\0'); // add NUL 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; extended_ = false;
tt.civil_max = LocalTime(seconds::max().count(), tt).cs; 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) { bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
// Read and validate the header. // Read and validate the header.
tzhead tzh; tzhead tzh;
if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false;
return false;
if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0) if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0)
return false; return false;
Header hdr; Header hdr;
if (!hdr.Build(tzh)) if (!hdr.Build(tzh)) return false;
return false;
std::size_t time_len = 4; std::size_t time_len = 4;
if (tzh.tzh_version[0] != '\0') { if (tzh.tzh_version[0] != '\0') {
// Skip the 4-byte data. // Skip the 4-byte data.
if (zip->Skip(hdr.DataLength(time_len)) != 0) if (zip->Skip(hdr.DataLength(time_len)) != 0) return false;
return false;
// Read and validate the header for the 8-byte data. // Read and validate the header for the 8-byte data.
if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false;
return false;
if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0) if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0)
return false; return false;
if (tzh.tzh_version[0] == '\0') if (tzh.tzh_version[0] == '\0') return false;
return false; if (!hdr.Build(tzh)) return false;
if (!hdr.Build(tzh))
return false;
time_len = 8; time_len = 8;
} }
if (hdr.typecnt == 0) if (hdr.typecnt == 0) return false;
return false;
if (hdr.leapcnt != 0) { if (hdr.leapcnt != 0) {
// This code assumes 60-second minutes so we do not want // This code assumes 60-second minutes so we do not want
// the leap-second encoded zoneinfo. We could reverse the // 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. // so currently we simply reject such data.
return false; return false;
} }
if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt) if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt) return false;
return false; if (hdr.ttisutcnt != 0 && hdr.ttisutcnt != hdr.typecnt) return false;
if (hdr.ttisutcnt != 0 && hdr.ttisutcnt != hdr.typecnt)
return false;
// Read the data into a local buffer. // Read the data into a local buffer.
std::size_t len = hdr.DataLength(time_len); std::size_t len = hdr.DataLength(time_len);
std::vector<char> tbuf(len); std::vector<char> tbuf(len);
if (zip->Read(tbuf.data(), len) != len) if (zip->Read(tbuf.data(), len) != len) return false;
return false;
const char* bp = tbuf.data(); const char* bp = tbuf.data();
// Decode and validate the transitions. // Decode and validate the transitions.
@ -452,10 +444,8 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
bool seen_type_0 = false; bool seen_type_0 = false;
for (std::size_t i = 0; i != hdr.timecnt; ++i) { for (std::size_t i = 0; i != hdr.timecnt; ++i) {
transitions_[i].type_index = Decode8(bp++); transitions_[i].type_index = Decode8(bp++);
if (transitions_[i].type_index >= hdr.typecnt) if (transitions_[i].type_index >= hdr.typecnt) return false;
return false; if (transitions_[i].type_index == 0) seen_type_0 = true;
if (transitions_[i].type_index == 0)
seen_type_0 = true;
} }
// Decode and validate the transition types. // Decode and validate the transition types.
@ -469,8 +459,7 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
bp += 4; bp += 4;
transition_types_[i].is_dst = (Decode8(bp++) != 0); transition_types_[i].is_dst = (Decode8(bp++) != 0);
transition_types_[i].abbr_index = Decode8(bp++); transition_types_[i].abbr_index = Decode8(bp++);
if (transition_types_[i].abbr_index >= hdr.charcnt) if (transition_types_[i].abbr_index >= hdr.charcnt) return false;
return false;
} }
// Determine the before-first-transition type. // 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; std::uint_fast8_t index = 0;
if (transition_types_[0].is_dst) { if (transition_types_[0].is_dst) {
index = transitions_[0].type_index; index = transitions_[0].type_index;
while (index != 0 && transition_types_[index].is_dst) while (index != 0 && transition_types_[index].is_dst) --index;
--index;
} }
while (index != hdr.typecnt && transition_types_[index].is_dst) while (index != hdr.typecnt && transition_types_[index].is_dst) ++index;
++index; if (index != hdr.typecnt) default_transition_type_ = index;
if (index != hdr.typecnt)
default_transition_type_ = index;
} }
// Copy all the abbreviations. // 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 unsigned char ch; // all non-EOF results are positive
return (azip->Read(&ch, 1) == 1) ? ch : EOF; return (azip->Read(&ch, 1) == 1) ? ch : EOF;
}; };
if (get_char(zip) != '\n') if (get_char(zip) != '\n') return false;
return false;
for (int c = get_char(zip); c != '\n'; c = get_char(zip)) { for (int c = get_char(zip); c != '\n'; c = get_char(zip)) {
if (c == EOF) if (c == EOF) return false;
return false;
future_spec_.push_back(static_cast<char>(c)); future_spec_.push_back(static_cast<char>(c));
} }
} }
@ -624,7 +608,7 @@ class FileZoneInfoSource : public ZoneInfoSource {
: fp_(fp, fclose), len_(len) {} : fp_(fp, fclose), len_(len) {}
private: private:
std::unique_ptr<FILE, int(*)(FILE*)> fp_; std::unique_ptr<FILE, int (*)(FILE*)> fp_;
std::size_t len_; 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. // A civil time in "+offset" looks like (time+offset) in UTC.
// Note: We perform two additions in the civil_second domain to // Note: We perform two additions in the civil_second domain to
// sidestep the chance of overflow in (unix_time + tt.utc_offset). // sidestep the chance of overflow in (unix_time + tt.utc_offset).
return {(civil_second() + unix_time) + tt.utc_offset, return {(civil_second() + unix_time) + tt.utc_offset, tt.utc_offset,
tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]}; tt.is_dst, &abbreviations_[tt.abbr_index]};
} }
// BreakTime() translation for a particular transition. // BreakTime() translation for a particular transition.
time_zone::absolute_lookup TimeZoneInfo::LocalTime( time_zone::absolute_lookup TimeZoneInfo::LocalTime(std::int_fast64_t unix_time,
std::int_fast64_t unix_time, const Transition& tr) const { const Transition& tr) const {
const TransitionType& tt = transition_types_[tr.type_index]; const TransitionType& tt = transition_types_[tr.type_index];
// Note: (unix_time - tr.unix_time) will never overflow as we // Note: (unix_time - tr.unix_time) will never overflow as we
// have ensured that there is always a "nearby" transition. // 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)); return MakeUnique(tr->unix_time + (cs - tr->civil_sec));
} }
std::string TimeZoneInfo::Version() const { std::string TimeZoneInfo::Version() const { return version_; }
return version_;
}
std::string TimeZoneInfo::Description() const { std::string TimeZoneInfo::Description() const {
std::ostringstream oss; std::ostringstream oss;
@ -921,8 +903,8 @@ bool TimeZoneInfo::NextTransition(const time_point<seconds>& tp,
} }
std::int_fast64_t unix_time = ToUnixSeconds(tp); std::int_fast64_t unix_time = ToUnixSeconds(tp);
const Transition target = {unix_time, 0, civil_second(), civil_second()}; const Transition target = {unix_time, 0, civil_second(), civil_second()};
const Transition* tr = std::upper_bound(begin, end, target, const Transition* tr =
Transition::ByUnixTime()); std::upper_bound(begin, end, target, Transition::ByUnixTime());
for (; tr != end; ++tr) { // skip no-op transitions for (; tr != end; ++tr) { // skip no-op transitions
std::uint_fast8_t prev_type_index = std::uint_fast8_t prev_type_index =
(tr == begin) ? default_transition_type_ : tr[-1].type_index; (tr == begin) ? default_transition_type_ : tr[-1].type_index;
@ -956,8 +938,8 @@ bool TimeZoneInfo::PrevTransition(const time_point<seconds>& tp,
unix_time += 1; // ceils unix_time += 1; // ceils
} }
const Transition target = {unix_time, 0, civil_second(), civil_second()}; const Transition target = {unix_time, 0, civil_second(), civil_second()};
const Transition* tr = std::lower_bound(begin, end, target, const Transition* tr =
Transition::ByUnixTime()); std::lower_bound(begin, end, target, Transition::ByUnixTime());
for (; tr != begin; --tr) { // skip no-op transitions for (; tr != begin; --tr) { // skip no-op transitions
std::uint_fast8_t prev_type_index = std::uint_fast8_t prev_type_index =
(tr - 1 == begin) ? default_transition_type_ : tr[-2].type_index; (tr - 1 == begin) ? default_transition_type_ : tr[-2].type_index;
@ -972,4 +954,5 @@ bool TimeZoneInfo::PrevTransition(const time_point<seconds>& tp,
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl

View file

@ -21,6 +21,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.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/time_zone.h"
#include "absl/time/internal/cctz/include/cctz/zone_info_source.h" #include "absl/time/internal/cctz/include/cctz/zone_info_source.h"
@ -28,6 +29,7 @@
#include "tzfile.h" #include "tzfile.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -72,8 +74,7 @@ class TimeZoneInfo : public TimeZoneIf {
// TimeZoneIf implementations. // TimeZoneIf implementations.
time_zone::absolute_lookup BreakTime( time_zone::absolute_lookup BreakTime(
const time_point<seconds>& tp) const override; const time_point<seconds>& tp) const override;
time_zone::civil_lookup MakeTime( time_zone::civil_lookup MakeTime(const civil_second& cs) const override;
const civil_second& cs) const override;
bool NextTransition(const time_point<seconds>& tp, bool NextTransition(const time_point<seconds>& tp,
time_zone::civil_transition* trans) const override; time_zone::civil_transition* trans) const override;
bool PrevTransition(const time_point<seconds>& tp, bool PrevTransition(const time_point<seconds>& tp,
@ -82,7 +83,7 @@ class TimeZoneInfo : public TimeZoneIf {
std::string Description() const override; std::string Description() const override;
private: private:
struct Header { // counts of: struct Header { // counts of:
std::size_t timecnt; // transition times std::size_t timecnt; // transition times
std::size_t typecnt; // transition types std::size_t typecnt; // transition types
std::size_t charcnt; // zone abbreviation characters std::size_t charcnt; // zone abbreviation characters
@ -114,7 +115,7 @@ class TimeZoneInfo : public TimeZoneIf {
std::vector<Transition> transitions_; // ordered by unix_time and civil_sec std::vector<Transition> transitions_; // ordered by unix_time and civil_sec
std::vector<TransitionType> transition_types_; // distinct transition types std::vector<TransitionType> 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 abbreviations_; // all the NUL-terminated abbreviations
std::string version_; // the tzdata version if available std::string version_; // the tzdata version if available
@ -131,6 +132,7 @@ class TimeZoneInfo : public TimeZoneIf {
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_

View file

@ -23,10 +23,12 @@
#include <limits> #include <limits>
#include <utility> #include <utility>
#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.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/time_zone.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -84,9 +86,7 @@ auto tm_gmtoff(const T& tm) -> decltype(tm.__tm_gmtoff) {
} }
#endif // tm_gmtoff #endif // tm_gmtoff
#if defined(tm_zone) #if defined(tm_zone)
auto tm_zone(const std::tm& tm) -> decltype(tm.tm_zone) { auto tm_zone(const std::tm& tm) -> decltype(tm.tm_zone) { return tm.tm_zone; }
return tm.tm_zone;
}
#elif defined(__tm_zone) #elif defined(__tm_zone)
auto tm_zone(const std::tm& tm) -> decltype(tm.__tm_zone) { auto tm_zone(const std::tm& tm) -> decltype(tm.__tm_zone) {
return 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 // tm_zone
#endif #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) #if defined(_WIN32) || defined(_WIN64)
return gmtime_s(result, timep) ? nullptr : result; return gmtime_s(result, timep) ? nullptr : result;
#else #else
return gmtime_r(timep, result); return gmtime_r(timep, result);
#endif #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) #if defined(_WIN32) || defined(_WIN64)
return localtime_s(result, timep) ? nullptr : result; return localtime_s(result, timep) ? nullptr : result;
#else #else
return localtime_r(timep, result); return localtime_r(timep, result);
#endif #endif
} }
@ -208,8 +208,8 @@ time_zone::absolute_lookup TimeZoneLibC::BreakTime(
} }
const year_t year = tmp->tm_year + year_t{1900}; const year_t year = tmp->tm_year + year_t{1900};
al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday, al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec); tmp->tm_min, tmp->tm_sec);
al.offset = static_cast<int>(tm_gmtoff(*tmp)); al.offset = static_cast<int>(tm_gmtoff(*tmp));
al.abbr = local_ ? tm_zone(*tmp) : "UTC"; // as expected by cctz al.abbr = local_ ? tm_zone(*tmp) : "UTC"; // as expected by cctz
al.is_dst = tmp->tm_isdst > 0; al.is_dst = tmp->tm_isdst > 0;
@ -304,4 +304,5 @@ std::string TimeZoneLibC::Description() const {
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl

View file

@ -17,9 +17,11 @@
#include <string> #include <string>
#include "absl/base/config.h"
#include "time_zone_if.h" #include "time_zone_if.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -33,8 +35,7 @@ class TimeZoneLibC : public TimeZoneIf {
// TimeZoneIf implementations. // TimeZoneIf implementations.
time_zone::absolute_lookup BreakTime( time_zone::absolute_lookup BreakTime(
const time_point<seconds>& tp) const override; const time_point<seconds>& tp) const override;
time_zone::civil_lookup MakeTime( time_zone::civil_lookup MakeTime(const civil_second& cs) const override;
const civil_second& cs) const override;
bool NextTransition(const time_point<seconds>& tp, bool NextTransition(const time_point<seconds>& tp,
time_zone::civil_transition* trans) const override; time_zone::civil_transition* trans) const override;
bool PrevTransition(const time_point<seconds>& tp, bool PrevTransition(const time_point<seconds>& tp,
@ -48,6 +49,7 @@ class TimeZoneLibC : public TimeZoneIf {
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_ #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_

View file

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h"
#if defined(__ANDROID__) #if defined(__ANDROID__)
@ -23,6 +24,7 @@
#if defined(__APPLE__) #if defined(__APPLE__)
#include <CoreFoundation/CFTimeZone.h> #include <CoreFoundation/CFTimeZone.h>
#include <vector> #include <vector>
#endif #endif
@ -34,6 +36,7 @@
#include "time_zone_impl.h" #include "time_zone_impl.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -66,9 +69,7 @@ int __system_property_get(const char* name, char* value) {
} // namespace } // namespace
#endif #endif
std::string time_zone::name() const { std::string time_zone::name() const { return effective_impl().Name(); }
return effective_impl().Name();
}
time_zone::absolute_lookup time_zone::lookup( time_zone::absolute_lookup time_zone::lookup(
const time_point<seconds>& tp) const { const time_point<seconds>& tp) const {
@ -89,9 +90,7 @@ bool time_zone::prev_transition(const time_point<seconds>& tp,
return effective_impl().PrevTransition(tp, trans); return effective_impl().PrevTransition(tp, trans);
} }
std::string time_zone::version() const { std::string time_zone::version() const { return effective_impl().Version(); }
return effective_impl().Version();
}
std::string time_zone::description() const { std::string time_zone::description() const {
return effective_impl().Description(); return effective_impl().Description();
@ -184,4 +183,5 @@ time_zone local_time_zone() {
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl

File diff suppressed because it is too large Load diff

View file

@ -19,7 +19,10 @@
#include <limits> #include <limits>
#include <string> #include <string>
#include "absl/base/config.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -152,4 +155,5 @@ bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res) {
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl

View file

@ -55,7 +55,10 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include "absl/base/config.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -123,6 +126,7 @@ bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res);
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_ #endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_

View file

@ -22,36 +22,35 @@
*/ */
#ifndef TZDIR #ifndef TZDIR
#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */ #define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
#endif /* !defined TZDIR */ #endif /* !defined TZDIR */
#ifndef TZDEFAULT #ifndef TZDEFAULT
#define TZDEFAULT "/etc/localtime" #define TZDEFAULT "/etc/localtime"
#endif /* !defined TZDEFAULT */ #endif /* !defined TZDEFAULT */
#ifndef TZDEFRULES #ifndef TZDEFRULES
#define TZDEFRULES "posixrules" #define TZDEFRULES "posixrules"
#endif /* !defined TZDEFRULES */ #endif /* !defined TZDEFRULES */
/* See Internet RFC 8536 for more details about the following format. */ /* See Internet RFC 8536 for more details about the following format. */
/* /*
** Each file begins with. . . ** Each file begins with. . .
*/ */
#define TZ_MAGIC "TZif" #define TZ_MAGIC "TZif"
struct tzhead { struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */ char tzh_magic[4]; /* TZ_MAGIC */
char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */ char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
char tzh_reserved[15]; /* reserved; must be zero */ char tzh_reserved[15]; /* reserved; must be zero */
char tzh_ttisutcnt[4]; /* coded number of trans. time flags */ char tzh_ttisutcnt[4]; /* coded number of trans. time flags */
char tzh_ttisstdcnt[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_leapcnt[4]; /* coded number of leap seconds */
char tzh_timecnt[4]; /* coded number of transition times */ char tzh_timecnt[4]; /* coded number of transition times */
char tzh_typecnt[4]; /* coded number of local time types */ char tzh_typecnt[4]; /* coded number of local time types */
char tzh_charcnt[4]; /* coded number of abbr. chars */ char tzh_charcnt[4]; /* coded number of abbr. chars */
}; };
/* /*
@ -103,21 +102,21 @@ struct tzhead {
*/ */
#ifndef TZ_MAX_TIMES #ifndef TZ_MAX_TIMES
#define TZ_MAX_TIMES 2000 #define TZ_MAX_TIMES 2000
#endif /* !defined TZ_MAX_TIMES */ #endif /* !defined TZ_MAX_TIMES */
#ifndef TZ_MAX_TYPES #ifndef TZ_MAX_TYPES
/* This must be at least 17 for Europe/Samara and Europe/Vilnius. */ /* 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 */ #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 #ifndef TZ_MAX_CHARS
#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ #define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
/* (limited by what unsigned chars can hold) */ /* (limited by what unsigned chars can hold) */
#endif /* !defined TZ_MAX_CHARS */ #endif /* !defined TZ_MAX_CHARS */
#ifndef TZ_MAX_LEAPS #ifndef TZ_MAX_LEAPS
#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ #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 */ #endif /* !defined TZFILE_H */

View file

@ -14,7 +14,10 @@
#include "absl/time/internal/cctz/include/cctz/zone_info_source.h" #include "absl/time/internal/cctz/include/cctz/zone_info_source.h"
#include "absl/base/config.h"
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz { namespace cctz {
@ -24,9 +27,11 @@ std::string ZoneInfoSource::Version() const { return std::string(); }
} // namespace cctz } // namespace cctz
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal { namespace time_internal {
namespace cctz_extension { namespace cctz_extension {
@ -36,8 +41,9 @@ namespace {
// defers to the fallback factory. // defers to the fallback factory.
std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> DefaultFactory( std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> DefaultFactory(
const std::string& name, const std::string& name,
const std::function<std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource>( const std::function<
const std::string& name)>& fallback_factory) { std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource>(
const std::string& name)>& fallback_factory) {
return fallback_factory(name); return fallback_factory(name);
} }
@ -53,8 +59,8 @@ std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> DefaultFactory(
// Windows linker cannot handle that. Nor does the MinGW compiler know how to // Windows linker cannot handle that. Nor does the MinGW compiler know how to
// pass "#pragma comment(linker, ...)" to the Windows linker. // pass "#pragma comment(linker, ...)" to the Windows linker.
#if (__has_attribute(weak) || defined(__GNUC__)) && !defined(__MINGW32__) #if (__has_attribute(weak) || defined(__GNUC__)) && !defined(__MINGW32__)
ZoneInfoSourceFactory zone_info_source_factory ZoneInfoSourceFactory zone_info_source_factory __attribute__((weak)) =
__attribute__((weak)) = DefaultFactory; DefaultFactory;
#elif defined(_MSC_VER) && !defined(__MINGW32__) && !defined(_LIBCPP_VERSION) #elif defined(_MSC_VER) && !defined(__MINGW32__) && !defined(_LIBCPP_VERSION)
extern ZoneInfoSourceFactory zone_info_source_factory; extern ZoneInfoSourceFactory zone_info_source_factory;
extern ZoneInfoSourceFactory default_factory; extern ZoneInfoSourceFactory default_factory;
@ -77,4 +83,5 @@ ZoneInfoSourceFactory zone_info_source_factory = DefaultFactory;
} // namespace cctz_extension } // namespace cctz_extension
} // namespace time_internal } // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl } // namespace absl