From f004d6d9fab9fe732b94f0e7d254700795a37f30 Mon Sep 17 00:00:00 2001 From: Paul Fee Date: Wed, 27 Jan 2021 12:11:28 +0000 Subject: [PATCH] libstdc++: Add string contains member functions for C++2b This implements WG21 P1679R3, adding contains member functions to basic_string_view and basic_string. libstdc++-v3/ChangeLog: * include/bits/basic_string.h (basic_string::contains): New member functions. * include/std/string_view (basic_string_view::contains): Likewise. * include/std/version (__cpp_lib_string_contains): Define. * testsuite/21_strings/basic_string/operations/starts_with/char/1.cc: Remove trailing whitespace. * testsuite/21_strings/basic_string/operations/starts_with/wchar_t/1.cc: Likewise. * testsuite/21_strings/basic_string/operations/contains/char/1.cc: New test. * testsuite/21_strings/basic_string/operations/contains/wchar_t/1.cc: New test. * testsuite/21_strings/basic_string_view/operations/contains/char/1.cc: New test. * testsuite/21_strings/basic_string_view/operations/contains/char/2.cc: New test. * testsuite/21_strings/basic_string_view/operations/contains/wchar_t/1.cc: New test. --- libstdc++-v3/include/bits/basic_string.h | 29 +++++++++ libstdc++-v3/include/std/string_view | 15 +++++ libstdc++-v3/include/std/version | 9 ++- .../operations/contains/char/1.cc | 65 +++++++++++++++++++ .../operations/contains/wchar_t/1.cc | 65 +++++++++++++++++++ .../operations/starts_with/char/1.cc | 2 +- .../operations/starts_with/wchar_t/1.cc | 2 +- .../operations/contains/char/1.cc | 57 ++++++++++++++++ .../operations/contains/char/2.cc | 27 ++++++++ .../operations/contains/wchar_t/1.cc | 51 +++++++++++++++ 10 files changed, 318 insertions(+), 4 deletions(-) create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/char/1.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/wchar_t/1.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/1.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/2.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/wchar_t/1.cc diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index e272d332934..bfc97644bd0 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -3073,6 +3073,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { return __sv_type(this->data(), this->size()).ends_with(__x); } #endif // C++20 +#if __cplusplus > 202002L + bool + contains(basic_string_view<_CharT, _Traits> __x) const noexcept + { return __sv_type(this->data(), this->size()).contains(__x); } + + bool + contains(_CharT __x) const noexcept + { return __sv_type(this->data(), this->size()).contains(__x); } + + bool + contains(const _CharT* __x) const noexcept + { return __sv_type(this->data(), this->size()).contains(__x); } +#endif // C++23 + // Allow basic_stringbuf::__xfer_bufptrs to call _M_length: template friend class basic_stringbuf; }; @@ -5998,6 +6012,21 @@ _GLIBCXX_END_NAMESPACE_CXX11 { return __sv_type(this->data(), this->size()).ends_with(__x); } #endif // C++20 +#if __cplusplus >= 202011L \ + || (__cplusplus == 202002L && !defined __STRICT_ANSI__) + bool + contains(basic_string_view<_CharT, _Traits> __x) const noexcept + { return __sv_type(this->data(), this->size()).contains(__x); } + + bool + contains(_CharT __x) const noexcept + { return __sv_type(this->data(), this->size()).contains(__x); } + + bool + contains(const _CharT* __x) const noexcept + { return __sv_type(this->data(), this->size()).contains(__x); } +#endif // C++23 + # ifdef _GLIBCXX_TM_TS_INTERNAL friend void ::_txnal_cow_string_C1_for_exceptions(void* that, const char* s, diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view index e33e1bc4b79..dba757fad6b 100644 --- a/libstdc++-v3/include/std/string_view +++ b/libstdc++-v3/include/std/string_view @@ -352,6 +352,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return this->ends_with(basic_string_view(__x)); } #endif // C++20 +#if __cplusplus > 202002L +#define __cpp_lib_string_contains 202011L + constexpr bool + contains(basic_string_view __x) const noexcept + { return this->find(__x) != npos; } + + constexpr bool + contains(_CharT __x) const noexcept + { return this->find(__x) != npos; } + + constexpr bool + contains(const _CharT* __x) const noexcept + { return this->find(__x) != npos; } +#endif // C++23 + // [string.view.find], searching constexpr size_type diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index e3d52b88c21..ace87cf42cf 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -167,7 +167,7 @@ #endif #if __cplusplus > 201703L -// c++2a +// c++20 #define __cpp_lib_atomic_flag_test 201907L #define __cpp_lib_atomic_float 201711L #define __cpp_lib_atomic_ref 201806L @@ -256,7 +256,12 @@ #define __cpp_lib_to_address 201711L #define __cpp_lib_to_array 201907L #endif -#endif // C++2a + +#if __cplusplus > 202002L +// c++2b +#define __cpp_lib_string_contains 202011L +#endif // C++2b +#endif // C++20 #endif // C++17 #endif // C++14 #endif // C++11 diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/char/1.cc new file mode 100644 index 00000000000..d313bb553c8 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/char/1.cc @@ -0,0 +1,65 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +// Copyright (C) 2021 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// basic_string contains + +#include +#include + +void +test01() +{ + const std::string haystack("no place for needles"); + + VERIFY(haystack.contains(std::string(""))); + VERIFY(haystack.contains(std::string("no"))); + VERIFY(haystack.contains(std::string("needles"))); + VERIFY(haystack.contains(std::string(" for "))); + VERIFY(!haystack.contains(std::string("places"))); + + VERIFY(haystack.contains(std::string_view(""))); + VERIFY(haystack.contains(std::string_view("no"))); + VERIFY(haystack.contains(std::string_view("needles"))); + VERIFY(haystack.contains(std::string_view(" for "))); + VERIFY(!haystack.contains(std::string_view("places"))); + + VERIFY(!haystack.contains('\0')); + VERIFY(haystack.contains('n')); + VERIFY(haystack.contains('e')); + VERIFY(haystack.contains('s')); + VERIFY(!haystack.contains('x')); + + VERIFY(haystack.contains("")); + VERIFY(haystack.contains("no")); + VERIFY(haystack.contains("needles")); + VERIFY(haystack.contains(" for ")); + VERIFY(!haystack.contains("places")); + + const std::string nothing; + VERIFY(nothing.contains("")); + VERIFY(!nothing.contains('\0')); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/wchar_t/1.cc new file mode 100644 index 00000000000..14471f97dbd --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/wchar_t/1.cc @@ -0,0 +1,65 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +// Copyright (C) 2021 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// basic_string contains + +#include +#include + +void +test01() +{ + const std::wstring haystack(L"no place for needles"); + + VERIFY(haystack.contains(std::wstring(L""))); + VERIFY(haystack.contains(std::wstring(L"no"))); + VERIFY(haystack.contains(std::wstring(L"needles"))); + VERIFY(haystack.contains(std::wstring(L" for "))); + VERIFY(!haystack.contains(std::wstring(L"places"))); + + VERIFY(haystack.contains(std::wstring_view(L""))); + VERIFY(haystack.contains(std::wstring_view(L"no"))); + VERIFY(haystack.contains(std::wstring_view(L"needles"))); + VERIFY(haystack.contains(std::wstring_view(L" for "))); + VERIFY(!haystack.contains(std::wstring_view(L"places"))); + + VERIFY(!haystack.contains('\0')); + VERIFY(haystack.contains('n')); + VERIFY(haystack.contains('e')); + VERIFY(haystack.contains('s')); + VERIFY(!haystack.contains('x')); + + VERIFY(haystack.contains(L"")); + VERIFY(haystack.contains(L"no")); + VERIFY(haystack.contains(L"needles")); + VERIFY(haystack.contains(L" for ")); + VERIFY(!haystack.contains(L"places")); + + const std::wstring nothing; + VERIFY(nothing.contains(L"")); + VERIFY(!nothing.contains('\0')); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char/1.cc index 7445942679b..4f4a8d2c20c 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char/1.cc @@ -50,7 +50,7 @@ test01() int main() -{ +{ test01(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t/1.cc index 5c4e94aba75..022f128a2a0 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t/1.cc @@ -50,7 +50,7 @@ test01() int main() -{ +{ test01(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/1.cc new file mode 100644 index 00000000000..9aa87ad6a50 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/1.cc @@ -0,0 +1,57 @@ +// { dg-options "-std=gnu++23" } +// { dg-do compile { target c++23 } } + +// Copyright (C) 2021 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// basic_string_view contains + +#include + +#ifndef __cpp_lib_string_contains +# error "Feature-test macro for contains missing in " +#elif __cpp_lib_string_contains != 202011L +# error "Feature-test macro for contains has wrong value in " +#endif + +void +test01() +{ + constexpr std::string_view haystack("no place for needles"); + + static_assert(haystack.contains(std::string_view(""))); + static_assert(haystack.contains(std::string_view("no"))); + static_assert(haystack.contains(std::string_view("needles"))); + static_assert(haystack.contains(std::string_view(" for "))); + static_assert(!haystack.contains(std::string_view("places"))); + + static_assert(!haystack.contains('\0')); + static_assert(haystack.contains('n')); + static_assert(haystack.contains('e')); + static_assert(haystack.contains('s')); + static_assert(!haystack.contains('x')); + + static_assert(haystack.contains("")); + static_assert(haystack.contains("no")); + static_assert(haystack.contains("needles")); + static_assert(haystack.contains(" for ")); + static_assert(!haystack.contains("places")); + + constexpr std::string_view nothing; + static_assert(nothing.contains("")); + static_assert(!nothing.contains('\0')); +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/2.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/2.cc new file mode 100644 index 00000000000..8a9d783a63a --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/char/2.cc @@ -0,0 +1,27 @@ +// { dg-options "-std=gnu++23" } +// { dg-do compile { target c++23 } } + +// Copyright (C) 2021 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include + +#ifndef __cpp_lib_string_contains +# error "Feature-test macro for contains missing in " +#elif __cpp_lib_string_contains != 202011L +# error "Feature-test macro for contains has wrong value in " +#endif diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/wchar_t/1.cc new file mode 100644 index 00000000000..b01bea12384 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/wchar_t/1.cc @@ -0,0 +1,51 @@ +// { dg-options "-std=gnu++23" } +// { dg-do compile { target c++23 } } + +// Copyright (C) 2021 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// basic_string_view contains + +#include + +void +test01() +{ + constexpr std::wstring_view haystack = L"no place for needles"; + + static_assert(haystack.contains(std::wstring_view(L""))); + static_assert(haystack.contains(std::wstring_view(L"no"))); + static_assert(haystack.contains(std::wstring_view(L"needles"))); + static_assert(haystack.contains(std::wstring_view(L" for "))); + static_assert(!haystack.contains(std::wstring_view(L"places"))); + + static_assert(!haystack.contains('\0')); + static_assert(haystack.contains('n')); + static_assert(haystack.contains('e')); + static_assert(haystack.contains('s')); + static_assert(!haystack.contains('x')); + + static_assert(haystack.contains(L"")); + static_assert(haystack.contains(L"no")); + static_assert(haystack.contains(L"needles")); + static_assert(haystack.contains(L" for ")); + static_assert(!haystack.contains(L"places")); + + constexpr std::wstring_view nothing; + static_assert(nothing.contains(L"")); + static_assert(!nothing.contains('\0')); +}