mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 05:40:09 +00:00
Implement syncstream (p0053)
This patch implements `std::basic_syncbuf` and `std::basic_osyncstream` as specified in paper p0053r7. ~~For ease of reviewing I am submitting this patch before submitting a patch for `std::basic_osyncstream`. ~~ ~~Please note, this patch is not 100% complete. I plan on adding more tests (see comments), specifically I plan on adding tests for multithreading and synchronization.~~ Edit: I decided that it would be far easier for me to keep track of this and make changes that affect both `std::basic_syncbuf` and `std::basic_osyncstream` if both were in one patch. The patch was originally written by @zoecarver Implements - P0053R7 - C++ Synchronized Buffered Ostream - LWG-3127 basic_osyncstream::rdbuf needs a const_cast - LWG-3334 basic_osyncstream move assignment and destruction calls basic_syncbuf::emit() twice - LWG-3570 basic_osyncstream::emit should be an unformatted output function - LWG-3867 Should std::basic_osyncstream's move assignment operator be noexcept? Reviewed By: ldionne, #libc Differential Revision: https://reviews.llvm.org/D67086
This commit is contained in:
parent
f1b0a54451
commit
7cc72a0a2e
@ -286,7 +286,7 @@ Status
|
|||||||
--------------------------------------------------- -----------------
|
--------------------------------------------------- -----------------
|
||||||
``__cpp_lib_string_view`` ``201803L``
|
``__cpp_lib_string_view`` ``201803L``
|
||||||
--------------------------------------------------- -----------------
|
--------------------------------------------------- -----------------
|
||||||
``__cpp_lib_syncbuf`` *unimplemented*
|
``__cpp_lib_syncbuf`` ``201803L``
|
||||||
--------------------------------------------------- -----------------
|
--------------------------------------------------- -----------------
|
||||||
``__cpp_lib_three_way_comparison`` *unimplemented*
|
``__cpp_lib_three_way_comparison`` *unimplemented*
|
||||||
--------------------------------------------------- -----------------
|
--------------------------------------------------- -----------------
|
||||||
|
@ -47,6 +47,7 @@ Implemented Papers
|
|||||||
- P2443R1 - ``views::chunk_by``
|
- P2443R1 - ``views::chunk_by``
|
||||||
- P2538R1 - ADL-proof ``std::projected``
|
- P2538R1 - ADL-proof ``std::projected``
|
||||||
- P2614R2 - Deprecate ``numeric_limits::has_denorm``
|
- P2614R2 - Deprecate ``numeric_limits::has_denorm``
|
||||||
|
- P0053R7 - C++ Synchronized Buffered Ostream (in the experimental library)
|
||||||
|
|
||||||
|
|
||||||
Improvements and New Features
|
Improvements and New Features
|
||||||
|
@ -114,7 +114,7 @@
|
|||||||
"`3096 <https://wg21.link/LWG3096>`__","``path::lexically_relative``\ is confused by trailing slashes","San Diego","|Complete|",""
|
"`3096 <https://wg21.link/LWG3096>`__","``path::lexically_relative``\ is confused by trailing slashes","San Diego","|Complete|",""
|
||||||
"`3116 <https://wg21.link/LWG3116>`__","``OUTERMOST_ALLOC_TRAITS``\ needs ``remove_reference_t``\ ","San Diego","",""
|
"`3116 <https://wg21.link/LWG3116>`__","``OUTERMOST_ALLOC_TRAITS``\ needs ``remove_reference_t``\ ","San Diego","",""
|
||||||
"`3122 <https://wg21.link/LWG3122>`__","``__cpp_lib_chrono_udls``\ was accidentally dropped","San Diego","|Complete|",""
|
"`3122 <https://wg21.link/LWG3122>`__","``__cpp_lib_chrono_udls``\ was accidentally dropped","San Diego","|Complete|",""
|
||||||
"`3127 <https://wg21.link/LWG3127>`__","``basic_osyncstream::rdbuf``\ needs a ``const_cast``\ ","San Diego","",""
|
"`3127 <https://wg21.link/LWG3127>`__","``basic_osyncstream::rdbuf``\ needs a ``const_cast``\ ","San Diego","|Complete|","18.0"
|
||||||
"`3128 <https://wg21.link/LWG3128>`__","``strstream::rdbuf``\ needs a ``const_cast``\ ","San Diego","|Nothing To Do|",""
|
"`3128 <https://wg21.link/LWG3128>`__","``strstream::rdbuf``\ needs a ``const_cast``\ ","San Diego","|Nothing To Do|",""
|
||||||
"`3129 <https://wg21.link/LWG3129>`__","``regex_token_iterator``\ constructor uses wrong pointer arithmetic","San Diego","",""
|
"`3129 <https://wg21.link/LWG3129>`__","``regex_token_iterator``\ constructor uses wrong pointer arithmetic","San Diego","",""
|
||||||
"`3130 <https://wg21.link/LWG3130>`__","|sect|\ [input.output] needs many ``addressof``\ ","San Diego","",""
|
"`3130 <https://wg21.link/LWG3130>`__","|sect|\ [input.output] needs many ``addressof``\ ","San Diego","",""
|
||||||
@ -254,7 +254,7 @@
|
|||||||
"`3330 <https://wg21.link/LWG3330>`__","Include ``<compare>``\ from most library headers","Prague","|Complete|","13.0","|spaceship|"
|
"`3330 <https://wg21.link/LWG3330>`__","Include ``<compare>``\ from most library headers","Prague","|Complete|","13.0","|spaceship|"
|
||||||
"`3331 <https://wg21.link/LWG3331>`__","Define ``totally_ordered/_with``\ in terms of ``partially-ordered-with``\ ","Prague","|Complete|","13.0"
|
"`3331 <https://wg21.link/LWG3331>`__","Define ``totally_ordered/_with``\ in terms of ``partially-ordered-with``\ ","Prague","|Complete|","13.0"
|
||||||
"`3332 <https://wg21.link/LWG3332>`__","Issue in |sect|\ [time.format]","Prague","|Complete|","16.0","|chrono| |format|"
|
"`3332 <https://wg21.link/LWG3332>`__","Issue in |sect|\ [time.format]","Prague","|Complete|","16.0","|chrono| |format|"
|
||||||
"`3334 <https://wg21.link/LWG3334>`__","``basic_osyncstream``\ move assignment and destruction calls ``basic_syncbuf::emit()``\ twice","Prague","",""
|
"`3334 <https://wg21.link/LWG3334>`__","``basic_osyncstream``\ move assignment and destruction calls ``basic_syncbuf::emit()``\ twice","Prague","|Complete|","18.0"
|
||||||
"`3335 <https://wg21.link/LWG3335>`__","Resolve C++20 NB comments US 273 and GB 274","Prague","|Complete|","15.0","|ranges|"
|
"`3335 <https://wg21.link/LWG3335>`__","Resolve C++20 NB comments US 273 and GB 274","Prague","|Complete|","15.0","|ranges|"
|
||||||
"`3338 <https://wg21.link/LWG3338>`__","Rename ``default_constructible``\ to ``default_initializable``\ ","Prague","|Complete|","13.0"
|
"`3338 <https://wg21.link/LWG3338>`__","Rename ``default_constructible``\ to ``default_initializable``\ ","Prague","|Complete|","13.0"
|
||||||
"`3340 <https://wg21.link/LWG3340>`__","Formatting functions should throw on argument/format string mismatch in |sect|\ [format.functions]","Prague","|Complete|","14.0","|format|"
|
"`3340 <https://wg21.link/LWG3340>`__","Formatting functions should throw on argument/format string mismatch in |sect|\ [format.functions]","Prague","|Complete|","14.0","|format|"
|
||||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -3,7 +3,7 @@
|
|||||||
"`P0674R1 <https://wg21.link/P0674R1>`__","LWG","Extending make_shared to Support Arrays","Toronto","|Complete|","15.0"
|
"`P0674R1 <https://wg21.link/P0674R1>`__","LWG","Extending make_shared to Support Arrays","Toronto","|Complete|","15.0"
|
||||||
"","","","","","",""
|
"","","","","","",""
|
||||||
"`P0020R6 <https://wg21.link/P0020R6>`__","LWG","Floating Point Atomic","Albuquerque","",""
|
"`P0020R6 <https://wg21.link/P0020R6>`__","LWG","Floating Point Atomic","Albuquerque","",""
|
||||||
"`P0053R7 <https://wg21.link/P0053R7>`__","LWG","C++ Synchronized Buffered Ostream","Albuquerque","",""
|
"`P0053R7 <https://wg21.link/P0053R7>`__","LWG","C++ Synchronized Buffered Ostream","Albuquerque","|Complete|","18.0"
|
||||||
"`P0202R3 <https://wg21.link/P0202R3>`__","LWG","Add constexpr modifiers to functions in <algorithm> and <utility> Headers","Albuquerque","|Complete|","12.0"
|
"`P0202R3 <https://wg21.link/P0202R3>`__","LWG","Add constexpr modifiers to functions in <algorithm> and <utility> Headers","Albuquerque","|Complete|","12.0"
|
||||||
"`P0415R1 <https://wg21.link/P0415R1>`__","LWG","Constexpr for ``std::complex``\ ","Albuquerque","|Complete|","16.0"
|
"`P0415R1 <https://wg21.link/P0415R1>`__","LWG","Constexpr for ``std::complex``\ ","Albuquerque","|Complete|","16.0"
|
||||||
"`P0439R0 <https://wg21.link/P0439R0>`__","LWG","Make ``std::memory_order``\ a scoped enumeration","Albuquerque","|Complete|",""
|
"`P0439R0 <https://wg21.link/P0439R0>`__","LWG","Make ``std::memory_order``\ a scoped enumeration","Albuquerque","|Complete|",""
|
||||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -122,7 +122,7 @@
|
|||||||
`3566 <https://wg21.link/LWG3566>`__,"Constraint recursion for ``operator<=>(optional<T>, U)``","October 2021","|Complete|","17.0","|spaceship|"
|
`3566 <https://wg21.link/LWG3566>`__,"Constraint recursion for ``operator<=>(optional<T>, U)``","October 2021","|Complete|","17.0","|spaceship|"
|
||||||
`3567 <https://wg21.link/LWG3567>`__,"Formatting move-only iterators take two","October 2021","|Complete|","16.0","|format| |ranges|"
|
`3567 <https://wg21.link/LWG3567>`__,"Formatting move-only iterators take two","October 2021","|Complete|","16.0","|format| |ranges|"
|
||||||
`3568 <https://wg21.link/LWG3568>`__,"``basic_istream_view`` needs to initialize ``value_``","October 2021","|Complete|","16.0","|ranges|"
|
`3568 <https://wg21.link/LWG3568>`__,"``basic_istream_view`` needs to initialize ``value_``","October 2021","|Complete|","16.0","|ranges|"
|
||||||
`3570 <https://wg21.link/LWG3570>`__,"``basic_osyncstream::emit`` should be an unformatted output function","October 2021","",""
|
`3570 <https://wg21.link/LWG3570>`__,"``basic_osyncstream::emit`` should be an unformatted output function","October 2021","|Complete|","18.0"
|
||||||
`3571 <https://wg21.link/LWG3571>`__,"``flush_emit`` should set ``badbit`` if the ``emit`` call fails","October 2021","",""
|
`3571 <https://wg21.link/LWG3571>`__,"``flush_emit`` should set ``badbit`` if the ``emit`` call fails","October 2021","",""
|
||||||
`3572 <https://wg21.link/LWG3572>`__,"``copyable-box`` should be fully ``constexpr``","October 2021","|Complete|","14.0","|ranges|"
|
`3572 <https://wg21.link/LWG3572>`__,"``copyable-box`` should be fully ``constexpr``","October 2021","|Complete|","14.0","|ranges|"
|
||||||
`3573 <https://wg21.link/LWG3573>`__,"Missing Throws element for ``basic_string_view(It begin, End end)``","October 2021","|Complete|","14.0"
|
`3573 <https://wg21.link/LWG3573>`__,"Missing Throws element for ``basic_string_view(It begin, End end)``","October 2021","|Complete|","14.0"
|
||||||
@ -275,7 +275,7 @@
|
|||||||
"`3857 <https://wg21.link/LWG3857>`__","``basic_string_view`` should allow explicit conversion when only traits vary","February 2023","|Complete|","17.0",""
|
"`3857 <https://wg21.link/LWG3857>`__","``basic_string_view`` should allow explicit conversion when only traits vary","February 2023","|Complete|","17.0",""
|
||||||
"`3860 <https://wg21.link/LWG3860>`__","``range_common_reference_t`` is missing","February 2023","|Complete|","17.0","|ranges|"
|
"`3860 <https://wg21.link/LWG3860>`__","``range_common_reference_t`` is missing","February 2023","|Complete|","17.0","|ranges|"
|
||||||
"`3866 <https://wg21.link/LWG3866>`__","Bad Mandates for ``expected::transform_error`` overloads","February 2023","|Complete|","17.0",""
|
"`3866 <https://wg21.link/LWG3866>`__","Bad Mandates for ``expected::transform_error`` overloads","February 2023","|Complete|","17.0",""
|
||||||
"`3867 <https://wg21.link/LWG3867>`__","Should ``std::basic_osyncstream``'s move assignment operator be ``noexcept``?","February 2023","","",""
|
"`3867 <https://wg21.link/LWG3867>`__","Should ``std::basic_osyncstream``'s move assignment operator be ``noexcept``?","February 2023","|Complete|","18.0",""
|
||||||
"`3441 <https://wg21.link/LWG3441>`__","Misleading note about calls to customization points","February 2023","","",""
|
"`3441 <https://wg21.link/LWG3441>`__","Misleading note about calls to customization points","February 2023","","",""
|
||||||
"`3622 <https://wg21.link/LWG3622>`__","Misspecified transitivity of equivalence in §[unord.req.general]","February 2023","","",""
|
"`3622 <https://wg21.link/LWG3622>`__","Misspecified transitivity of equivalence in §[unord.req.general]","February 2023","","",""
|
||||||
"`3631 <https://wg21.link/LWG3631>`__","``basic_format_arg(T&&)`` should use ``remove_cvref_t<T>`` throughout","February 2023","|Complete|","17.0",""
|
"`3631 <https://wg21.link/LWG3631>`__","``basic_format_arg(T&&)`` should use ``remove_cvref_t<T>`` throughout","February 2023","|Complete|","17.0",""
|
||||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -1000,6 +1000,7 @@ set(files
|
|||||||
string.h
|
string.h
|
||||||
string_view
|
string_view
|
||||||
strstream
|
strstream
|
||||||
|
syncstream
|
||||||
system_error
|
system_error
|
||||||
tgmath.h
|
tgmath.h
|
||||||
thread
|
thread
|
||||||
|
@ -452,6 +452,7 @@
|
|||||||
# define _LIBCPP_HAS_NO_INCOMPLETE_PSTL
|
# define _LIBCPP_HAS_NO_INCOMPLETE_PSTL
|
||||||
# define _LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN
|
# define _LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN
|
||||||
# define _LIBCPP_HAS_NO_INCOMPLETE_TZDB
|
# define _LIBCPP_HAS_NO_INCOMPLETE_TZDB
|
||||||
|
# define _LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
// Need to detect which libc we're using if we're on Linux.
|
// Need to detect which libc we're using if we're on Linux.
|
||||||
|
@ -200,6 +200,9 @@
|
|||||||
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||||
# include <strstream>
|
# include <strstream>
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||||
|
# include <syncstream>
|
||||||
|
#endif
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
#include <tgmath.h>
|
#include <tgmath.h>
|
||||||
#if !defined(_LIBCPP_HAS_NO_THREADS)
|
#if !defined(_LIBCPP_HAS_NO_THREADS)
|
||||||
|
@ -90,6 +90,18 @@ using u8streampos = fpos<char_traits<char8_t>::state_type>; // C++20
|
|||||||
using u16streampos = fpos<char_traits<char16_t>::state_type>;
|
using u16streampos = fpos<char_traits<char16_t>::state_type>;
|
||||||
using u32streampos = fpos<char_traits<char32_t>::state_type>;
|
using u32streampos = fpos<char_traits<char32_t>::state_type>;
|
||||||
|
|
||||||
|
template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
|
||||||
|
class basic_syncbuf; // C++20
|
||||||
|
|
||||||
|
using syncbuf = basic_syncbuf<char>; // C++20
|
||||||
|
using wsyncbuf = basic_syncbuf<wchar_t>; // C++20
|
||||||
|
|
||||||
|
template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
|
||||||
|
class basic_osyncstream; // C++20
|
||||||
|
|
||||||
|
using osyncstream = basic_osyncstream<char>; // C++20
|
||||||
|
using wosyncstream = basic_osyncstream<wchar_t>; // C++20
|
||||||
|
|
||||||
} // std
|
} // std
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@ -130,6 +142,26 @@ typedef fpos<mbstate_t> u8streampos;
|
|||||||
typedef fpos<mbstate_t> u16streampos;
|
typedef fpos<mbstate_t> u16streampos;
|
||||||
typedef fpos<mbstate_t> u32streampos;
|
typedef fpos<mbstate_t> u32streampos;
|
||||||
|
|
||||||
|
#if _LIBCPP_STD_VER >= 20
|
||||||
|
|
||||||
|
template <class _CharT, class _Traits = char_traits<_CharT>, class _Allocator = allocator<_CharT>>
|
||||||
|
class basic_syncbuf;
|
||||||
|
|
||||||
|
using syncbuf = basic_syncbuf<char>;
|
||||||
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||||
|
using wsyncbuf = basic_syncbuf<wchar_t>;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class _CharT, class _Traits = char_traits<_CharT>, class _Allocator = allocator<_CharT>>
|
||||||
|
class basic_osyncstream;
|
||||||
|
|
||||||
|
using osyncstream = basic_osyncstream<char>;
|
||||||
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||||
|
using wosyncstream = basic_osyncstream<wchar_t>;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _LIBCPP_STD_VER >=20
|
||||||
|
|
||||||
// Include other forward declarations here
|
// Include other forward declarations here
|
||||||
template <class _Tp, class _Alloc = allocator<_Tp> >
|
template <class _Tp, class _Alloc = allocator<_Tp> >
|
||||||
class _LIBCPP_TEMPLATE_VIS vector;
|
class _LIBCPP_TEMPLATE_VIS vector;
|
||||||
|
@ -1700,6 +1700,8 @@ template <class _Key, class _Tp, class _Compare, class _Allocator>
|
|||||||
_Tp&
|
_Tp&
|
||||||
map<_Key, _Tp, _Compare, _Allocator>::operator[](key_type&& __k)
|
map<_Key, _Tp, _Compare, _Allocator>::operator[](key_type&& __k)
|
||||||
{
|
{
|
||||||
|
// TODO investigate this clang-tidy warning.
|
||||||
|
// NOLINTNEXTLINE(bugprone-use-after-move)
|
||||||
return __tree_.__emplace_unique_key_args(__k,
|
return __tree_.__emplace_unique_key_args(__k,
|
||||||
_VSTD::piecewise_construct,
|
_VSTD::piecewise_construct,
|
||||||
_VSTD::forward_as_tuple(_VSTD::move(__k)),
|
_VSTD::forward_as_tuple(_VSTD::move(__k)),
|
||||||
|
@ -110,6 +110,7 @@ protected:
|
|||||||
#include <__assert> // all public C++ headers provide the assertion handler
|
#include <__assert> // all public C++ headers provide the assertion handler
|
||||||
#include <__config>
|
#include <__config>
|
||||||
#include <__fwd/streambuf.h>
|
#include <__fwd/streambuf.h>
|
||||||
|
#include <climits>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <version>
|
#include <version>
|
||||||
|
510
libcxx/include/syncstream
Normal file
510
libcxx/include/syncstream
Normal file
@ -0,0 +1,510 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef _LIBCPP_SYNCSTREAM
|
||||||
|
#define _LIBCPP_SYNCSTREAM
|
||||||
|
|
||||||
|
/*
|
||||||
|
syncstream synopsis
|
||||||
|
|
||||||
|
#include <ostream> // see [ostream.syn]
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template<class charT, class traits, class Allocator>
|
||||||
|
class basic_syncbuf;
|
||||||
|
|
||||||
|
// [syncstream.syncbuf.special], specialized algorithms
|
||||||
|
template<class charT, class traits, class Allocator>
|
||||||
|
void swap(basic_syncbuf<charT, traits, Allocator>&,
|
||||||
|
basic_syncbuf<charT, traits, Allocator>&);
|
||||||
|
|
||||||
|
using syncbuf = basic_syncbuf<char>;
|
||||||
|
using wsyncbuf = basic_syncbuf<wchar_t>;
|
||||||
|
|
||||||
|
template<class charT, class traits, class Allocator>
|
||||||
|
class basic_osyncstream;
|
||||||
|
|
||||||
|
using osyncstream = basic_osyncstream<char>;
|
||||||
|
using wosyncstream = basic_osyncstream<wchar_t>;
|
||||||
|
|
||||||
|
template<class charT, class traits, class Allocator>
|
||||||
|
class basic_syncbuf : public basic_streambuf<charT, traits> {
|
||||||
|
public:
|
||||||
|
using char_type = charT;
|
||||||
|
using int_type = typename traits::int_type;
|
||||||
|
using pos_type = typename traits::pos_type;
|
||||||
|
using off_type = typename traits::off_type;
|
||||||
|
using traits_type = traits;
|
||||||
|
using allocator_type = Allocator;
|
||||||
|
|
||||||
|
using streambuf_type = basic_streambuf<charT, traits>;
|
||||||
|
|
||||||
|
// [syncstream.syncbuf.cons], construction and destruction
|
||||||
|
explicit basic_syncbuf(streambuf_type* obuf = nullptr)
|
||||||
|
: basic_syncbuf(obuf, Allocator()) {}
|
||||||
|
basic_syncbuf(streambuf_type*, const Allocator&);
|
||||||
|
basic_syncbuf(basic_syncbuf&&);
|
||||||
|
~basic_syncbuf();
|
||||||
|
|
||||||
|
// [syncstream.syncbuf.assign], assignment and swap
|
||||||
|
basic_syncbuf& operator=(basic_syncbuf&&);
|
||||||
|
void swap(basic_syncbuf&);
|
||||||
|
|
||||||
|
// [syncstream.syncbuf.members], member functions
|
||||||
|
bool emit();
|
||||||
|
streambuf_type* get_wrapped() const noexcept;
|
||||||
|
allocator_type get_allocator() const noexcept;
|
||||||
|
void set_emit_on_sync(bool) noexcept;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// [syncstream.syncbuf.virtuals], overridden virtual functions
|
||||||
|
int sync() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
streambuf_type* wrapped; // exposition only
|
||||||
|
bool emit_on_sync{}; // exposition only
|
||||||
|
};
|
||||||
|
|
||||||
|
// [syncstream.syncbuf.special], specialized algorithms
|
||||||
|
template<class charT, class traits, class Allocator>
|
||||||
|
void swap(basic_syncbuf<charT, traits, Allocator>&,
|
||||||
|
basic_syncbuf<charT, traits, Allocator>&);
|
||||||
|
|
||||||
|
template<class charT, class traits, class Allocator>
|
||||||
|
class basic_osyncstream : public basic_ostream<charT, traits> {
|
||||||
|
public:
|
||||||
|
using char_type = charT;
|
||||||
|
using int_type = typename traits::int_type;
|
||||||
|
using pos_type = typename traits::pos_type;
|
||||||
|
using off_type = typename traits::off_type;
|
||||||
|
using traits_type = traits;
|
||||||
|
|
||||||
|
using allocator_type = Allocator;
|
||||||
|
using streambuf_type = basic_streambuf<charT, traits>;
|
||||||
|
using syncbuf_type = basic_syncbuf<charT, traits, Allocator>;
|
||||||
|
|
||||||
|
// [syncstream.osyncstream.cons], construction and destruction
|
||||||
|
basic_osyncstream(streambuf_type*, const Allocator&);
|
||||||
|
explicit basic_osyncstream(streambuf_type* obuf)
|
||||||
|
: basic_osyncstream(obuf, Allocator()) {}
|
||||||
|
basic_osyncstream(basic_ostream<charT, traits>& os, const Allocator& allocator)
|
||||||
|
: basic_osyncstream(os.rdbuf(), allocator) {}
|
||||||
|
explicit basic_osyncstream(basic_ostream<charT, traits>& os)
|
||||||
|
: basic_osyncstream(os, Allocator()) {}
|
||||||
|
basic_osyncstream(basic_osyncstream&&) noexcept;
|
||||||
|
~basic_osyncstream();
|
||||||
|
|
||||||
|
// [syncstream.osyncstream.assign], assignment
|
||||||
|
basic_osyncstream& operator=(basic_osyncstream&&);
|
||||||
|
|
||||||
|
// [syncstream.osyncstream.members], member functions
|
||||||
|
void emit();
|
||||||
|
streambuf_type* get_wrapped() const noexcept;
|
||||||
|
syncbuf_type* rdbuf() const noexcept { return const_cast<syncbuf_type*>(addressof(sb)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
syncbuf_type sb; // exposition only
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <__config>
|
||||||
|
#include <__utility/move.h>
|
||||||
|
#include <iosfwd> // required for declaration of default arguments
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||||
|
# include <map>
|
||||||
|
# include <mutex>
|
||||||
|
# include <shared_mutex>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// standard-mandated includes
|
||||||
|
|
||||||
|
// [syncstream.syn]
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||||
|
# pragma GCC system_header
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_LIBCPP_PUSH_MACROS
|
||||||
|
#include <__undef_macros>
|
||||||
|
|
||||||
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||||
|
|
||||||
|
#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
|
||||||
|
|
||||||
|
// [syncstream.syncbuf.overview]/1
|
||||||
|
// Class template basic_syncbuf stores character data written to it,
|
||||||
|
// known as the associated output, into internal buffers allocated
|
||||||
|
// using the object's allocator. The associated output is transferred
|
||||||
|
// to the wrapped stream buffer object *wrapped when emit() is called
|
||||||
|
// or when the basic_syncbuf object is destroyed. Such transfers are
|
||||||
|
// atomic with respect to transfers by other basic_syncbuf objects
|
||||||
|
// with the same wrapped stream buffer object.
|
||||||
|
//
|
||||||
|
// This helper singleton is used to implement the required
|
||||||
|
// synchronisation guarantees.
|
||||||
|
# ifndef _LIBCPP_HAS_NO_THREADS
|
||||||
|
class __wrapped_streambuf_mutex {
|
||||||
|
_LIBCPP_HIDE_FROM_ABI __wrapped_streambuf_mutex() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
__wrapped_streambuf_mutex(const __wrapped_streambuf_mutex&) = delete;
|
||||||
|
__wrapped_streambuf_mutex& operator=(const __wrapped_streambuf_mutex&) = delete;
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI void __inc_reference([[maybe_unused]] void* __ptr) {
|
||||||
|
_LIBCPP_ASSERT_INTERNAL(__ptr != nullptr, "non-wrapped streambufs are never written to");
|
||||||
|
unique_lock __lock{__mutex_};
|
||||||
|
++__lut_[reinterpret_cast<uintptr_t>(__ptr)].__count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pre: __ptr is in __lut_
|
||||||
|
_LIBCPP_HIDE_FROM_ABI void __dec_reference([[maybe_unused]] void* __ptr) noexcept {
|
||||||
|
unique_lock __lock{__mutex_};
|
||||||
|
|
||||||
|
auto __it = __get_it(__ptr);
|
||||||
|
if (__it->second.__count == 1)
|
||||||
|
__lut_.erase(__it);
|
||||||
|
else
|
||||||
|
--__it->second.__count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// This function causes emit() aquire two mutexes:
|
||||||
|
// - __mutex_ shared
|
||||||
|
// _ __get_it(__ptr)->second.__mutex exclusive
|
||||||
|
//
|
||||||
|
// Instead store a pointer to __get_it(__ptr)->second.__mutex when
|
||||||
|
// calling __inc_reference.
|
||||||
|
//
|
||||||
|
// pre: __ptr is in __lut_
|
||||||
|
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI lock_guard<mutex> __get_lock([[maybe_unused]] void* __ptr) noexcept {
|
||||||
|
shared_lock __lock{__mutex_};
|
||||||
|
return lock_guard{__get_it(__ptr)->second.__mutex};
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is used for testing.
|
||||||
|
//
|
||||||
|
// It is allowed to call this function with a non-registered pointer.
|
||||||
|
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __get_count([[maybe_unused]] void* __ptr) noexcept {
|
||||||
|
_LIBCPP_ASSERT_INTERNAL(__ptr != nullptr, "non-wrapped streambufs are never written to");
|
||||||
|
shared_lock __lock{__mutex_};
|
||||||
|
|
||||||
|
auto __it = __lut_.find(reinterpret_cast<uintptr_t>(__ptr));
|
||||||
|
return __it != __lut_.end() ? __it->second.__count : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static _LIBCPP_HIDE_FROM_ABI __wrapped_streambuf_mutex& __instance() noexcept {
|
||||||
|
static __wrapped_streambuf_mutex __result;
|
||||||
|
return __result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct __value {
|
||||||
|
mutex __mutex;
|
||||||
|
size_t __count{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
shared_mutex __mutex_;
|
||||||
|
map<uintptr_t, __value> __lut_;
|
||||||
|
|
||||||
|
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI map<uintptr_t, __value>::iterator __get_it(void* __ptr) noexcept {
|
||||||
|
_LIBCPP_ASSERT_INTERNAL(__ptr != nullptr, "non-wrapped streambufs are never written to");
|
||||||
|
|
||||||
|
auto __it = __lut_.find(reinterpret_cast<uintptr_t>(__ptr));
|
||||||
|
_LIBCPP_ASSERT_INTERNAL(__it != __lut_.end(), "using a wrapped streambuf that has not been registered");
|
||||||
|
_LIBCPP_ASSERT_INTERNAL(__it->second.__count >= 1, "found an inactive streambuf wrapper");
|
||||||
|
return __it;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
# endif // _LIBCPP_HAS_NO_THREADS
|
||||||
|
|
||||||
|
// basic_syncbuf
|
||||||
|
|
||||||
|
// The class uses a basic_string<_CharT, _Traits, _Allocator> as
|
||||||
|
// internal buffer. Per [syncstream.syncbuf.cons]/4
|
||||||
|
// Remarks: A copy of allocator is used to allocate memory for
|
||||||
|
// internal buffers holding the associated output.
|
||||||
|
//
|
||||||
|
// Therefore the allocator used in the constructor is passed to the
|
||||||
|
// basic_string. The class does not keep a copy of this allocator.
|
||||||
|
template <class _CharT, class _Traits, class _Allocator>
|
||||||
|
class _LIBCPP_TEMPLATE_VIS basic_syncbuf : public basic_streambuf<_CharT, _Traits> {
|
||||||
|
public:
|
||||||
|
using char_type = _CharT;
|
||||||
|
using traits_type = _Traits;
|
||||||
|
using int_type = typename traits_type::int_type;
|
||||||
|
using pos_type = typename traits_type::pos_type;
|
||||||
|
using off_type = typename traits_type::off_type;
|
||||||
|
using allocator_type = _Allocator;
|
||||||
|
|
||||||
|
using streambuf_type = basic_streambuf<_CharT, _Traits>;
|
||||||
|
|
||||||
|
// [syncstream.syncbuf.cons], construction and destruction
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI explicit basic_syncbuf(streambuf_type* __obuf = nullptr)
|
||||||
|
: basic_syncbuf(__obuf, _Allocator()) {}
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI basic_syncbuf(streambuf_type* __obuf, _Allocator const& __alloc)
|
||||||
|
: __wrapped_(__obuf), __str_(__alloc) {
|
||||||
|
__inc_reference();
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI basic_syncbuf(basic_syncbuf&& __other)
|
||||||
|
: __wrapped_(__other.get_wrapped()), __str_(std::move(__other.__str_)), __emit_on_sync_(__other.__emit_on_sync_) {
|
||||||
|
__move_common(__other);
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI ~basic_syncbuf() {
|
||||||
|
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||||
|
try {
|
||||||
|
# endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||||
|
emit();
|
||||||
|
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
# endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||||
|
__dec_reference();
|
||||||
|
}
|
||||||
|
|
||||||
|
// [syncstream.syncbuf.assign], assignment and swap
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI basic_syncbuf& operator=(basic_syncbuf&& __other) {
|
||||||
|
// The function is specified to call emit. This call should
|
||||||
|
// propagate the exception thrown.
|
||||||
|
emit();
|
||||||
|
__dec_reference();
|
||||||
|
|
||||||
|
__wrapped_ = __other.get_wrapped();
|
||||||
|
__str_ = std::move(__other.__str_);
|
||||||
|
__emit_on_sync_ = __other.__emit_on_sync_;
|
||||||
|
|
||||||
|
__move_common(__other);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI void swap(basic_syncbuf& __other) {
|
||||||
|
_LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
|
||||||
|
allocator_traits<_Allocator>::propagate_on_container_swap::value || get_allocator() == __other.get_allocator(),
|
||||||
|
"violates the mandated swap precondition");
|
||||||
|
|
||||||
|
basic_syncbuf __tmp(std::move(__other));
|
||||||
|
__other = std::move(*this);
|
||||||
|
*this = std::move(__tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [syncstream.syncbuf.members], member functions
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI bool emit() { return emit(false); }
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI streambuf_type* get_wrapped() const noexcept { return __wrapped_; }
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const noexcept { return __str_.get_allocator(); }
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI void set_emit_on_sync(bool __b) noexcept { __emit_on_sync_ = __b; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// [syncstream.syncbuf.virtuals], overridden virtual functions
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI_VIRTUAL
|
||||||
|
int sync() override {
|
||||||
|
if (__emit_on_sync_ && !emit(true))
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI_VIRTUAL
|
||||||
|
int_type overflow(int_type __c = traits_type::eof()) override {
|
||||||
|
if (traits_type::eq_int_type(__c, traits_type::eof()))
|
||||||
|
return traits_type::not_eof(__c);
|
||||||
|
|
||||||
|
if (this->pptr() == this->epptr()) {
|
||||||
|
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||||
|
try {
|
||||||
|
# endif
|
||||||
|
size_t __size = __str_.size();
|
||||||
|
__str_.resize(__str_.capacity() + 1);
|
||||||
|
_LIBCPP_ASSERT_INTERNAL(__str_.size() > __size, "the buffer hasn't grown");
|
||||||
|
|
||||||
|
char_type* __p = static_cast<char_type*>(__str_.data());
|
||||||
|
this->setp(__p, __p + __str_.size());
|
||||||
|
this->pbump(__size);
|
||||||
|
|
||||||
|
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||||
|
} catch (...) {
|
||||||
|
return traits_type::eof();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->sputc(traits_type::to_char_type(__c));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
streambuf_type* __wrapped_;
|
||||||
|
|
||||||
|
// TODO Use a more generic buffer.
|
||||||
|
// That buffer should be light with almost no additional headers. Then
|
||||||
|
// it can be use here, the __retarget_buffer, and place that use
|
||||||
|
// the now deprecated get_temporary_buffer
|
||||||
|
|
||||||
|
basic_string<_CharT, _Traits, _Allocator> __str_;
|
||||||
|
bool __emit_on_sync_{false};
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI bool emit(bool __flush) {
|
||||||
|
if (!__wrapped_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
# ifndef _LIBCPP_HAS_NO_THREADS
|
||||||
|
lock_guard<mutex> __lock = __wrapped_streambuf_mutex::__instance().__get_lock(__wrapped_);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
bool __result = true;
|
||||||
|
if (this->pptr() != this->pbase()) {
|
||||||
|
_LIBCPP_ASSERT_INTERNAL(this->pbase() && this->pptr() && this->epptr(), "all put area pointers shold be valid");
|
||||||
|
|
||||||
|
// The __str_ does not know how much of its buffer is used. This
|
||||||
|
// information is extracted from the information of the base class.
|
||||||
|
__result &= (__wrapped_->sputn(this->pbase(), this->pptr() - this->pbase()) != -1);
|
||||||
|
// Clears the buffer, but keeps the contents (and) size of the
|
||||||
|
// internal buffer.
|
||||||
|
this->setp(this->pbase(), this->epptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (__flush)
|
||||||
|
__result &= (__wrapped_->pubsync() != -1);
|
||||||
|
|
||||||
|
return __result;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI void __move_common(basic_syncbuf& __other) {
|
||||||
|
// Adjust the put area pointers to our buffer.
|
||||||
|
char_type* __p = static_cast<char_type*>(__str_.data());
|
||||||
|
this->setp(__p, __p + __str_.size());
|
||||||
|
this->pbump(__other.pptr() - __other.pbase());
|
||||||
|
|
||||||
|
// Clear __other_ so the destructor will act as a NOP.
|
||||||
|
__other.setp(nullptr, nullptr);
|
||||||
|
__other.__wrapped_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI void __inc_reference() {
|
||||||
|
# ifndef _LIBCPP_HAS_NO_THREADS
|
||||||
|
if (__wrapped_)
|
||||||
|
__wrapped_streambuf_mutex::__instance().__inc_reference(__wrapped_);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI void __dec_reference() noexcept {
|
||||||
|
# ifndef _LIBCPP_HAS_NO_THREADS
|
||||||
|
if (__wrapped_)
|
||||||
|
__wrapped_streambuf_mutex::__instance().__dec_reference(__wrapped_);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using std::syncbuf;
|
||||||
|
# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||||
|
using std::wsyncbuf;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// [syncstream.syncbuf.special], specialized algorithms
|
||||||
|
template <class _CharT, class _Traits, class _Allocator>
|
||||||
|
_LIBCPP_HIDE_FROM_ABI void
|
||||||
|
swap(basic_syncbuf<_CharT, _Traits, _Allocator>& __lhs, basic_syncbuf<_CharT, _Traits, _Allocator>& __rhs) {
|
||||||
|
__lhs.swap(__rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// basic_osyncstream
|
||||||
|
|
||||||
|
template <class _CharT, class _Traits, class _Allocator>
|
||||||
|
class _LIBCPP_TEMPLATE_VIS basic_osyncstream : public basic_ostream<_CharT, _Traits> {
|
||||||
|
public:
|
||||||
|
using char_type = _CharT;
|
||||||
|
using traits_type = _Traits;
|
||||||
|
using int_type = typename traits_type::int_type;
|
||||||
|
using pos_type = typename traits_type::pos_type;
|
||||||
|
using off_type = typename traits_type::off_type;
|
||||||
|
|
||||||
|
using allocator_type = _Allocator;
|
||||||
|
using streambuf_type = basic_streambuf<char_type, traits_type>;
|
||||||
|
using syncbuf_type = basic_syncbuf<char_type, traits_type, allocator_type>;
|
||||||
|
|
||||||
|
// [syncstream.osyncstream.cons], construction and destruction
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI basic_osyncstream(streambuf_type* __obuf, allocator_type const& __alloc)
|
||||||
|
: basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__obuf, __alloc) {}
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI explicit basic_osyncstream(streambuf_type* __obuf)
|
||||||
|
: basic_osyncstream(__obuf, allocator_type()) {}
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI basic_osyncstream(basic_ostream<char_type, traits_type>& __os, allocator_type const& __alloc)
|
||||||
|
: basic_osyncstream(__os.rdbuf(), __alloc) {}
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI explicit basic_osyncstream(basic_ostream<char_type, traits_type>& __os)
|
||||||
|
: basic_osyncstream(__os, allocator_type()) {}
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI basic_osyncstream(basic_osyncstream&& __other) noexcept
|
||||||
|
: basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(std::move(__other.__sb_)) {
|
||||||
|
this->set_rdbuf(std::addressof(__sb_));
|
||||||
|
}
|
||||||
|
|
||||||
|
// [syncstream.osyncstream.assign], assignment
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI basic_osyncstream& operator=(basic_osyncstream&& __other) = default;
|
||||||
|
|
||||||
|
// [syncstream.osyncstream.members], member functions
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI void emit() {
|
||||||
|
// The basic_ostream::put places the sentry in a try
|
||||||
|
// catch, this does not match the wording of the standard
|
||||||
|
// [ostream.unformatted]
|
||||||
|
// TODO validate other unformatted output functions.
|
||||||
|
typename basic_ostream<char_type, traits_type>::sentry __s(*this);
|
||||||
|
if (__s) {
|
||||||
|
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||||
|
try {
|
||||||
|
# endif
|
||||||
|
|
||||||
|
if (__sb_.emit() == false)
|
||||||
|
this->setstate(ios::badbit);
|
||||||
|
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||||
|
} catch (...) {
|
||||||
|
this->__set_badbit_and_consider_rethrow();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI streambuf_type* get_wrapped() const noexcept { return __sb_.get_wrapped(); }
|
||||||
|
|
||||||
|
_LIBCPP_HIDE_FROM_ABI syncbuf_type* rdbuf() const noexcept {
|
||||||
|
return const_cast<syncbuf_type*>(std::addressof(__sb_));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
syncbuf_type __sb_;
|
||||||
|
};
|
||||||
|
|
||||||
|
using std::osyncstream;
|
||||||
|
# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||||
|
using std::wosyncstream;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
|
||||||
|
|
||||||
|
_LIBCPP_END_NAMESPACE_STD
|
||||||
|
|
||||||
|
_LIBCPP_POP_MACROS
|
||||||
|
|
||||||
|
#endif // _LIBCPP_SYNCSTREAM
|
@ -401,7 +401,9 @@ __cpp_lib_within_lifetime 202306L <type_traits>
|
|||||||
# define __cpp_lib_starts_ends_with 201711L
|
# define __cpp_lib_starts_ends_with 201711L
|
||||||
# undef __cpp_lib_string_view
|
# undef __cpp_lib_string_view
|
||||||
# define __cpp_lib_string_view 201803L
|
# define __cpp_lib_string_view 201803L
|
||||||
// # define __cpp_lib_syncbuf 201803L
|
# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
|
||||||
|
# define __cpp_lib_syncbuf 201803L
|
||||||
|
# endif
|
||||||
// # define __cpp_lib_three_way_comparison 201907L
|
// # define __cpp_lib_three_way_comparison 201907L
|
||||||
# define __cpp_lib_to_address 201711L
|
# define __cpp_lib_to_address 201711L
|
||||||
# define __cpp_lib_to_array 201907L
|
# define __cpp_lib_to_array 201907L
|
||||||
|
@ -148,6 +148,9 @@ module;
|
|||||||
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||||
# include <strstream>
|
# include <strstream>
|
||||||
#endif
|
#endif
|
||||||
|
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||||
|
# include <syncstream>
|
||||||
|
#endif
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
#if !defined(_LIBCPP_HAS_NO_THREADS)
|
#if !defined(_LIBCPP_HAS_NO_THREADS)
|
||||||
# include <thread>
|
# include <thread>
|
||||||
@ -189,9 +192,6 @@ module;
|
|||||||
#if __has_include(<stdfloat>)
|
#if __has_include(<stdfloat>)
|
||||||
# error "update the header information for <stdfloat> in libcxx/utils/generate_std_cppm_in.py"
|
# error "update the header information for <stdfloat> in libcxx/utils/generate_std_cppm_in.py"
|
||||||
#endif // __has_include(<stdfloat>)
|
#endif // __has_include(<stdfloat>)
|
||||||
#if __has_include(<syncstream>)
|
|
||||||
# error "update the header information for <syncstream> in libcxx/utils/generate_std_cppm_in.py"
|
|
||||||
#endif // __has_include(<syncstream>)
|
|
||||||
#if __has_include(<text_encoding>)
|
#if __has_include(<text_encoding>)
|
||||||
# error "update the header information for <text_encoding> in libcxx/utils/generate_std_cppm_in.py"
|
# error "update the header information for <text_encoding> in libcxx/utils/generate_std_cppm_in.py"
|
||||||
#endif // __has_include(<text_encoding>)
|
#endif // __has_include(<text_encoding>)
|
||||||
|
@ -16,8 +16,19 @@ export namespace std {
|
|||||||
using std::u32streampos;
|
using std::u32streampos;
|
||||||
using std::u8streampos;
|
using std::u8streampos;
|
||||||
|
|
||||||
|
using std::basic_osyncstream;
|
||||||
|
using std::basic_syncbuf;
|
||||||
|
|
||||||
using std::istreambuf_iterator;
|
using std::istreambuf_iterator;
|
||||||
using std::ostreambuf_iterator;
|
using std::ostreambuf_iterator;
|
||||||
|
|
||||||
|
using std::osyncstream;
|
||||||
|
using std::syncbuf;
|
||||||
|
|
||||||
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||||
|
using std::wosyncstream;
|
||||||
|
using std::wsyncbuf;
|
||||||
|
#endif
|
||||||
|
|
||||||
using std::fpos;
|
using std::fpos;
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
export namespace std {
|
export namespace std {
|
||||||
#if 0
|
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
|
||||||
using std::basic_syncbuf;
|
using std::basic_syncbuf;
|
||||||
|
|
||||||
// [syncstream.syncbuf.special], specialized algorithms
|
// [syncstream.syncbuf.special], specialized algorithms
|
||||||
@ -24,5 +24,5 @@ export namespace std {
|
|||||||
# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||||
using std::wosyncstream;
|
using std::wosyncstream;
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif // !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
@ -27,3 +27,7 @@
|
|||||||
#ifdef _LIBCPP_HAS_NO_INCOMPLETE_TZDB
|
#ifdef _LIBCPP_HAS_NO_INCOMPLETE_TZDB
|
||||||
# error "-fexperimental-library should enable the chrono TZDB"
|
# error "-fexperimental-library should enable the chrono TZDB"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM
|
||||||
|
# error "-fexperimental-library should enable the syncstream header"
|
||||||
|
#endif
|
||||||
|
@ -813,6 +813,7 @@ stop_token limits
|
|||||||
stop_token ratio
|
stop_token ratio
|
||||||
stop_token type_traits
|
stop_token type_traits
|
||||||
stop_token version
|
stop_token version
|
||||||
|
streambuf climits
|
||||||
streambuf cstdint
|
streambuf cstdint
|
||||||
streambuf ios
|
streambuf ios
|
||||||
streambuf iosfwd
|
streambuf iosfwd
|
||||||
@ -859,6 +860,13 @@ string_view version
|
|||||||
strstream istream
|
strstream istream
|
||||||
strstream ostream
|
strstream ostream
|
||||||
strstream version
|
strstream version
|
||||||
|
syncstream cstddef
|
||||||
|
syncstream iosfwd
|
||||||
|
syncstream map
|
||||||
|
syncstream mutex
|
||||||
|
syncstream ostream
|
||||||
|
syncstream shared_mutex
|
||||||
|
syncstream string
|
||||||
system_error cerrno
|
system_error cerrno
|
||||||
system_error compare
|
system_error compare
|
||||||
system_error cstddef
|
system_error cstddef
|
||||||
|
|
@ -819,6 +819,7 @@ stop_token limits
|
|||||||
stop_token ratio
|
stop_token ratio
|
||||||
stop_token type_traits
|
stop_token type_traits
|
||||||
stop_token version
|
stop_token version
|
||||||
|
streambuf climits
|
||||||
streambuf cstdint
|
streambuf cstdint
|
||||||
streambuf ios
|
streambuf ios
|
||||||
streambuf iosfwd
|
streambuf iosfwd
|
||||||
@ -865,6 +866,13 @@ string_view version
|
|||||||
strstream istream
|
strstream istream
|
||||||
strstream ostream
|
strstream ostream
|
||||||
strstream version
|
strstream version
|
||||||
|
syncstream cstddef
|
||||||
|
syncstream iosfwd
|
||||||
|
syncstream map
|
||||||
|
syncstream mutex
|
||||||
|
syncstream ostream
|
||||||
|
syncstream shared_mutex
|
||||||
|
syncstream string
|
||||||
system_error cerrno
|
system_error cerrno
|
||||||
system_error compare
|
system_error compare
|
||||||
system_error cstddef
|
system_error cstddef
|
||||||
|
|
@ -821,6 +821,7 @@ stop_token limits
|
|||||||
stop_token ratio
|
stop_token ratio
|
||||||
stop_token type_traits
|
stop_token type_traits
|
||||||
stop_token version
|
stop_token version
|
||||||
|
streambuf climits
|
||||||
streambuf cstdint
|
streambuf cstdint
|
||||||
streambuf ios
|
streambuf ios
|
||||||
streambuf iosfwd
|
streambuf iosfwd
|
||||||
@ -867,6 +868,13 @@ string_view version
|
|||||||
strstream istream
|
strstream istream
|
||||||
strstream ostream
|
strstream ostream
|
||||||
strstream version
|
strstream version
|
||||||
|
syncstream cstddef
|
||||||
|
syncstream iosfwd
|
||||||
|
syncstream map
|
||||||
|
syncstream mutex
|
||||||
|
syncstream ostream
|
||||||
|
syncstream shared_mutex
|
||||||
|
syncstream string
|
||||||
system_error cerrno
|
system_error cerrno
|
||||||
system_error compare
|
system_error compare
|
||||||
system_error cstddef
|
system_error cstddef
|
||||||
|
|
@ -821,6 +821,7 @@ stop_token limits
|
|||||||
stop_token ratio
|
stop_token ratio
|
||||||
stop_token type_traits
|
stop_token type_traits
|
||||||
stop_token version
|
stop_token version
|
||||||
|
streambuf climits
|
||||||
streambuf cstdint
|
streambuf cstdint
|
||||||
streambuf ios
|
streambuf ios
|
||||||
streambuf iosfwd
|
streambuf iosfwd
|
||||||
@ -867,6 +868,13 @@ string_view version
|
|||||||
strstream istream
|
strstream istream
|
||||||
strstream ostream
|
strstream ostream
|
||||||
strstream version
|
strstream version
|
||||||
|
syncstream cstddef
|
||||||
|
syncstream iosfwd
|
||||||
|
syncstream map
|
||||||
|
syncstream mutex
|
||||||
|
syncstream ostream
|
||||||
|
syncstream shared_mutex
|
||||||
|
syncstream string
|
||||||
system_error cerrno
|
system_error cerrno
|
||||||
system_error compare
|
system_error compare
|
||||||
system_error cstddef
|
system_error cstddef
|
||||||
|
|
@ -826,6 +826,7 @@ stop_token limits
|
|||||||
stop_token ratio
|
stop_token ratio
|
||||||
stop_token type_traits
|
stop_token type_traits
|
||||||
stop_token version
|
stop_token version
|
||||||
|
streambuf climits
|
||||||
streambuf cstdint
|
streambuf cstdint
|
||||||
streambuf ios
|
streambuf ios
|
||||||
streambuf iosfwd
|
streambuf iosfwd
|
||||||
@ -872,6 +873,13 @@ string_view version
|
|||||||
strstream istream
|
strstream istream
|
||||||
strstream ostream
|
strstream ostream
|
||||||
strstream version
|
strstream version
|
||||||
|
syncstream cstddef
|
||||||
|
syncstream iosfwd
|
||||||
|
syncstream map
|
||||||
|
syncstream mutex
|
||||||
|
syncstream ostream
|
||||||
|
syncstream shared_mutex
|
||||||
|
syncstream string
|
||||||
system_error cerrno
|
system_error cerrno
|
||||||
system_error compare
|
system_error compare
|
||||||
system_error cstddef
|
system_error cstddef
|
||||||
|
|
@ -564,6 +564,7 @@ stop_token ctime
|
|||||||
stop_token limits
|
stop_token limits
|
||||||
stop_token ratio
|
stop_token ratio
|
||||||
stop_token version
|
stop_token version
|
||||||
|
streambuf climits
|
||||||
streambuf ios
|
streambuf ios
|
||||||
streambuf iosfwd
|
streambuf iosfwd
|
||||||
streambuf version
|
streambuf version
|
||||||
@ -597,6 +598,13 @@ string_view version
|
|||||||
strstream istream
|
strstream istream
|
||||||
strstream ostream
|
strstream ostream
|
||||||
strstream version
|
strstream version
|
||||||
|
syncstream cstddef
|
||||||
|
syncstream iosfwd
|
||||||
|
syncstream map
|
||||||
|
syncstream mutex
|
||||||
|
syncstream ostream
|
||||||
|
syncstream shared_mutex
|
||||||
|
syncstream string
|
||||||
system_error cerrno
|
system_error cerrno
|
||||||
system_error compare
|
system_error compare
|
||||||
system_error cstddef
|
system_error cstddef
|
||||||
|
|
@ -564,6 +564,7 @@ stop_token ctime
|
|||||||
stop_token limits
|
stop_token limits
|
||||||
stop_token ratio
|
stop_token ratio
|
||||||
stop_token version
|
stop_token version
|
||||||
|
streambuf climits
|
||||||
streambuf ios
|
streambuf ios
|
||||||
streambuf iosfwd
|
streambuf iosfwd
|
||||||
streambuf version
|
streambuf version
|
||||||
@ -597,6 +598,13 @@ string_view version
|
|||||||
strstream istream
|
strstream istream
|
||||||
strstream ostream
|
strstream ostream
|
||||||
strstream version
|
strstream version
|
||||||
|
syncstream cstddef
|
||||||
|
syncstream iosfwd
|
||||||
|
syncstream map
|
||||||
|
syncstream mutex
|
||||||
|
syncstream ostream
|
||||||
|
syncstream shared_mutex
|
||||||
|
syncstream string
|
||||||
system_error cerrno
|
system_error cerrno
|
||||||
system_error compare
|
system_error compare
|
||||||
system_error cstddef
|
system_error cstddef
|
||||||
|
|
@ -0,0 +1,101 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_osyncstream;
|
||||||
|
|
||||||
|
// basic_osyncstream& operator=(basic_osyncstream&& rhs);
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "test_allocator.h"
|
||||||
|
|
||||||
|
template <class CharT, bool propagate>
|
||||||
|
static void test() {
|
||||||
|
using Traits = std::char_traits<CharT>;
|
||||||
|
using Allocator = std::conditional_t<propagate, other_allocator<CharT>, test_allocator<CharT>>;
|
||||||
|
static_assert(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value == propagate);
|
||||||
|
|
||||||
|
using OS = std::basic_osyncstream<CharT, Traits, Allocator>;
|
||||||
|
|
||||||
|
std::basic_stringbuf<CharT, Traits, Allocator> base1;
|
||||||
|
std::basic_stringbuf<CharT, Traits, Allocator> base2;
|
||||||
|
|
||||||
|
{
|
||||||
|
OS out1{&base1, Allocator{42}};
|
||||||
|
assert(out1.get_wrapped() == &base1);
|
||||||
|
|
||||||
|
typename OS::syncbuf_type* sb1 = out1.rdbuf();
|
||||||
|
assert(sb1->get_wrapped() == &base1);
|
||||||
|
assert(sb1->get_allocator().get_data() == 42);
|
||||||
|
|
||||||
|
out1 << CharT('A');
|
||||||
|
|
||||||
|
static_assert(!noexcept(out1.operator=(std::move(out1)))); // LWG-3867
|
||||||
|
OS out2{&base2, Allocator{99}};
|
||||||
|
|
||||||
|
out2 << CharT('Z');
|
||||||
|
|
||||||
|
// Validate the data is still in the syncbuf and not in the stringbuf.
|
||||||
|
assert(base1.str().empty());
|
||||||
|
assert(base2.str().empty());
|
||||||
|
|
||||||
|
out2 = std::move(out1);
|
||||||
|
|
||||||
|
// Since sb2 is overwritten by the move its data should be in its stringbuf.
|
||||||
|
assert(base1.str().empty());
|
||||||
|
assert(base2.str().size() == 1);
|
||||||
|
assert(base2.str()[0] == CharT('Z'));
|
||||||
|
|
||||||
|
assert(out2.get_wrapped() == &base1);
|
||||||
|
|
||||||
|
typename OS::syncbuf_type* sb2 = out2.rdbuf();
|
||||||
|
assert(sb2->get_wrapped() == &base1);
|
||||||
|
if constexpr (std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value)
|
||||||
|
assert(sb2->get_allocator().get_data() == 42);
|
||||||
|
else
|
||||||
|
assert(sb2->get_allocator().get_data() == 99);
|
||||||
|
|
||||||
|
assert(out1.get_wrapped() == nullptr);
|
||||||
|
assert(sb1->get_wrapped() == nullptr);
|
||||||
|
|
||||||
|
// The data written to 2 will be stored in sb1. The write happens after the destruction.
|
||||||
|
out2 << CharT('B');
|
||||||
|
assert(base1.str().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(base1.str().size() == 2);
|
||||||
|
assert(base1.str()[0] == CharT('A'));
|
||||||
|
assert(base1.str()[1] == CharT('B'));
|
||||||
|
assert(base2.str().size() == 1);
|
||||||
|
assert(base2.str()[0] == CharT('Z'));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test() {
|
||||||
|
test<CharT, true>();
|
||||||
|
test<CharT, false>();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_osyncstream;
|
||||||
|
|
||||||
|
// void emit();
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
using OS = std::basic_osyncstream<CharT>;
|
||||||
|
using SS = std::basic_ostringstream<CharT>;
|
||||||
|
CharT c = 'f';
|
||||||
|
|
||||||
|
SS ss;
|
||||||
|
OS out(ss);
|
||||||
|
out << c;
|
||||||
|
assert(ss.str().empty());
|
||||||
|
out.emit();
|
||||||
|
assert(ss.str()[0] == c);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_osyncstream;
|
||||||
|
|
||||||
|
// streambuf_type* get_wrapped() const noexcept;
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
std::basic_stringbuf<CharT> base;
|
||||||
|
const std::basic_osyncstream<CharT> out{&base};
|
||||||
|
assert(out.get_wrapped() == &base);
|
||||||
|
ASSERT_NOEXCEPT(out.get_wrapped());
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_osyncstream;
|
||||||
|
|
||||||
|
// syncbuf_type* rdbuf() const noexcept
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
const std::basic_osyncstream<CharT> out{nullptr};
|
||||||
|
assert(out.rdbuf() != nullptr);
|
||||||
|
ASSERT_NOEXCEPT(out.rdbuf());
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,135 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_osyncstream;
|
||||||
|
|
||||||
|
// basic_osyncstream(basic_osyncstream&&) noexcept;
|
||||||
|
|
||||||
|
// TODO Why is this noexcept?
|
||||||
|
// Does the reasoning for https://cplusplus.github.io/LWG/issue3867 not hold true here?
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <sstream>
|
||||||
|
#include <syncstream>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "constexpr_char_traits.h"
|
||||||
|
#include "test_allocator.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT>;
|
||||||
|
using W = std::basic_syncbuf<CharT>;
|
||||||
|
|
||||||
|
const std::allocator<CharT> alloc;
|
||||||
|
{
|
||||||
|
OS os = {OS{nullptr, alloc}};
|
||||||
|
assert(os.get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
ASSERT_NOEXCEPT(OS{std::move(os)});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os = {OS{&w, alloc}};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT, constexpr_char_traits<CharT>>;
|
||||||
|
using W = std::basic_stringbuf<CharT, constexpr_char_traits<CharT>>;
|
||||||
|
|
||||||
|
const std::allocator<CharT> alloc;
|
||||||
|
{
|
||||||
|
OS os = {OS{nullptr, alloc}};
|
||||||
|
assert(os.get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os = {OS{&w, alloc}};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
using W = std::basic_stringbuf<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
|
||||||
|
const test_allocator<CharT> alloc;
|
||||||
|
{
|
||||||
|
OS os = {OS{nullptr, alloc}};
|
||||||
|
assert(os.get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os = {OS{&w, alloc}};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_osyncstream;
|
||||||
|
|
||||||
|
// basic_osyncstream(basic_ostream& os, const Allocator& allocator);
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <concepts>
|
||||||
|
#include <syncstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "constexpr_char_traits.h"
|
||||||
|
#include "test_allocator.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT>;
|
||||||
|
using W = std::basic_ostringstream<CharT>;
|
||||||
|
|
||||||
|
const std::allocator<CharT> alloc;
|
||||||
|
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os = {w, alloc};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == w.rdbuf());
|
||||||
|
assert(os.rdbuf()->get_wrapped() == w.rdbuf());
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT, constexpr_char_traits<CharT>>;
|
||||||
|
using W = std::basic_ostringstream<CharT, constexpr_char_traits<CharT>>;
|
||||||
|
|
||||||
|
const std::allocator<CharT> alloc;
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os = {w.rdbuf(), alloc};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == w.rdbuf());
|
||||||
|
assert(os.rdbuf()->get_wrapped() == w.rdbuf());
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
using W = std::basic_ostringstream<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
|
||||||
|
const test_allocator<CharT> alloc;
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os = {w.rdbuf(), alloc};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == w.rdbuf());
|
||||||
|
assert(os.rdbuf()->get_wrapped() == w.rdbuf());
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_osyncstream;
|
||||||
|
|
||||||
|
// explicit basic_osyncstream(basic_ostream& os);
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <concepts>
|
||||||
|
#include <syncstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "constexpr_char_traits.h"
|
||||||
|
#include "test_allocator.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT>;
|
||||||
|
using W = std::basic_ostringstream<CharT>;
|
||||||
|
|
||||||
|
static_assert(!std::convertible_to<std::basic_ostream<CharT>&, OS>);
|
||||||
|
static_assert(std::constructible_from<OS, std::basic_ostream<CharT>&>);
|
||||||
|
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os{w};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == w.rdbuf());
|
||||||
|
assert(os.rdbuf()->get_wrapped() == w.rdbuf());
|
||||||
|
assert(os.rdbuf()->get_allocator() == std::allocator<CharT>());
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT, constexpr_char_traits<CharT>>;
|
||||||
|
using W = std::basic_ostringstream<CharT, constexpr_char_traits<CharT>>;
|
||||||
|
|
||||||
|
static_assert(!std::convertible_to<std::basic_ostream<CharT, constexpr_char_traits<CharT>>&, OS>);
|
||||||
|
static_assert(std::constructible_from<OS, std::basic_ostream<CharT, constexpr_char_traits<CharT>>&>);
|
||||||
|
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os{w};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == w.rdbuf());
|
||||||
|
assert(os.rdbuf()->get_wrapped() == w.rdbuf());
|
||||||
|
assert(os.rdbuf()->get_allocator() == std::allocator<CharT>());
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
using W = std::basic_ostringstream<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
|
||||||
|
static_assert(!std::convertible_to<std::basic_ostream<CharT, constexpr_char_traits<CharT>>&, OS>);
|
||||||
|
static_assert(std::constructible_from<OS, std::basic_ostream<CharT, constexpr_char_traits<CharT>>&>);
|
||||||
|
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os{w};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == w.rdbuf());
|
||||||
|
assert(os.rdbuf()->get_wrapped() == w.rdbuf());
|
||||||
|
assert(os.rdbuf()->get_allocator() == test_allocator<CharT>());
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(w.rdbuf()) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,132 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_osyncstream;
|
||||||
|
|
||||||
|
// basic_osyncstream(streambuf_type* os, const Allocator& allocator);
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <concepts>
|
||||||
|
#include <syncstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "constexpr_char_traits.h"
|
||||||
|
#include "test_allocator.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT>;
|
||||||
|
using W = std::basic_stringbuf<CharT>;
|
||||||
|
|
||||||
|
const std::allocator<CharT> alloc;
|
||||||
|
{
|
||||||
|
OS os = {nullptr, alloc};
|
||||||
|
assert(os.get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os = {&w, alloc};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT, constexpr_char_traits<CharT>>;
|
||||||
|
using W = std::basic_stringbuf<CharT, constexpr_char_traits<CharT>>;
|
||||||
|
|
||||||
|
const std::allocator<CharT> alloc;
|
||||||
|
{
|
||||||
|
OS os = {nullptr, alloc};
|
||||||
|
assert(os.get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os = {&w, alloc};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
using W = std::basic_stringbuf<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
|
||||||
|
const test_allocator<CharT> alloc;
|
||||||
|
{
|
||||||
|
OS os = {nullptr, alloc};
|
||||||
|
assert(os.get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os = {&w, alloc};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,140 @@
|
|||||||
|
//==----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_osyncstream;
|
||||||
|
|
||||||
|
// explicit basic_osyncstream(streambuf_type* os);
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <concepts>
|
||||||
|
#include <syncstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "constexpr_char_traits.h"
|
||||||
|
#include "test_allocator.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT>;
|
||||||
|
using W = std::basic_stringbuf<CharT>;
|
||||||
|
|
||||||
|
static_assert(!std::convertible_to<std::basic_syncbuf<CharT>*, OS>);
|
||||||
|
static_assert(std::constructible_from<OS, std::basic_syncbuf<CharT>*>);
|
||||||
|
|
||||||
|
{
|
||||||
|
OS os{nullptr};
|
||||||
|
assert(os.get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_allocator() == std::allocator<CharT>());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os{&w};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_allocator() == std::allocator<CharT>());
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT, constexpr_char_traits<CharT>>;
|
||||||
|
using W = std::basic_stringbuf<CharT, constexpr_char_traits<CharT>>;
|
||||||
|
|
||||||
|
static_assert(!std::convertible_to<std::basic_syncbuf<CharT, constexpr_char_traits<CharT>>*, OS>);
|
||||||
|
static_assert(std::constructible_from<OS, std::basic_syncbuf<CharT, constexpr_char_traits<CharT>>*>);
|
||||||
|
|
||||||
|
{
|
||||||
|
OS os{nullptr};
|
||||||
|
assert(os.get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_allocator() == std::allocator<CharT>());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os{&w};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_allocator() == std::allocator<CharT>());
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using OS = std::basic_osyncstream<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
using W = std::basic_stringbuf<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
!std::convertible_to<std::basic_syncbuf<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>*, OS>);
|
||||||
|
static_assert(
|
||||||
|
std::constructible_from<OS, std::basic_syncbuf<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>*>);
|
||||||
|
|
||||||
|
{
|
||||||
|
OS os{nullptr};
|
||||||
|
assert(os.get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == nullptr);
|
||||||
|
assert(os.rdbuf()->get_allocator() == test_allocator<CharT>());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
W w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
OS os{&w};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(os.get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_wrapped() == &w);
|
||||||
|
assert(os.rdbuf()->get_allocator() == test_allocator<CharT>());
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: no-threads
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_osyncstream;
|
||||||
|
|
||||||
|
// Basic test whether the code works in a threaded environment.
|
||||||
|
// Using timing the output order should be stable.
|
||||||
|
// several_threads.pass.cpp tests with more threads.
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
static std::basic_ostringstream<char> ss;
|
||||||
|
static const char a = 'a';
|
||||||
|
static const char b = 'b';
|
||||||
|
static const char c = 'c';
|
||||||
|
static const char d = 'd';
|
||||||
|
|
||||||
|
void f1() {
|
||||||
|
std::basic_osyncstream<char> out(ss);
|
||||||
|
out << a;
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||||
|
out << b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void f2() {
|
||||||
|
std::basic_osyncstream<char> out(ss);
|
||||||
|
out << c;
|
||||||
|
out << d;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
std::thread t1(f1);
|
||||||
|
std::thread t2(f2);
|
||||||
|
t1.join();
|
||||||
|
t2.join();
|
||||||
|
|
||||||
|
assert(ss.str() == "cdab");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,144 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: no-threads
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_osyncstream;
|
||||||
|
|
||||||
|
// The test writes all elements in test_strings in a random order in ss. Every
|
||||||
|
// write is done by an osyncstream. This means the output is in random order,
|
||||||
|
// but the words should be written without interleaving. To increment the
|
||||||
|
// change of interleaving words are written one character at a time.
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <chrono>
|
||||||
|
#include <mutex>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <syncstream>
|
||||||
|
#include <thread>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
static std::ostringstream ss;
|
||||||
|
|
||||||
|
static std::unordered_multiset<std::string> test_strings = {
|
||||||
|
"C++ ",
|
||||||
|
"is ",
|
||||||
|
"a ",
|
||||||
|
"general-purpose ",
|
||||||
|
"programming ",
|
||||||
|
"language ",
|
||||||
|
"created ",
|
||||||
|
"by ",
|
||||||
|
"Bjarne ",
|
||||||
|
"Stroustrup ",
|
||||||
|
"as ",
|
||||||
|
"an ",
|
||||||
|
"extension ",
|
||||||
|
"of ",
|
||||||
|
"the ",
|
||||||
|
"C ",
|
||||||
|
"programming ",
|
||||||
|
"language, ",
|
||||||
|
"or ",
|
||||||
|
"C ",
|
||||||
|
"with ",
|
||||||
|
"Classes. ",
|
||||||
|
"The ",
|
||||||
|
"language ",
|
||||||
|
"has ",
|
||||||
|
"expanded ",
|
||||||
|
"significantly ",
|
||||||
|
"over ",
|
||||||
|
"time, ",
|
||||||
|
"and ",
|
||||||
|
"modern ",
|
||||||
|
"C++ ",
|
||||||
|
"has ",
|
||||||
|
"object-oriented, ",
|
||||||
|
"generic, ",
|
||||||
|
"and ",
|
||||||
|
"functional ",
|
||||||
|
"features ",
|
||||||
|
"in ",
|
||||||
|
"addition ",
|
||||||
|
"to ",
|
||||||
|
"facilities ",
|
||||||
|
"for ",
|
||||||
|
"low-level ",
|
||||||
|
"memory ",
|
||||||
|
"manipulation. ",
|
||||||
|
"It ",
|
||||||
|
"is ",
|
||||||
|
"almost ",
|
||||||
|
"always ",
|
||||||
|
"implemented ",
|
||||||
|
"as ",
|
||||||
|
"a ",
|
||||||
|
"compiled ",
|
||||||
|
"language, ",
|
||||||
|
"and ",
|
||||||
|
"many ",
|
||||||
|
"vendors ",
|
||||||
|
"provide ",
|
||||||
|
"C++ ",
|
||||||
|
"compilers, ",
|
||||||
|
"including ",
|
||||||
|
"the ",
|
||||||
|
"Free ",
|
||||||
|
"Software ",
|
||||||
|
"Foundation, ",
|
||||||
|
"LLVM, ",
|
||||||
|
"Microsoft, ",
|
||||||
|
"Intel, ",
|
||||||
|
"and ",
|
||||||
|
"IBM, ",
|
||||||
|
"so ",
|
||||||
|
"it ",
|
||||||
|
"is ",
|
||||||
|
"available ",
|
||||||
|
"on ",
|
||||||
|
"many ",
|
||||||
|
"platforms."};
|
||||||
|
|
||||||
|
void f(std::string text) {
|
||||||
|
std::osyncstream out(ss);
|
||||||
|
for (char c : text)
|
||||||
|
out << c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
ss = std::basic_ostringstream<char>();
|
||||||
|
std::vector<std::thread> threads;
|
||||||
|
for (std::string const& word : test_strings)
|
||||||
|
threads.push_back(std::thread(f, word));
|
||||||
|
|
||||||
|
for (auto& thread : threads)
|
||||||
|
thread.join();
|
||||||
|
|
||||||
|
std::string output = ss.str();
|
||||||
|
for (const std::string& word : test_strings)
|
||||||
|
assert(output.find(word) != std::string::npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
// The more we test, the more likely we catch an error
|
||||||
|
for (size_t i = 0; i < 1024; ++i)
|
||||||
|
test();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
//
|
||||||
|
// template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
|
||||||
|
// class basic_osyncstream : public basic_ostream<charT, traits> {
|
||||||
|
// public:
|
||||||
|
// using char_type = charT;
|
||||||
|
// using int_type = typename traits::int_type;
|
||||||
|
// using pos_type = typename traits::pos_type;
|
||||||
|
// using off_type = typename traits::off_type;
|
||||||
|
// using traits_type = traits;
|
||||||
|
//
|
||||||
|
// using allocator_type = Allocator;
|
||||||
|
// using streambuf_type = basic_streambuf<charT, traits>;
|
||||||
|
// using syncbuf_type = basic_syncbuf<charT, traits, Allocator>;
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <concepts>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "constexpr_char_traits.h"
|
||||||
|
#include "test_allocator.h"
|
||||||
|
|
||||||
|
static_assert(std::same_as<std::basic_osyncstream<char>,
|
||||||
|
std::basic_osyncstream<char, std::char_traits<char>, std::allocator<char>>>);
|
||||||
|
static_assert(std::same_as<std::basic_osyncstream<char, constexpr_char_traits<char>>,
|
||||||
|
std::basic_osyncstream<char, constexpr_char_traits<char>, std::allocator<char>>>);
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_osyncstream<char, constexpr_char_traits<char>, test_allocator<char>>::char_type, char>);
|
||||||
|
static_assert(std::same_as<std::basic_osyncstream<char, constexpr_char_traits<char>, test_allocator<char>>::int_type,
|
||||||
|
constexpr_char_traits<char>::int_type>);
|
||||||
|
static_assert(std::same_as<std::basic_osyncstream<char, constexpr_char_traits<char>, test_allocator<char>>::pos_type,
|
||||||
|
constexpr_char_traits<char>::pos_type>);
|
||||||
|
static_assert(std::same_as<std::basic_osyncstream<char, constexpr_char_traits<char>, test_allocator<char>>::off_type,
|
||||||
|
constexpr_char_traits<char>::off_type>);
|
||||||
|
static_assert(std::same_as<std::basic_osyncstream<char, constexpr_char_traits<char>, test_allocator<char>>::traits_type,
|
||||||
|
constexpr_char_traits<char>>);
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_osyncstream<char, constexpr_char_traits<char>, test_allocator<char>>::allocator_type,
|
||||||
|
test_allocator<char>>);
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_osyncstream<char, constexpr_char_traits<char>, test_allocator<char>>::streambuf_type,
|
||||||
|
std::basic_streambuf<char, constexpr_char_traits<char>>>);
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_osyncstream<char, constexpr_char_traits<char>, test_allocator<char>>::syncbuf_type,
|
||||||
|
std::basic_syncbuf<char, constexpr_char_traits<char>, test_allocator<char>>>);
|
||||||
|
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
|
||||||
|
static_assert(std::same_as<std::basic_osyncstream<wchar_t>,
|
||||||
|
std::basic_osyncstream<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>);
|
||||||
|
static_assert(std::same_as<std::basic_osyncstream<wchar_t, constexpr_char_traits<wchar_t>>,
|
||||||
|
std::basic_osyncstream<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>>);
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_osyncstream<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::char_type,
|
||||||
|
wchar_t>);
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_osyncstream<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::int_type,
|
||||||
|
constexpr_char_traits<wchar_t>::int_type>);
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_osyncstream<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::pos_type,
|
||||||
|
constexpr_char_traits<wchar_t>::pos_type>);
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_osyncstream<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::off_type,
|
||||||
|
constexpr_char_traits<wchar_t>::off_type>);
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_osyncstream<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::traits_type,
|
||||||
|
constexpr_char_traits<wchar_t>>);
|
||||||
|
static_assert(std::same_as<
|
||||||
|
std::basic_osyncstream<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::allocator_type,
|
||||||
|
test_allocator<wchar_t>>);
|
||||||
|
static_assert(std::same_as<
|
||||||
|
std::basic_osyncstream<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::streambuf_type,
|
||||||
|
std::basic_streambuf<wchar_t, constexpr_char_traits<wchar_t>>>);
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_osyncstream<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::syncbuf_type,
|
||||||
|
std::basic_syncbuf<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>>);
|
||||||
|
|
||||||
|
#endif // TEST_HAS_NO_WIDE_CHARACTERS
|
38
libcxx/test/std/input.output/syncstream/syncbuf/helpers.h
Normal file
38
libcxx/test/std/input.output/syncstream/syncbuf/helpers.h
Normal file
@ -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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef TEST_STD_INPUT_OUTPUT_SYNCSTREAM_SYNCBUF_SYNCSTREAM_SYNCBUF_MEMBERS_H
|
||||||
|
#define TEST_STD_INPUT_OUTPUT_SYNCSTREAM_SYNCBUF_SYNCSTREAM_SYNCBUF_MEMBERS_H
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class test_buf : public std::basic_streambuf<T> {
|
||||||
|
public:
|
||||||
|
int id;
|
||||||
|
|
||||||
|
test_buf(int _id = 0) : id(_id) {}
|
||||||
|
|
||||||
|
T* _pptr() { return this->pptr(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class Alloc = std::allocator<T>>
|
||||||
|
class test_syncbuf : public std::basic_syncbuf<T, std::char_traits<T>, Alloc> {
|
||||||
|
public:
|
||||||
|
test_syncbuf(test_buf<T>* buf, Alloc alloc) : std::basic_syncbuf<T, std::char_traits<T>, Alloc>(buf, alloc) {}
|
||||||
|
|
||||||
|
void _setp(T* begin, T* end) { return this->setp(begin, end); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct test_allocator : std::allocator<T> {
|
||||||
|
int id;
|
||||||
|
test_allocator(int _id = 0) : id(_id) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TEST_STD_INPUT_OUTPUT_SYNCSTREAM_SYNCBUF_SYNCSTREAM_SYNCBUF_MEMBERS_H
|
151
libcxx/test/std/input.output/syncstream/syncbuf/sputc.pass.cpp
Normal file
151
libcxx/test/std/input.output/syncstream/syncbuf/sputc.pass.cpp
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_syncbuf;
|
||||||
|
|
||||||
|
// Tests the inherited function using a custom allocator.
|
||||||
|
//
|
||||||
|
// int_type basic_streambuf<charT, traits>::sputc(char_type c);
|
||||||
|
//
|
||||||
|
// This test also validates the observable behaviour after move assignment and
|
||||||
|
// construction. This test uses a small so the underlying string is in short
|
||||||
|
// mode.
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <syncstream>
|
||||||
|
#include <cassert>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "test_allocator.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
std::array< CharT, 17> input{
|
||||||
|
CharT('a'),
|
||||||
|
CharT('1'),
|
||||||
|
CharT('+'),
|
||||||
|
CharT('A'),
|
||||||
|
CharT('g'),
|
||||||
|
CharT('0'),
|
||||||
|
CharT('@'),
|
||||||
|
CharT('Z'),
|
||||||
|
CharT('q'),
|
||||||
|
CharT('8'),
|
||||||
|
CharT('#'),
|
||||||
|
CharT('D'),
|
||||||
|
CharT('t'),
|
||||||
|
CharT('9'),
|
||||||
|
CharT('$'),
|
||||||
|
CharT('A'),
|
||||||
|
CharT(' ')};
|
||||||
|
using SyncBuf = std::basic_syncbuf<CharT, std::char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
|
||||||
|
{ // Normal
|
||||||
|
std::basic_string<CharT> expected;
|
||||||
|
std::basic_stringbuf<CharT> buf;
|
||||||
|
test_allocator_statistics stats;
|
||||||
|
test_allocator<CharT> allocator{&stats};
|
||||||
|
|
||||||
|
{
|
||||||
|
SyncBuf sync_buf{&buf, allocator};
|
||||||
|
for (int i = 0; i < 1024; ++i) {
|
||||||
|
CharT c = input[i % input.size()];
|
||||||
|
expected.push_back(c);
|
||||||
|
typename SyncBuf::int_type ret = sync_buf.sputc(c);
|
||||||
|
assert(ret == typename SyncBuf::int_type(c));
|
||||||
|
}
|
||||||
|
// The synchchronization happens upon destruction of sync_buf.
|
||||||
|
assert(buf.str().empty());
|
||||||
|
assert(stats.allocated_size >= 1024);
|
||||||
|
}
|
||||||
|
assert(buf.str() == expected);
|
||||||
|
assert(stats.allocated_size == 0);
|
||||||
|
}
|
||||||
|
{ // Move construction
|
||||||
|
std::basic_stringbuf<CharT> buf;
|
||||||
|
test_allocator_statistics stats;
|
||||||
|
test_allocator<CharT> allocator{&stats};
|
||||||
|
|
||||||
|
{
|
||||||
|
SyncBuf sync_buf{&buf, allocator};
|
||||||
|
CharT c = CharT('4');
|
||||||
|
typename SyncBuf::int_type ret = sync_buf.sputc(c);
|
||||||
|
assert(ret == typename SyncBuf::int_type(c));
|
||||||
|
|
||||||
|
{
|
||||||
|
c = CharT('2');
|
||||||
|
|
||||||
|
SyncBuf new_sync_buf{std::move(sync_buf)};
|
||||||
|
ret = new_sync_buf.sputc(c);
|
||||||
|
assert(ret == typename SyncBuf::int_type(c));
|
||||||
|
|
||||||
|
// The synchchronization happens upon destruction of new_sync_buf.
|
||||||
|
assert(buf.str().empty());
|
||||||
|
assert(stats.allocated_size >= 2);
|
||||||
|
}
|
||||||
|
assert(buf.str().size() == 2);
|
||||||
|
assert(buf.str()[0] == CharT('4'));
|
||||||
|
assert(buf.str()[1] == CharT('2'));
|
||||||
|
assert(stats.allocated_size == 0);
|
||||||
|
}
|
||||||
|
assert(buf.str().size() == 2);
|
||||||
|
assert(buf.str()[0] == CharT('4'));
|
||||||
|
assert(buf.str()[1] == CharT('2'));
|
||||||
|
assert(stats.allocated_size == 0);
|
||||||
|
}
|
||||||
|
{ // Move assignment non-propagating allocator
|
||||||
|
std::basic_stringbuf<CharT> buf;
|
||||||
|
test_allocator_statistics stats;
|
||||||
|
test_allocator<CharT> allocator{&stats};
|
||||||
|
static_assert(!std::allocator_traits<test_allocator<CharT>>::propagate_on_container_move_assignment::value);
|
||||||
|
|
||||||
|
{
|
||||||
|
SyncBuf sync_buf{&buf, allocator};
|
||||||
|
CharT c = CharT('4');
|
||||||
|
typename SyncBuf::int_type ret = sync_buf.sputc(c);
|
||||||
|
assert(ret == typename SyncBuf::int_type(c));
|
||||||
|
|
||||||
|
{
|
||||||
|
c = CharT('2');
|
||||||
|
|
||||||
|
SyncBuf new_sync_buf;
|
||||||
|
test_allocator<CharT> a = new_sync_buf.get_allocator();
|
||||||
|
new_sync_buf = std::move(sync_buf);
|
||||||
|
assert(new_sync_buf.get_allocator() == a);
|
||||||
|
|
||||||
|
ret = new_sync_buf.sputc(c);
|
||||||
|
assert(ret == typename SyncBuf::int_type(c));
|
||||||
|
|
||||||
|
// The synchchronization happens upon destruction of new_sync_buf.
|
||||||
|
assert(buf.str().empty());
|
||||||
|
}
|
||||||
|
assert(buf.str().size() == 2);
|
||||||
|
assert(buf.str()[0] == CharT('4'));
|
||||||
|
assert(buf.str()[1] == CharT('2'));
|
||||||
|
}
|
||||||
|
assert(buf.str().size() == 2);
|
||||||
|
assert(buf.str()[0] == CharT('4'));
|
||||||
|
assert(buf.str()[1] == CharT('2'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
134
libcxx/test/std/input.output/syncstream/syncbuf/sputn.pass.cpp
Normal file
134
libcxx/test/std/input.output/syncstream/syncbuf/sputn.pass.cpp
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_syncbuf;
|
||||||
|
|
||||||
|
// Tests the inherited function using a custom allocator.
|
||||||
|
//
|
||||||
|
// streamsize basic_streambuf<charT, traits>::sputc(const char_type* s, streamsize n);
|
||||||
|
//
|
||||||
|
// This test also validates the observable behaviour after move assignment and
|
||||||
|
// construction. This test uses a large buffer so the underlying string is in
|
||||||
|
// long mode.
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <syncstream>
|
||||||
|
#include <cassert>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "test_allocator.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
std::array< CharT, 17> input{
|
||||||
|
CharT('a'),
|
||||||
|
CharT('1'),
|
||||||
|
CharT('+'),
|
||||||
|
CharT('A'),
|
||||||
|
CharT('g'),
|
||||||
|
CharT('0'),
|
||||||
|
CharT('@'),
|
||||||
|
CharT('Z'),
|
||||||
|
CharT('q'),
|
||||||
|
CharT('8'),
|
||||||
|
CharT('#'),
|
||||||
|
CharT('D'),
|
||||||
|
CharT('t'),
|
||||||
|
CharT('9'),
|
||||||
|
CharT('$'),
|
||||||
|
CharT('A'),
|
||||||
|
CharT(' ')};
|
||||||
|
std::basic_string<CharT> expected;
|
||||||
|
for (int i = 0; i < 1024; ++i)
|
||||||
|
expected.push_back(input[i % input.size()]);
|
||||||
|
|
||||||
|
using SyncBuf = std::basic_syncbuf<CharT, std::char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
{ // Normal
|
||||||
|
std::basic_stringbuf<CharT> buf;
|
||||||
|
test_allocator_statistics stats;
|
||||||
|
test_allocator<CharT> allocator{&stats};
|
||||||
|
|
||||||
|
{
|
||||||
|
SyncBuf sync_buf{&buf, allocator};
|
||||||
|
std::streamsize ret = sync_buf.sputn(expected.data(), expected.size());
|
||||||
|
assert(ret == 1024);
|
||||||
|
|
||||||
|
// The synchchronization happens upon destruction of sync_buf.
|
||||||
|
assert(buf.str().empty());
|
||||||
|
assert(stats.allocated_size >= 1024);
|
||||||
|
}
|
||||||
|
assert(buf.str() == expected);
|
||||||
|
assert(stats.allocated_size == 0);
|
||||||
|
}
|
||||||
|
{ // Move construction
|
||||||
|
std::basic_stringbuf<CharT> buf;
|
||||||
|
test_allocator_statistics stats;
|
||||||
|
test_allocator<CharT> allocator{&stats};
|
||||||
|
|
||||||
|
{
|
||||||
|
SyncBuf sync_buf{&buf, allocator};
|
||||||
|
std::streamsize ret = sync_buf.sputn(expected.data(), expected.size());
|
||||||
|
assert(ret == 1024);
|
||||||
|
{
|
||||||
|
SyncBuf new_sync_buf{std::move(sync_buf)};
|
||||||
|
ret = new_sync_buf.sputn(expected.data(), expected.size());
|
||||||
|
assert(ret == 1024);
|
||||||
|
|
||||||
|
// The synchchronization happens upon destruction of new_sync_buf.
|
||||||
|
assert(buf.str().empty());
|
||||||
|
assert(stats.allocated_size >= 2048);
|
||||||
|
}
|
||||||
|
assert(buf.str() == expected + expected);
|
||||||
|
assert(stats.allocated_size == 0);
|
||||||
|
}
|
||||||
|
assert(buf.str() == expected + expected);
|
||||||
|
assert(stats.allocated_size == 0);
|
||||||
|
}
|
||||||
|
{ // Move assignment non-propagating allocator
|
||||||
|
std::basic_stringbuf<CharT> buf;
|
||||||
|
test_allocator_statistics stats;
|
||||||
|
test_allocator<CharT> allocator{&stats};
|
||||||
|
static_assert(!std::allocator_traits<test_allocator<CharT>>::propagate_on_container_move_assignment::value);
|
||||||
|
|
||||||
|
{
|
||||||
|
SyncBuf sync_buf{&buf, allocator};
|
||||||
|
std::streamsize ret = sync_buf.sputn(expected.data(), expected.size());
|
||||||
|
assert(ret == 1024);
|
||||||
|
{
|
||||||
|
SyncBuf new_sync_buf;
|
||||||
|
test_allocator<CharT> a = new_sync_buf.get_allocator();
|
||||||
|
new_sync_buf = std::move(sync_buf);
|
||||||
|
assert(new_sync_buf.get_allocator() == a);
|
||||||
|
|
||||||
|
ret = new_sync_buf.sputn(expected.data(), expected.size());
|
||||||
|
assert(ret == 1024);
|
||||||
|
|
||||||
|
// The synchchronization happens upon destruction of new_sync_buf.
|
||||||
|
assert(buf.str().empty());
|
||||||
|
}
|
||||||
|
assert(buf.str() == expected + expected);
|
||||||
|
}
|
||||||
|
assert(buf.str() == expected + expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_syncbuf;
|
||||||
|
|
||||||
|
// protected:
|
||||||
|
// [syncstream.syncbuf.virtuals], overridden virtual functions
|
||||||
|
// int sync() override;
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <ostream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test_sync(bool emit_on_sync) {
|
||||||
|
std::basic_stringbuf<CharT> base;
|
||||||
|
std::basic_syncbuf<CharT> buff(&base);
|
||||||
|
std::basic_ostream<CharT> out(&buff);
|
||||||
|
|
||||||
|
buff.set_emit_on_sync(emit_on_sync);
|
||||||
|
|
||||||
|
out << 'a';
|
||||||
|
out.flush(); // This is an indirect call to sync.
|
||||||
|
|
||||||
|
if (emit_on_sync) {
|
||||||
|
assert(base.str().size() == 1);
|
||||||
|
assert(base.str()[0] == CharT('a'));
|
||||||
|
} else
|
||||||
|
assert(base.str().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test_sync<char>(true);
|
||||||
|
test_sync<char>(false);
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test_sync<wchar_t>(true);
|
||||||
|
test_sync<wchar_t>(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,399 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_syncbuf;
|
||||||
|
|
||||||
|
// basic_syncbuf& operator=(basic_syncbuf&& rhs);
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <cassert>
|
||||||
|
#include <concepts>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
template <class T, class propagate>
|
||||||
|
struct test_allocator : std::allocator<T> {
|
||||||
|
using propagate_on_container_move_assignment = propagate;
|
||||||
|
|
||||||
|
int id{-1};
|
||||||
|
|
||||||
|
test_allocator(int _id = -1) : id(_id) {}
|
||||||
|
test_allocator(test_allocator const& other) = default;
|
||||||
|
test_allocator(test_allocator&& other) = default;
|
||||||
|
test_allocator& operator=(const test_allocator& other) = default;
|
||||||
|
|
||||||
|
test_allocator& operator=(test_allocator&& other) {
|
||||||
|
if constexpr (propagate_on_container_move_assignment::value)
|
||||||
|
id = other.id;
|
||||||
|
else
|
||||||
|
id = -1;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class test_buf : public std::basic_streambuf<T> {
|
||||||
|
public:
|
||||||
|
int id;
|
||||||
|
|
||||||
|
test_buf(int _id = 0) : id(_id) {}
|
||||||
|
|
||||||
|
T* _pptr() { return this->pptr(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class Alloc = std::allocator<T>>
|
||||||
|
class test_syncbuf : public std::basic_syncbuf<T, std::char_traits<T>, Alloc> {
|
||||||
|
using Base = std::basic_syncbuf<T, std::char_traits<T>, Alloc>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
test_syncbuf() = default;
|
||||||
|
|
||||||
|
test_syncbuf(test_buf<T>* buf, Alloc alloc) : Base(buf, alloc) {}
|
||||||
|
|
||||||
|
test_syncbuf(typename Base::streambuf_type* buf, Alloc alloc) : Base(buf, alloc) {}
|
||||||
|
|
||||||
|
void _setp(T* begin, T* end) { return this->setp(begin, end); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper wrapper to inspect the internal state of the basic_syncbuf
|
||||||
|
//
|
||||||
|
// This is used the valiate some standard requirements and libc++
|
||||||
|
// implementation details.
|
||||||
|
template <class CharT, class Traits, class Allocator>
|
||||||
|
class syncbuf_inspector : public std::basic_syncbuf<CharT, Traits, Allocator> {
|
||||||
|
public:
|
||||||
|
syncbuf_inspector() = default;
|
||||||
|
explicit syncbuf_inspector(std::basic_syncbuf<CharT, Traits, Allocator>&& base)
|
||||||
|
: std::basic_syncbuf<CharT, Traits, Allocator>(std::move(base)) {}
|
||||||
|
|
||||||
|
void operator=(std::basic_syncbuf<CharT, Traits, Allocator>&& base) { *this = std::move(base); }
|
||||||
|
|
||||||
|
using std::basic_syncbuf<CharT, Traits, Allocator>::pbase;
|
||||||
|
using std::basic_syncbuf<CharT, Traits, Allocator>::pptr;
|
||||||
|
using std::basic_syncbuf<CharT, Traits, Allocator>::epptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_assign() {
|
||||||
|
test_buf<CharT> base;
|
||||||
|
|
||||||
|
{ // Test using the real class, propagating allocator.
|
||||||
|
using BuffT = std::basic_syncbuf<CharT, std::char_traits<CharT>, test_allocator<CharT, std::true_type>>;
|
||||||
|
|
||||||
|
BuffT buff1(&base, test_allocator<CharT, std::true_type>{42});
|
||||||
|
buff1.sputc(CharT('A'));
|
||||||
|
|
||||||
|
assert(buff1.get_wrapped() != nullptr);
|
||||||
|
|
||||||
|
BuffT buff2;
|
||||||
|
assert(buff2.get_allocator().id == -1);
|
||||||
|
buff2 = std::move(buff1);
|
||||||
|
assert(buff1.get_wrapped() == nullptr);
|
||||||
|
assert(buff2.get_wrapped() == &base);
|
||||||
|
|
||||||
|
assert(buff2.get_wrapped() == &base);
|
||||||
|
assert(buff2.get_allocator().id == 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // Test using the real class, non-propagating allocator.
|
||||||
|
using BuffT = std::basic_syncbuf<CharT, std::char_traits<CharT>, test_allocator<CharT, std::false_type>>;
|
||||||
|
|
||||||
|
BuffT buff1(&base, test_allocator<CharT, std::false_type>{42});
|
||||||
|
buff1.sputc(CharT('A'));
|
||||||
|
|
||||||
|
assert(buff1.get_wrapped() != nullptr);
|
||||||
|
|
||||||
|
BuffT buff2;
|
||||||
|
assert(buff2.get_allocator().id == -1);
|
||||||
|
buff2 = std::move(buff1);
|
||||||
|
assert(buff1.get_wrapped() == nullptr);
|
||||||
|
assert(buff2.get_wrapped() == &base);
|
||||||
|
|
||||||
|
assert(buff2.get_wrapped() == &base);
|
||||||
|
assert(buff2.get_allocator().id == -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // Move assignment propagating allocator
|
||||||
|
// Test using the inspection wrapper.
|
||||||
|
// Not all these requirements are explicitly in the Standard,
|
||||||
|
// however the asserts are based on secondary requirements. The
|
||||||
|
// LIBCPP_ASSERTs are implementation specific.
|
||||||
|
|
||||||
|
using BuffT = std::basic_syncbuf<CharT, std::char_traits<CharT>, std::allocator<CharT>>;
|
||||||
|
|
||||||
|
using Inspector = syncbuf_inspector<CharT, std::char_traits<CharT>, std::allocator<CharT>>;
|
||||||
|
Inspector inspector1{BuffT(&base)};
|
||||||
|
inspector1.sputc(CharT('A'));
|
||||||
|
|
||||||
|
assert(inspector1.get_wrapped() != nullptr);
|
||||||
|
assert(inspector1.pbase() != nullptr);
|
||||||
|
assert(inspector1.pptr() != nullptr);
|
||||||
|
assert(inspector1.epptr() != nullptr);
|
||||||
|
assert(inspector1.pbase() != inspector1.pptr());
|
||||||
|
assert(inspector1.pptr() - inspector1.pbase() == 1);
|
||||||
|
[[maybe_unused]] std::streamsize size = inspector1.epptr() - inspector1.pbase();
|
||||||
|
|
||||||
|
Inspector inspector2;
|
||||||
|
inspector2 = std::move(inspector1);
|
||||||
|
|
||||||
|
assert(inspector1.get_wrapped() == nullptr);
|
||||||
|
LIBCPP_ASSERT(inspector1.pbase() == nullptr);
|
||||||
|
LIBCPP_ASSERT(inspector1.pptr() == nullptr);
|
||||||
|
LIBCPP_ASSERT(inspector1.epptr() == nullptr);
|
||||||
|
assert(inspector1.pbase() == inspector1.pptr());
|
||||||
|
|
||||||
|
assert(inspector2.get_wrapped() == &base);
|
||||||
|
LIBCPP_ASSERT(inspector2.pbase() != nullptr);
|
||||||
|
LIBCPP_ASSERT(inspector2.pptr() != nullptr);
|
||||||
|
LIBCPP_ASSERT(inspector2.epptr() != nullptr);
|
||||||
|
assert(inspector2.pptr() - inspector2.pbase() == 1);
|
||||||
|
LIBCPP_ASSERT(inspector2.epptr() - inspector2.pbase() == size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_basic() {
|
||||||
|
{ // Test properties
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(nullptr);
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(nullptr);
|
||||||
|
[[maybe_unused]] std::same_as<std::basic_syncbuf<CharT>&> decltype(auto) ret =
|
||||||
|
sync_buf1.operator=(std::move(sync_buf2));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::basic_stringbuf<CharT> sstr1;
|
||||||
|
std::basic_stringbuf<CharT> sstr2;
|
||||||
|
std::basic_string<CharT> expected(42, CharT('*')); // a long string
|
||||||
|
|
||||||
|
{
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(&sstr1);
|
||||||
|
sync_buf1.sputc(CharT('A')); // a short string
|
||||||
|
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(&sstr2);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&sstr1) == 1);
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&sstr2) == 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sync_buf2 = std::move(sync_buf1);
|
||||||
|
assert(sync_buf2.get_wrapped() == &sstr1);
|
||||||
|
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&sstr1) == 1);
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&sstr2) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sstr1.str().size() == 1);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_short_write_after_assign() {
|
||||||
|
std::basic_stringbuf<CharT> sstr1;
|
||||||
|
std::basic_stringbuf<CharT> sstr2;
|
||||||
|
std::basic_string<CharT> expected(42, CharT('*')); // a long string
|
||||||
|
|
||||||
|
{
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(&sstr1);
|
||||||
|
sync_buf1.sputc(CharT('A')); // a short string
|
||||||
|
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(&sstr2);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
sync_buf2 = std::move(sync_buf1);
|
||||||
|
sync_buf2.sputc(CharT('Z'));
|
||||||
|
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sstr1.str().size() == 2);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr1.str()[1] == CharT('Z'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_long_write_after_assign() {
|
||||||
|
std::basic_stringbuf<CharT> sstr1;
|
||||||
|
std::basic_stringbuf<CharT> sstr2;
|
||||||
|
std::basic_string<CharT> expected(42, CharT('*')); // a long string
|
||||||
|
|
||||||
|
{
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(&sstr1);
|
||||||
|
sync_buf1.sputc(CharT('A')); // a short string
|
||||||
|
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(&sstr2);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
sync_buf2 = std::move(sync_buf1);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sstr1.str().size() == 1 + expected.size());
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr1.str().substr(1) == expected);
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_emit_on_assign() {
|
||||||
|
{ // don't emit / don't emit
|
||||||
|
|
||||||
|
std::basic_stringbuf<CharT> sstr1;
|
||||||
|
std::basic_stringbuf<CharT> sstr2;
|
||||||
|
std::basic_string<CharT> expected(42, CharT('*')); // a long string
|
||||||
|
|
||||||
|
{
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(&sstr1);
|
||||||
|
sync_buf1.set_emit_on_sync(false);
|
||||||
|
sync_buf1.sputc(CharT('A')); // a short string
|
||||||
|
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(&sstr2);
|
||||||
|
sync_buf2.set_emit_on_sync(false);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
sync_buf2 = std::move(sync_buf1);
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
|
||||||
|
sync_buf2.pubsync();
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sstr1.str().size() == 1);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // don't emit / do emit
|
||||||
|
|
||||||
|
std::basic_stringbuf<CharT> sstr1;
|
||||||
|
std::basic_stringbuf<CharT> sstr2;
|
||||||
|
std::basic_string<CharT> expected(42, CharT('*')); // a long string
|
||||||
|
|
||||||
|
{
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(&sstr1);
|
||||||
|
sync_buf1.set_emit_on_sync(true);
|
||||||
|
sync_buf1.sputc(CharT('A')); // a short string
|
||||||
|
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(&sstr2);
|
||||||
|
sync_buf2.set_emit_on_sync(false);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
sync_buf2 = std::move(sync_buf1);
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
|
||||||
|
sync_buf2.pubsync();
|
||||||
|
assert(sstr1.str().size() == 1);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sstr1.str().size() == 1);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // do emit / don't emit
|
||||||
|
|
||||||
|
std::basic_stringbuf<CharT> sstr1;
|
||||||
|
std::basic_stringbuf<CharT> sstr2;
|
||||||
|
std::basic_string<CharT> expected(42, CharT('*')); // a long string
|
||||||
|
|
||||||
|
{
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(&sstr1);
|
||||||
|
sync_buf1.set_emit_on_sync(false);
|
||||||
|
sync_buf1.sputc(CharT('A')); // a short string
|
||||||
|
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(&sstr2);
|
||||||
|
sync_buf2.set_emit_on_sync(true);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
sync_buf2 = std::move(sync_buf1);
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
|
||||||
|
sync_buf2.pubsync();
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sstr1.str().size() == 1);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // do emit / do emit
|
||||||
|
|
||||||
|
std::basic_stringbuf<CharT> sstr1;
|
||||||
|
std::basic_stringbuf<CharT> sstr2;
|
||||||
|
std::basic_string<CharT> expected(42, CharT('*')); // a long string
|
||||||
|
|
||||||
|
{
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(&sstr1);
|
||||||
|
sync_buf1.set_emit_on_sync(true);
|
||||||
|
sync_buf1.sputc(CharT('A')); // a short string
|
||||||
|
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(&sstr2);
|
||||||
|
sync_buf2.set_emit_on_sync(true);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
sync_buf2 = std::move(sync_buf1);
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
|
||||||
|
sync_buf2.pubsync();
|
||||||
|
assert(sstr1.str().size() == 1);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sstr1.str().size() == 1);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test() {
|
||||||
|
test_assign<CharT>();
|
||||||
|
test_basic<CharT>();
|
||||||
|
test_short_write_after_assign<CharT>();
|
||||||
|
test_long_write_after_assign<CharT>();
|
||||||
|
test_emit_on_assign<CharT>();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,274 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_syncbuf;
|
||||||
|
|
||||||
|
// void swap(basic_syncbuf& other) noexcept;
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_basic() {
|
||||||
|
std::basic_stringbuf<CharT> sstr1;
|
||||||
|
std::basic_stringbuf<CharT> sstr2;
|
||||||
|
std::basic_string<CharT> expected(42, CharT('*')); // a long string
|
||||||
|
|
||||||
|
{
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(&sstr1);
|
||||||
|
sync_buf1.sputc(CharT('A')); // a short string
|
||||||
|
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(&sstr2);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&sstr1) == 1);
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&sstr2) == 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sync_buf1.swap(sync_buf2);
|
||||||
|
assert(sync_buf1.get_wrapped() == &sstr2);
|
||||||
|
assert(sync_buf2.get_wrapped() == &sstr1);
|
||||||
|
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str().empty());
|
||||||
|
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&sstr1) == 1);
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&sstr2) == 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sstr1.str().size() == 1);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_short_write_after_swap() {
|
||||||
|
std::basic_stringbuf<CharT> sstr1;
|
||||||
|
std::basic_stringbuf<CharT> sstr2;
|
||||||
|
std::basic_string<CharT> expected(42, CharT('*')); // a long string
|
||||||
|
|
||||||
|
{
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(&sstr1);
|
||||||
|
sync_buf1.sputc(CharT('A')); // a short string
|
||||||
|
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(&sstr2);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
sync_buf1.swap(sync_buf2);
|
||||||
|
expected.push_back(sync_buf1.sputc(CharT('B')));
|
||||||
|
sync_buf2.sputc(CharT('Z'));
|
||||||
|
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sstr1.str().size() == 2);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr1.str()[1] == CharT('Z'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_long_write_after_swap() {
|
||||||
|
std::basic_stringbuf<CharT> sstr1;
|
||||||
|
std::basic_stringbuf<CharT> sstr2;
|
||||||
|
std::basic_string<CharT> expected(42, CharT('*')); // a long string
|
||||||
|
|
||||||
|
{
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(&sstr1);
|
||||||
|
sync_buf1.sputc(CharT('A')); // a short string
|
||||||
|
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(&sstr2);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
sync_buf1.swap(sync_buf2);
|
||||||
|
sync_buf1.sputn(expected.data(), expected.size());
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sstr1.str().size() == 1 + expected.size());
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr1.str().substr(1) == expected);
|
||||||
|
assert(sstr2.str() == expected + expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_emit_on_sync() {
|
||||||
|
{ // false false
|
||||||
|
|
||||||
|
std::basic_stringbuf<CharT> sstr1;
|
||||||
|
std::basic_stringbuf<CharT> sstr2;
|
||||||
|
std::basic_string<CharT> expected(42, CharT('*')); // a long string
|
||||||
|
|
||||||
|
{
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(&sstr1);
|
||||||
|
sync_buf1.set_emit_on_sync(false);
|
||||||
|
sync_buf1.sputc(CharT('A')); // a short string
|
||||||
|
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(&sstr2);
|
||||||
|
sync_buf2.set_emit_on_sync(false);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
sync_buf1.swap(sync_buf2);
|
||||||
|
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str().empty());
|
||||||
|
|
||||||
|
sync_buf1.pubsync();
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str().empty());
|
||||||
|
|
||||||
|
sync_buf2.pubsync();
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sstr1.str().size() == 1);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // false true
|
||||||
|
|
||||||
|
std::basic_stringbuf<CharT> sstr1;
|
||||||
|
std::basic_stringbuf<CharT> sstr2;
|
||||||
|
std::basic_string<CharT> expected(42, CharT('*')); // a long string
|
||||||
|
|
||||||
|
{
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(&sstr1);
|
||||||
|
sync_buf1.set_emit_on_sync(true);
|
||||||
|
sync_buf1.sputc(CharT('A')); // a short string
|
||||||
|
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(&sstr2);
|
||||||
|
sync_buf2.set_emit_on_sync(false);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
sync_buf1.swap(sync_buf2);
|
||||||
|
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str().empty());
|
||||||
|
|
||||||
|
sync_buf1.pubsync();
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str().empty());
|
||||||
|
|
||||||
|
sync_buf2.pubsync();
|
||||||
|
assert(sstr1.str().size() == 1);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr2.str().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sstr1.str().size() == 1);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // true false
|
||||||
|
|
||||||
|
std::basic_stringbuf<CharT> sstr1;
|
||||||
|
std::basic_stringbuf<CharT> sstr2;
|
||||||
|
std::basic_string<CharT> expected(42, CharT('*')); // a long string
|
||||||
|
|
||||||
|
{
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(&sstr1);
|
||||||
|
sync_buf1.set_emit_on_sync(false);
|
||||||
|
sync_buf1.sputc(CharT('A')); // a short string
|
||||||
|
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(&sstr2);
|
||||||
|
sync_buf2.set_emit_on_sync(true);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
sync_buf1.swap(sync_buf2);
|
||||||
|
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str().empty());
|
||||||
|
|
||||||
|
sync_buf1.pubsync();
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
|
||||||
|
sync_buf2.pubsync();
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sstr1.str().size() == 1);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // true true
|
||||||
|
|
||||||
|
std::basic_stringbuf<CharT> sstr1;
|
||||||
|
std::basic_stringbuf<CharT> sstr2;
|
||||||
|
std::basic_string<CharT> expected(42, CharT('*')); // a long string
|
||||||
|
|
||||||
|
{
|
||||||
|
std::basic_syncbuf<CharT> sync_buf1(&sstr1);
|
||||||
|
sync_buf1.set_emit_on_sync(true);
|
||||||
|
sync_buf1.sputc(CharT('A')); // a short string
|
||||||
|
|
||||||
|
std::basic_syncbuf<CharT> sync_buf2(&sstr2);
|
||||||
|
sync_buf2.set_emit_on_sync(true);
|
||||||
|
sync_buf2.sputn(expected.data(), expected.size());
|
||||||
|
|
||||||
|
sync_buf1.swap(sync_buf2);
|
||||||
|
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str().empty());
|
||||||
|
|
||||||
|
sync_buf1.pubsync();
|
||||||
|
assert(sstr1.str().empty());
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
|
||||||
|
sync_buf2.pubsync();
|
||||||
|
assert(sstr1.str().size() == 1);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sstr1.str().size() == 1);
|
||||||
|
assert(sstr1.str()[0] == CharT('A'));
|
||||||
|
assert(sstr2.str() == expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test() {
|
||||||
|
test_basic<CharT>();
|
||||||
|
test_emit_on_sync<CharT>();
|
||||||
|
test_short_write_after_swap<CharT>();
|
||||||
|
test_long_write_after_swap<CharT>();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_syncbuf;
|
||||||
|
|
||||||
|
// basic_syncbuf();
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <concepts>
|
||||||
|
#include <syncstream>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "constexpr_char_traits.h"
|
||||||
|
#include "test_allocator.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
{
|
||||||
|
using Buf = std::basic_syncbuf<CharT>;
|
||||||
|
static_assert(std::default_initializable<Buf>);
|
||||||
|
Buf buf;
|
||||||
|
assert(buf.get_wrapped() == nullptr);
|
||||||
|
assert(buf.get_allocator() == std::allocator<CharT>());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
using Buf = std::basic_syncbuf<CharT, constexpr_char_traits<CharT>>;
|
||||||
|
static_assert(std::default_initializable<Buf>);
|
||||||
|
Buf buf;
|
||||||
|
assert(buf.get_wrapped() == nullptr);
|
||||||
|
assert(buf.get_allocator() == std::allocator<CharT>());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
using Buf = std::basic_syncbuf<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
static_assert(std::default_initializable<Buf>);
|
||||||
|
Buf buf;
|
||||||
|
assert(buf.get_wrapped() == nullptr);
|
||||||
|
assert(buf.get_allocator() == test_allocator<CharT>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,136 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_syncbuf;
|
||||||
|
|
||||||
|
// basic_syncbuf(basic_syncbuf&& other);
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "constexpr_char_traits.h"
|
||||||
|
#include "test_allocator.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
{
|
||||||
|
using Buf = std::basic_syncbuf<CharT>;
|
||||||
|
const std::allocator<CharT> alloc;
|
||||||
|
{
|
||||||
|
Buf b1{nullptr, alloc};
|
||||||
|
Buf b2{std::move(b1)};
|
||||||
|
|
||||||
|
assert(b2.get_wrapped() == nullptr);
|
||||||
|
assert(b2.get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Buf w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Buf b1{&w, alloc};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
Buf b2{std::move(b1)};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(b2.get_wrapped() == &w);
|
||||||
|
assert(b2.get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using Buf = std::basic_syncbuf<CharT, constexpr_char_traits<CharT>>;
|
||||||
|
const std::allocator<CharT> alloc;
|
||||||
|
{
|
||||||
|
Buf b1{nullptr, alloc};
|
||||||
|
Buf b2{std::move(b1)};
|
||||||
|
|
||||||
|
assert(b2.get_wrapped() == nullptr);
|
||||||
|
assert(b2.get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Buf w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Buf b1{&w, alloc};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
Buf b2{std::move(b1)};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(b2.get_wrapped() == &w);
|
||||||
|
assert(b2.get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using Buf = std::basic_syncbuf<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
test_allocator<CharT> alloc{42};
|
||||||
|
{
|
||||||
|
Buf b1{nullptr, alloc};
|
||||||
|
Buf b2{std::move(b1)};
|
||||||
|
|
||||||
|
assert(b2.get_wrapped() == nullptr);
|
||||||
|
assert(b2.get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Buf w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Buf b1{&w, alloc};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
Buf b2{std::move(b1)};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(b2.get_wrapped() == &w);
|
||||||
|
assert(b2.get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,119 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_syncbuf;
|
||||||
|
|
||||||
|
// basic_syncbuf(streambuf_type* obuf, const Allocator&);
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <concepts>
|
||||||
|
#include <syncstream>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "constexpr_char_traits.h"
|
||||||
|
#include "test_allocator.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
{
|
||||||
|
using Buf = std::basic_syncbuf<CharT>;
|
||||||
|
const std::allocator<CharT> alloc;
|
||||||
|
{
|
||||||
|
Buf buf = {nullptr, alloc};
|
||||||
|
assert(buf.get_wrapped() == nullptr);
|
||||||
|
assert(buf.get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Buf w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Buf buf = {&w, alloc};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(buf.get_wrapped() == &w);
|
||||||
|
assert(buf.get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using Buf = std::basic_syncbuf<CharT, constexpr_char_traits<CharT>>;
|
||||||
|
const std::allocator<CharT> alloc;
|
||||||
|
{
|
||||||
|
Buf buf = {nullptr, alloc};
|
||||||
|
assert(buf.get_wrapped() == nullptr);
|
||||||
|
assert(buf.get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Buf w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Buf buf{&w, alloc};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(buf.get_wrapped() == &w);
|
||||||
|
assert(buf.get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using Buf = std::basic_syncbuf<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
test_allocator<CharT> alloc{42};
|
||||||
|
{
|
||||||
|
Buf buf = {nullptr, alloc};
|
||||||
|
assert(buf.get_wrapped() == nullptr);
|
||||||
|
assert(buf.get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Buf w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Buf buf{&w, alloc};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(buf.get_wrapped() == &w);
|
||||||
|
assert(buf.get_allocator() == alloc);
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,128 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_syncbuf;
|
||||||
|
|
||||||
|
// explicit basic_syncbuf(streambuf_type* obuf);
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <concepts>
|
||||||
|
#include <syncstream>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "constexpr_char_traits.h"
|
||||||
|
#include "test_allocator.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
{
|
||||||
|
using Buf = std::basic_syncbuf<CharT>;
|
||||||
|
|
||||||
|
static_assert(!std::convertible_to<std::basic_streambuf<CharT>*, Buf>);
|
||||||
|
static_assert(std::constructible_from<Buf, std::basic_streambuf<CharT>*>);
|
||||||
|
|
||||||
|
{
|
||||||
|
Buf buf{nullptr};
|
||||||
|
assert(buf.get_wrapped() == nullptr);
|
||||||
|
assert(buf.get_allocator() == std::allocator<CharT>());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Buf w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Buf buf{&w};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(buf.get_wrapped() == &w);
|
||||||
|
assert(buf.get_allocator() == std::allocator<CharT>());
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using Buf = std::basic_syncbuf<CharT, constexpr_char_traits<CharT>>;
|
||||||
|
|
||||||
|
static_assert(!std::convertible_to<std::basic_streambuf<CharT, constexpr_char_traits<CharT>>*, Buf>);
|
||||||
|
static_assert(std::constructible_from<Buf, std::basic_streambuf<CharT, constexpr_char_traits<CharT>>*>);
|
||||||
|
|
||||||
|
{
|
||||||
|
Buf buf{nullptr};
|
||||||
|
assert(buf.get_wrapped() == nullptr);
|
||||||
|
assert(buf.get_allocator() == std::allocator<CharT>());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Buf w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Buf buf{&w};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(buf.get_wrapped() == &w);
|
||||||
|
assert(buf.get_allocator() == std::allocator<CharT>());
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using Buf = std::basic_syncbuf<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>;
|
||||||
|
|
||||||
|
static_assert(!std::convertible_to<std::basic_streambuf<CharT, constexpr_char_traits<CharT>>*, Buf>);
|
||||||
|
static_assert(std::constructible_from<Buf, std::basic_streambuf<CharT, constexpr_char_traits<CharT>>*>);
|
||||||
|
|
||||||
|
{
|
||||||
|
Buf buf{nullptr};
|
||||||
|
assert(buf.get_wrapped() == nullptr);
|
||||||
|
assert(buf.get_allocator() == test_allocator<CharT>());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Buf w;
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Buf buf{&w};
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 1);
|
||||||
|
#endif
|
||||||
|
assert(buf.get_wrapped() == &w);
|
||||||
|
assert(buf.get_allocator() == test_allocator<CharT>());
|
||||||
|
}
|
||||||
|
#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS)
|
||||||
|
assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&w) == 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_syncbuf;
|
||||||
|
|
||||||
|
// ~basic_syncbuf();
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "../helpers.h"
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
// We do this because we want to be able to use CharT
|
||||||
|
CharT arr[3] = {'a', 'b', 'c'};
|
||||||
|
CharT* ptr = arr;
|
||||||
|
|
||||||
|
test_buf<CharT> base;
|
||||||
|
const std::allocator<CharT> alloc;
|
||||||
|
{
|
||||||
|
test_syncbuf<CharT> buf(&base, alloc);
|
||||||
|
|
||||||
|
buf._setp(ptr, ptr + 3);
|
||||||
|
assert(base._pptr() == nullptr);
|
||||||
|
// The destructor calls buf.emit();
|
||||||
|
}
|
||||||
|
CharT* pptr = base._pptr();
|
||||||
|
while (pptr) {
|
||||||
|
assert(*pptr++ == *ptr++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_syncbuf;
|
||||||
|
|
||||||
|
// bool emit();
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "../helpers.h"
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
// We do this because we want to be able to use CharT
|
||||||
|
CharT arr[3] = {'a', 'b', 'c'};
|
||||||
|
CharT* ptr = arr;
|
||||||
|
|
||||||
|
test_buf<CharT> base;
|
||||||
|
const std::allocator<CharT> alloc;
|
||||||
|
test_syncbuf<CharT> buff(&base, alloc);
|
||||||
|
|
||||||
|
buff._setp(ptr, ptr + 3);
|
||||||
|
assert(base._pptr() == nullptr);
|
||||||
|
buff.emit();
|
||||||
|
CharT* pptr = base._pptr();
|
||||||
|
while (pptr) {
|
||||||
|
assert(*pptr++ == *ptr++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_syncbuf;
|
||||||
|
|
||||||
|
// allocator_type get_allocator() const noexcept;
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "../helpers.h"
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void test_get_allocator() {
|
||||||
|
test_buf<T> base;
|
||||||
|
test_allocator<T> alloc(42);
|
||||||
|
const test_syncbuf<T, test_allocator<T>> buff(&base, alloc);
|
||||||
|
assert(buff.get_allocator().id == 42);
|
||||||
|
ASSERT_NOEXCEPT(buff.get_allocator());
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test_get_allocator<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test_get_allocator<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_syncbuf;
|
||||||
|
|
||||||
|
// streambuf_type* get_wrapped() const noexcept;
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <concepts>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "../helpers.h"
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void test() {
|
||||||
|
test_buf<T> base(42);
|
||||||
|
const std::allocator<T> alloc;
|
||||||
|
const test_syncbuf<T> buff(&base, alloc);
|
||||||
|
std::same_as<std::basic_streambuf<T>*> auto wrapped = buff.get_wrapped();
|
||||||
|
assert(static_cast<test_buf<T>*>(wrapped)->id == 42);
|
||||||
|
ASSERT_NOEXCEPT(buff.get_wrapped());
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template <class charT, class traits, class Allocator>
|
||||||
|
// class basic_syncbuf;
|
||||||
|
|
||||||
|
// void set_emit_on_sync(bool) noexcept;
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "../helpers.h"
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void test_set_emit_on_sync() {
|
||||||
|
// set_emit_on_sync tested in sync, which is called by pubsync. The assign
|
||||||
|
// and swap test use this.
|
||||||
|
test_syncbuf<T, std::allocator<T>> buff(nullptr, std::allocator<T>());
|
||||||
|
ASSERT_NOEXCEPT(buff.set_emit_on_sync(false));
|
||||||
|
buff.set_emit_on_sync(false); // Validates the function can be called.
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test_set_emit_on_sync<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test_set_emit_on_sync<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template<class charT, class traits, class Allocator>
|
||||||
|
// void swap(basic_syncbuf<charT, traits, Allocator>&,
|
||||||
|
// basic_syncbuf<charT, traits, Allocator>&);
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
void test() {
|
||||||
|
std::basic_syncbuf<CharT> base1;
|
||||||
|
std::basic_syncbuf<CharT> base2;
|
||||||
|
std::basic_syncbuf<CharT> buff1(&base1);
|
||||||
|
std::basic_syncbuf<CharT> buff2(&base2);
|
||||||
|
std::swap(buff1, buff2);
|
||||||
|
|
||||||
|
assert(buff1.get_wrapped() == &base2);
|
||||||
|
assert(buff2.get_wrapped() == &base1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
|
||||||
|
// class basic_syncbuf {
|
||||||
|
//
|
||||||
|
// public:
|
||||||
|
// using char_type = charT;
|
||||||
|
// using int_type = typename traits::int_type;
|
||||||
|
// using pos_type = typename traits::pos_type;
|
||||||
|
// using off_type = typename traits::off_type;
|
||||||
|
// using traits_type = traits;
|
||||||
|
// using allocator_type = Allocator;
|
||||||
|
//
|
||||||
|
// using streambuf_type = basic_streambuf<charT, traits>;
|
||||||
|
//
|
||||||
|
// ...
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include <concepts>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "constexpr_char_traits.h"
|
||||||
|
#include "test_allocator.h"
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_syncbuf<char>, std::basic_syncbuf<char, std::char_traits<char>, std::allocator<char>>>);
|
||||||
|
static_assert(std::same_as<std::basic_syncbuf<char, constexpr_char_traits<char>>,
|
||||||
|
std::basic_syncbuf<char, constexpr_char_traits<char>, std::allocator<char>>>);
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_syncbuf<char, constexpr_char_traits<char>, test_allocator<char>>::char_type, char>);
|
||||||
|
static_assert(std::same_as<std::basic_syncbuf<char, constexpr_char_traits<char>, test_allocator<char>>::int_type,
|
||||||
|
constexpr_char_traits<char>::int_type>);
|
||||||
|
static_assert(std::same_as<std::basic_syncbuf<char, constexpr_char_traits<char>, test_allocator<char>>::pos_type,
|
||||||
|
constexpr_char_traits<char>::pos_type>);
|
||||||
|
static_assert(std::same_as<std::basic_syncbuf<char, constexpr_char_traits<char>, test_allocator<char>>::off_type,
|
||||||
|
constexpr_char_traits<char>::off_type>);
|
||||||
|
static_assert(std::same_as<std::basic_syncbuf<char, constexpr_char_traits<char>, test_allocator<char>>::traits_type,
|
||||||
|
constexpr_char_traits<char>>);
|
||||||
|
static_assert(std::same_as<std::basic_syncbuf<char, constexpr_char_traits<char>, test_allocator<char>>::allocator_type,
|
||||||
|
test_allocator<char>>);
|
||||||
|
static_assert(std::same_as<std::basic_syncbuf<char, constexpr_char_traits<char>, test_allocator<char>>::streambuf_type,
|
||||||
|
std::basic_streambuf<char, constexpr_char_traits<char>>>);
|
||||||
|
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
static_assert(std::same_as<std::basic_syncbuf<wchar_t>,
|
||||||
|
std::basic_syncbuf<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>);
|
||||||
|
static_assert(std::same_as<std::basic_syncbuf<wchar_t, constexpr_char_traits<wchar_t>>,
|
||||||
|
std::basic_syncbuf<wchar_t, constexpr_char_traits<wchar_t>, std::allocator<wchar_t>>>);
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_syncbuf<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::char_type,
|
||||||
|
wchar_t>);
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_syncbuf<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::int_type,
|
||||||
|
constexpr_char_traits<wchar_t>::int_type>);
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_syncbuf<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::pos_type,
|
||||||
|
constexpr_char_traits<wchar_t>::pos_type>);
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_syncbuf<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::off_type,
|
||||||
|
constexpr_char_traits<wchar_t>::off_type>);
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_syncbuf<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::traits_type,
|
||||||
|
constexpr_char_traits<wchar_t>>);
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_syncbuf<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::allocator_type,
|
||||||
|
test_allocator<wchar_t>>);
|
||||||
|
static_assert(
|
||||||
|
std::same_as<std::basic_syncbuf<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>::streambuf_type,
|
||||||
|
std::basic_streambuf<wchar_t, constexpr_char_traits<wchar_t>>>);
|
||||||
|
#endif // TEST_HAS_NO_WIDE_CHARACTERS
|
@ -0,0 +1,91 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// WARNING: This test was generated by generate_feature_test_macro_components.py
|
||||||
|
// and should not be edited manually.
|
||||||
|
//
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
// UNSUPPORTED: no-localization
|
||||||
|
|
||||||
|
// <syncstream>
|
||||||
|
|
||||||
|
// Test the feature test macros defined by <syncstream>
|
||||||
|
|
||||||
|
/* Constant Value
|
||||||
|
__cpp_lib_syncbuf 201803L [C++20]
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <syncstream>
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
#if TEST_STD_VER < 14
|
||||||
|
|
||||||
|
# ifdef __cpp_lib_syncbuf
|
||||||
|
# error "__cpp_lib_syncbuf should not be defined before c++20"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif TEST_STD_VER == 14
|
||||||
|
|
||||||
|
# ifdef __cpp_lib_syncbuf
|
||||||
|
# error "__cpp_lib_syncbuf should not be defined before c++20"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif TEST_STD_VER == 17
|
||||||
|
|
||||||
|
# ifdef __cpp_lib_syncbuf
|
||||||
|
# error "__cpp_lib_syncbuf should not be defined before c++20"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif TEST_STD_VER == 20
|
||||||
|
|
||||||
|
# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
|
||||||
|
# ifndef __cpp_lib_syncbuf
|
||||||
|
# error "__cpp_lib_syncbuf should be defined in c++20"
|
||||||
|
# endif
|
||||||
|
# if __cpp_lib_syncbuf != 201803L
|
||||||
|
# error "__cpp_lib_syncbuf should have the value 201803L in c++20"
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# ifdef __cpp_lib_syncbuf
|
||||||
|
# error "__cpp_lib_syncbuf should not be defined when the requirement '!defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)' is not met!"
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif TEST_STD_VER == 23
|
||||||
|
|
||||||
|
# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
|
||||||
|
# ifndef __cpp_lib_syncbuf
|
||||||
|
# error "__cpp_lib_syncbuf should be defined in c++23"
|
||||||
|
# endif
|
||||||
|
# if __cpp_lib_syncbuf != 201803L
|
||||||
|
# error "__cpp_lib_syncbuf should have the value 201803L in c++23"
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# ifdef __cpp_lib_syncbuf
|
||||||
|
# error "__cpp_lib_syncbuf should not be defined when the requirement '!defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)' is not met!"
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif TEST_STD_VER > 23
|
||||||
|
|
||||||
|
# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
|
||||||
|
# ifndef __cpp_lib_syncbuf
|
||||||
|
# error "__cpp_lib_syncbuf should be defined in c++26"
|
||||||
|
# endif
|
||||||
|
# if __cpp_lib_syncbuf != 201803L
|
||||||
|
# error "__cpp_lib_syncbuf should have the value 201803L in c++26"
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# ifdef __cpp_lib_syncbuf
|
||||||
|
# error "__cpp_lib_syncbuf should not be defined when the requirement '!defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)' is not met!"
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif // TEST_STD_VER > 23
|
||||||
|
|
@ -3822,16 +3822,16 @@
|
|||||||
# error "__cpp_lib_submdspan should not be defined before c++26"
|
# error "__cpp_lib_submdspan should not be defined before c++26"
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if !defined(_LIBCPP_VERSION)
|
# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
|
||||||
# ifndef __cpp_lib_syncbuf
|
# ifndef __cpp_lib_syncbuf
|
||||||
# error "__cpp_lib_syncbuf should be defined in c++20"
|
# error "__cpp_lib_syncbuf should be defined in c++20"
|
||||||
# endif
|
# endif
|
||||||
# if __cpp_lib_syncbuf != 201803L
|
# if __cpp_lib_syncbuf != 201803L
|
||||||
# error "__cpp_lib_syncbuf should have the value 201803L in c++20"
|
# error "__cpp_lib_syncbuf should have the value 201803L in c++20"
|
||||||
# endif
|
# endif
|
||||||
# else // _LIBCPP_VERSION
|
# else
|
||||||
# ifdef __cpp_lib_syncbuf
|
# ifdef __cpp_lib_syncbuf
|
||||||
# error "__cpp_lib_syncbuf should not be defined because it is unimplemented in libc++!"
|
# error "__cpp_lib_syncbuf should not be defined when the requirement '!defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)' is not met!"
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
@ -5294,16 +5294,16 @@
|
|||||||
# error "__cpp_lib_submdspan should not be defined before c++26"
|
# error "__cpp_lib_submdspan should not be defined before c++26"
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if !defined(_LIBCPP_VERSION)
|
# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
|
||||||
# ifndef __cpp_lib_syncbuf
|
# ifndef __cpp_lib_syncbuf
|
||||||
# error "__cpp_lib_syncbuf should be defined in c++23"
|
# error "__cpp_lib_syncbuf should be defined in c++23"
|
||||||
# endif
|
# endif
|
||||||
# if __cpp_lib_syncbuf != 201803L
|
# if __cpp_lib_syncbuf != 201803L
|
||||||
# error "__cpp_lib_syncbuf should have the value 201803L in c++23"
|
# error "__cpp_lib_syncbuf should have the value 201803L in c++23"
|
||||||
# endif
|
# endif
|
||||||
# else // _LIBCPP_VERSION
|
# else
|
||||||
# ifdef __cpp_lib_syncbuf
|
# ifdef __cpp_lib_syncbuf
|
||||||
# error "__cpp_lib_syncbuf should not be defined because it is unimplemented in libc++!"
|
# error "__cpp_lib_syncbuf should not be defined when the requirement '!defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)' is not met!"
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
@ -6868,16 +6868,16 @@
|
|||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if !defined(_LIBCPP_VERSION)
|
# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
|
||||||
# ifndef __cpp_lib_syncbuf
|
# ifndef __cpp_lib_syncbuf
|
||||||
# error "__cpp_lib_syncbuf should be defined in c++26"
|
# error "__cpp_lib_syncbuf should be defined in c++26"
|
||||||
# endif
|
# endif
|
||||||
# if __cpp_lib_syncbuf != 201803L
|
# if __cpp_lib_syncbuf != 201803L
|
||||||
# error "__cpp_lib_syncbuf should have the value 201803L in c++26"
|
# error "__cpp_lib_syncbuf should have the value 201803L in c++26"
|
||||||
# endif
|
# endif
|
||||||
# else // _LIBCPP_VERSION
|
# else
|
||||||
# ifdef __cpp_lib_syncbuf
|
# ifdef __cpp_lib_syncbuf
|
||||||
# error "__cpp_lib_syncbuf should not be defined because it is unimplemented in libc++!"
|
# error "__cpp_lib_syncbuf should not be defined when the requirement '!defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)' is not met!"
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
@ -29,8 +29,9 @@ TEST_CONSTEXPR_CXX20 inline typename std::allocator_traits<Alloc>::size_type all
|
|||||||
struct test_allocator_statistics {
|
struct test_allocator_statistics {
|
||||||
int time_to_throw = 0;
|
int time_to_throw = 0;
|
||||||
int throw_after = INT_MAX;
|
int throw_after = INT_MAX;
|
||||||
int count = 0;
|
int count = 0; // the number of active instances
|
||||||
int alloc_count = 0;
|
int alloc_count = 0; // the number of allocations not deallocating
|
||||||
|
int allocated_size = 0; // the size of allocated elements
|
||||||
int construct_count = 0; // the number of times that ::construct was called
|
int construct_count = 0; // the number of times that ::construct was called
|
||||||
int destroy_count = 0; // the number of times that ::destroy was called
|
int destroy_count = 0; // the number of times that ::destroy was called
|
||||||
int copied = 0;
|
int copied = 0;
|
||||||
@ -42,6 +43,7 @@ struct test_allocator_statistics {
|
|||||||
count = 0;
|
count = 0;
|
||||||
time_to_throw = 0;
|
time_to_throw = 0;
|
||||||
alloc_count = 0;
|
alloc_count = 0;
|
||||||
|
allocated_size = 0;
|
||||||
construct_count = 0;
|
construct_count = 0;
|
||||||
destroy_count = 0;
|
destroy_count = 0;
|
||||||
throw_after = INT_MAX;
|
throw_after = INT_MAX;
|
||||||
@ -155,14 +157,17 @@ public:
|
|||||||
TEST_THROW(std::bad_alloc());
|
TEST_THROW(std::bad_alloc());
|
||||||
++stats_->time_to_throw;
|
++stats_->time_to_throw;
|
||||||
++stats_->alloc_count;
|
++stats_->alloc_count;
|
||||||
|
stats_->allocated_size += n;
|
||||||
}
|
}
|
||||||
return std::allocator<value_type>().allocate(n);
|
return std::allocator<value_type>().allocate(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CONSTEXPR_CXX14 void deallocate(pointer p, size_type s) {
|
TEST_CONSTEXPR_CXX14 void deallocate(pointer p, size_type s) {
|
||||||
assert(data_ != test_alloc_base::destructed_value);
|
assert(data_ != test_alloc_base::destructed_value);
|
||||||
if (stats_ != nullptr)
|
if (stats_ != nullptr) {
|
||||||
--stats_->alloc_count;
|
--stats_->alloc_count;
|
||||||
|
stats_->allocated_size -= s;
|
||||||
|
}
|
||||||
std::allocator<value_type>().deallocate(p, s);
|
std::allocator<value_type>().deallocate(p, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,6 +280,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CONSTEXPR_CXX14 friend bool operator!=(const other_allocator& x, const other_allocator& y) { return !(x == y); }
|
TEST_CONSTEXPR_CXX14 friend bool operator!=(const other_allocator& x, const other_allocator& y) { return !(x == y); }
|
||||||
|
TEST_CONSTEXPR int get_data() const { return data_; }
|
||||||
|
|
||||||
typedef std::true_type propagate_on_container_copy_assignment;
|
typedef std::true_type propagate_on_container_copy_assignment;
|
||||||
typedef std::true_type propagate_on_container_move_assignment;
|
typedef std::true_type propagate_on_container_move_assignment;
|
||||||
|
@ -1023,7 +1023,8 @@ feature_test_macros = [
|
|||||||
"name": "__cpp_lib_syncbuf",
|
"name": "__cpp_lib_syncbuf",
|
||||||
"values": {"c++20": 201803},
|
"values": {"c++20": 201803},
|
||||||
"headers": ["syncstream"],
|
"headers": ["syncstream"],
|
||||||
"unimplemented": True,
|
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)",
|
||||||
|
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "__cpp_lib_text_encoding",
|
"name": "__cpp_lib_text_encoding",
|
||||||
@ -1180,6 +1181,7 @@ lit_markup = {
|
|||||||
"semaphore": ["UNSUPPORTED: no-threads"],
|
"semaphore": ["UNSUPPORTED: no-threads"],
|
||||||
"shared_mutex": ["UNSUPPORTED: no-threads"],
|
"shared_mutex": ["UNSUPPORTED: no-threads"],
|
||||||
"sstream": ["UNSUPPORTED: no-localization"],
|
"sstream": ["UNSUPPORTED: no-localization"],
|
||||||
|
"syncstream": ["UNSUPPORTED: no-localization"],
|
||||||
"stdatomic.h": ["UNSUPPORTED: no-threads"],
|
"stdatomic.h": ["UNSUPPORTED: no-threads"],
|
||||||
"stop_token": ["UNSUPPORTED: no-threads"],
|
"stop_token": ["UNSUPPORTED: no-threads"],
|
||||||
"thread": ["UNSUPPORTED: no-threads"],
|
"thread": ["UNSUPPORTED: no-threads"],
|
||||||
|
@ -30,6 +30,7 @@ header_restrictions = {
|
|||||||
"sstream": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
|
"sstream": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
|
||||||
"streambuf": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
|
"streambuf": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
|
||||||
"strstream": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
|
"strstream": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
|
||||||
|
"syncstream": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
|
||||||
|
|
||||||
# headers with #error directives
|
# headers with #error directives
|
||||||
"barrier": "!defined(_LIBCPP_HAS_NO_THREADS)",
|
"barrier": "!defined(_LIBCPP_HAS_NO_THREADS)",
|
||||||
@ -92,6 +93,7 @@ lit_header_restrictions = {
|
|||||||
"stop_token": "// UNSUPPORTED: no-threads, c++03, c++11, c++14, c++17",
|
"stop_token": "// UNSUPPORTED: no-threads, c++03, c++11, c++14, c++17",
|
||||||
"streambuf": "// UNSUPPORTED: no-localization",
|
"streambuf": "// UNSUPPORTED: no-localization",
|
||||||
"strstream": "// UNSUPPORTED: no-localization",
|
"strstream": "// UNSUPPORTED: no-localization",
|
||||||
|
"syncstream": "// UNSUPPORTED: no-localization",
|
||||||
"thread": "// UNSUPPORTED: no-threads, c++03",
|
"thread": "// UNSUPPORTED: no-threads, c++03",
|
||||||
"wchar.h": "// UNSUPPORTED: no-wide-characters",
|
"wchar.h": "// UNSUPPORTED: no-wide-characters",
|
||||||
"wctype.h": "// UNSUPPORTED: no-wide-characters",
|
"wctype.h": "// UNSUPPORTED: no-wide-characters",
|
||||||
@ -127,7 +129,7 @@ mandatory_inclusions = {
|
|||||||
"stack": ["compare", "initializer_list"],
|
"stack": ["compare", "initializer_list"],
|
||||||
"string_view": ["compare"],
|
"string_view": ["compare"],
|
||||||
"string": ["compare", "initializer_list"],
|
"string": ["compare", "initializer_list"],
|
||||||
# TODO "syncstream": ["ostream"],
|
"syncstream": ["ostream"],
|
||||||
"system_error": ["compare"],
|
"system_error": ["compare"],
|
||||||
"tgmath.h": ["cmath", "complex"],
|
"tgmath.h": ["cmath", "complex"],
|
||||||
"thread": ["compare"],
|
"thread": ["compare"],
|
||||||
@ -156,7 +158,6 @@ headers_not_available = [
|
|||||||
"spanstream",
|
"spanstream",
|
||||||
"stacktrace",
|
"stacktrace",
|
||||||
"stdfloat",
|
"stdfloat",
|
||||||
"syncstream",
|
|
||||||
"text_encoding",
|
"text_encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -267,6 +267,7 @@ DEFAULT_PARAMETERS = [
|
|||||||
AddFeature("libcpp-has-no-incomplete-pstl"),
|
AddFeature("libcpp-has-no-incomplete-pstl"),
|
||||||
AddFeature("libcpp-has-no-experimental-stop_token"),
|
AddFeature("libcpp-has-no-experimental-stop_token"),
|
||||||
AddFeature("libcpp-has-no-incomplete-tzdb"),
|
AddFeature("libcpp-has-no-incomplete-tzdb"),
|
||||||
|
AddFeature("libcpp-has-no-experimental-syncstream"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Parameter(
|
Parameter(
|
||||||
|
Loading…
Reference in New Issue
Block a user