From 6ed40418914b6439edd995298268d60e2df0cce4 Mon Sep 17 00:00:00 2001 From: Piotr Fusik Date: Sun, 16 Jul 2023 15:18:20 +0200 Subject: [PATCH] [libc++] Implement ostringstream members of P0408R7 (Efficient Access to basic_stringbuf's Buffer) Reviewed By: #libc, Mordante Differential Revision: https://reviews.llvm.org/D155276 --- libcxx/docs/Status/Cxx20.rst | 2 +- libcxx/include/sstream | 90 +++++++++++++++++----- .../ostringstream.cons/mode.alloc.pass.cpp | 38 +++++++++ .../ostringstream.cons/string-alloc.mode.pass.cpp | 49 ++++++++++++ .../ostringstream.cons/string.alloc.pass.cpp | 45 +++++++++++ .../ostringstream.cons/string.mode.alloc.pass.cpp | 44 +++++++++++ .../ostringstream.cons/string.move.mode.pass.cpp | 46 +++++++++++ .../ostringstream.members/str.alloc.pass.cpp | 44 +++++++++++ .../ostringstream.members/str.move.pass.cpp | 42 ++++++++++ .../str.string-alloc.pass.cpp | 45 +++++++++++ .../ostringstream.members/str.string.move.pass.cpp | 42 ++++++++++ 11 files changed, 468 insertions(+), 19 deletions(-) create mode 100644 libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/mode.alloc.pass.cpp create mode 100644 libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string-alloc.mode.pass.cpp create mode 100644 libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.alloc.pass.cpp create mode 100644 libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.mode.alloc.pass.cpp create mode 100644 libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.move.mode.pass.cpp create mode 100644 libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.alloc.pass.cpp create mode 100644 libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.move.pass.cpp create mode 100644 libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.string-alloc.pass.cpp create mode 100644 libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.string.move.pass.cpp diff --git a/libcxx/docs/Status/Cxx20.rst b/libcxx/docs/Status/Cxx20.rst index fa296f3..5b6b792 100644 --- a/libcxx/docs/Status/Cxx20.rst +++ b/libcxx/docs/Status/Cxx20.rst @@ -49,7 +49,7 @@ Paper Status .. [#note-P0883.1] P0883: shared_ptr and floating-point changes weren't applied as they themselves aren't implemented yet. .. [#note-P0883.2] P0883: ``ATOMIC_FLAG_INIT`` was marked deprecated in version 14.0, but was undeprecated with the implementation of LWG3659 in version 15.0. .. [#note-P2231] P2231: Optional is complete. The changes to variant haven't been implemented yet. - .. [#note-P0408] P0408: All `stringbuf` and `istringstream` members plus `view()` in all classes implemented. + .. [#note-P0408] P0408: Implemented all `stringbuf`/`istringstream`/`ostringstream` members and `view()` in `stringstream`. .. [#note-P0660] P0660: Section 32.3 Stop Tokens is complete. ``jthread`` hasn't been implemented yet. .. _issues-status-cxx20: diff --git a/libcxx/include/sstream b/libcxx/include/sstream index 4c7ec48d..342e024 100644 --- a/libcxx/include/sstream +++ b/libcxx/include/sstream @@ -159,12 +159,23 @@ public: typedef Allocator allocator_type; // [ostringstream.cons] Constructors: - explicit basic_ostringstream(ios_base::openmode which = ios_base::out); // before C++20 - basic_ostringstream() : basic_ostringstream(ios_base::out) {} // C++20 - explicit basic_ostringstream(ios_base::openmode which); // C++20 - - explicit basic_ostringstream(const basic_string& str, + explicit basic_ostringstream(ios_base::openmode which = ios_base::out); // before C++20 + basic_ostringstream() : basic_ostringstream(ios_base::out) {} // C++20 + explicit basic_ostringstream(ios_base::openmode which); // C++20 + explicit basic_ostringstream(const basic_string& s, ios_base::openmode which = ios_base::out); + basic_ostringstream(ios_base::openmode which, const allocator_type& a); // C++20 + explicit basic_ostringstream(basic_string&& s, + ios_base::openmode which = ios_base::out); // C++20 + template + basic_ostringstream(const basic_string& s, const allocator_type& a) + : basic_ostringstream(s, ios_base::out, a) {} // C++20 + template + basic_ostringstream(const basic_string& s, + ios_base::openmode which, const allocator_type& a); // C++20 + template + explicit basic_ostringstream(const basic_string& s, + ios_base::openmode which = ios_base::out); // C++20 basic_ostringstream(basic_ostringstream&& rhs); // [ostringstream.assign] Assign and swap: @@ -173,9 +184,16 @@ public: // [ostringstream.members] Member functions: basic_stringbuf* rdbuf() const; - basic_string str() const; + basic_string str() const; // before C++20 + basic_string str() const &; // C++20 + template + basic_string str(const SAlloc& sa) const; // C++20 + basic_string str() &&; // C++20 + basic_string_view view() const noexcept; // C++20 void str(const basic_string& s); - basic_string_view view() const noexcept; // C++20 + template + void str(const basic_string& s); // C++20 + void str(basic_string&& s); // C++20 }; template @@ -929,6 +947,29 @@ public: , __sb_(__s, __wch | ios_base::out) { } +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI basic_ostringstream(ios_base::openmode __wch, const _Allocator& __a) + : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__wch | ios_base::out, __a) {} + + _LIBCPP_HIDE_FROM_ABI explicit basic_ostringstream(string_type&& __s, ios_base::openmode __wch = ios_base::out) + : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(std::move(__s), __wch | ios_base::out) {} + + template + _LIBCPP_HIDE_FROM_ABI basic_ostringstream(const basic_string<_CharT, _Traits, _SAlloc>& __s, const _Allocator& __a) + : basic_ostringstream(__s, ios_base::out, __a) {} + + template + _LIBCPP_HIDE_FROM_ABI basic_ostringstream( + const basic_string<_CharT, _Traits, _SAlloc>& __s, ios_base::openmode __wch, const _Allocator& __a) + : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch | ios_base::out, __a) {} + + template + requires (!is_same_v<_SAlloc, allocator_type>) + _LIBCPP_HIDE_FROM_ABI explicit basic_ostringstream(const basic_string<_CharT, _Traits, _SAlloc>& __s, + ios_base::openmode __wch = ios_base::out) + : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch | ios_base::out) {} +#endif // _LIBCPP_STD_VER >= 20 + _LIBCPP_INLINE_VISIBILITY basic_ostringstream(basic_ostringstream&& __rhs) : basic_ostream<_CharT, _Traits>(_VSTD::move(__rhs)) @@ -955,20 +996,33 @@ public: basic_stringbuf* rdbuf() const { return const_cast*>(&__sb_); } - _LIBCPP_INLINE_VISIBILITY - string_type str() const { - return __sb_.str(); - } - _LIBCPP_INLINE_VISIBILITY - void str(const string_type& __s) { - __sb_.str(__s); + +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI string_type str() const & { return __sb_.str(); } + + template + requires __is_allocator<_SAlloc>::value + _LIBCPP_HIDE_FROM_ABI basic_string str(const _SAlloc& __sa) const { + return __sb_.str(__sa); } + + _LIBCPP_HIDE_FROM_ABI string_type str() && { return std::move(__sb_).str(); } + + _LIBCPP_HIDE_FROM_ABI basic_string_view view() const noexcept { return __sb_.view(); } +#else // _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI string_type str() const { return __sb_.str(); } +#endif // _LIBCPP_STD_VER >= 20 + + _LIBCPP_HIDE_FROM_ABI void str(const string_type& __s) { __sb_.str(__s); } + #if _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI - basic_string_view view() const noexcept { - return __sb_.view(); + template + _LIBCPP_HIDE_FROM_ABI void str(const basic_string& __s) { + __sb_.str(__s); } -#endif + + _LIBCPP_HIDE_FROM_ABI void str(string_type&& __s) { __sb_.str(std::move(__s)); } +#endif // _LIBCPP_STD_VER >= 20 }; template diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/mode.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/mode.alloc.pass.cpp new file mode 100644 index 0000000..6b6dc8f --- /dev/null +++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/mode.alloc.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template , class Allocator = allocator> +// class basic_ostringstream + +// basic_ostringstream(ios_base::openmode which, const Allocator& a); + +#include +#include + +#include "test_allocator.h" +#include "test_macros.h" + +template +static void test() { + const test_allocator a(2); + const std::basic_ostringstream, test_allocator> ss(std::ios_base::binary, a); + assert(ss.rdbuf()->get_allocator() == a); + assert(ss.view().empty()); +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + return 0; +} diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string-alloc.mode.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string-alloc.mode.pass.cpp new file mode 100644 index 0000000..36b615f --- /dev/null +++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string-alloc.mode.pass.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template , class Allocator = allocator> +// class basic_ostringstream + +// template +// explicit basic_ostringstream(const basic_string& s, ios_base::openmode which = ios_base::out) + +#include +#include + +#include "make_string.h" +#include "test_allocator.h" +#include "test_macros.h" + +#define STR(S) MAKE_STRING(CharT, S) +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static void test() { + { + const std::basic_string s(STR("testing")); + const std::basic_ostringstream, test_allocator> ss(s); + assert(ss.view() == SV("testing")); + } + { + const std::basic_string s(STR("testing")); + const std::basic_ostringstream, test_allocator> ss(s, std::ios_base::binary); + assert(ss.view() == SV("testing")); + } +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + return 0; +} diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.alloc.pass.cpp new file mode 100644 index 0000000..1425988 --- /dev/null +++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.alloc.pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template , class Allocator = allocator> +// class basic_ostringstream + +// template +// basic_ostringstream(const basic_string& s, const Allocator& a) +// : basic_ostringstream(s, ios_base::out, a) {} + +#include +#include + +#include "make_string.h" +#include "test_allocator.h" +#include "test_macros.h" + +#define STR(S) MAKE_STRING(CharT, S) +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static void test() { + const std::basic_string s(STR("testing")); + const test_allocator a(2); + const std::basic_ostringstream, test_allocator> ss(s, a); + assert(ss.rdbuf()->get_allocator() == a); + assert(ss.view() == SV("testing")); +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + return 0; +} diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.mode.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.mode.alloc.pass.cpp new file mode 100644 index 0000000..18365e6 --- /dev/null +++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.mode.alloc.pass.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template , class Allocator = allocator> +// class basic_ostringstream + +// template +// basic_ostringstream(const basic_string& s, ios_base::openmode which, const Allocator& a) + +#include +#include + +#include "make_string.h" +#include "test_allocator.h" +#include "test_macros.h" + +#define STR(S) MAKE_STRING(CharT, S) +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static void test() { + const std::basic_string s(STR("testing")); + const test_allocator a(2); + const std::basic_ostringstream, test_allocator> ss(s, std::ios_base::binary, a); + assert(ss.rdbuf()->get_allocator() == a); + assert(ss.view() == SV("testing")); +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + return 0; +} diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.move.mode.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.move.mode.pass.cpp new file mode 100644 index 0000000..e24ac5c --- /dev/null +++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/string.move.mode.pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template , class Allocator = allocator> +// class basic_ostringstream + +// explicit basic_ostringstream(basic_string&& s, ios_base::openmode which = ios_base::out); + +#include +#include + +#include "make_string.h" +#include "test_macros.h" + +#define STR(S) MAKE_STRING(CharT, S) + +template +static void test() { + { + std::basic_string s(STR("testing")); + const std::basic_ostringstream ss(std::move(s)); + assert(ss.str() == STR("testing")); + } + { + std::basic_string s(STR("testing")); + const std::basic_ostringstream ss(std::move(s), std::ios_base::binary); + assert(ss.str() == STR("testing")); + } +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + return 0; +} diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.alloc.pass.cpp new file mode 100644 index 0000000..f01d953 --- /dev/null +++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.alloc.pass.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template , class Allocator = allocator> +// class basic_ostringstream + +// template +// basic_string str(const SAlloc& sa) const; + +#include +#include + +#include "make_string.h" +#include "test_allocator.h" +#include "test_macros.h" + +#define STR(S) MAKE_STRING(CharT, S) +#define SV(S) MAKE_STRING_VIEW(CharT, S) + +template +static void test() { + const std::basic_ostringstream ss(STR("testing")); + const test_allocator a(1); + const std::basic_string, test_allocator> s = ss.str(a); + assert(s == SV("testing")); + assert(s.get_allocator() == a); +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + return 0; +} diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.move.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.move.pass.cpp new file mode 100644 index 0000000..5fbdf81 --- /dev/null +++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.move.pass.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template , class Allocator = allocator> +// class basic_ostringstream + +// basic_string str() &&; + +#include +#include + +#include "make_string.h" +#include "test_macros.h" + +#define STR(S) MAKE_STRING(CharT, S) + +template +static void test() { + { + std::basic_ostringstream ss(STR("testing")); + std::basic_string s = std::move(ss).str(); + assert(s == STR("testing")); + assert(ss.view().empty()); + } +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + return 0; +} diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.string-alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.string-alloc.pass.cpp new file mode 100644 index 0000000..4e5356c --- /dev/null +++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.string-alloc.pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template , class Allocator = allocator> +// class basic_ostringstream + +// template +// void str(const basic_string& s); + +#include +#include + +#include "make_string.h" +#include "test_allocator.h" +#include "test_macros.h" + +#define STR(S) MAKE_STRING(CharT, S) + +template +static void test() { + { + const test_allocator a(6); + const std::basic_string, test_allocator> s(STR("testing"), a); + std::basic_ostringstream ss; + ss.str(s); + assert(ss.str() == STR("testing")); + } +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + return 0; +} diff --git a/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.string.move.pass.cpp b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.string.move.pass.cpp new file mode 100644 index 0000000..532ae77 --- /dev/null +++ b/libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.string.move.pass.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template , class Allocator = allocator> +// class basic_ostringstream + +// void str(basic_string&& s); + +#include +#include + +#include "make_string.h" +#include "test_macros.h" + +#define STR(S) MAKE_STRING(CharT, S) + +template +static void test() { + { + std::basic_ostringstream ss; + std::basic_string s(STR("testing")); + ss.str(std::move(s)); + assert(ss.str() == STR("testing")); + } +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + return 0; +} -- 2.7.4