From 7aacab8ae05d7115049923da9cfbf584dc1f8338 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 31 May 2018 12:26:35 -0700 Subject: - e2f6b8ac647271815b4fed2991f405524dd762c3 Release cctz microbenchmarks. by Alex Strelnikov - 924ba2a3f9fca695d73c6bf491d20669e2b96b8e Changed RawPtr to use std::addressof() instead of operato... by Abseil Team - e8cf67f9fa74d4c5632da35547025ad2301c6819 Import of CCTZ from GitHub. by Alex Strelnikov - 2ece8a96611afcddd7b91e0197dadb896248250c Abandon ".inc" files in favor of ".h" headers. by Jorg Brown - 37f5ed5da4058f90fb3e6a2733fce5b1fd0aaedf Add exception safety tests for absl::optional by Abseil Team - 337f995a866b8f905f64ca6b271b5fec8f248a60 Update WORKSPACE to grab specific commits of dependencies... by Alex Strelnikov - 93e5b134607a554993387ad913e6c1621606004b Release Charmap microbenchmark. by Alex Strelnikov - 95c2e29b6d93ec1334484ee37d91f63101c45307 Release OStringStream microbenchmarks. by Alex Strelnikov - 250f51839ed26dd1e6b658d35aa291413e5f4825 Internal change by Greg Falcon - ce34900fa3d1a95a8446bc943cdd801fac95be25 Improve compatibility of cctz cc_test targets for portabl... by Shaindel Schwartz - ce7e31dbf2c1ee93c79aae5b7dc7c603cb4babcf Improve portability of cc_tests. (Mark more tests that ca... by Abseil Team - dfcd4e455923703c1a1dcd523c5f915f7990fa2a Accept strings with custom allocators as arguments to abs... by Greg Falcon - 2946b41ed3d5b8b5a8dc11182e443cf1ab6e3bde Link against benchmark_main instead of using BENCHMARK_MA... by Alex Strelnikov - f09de9e03bf8edd363069c4b352d8009423f531c Adds link to doc about the formats allowed by SimpleAtof(... by Greg Miller - 59b0977e7a308e0800277886cf60226b2cc426a1 Simplify the HideMask() calculation so that it doesn't us... by Jorg Brown GitOrigin-RevId: e2f6b8ac647271815b4fed2991f405524dd762c3 Change-Id: Ib9c8547ed7fe217fad6cb3ab1362e96181aa5cfa --- absl/strings/BUILD.bazel | 41 ++++-- absl/strings/escaping_benchmark.cc | 6 +- absl/strings/escaping_test.cc | 4 +- absl/strings/internal/char_map_benchmark.cc | 61 ++++++++ absl/strings/internal/escaping_test_common.h | 131 +++++++++++++++++ absl/strings/internal/escaping_test_common.inc | 113 -------------- absl/strings/internal/numbers_test_common.h | 178 +++++++++++++++++++++++ absl/strings/internal/numbers_test_common.inc | 156 -------------------- absl/strings/internal/ostringstream_benchmark.cc | 106 ++++++++++++++ absl/strings/numbers.h | 4 + absl/strings/numbers_test.cc | 21 +-- absl/strings/str_cat_benchmark.cc | 2 - absl/strings/str_join_benchmark.cc | 2 - absl/strings/str_replace_benchmark.cc | 2 - absl/strings/str_split_benchmark.cc | 2 - absl/strings/string_view_benchmark.cc | 2 - absl/strings/substitute.h | 5 +- 17 files changed, 532 insertions(+), 304 deletions(-) create mode 100644 absl/strings/internal/char_map_benchmark.cc create mode 100644 absl/strings/internal/escaping_test_common.h delete mode 100644 absl/strings/internal/escaping_test_common.inc create mode 100644 absl/strings/internal/numbers_test_common.h delete mode 100644 absl/strings/internal/numbers_test_common.inc create mode 100644 absl/strings/internal/ostringstream_benchmark.cc (limited to 'absl/strings') 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", ], ) @@ -294,6 +294,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", @@ -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 + +#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(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 +#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_strings() { + static const std::array 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 +#include +#include +#include + +namespace absl { +namespace strings_internal { + +template +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& strtouint32_test_cases() { + static const std::array test_cases{{ + {"0xffffffff", true, 16, std::numeric_limits::max()}, + {"0x34234324", true, 16, 0x34234324}, + {"34234324", true, 16, 0x34234324}, + {"0", true, 16, 0}, + {" \t\n 0xffffffff", true, 16, std::numeric_limits::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::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::max()}, + {"0x100000000", false, 0, std::numeric_limits::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& strtouint64_test_cases() { + static const std::array 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::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::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::max()}, + {"0X10000000000000000", false, 16, + std::numeric_limits::max()}, // 0X versus 0x. + {"0x10000000000000000", false, 0, std::numeric_limits::max()}, + {"0X10000000000000000", false, 0, + std::numeric_limits::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 -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::max()}, - {"0x34234324", true, 16, 0x34234324}, - {"34234324", true, 16, 0x34234324}, - {"0", true, 16, 0}, - {" \t\n 0xffffffff", true, 16, std::numeric_limits::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::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::max()}, - {"0x100000000", false, 0, std::numeric_limits::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::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::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::max()}, - {"0X10000000000000000", false, 16, - std::numeric_limits::max()}, // 0X versus 0x. - {"0x10000000000000000", false, 0, std::numeric_limits::max()}, - {"0X10000000000000000", false, 0, - std::numeric_limits::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 +#include + +#include "benchmark/benchmark.h" + +namespace { + +enum StringType { + kNone, + kStdString, +}; + +// Benchmarks for std::ostringstream. +template +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 +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 + Arg( // NOLINT + const std::basic_string, Allocator>& + value) noexcept : piece_(value) {} Arg(absl::string_view value) // NOLINT(runtime/explicit) : piece_(value) {} -- cgit v1.2.3