summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2018-05-31 12:26:35 -0700
committerGravatar Mark Barolak <mbar@google.com>2018-05-31 15:58:36 -0400
commit7aacab8ae05d7115049923da9cfbf584dc1f8338 (patch)
tree4394fc5eeed08a356d02ccfef33d1201f21b0dc3
parent99477fa9f1e89a7d8253c8aeee331864710d080c (diff)
- e2f6b8ac647271815b4fed2991f405524dd762c3 Release cctz microbenchmarks. by Alex Strelnikov <strel@google.com>
- 924ba2a3f9fca695d73c6bf491d20669e2b96b8e Changed RawPtr to use std::addressof() instead of operato... by Abseil Team <absl-team@google.com> - e8cf67f9fa74d4c5632da35547025ad2301c6819 Import of CCTZ from GitHub. by Alex Strelnikov <strel@google.com> - 2ece8a96611afcddd7b91e0197dadb896248250c Abandon ".inc" files in favor of ".h" headers. by Jorg Brown <jorg@google.com> - 37f5ed5da4058f90fb3e6a2733fce5b1fd0aaedf Add exception safety tests for absl::optional<T> by Abseil Team <absl-team@google.com> - 337f995a866b8f905f64ca6b271b5fec8f248a60 Update WORKSPACE to grab specific commits of dependencies... by Alex Strelnikov <strel@google.com> - 93e5b134607a554993387ad913e6c1621606004b Release Charmap microbenchmark. by Alex Strelnikov <strel@google.com> - 95c2e29b6d93ec1334484ee37d91f63101c45307 Release OStringStream microbenchmarks. by Alex Strelnikov <strel@google.com> - 250f51839ed26dd1e6b658d35aa291413e5f4825 Internal change by Greg Falcon <gfalcon@google.com> - ce34900fa3d1a95a8446bc943cdd801fac95be25 Improve compatibility of cctz cc_test targets for portabl... by Shaindel Schwartz <shaindel@google.com> - ce7e31dbf2c1ee93c79aae5b7dc7c603cb4babcf Improve portability of cc_tests. (Mark more tests that ca... by Abseil Team <absl-team@google.com> - dfcd4e455923703c1a1dcd523c5f915f7990fa2a Accept strings with custom allocators as arguments to abs... by Greg Falcon <gfalcon@google.com> - 2946b41ed3d5b8b5a8dc11182e443cf1ab6e3bde Link against benchmark_main instead of using BENCHMARK_MA... by Alex Strelnikov <strel@google.com> - f09de9e03bf8edd363069c4b352d8009423f531c Adds link to doc about the formats allowed by SimpleAtof(... by Greg Miller <jgm@google.com> - 59b0977e7a308e0800277886cf60226b2cc426a1 Simplify the HideMask() calculation so that it doesn't us... by Jorg Brown <jorg@google.com> GitOrigin-RevId: e2f6b8ac647271815b4fed2991f405524dd762c3 Change-Id: Ib9c8547ed7fe217fad6cb3ab1362e96181aa5cfa
-rw-r--r--WORKSPACE12
-rw-r--r--absl/algorithm/BUILD.bazel2
-rw-r--r--absl/algorithm/equal_benchmark.cc2
-rw-r--r--absl/base/BUILD.bazel7
-rw-r--r--absl/base/internal/hide_ptr.h4
-rw-r--r--absl/base/internal/thread_identity_benchmark.cc2
-rw-r--r--absl/container/BUILD.bazel9
-rw-r--r--absl/container/fixed_array_benchmark.cc2
-rw-r--r--absl/container/inlined_vector_benchmark.cc2
-rw-r--r--absl/memory/memory.h4
-rw-r--r--absl/strings/BUILD.bazel41
-rw-r--r--absl/strings/escaping_benchmark.cc6
-rw-r--r--absl/strings/escaping_test.cc4
-rw-r--r--absl/strings/internal/char_map_benchmark.cc61
-rw-r--r--absl/strings/internal/escaping_test_common.h131
-rw-r--r--absl/strings/internal/escaping_test_common.inc113
-rw-r--r--absl/strings/internal/numbers_test_common.h178
-rw-r--r--absl/strings/internal/numbers_test_common.inc156
-rw-r--r--absl/strings/internal/ostringstream_benchmark.cc106
-rw-r--r--absl/strings/numbers.h4
-rw-r--r--absl/strings/numbers_test.cc21
-rw-r--r--absl/strings/str_cat_benchmark.cc2
-rw-r--r--absl/strings/str_join_benchmark.cc2
-rw-r--r--absl/strings/str_replace_benchmark.cc2
-rw-r--r--absl/strings/str_split_benchmark.cc2
-rw-r--r--absl/strings/string_view_benchmark.cc2
-rw-r--r--absl/strings/substitute.h5
-rw-r--r--absl/synchronization/BUILD.bazel4
-rw-r--r--absl/synchronization/internal/graphcycles_benchmark.cc2
-rw-r--r--absl/synchronization/mutex_benchmark.cc2
-rw-r--r--absl/time/BUILD.bazel4
-rw-r--r--absl/time/internal/cctz/BUILD.bazel28
-rw-r--r--absl/time/internal/cctz/src/cctz_benchmark.cc982
-rw-r--r--absl/time/internal/cctz/src/time_zone_format_test.cc9
-rw-r--r--absl/types/BUILD.bazel14
-rw-r--r--absl/types/CMakeLists.txt17
-rw-r--r--absl/types/optional_exception_safety_test.cc284
37 files changed, 1879 insertions, 349 deletions
diff --git a/WORKSPACE b/WORKSPACE
index 06445930..9c950650 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -13,20 +13,20 @@ http_archive(
# GoogleTest/GoogleMock framework. Used by most unit-tests.
http_archive(
name = "com_google_googletest",
- urls = ["https://github.com/google/googletest/archive/master.zip"],
- strip_prefix = "googletest-master",
+ urls = ["https://github.com/google/googletest/archive/4e4df226fc197c0dda6e37f5c8c3845ca1e73a49.zip"],
+ strip_prefix = "googletest-4e4df226fc197c0dda6e37f5c8c3845ca1e73a49",
)
# Google benchmark.
http_archive(
name = "com_github_google_benchmark",
- urls = ["https://github.com/google/benchmark/archive/master.zip"],
- strip_prefix = "benchmark-master",
+ urls = ["https://github.com/google/benchmark/archive/16703ff83c1ae6d53e5155df3bb3ab0bc96083be.zip"],
+ strip_prefix = "benchmark-16703ff83c1ae6d53e5155df3bb3ab0bc96083be",
)
# RE2 regular-expression framework. Used by some unit-tests.
http_archive(
name = "com_googlesource_code_re2",
- urls = ["https://github.com/google/re2/archive/master.zip"],
- strip_prefix = "re2-master",
+ urls = ["https://github.com/google/re2/archive/6cf8ccd82dbaab2668e9b13596c68183c9ecd13f.zip"],
+ strip_prefix = "re2-6cf8ccd82dbaab2668e9b13596c68183c9ecd13f",
)
diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel
index 3b24ce12..d04dc712 100644
--- a/absl/algorithm/BUILD.bazel
+++ b/absl/algorithm/BUILD.bazel
@@ -49,7 +49,7 @@ cc_test(
deps = [
":algorithm",
"//absl/base:core_headers",
- "@com_github_google_benchmark//:benchmark",
+ "@com_github_google_benchmark//:benchmark_main",
],
)
diff --git a/absl/algorithm/equal_benchmark.cc b/absl/algorithm/equal_benchmark.cc
index 9af36ce7..19c0780c 100644
--- a/absl/algorithm/equal_benchmark.cc
+++ b/absl/algorithm/equal_benchmark.cc
@@ -124,5 +124,3 @@ BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, EightBits)
->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
} // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 748f2f9f..1e93d97e 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -392,11 +392,6 @@ cc_test(
"//absl:windows": [],
"//conditions:default": ["-pthread"],
}),
- tags = [
- "no_test_android_arm",
- "no_test_android_arm64",
- "no_test_android_x86",
- ],
deps = [":malloc_internal"],
)
@@ -426,6 +421,6 @@ cc_test(
deps = [
":base",
"//absl/synchronization",
- "@com_github_google_benchmark//:benchmark",
+ "@com_github_google_benchmark//:benchmark_main",
],
)
diff --git a/absl/base/internal/hide_ptr.h b/absl/base/internal/hide_ptr.h
index 2c2e11f6..45cf4389 100644
--- a/absl/base/internal/hide_ptr.h
+++ b/absl/base/internal/hide_ptr.h
@@ -23,9 +23,7 @@ namespace base_internal {
// Arbitrary value with high bits set. Xor'ing with it is unlikely
// to map one valid pointer to another valid pointer.
constexpr uintptr_t HideMask() {
- static_assert(sizeof(uintptr_t) == 4 || sizeof(uintptr_t) == 8,
- "uintptr_t must be 32 or 64 bits");
- return sizeof(uintptr_t) == 8 ? 0xF03A5F7BF03A5F7BULL : 0xF03A5F7BUL;
+ return (uintptr_t{0xF03A5F7BU} << (sizeof(uintptr_t) - 4) * 8) | 0xF03A5F7BU;
}
// Hide a pointer from the leak checker. For internal use only.
diff --git a/absl/base/internal/thread_identity_benchmark.cc b/absl/base/internal/thread_identity_benchmark.cc
index fe22e4cf..242522b4 100644
--- a/absl/base/internal/thread_identity_benchmark.cc
+++ b/absl/base/internal/thread_identity_benchmark.cc
@@ -36,5 +36,3 @@ void BM_UnsafeCurrentThreadIdentity(benchmark::State& state) {
BENCHMARK(BM_UnsafeCurrentThreadIdentity);
} // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index 897be90f..119d5c88 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -42,11 +42,6 @@ cc_test(
name = "fixed_array_test",
srcs = ["fixed_array_test.cc"],
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- tags = [
- "no_test_android_arm",
- "no_test_android_arm64",
- "no_test_android_x86",
- ],
deps = [
":fixed_array",
"//absl/base:exception_testing",
@@ -74,7 +69,7 @@ cc_test(
tags = ["benchmark"],
deps = [
":fixed_array",
- "@com_github_google_benchmark//:benchmark",
+ "@com_github_google_benchmark//:benchmark_main",
],
)
@@ -131,7 +126,7 @@ cc_test(
":inlined_vector",
"//absl/base",
"//absl/strings",
- "@com_github_google_benchmark//:benchmark",
+ "@com_github_google_benchmark//:benchmark_main",
],
)
diff --git a/absl/container/fixed_array_benchmark.cc b/absl/container/fixed_array_benchmark.cc
index 2d39898d..b4f0cf2a 100644
--- a/absl/container/fixed_array_benchmark.cc
+++ b/absl/container/fixed_array_benchmark.cc
@@ -64,5 +64,3 @@ BENCHMARK_TEMPLATE(BM_FixedArray, std::string, 256)->Range(0, 1 << 16);
BENCHMARK_TEMPLATE(BM_FixedArray, std::string, 65536)->Range(0, 1 << 16);
} // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/container/inlined_vector_benchmark.cc b/absl/container/inlined_vector_benchmark.cc
index c6bc5cd9..5977bc93 100644
--- a/absl/container/inlined_vector_benchmark.cc
+++ b/absl/container/inlined_vector_benchmark.cc
@@ -372,5 +372,3 @@ void BM_StdVectorEmpty(benchmark::State& state) {
BENCHMARK(BM_StdVectorEmpty);
} // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/memory/memory.h b/absl/memory/memory.h
index 055d88e0..cd818cff 100644
--- a/absl/memory/memory.h
+++ b/absl/memory/memory.h
@@ -179,9 +179,9 @@ typename memory_internal::MakeUniqueResult<T>::invalid make_unique(
// useful within templates that need to handle a complement of raw pointers,
// `std::nullptr_t`, and smart pointers.
template <typename T>
-auto RawPtr(T&& ptr) -> decltype(&*ptr) {
+auto RawPtr(T&& ptr) -> decltype(std::addressof(*ptr)) {
// ptr is a forwarding reference to support Ts with non-const operators.
- return (ptr != nullptr) ? &*ptr : nullptr;
+ return (ptr != nullptr) ? std::addressof(*ptr) : nullptr;
}
inline std::nullptr_t RawPtr(std::nullptr_t) { return nullptr; }
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index e6bb7ff5..d1c6878c 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -111,7 +111,7 @@ cc_test(
size = "small",
srcs = [
"escaping_test.cc",
- "internal/escaping_test_common.inc",
+ "internal/escaping_test_common.h",
],
copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
@@ -127,7 +127,7 @@ cc_test(
name = "escaping_benchmark",
srcs = [
"escaping_benchmark.cc",
- "internal/escaping_test_common.inc",
+ "internal/escaping_test_common.h",
],
copts = ABSL_TEST_COPTS,
tags = ["benchmark"],
@@ -135,7 +135,7 @@ cc_test(
deps = [
":strings",
"//absl/base",
- "@com_github_google_benchmark//:benchmark",
+ "@com_github_google_benchmark//:benchmark_main",
],
)
@@ -199,7 +199,7 @@ cc_test(
":strings",
"//absl/base",
"//absl/base:core_headers",
- "@com_github_google_benchmark//:benchmark",
+ "@com_github_google_benchmark//:benchmark_main",
],
)
@@ -240,7 +240,7 @@ cc_test(
deps = [
":strings",
"//absl/base",
- "@com_github_google_benchmark//:benchmark",
+ "@com_github_google_benchmark//:benchmark_main",
],
)
@@ -278,7 +278,7 @@ cc_test(
deps = [
":strings",
"//absl/base",
- "@com_github_google_benchmark//:benchmark",
+ "@com_github_google_benchmark//:benchmark_main",
],
)
@@ -295,6 +295,18 @@ cc_test(
)
cc_test(
+ name = "ostringstream_benchmark",
+ srcs = ["internal/ostringstream_benchmark.cc"],
+ copts = ABSL_TEST_COPTS,
+ tags = ["benchmark"],
+ visibility = ["//visibility:private"],
+ deps = [
+ ":internal",
+ "@com_github_google_benchmark//:benchmark_main",
+ ],
+)
+
+cc_test(
name = "resize_uninitialized_test",
size = "small",
srcs = [
@@ -333,7 +345,7 @@ cc_test(
deps = [
":strings",
"//absl/memory",
- "@com_github_google_benchmark//:benchmark",
+ "@com_github_google_benchmark//:benchmark_main",
],
)
@@ -358,7 +370,7 @@ cc_test(
visibility = ["//visibility:private"],
deps = [
":strings",
- "@com_github_google_benchmark//:benchmark",
+ "@com_github_google_benchmark//:benchmark_main",
],
)
@@ -366,7 +378,7 @@ cc_test(
name = "numbers_test",
size = "small",
srcs = [
- "internal/numbers_test_common.inc",
+ "internal/numbers_test_common.h",
"numbers_test.cc",
],
copts = ABSL_TEST_COPTS,
@@ -411,3 +423,14 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
+
+cc_test(
+ name = "char_map_benchmark",
+ srcs = ["internal/char_map_benchmark.cc"],
+ copts = ABSL_TEST_COPTS,
+ tags = ["benchmark"],
+ deps = [
+ ":internal",
+ "@com_github_google_benchmark//:benchmark_main",
+ ],
+)
diff --git a/absl/strings/escaping_benchmark.cc b/absl/strings/escaping_benchmark.cc
index 26ddc2d5..0f791f4e 100644
--- a/absl/strings/escaping_benchmark.cc
+++ b/absl/strings/escaping_benchmark.cc
@@ -20,7 +20,7 @@
#include "benchmark/benchmark.h"
#include "absl/base/internal/raw_logging.h"
-#include "absl/strings/internal/escaping_test_common.inc"
+#include "absl/strings/internal/escaping_test_common.h"
namespace {
@@ -39,7 +39,7 @@ BENCHMARK(BM_CUnescapeHexString);
void BM_WebSafeBase64Escape_string(benchmark::State& state) {
std::string raw;
for (int i = 0; i < 10; ++i) {
- for (const auto& test_set : base64_strings) {
+ for (const auto& test_set : absl::strings_internal::base64_strings()) {
raw += std::string(test_set.plaintext);
}
}
@@ -92,5 +92,3 @@ void BM_CEscape_MostEscaped(benchmark::State& state) {
BENCHMARK(BM_CEscape_MostEscaped)->Range(1, 1 << 14);
} // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/strings/escaping_test.cc b/absl/strings/escaping_test.cc
index 982989b8..3f65ec10 100644
--- a/absl/strings/escaping_test.cc
+++ b/absl/strings/escaping_test.cc
@@ -25,7 +25,7 @@
#include "absl/container/fixed_array.h"
#include "absl/strings/str_cat.h"
-#include "absl/strings/internal/escaping_test_common.inc"
+#include "absl/strings/internal/escaping_test_common.h"
namespace {
@@ -575,7 +575,7 @@ TEST(Base64, EscapeAndUnescape) {
}
// Now try the long strings, this tests the streaming
- for (const auto& tc : base64_strings) {
+ for (const auto& tc : absl::strings_internal::base64_strings()) {
std::string buffer;
absl::WebSafeBase64Escape(tc.plaintext, &buffer);
EXPECT_EQ(tc.cyphertext, buffer);
diff --git a/absl/strings/internal/char_map_benchmark.cc b/absl/strings/internal/char_map_benchmark.cc
new file mode 100644
index 00000000..c45f3157
--- /dev/null
+++ b/absl/strings/internal/char_map_benchmark.cc
@@ -0,0 +1,61 @@
+// Copyright 2017 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
+//
+// http://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/strings/internal/char_map.h"
+
+#include <cstdint>
+
+#include "benchmark/benchmark.h"
+
+namespace {
+
+absl::strings_internal::Charmap MakeBenchmarkMap() {
+ absl::strings_internal::Charmap m;
+ uint32_t x[] = {0x0, 0x1, 0x2, 0x3, 0xf, 0xe, 0xd, 0xc};
+ for (uint32_t& t : x) t *= static_cast<uint32_t>(0x11111111UL);
+ for (uint32_t i = 0; i < 256; ++i) {
+ if ((x[i / 32] >> (i % 32)) & 1)
+ m = m | absl::strings_internal::Charmap::Char(i);
+ }
+ return m;
+}
+
+// Micro-benchmark for Charmap::contains.
+void BM_Contains(benchmark::State& state) {
+ // Loop-body replicated 10 times to increase time per iteration.
+ // Argument continuously changed to avoid generating common subexpressions.
+ const absl::strings_internal::Charmap benchmark_map = MakeBenchmarkMap();
+ unsigned char c = 0;
+ int ops = 0;
+ for (auto _ : state) {
+ ops += benchmark_map.contains(c++);
+ ops += benchmark_map.contains(c++);
+ ops += benchmark_map.contains(c++);
+ ops += benchmark_map.contains(c++);
+ ops += benchmark_map.contains(c++);
+ ops += benchmark_map.contains(c++);
+ ops += benchmark_map.contains(c++);
+ ops += benchmark_map.contains(c++);
+ ops += benchmark_map.contains(c++);
+ ops += benchmark_map.contains(c++);
+ }
+ benchmark::DoNotOptimize(ops);
+}
+BENCHMARK(BM_Contains);
+
+// We don't bother benchmarking Charmap::IsZero or Charmap::IntersectsWith;
+// their running time is data-dependent and it is not worth characterizing
+// "typical" data.
+
+} // namespace
diff --git a/absl/strings/internal/escaping_test_common.h b/absl/strings/internal/escaping_test_common.h
new file mode 100644
index 00000000..cc41f431
--- /dev/null
+++ b/absl/strings/internal/escaping_test_common.h
@@ -0,0 +1,131 @@
+// Copyright 2017 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
+//
+// http://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.
+//
+// This test contains common things needed by both escaping_test.cc and
+// escaping_benchmark.cc.
+
+#ifndef ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
+#define ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
+
+#include <array>
+#include "absl/strings/string_view.h"
+
+namespace absl {
+namespace strings_internal {
+
+struct base64_testcase {
+ absl::string_view plaintext;
+ absl::string_view cyphertext;
+};
+
+inline const std::array<base64_testcase, 5>& base64_strings() {
+ static const std::array<base64_testcase, 5> testcase{{
+ // Some google quotes
+ // Cyphertext created with "uuencode (GNU sharutils) 4.6.3"
+ // (Note that we're testing the websafe encoding, though, so if
+ // you add messages, be sure to run "tr -- '+/' '-_'" on the output)
+ { "I was always good at math and science, and I never realized "
+ "that was unusual or somehow undesirable. So one of the things "
+ "I care a lot about is helping to remove that stigma, "
+ "to show girls that you can be feminine, you can like the things "
+ "that girls like, but you can also be really good at technology. "
+ "You can be really good at building things."
+ " - Marissa Meyer, Newsweek, 2010-12-22" "\n",
+
+ "SSB3YXMgYWx3YXlzIGdvb2QgYXQgbWF0aCBhbmQgc2NpZW5jZSwgYW5kIEkg"
+ "bmV2ZXIgcmVhbGl6ZWQgdGhhdCB3YXMgdW51c3VhbCBvciBzb21laG93IHVu"
+ "ZGVzaXJhYmxlLiBTbyBvbmUgb2YgdGhlIHRoaW5ncyBJIGNhcmUgYSBsb3Qg"
+ "YWJvdXQgaXMgaGVscGluZyB0byByZW1vdmUgdGhhdCBzdGlnbWEsIHRvIHNo"
+ "b3cgZ2lybHMgdGhhdCB5b3UgY2FuIGJlIGZlbWluaW5lLCB5b3UgY2FuIGxp"
+ "a2UgdGhlIHRoaW5ncyB0aGF0IGdpcmxzIGxpa2UsIGJ1dCB5b3UgY2FuIGFs"
+ "c28gYmUgcmVhbGx5IGdvb2QgYXQgdGVjaG5vbG9neS4gWW91IGNhbiBiZSBy"
+ "ZWFsbHkgZ29vZCBhdCBidWlsZGluZyB0aGluZ3MuIC0gTWFyaXNzYSBNZXll"
+ "ciwgTmV3c3dlZWssIDIwMTAtMTItMjIK" },
+
+ { "Typical first year for a new cluster: "
+ "~0.5 overheating "
+ "~1 PDU failure "
+ "~1 rack-move "
+ "~1 network rewiring "
+ "~20 rack failures "
+ "~5 racks go wonky "
+ "~8 network maintenances "
+ "~12 router reloads "
+ "~3 router failures "
+ "~dozens of minor 30-second blips for dns "
+ "~1000 individual machine failures "
+ "~thousands of hard drive failures "
+ "slow disks, bad memory, misconfigured machines, flaky machines, etc."
+ " - Jeff Dean, The Joys of Real Hardware" "\n",
+
+ "VHlwaWNhbCBmaXJzdCB5ZWFyIGZvciBhIG5ldyBjbHVzdGVyOiB-MC41IG92"
+ "ZXJoZWF0aW5nIH4xIFBEVSBmYWlsdXJlIH4xIHJhY2stbW92ZSB-MSBuZXR3"
+ "b3JrIHJld2lyaW5nIH4yMCByYWNrIGZhaWx1cmVzIH41IHJhY2tzIGdvIHdv"
+ "bmt5IH44IG5ldHdvcmsgbWFpbnRlbmFuY2VzIH4xMiByb3V0ZXIgcmVsb2Fk"
+ "cyB-MyByb3V0ZXIgZmFpbHVyZXMgfmRvemVucyBvZiBtaW5vciAzMC1zZWNv"
+ "bmQgYmxpcHMgZm9yIGRucyB-MTAwMCBpbmRpdmlkdWFsIG1hY2hpbmUgZmFp"
+ "bHVyZXMgfnRob3VzYW5kcyBvZiBoYXJkIGRyaXZlIGZhaWx1cmVzIHNsb3cg"
+ "ZGlza3MsIGJhZCBtZW1vcnksIG1pc2NvbmZpZ3VyZWQgbWFjaGluZXMsIGZs"
+ "YWt5IG1hY2hpbmVzLCBldGMuIC0gSmVmZiBEZWFuLCBUaGUgSm95cyBvZiBS"
+ "ZWFsIEhhcmR3YXJlCg" },
+
+ { "I'm the head of the webspam team at Google. "
+ "That means that if you type your name into Google and get porn back, "
+ "it's my fault. Unless you're a porn star, in which case porn is a "
+ "completely reasonable response."
+ " - Matt Cutts, Google Plus" "\n",
+
+ "SSdtIHRoZSBoZWFkIG9mIHRoZSB3ZWJzcGFtIHRlYW0gYXQgR29vZ2xlLiAg"
+ "VGhhdCBtZWFucyB0aGF0IGlmIHlvdSB0eXBlIHlvdXIgbmFtZSBpbnRvIEdv"
+ "b2dsZSBhbmQgZ2V0IHBvcm4gYmFjaywgaXQncyBteSBmYXVsdC4gVW5sZXNz"
+ "IHlvdSdyZSBhIHBvcm4gc3RhciwgaW4gd2hpY2ggY2FzZSBwb3JuIGlzIGEg"
+ "Y29tcGxldGVseSByZWFzb25hYmxlIHJlc3BvbnNlLiAtIE1hdHQgQ3V0dHMs"
+ "IEdvb2dsZSBQbHVzCg" },
+
+ { "It will still be a long time before machines approach human "
+ "intelligence. "
+ "But luckily, machines don't actually have to be intelligent; "
+ "they just have to fake it. Access to a wealth of information, "
+ "combined with a rudimentary decision-making capacity, "
+ "can often be almost as useful. Of course, the results are better yet "
+ "when coupled with intelligence. A reference librarian with access to "
+ "a good search engine is a formidable tool."
+ " - Craig Silverstein, Siemens Pictures of the Future, Spring 2004"
+ "\n",
+
+ "SXQgd2lsbCBzdGlsbCBiZSBhIGxvbmcgdGltZSBiZWZvcmUgbWFjaGluZXMg"
+ "YXBwcm9hY2ggaHVtYW4gaW50ZWxsaWdlbmNlLiBCdXQgbHVja2lseSwgbWFj"
+ "aGluZXMgZG9uJ3QgYWN0dWFsbHkgaGF2ZSB0byBiZSBpbnRlbGxpZ2VudDsg"
+ "dGhleSBqdXN0IGhhdmUgdG8gZmFrZSBpdC4gQWNjZXNzIHRvIGEgd2VhbHRo"
+ "IG9mIGluZm9ybWF0aW9uLCBjb21iaW5lZCB3aXRoIGEgcnVkaW1lbnRhcnkg"
+ "ZGVjaXNpb24tbWFraW5nIGNhcGFjaXR5LCBjYW4gb2Z0ZW4gYmUgYWxtb3N0"
+ "IGFzIHVzZWZ1bC4gT2YgY291cnNlLCB0aGUgcmVzdWx0cyBhcmUgYmV0dGVy"
+ "IHlldCB3aGVuIGNvdXBsZWQgd2l0aCBpbnRlbGxpZ2VuY2UuIEEgcmVmZXJl"
+ "bmNlIGxpYnJhcmlhbiB3aXRoIGFjY2VzcyB0byBhIGdvb2Qgc2VhcmNoIGVu"
+ "Z2luZSBpcyBhIGZvcm1pZGFibGUgdG9vbC4gLSBDcmFpZyBTaWx2ZXJzdGVp"
+ "biwgU2llbWVucyBQaWN0dXJlcyBvZiB0aGUgRnV0dXJlLCBTcHJpbmcgMjAw"
+ "NAo" },
+
+ // Degenerate edge case
+ { "",
+ "" },
+ }};
+
+ return testcase;
+}
+
+} // namespace strings_internal
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
diff --git a/absl/strings/internal/escaping_test_common.inc b/absl/strings/internal/escaping_test_common.inc
deleted file mode 100644
index 6f29140e..00000000
--- a/absl/strings/internal/escaping_test_common.inc
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2017 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
-//
-// http://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.
-//
-// This test contains common things needed by both escaping_test.cc and
-// escaping_benchmark.cc.
-
-namespace {
-
-struct {
- absl::string_view plaintext;
- absl::string_view cyphertext;
-} const base64_strings[] = {
- // Some google quotes
- // Cyphertext created with "uuencode (GNU sharutils) 4.6.3"
- // (Note that we're testing the websafe encoding, though, so if
- // you add messages, be sure to run "tr -- '+/' '-_'" on the output)
- { "I was always good at math and science, and I never realized "
- "that was unusual or somehow undesirable. So one of the things "
- "I care a lot about is helping to remove that stigma, "
- "to show girls that you can be feminine, you can like the things "
- "that girls like, but you can also be really good at technology. "
- "You can be really good at building things."
- " - Marissa Meyer, Newsweek, 2010-12-22" "\n",
-
- "SSB3YXMgYWx3YXlzIGdvb2QgYXQgbWF0aCBhbmQgc2NpZW5jZSwgYW5kIEkg"
- "bmV2ZXIgcmVhbGl6ZWQgdGhhdCB3YXMgdW51c3VhbCBvciBzb21laG93IHVu"
- "ZGVzaXJhYmxlLiBTbyBvbmUgb2YgdGhlIHRoaW5ncyBJIGNhcmUgYSBsb3Qg"
- "YWJvdXQgaXMgaGVscGluZyB0byByZW1vdmUgdGhhdCBzdGlnbWEsIHRvIHNo"
- "b3cgZ2lybHMgdGhhdCB5b3UgY2FuIGJlIGZlbWluaW5lLCB5b3UgY2FuIGxp"
- "a2UgdGhlIHRoaW5ncyB0aGF0IGdpcmxzIGxpa2UsIGJ1dCB5b3UgY2FuIGFs"
- "c28gYmUgcmVhbGx5IGdvb2QgYXQgdGVjaG5vbG9neS4gWW91IGNhbiBiZSBy"
- "ZWFsbHkgZ29vZCBhdCBidWlsZGluZyB0aGluZ3MuIC0gTWFyaXNzYSBNZXll"
- "ciwgTmV3c3dlZWssIDIwMTAtMTItMjIK" },
-
- { "Typical first year for a new cluster: "
- "~0.5 overheating "
- "~1 PDU failure "
- "~1 rack-move "
- "~1 network rewiring "
- "~20 rack failures "
- "~5 racks go wonky "
- "~8 network maintenances "
- "~12 router reloads "
- "~3 router failures "
- "~dozens of minor 30-second blips for dns "
- "~1000 individual machine failures "
- "~thousands of hard drive failures "
- "slow disks, bad memory, misconfigured machines, flaky machines, etc."
- " - Jeff Dean, The Joys of Real Hardware" "\n",
-
- "VHlwaWNhbCBmaXJzdCB5ZWFyIGZvciBhIG5ldyBjbHVzdGVyOiB-MC41IG92"
- "ZXJoZWF0aW5nIH4xIFBEVSBmYWlsdXJlIH4xIHJhY2stbW92ZSB-MSBuZXR3"
- "b3JrIHJld2lyaW5nIH4yMCByYWNrIGZhaWx1cmVzIH41IHJhY2tzIGdvIHdv"
- "bmt5IH44IG5ldHdvcmsgbWFpbnRlbmFuY2VzIH4xMiByb3V0ZXIgcmVsb2Fk"
- "cyB-MyByb3V0ZXIgZmFpbHVyZXMgfmRvemVucyBvZiBtaW5vciAzMC1zZWNv"
- "bmQgYmxpcHMgZm9yIGRucyB-MTAwMCBpbmRpdmlkdWFsIG1hY2hpbmUgZmFp"
- "bHVyZXMgfnRob3VzYW5kcyBvZiBoYXJkIGRyaXZlIGZhaWx1cmVzIHNsb3cg"
- "ZGlza3MsIGJhZCBtZW1vcnksIG1pc2NvbmZpZ3VyZWQgbWFjaGluZXMsIGZs"
- "YWt5IG1hY2hpbmVzLCBldGMuIC0gSmVmZiBEZWFuLCBUaGUgSm95cyBvZiBS"
- "ZWFsIEhhcmR3YXJlCg" },
-
- { "I'm the head of the webspam team at Google. "
- "That means that if you type your name into Google and get porn back, "
- "it's my fault. Unless you're a porn star, in which case porn is a "
- "completely reasonable response."
- " - Matt Cutts, Google Plus" "\n",
-
- "SSdtIHRoZSBoZWFkIG9mIHRoZSB3ZWJzcGFtIHRlYW0gYXQgR29vZ2xlLiAg"
- "VGhhdCBtZWFucyB0aGF0IGlmIHlvdSB0eXBlIHlvdXIgbmFtZSBpbnRvIEdv"
- "b2dsZSBhbmQgZ2V0IHBvcm4gYmFjaywgaXQncyBteSBmYXVsdC4gVW5sZXNz"
- "IHlvdSdyZSBhIHBvcm4gc3RhciwgaW4gd2hpY2ggY2FzZSBwb3JuIGlzIGEg"
- "Y29tcGxldGVseSByZWFzb25hYmxlIHJlc3BvbnNlLiAtIE1hdHQgQ3V0dHMs"
- "IEdvb2dsZSBQbHVzCg" },
-
- { "It will still be a long time before machines approach human intelligence. "
- "But luckily, machines don't actually have to be intelligent; "
- "they just have to fake it. Access to a wealth of information, "
- "combined with a rudimentary decision-making capacity, "
- "can often be almost as useful. Of course, the results are better yet "
- "when coupled with intelligence. A reference librarian with access to "
- "a good search engine is a formidable tool."
- " - Craig Silverstein, Siemens Pictures of the Future, Spring 2004" "\n",
-
- "SXQgd2lsbCBzdGlsbCBiZSBhIGxvbmcgdGltZSBiZWZvcmUgbWFjaGluZXMg"
- "YXBwcm9hY2ggaHVtYW4gaW50ZWxsaWdlbmNlLiBCdXQgbHVja2lseSwgbWFj"
- "aGluZXMgZG9uJ3QgYWN0dWFsbHkgaGF2ZSB0byBiZSBpbnRlbGxpZ2VudDsg"
- "dGhleSBqdXN0IGhhdmUgdG8gZmFrZSBpdC4gQWNjZXNzIHRvIGEgd2VhbHRo"
- "IG9mIGluZm9ybWF0aW9uLCBjb21iaW5lZCB3aXRoIGEgcnVkaW1lbnRhcnkg"
- "ZGVjaXNpb24tbWFraW5nIGNhcGFjaXR5LCBjYW4gb2Z0ZW4gYmUgYWxtb3N0"
- "IGFzIHVzZWZ1bC4gT2YgY291cnNlLCB0aGUgcmVzdWx0cyBhcmUgYmV0dGVy"
- "IHlldCB3aGVuIGNvdXBsZWQgd2l0aCBpbnRlbGxpZ2VuY2UuIEEgcmVmZXJl"
- "bmNlIGxpYnJhcmlhbiB3aXRoIGFjY2VzcyB0byBhIGdvb2Qgc2VhcmNoIGVu"
- "Z2luZSBpcyBhIGZvcm1pZGFibGUgdG9vbC4gLSBDcmFpZyBTaWx2ZXJzdGVp"
- "biwgU2llbWVucyBQaWN0dXJlcyBvZiB0aGUgRnV0dXJlLCBTcHJpbmcgMjAw"
- "NAo" },
-
- // Degenerate edge case
- { "",
- "" },
-};
-
-} // namespace
diff --git a/absl/strings/internal/numbers_test_common.h b/absl/strings/internal/numbers_test_common.h
new file mode 100644
index 00000000..20e3af51
--- /dev/null
+++ b/absl/strings/internal/numbers_test_common.h
@@ -0,0 +1,178 @@
+// Copyright 2017 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
+//
+// http://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.
+//
+// This file contains common things needed by numbers_test.cc,
+// numbers_legacy_test.cc and numbers_benchmark.cc.
+
+#ifndef ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
+#define ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
+
+#include <array>
+#include <cstdint>
+#include <limits>
+#include <string>
+
+namespace absl {
+namespace strings_internal {
+
+template <typename IntType>
+inline bool Itoa(IntType value, int base, std::string* destination) {
+ destination->clear();
+ if (base <= 1 || base > 36) {
+ return false;
+ }
+
+ if (value == 0) {
+ destination->push_back('0');
+ return true;
+ }
+
+ bool negative = value < 0;
+ while (value != 0) {
+ const IntType next_value = value / base;
+ // Can't use std::abs here because of problems when IntType is unsigned.
+ int remainder = value > next_value * base ? value - next_value * base
+ : next_value * base - value;
+ char c = remainder < 10 ? '0' + remainder : 'A' + remainder - 10;
+ destination->insert(0, 1, c);
+ value = next_value;
+ }
+
+ if (negative) {
+ destination->insert(0, 1, '-');
+ }
+ return true;
+}
+
+struct uint32_test_case {
+ const char* str;
+ bool expect_ok;
+ int base; // base to pass to the conversion function
+ uint32_t expected;
+};
+
+inline const std::array<uint32_test_case, 27>& strtouint32_test_cases() {
+ static const std::array<uint32_test_case, 27> test_cases{{
+ {"0xffffffff", true, 16, std::numeric_limits<uint32_t>::max()},
+ {"0x34234324", true, 16, 0x34234324},
+ {"34234324", true, 16, 0x34234324},
+ {"0", true, 16, 0},
+ {" \t\n 0xffffffff", true, 16, std::numeric_limits<uint32_t>::max()},
+ {" \f\v 46", true, 10, 46}, // must accept weird whitespace
+ {" \t\n 72717222", true, 8, 072717222},
+ {" \t\n 072717222", true, 8, 072717222},
+ {" \t\n 072717228", false, 8, 07271722},
+ {"0", true, 0, 0},
+
+ // Base-10 version.
+ {"34234324", true, 0, 34234324},
+ {"4294967295", true, 0, std::numeric_limits<uint32_t>::max()},
+ {"34234324 \n\t", true, 10, 34234324},
+
+ // Unusual base
+ {"0", true, 3, 0},
+ {"2", true, 3, 2},
+ {"11", true, 3, 4},
+
+ // Invalid uints.
+ {"", false, 0, 0},
+ {" ", false, 0, 0},
+ {"abc", false, 0, 0}, // would be valid hex, but prefix is missing
+ {"34234324a", false, 0, 34234324},
+ {"34234.3", false, 0, 34234},
+ {"-1", false, 0, 0},
+ {" -123", false, 0, 0},
+ {" \t\n -123", false, 0, 0},
+
+ // Out of bounds.
+ {"4294967296", false, 0, std::numeric_limits<uint32_t>::max()},
+ {"0x100000000", false, 0, std::numeric_limits<uint32_t>::max()},
+ {nullptr, false, 0, 0},
+ }};
+ return test_cases;
+}
+
+struct uint64_test_case {
+ const char* str;
+ bool expect_ok;
+ int base;
+ uint64_t expected;
+};
+
+inline const std::array<uint64_test_case, 34>& strtouint64_test_cases() {
+ static const std::array<uint64_test_case, 34> test_cases{{
+ {"0x3423432448783446", true, 16, int64_t{0x3423432448783446}},
+ {"3423432448783446", true, 16, int64_t{0x3423432448783446}},
+
+ {"0", true, 16, 0},
+ {"000", true, 0, 0},
+ {"0", true, 0, 0},
+ {" \t\n 0xffffffffffffffff", true, 16,
+ std::numeric_limits<uint64_t>::max()},
+
+ {"012345670123456701234", true, 8, int64_t{012345670123456701234}},
+ {"12345670123456701234", true, 8, int64_t{012345670123456701234}},
+
+ {"12845670123456701234", false, 8, 0},
+
+ // Base-10 version.
+ {"34234324487834466", true, 0, int64_t{34234324487834466}},
+
+ {" \t\n 18446744073709551615", true, 0,
+ std::numeric_limits<uint64_t>::max()},
+
+ {"34234324487834466 \n\t ", true, 0, int64_t{34234324487834466}},
+
+ {" \f\v 46", true, 10, 46}, // must accept weird whitespace
+
+ // Unusual base
+ {"0", true, 3, 0},
+ {"2", true, 3, 2},
+ {"11", true, 3, 4},
+
+ {"0", true, 0, 0},
+
+ // Invalid uints.
+ {"", false, 0, 0},
+ {" ", false, 0, 0},
+ {"abc", false, 0, 0},
+ {"34234324487834466a", false, 0, 0},
+ {"34234487834466.3", false, 0, 0},
+ {"-1", false, 0, 0},
+ {" -123", false, 0, 0},
+ {" \t\n -123", false, 0, 0},
+
+ // Out of bounds.
+ {"18446744073709551616", false, 10, 0},
+ {"18446744073709551616", false, 0, 0},
+ {"0x10000000000000000", false, 16, std::numeric_limits<uint64_t>::max()},
+ {"0X10000000000000000", false, 16,
+ std::numeric_limits<uint64_t>::max()}, // 0X versus 0x.
+ {"0x10000000000000000", false, 0, std::numeric_limits<uint64_t>::max()},
+ {"0X10000000000000000", false, 0,
+ std::numeric_limits<uint64_t>::max()}, // 0X versus 0x.
+
+ {"0x1234", true, 16, 0x1234},
+
+ // Base-10 std::string version.
+ {"1234", true, 0, 1234},
+ {nullptr, false, 0, 0},
+ }};
+ return test_cases;
+}
+
+} // namespace strings_internal
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
diff --git a/absl/strings/internal/numbers_test_common.inc b/absl/strings/internal/numbers_test_common.inc
deleted file mode 100644
index 81d2a1b7..00000000
--- a/absl/strings/internal/numbers_test_common.inc
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2017 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
-//
-// http://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.
-//
-// This file contains common things needed by numbers_test.cc,
-// numbers_legacy_test.cc and numbers_benchmark.cc.
-
-namespace {
-
-template <typename IntType>
-bool Itoa(IntType value, int base, std::string* destination) {
- destination->clear();
- if (base <= 1 || base > 36) {
- return false;
- }
-
- if (value == 0) {
- destination->push_back('0');
- return true;
- }
-
- bool negative = value < 0;
- while (value != 0) {
- const IntType next_value = value / base;
- // Can't use std::abs here because of problems when IntType is unsigned.
- int remainder = value > next_value * base ? value - next_value * base
- : next_value * base - value;
- char c = remainder < 10 ? '0' + remainder : 'A' + remainder - 10;
- destination->insert(0, 1, c);
- value = next_value;
- }
-
- if (negative) {
- destination->insert(0, 1, '-');
- }
- return true;
-}
-
-struct uint32_test_case {
- const char* str;
- bool expect_ok;
- int base; // base to pass to the conversion function
- uint32_t expected;
-} const strtouint32_test_cases[] = {
- {"0xffffffff", true, 16, std::numeric_limits<uint32_t>::max()},
- {"0x34234324", true, 16, 0x34234324},
- {"34234324", true, 16, 0x34234324},
- {"0", true, 16, 0},
- {" \t\n 0xffffffff", true, 16, std::numeric_limits<uint32_t>::max()},
- {" \f\v 46", true, 10, 46}, // must accept weird whitespace
- {" \t\n 72717222", true, 8, 072717222},
- {" \t\n 072717222", true, 8, 072717222},
- {" \t\n 072717228", false, 8, 07271722},
- {"0", true, 0, 0},
-
- // Base-10 version.
- {"34234324", true, 0, 34234324},
- {"4294967295", true, 0, std::numeric_limits<uint32_t>::max()},
- {"34234324 \n\t", true, 10, 34234324},
-
- // Unusual base
- {"0", true, 3, 0},
- {"2", true, 3, 2},
- {"11", true, 3, 4},
-
- // Invalid uints.
- {"", false, 0, 0},
- {" ", false, 0, 0},
- {"abc", false, 0, 0}, // would be valid hex, but prefix is missing
- {"34234324a", false, 0, 34234324},
- {"34234.3", false, 0, 34234},
- {"-1", false, 0, 0},
- {" -123", false, 0, 0},
- {" \t\n -123", false, 0, 0},
-
- // Out of bounds.
- {"4294967296", false, 0, std::numeric_limits<uint32_t>::max()},
- {"0x100000000", false, 0, std::numeric_limits<uint32_t>::max()},
- {nullptr, false, 0, 0},
-};
-
-struct uint64_test_case {
- const char* str;
- bool expect_ok;
- int base;
- uint64_t expected;
-} const strtouint64_test_cases[] = {
- {"0x3423432448783446", true, 16, int64_t{0x3423432448783446}},
- {"3423432448783446", true, 16, int64_t{0x3423432448783446}},
-
- {"0", true, 16, 0},
- {"000", true, 0, 0},
- {"0", true, 0, 0},
- {" \t\n 0xffffffffffffffff", true, 16,
- std::numeric_limits<uint64_t>::max()},
-
- {"012345670123456701234", true, 8, int64_t{012345670123456701234}},
- {"12345670123456701234", true, 8, int64_t{012345670123456701234}},
-
- {"12845670123456701234", false, 8, 0},
-
- // Base-10 version.
- {"34234324487834466", true, 0, int64_t{34234324487834466}},
-
- {" \t\n 18446744073709551615", true, 0,
- std::numeric_limits<uint64_t>::max()},
-
- {"34234324487834466 \n\t ", true, 0, int64_t{34234324487834466}},
-
- {" \f\v 46", true, 10, 46}, // must accept weird whitespace
-
- // Unusual base
- {"0", true, 3, 0},
- {"2", true, 3, 2},
- {"11", true, 3, 4},
-
- {"0", true, 0, 0},
-
- // Invalid uints.
- {"", false, 0, 0},
- {" ", false, 0, 0},
- {"abc", false, 0, 0},
- {"34234324487834466a", false, 0, 0},
- {"34234487834466.3", false, 0, 0},
- {"-1", false, 0, 0},
- {" -123", false, 0, 0},
- {" \t\n -123", false, 0, 0},
-
- // Out of bounds.
- {"18446744073709551616", false, 10, 0},
- {"18446744073709551616", false, 0, 0},
- {"0x10000000000000000", false, 16, std::numeric_limits<uint64_t>::max()},
- {"0X10000000000000000", false, 16,
- std::numeric_limits<uint64_t>::max()}, // 0X versus 0x.
- {"0x10000000000000000", false, 0, std::numeric_limits<uint64_t>::max()},
- {"0X10000000000000000", false, 0,
- std::numeric_limits<uint64_t>::max()}, // 0X versus 0x.
-
- {"0x1234", true, 16, 0x1234},
-
- // Base-10 std::string version.
- {"1234", true, 0, 1234},
- {nullptr, false, 0, 0},
-};
-
-} // namespace
diff --git a/absl/strings/internal/ostringstream_benchmark.cc b/absl/strings/internal/ostringstream_benchmark.cc
new file mode 100644
index 00000000..c93f9690
--- /dev/null
+++ b/absl/strings/internal/ostringstream_benchmark.cc
@@ -0,0 +1,106 @@
+// 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
+//
+// http://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/strings/internal/ostringstream.h"
+
+#include <sstream>
+#include <string>
+
+#include "benchmark/benchmark.h"
+
+namespace {
+
+enum StringType {
+ kNone,
+ kStdString,
+};
+
+// Benchmarks for std::ostringstream.
+template <StringType kOutput>
+void BM_StdStream(benchmark::State& state) {
+ const int num_writes = state.range(0);
+ const int bytes_per_write = state.range(1);
+ const std::string payload(bytes_per_write, 'x');
+ for (auto _ : state) {
+ std::ostringstream strm;
+ benchmark::DoNotOptimize(strm);
+ for (int i = 0; i != num_writes; ++i) {
+ strm << payload;
+ }
+ switch (kOutput) {
+ case kNone: {
+ break;
+ }
+ case kStdString: {
+ std::string s = strm.str();
+ benchmark::DoNotOptimize(s);
+ break;
+ }
+ }
+ }
+}
+
+// Create the stream, optionally write to it, then destroy it.
+BENCHMARK_TEMPLATE(BM_StdStream, kNone)
+ ->ArgPair(0, 0)
+ ->ArgPair(1, 16) // 16 bytes is small enough for SSO
+ ->ArgPair(1, 256) // 256 bytes requires heap allocation
+ ->ArgPair(1024, 256);
+// Create the stream, write to it, get std::string out, then destroy.
+BENCHMARK_TEMPLATE(BM_StdStream, kStdString)
+ ->ArgPair(1, 16) // 16 bytes is small enough for SSO
+ ->ArgPair(1, 256) // 256 bytes requires heap allocation
+ ->ArgPair(1024, 256);
+
+// Benchmarks for OStringStream.
+template <StringType kOutput>
+void BM_CustomStream(benchmark::State& state) {
+ const int num_writes = state.range(0);
+ const int bytes_per_write = state.range(1);
+ const std::string payload(bytes_per_write, 'x');
+ for (auto _ : state) {
+ std::string out;
+ absl::strings_internal::OStringStream strm(&out);
+ benchmark::DoNotOptimize(strm);
+ for (int i = 0; i != num_writes; ++i) {
+ strm << payload;
+ }
+ switch (kOutput) {
+ case kNone: {
+ break;
+ }
+ case kStdString: {
+ std::string s = out;
+ benchmark::DoNotOptimize(s);
+ break;
+ }
+ }
+ }
+}
+
+// Create the stream, optionally write to it, then destroy it.
+BENCHMARK_TEMPLATE(BM_CustomStream, kNone)
+ ->ArgPair(0, 0)
+ ->ArgPair(1, 16) // 16 bytes is small enough for SSO
+ ->ArgPair(1, 256) // 256 bytes requires heap allocation
+ ->ArgPair(1024, 256);
+// Create the stream, write to it, get std::string out, then destroy.
+// It's not useful in practice to extract std::string from OStringStream; we
+// measure it for completeness.
+BENCHMARK_TEMPLATE(BM_CustomStream, kStdString)
+ ->ArgPair(1, 16) // 16 bytes is small enough for SSO
+ ->ArgPair(1, 256) // 256 bytes requires heap allocation
+ ->ArgPair(1024, 256);
+
+} // namespace
diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h
index 75925e61..cf3c5972 100644
--- a/absl/strings/numbers.h
+++ b/absl/strings/numbers.h
@@ -52,12 +52,16 @@ ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view s, int_type* out);
//
// Converts the given std::string (optionally followed or preceded by ASCII
// whitespace) into a float, which may be rounded on overflow or underflow.
+// See http://en.cppreference.com/w/c/std::string/byte/strtof for details about the
+// allowed formats for `str`.
ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* value);
// SimpleAtod()
//
// Converts the given std::string (optionally followed or preceded by ASCII
// whitespace) into a double, which may be rounded on overflow or underflow.
+// See http://en.cppreference.com/w/c/std::string/byte/strtof for details about the
+// allowed formats for `str`.
ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* value);
// SimpleAtob()
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index e372eea1..24e7138c 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -38,7 +38,7 @@
#include "absl/base/internal/raw_logging.h"
#include "absl/strings/str_cat.h"
-#include "absl/strings/internal/numbers_test_common.inc"
+#include "absl/strings/internal/numbers_test_common.h"
namespace {
@@ -48,6 +48,9 @@ using absl::numbers_internal::safe_strto64_base;
using absl::numbers_internal::safe_strtou32_base;
using absl::numbers_internal::safe_strtou64_base;
using absl::numbers_internal::SixDigitsToBuffer;
+using absl::strings_internal::Itoa;
+using absl::strings_internal::strtouint32_test_cases;
+using absl::strings_internal::strtouint64_test_cases;
using absl::SimpleAtoi;
using testing::Eq;
using testing::MatchesRegex;
@@ -654,8 +657,8 @@ TEST(stringtest, safe_strtou64_random) {
}
TEST(stringtest, safe_strtou32_base) {
- for (int i = 0; strtouint32_test_cases[i].str != nullptr; ++i) {
- const auto& e = strtouint32_test_cases[i];
+ for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
+ const auto& e = strtouint32_test_cases()[i];
uint32_t value;
EXPECT_EQ(e.expect_ok, safe_strtou32_base(e.str, &value, e.base))
<< "str=\"" << e.str << "\" base=" << e.base;
@@ -667,8 +670,8 @@ TEST(stringtest, safe_strtou32_base) {
}
TEST(stringtest, safe_strtou32_base_length_delimited) {
- for (int i = 0; strtouint32_test_cases[i].str != nullptr; ++i) {
- const auto& e = strtouint32_test_cases[i];
+ for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
+ const auto& e = strtouint32_test_cases()[i];
std::string tmp(e.str);
tmp.append("12"); // Adds garbage at the end.
@@ -685,8 +688,8 @@ TEST(stringtest, safe_strtou32_base_length_delimited) {
}
TEST(stringtest, safe_strtou64_base) {
- for (int i = 0; strtouint64_test_cases[i].str != nullptr; ++i) {
- const auto& e = strtouint64_test_cases[i];
+ for (int i = 0; strtouint64_test_cases()[i].str != nullptr; ++i) {
+ const auto& e = strtouint64_test_cases()[i];
uint64_t value;
EXPECT_EQ(e.expect_ok, safe_strtou64_base(e.str, &value, e.base))
<< "str=\"" << e.str << "\" base=" << e.base;
@@ -697,8 +700,8 @@ TEST(stringtest, safe_strtou64_base) {
}
TEST(stringtest, safe_strtou64_base_length_delimited) {
- for (int i = 0; strtouint64_test_cases[i].str != nullptr; ++i) {
- const auto& e = strtouint64_test_cases[i];
+ for (int i = 0; strtouint64_test_cases()[i].str != nullptr; ++i) {
+ const auto& e = strtouint64_test_cases()[i];
std::string tmp(e.str);
tmp.append("12"); // Adds garbage at the end.
diff --git a/absl/strings/str_cat_benchmark.cc b/absl/strings/str_cat_benchmark.cc
index 1791410c..b6df9e30 100644
--- a/absl/strings/str_cat_benchmark.cc
+++ b/absl/strings/str_cat_benchmark.cc
@@ -138,5 +138,3 @@ void BM_DoubleToString_By_SixDigits(benchmark::State& state) {
BENCHMARK(BM_DoubleToString_By_SixDigits);
} // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/strings/str_join_benchmark.cc b/absl/strings/str_join_benchmark.cc
index 79cad5e3..7fb0e497 100644
--- a/absl/strings/str_join_benchmark.cc
+++ b/absl/strings/str_join_benchmark.cc
@@ -94,5 +94,3 @@ BENCHMARK(BM_JoinStreamable)
->ArgPair(256, 256);
} // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/strings/str_replace_benchmark.cc b/absl/strings/str_replace_benchmark.cc
index 9dd72eb6..e608de8d 100644
--- a/absl/strings/str_replace_benchmark.cc
+++ b/absl/strings/str_replace_benchmark.cc
@@ -120,5 +120,3 @@ void BM_StrReplaceAll(benchmark::State& state) {
BENCHMARK(BM_StrReplaceAll);
} // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/strings/str_split_benchmark.cc b/absl/strings/str_split_benchmark.cc
index c35787b7..326ff744 100644
--- a/absl/strings/str_split_benchmark.cc
+++ b/absl/strings/str_split_benchmark.cc
@@ -154,5 +154,3 @@ BENCHMARK_TEMPLATE(BM_SplitStringWithOneCharNoVector, OneCharLiteral);
BENCHMARK_TEMPLATE(BM_SplitStringWithOneCharNoVector, OneCharStringLiteral);
} // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/strings/string_view_benchmark.cc b/absl/strings/string_view_benchmark.cc
index c66f0fbd..fb46db18 100644
--- a/absl/strings/string_view_benchmark.cc
+++ b/absl/strings/string_view_benchmark.cc
@@ -327,5 +327,3 @@ void BM_AppendToStringNative(benchmark::State& state) {
BENCHMARK(BM_AppendToStringNative)->Range(1 << 3, 1 << 12);
} // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h
index 5747d384..c4b25ba7 100644
--- a/absl/strings/substitute.h
+++ b/absl/strings/substitute.h
@@ -99,7 +99,10 @@ class Arg {
// Explicitly overload `const char*` so the compiler doesn't cast to `bool`.
Arg(const char* value) // NOLINT(runtime/explicit)
: piece_(absl::NullSafeStringView(value)) {}
- Arg(const std::string& value) // NOLINT(runtime/explicit)
+ template <typename Allocator>
+ Arg( // NOLINT
+ const std::basic_string<char, std::char_traits<char>, Allocator>&
+ value) noexcept
: piece_(value) {}
Arg(absl::string_view value) // NOLINT(runtime/explicit)
: piece_(value) {}
diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel
index 2502c53f..123536ea 100644
--- a/absl/synchronization/BUILD.bazel
+++ b/absl/synchronization/BUILD.bazel
@@ -130,7 +130,7 @@ cc_test(
deps = [
":graphcycles_internal",
"//absl/base",
- "@com_github_google_benchmark//:benchmark",
+ "@com_github_google_benchmark//:benchmark_main",
],
)
@@ -176,7 +176,7 @@ cc_test(
":synchronization",
":thread_pool",
"//absl/base",
- "@com_github_google_benchmark//:benchmark",
+ "@com_github_google_benchmark//:benchmark_main",
],
)
diff --git a/absl/synchronization/internal/graphcycles_benchmark.cc b/absl/synchronization/internal/graphcycles_benchmark.cc
index b4a1debe..a239c25c 100644
--- a/absl/synchronization/internal/graphcycles_benchmark.cc
+++ b/absl/synchronization/internal/graphcycles_benchmark.cc
@@ -42,5 +42,3 @@ void BM_StressTest(benchmark::State& state) {
BENCHMARK(BM_StressTest)->Range(2048, 1048576);
} // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/synchronization/mutex_benchmark.cc b/absl/synchronization/mutex_benchmark.cc
index d91071b7..30a52355 100644
--- a/absl/synchronization/mutex_benchmark.cc
+++ b/absl/synchronization/mutex_benchmark.cc
@@ -92,5 +92,3 @@ BENCHMARK(BM_ContendedMutex)->Threads(1);
BENCHMARK(BM_ContendedMutex)->ThreadPerCpu();
} // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel
index 7126f141..64cb99f7 100644
--- a/absl/time/BUILD.bazel
+++ b/absl/time/BUILD.bazel
@@ -81,10 +81,6 @@ cc_test(
],
copts = ABSL_TEST_COPTS,
tags = [
- "no_test_android_arm",
- "no_test_android_arm64",
- "no_test_android_x86",
- "no_test_ios_x86_64",
"no_test_loonix",
],
deps = [
diff --git a/absl/time/internal/cctz/BUILD.bazel b/absl/time/internal/cctz/BUILD.bazel
index 468470b4..9f1ba21c 100644
--- a/absl/time/internal/cctz/BUILD.bazel
+++ b/absl/time/internal/cctz/BUILD.bazel
@@ -81,6 +81,11 @@ cc_test(
size = "small",
srcs = ["src/time_zone_format_test.cc"],
data = [":zoneinfo"],
+ tags = [
+ "no_test_android_arm",
+ "no_test_android_arm64",
+ "no_test_android_x86",
+ ],
deps = [
":civil_time",
":time_zone",
@@ -93,6 +98,11 @@ cc_test(
size = "small",
srcs = ["src/time_zone_lookup_test.cc"],
data = [":zoneinfo"],
+ tags = [
+ "no_test_android_arm",
+ "no_test_android_arm64",
+ "no_test_android_x86",
+ ],
deps = [
":civil_time",
":time_zone",
@@ -102,6 +112,24 @@ cc_test(
### benchmarks
+cc_test(
+ name = "cctz_benchmark",
+ srcs = [
+ "src/cctz_benchmark.cc",
+ "src/time_zone_if.h",
+ "src/time_zone_impl.h",
+ "src/time_zone_info.h",
+ "src/tzfile.h",
+ ],
+ linkstatic = 1,
+ tags = ["benchmark"],
+ deps = [
+ ":civil_time",
+ ":time_zone",
+ "@com_github_google_benchmark//:benchmark_main",
+ ],
+)
+
### examples
### binaries
diff --git a/absl/time/internal/cctz/src/cctz_benchmark.cc b/absl/time/internal/cctz/src/cctz_benchmark.cc
new file mode 100644
index 00000000..f13cb4ee
--- /dev/null
+++ b/absl/time/internal/cctz/src/cctz_benchmark.cc
@@ -0,0 +1,982 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// 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
+//
+// http://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 <algorithm>
+#include <cassert>
+#include <chrono>
+#include <ctime>
+#include <random>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "absl/time/internal/cctz/include/cctz/civil_time.h"
+#include "absl/time/internal/cctz/include/cctz/time_zone.h"
+#include "time_zone_impl.h"
+
+namespace {
+
+namespace cctz = absl::time_internal::cctz;
+
+void BM_Difference_Days(benchmark::State& state) {
+ const cctz::civil_day c(2014, 8, 22);
+ const cctz::civil_day epoch(1970, 1, 1);
+ while (state.KeepRunning()) {
+ benchmark::DoNotOptimize(c - epoch);
+ }
+}
+BENCHMARK(BM_Difference_Days);
+
+void BM_Step_Days(benchmark::State& state) {
+ const cctz::civil_day kStart(2014, 8, 22);
+ cctz::civil_day c = kStart;
+ while (state.KeepRunning()) {
+ benchmark::DoNotOptimize(++c);
+ }
+}
+BENCHMARK(BM_Step_Days);
+
+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 RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z";
+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/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<std::string> AllTimeZoneNames() {
+ std::vector<std::string> names;
+ for (const char* const* namep = kTimeZoneNames; *namep != nullptr; ++namep) {
+ names.push_back(std::string("file:") + *namep);
+ }
+ assert(!names.empty());
+
+ std::mt19937 urbg(42); // a UniformRandomBitGenerator with fixed seed
+ std::shuffle(names.begin(), names.end(), urbg);
+ return names;
+}
+
+cctz::time_zone TestTimeZone() {
+ cctz::time_zone tz;
+ cctz::load_time_zone("America/Los_Angeles", &tz);
+ return tz;
+}
+
+void BM_Zone_LoadUTCTimeZoneFirst(benchmark::State& state) {
+ cctz::time_zone tz;
+ cctz::load_time_zone("UTC", &tz); // in case we're first
+ cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();
+ while (state.KeepRunning()) {
+ benchmark::DoNotOptimize(cctz::load_time_zone("UTC", &tz));
+ }
+}
+BENCHMARK(BM_Zone_LoadUTCTimeZoneFirst);
+
+void BM_Zone_LoadUTCTimeZoneLast(benchmark::State& state) {
+ cctz::time_zone tz;
+ for (const auto& name : AllTimeZoneNames()) {
+ cctz::load_time_zone(name, &tz); // prime cache
+ }
+ while (state.KeepRunning()) {
+ benchmark::DoNotOptimize(cctz::load_time_zone("UTC", &tz));
+ }
+}
+BENCHMARK(BM_Zone_LoadUTCTimeZoneLast);
+
+void BM_Zone_LoadTimeZoneFirst(benchmark::State& state) {
+ cctz::time_zone tz = cctz::utc_time_zone(); // in case we're first
+ const std::string name = "file:America/Los_Angeles";
+ while (state.KeepRunning()) {
+ state.PauseTiming();
+ cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();
+ state.ResumeTiming();
+ benchmark::DoNotOptimize(cctz::load_time_zone(name, &tz));
+ }
+}
+BENCHMARK(BM_Zone_LoadTimeZoneFirst);
+
+void BM_Zone_LoadTimeZoneCached(benchmark::State& state) {
+ cctz::time_zone tz = cctz::utc_time_zone(); // in case we're first
+ cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();
+ const std::string name = "file:America/Los_Angeles";
+ cctz::load_time_zone(name, &tz); // prime cache
+ while (state.KeepRunning()) {
+ benchmark::DoNotOptimize(cctz::load_time_zone(name, &tz));
+ }
+}
+BENCHMARK(BM_Zone_LoadTimeZoneCached);
+
+void BM_Zone_LoadLocalTimeZoneCached(benchmark::State& state) {
+ cctz::utc_time_zone(); // in case we're first
+ cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();
+ cctz::local_time_zone(); // prime cache
+ while (state.KeepRunning()) {
+ benchmark::DoNotOptimize(cctz::local_time_zone());
+ }
+}
+BENCHMARK(BM_Zone_LoadLocalTimeZoneCached);
+
+void BM_Zone_LoadAllTimeZonesFirst(benchmark::State& state) {
+ cctz::time_zone tz;
+ const std::vector<std::string> names = AllTimeZoneNames();
+ for (auto index = names.size(); state.KeepRunning(); ++index) {
+ if (index == names.size()) {
+ index = 0;
+ }
+ if (index == 0) {
+ state.PauseTiming();
+ cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();
+ state.ResumeTiming();
+ }
+ benchmark::DoNotOptimize(cctz::load_time_zone(names[index], &tz));
+ }
+}
+BENCHMARK(BM_Zone_LoadAllTimeZonesFirst);
+
+void BM_Zone_LoadAllTimeZonesCached(benchmark::State& state) {
+ cctz::time_zone tz;
+ const std::vector<std::string> names = AllTimeZoneNames();
+ for (const auto& name : names) {
+ cctz::load_time_zone(name, &tz); // prime cache
+ }
+ for (auto index = names.size(); state.KeepRunning(); ++index) {
+ if (index == names.size()) {
+ index = 0;
+ }
+ benchmark::DoNotOptimize(cctz::load_time_zone(names[index], &tz));
+ }
+}
+BENCHMARK(BM_Zone_LoadAllTimeZonesCached);
+
+void BM_Zone_TimeZoneImplGetImplicit(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(BM_Zone_TimeZoneImplGetImplicit);
+
+void BM_Zone_TimeZoneImplGetExplicit(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(BM_Zone_TimeZoneImplGetExplicit);
+
+void BM_Zone_UTCTimeZone(benchmark::State& state) {
+ cctz::time_zone tz;
+ while (state.KeepRunning()) {
+ benchmark::DoNotOptimize(cctz::utc_time_zone());
+ }
+}
+BENCHMARK(BM_Zone_UTCTimeZone);
+
+// In each "ToDateTime" benchmark we switch between two instants
+// separated by at least one transition in order to defeat any
+// internal caching of previous results (e.g., see local_time_hint_).
+//
+// The "UTC" variants use UTC instead of the Google/local time zone.
+
+void BM_Time_ToDateTime_CCTZ(benchmark::State& state) {
+ const cctz::time_zone tz = TestTimeZone();
+ std::chrono::system_clock::time_point tp =
+ std::chrono::system_clock::from_time_t(1384569027);
+ std::chrono::system_clock::time_point tp2 =
+ std::chrono::system_clock::from_time_t(1418962578);
+ while (state.KeepRunning()) {
+ std::swap(tp, tp2);
+ tp += std::chrono::seconds(1);
+ benchmark::DoNotOptimize(cctz::convert(tp, tz));
+ }
+}
+BENCHMARK(BM_Time_ToDateTime_CCTZ);
+
+void BM_Time_ToDateTime_Libc(benchmark::State& state) {
+ // No timezone support, so just use localtime.
+ time_t t = 1384569027;
+ time_t t2 = 1418962578;
+ struct tm tm;
+ while (state.KeepRunning()) {
+ std::swap(t, t2);
+ t += 1;
+#if defined(_WIN32) || defined(_WIN64)
+ benchmark::DoNotOptimize(localtime_s(&tm, &t));
+#else
+ benchmark::DoNotOptimize(localtime_r(&t, &tm));
+#endif
+ }
+}
+BENCHMARK(BM_Time_ToDateTime_Libc);
+
+void BM_Time_ToDateTimeUTC_CCTZ(benchmark::State& state) {
+ const cctz::time_zone tz = cctz::utc_time_zone();
+ std::chrono::system_clock::time_point tp =
+ std::chrono::system_clock::from_time_t(1384569027);
+ while (state.KeepRunning()) {
+ tp += std::chrono::seconds(1);
+ benchmark::DoNotOptimize(cctz::convert(tp, tz));
+ }
+}
+BENCHMARK(BM_Time_ToDateTimeUTC_CCTZ);
+
+void BM_Time_ToDateTimeUTC_Libc(benchmark::State& state) {
+ time_t t = 1384569027;
+ struct tm tm;
+ while (state.KeepRunning()) {
+ t += 1;
+#if defined(_WIN32) || defined(_WIN64)
+ benchmark::DoNotOptimize(gmtime_s(&tm, &t));
+#else
+ benchmark::DoNotOptimize(gmtime_r(&t, &tm));
+#endif
+ }
+}
+BENCHMARK(BM_Time_ToDateTimeUTC_Libc);
+
+// In each "FromDateTime" benchmark we switch between two YMDhms
+// values separated by at least one transition in order to defeat any
+// internal caching of previous results (e.g., see time_local_hint_).
+//
+// The "UTC" variants use UTC instead of the Google/local time zone.
+// The "Day0" variants require normalization of the day of month.
+
+void BM_Time_FromDateTime_CCTZ(benchmark::State& state) {
+ const cctz::time_zone tz = TestTimeZone();
+ int i = 0;
+ while (state.KeepRunning()) {
+ if ((i++ & 1) == 0) {
+ benchmark::DoNotOptimize(
+ cctz::convert(cctz::civil_second(2014, 12, 18, 20, 16, 18), tz));
+ } else {
+ benchmark::DoNotOptimize(
+ cctz::convert(cctz::civil_second(2013, 11, 15, 18, 30, 27), tz));
+ }
+ }
+}
+BENCHMARK(BM_Time_FromDateTime_CCTZ);
+
+void BM_Time_FromDateTime_Libc(benchmark::State& state) {
+ // No timezone support, so just use localtime.
+ int i = 0;
+ while (state.KeepRunning()) {
+ struct tm tm;
+ if ((i++ & 1) == 0) {
+ tm.tm_year = 2014 - 1900;
+ tm.tm_mon = 12 - 1;
+ tm.tm_mday = 18;
+ tm.tm_hour = 20;
+ tm.tm_min = 16;
+ tm.tm_sec = 18;
+ } else {
+ tm.tm_year = 2013 - 1900;
+ tm.tm_mon = 11 - 1;
+ tm.tm_mday = 15;
+ tm.tm_hour = 18;
+ tm.tm_min = 30;
+ tm.tm_sec = 27;
+ }
+ tm.tm_isdst = -1;
+ benchmark::DoNotOptimize(mktime(&tm));
+ }
+}
+BENCHMARK(BM_Time_FromDateTime_Libc);
+
+void BM_Time_FromDateTimeUTC_CCTZ(benchmark::State& state) {
+ const cctz::time_zone tz = cctz::utc_time_zone();
+ while (state.KeepRunning()) {
+ benchmark::DoNotOptimize(
+ cctz::convert(cctz::civil_second(2014, 12, 18, 20, 16, 18), tz));
+ }
+}
+BENCHMARK(BM_Time_FromDateTimeUTC_CCTZ);
+
+// There is no BM_Time_FromDateTimeUTC_Libc.
+
+void BM_Time_FromDateTimeDay0_CCTZ(benchmark::State& state) {
+ const cctz::time_zone tz = TestTimeZone();
+ int i = 0;
+ while (state.KeepRunning()) {
+ if ((i++ & 1) == 0) {
+ benchmark::DoNotOptimize(
+ cctz::convert(cctz::civil_second(2014, 12, 0, 20, 16, 18), tz));
+ } else {
+ benchmark::DoNotOptimize(
+ cctz::convert(cctz::civil_second(2013, 11, 0, 18, 30, 27), tz));
+ }
+ }
+}
+BENCHMARK(BM_Time_FromDateTimeDay0_CCTZ);
+
+void BM_Time_FromDateTimeDay0_Libc(benchmark::State& state) {
+ // No timezone support, so just use localtime.
+ int i = 0;
+ while (state.KeepRunning()) {
+ struct tm tm;
+ if ((i++ & 1) == 0) {
+ tm.tm_year = 2014 - 1900;
+ tm.tm_mon = 12 - 1;
+ tm.tm_mday = 0;
+ tm.tm_hour = 20;
+ tm.tm_min = 16;
+ tm.tm_sec = 18;
+ } else {
+ tm.tm_year = 2013 - 1900;
+ tm.tm_mon = 11 - 1;
+ tm.tm_mday = 0;
+ tm.tm_hour = 18;
+ tm.tm_min = 30;
+ tm.tm_sec = 27;
+ }
+ tm.tm_isdst = -1;
+ benchmark::DoNotOptimize(mktime(&tm));
+ }
+}
+BENCHMARK(BM_Time_FromDateTimeDay0_Libc);
+
+const char* const kFormats[] = {
+ RFC1123_full, // 0
+ RFC1123_no_wday, // 1
+ RFC3339_full, // 2
+ RFC3339_sec, // 3
+ "%Y-%m-%dT%H:%M:%S", // 4
+ "%Y-%m-%d", // 5
+};
+const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
+
+void BM_Format_FormatTime(benchmark::State& state) {
+ const std::string fmt = kFormats[state.range(0)];
+ state.SetLabel(fmt);
+ const cctz::time_zone tz = TestTimeZone();
+ const std::chrono::system_clock::time_point tp =
+ cctz::convert(cctz::civil_second(1977, 6, 28, 9, 8, 7), tz) +
+ std::chrono::microseconds(1);
+ while (state.KeepRunning()) {
+ benchmark::DoNotOptimize(cctz::format(fmt, tp, tz));
+ }
+}
+BENCHMARK(BM_Format_FormatTime)->DenseRange(0, kNumFormats - 1);
+
+void BM_Format_ParseTime(benchmark::State& state) {
+ const std::string fmt = kFormats[state.range(0)];
+ state.SetLabel(fmt);
+ const cctz::time_zone tz = TestTimeZone();
+ std::chrono::system_clock::time_point tp =
+ cctz::convert(cctz::civil_second(1977, 6, 28, 9, 8, 7), tz) +
+ std::chrono::microseconds(1);
+ const std::string when = cctz::format(fmt, tp, tz);
+ while (state.KeepRunning()) {
+ benchmark::DoNotOptimize(cctz::parse(fmt, when, tz, &tp));
+ }
+}
+BENCHMARK(BM_Format_ParseTime)->DenseRange(0, kNumFormats - 1);
+
+} // namespace
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 6cea0360..3a5f19ac 100644
--- a/absl/time/internal/cctz/src/time_zone_format_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_format_test.cc
@@ -463,8 +463,13 @@ TEST(Format, ExtendedSecondOffset) {
EXPECT_TRUE(load_time_zone("Europe/Moscow", &tz));
tp = convert(civil_second(1919, 6, 30, 23, 59, 59), utc);
- TestFormatSpecifier(tp, tz, "%E*z", "+04:31:19");
- TestFormatSpecifier(tp, tz, "%Ez", "+04:31");
+ if (tz.lookup(tp).offset == 4 * 60 * 60) {
+ // We're likely dealing with zoneinfo that doesn't support really old
+ // timestamps, so Europe/Moscow never looks to be on local mean time.
+ } else {
+ TestFormatSpecifier(tp, tz, "%E*z", "+04:31:19");
+ TestFormatSpecifier(tp, tz, "%Ez", "+04:31");
+ }
tp += seconds(1);
TestFormatSpecifier(tp, tz, "%E*z", "+04:00:00");
}
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index f8d53c26..c26c68d0 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -193,6 +193,20 @@ cc_test(
],
)
+cc_test(
+ name = "optional_exception_safety_test",
+ srcs = [
+ "optional_exception_safety_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
+ deps = [
+ ":optional",
+ "//absl/base:exception_safety_testing",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+
cc_library(
name = "variant",
srcs = ["internal/variant.h"],
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt
index fbd83740..2f2e3a77 100644
--- a/absl/types/CMakeLists.txt
+++ b/absl/types/CMakeLists.txt
@@ -209,3 +209,20 @@ absl_test(
)
+# test optional_exception_safety_test
+set(OPTIONAL_EXCEPTION_SAFETY_TEST_SRC "optional_exception_safety_test.cc")
+set(OPTIONAL_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
+ absl::optional
+ absl_base_internal_exception_safety_testing
+)
+
+absl_test(
+ TARGET
+ optional_exception_safety_test
+ SOURCES
+ ${OPTIONAL_EXCEPTION_SAFETY_TEST_SRC}
+ PUBLIC_LIBRARIES
+ ${OPTIONAL_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
+ PRIVATE_COMPILE_FLAGS
+ ${ABSL_EXCEPTIONS_FLAG}
+)
diff --git a/absl/types/optional_exception_safety_test.cc b/absl/types/optional_exception_safety_test.cc
new file mode 100644
index 00000000..7f6348e1
--- /dev/null
+++ b/absl/types/optional_exception_safety_test.cc
@@ -0,0 +1,284 @@
+// Copyright 2017 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
+//
+// http://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/types/optional.h"
+
+#include "gtest/gtest.h"
+#include "absl/base/internal/exception_safety_testing.h"
+
+namespace absl {
+
+namespace {
+
+using ::testing::AssertionFailure;
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using ::testing::MakeExceptionSafetyTester;
+
+using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>;
+using Optional = absl::optional<Thrower>;
+
+using MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
+using MoveOptional = absl::optional<MoveThrower>;
+
+constexpr int kInitialInteger = 5;
+constexpr int kUpdatedInteger = 10;
+
+template <typename OptionalT>
+bool ValueThrowsBadOptionalAccess(const OptionalT& optional) try {
+ return (static_cast<void>(optional.value()), false);
+} catch (absl::bad_optional_access) {
+ return true;
+}
+
+template <typename OptionalT>
+AssertionResult CheckInvariants(OptionalT* optional_ptr) {
+ // Check the current state post-throw for validity
+ auto& optional = *optional_ptr;
+
+ if (optional.has_value() && ValueThrowsBadOptionalAccess(optional)) {
+ return AssertionFailure()
+ << "Optional with value should not throw bad_optional_access when "
+ "accessing the value.";
+ }
+ if (!optional.has_value() && !ValueThrowsBadOptionalAccess(optional)) {
+ return AssertionFailure()
+ << "Optional without a value should throw bad_optional_access when "
+ "accessing the value.";
+ }
+
+ // Reset to a known state
+ optional.reset();
+
+ // Confirm that the known post-reset state is valid
+ if (optional.has_value()) {
+ return AssertionFailure()
+ << "Optional should not contain a value after being reset.";
+ }
+ if (!ValueThrowsBadOptionalAccess(optional)) {
+ return AssertionFailure() << "Optional should throw bad_optional_access "
+ "when accessing the value after being reset.";
+ }
+
+ return AssertionSuccess();
+}
+
+template <typename OptionalT>
+AssertionResult CheckDisengaged(OptionalT* optional_ptr) {
+ auto& optional = *optional_ptr;
+
+ if (optional.has_value()) {
+ return AssertionFailure()
+ << "Expected optional to not contain a value but a value was found.";
+ }
+
+ return AssertionSuccess();
+}
+
+template <typename OptionalT>
+AssertionResult CheckEngaged(OptionalT* optional_ptr) {
+ auto& optional = *optional_ptr;
+
+ if (!optional.has_value()) {
+ return AssertionFailure()
+ << "Expected optional to contain a value but no value was found.";
+ }
+
+ return AssertionSuccess();
+}
+
+TEST(OptionalExceptionSafety, ThrowingConstructors) {
+ auto thrower_nonempty = Optional(Thrower(kInitialInteger));
+ testing::TestThrowingCtor<Optional>(thrower_nonempty);
+
+ auto integer_nonempty = absl::optional<int>(kInitialInteger);
+ testing::TestThrowingCtor<Optional>(integer_nonempty);
+ testing::TestThrowingCtor<Optional>(std::move(integer_nonempty)); // NOLINT
+
+ testing::TestThrowingCtor<Optional>(kInitialInteger);
+ using ThrowerVec = std::vector<Thrower, testing::ThrowingAllocator<Thrower>>;
+ testing::TestThrowingCtor<absl::optional<ThrowerVec>>(
+ absl::in_place,
+ std::initializer_list<Thrower>{Thrower(), Thrower(), Thrower()},
+ testing::ThrowingAllocator<Thrower>());
+}
+
+TEST(OptionalExceptionSafety, NothrowConstructors) {
+ // This constructor is marked noexcept. If it throws, the program will
+ // terminate.
+ testing::TestThrowingCtor<MoveOptional>(MoveOptional(kUpdatedInteger));
+}
+
+TEST(OptionalExceptionSafety, Emplace) {
+ // Test the basic guarantee plus test the result of optional::has_value()
+ // is false in all cases
+ auto disengaged_test = MakeExceptionSafetyTester().WithInvariants(
+ CheckInvariants<Optional>, CheckDisengaged<Optional>);
+ auto disengaged_test_empty = disengaged_test.WithInitialValue(Optional());
+ auto disengaged_test_nonempty =
+ disengaged_test.WithInitialValue(Optional(kInitialInteger));
+
+ auto emplace_thrower_directly = [](Optional* optional_ptr) {
+ optional_ptr->emplace(kUpdatedInteger);
+ };
+ EXPECT_TRUE(disengaged_test_empty.Test(emplace_thrower_directly));
+ EXPECT_TRUE(disengaged_test_nonempty.Test(emplace_thrower_directly));
+
+ auto emplace_thrower_copy = [](Optional* optional_ptr) {
+ auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor);
+ optional_ptr->emplace(thrower);
+ };
+ EXPECT_TRUE(disengaged_test_empty.Test(emplace_thrower_copy));
+ EXPECT_TRUE(disengaged_test_nonempty.Test(emplace_thrower_copy));
+}
+
+TEST(OptionalExceptionSafety, EverythingThrowsSwap) {
+ // Test the basic guarantee plus test the result of optional::has_value()
+ // remains the same
+ auto test =
+ MakeExceptionSafetyTester().WithInvariants(CheckInvariants<Optional>);
+ auto disengaged_test_empty = test.WithInitialValue(Optional())
+ .WithInvariants(CheckDisengaged<Optional>);
+ auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger))
+ .WithInvariants(CheckEngaged<Optional>);
+
+ auto swap_empty = [](Optional* optional_ptr) {
+ auto empty = Optional();
+ optional_ptr->swap(empty);
+ };
+ EXPECT_TRUE(engaged_test_nonempty.Test(swap_empty));
+
+ auto swap_nonempty = [](Optional* optional_ptr) {
+ auto nonempty =
+ Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor);
+ optional_ptr->swap(nonempty);
+ };
+ EXPECT_TRUE(disengaged_test_empty.Test(swap_nonempty));
+ EXPECT_TRUE(engaged_test_nonempty.Test(swap_nonempty));
+}
+
+TEST(OptionalExceptionSafety, NoThrowMoveSwap) {
+ // Tests the nothrow guarantee for optional of T with non-throwing move
+ auto nothrow_test =
+ MakeExceptionSafetyTester().WithInvariants(testing::nothrow_guarantee);
+ auto nothrow_test_empty = nothrow_test.WithInitialValue(MoveOptional());
+ auto nothrow_test_nonempty =
+ nothrow_test.WithInitialValue(MoveOptional(kInitialInteger));
+
+ auto swap_empty = [](MoveOptional* optional_ptr) {
+ auto empty = MoveOptional();
+ optional_ptr->swap(empty);
+ };
+ EXPECT_TRUE(nothrow_test_nonempty.Test(swap_empty));
+
+ auto swap_nonempty = [](MoveOptional* optional_ptr) {
+ auto nonempty =
+ MoveOptional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor);
+ optional_ptr->swap(nonempty);
+ };
+ EXPECT_TRUE(nothrow_test_empty.Test(swap_nonempty));
+ EXPECT_TRUE(nothrow_test_nonempty.Test(swap_nonempty));
+}
+
+TEST(OptionalExceptionSafety, CopyAssign) {
+ // Test the basic guarantee plus test the result of optional::has_value()
+ // remains the same
+ auto test =
+ MakeExceptionSafetyTester().WithInvariants(CheckInvariants<Optional>);
+ auto disengaged_test_empty = test.WithInitialValue(Optional())
+ .WithInvariants(CheckDisengaged<Optional>);
+ auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger))
+ .WithInvariants(CheckEngaged<Optional>);
+
+ auto copyassign_nonempty = [](Optional* optional_ptr) {
+ auto nonempty =
+ Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor);
+ *optional_ptr = nonempty;
+ };
+ EXPECT_TRUE(disengaged_test_empty.Test(copyassign_nonempty));
+ EXPECT_TRUE(engaged_test_nonempty.Test(copyassign_nonempty));
+
+ auto copyassign_thrower = [](Optional* optional_ptr) {
+ auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor);
+ *optional_ptr = thrower;
+ };
+ EXPECT_TRUE(disengaged_test_empty.Test(copyassign_thrower));
+ EXPECT_TRUE(engaged_test_nonempty.Test(copyassign_thrower));
+}
+
+TEST(OptionalExceptionSafety, MoveAssign) {
+ // Test the basic guarantee plus test the result of optional::has_value()
+ // remains the same
+ auto test =
+ MakeExceptionSafetyTester().WithInvariants(CheckInvariants<Optional>);
+ auto disengaged_test_empty = test.WithInitialValue(Optional())
+ .WithInvariants(CheckDisengaged<Optional>);
+ auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger))
+ .WithInvariants(CheckEngaged<Optional>);
+
+ auto moveassign_empty = [](Optional* optional_ptr) {
+ auto empty = Optional();
+ *optional_ptr = std::move(empty);
+ };
+ EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_empty));
+
+ auto moveassign_nonempty = [](Optional* optional_ptr) {
+ auto nonempty =
+ Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor);
+ *optional_ptr = std::move(nonempty);
+ };
+ EXPECT_TRUE(disengaged_test_empty.Test(moveassign_nonempty));
+ EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_nonempty));
+
+ auto moveassign_thrower = [](Optional* optional_ptr) {
+ auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor);
+ *optional_ptr = std::move(thrower);
+ };
+ EXPECT_TRUE(disengaged_test_empty.Test(moveassign_thrower));
+ EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_thrower));
+}
+
+TEST(OptionalExceptionSafety, NothrowMoveAssign) {
+ // Tests the nothrow guarantee for optional of T with non-throwing move
+ auto nothrow_test =
+ MakeExceptionSafetyTester().WithInvariants(testing::nothrow_guarantee);
+ auto nothrow_test_empty = nothrow_test.WithInitialValue(MoveOptional());
+ auto nothrow_test_nonempty =
+ nothrow_test.WithInitialValue(MoveOptional(kInitialInteger));
+
+ auto moveassign_empty = [](MoveOptional* optional_ptr) {
+ auto empty = MoveOptional();
+ *optional_ptr = std::move(empty);
+ };
+ EXPECT_TRUE(nothrow_test_nonempty.Test(moveassign_empty));
+
+ auto moveassign_nonempty = [](MoveOptional* optional_ptr) {
+ auto nonempty =
+ MoveOptional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor);
+ *optional_ptr = std::move(nonempty);
+ };
+ EXPECT_TRUE(nothrow_test_empty.Test(moveassign_nonempty));
+ EXPECT_TRUE(nothrow_test_nonempty.Test(moveassign_nonempty));
+
+ auto moveassign_thrower = [](MoveOptional* optional_ptr) {
+ auto thrower = MoveThrower(kUpdatedInteger, testing::nothrow_ctor);
+ *optional_ptr = std::move(thrower);
+ };
+ EXPECT_TRUE(nothrow_test_empty.Test(moveassign_thrower));
+ EXPECT_TRUE(nothrow_test_nonempty.Test(moveassign_thrower));
+}
+
+} // namespace
+
+} // namespace absl