diff --git a/absl/strings/ascii.h b/absl/strings/ascii.h index 591c451b67f..c8c40e85e90 100644 --- a/absl/strings/ascii.h +++ b/absl/strings/ascii.h @@ -55,6 +55,7 @@ #include #include #include +#include #include "absl/base/attributes.h" #include "absl/base/config.h" @@ -184,6 +185,16 @@ ABSL_MUST_USE_RESULT inline std::string AsciiStrToLower(absl::string_view s) { return result; } +// Creates a lowercase string from a given std::string&&. +// +// (Template is used to lower priority of this overload.) +template +ABSL_MUST_USE_RESULT inline std::string AsciiStrToLower(std::string&& s) { + std::string result = std::move(s); + absl::AsciiStrToLower(&result); + return result; +} + // ascii_toupper() // // Returns the ASCII character, converting to upper-case if lower-case is @@ -203,6 +214,16 @@ ABSL_MUST_USE_RESULT inline std::string AsciiStrToUpper(absl::string_view s) { return result; } +// Creates an uppercase string from a given std::string&&. +// +// (Template is used to lower priority of this overload.) +template +ABSL_MUST_USE_RESULT inline std::string AsciiStrToUpper(std::string&& s) { + std::string result = std::move(s); + absl::AsciiStrToUpper(&result); + return result; +} + // Returns absl::string_view with whitespace stripped from the beginning of the // given string_view. ABSL_MUST_USE_RESULT inline absl::string_view StripLeadingAsciiWhitespace( diff --git a/absl/strings/ascii_benchmark.cc b/absl/strings/ascii_benchmark.cc index 4ae73174688..0eff801aec6 100644 --- a/absl/strings/ascii_benchmark.cc +++ b/absl/strings/ascii_benchmark.cc @@ -129,4 +129,32 @@ BENCHMARK(BM_StrToUpper) ->RangeMultiplier(2) ->Range(64, 1 << 26); +static void BM_StrToUpperFromRvalref(benchmark::State& state) { + const size_t size = static_cast(state.range(0)); + std::string s(size, 'X'); + for (auto _ : state) { + benchmark::DoNotOptimize(s); + std::string res = absl::AsciiStrToUpper(std::string(s)); + benchmark::DoNotOptimize(res); + } +} +BENCHMARK(BM_StrToUpperFromRvalref) + ->DenseRange(0, 32) + ->RangeMultiplier(2) + ->Range(64, 1 << 26); + +static void BM_StrToLowerFromRvalref(benchmark::State& state) { + const size_t size = static_cast(state.range(0)); + std::string s(size, 'x'); + for (auto _ : state) { + benchmark::DoNotOptimize(s); + std::string res = absl::AsciiStrToLower(std::string(s)); + benchmark::DoNotOptimize(res); + } +} +BENCHMARK(BM_StrToLowerFromRvalref) + ->DenseRange(0, 32) + ->RangeMultiplier(2) + ->Range(64, 1 << 26); + } // namespace diff --git a/absl/strings/ascii_test.cc b/absl/strings/ascii_test.cc index 8885bb15d42..896ffb7d6f7 100644 --- a/absl/strings/ascii_test.cc +++ b/absl/strings/ascii_test.cc @@ -192,11 +192,13 @@ TEST(AsciiStrTo, Lower) { const absl::string_view sp(str2); const std::string long_str("ABCDEFGHIJKLMNOPQRSTUVWXYZ1!a"); std::string mutable_str("_`?@[{AMNOPQRSTUVWXYZ"); + auto fun = []() -> std::string { return "PQRSTU"; }; EXPECT_EQ("abcdef", absl::AsciiStrToLower(buf)); EXPECT_EQ("ghijkl", absl::AsciiStrToLower(str)); EXPECT_EQ("mnopqr", absl::AsciiStrToLower(sp)); EXPECT_EQ("abcdefghijklmnopqrstuvwxyz1!a", absl::AsciiStrToLower(long_str)); + EXPECT_EQ("pqrstu", absl::AsciiStrToLower(fun())); absl::AsciiStrToLower(&mutable_str); EXPECT_EQ("_`?@[{amnopqrstuvwxyz", mutable_str); @@ -213,11 +215,13 @@ TEST(AsciiStrTo, Upper) { const std::string str2("_`?@[{amnopqrstuvwxyz"); const absl::string_view sp(str2); const std::string long_str("abcdefghijklmnopqrstuvwxyz1!A"); + auto fun = []() -> std::string { return "pqrstu"; }; EXPECT_EQ("ABCDEF", absl::AsciiStrToUpper(buf)); EXPECT_EQ("GHIJKL", absl::AsciiStrToUpper(str)); EXPECT_EQ("_`?@[{AMNOPQRSTUVWXYZ", absl::AsciiStrToUpper(sp)); EXPECT_EQ("ABCDEFGHIJKLMNOPQRSTUVWXYZ1!A", absl::AsciiStrToUpper(long_str)); + EXPECT_EQ("PQRSTU", absl::AsciiStrToUpper(fun())); char mutable_buf[] = "Mutable"; std::transform(mutable_buf, mutable_buf + strlen(mutable_buf),