diff options
Diffstat (limited to 'absl/strings')
-rw-r--r-- | absl/strings/BUILD.bazel | 41 | ||||
-rw-r--r-- | absl/strings/escaping_benchmark.cc | 6 | ||||
-rw-r--r-- | absl/strings/escaping_test.cc | 4 | ||||
-rw-r--r-- | absl/strings/internal/char_map_benchmark.cc | 61 | ||||
-rw-r--r-- | absl/strings/internal/escaping_test_common.h | 131 | ||||
-rw-r--r-- | absl/strings/internal/escaping_test_common.inc | 113 | ||||
-rw-r--r-- | absl/strings/internal/numbers_test_common.h | 178 | ||||
-rw-r--r-- | absl/strings/internal/numbers_test_common.inc | 156 | ||||
-rw-r--r-- | absl/strings/internal/ostringstream_benchmark.cc | 106 | ||||
-rw-r--r-- | absl/strings/numbers.h | 4 | ||||
-rw-r--r-- | absl/strings/numbers_test.cc | 21 | ||||
-rw-r--r-- | absl/strings/str_cat_benchmark.cc | 2 | ||||
-rw-r--r-- | absl/strings/str_join_benchmark.cc | 2 | ||||
-rw-r--r-- | absl/strings/str_replace_benchmark.cc | 2 | ||||
-rw-r--r-- | absl/strings/str_split_benchmark.cc | 2 | ||||
-rw-r--r-- | absl/strings/string_view_benchmark.cc | 2 | ||||
-rw-r--r-- | absl/strings/substitute.h | 5 |
17 files changed, 532 insertions, 304 deletions
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index e6bb7ff530e4..d1c6878c41e4 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 26ddc2d5f318..0f791f4e8750 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 982989b8b4a4..3f65ec107f45 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 000000000000..c45f3157c291 --- /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 000000000000..cc41f4312c7c --- /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 6f29140e3584..000000000000 --- 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 000000000000..20e3af51141e --- /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 81d2a1b70510..000000000000 --- 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 000000000000..c93f96909d8b --- /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 75925e61f2c0..cf3c597266cf 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 e372eea14ca8..24e7138cfae2 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 1791410c6e3a..b6df9e309c4f 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 79cad5e39300..7fb0e4973cb4 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 9dd72eb6e77c..e608de8d19e4 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 c35787b7ef4b..326ff744ebd9 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 c66f0fbd5430..fb46db18b3c3 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 5747d384d34e..c4b25ba70952 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) {} |