diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 7b75b10b5ce..73d5b1c460e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,25 @@ +2018-11-30 Edward Smith-Rowland <3dw4rd@verizon.net> + + Implement P0457R2 String Prefix and Suffix Checking. + * include/bits/basic_string.h: Add starts_with, ends_with members. + * include/std/string_view: Ditto. + * testsuite/21_strings/basic_string/operations/starts_with/ + char/1.cc: New test. + * testsuite/21_strings/basic_string/operations/starts_with/ + wchar_t/1.cc: New test. + * testsuite/21_strings/basic_string/operations/ends_with/ + char/1.cc: New test. + * testsuite/21_strings/basic_string/operations/ends_with/ + wchar_t/1.cc: New test. + * testsuite/21_strings/basic_string_view/operations/starts_with/ + char/1.cc: New test. + * testsuite/21_strings/basic_string_view/operations/starts_with/ + wchar_t/1.cc: New test. + * testsuite/21_strings/basic_string_view/operations/ends_with/ + char/1.cc: New test. + * testsuite/21_strings/basic_string_view/operations/ends_with/ + wchar_t/1.cc: New test. + 2018-11-30 Edward Smith-Rowland <3dw4rd@verizon.net> Pre-emptively support P0646R1 for std container erasure. @@ -10,6 +32,7 @@ * include/std/unordered_map (): Ditto. * include/std/unordered_set (): Ditto. * include/std/vector (): Ditto. + * include/std/deque (): Ditto. * testsuite/21_strings/basic_string/erasure.cc: Test number of erasures. * testsuite/23_containers/deque/erasure.cc: Ditto. * testsuite/23_containers/forward_list/erasure.cc: Ditto. diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index ae6530fcdc9..a2573d382b0 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -3038,6 +3038,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 compare(size_type __pos, size_type __n1, const _CharT* __s, size_type __n2) const; +#if __cplusplus > 201703L + bool + starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept + { return __sv_type(this->data(), this->size()).starts_with(__x); } + + bool + starts_with(_CharT __x) const noexcept + { return __sv_type(this->data(), this->size()).starts_with(__x); } + + bool + starts_with(const _CharT* __x) const noexcept + { return __sv_type(this->data(), this->size()).starts_with(__x); } + + bool + ends_with(basic_string_view<_CharT, _Traits> __x) const noexcept + { return __sv_type(this->data(), this->size()).ends_with(__x); } + + bool + ends_with(_CharT __x) const noexcept + { return __sv_type(this->data(), this->size()).ends_with(__x); } + + bool + ends_with(const _CharT* __x) const noexcept + { return __sv_type(this->data(), this->size()).ends_with(__x); } +#endif // C++20 + // Allow basic_stringbuf::__xfer_bufptrs to call _M_length: template friend class basic_stringbuf; }; @@ -5884,6 +5910,32 @@ _GLIBCXX_END_NAMESPACE_CXX11 compare(size_type __pos, size_type __n1, const _CharT* __s, size_type __n2) const; +#if __cplusplus > 201703L + bool + starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept + { return __sv_type(this->data(), this->size()).starts_with(__x); } + + bool + starts_with(_CharT __x) const noexcept + { return __sv_type(this->data(), this->size()).starts_with(__x); } + + bool + starts_with(const _CharT* __x) const noexcept + { return __sv_type(this->data(), this->size()).starts_with(__x); } + + bool + ends_with(basic_string_view<_CharT, _Traits> __x) const noexcept + { return __sv_type(this->data(), this->size()).ends_with(__x); } + + bool + ends_with(_CharT __x) const noexcept + { return __sv_type(this->data(), this->size()).ends_with(__x); } + + bool + ends_with(const _CharT* __x) const noexcept + { return __sv_type(this->data(), this->size()).ends_with(__x); } +#endif // C++20 + # 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 b4d9cf56a9d..28d3fa46718 100644 --- a/libstdc++-v3/include/std/string_view +++ b/libstdc++-v3/include/std/string_view @@ -227,7 +227,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __sv = __tmp; } - // [string.view.ops], string operations: size_type @@ -387,6 +386,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION traits_type::length(__str)); } +#if __cplusplus > 201703L + constexpr bool + starts_with(basic_string_view __x) const noexcept + { + return this->size() >= __x.size() + && this->compare(0, __x.size(), __x) == 0; + } + + constexpr bool + starts_with(_CharT __x) const noexcept + { return this->starts_with(basic_string_view(&__x, 1)); } + + constexpr bool + starts_with(const _CharT* __x) const noexcept + { return this->starts_with(basic_string_view(__x)); } + + constexpr bool + ends_with(basic_string_view __x) const noexcept + { + return this->size() >= __x.size() + && this->compare(this->size() - __x.size(), npos, __x) == 0; + } + + constexpr bool + ends_with(_CharT __x) const noexcept + { return this->ends_with(basic_string_view(&__x, 1)); } + + constexpr bool + ends_with(const _CharT* __x) const noexcept + { return this->ends_with(basic_string_view(__x)); } +#endif // C++20 + constexpr size_type _M_check(size_type __pos, const char* __s) const noexcept(false) { diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/char/1.cc new file mode 100644 index 00000000000..1b0bdae8116 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/char/1.cc @@ -0,0 +1,56 @@ +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +// Copyright (C) 2018 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 ends_with + +#include +#include + +void +test01() +{ + const char cstr_suf[] = ".jpg"; + const std::string_view sv_suf(".jpg"); + const char cstr_suf2[] = ".rgb"; + const std::string_view sv_suf2(".rgb"); + + const std::string s_test("slugs/slimy.jpg"); + + const auto cstr_in_slugs = s_test.ends_with(cstr_suf); + VERIFY( cstr_in_slugs ); + const auto sv_in_slugs = s_test.ends_with(sv_suf); + VERIFY( sv_in_slugs ); + const auto char_g = s_test.ends_with('g'); + VERIFY( char_g ); + + const auto cstr_in_worms = s_test.ends_with(cstr_suf2); + VERIFY( !cstr_in_worms ); + const auto sv_in_worms = s_test.ends_with(sv_suf2); + VERIFY( !sv_in_worms ); + const auto char_b = s_test.ends_with('b'); + VERIFY( !char_b ); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/wchar_t/1.cc new file mode 100644 index 00000000000..0e95da34dce --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/wchar_t/1.cc @@ -0,0 +1,56 @@ +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +// Copyright (C) 2018 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 ends_with + +#include +#include + +void +test01() +{ + const wchar_t cstr_suf[] = L".jpg"; + const std::wstring_view sv_suf(L".jpg"); + const wchar_t cstr_suf2[] = L".rgb"; + const std::wstring_view sv_suf2(L".rgb"); + + const std::wstring s_test(L"slugs/slimy.jpg"); + + const auto cstr_in_slugs = s_test.ends_with(cstr_suf); + VERIFY( cstr_in_slugs ); + const auto sv_in_slugs = s_test.ends_with(sv_suf); + VERIFY( sv_in_slugs ); + const auto char_g = s_test.ends_with(L'g'); + VERIFY( char_g ); + + const auto cstr_in_worms = s_test.ends_with(cstr_suf2); + VERIFY( !cstr_in_worms ); + const auto sv_in_worms = s_test.ends_with(sv_suf2); + VERIFY( !sv_in_worms ); + const auto char_b = s_test.ends_with(L'b'); + VERIFY( !char_b ); +} + +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 new file mode 100644 index 00000000000..233bf948efd --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char/1.cc @@ -0,0 +1,56 @@ +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +// Copyright (C) 2018 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 begins_with + +#include +#include + +void +test01() +{ + const char cstr_dir[] = "slugs/"; + const std::string_view sv_dir("slugs/"); + const char cstr_dir2[] = "worms/"; + const std::string_view sv_dir2("worms/"); + + const std::string s_test("slugs/slimy.jpg"); + + const auto cstr_in_slugs = s_test.starts_with(cstr_dir); + VERIFY( cstr_in_slugs ); + const auto sv_in_slugs = s_test.starts_with(sv_dir); + VERIFY( sv_in_slugs ); + const auto char_s = s_test.starts_with('s'); + VERIFY( char_s ); + + const auto cstr_in_worms = s_test.starts_with(cstr_dir2); + VERIFY( !cstr_in_worms ); + const auto sv_in_worms = s_test.starts_with(sv_dir2); + VERIFY( !sv_in_worms ); + const auto char_w = s_test.starts_with('w'); + VERIFY( !char_w ); +} + +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 new file mode 100644 index 00000000000..92f269a14a9 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t/1.cc @@ -0,0 +1,56 @@ +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +// Copyright (C) 2018 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 begins_with + +#include +#include + +void +test01() +{ + const wchar_t cstr_dir[] = L"slugs/"; + const std::wstring_view sv_dir(L"slugs/"); + const wchar_t cstr_dir2[] = L"worms/"; + const std::wstring_view sv_dir2(L"worms/"); + + const std::wstring s_test(L"slugs/slimy.jpg"); + + const auto cstr_in_slugs = s_test.starts_with(cstr_dir); + VERIFY( cstr_in_slugs ); + const auto sv_in_slugs = s_test.starts_with(sv_dir); + VERIFY( sv_in_slugs ); + const auto char_s = s_test.starts_with(L's'); + VERIFY( char_s ); + + const auto cstr_in_worms = s_test.starts_with(cstr_dir2); + VERIFY( !cstr_in_worms ); + const auto sv_in_worms = s_test.starts_with(sv_dir2); + VERIFY( !sv_in_worms ); + const auto char_w = s_test.starts_with(L'w'); + VERIFY( !char_w ); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/char/1.cc new file mode 100644 index 00000000000..90d5d6c6d89 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/char/1.cc @@ -0,0 +1,48 @@ +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +// Copyright (C) 2018 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 ends_with + +#include + +void +test01() +{ + constexpr char cstr_suf[] = ".jpg"; + constexpr std::string_view sv_suf(".jpg"); + constexpr char cstr_suf2[] = ".rgb"; + constexpr std::string_view sv_suf2(".rgb"); + + constexpr std::string_view sv_test("slugs/slimy.jpg"); + + constexpr auto cstr_in_slugs = sv_test.ends_with(cstr_suf); + static_assert(cstr_in_slugs); + constexpr auto sv_in_slugs = sv_test.ends_with(sv_suf); + static_assert(sv_in_slugs); + constexpr auto char_g = sv_test.ends_with('g'); + static_assert(char_g); + + constexpr auto cstr_in_worms = sv_test.ends_with(cstr_suf2); + static_assert(!cstr_in_worms); + constexpr auto sv_in_worms = sv_test.ends_with(sv_suf2); + static_assert(!sv_in_worms); + constexpr auto char_b = sv_test.ends_with('b'); + static_assert(!char_b); +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/wchar_t/1.cc new file mode 100644 index 00000000000..c23ac6079a0 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/wchar_t/1.cc @@ -0,0 +1,48 @@ +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +// Copyright (C) 2018 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 ends_with + +#include + +void +test01() +{ + constexpr wchar_t cstr_suf[] = L".jpg"; + constexpr std::wstring_view sv_suf(L".jpg"); + constexpr wchar_t cstr_suf2[] = L".rgb"; + constexpr std::wstring_view sv_suf2(L".rgb"); + + constexpr std::wstring_view sv_test(L"slugs/slimy.jpg"); + + constexpr auto cstr_in_slugs = sv_test.ends_with(cstr_suf); + static_assert(cstr_in_slugs); + constexpr auto sv_in_slugs = sv_test.ends_with(sv_suf); + static_assert(sv_in_slugs); + constexpr auto char_g = sv_test.ends_with(L'g'); + static_assert(char_g); + + constexpr auto cstr_in_worms = sv_test.ends_with(cstr_suf2); + static_assert(!cstr_in_worms); + constexpr auto sv_in_worms = sv_test.ends_with(sv_suf2); + static_assert(!sv_in_worms); + constexpr auto char_b = sv_test.ends_with(L'b'); + static_assert(!char_b); +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/char/1.cc new file mode 100644 index 00000000000..3d77276b639 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/char/1.cc @@ -0,0 +1,48 @@ +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +// Copyright (C) 2018 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 begins_with + +#include + +void +test01() +{ + constexpr char cstr_dir[] = "slugs/"; + constexpr std::string_view sv_dir("slugs/"); + constexpr char cstr_dir2[] = "worms/"; + constexpr std::string_view sv_dir2("worms/"); + + constexpr std::string_view sv_test("slugs/slimy.jpg"); + + constexpr auto cstr_in_slugs = sv_test.starts_with(cstr_dir); + static_assert(cstr_in_slugs); + constexpr auto sv_in_slugs = sv_test.starts_with(sv_dir); + static_assert(sv_in_slugs); + constexpr auto char_s = sv_test.starts_with('s'); + static_assert(char_s); + + constexpr auto cstr_in_worms = sv_test.starts_with(cstr_dir2); + static_assert(!cstr_in_worms); + constexpr auto sv_in_worms = sv_test.starts_with(sv_dir2); + static_assert(!sv_in_worms); + constexpr auto char_w = sv_test.starts_with('w'); + static_assert(!char_w); +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/wchar_t/1.cc new file mode 100644 index 00000000000..854efb8eb04 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/wchar_t/1.cc @@ -0,0 +1,48 @@ +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +// Copyright (C) 2018 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 begins_with + +#include + +void +test01() +{ + constexpr wchar_t cstr_dir[] = L"slugs/"; + constexpr std::wstring_view sv_dir(L"slugs/"); + constexpr wchar_t cstr_dir2[] = L"worms/"; + constexpr std::wstring_view sv_dir2(L"worms/"); + + constexpr std::wstring_view sv_test(L"slugs/slimy.jpg"); + + constexpr auto cstr_in_slugs = sv_test.starts_with(cstr_dir); + static_assert(cstr_in_slugs); + constexpr auto sv_in_slugs = sv_test.starts_with(sv_dir); + static_assert(sv_in_slugs); + constexpr auto char_s = sv_test.starts_with(L's'); + static_assert(char_s); + + constexpr auto cstr_in_worms = sv_test.starts_with(cstr_dir2); + static_assert(!cstr_in_worms); + constexpr auto sv_in_worms = sv_test.starts_with(sv_dir2); + static_assert(!sv_in_worms); + constexpr auto char_w = sv_test.starts_with(L'w'); + static_assert(!char_w); +}