17cc72a0aSMark de Wever// -*- C++ -*- 27cc72a0aSMark de Wever//===----------------------------------------------------------------------===// 37cc72a0aSMark de Wever// 47cc72a0aSMark de Wever// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 57cc72a0aSMark de Wever// See https://llvm.org/LICENSE.txt for license information. 67cc72a0aSMark de Wever// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 77cc72a0aSMark de Wever// 87cc72a0aSMark de Wever//===----------------------------------------------------------------------===// 97cc72a0aSMark de Wever 107cc72a0aSMark de Wever#ifndef _LIBCPP_SYNCSTREAM 117cc72a0aSMark de Wever#define _LIBCPP_SYNCSTREAM 127cc72a0aSMark de Wever 137cc72a0aSMark de Wever/* 147cc72a0aSMark de Wever syncstream synopsis 157cc72a0aSMark de Wever 167cc72a0aSMark de Wever#include <ostream> // see [ostream.syn] 177cc72a0aSMark de Wever 187cc72a0aSMark de Wevernamespace std { 197cc72a0aSMark de Wever template<class charT, class traits, class Allocator> 207cc72a0aSMark de Wever class basic_syncbuf; 217cc72a0aSMark de Wever 227cc72a0aSMark de Wever // [syncstream.syncbuf.special], specialized algorithms 237cc72a0aSMark de Wever template<class charT, class traits, class Allocator> 247cc72a0aSMark de Wever void swap(basic_syncbuf<charT, traits, Allocator>&, 257cc72a0aSMark de Wever basic_syncbuf<charT, traits, Allocator>&); 267cc72a0aSMark de Wever 277cc72a0aSMark de Wever using syncbuf = basic_syncbuf<char>; 287cc72a0aSMark de Wever using wsyncbuf = basic_syncbuf<wchar_t>; 297cc72a0aSMark de Wever 307cc72a0aSMark de Wever template<class charT, class traits, class Allocator> 317cc72a0aSMark de Wever class basic_osyncstream; 327cc72a0aSMark de Wever 337cc72a0aSMark de Wever using osyncstream = basic_osyncstream<char>; 347cc72a0aSMark de Wever using wosyncstream = basic_osyncstream<wchar_t>; 357cc72a0aSMark de Wever 367cc72a0aSMark de Wever template<class charT, class traits, class Allocator> 377cc72a0aSMark de Wever class basic_syncbuf : public basic_streambuf<charT, traits> { 387cc72a0aSMark de Wever public: 397cc72a0aSMark de Wever using char_type = charT; 407cc72a0aSMark de Wever using int_type = typename traits::int_type; 417cc72a0aSMark de Wever using pos_type = typename traits::pos_type; 427cc72a0aSMark de Wever using off_type = typename traits::off_type; 437cc72a0aSMark de Wever using traits_type = traits; 447cc72a0aSMark de Wever using allocator_type = Allocator; 457cc72a0aSMark de Wever 467cc72a0aSMark de Wever using streambuf_type = basic_streambuf<charT, traits>; 477cc72a0aSMark de Wever 487cc72a0aSMark de Wever // [syncstream.syncbuf.cons], construction and destruction 49f4ea19b4SMark de Wever basic_syncbuf() 50f4ea19b4SMark de Wever : basic_syncbuf(nullptr) {} 51f4ea19b4SMark de Wever explicit basic_syncbuf(streambuf_type* obuf) 527cc72a0aSMark de Wever : basic_syncbuf(obuf, Allocator()) {} 537cc72a0aSMark de Wever basic_syncbuf(streambuf_type*, const Allocator&); 547cc72a0aSMark de Wever basic_syncbuf(basic_syncbuf&&); 557cc72a0aSMark de Wever ~basic_syncbuf(); 567cc72a0aSMark de Wever 577cc72a0aSMark de Wever // [syncstream.syncbuf.assign], assignment and swap 587cc72a0aSMark de Wever basic_syncbuf& operator=(basic_syncbuf&&); 597cc72a0aSMark de Wever void swap(basic_syncbuf&); 607cc72a0aSMark de Wever 617cc72a0aSMark de Wever // [syncstream.syncbuf.members], member functions 627cc72a0aSMark de Wever bool emit(); 637cc72a0aSMark de Wever streambuf_type* get_wrapped() const noexcept; 647cc72a0aSMark de Wever allocator_type get_allocator() const noexcept; 657cc72a0aSMark de Wever void set_emit_on_sync(bool) noexcept; 667cc72a0aSMark de Wever 677cc72a0aSMark de Wever protected: 687cc72a0aSMark de Wever // [syncstream.syncbuf.virtuals], overridden virtual functions 697cc72a0aSMark de Wever int sync() override; 707cc72a0aSMark de Wever 717cc72a0aSMark de Wever private: 727cc72a0aSMark de Wever streambuf_type* wrapped; // exposition only 737cc72a0aSMark de Wever bool emit_on_sync{}; // exposition only 747cc72a0aSMark de Wever }; 757cc72a0aSMark de Wever 767cc72a0aSMark de Wever // [syncstream.syncbuf.special], specialized algorithms 777cc72a0aSMark de Wever template<class charT, class traits, class Allocator> 787cc72a0aSMark de Wever void swap(basic_syncbuf<charT, traits, Allocator>&, 797cc72a0aSMark de Wever basic_syncbuf<charT, traits, Allocator>&); 807cc72a0aSMark de Wever 817cc72a0aSMark de Wever template<class charT, class traits, class Allocator> 827cc72a0aSMark de Wever class basic_osyncstream : public basic_ostream<charT, traits> { 837cc72a0aSMark de Wever public: 847cc72a0aSMark de Wever using char_type = charT; 857cc72a0aSMark de Wever using int_type = typename traits::int_type; 867cc72a0aSMark de Wever using pos_type = typename traits::pos_type; 877cc72a0aSMark de Wever using off_type = typename traits::off_type; 887cc72a0aSMark de Wever using traits_type = traits; 897cc72a0aSMark de Wever 907cc72a0aSMark de Wever using allocator_type = Allocator; 917cc72a0aSMark de Wever using streambuf_type = basic_streambuf<charT, traits>; 927cc72a0aSMark de Wever using syncbuf_type = basic_syncbuf<charT, traits, Allocator>; 937cc72a0aSMark de Wever 947cc72a0aSMark de Wever // [syncstream.osyncstream.cons], construction and destruction 957cc72a0aSMark de Wever basic_osyncstream(streambuf_type*, const Allocator&); 967cc72a0aSMark de Wever explicit basic_osyncstream(streambuf_type* obuf) 977cc72a0aSMark de Wever : basic_osyncstream(obuf, Allocator()) {} 987cc72a0aSMark de Wever basic_osyncstream(basic_ostream<charT, traits>& os, const Allocator& allocator) 997cc72a0aSMark de Wever : basic_osyncstream(os.rdbuf(), allocator) {} 1007cc72a0aSMark de Wever explicit basic_osyncstream(basic_ostream<charT, traits>& os) 1017cc72a0aSMark de Wever : basic_osyncstream(os, Allocator()) {} 1027cc72a0aSMark de Wever basic_osyncstream(basic_osyncstream&&) noexcept; 1037cc72a0aSMark de Wever ~basic_osyncstream(); 1047cc72a0aSMark de Wever 1057cc72a0aSMark de Wever // [syncstream.osyncstream.assign], assignment 1067cc72a0aSMark de Wever basic_osyncstream& operator=(basic_osyncstream&&); 1077cc72a0aSMark de Wever 1087cc72a0aSMark de Wever // [syncstream.osyncstream.members], member functions 1097cc72a0aSMark de Wever void emit(); 1107cc72a0aSMark de Wever streambuf_type* get_wrapped() const noexcept; 1117cc72a0aSMark de Wever syncbuf_type* rdbuf() const noexcept { return const_cast<syncbuf_type*>(addressof(sb)); } 1127cc72a0aSMark de Wever 1137cc72a0aSMark de Wever private: 1147cc72a0aSMark de Wever syncbuf_type sb; // exposition only 1157cc72a0aSMark de Wever }; 1167cc72a0aSMark de Wever} 1177cc72a0aSMark de Wever 1187cc72a0aSMark de Wever*/ 1197cc72a0aSMark de Wever 120b9a2658aSNikolas Klauser#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) 121b9a2658aSNikolas Klauser# include <__cxx03/syncstream> 122b9a2658aSNikolas Klauser#else 1237cc72a0aSMark de Wever# include <__config> 12487d56c59SLouis Dionne 125c6f3b7bcSNikolas Klauser# if _LIBCPP_HAS_LOCALIZATION 12687d56c59SLouis Dionne 1274a8329cdSNikolas Klauser# include <__mutex/lock_guard.h> 1287cc72a0aSMark de Wever# include <__utility/move.h> 12917f00620SNikolas Klauser# include <ios> 1307cc72a0aSMark de Wever# include <iosfwd> // required for declaration of default arguments 13117f00620SNikolas Klauser# include <streambuf> 1327cc72a0aSMark de Wever# include <string> 1337cc72a0aSMark de Wever 134c6f3b7bcSNikolas Klauser# if _LIBCPP_HAS_THREADS 1357cc72a0aSMark de Wever# include <map> 1367cc72a0aSMark de Wever# include <shared_mutex> 1377cc72a0aSMark de Wever# endif 1387cc72a0aSMark de Wever 1397cc72a0aSMark de Wever// standard-mandated includes 1407cc72a0aSMark de Wever 1417cc72a0aSMark de Wever// [syncstream.syn] 1427cc72a0aSMark de Wever# include <ostream> 1437cc72a0aSMark de Wever 1447cc72a0aSMark de Wever# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 1457cc72a0aSMark de Wever# pragma GCC system_header 1467cc72a0aSMark de Wever# endif 1477cc72a0aSMark de Wever 1487cc72a0aSMark de Wever_LIBCPP_PUSH_MACROS 1497cc72a0aSMark de Wever# include <__undef_macros> 1507cc72a0aSMark de Wever 1517cc72a0aSMark de Wever_LIBCPP_BEGIN_NAMESPACE_STD 1527cc72a0aSMark de Wever 153*24e70e39SNikolas Klauser# if _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM 1547cc72a0aSMark de Wever 1557cc72a0aSMark de Wever// [syncstream.syncbuf.overview]/1 1567cc72a0aSMark de Wever// Class template basic_syncbuf stores character data written to it, 1577cc72a0aSMark de Wever// known as the associated output, into internal buffers allocated 1587cc72a0aSMark de Wever// using the object's allocator. The associated output is transferred 1597cc72a0aSMark de Wever// to the wrapped stream buffer object *wrapped when emit() is called 1607cc72a0aSMark de Wever// or when the basic_syncbuf object is destroyed. Such transfers are 1617cc72a0aSMark de Wever// atomic with respect to transfers by other basic_syncbuf objects 1627cc72a0aSMark de Wever// with the same wrapped stream buffer object. 1637cc72a0aSMark de Wever// 1647cc72a0aSMark de Wever// This helper singleton is used to implement the required 1657cc72a0aSMark de Wever// synchronisation guarantees. 166c6f3b7bcSNikolas Klauser# if _LIBCPP_HAS_THREADS 1677cc72a0aSMark de Weverclass __wrapped_streambuf_mutex { 1687cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI __wrapped_streambuf_mutex() = default; 1697cc72a0aSMark de Wever 1707cc72a0aSMark de Weverpublic: 1717cc72a0aSMark de Wever __wrapped_streambuf_mutex(const __wrapped_streambuf_mutex&) = delete; 1727cc72a0aSMark de Wever __wrapped_streambuf_mutex& operator=(const __wrapped_streambuf_mutex&) = delete; 1737cc72a0aSMark de Wever 1747cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI void __inc_reference([[maybe_unused]] void* __ptr) { 1757cc72a0aSMark de Wever _LIBCPP_ASSERT_INTERNAL(__ptr != nullptr, "non-wrapped streambufs are never written to"); 1767cc72a0aSMark de Wever unique_lock __lock{__mutex_}; 1777cc72a0aSMark de Wever ++__lut_[reinterpret_cast<uintptr_t>(__ptr)].__count; 1787cc72a0aSMark de Wever } 1797cc72a0aSMark de Wever 1807cc72a0aSMark de Wever // pre: __ptr is in __lut_ 1817cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI void __dec_reference([[maybe_unused]] void* __ptr) noexcept { 1827cc72a0aSMark de Wever unique_lock __lock{__mutex_}; 1837cc72a0aSMark de Wever 1847cc72a0aSMark de Wever auto __it = __get_it(__ptr); 1857cc72a0aSMark de Wever if (__it->second.__count == 1) 1867cc72a0aSMark de Wever __lut_.erase(__it); 1877cc72a0aSMark de Wever else 1887cc72a0aSMark de Wever --__it->second.__count; 1897cc72a0aSMark de Wever } 1907cc72a0aSMark de Wever 1917cc72a0aSMark de Wever // TODO 1927cc72a0aSMark de Wever // This function causes emit() aquire two mutexes: 1937cc72a0aSMark de Wever // - __mutex_ shared 1947cc72a0aSMark de Wever // _ __get_it(__ptr)->second.__mutex exclusive 1957cc72a0aSMark de Wever // 1967cc72a0aSMark de Wever // Instead store a pointer to __get_it(__ptr)->second.__mutex when 1977cc72a0aSMark de Wever // calling __inc_reference. 1987cc72a0aSMark de Wever // 1997cc72a0aSMark de Wever // pre: __ptr is in __lut_ 2007cc72a0aSMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI lock_guard<mutex> __get_lock([[maybe_unused]] void* __ptr) noexcept { 2017cc72a0aSMark de Wever shared_lock __lock{__mutex_}; 2027cc72a0aSMark de Wever return lock_guard{__get_it(__ptr)->second.__mutex}; 2037cc72a0aSMark de Wever } 2047cc72a0aSMark de Wever 2057cc72a0aSMark de Wever // This function is used for testing. 2067cc72a0aSMark de Wever // 2077cc72a0aSMark de Wever // It is allowed to call this function with a non-registered pointer. 2087cc72a0aSMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t __get_count([[maybe_unused]] void* __ptr) noexcept { 2097cc72a0aSMark de Wever _LIBCPP_ASSERT_INTERNAL(__ptr != nullptr, "non-wrapped streambufs are never written to"); 2107cc72a0aSMark de Wever shared_lock __lock{__mutex_}; 2117cc72a0aSMark de Wever 2127cc72a0aSMark de Wever auto __it = __lut_.find(reinterpret_cast<uintptr_t>(__ptr)); 2137cc72a0aSMark de Wever return __it != __lut_.end() ? __it->second.__count : 0; 2147cc72a0aSMark de Wever } 2157cc72a0aSMark de Wever 2167cc72a0aSMark de Wever [[nodiscard]] static _LIBCPP_HIDE_FROM_ABI __wrapped_streambuf_mutex& __instance() noexcept { 2177cc72a0aSMark de Wever static __wrapped_streambuf_mutex __result; 2187cc72a0aSMark de Wever return __result; 2197cc72a0aSMark de Wever } 2207cc72a0aSMark de Wever 2217cc72a0aSMark de Weverprivate: 2227cc72a0aSMark de Wever struct __value { 2237cc72a0aSMark de Wever mutex __mutex; 2247cc72a0aSMark de Wever size_t __count{0}; 2257cc72a0aSMark de Wever }; 2267cc72a0aSMark de Wever 2277cc72a0aSMark de Wever shared_mutex __mutex_; 2287cc72a0aSMark de Wever map<uintptr_t, __value> __lut_; 2297cc72a0aSMark de Wever 2307cc72a0aSMark de Wever [[nodiscard]] _LIBCPP_HIDE_FROM_ABI map<uintptr_t, __value>::iterator __get_it(void* __ptr) noexcept { 2317cc72a0aSMark de Wever _LIBCPP_ASSERT_INTERNAL(__ptr != nullptr, "non-wrapped streambufs are never written to"); 2327cc72a0aSMark de Wever 2337cc72a0aSMark de Wever auto __it = __lut_.find(reinterpret_cast<uintptr_t>(__ptr)); 2347cc72a0aSMark de Wever _LIBCPP_ASSERT_INTERNAL(__it != __lut_.end(), "using a wrapped streambuf that has not been registered"); 2357cc72a0aSMark de Wever _LIBCPP_ASSERT_INTERNAL(__it->second.__count >= 1, "found an inactive streambuf wrapper"); 2367cc72a0aSMark de Wever return __it; 2377cc72a0aSMark de Wever } 2387cc72a0aSMark de Wever}; 239c6f3b7bcSNikolas Klauser# endif // _LIBCPP_HAS_THREADS 2407cc72a0aSMark de Wever 2417cc72a0aSMark de Wever// basic_syncbuf 2427cc72a0aSMark de Wever 2437cc72a0aSMark de Wever// The class uses a basic_string<_CharT, _Traits, _Allocator> as 2447cc72a0aSMark de Wever// internal buffer. Per [syncstream.syncbuf.cons]/4 2457cc72a0aSMark de Wever// Remarks: A copy of allocator is used to allocate memory for 2467cc72a0aSMark de Wever// internal buffers holding the associated output. 2477cc72a0aSMark de Wever// 2487cc72a0aSMark de Wever// Therefore the allocator used in the constructor is passed to the 2497cc72a0aSMark de Wever// basic_string. The class does not keep a copy of this allocator. 2507cc72a0aSMark de Wevertemplate <class _CharT, class _Traits, class _Allocator> 2517cc72a0aSMark de Weverclass _LIBCPP_TEMPLATE_VIS basic_syncbuf : public basic_streambuf<_CharT, _Traits> { 2527cc72a0aSMark de Weverpublic: 2537cc72a0aSMark de Wever using char_type = _CharT; 2547cc72a0aSMark de Wever using traits_type = _Traits; 2557cc72a0aSMark de Wever using int_type = typename traits_type::int_type; 2567cc72a0aSMark de Wever using pos_type = typename traits_type::pos_type; 2577cc72a0aSMark de Wever using off_type = typename traits_type::off_type; 2587cc72a0aSMark de Wever using allocator_type = _Allocator; 2597cc72a0aSMark de Wever 2607cc72a0aSMark de Wever using streambuf_type = basic_streambuf<_CharT, _Traits>; 2617cc72a0aSMark de Wever 2627cc72a0aSMark de Wever // [syncstream.syncbuf.cons], construction and destruction 2637cc72a0aSMark de Wever 264348e7413SLouis Dionne _LIBCPP_HIDE_FROM_ABI basic_syncbuf() : basic_syncbuf(nullptr) {} 265f4ea19b4SMark de Wever 266348e7413SLouis Dionne _LIBCPP_HIDE_FROM_ABI explicit basic_syncbuf(streambuf_type* __obuf) : basic_syncbuf(__obuf, _Allocator()) {} 2677cc72a0aSMark de Wever 2687cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI basic_syncbuf(streambuf_type* __obuf, _Allocator const& __alloc) 2697cc72a0aSMark de Wever : __wrapped_(__obuf), __str_(__alloc) { 2707cc72a0aSMark de Wever __inc_reference(); 2717cc72a0aSMark de Wever } 2727cc72a0aSMark de Wever 2737cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI basic_syncbuf(basic_syncbuf&& __other) 2747cc72a0aSMark de Wever : __wrapped_(__other.get_wrapped()), __str_(std::move(__other.__str_)), __emit_on_sync_(__other.__emit_on_sync_) { 2757cc72a0aSMark de Wever __move_common(__other); 2767cc72a0aSMark de Wever } 2777cc72a0aSMark de Wever 2787cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI ~basic_syncbuf() { 279ba87515fSNikolas Klauser# if _LIBCPP_HAS_EXCEPTIONS 2807cc72a0aSMark de Wever try { 281ba87515fSNikolas Klauser# endif // _LIBCPP_HAS_EXCEPTIONS 2827cc72a0aSMark de Wever emit(); 283ba87515fSNikolas Klauser# if _LIBCPP_HAS_EXCEPTIONS 2847cc72a0aSMark de Wever } catch (...) { 2857cc72a0aSMark de Wever } 286ba87515fSNikolas Klauser# endif // _LIBCPP_HAS_EXCEPTIONS 2877cc72a0aSMark de Wever __dec_reference(); 2887cc72a0aSMark de Wever } 2897cc72a0aSMark de Wever 2907cc72a0aSMark de Wever // [syncstream.syncbuf.assign], assignment and swap 2917cc72a0aSMark de Wever 2927cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI basic_syncbuf& operator=(basic_syncbuf&& __other) { 2937cc72a0aSMark de Wever // The function is specified to call emit. This call should 2947cc72a0aSMark de Wever // propagate the exception thrown. 2957cc72a0aSMark de Wever emit(); 2967cc72a0aSMark de Wever __dec_reference(); 2977cc72a0aSMark de Wever 2987cc72a0aSMark de Wever __wrapped_ = __other.get_wrapped(); 2997cc72a0aSMark de Wever __str_ = std::move(__other.__str_); 3007cc72a0aSMark de Wever __emit_on_sync_ = __other.__emit_on_sync_; 3017cc72a0aSMark de Wever 3027cc72a0aSMark de Wever __move_common(__other); 3037cc72a0aSMark de Wever 3047cc72a0aSMark de Wever return *this; 3057cc72a0aSMark de Wever } 3067cc72a0aSMark de Wever 3077cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI void swap(basic_syncbuf& __other) { 3087cc72a0aSMark de Wever _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( 3097cc72a0aSMark de Wever allocator_traits<_Allocator>::propagate_on_container_swap::value || get_allocator() == __other.get_allocator(), 3107cc72a0aSMark de Wever "violates the mandated swap precondition"); 3117cc72a0aSMark de Wever 3127cc72a0aSMark de Wever basic_syncbuf __tmp(std::move(__other)); 3137cc72a0aSMark de Wever __other = std::move(*this); 3147cc72a0aSMark de Wever *this = std::move(__tmp); 3157cc72a0aSMark de Wever } 3167cc72a0aSMark de Wever 3177cc72a0aSMark de Wever // [syncstream.syncbuf.members], member functions 3187cc72a0aSMark de Wever 3197cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI bool emit() { return emit(false); } 3207cc72a0aSMark de Wever 3217cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI streambuf_type* get_wrapped() const noexcept { return __wrapped_; } 3227cc72a0aSMark de Wever 3237cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const noexcept { return __str_.get_allocator(); } 3247cc72a0aSMark de Wever 3257cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI void set_emit_on_sync(bool __b) noexcept { __emit_on_sync_ = __b; } 3267cc72a0aSMark de Wever 3277cc72a0aSMark de Weverprotected: 3287cc72a0aSMark de Wever // [syncstream.syncbuf.virtuals], overridden virtual functions 3297cc72a0aSMark de Wever 3307cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI_VIRTUAL 3317cc72a0aSMark de Wever int sync() override { 3327cc72a0aSMark de Wever if (__emit_on_sync_ && !emit(true)) 3337cc72a0aSMark de Wever return -1; 3347cc72a0aSMark de Wever return 0; 3357cc72a0aSMark de Wever } 3367cc72a0aSMark de Wever 3377cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI_VIRTUAL 3387cc72a0aSMark de Wever int_type overflow(int_type __c = traits_type::eof()) override { 3397cc72a0aSMark de Wever if (traits_type::eq_int_type(__c, traits_type::eof())) 3407cc72a0aSMark de Wever return traits_type::not_eof(__c); 3417cc72a0aSMark de Wever 3427cc72a0aSMark de Wever if (this->pptr() == this->epptr()) { 343ba87515fSNikolas Klauser# if _LIBCPP_HAS_EXCEPTIONS 3447cc72a0aSMark de Wever try { 3457cc72a0aSMark de Wever# endif 3467cc72a0aSMark de Wever size_t __size = __str_.size(); 3477cc72a0aSMark de Wever __str_.resize(__str_.capacity() + 1); 3487cc72a0aSMark de Wever _LIBCPP_ASSERT_INTERNAL(__str_.size() > __size, "the buffer hasn't grown"); 3497cc72a0aSMark de Wever 3507cc72a0aSMark de Wever char_type* __p = static_cast<char_type*>(__str_.data()); 3517cc72a0aSMark de Wever this->setp(__p, __p + __str_.size()); 3527cc72a0aSMark de Wever this->pbump(__size); 3537cc72a0aSMark de Wever 354ba87515fSNikolas Klauser# if _LIBCPP_HAS_EXCEPTIONS 3557cc72a0aSMark de Wever } catch (...) { 3567cc72a0aSMark de Wever return traits_type::eof(); 3577cc72a0aSMark de Wever } 3587cc72a0aSMark de Wever# endif 3597cc72a0aSMark de Wever } 3607cc72a0aSMark de Wever 3617cc72a0aSMark de Wever return this->sputc(traits_type::to_char_type(__c)); 3627cc72a0aSMark de Wever } 3637cc72a0aSMark de Wever 3647cc72a0aSMark de Weverprivate: 3657cc72a0aSMark de Wever streambuf_type* __wrapped_; 3667cc72a0aSMark de Wever 3677cc72a0aSMark de Wever // TODO Use a more generic buffer. 3687cc72a0aSMark de Wever // That buffer should be light with almost no additional headers. Then 3697cc72a0aSMark de Wever // it can be use here, the __retarget_buffer, and place that use 37094e7c0b0SA. Jiang // the now removed get_temporary_buffer 3717cc72a0aSMark de Wever 3727cc72a0aSMark de Wever basic_string<_CharT, _Traits, _Allocator> __str_; 3737cc72a0aSMark de Wever bool __emit_on_sync_{false}; 3747cc72a0aSMark de Wever 3757cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI bool emit(bool __flush) { 3767cc72a0aSMark de Wever if (!__wrapped_) 3777cc72a0aSMark de Wever return false; 3787cc72a0aSMark de Wever 379c6f3b7bcSNikolas Klauser# if _LIBCPP_HAS_THREADS 3807cc72a0aSMark de Wever lock_guard<mutex> __lock = __wrapped_streambuf_mutex::__instance().__get_lock(__wrapped_); 3817cc72a0aSMark de Wever# endif 3827cc72a0aSMark de Wever 3837cc72a0aSMark de Wever bool __result = true; 3847cc72a0aSMark de Wever if (this->pptr() != this->pbase()) { 3857cc72a0aSMark de Wever _LIBCPP_ASSERT_INTERNAL(this->pbase() && this->pptr() && this->epptr(), "all put area pointers shold be valid"); 3867cc72a0aSMark de Wever 3877cc72a0aSMark de Wever // The __str_ does not know how much of its buffer is used. This 3887cc72a0aSMark de Wever // information is extracted from the information of the base class. 3897cc72a0aSMark de Wever __result &= (__wrapped_->sputn(this->pbase(), this->pptr() - this->pbase()) != -1); 3907cc72a0aSMark de Wever // Clears the buffer, but keeps the contents (and) size of the 3917cc72a0aSMark de Wever // internal buffer. 3927cc72a0aSMark de Wever this->setp(this->pbase(), this->epptr()); 3937cc72a0aSMark de Wever } 3947cc72a0aSMark de Wever 3957cc72a0aSMark de Wever if (__flush) 3967cc72a0aSMark de Wever __result &= (__wrapped_->pubsync() != -1); 3977cc72a0aSMark de Wever 3987cc72a0aSMark de Wever return __result; 3997cc72a0aSMark de Wever } 4007cc72a0aSMark de Wever 4017cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI void __move_common(basic_syncbuf& __other) { 4027cc72a0aSMark de Wever // Adjust the put area pointers to our buffer. 4037cc72a0aSMark de Wever char_type* __p = static_cast<char_type*>(__str_.data()); 4047cc72a0aSMark de Wever this->setp(__p, __p + __str_.size()); 4057cc72a0aSMark de Wever this->pbump(__other.pptr() - __other.pbase()); 4067cc72a0aSMark de Wever 4077cc72a0aSMark de Wever // Clear __other_ so the destructor will act as a NOP. 4087cc72a0aSMark de Wever __other.setp(nullptr, nullptr); 4097cc72a0aSMark de Wever __other.__wrapped_ = nullptr; 4107cc72a0aSMark de Wever } 4117cc72a0aSMark de Wever 4127cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI void __inc_reference() { 413c6f3b7bcSNikolas Klauser# if _LIBCPP_HAS_THREADS 4147cc72a0aSMark de Wever if (__wrapped_) 4157cc72a0aSMark de Wever __wrapped_streambuf_mutex::__instance().__inc_reference(__wrapped_); 4167cc72a0aSMark de Wever# endif 4177cc72a0aSMark de Wever } 4187cc72a0aSMark de Wever 4197cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI void __dec_reference() noexcept { 420c6f3b7bcSNikolas Klauser# if _LIBCPP_HAS_THREADS 4217cc72a0aSMark de Wever if (__wrapped_) 4227cc72a0aSMark de Wever __wrapped_streambuf_mutex::__instance().__dec_reference(__wrapped_); 4237cc72a0aSMark de Wever# endif 4247cc72a0aSMark de Wever } 4257cc72a0aSMark de Wever}; 4267cc72a0aSMark de Wever 4277cc72a0aSMark de Weverusing std::syncbuf; 428c6f3b7bcSNikolas Klauser# if _LIBCPP_HAS_WIDE_CHARACTERS 4297cc72a0aSMark de Weverusing std::wsyncbuf; 4307cc72a0aSMark de Wever# endif 4317cc72a0aSMark de Wever 4327cc72a0aSMark de Wever// [syncstream.syncbuf.special], specialized algorithms 4337cc72a0aSMark de Wevertemplate <class _CharT, class _Traits, class _Allocator> 4347cc72a0aSMark de Wever_LIBCPP_HIDE_FROM_ABI void 4357cc72a0aSMark de Weverswap(basic_syncbuf<_CharT, _Traits, _Allocator>& __lhs, basic_syncbuf<_CharT, _Traits, _Allocator>& __rhs) { 4367cc72a0aSMark de Wever __lhs.swap(__rhs); 4377cc72a0aSMark de Wever} 4387cc72a0aSMark de Wever 4397cc72a0aSMark de Wever// basic_osyncstream 4407cc72a0aSMark de Wever 4417cc72a0aSMark de Wevertemplate <class _CharT, class _Traits, class _Allocator> 4427cc72a0aSMark de Weverclass _LIBCPP_TEMPLATE_VIS basic_osyncstream : public basic_ostream<_CharT, _Traits> { 4437cc72a0aSMark de Weverpublic: 4447cc72a0aSMark de Wever using char_type = _CharT; 4457cc72a0aSMark de Wever using traits_type = _Traits; 4467cc72a0aSMark de Wever using int_type = typename traits_type::int_type; 4477cc72a0aSMark de Wever using pos_type = typename traits_type::pos_type; 4487cc72a0aSMark de Wever using off_type = typename traits_type::off_type; 4497cc72a0aSMark de Wever 4507cc72a0aSMark de Wever using allocator_type = _Allocator; 4517cc72a0aSMark de Wever using streambuf_type = basic_streambuf<char_type, traits_type>; 4527cc72a0aSMark de Wever using syncbuf_type = basic_syncbuf<char_type, traits_type, allocator_type>; 4537cc72a0aSMark de Wever 4547cc72a0aSMark de Wever // [syncstream.osyncstream.cons], construction and destruction 4557cc72a0aSMark de Wever 4567cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI basic_osyncstream(streambuf_type* __obuf, allocator_type const& __alloc) 4577cc72a0aSMark de Wever : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__obuf, __alloc) {} 4587cc72a0aSMark de Wever 4597cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI explicit basic_osyncstream(streambuf_type* __obuf) 4607cc72a0aSMark de Wever : basic_osyncstream(__obuf, allocator_type()) {} 4617cc72a0aSMark de Wever 4627cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI basic_osyncstream(basic_ostream<char_type, traits_type>& __os, allocator_type const& __alloc) 4637cc72a0aSMark de Wever : basic_osyncstream(__os.rdbuf(), __alloc) {} 4647cc72a0aSMark de Wever 4657cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI explicit basic_osyncstream(basic_ostream<char_type, traits_type>& __os) 4667cc72a0aSMark de Wever : basic_osyncstream(__os, allocator_type()) {} 4677cc72a0aSMark de Wever 4687cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI basic_osyncstream(basic_osyncstream&& __other) noexcept 4697cc72a0aSMark de Wever : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(std::move(__other.__sb_)) { 4707cc72a0aSMark de Wever this->set_rdbuf(std::addressof(__sb_)); 4717cc72a0aSMark de Wever } 4727cc72a0aSMark de Wever 4737cc72a0aSMark de Wever // [syncstream.osyncstream.assign], assignment 4747cc72a0aSMark de Wever 4757cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI basic_osyncstream& operator=(basic_osyncstream&& __other) = default; 4767cc72a0aSMark de Wever 4777cc72a0aSMark de Wever // [syncstream.osyncstream.members], member functions 4787cc72a0aSMark de Wever 4797cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI void emit() { 4807cc72a0aSMark de Wever // The basic_ostream::put places the sentry in a try 4817cc72a0aSMark de Wever // catch, this does not match the wording of the standard 4827cc72a0aSMark de Wever // [ostream.unformatted] 4837cc72a0aSMark de Wever // TODO validate other unformatted output functions. 4847cc72a0aSMark de Wever typename basic_ostream<char_type, traits_type>::sentry __s(*this); 4857cc72a0aSMark de Wever if (__s) { 486ba87515fSNikolas Klauser# if _LIBCPP_HAS_EXCEPTIONS 4877cc72a0aSMark de Wever try { 4887cc72a0aSMark de Wever# endif 4897cc72a0aSMark de Wever 4907cc72a0aSMark de Wever if (__sb_.emit() == false) 4917cc72a0aSMark de Wever this->setstate(ios::badbit); 492ba87515fSNikolas Klauser# if _LIBCPP_HAS_EXCEPTIONS 4937cc72a0aSMark de Wever } catch (...) { 4947cc72a0aSMark de Wever this->__set_badbit_and_consider_rethrow(); 4957cc72a0aSMark de Wever } 4967cc72a0aSMark de Wever# endif 4977cc72a0aSMark de Wever } 4987cc72a0aSMark de Wever } 4997cc72a0aSMark de Wever 5007cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI streambuf_type* get_wrapped() const noexcept { return __sb_.get_wrapped(); } 5017cc72a0aSMark de Wever 5027cc72a0aSMark de Wever _LIBCPP_HIDE_FROM_ABI syncbuf_type* rdbuf() const noexcept { 5037cc72a0aSMark de Wever return const_cast<syncbuf_type*>(std::addressof(__sb_)); 5047cc72a0aSMark de Wever } 5057cc72a0aSMark de Wever 5067cc72a0aSMark de Weverprivate: 5077cc72a0aSMark de Wever syncbuf_type __sb_; 5087cc72a0aSMark de Wever}; 5097cc72a0aSMark de Wever 5107cc72a0aSMark de Weverusing std::osyncstream; 511c6f3b7bcSNikolas Klauser# if _LIBCPP_HAS_WIDE_CHARACTERS 5127cc72a0aSMark de Weverusing std::wosyncstream; 5137cc72a0aSMark de Wever# endif 5147cc72a0aSMark de Wever 515*24e70e39SNikolas Klauser# endif // _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM 5167cc72a0aSMark de Wever 5177cc72a0aSMark de Wever_LIBCPP_END_NAMESPACE_STD 5187cc72a0aSMark de Wever 5197cc72a0aSMark de Wever_LIBCPP_POP_MACROS 5207cc72a0aSMark de Wever 521c6f3b7bcSNikolas Klauser# endif // _LIBCPP_HAS_LOCALIZATION 522b9a2658aSNikolas Klauser#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) 52387d56c59SLouis Dionne 5247cc72a0aSMark de Wever#endif // _LIBCPP_SYNCSTREAM 525