Re: [PATCH, libstdc++, C++20] Implement P0457R2 String Prefix and Suffix Checking.

2018-11-30 Thread Ed Smith-Rowland

On 11/30/18 5:33 AM, Jonathan Wakely wrote:

On 29/11/18 21:35 -0500, Ed Smith-Rowland wrote:

Greetings,

This patch implements starts_with and ends_with for basic_string and 
basic_string_view for C++20.


This was on my TODO list, thanks for taking care of it.


+#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


This can be noexcept. It isn't in the standard, because it has a
narrow contract (there's a precondition that __x is null-terminated).
But since we can't reliably detect whether __x is null-terminated, and
even if we could we wouldn't want to throw an exception, we can just
make it noexcept. Same for the ends_with(const _CharT*) one, and the
equivalent members in the COW basic_string and basic_string_view.


Index: include/std/string_view
===
--- include/std/string_view    (revision 266645)
+++ include/std/string_view    (working copy)
@@ -227,7 +227,6 @@
__sv = __tmp;
  }

-
  // [string.view.ops], string operations:

  size_type
@@ -387,6 +386,36 @@
  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; }


Please put the opening and closing braces on their own lines, as for
ends_with below:


+  constexpr bool
+  ends_with(basic_string_view __x) const noexcept
+  {
+    return this->size() >= __x.size()
+    && this->compare(this->size() - __x.size(), npos, __x) == 0;
+  }


OK with those changes, thanks


Committed 266674.

New patch attached.

Ed



2018-11-30  Edward Smith-Rowland  <3dw...@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.

Index: include/bits/basic_string.h
===
--- include/bits/basic_string.h (revision 266671)
+++ include/bits/basic_string.h (working copy)
@@ -3038,6 +3038,32 @@
   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 @@
   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(), 

Re: [PATCH, libstdc++, C++20] Implement P0457R2 String Prefix and Suffix Checking.

2018-11-30 Thread Jonathan Wakely

On 29/11/18 21:35 -0500, Ed Smith-Rowland wrote:

Greetings,

This patch implements starts_with and ends_with for basic_string and 
basic_string_view for C++20.


This was on my TODO list, thanks for taking care of it.


+#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


This can be noexcept. It isn't in the standard, because it has a
narrow contract (there's a precondition that __x is null-terminated).
But since we can't reliably detect whether __x is null-terminated, and
even if we could we wouldn't want to throw an exception, we can just
make it noexcept. Same for the ends_with(const _CharT*) one, and the
equivalent members in the COW basic_string and basic_string_view.


Index: include/std/string_view
===
--- include/std/string_view (revision 266645)
+++ include/std/string_view (working copy)
@@ -227,7 +227,6 @@
__sv = __tmp;
  }

-
  // [string.view.ops], string operations:

  size_type
@@ -387,6 +386,36 @@
  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; }


Please put the opening and closing braces on their own lines, as for
ends_with below:


+  constexpr bool
+  ends_with(basic_string_view __x) const noexcept
+  {
+   return this->size() >= __x.size()
+   && this->compare(this->size() - __x.size(), npos, __x) == 0;
+  }


OK with those changes, thanks.




[PATCH, libstdc++, C++20] Implement P0457R2 String Prefix and Suffix Checking.

2018-11-29 Thread Ed Smith-Rowland

Greetings,

This patch implements starts_with and ends_with for basic_string and 
basic_string_view for C++20.


This builds and tests cleanly on x86_64-linux.

Ed



2018-11-30  Edward Smith-Rowland  <3dw...@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.

Index: include/bits/basic_string.h
===
--- include/bits/basic_string.h (revision 266645)
+++ include/bits/basic_string.h (working copy)
@@ -3038,6 +3038,32 @@
   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
+  { 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
+  { 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 @@
   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
+  { 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
+  { 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,
Index: include/std/string_view
===
--- include/std/string_view (revision 266645)
+++ include/std/string_view (working copy)
@@ -227,7 +227,6 @@
__sv = __tmp;
   }
 
-
   // [string.view.ops], string operations:
 
   size_type
@@ -387,6 +386,36 @@
  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
+  { 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
+  { return