about summary refs log tree commit diff
path: root/absl/strings/internal
diff options
context:
space:
mode:
Diffstat (limited to 'absl/strings/internal')
-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
6 files changed, 476 insertions, 269 deletions
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