xref: /freebsd/contrib/llvm-project/libcxx/include/__locale_dir/wbuffer_convert.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric 
9*700637cbSDimitry Andric #ifndef _LIBCPP___LOCALE_DIR_WBUFFER_CONVERT_H
10*700637cbSDimitry Andric #define _LIBCPP___LOCALE_DIR_WBUFFER_CONVERT_H
11*700637cbSDimitry Andric 
12*700637cbSDimitry Andric #include <__algorithm/reverse.h>
13*700637cbSDimitry Andric #include <__config>
14*700637cbSDimitry Andric #include <__string/char_traits.h>
15*700637cbSDimitry Andric #include <ios>
16*700637cbSDimitry Andric #include <streambuf>
17*700637cbSDimitry Andric 
18*700637cbSDimitry Andric #if _LIBCPP_HAS_LOCALIZATION
19*700637cbSDimitry Andric 
20*700637cbSDimitry Andric #  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
21*700637cbSDimitry Andric #    pragma GCC system_header
22*700637cbSDimitry Andric #  endif
23*700637cbSDimitry Andric 
24*700637cbSDimitry Andric #  if _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT)
25*700637cbSDimitry Andric 
26*700637cbSDimitry Andric _LIBCPP_PUSH_MACROS
27*700637cbSDimitry Andric #    include <__undef_macros>
28*700637cbSDimitry Andric 
29*700637cbSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
30*700637cbSDimitry Andric 
31*700637cbSDimitry Andric template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
32*700637cbSDimitry Andric class _LIBCPP_DEPRECATED_IN_CXX17 wbuffer_convert : public basic_streambuf<_Elem, _Tr> {
33*700637cbSDimitry Andric public:
34*700637cbSDimitry Andric   // types:
35*700637cbSDimitry Andric   typedef _Elem char_type;
36*700637cbSDimitry Andric   typedef _Tr traits_type;
37*700637cbSDimitry Andric   typedef typename traits_type::int_type int_type;
38*700637cbSDimitry Andric   typedef typename traits_type::pos_type pos_type;
39*700637cbSDimitry Andric   typedef typename traits_type::off_type off_type;
40*700637cbSDimitry Andric   typedef typename _Codecvt::state_type state_type;
41*700637cbSDimitry Andric 
42*700637cbSDimitry Andric private:
43*700637cbSDimitry Andric   char* __extbuf_;
44*700637cbSDimitry Andric   const char* __extbufnext_;
45*700637cbSDimitry Andric   const char* __extbufend_;
46*700637cbSDimitry Andric   char __extbuf_min_[8];
47*700637cbSDimitry Andric   size_t __ebs_;
48*700637cbSDimitry Andric   char_type* __intbuf_;
49*700637cbSDimitry Andric   size_t __ibs_;
50*700637cbSDimitry Andric   streambuf* __bufptr_;
51*700637cbSDimitry Andric   _Codecvt* __cv_;
52*700637cbSDimitry Andric   state_type __st_;
53*700637cbSDimitry Andric   ios_base::openmode __cm_;
54*700637cbSDimitry Andric   bool __owns_eb_;
55*700637cbSDimitry Andric   bool __owns_ib_;
56*700637cbSDimitry Andric   bool __always_noconv_;
57*700637cbSDimitry Andric 
58*700637cbSDimitry Andric public:
59*700637cbSDimitry Andric #    ifndef _LIBCPP_CXX03_LANG
wbuffer_convert()60*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI wbuffer_convert() : wbuffer_convert(nullptr) {}
61*700637cbSDimitry Andric   explicit _LIBCPP_HIDE_FROM_ABI
62*700637cbSDimitry Andric   wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type());
63*700637cbSDimitry Andric #    else
64*700637cbSDimitry Andric   _LIBCPP_EXPLICIT_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI
65*700637cbSDimitry Andric   wbuffer_convert(streambuf* __bytebuf = nullptr, _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type());
66*700637cbSDimitry Andric #    endif
67*700637cbSDimitry Andric 
68*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI ~wbuffer_convert();
69*700637cbSDimitry Andric 
rdbuf()70*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI streambuf* rdbuf() const { return __bufptr_; }
rdbuf(streambuf * __bytebuf)71*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI streambuf* rdbuf(streambuf* __bytebuf) {
72*700637cbSDimitry Andric     streambuf* __r = __bufptr_;
73*700637cbSDimitry Andric     __bufptr_      = __bytebuf;
74*700637cbSDimitry Andric     return __r;
75*700637cbSDimitry Andric   }
76*700637cbSDimitry Andric 
77*700637cbSDimitry Andric   wbuffer_convert(const wbuffer_convert&)            = delete;
78*700637cbSDimitry Andric   wbuffer_convert& operator=(const wbuffer_convert&) = delete;
79*700637cbSDimitry Andric 
state()80*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI state_type state() const { return __st_; }
81*700637cbSDimitry Andric 
82*700637cbSDimitry Andric protected:
83*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type underflow();
84*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type pbackfail(int_type __c = traits_type::eof());
85*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type overflow(int_type __c = traits_type::eof());
86*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s, streamsize __n);
87*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual pos_type
88*700637cbSDimitry Andric   seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __wch = ios_base::in | ios_base::out);
89*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual pos_type
90*700637cbSDimitry Andric   seekpos(pos_type __sp, ios_base::openmode __wch = ios_base::in | ios_base::out);
91*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int sync();
92*700637cbSDimitry Andric 
93*700637cbSDimitry Andric private:
94*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI_VIRTUAL bool __read_mode();
95*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __write_mode();
96*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI_VIRTUAL wbuffer_convert* __close();
97*700637cbSDimitry Andric };
98*700637cbSDimitry Andric 
99*700637cbSDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
100*700637cbSDimitry Andric template <class _Codecvt, class _Elem, class _Tr>
wbuffer_convert(streambuf * __bytebuf,_Codecvt * __pcvt,state_type __state)101*700637cbSDimitry Andric wbuffer_convert<_Codecvt, _Elem, _Tr>::wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
102*700637cbSDimitry Andric     : __extbuf_(nullptr),
103*700637cbSDimitry Andric       __extbufnext_(nullptr),
104*700637cbSDimitry Andric       __extbufend_(nullptr),
105*700637cbSDimitry Andric       __ebs_(0),
106*700637cbSDimitry Andric       __intbuf_(0),
107*700637cbSDimitry Andric       __ibs_(0),
108*700637cbSDimitry Andric       __bufptr_(__bytebuf),
109*700637cbSDimitry Andric       __cv_(__pcvt),
110*700637cbSDimitry Andric       __st_(__state),
111*700637cbSDimitry Andric       __cm_(0),
112*700637cbSDimitry Andric       __owns_eb_(false),
113*700637cbSDimitry Andric       __owns_ib_(false),
114*700637cbSDimitry Andric       __always_noconv_(__cv_ ? __cv_->always_noconv() : false) {
115*700637cbSDimitry Andric   setbuf(0, 4096);
116*700637cbSDimitry Andric }
117*700637cbSDimitry Andric 
118*700637cbSDimitry Andric template <class _Codecvt, class _Elem, class _Tr>
~wbuffer_convert()119*700637cbSDimitry Andric wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert() {
120*700637cbSDimitry Andric   __close();
121*700637cbSDimitry Andric   delete __cv_;
122*700637cbSDimitry Andric   if (__owns_eb_)
123*700637cbSDimitry Andric     delete[] __extbuf_;
124*700637cbSDimitry Andric   if (__owns_ib_)
125*700637cbSDimitry Andric     delete[] __intbuf_;
126*700637cbSDimitry Andric }
127*700637cbSDimitry Andric 
128*700637cbSDimitry Andric template <class _Codecvt, class _Elem, class _Tr>
underflow()129*700637cbSDimitry Andric typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow() {
130*700637cbSDimitry Andric   _LIBCPP_SUPPRESS_DEPRECATED_POP
131*700637cbSDimitry Andric   if (__cv_ == 0 || __bufptr_ == nullptr)
132*700637cbSDimitry Andric     return traits_type::eof();
133*700637cbSDimitry Andric   bool __initial = __read_mode();
134*700637cbSDimitry Andric   char_type __1buf;
135*700637cbSDimitry Andric   if (this->gptr() == 0)
136*700637cbSDimitry Andric     this->setg(std::addressof(__1buf), std::addressof(__1buf) + 1, std::addressof(__1buf) + 1);
137*700637cbSDimitry Andric   const size_t __unget_sz = __initial ? 0 : std::min<size_t>((this->egptr() - this->eback()) / 2, 4);
138*700637cbSDimitry Andric   int_type __c            = traits_type::eof();
139*700637cbSDimitry Andric   if (this->gptr() == this->egptr()) {
140*700637cbSDimitry Andric     std::memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
141*700637cbSDimitry Andric     if (__always_noconv_) {
142*700637cbSDimitry Andric       streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
143*700637cbSDimitry Andric       __nmemb            = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
144*700637cbSDimitry Andric       if (__nmemb != 0) {
145*700637cbSDimitry Andric         this->setg(this->eback(), this->eback() + __unget_sz, this->eback() + __unget_sz + __nmemb);
146*700637cbSDimitry Andric         __c = *this->gptr();
147*700637cbSDimitry Andric       }
148*700637cbSDimitry Andric     } else {
149*700637cbSDimitry Andric       if (__extbufend_ != __extbufnext_) {
150*700637cbSDimitry Andric         _LIBCPP_ASSERT_NON_NULL(__extbufnext_ != nullptr, "underflow moving from nullptr");
151*700637cbSDimitry Andric         _LIBCPP_ASSERT_NON_NULL(__extbuf_ != nullptr, "underflow moving into nullptr");
152*700637cbSDimitry Andric         std::memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
153*700637cbSDimitry Andric       }
154*700637cbSDimitry Andric       __extbufnext_      = __extbuf_ + (__extbufend_ - __extbufnext_);
155*700637cbSDimitry Andric       __extbufend_       = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
156*700637cbSDimitry Andric       streamsize __nmemb = std::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
157*700637cbSDimitry Andric                                     static_cast<streamsize>(__extbufend_ - __extbufnext_));
158*700637cbSDimitry Andric       codecvt_base::result __r;
159*700637cbSDimitry Andric       // FIXME: Do we ever need to restore the state here?
160*700637cbSDimitry Andric       // state_type __svs = __st_;
161*700637cbSDimitry Andric       streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
162*700637cbSDimitry Andric       if (__nr != 0) {
163*700637cbSDimitry Andric         __extbufend_ = __extbufnext_ + __nr;
164*700637cbSDimitry Andric         char_type* __inext;
165*700637cbSDimitry Andric         __r = __cv_->in(
166*700637cbSDimitry Andric             __st_, __extbuf_, __extbufend_, __extbufnext_, this->eback() + __unget_sz, this->egptr(), __inext);
167*700637cbSDimitry Andric         if (__r == codecvt_base::noconv) {
168*700637cbSDimitry Andric           this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)const_cast<char*>(__extbufend_));
169*700637cbSDimitry Andric           __c = *this->gptr();
170*700637cbSDimitry Andric         } else if (__inext != this->eback() + __unget_sz) {
171*700637cbSDimitry Andric           this->setg(this->eback(), this->eback() + __unget_sz, __inext);
172*700637cbSDimitry Andric           __c = *this->gptr();
173*700637cbSDimitry Andric         }
174*700637cbSDimitry Andric       }
175*700637cbSDimitry Andric     }
176*700637cbSDimitry Andric   } else
177*700637cbSDimitry Andric     __c = *this->gptr();
178*700637cbSDimitry Andric   if (this->eback() == std::addressof(__1buf))
179*700637cbSDimitry Andric     this->setg(0, 0, 0);
180*700637cbSDimitry Andric   return __c;
181*700637cbSDimitry Andric }
182*700637cbSDimitry Andric 
183*700637cbSDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
184*700637cbSDimitry Andric template <class _Codecvt, class _Elem, class _Tr>
185*700637cbSDimitry Andric typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
pbackfail(int_type __c)186*700637cbSDimitry Andric wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c) {
187*700637cbSDimitry Andric   _LIBCPP_SUPPRESS_DEPRECATED_POP
188*700637cbSDimitry Andric   if (__cv_ != 0 && __bufptr_ && this->eback() < this->gptr()) {
189*700637cbSDimitry Andric     if (traits_type::eq_int_type(__c, traits_type::eof())) {
190*700637cbSDimitry Andric       this->gbump(-1);
191*700637cbSDimitry Andric       return traits_type::not_eof(__c);
192*700637cbSDimitry Andric     }
193*700637cbSDimitry Andric     if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1])) {
194*700637cbSDimitry Andric       this->gbump(-1);
195*700637cbSDimitry Andric       *this->gptr() = traits_type::to_char_type(__c);
196*700637cbSDimitry Andric       return __c;
197*700637cbSDimitry Andric     }
198*700637cbSDimitry Andric   }
199*700637cbSDimitry Andric   return traits_type::eof();
200*700637cbSDimitry Andric }
201*700637cbSDimitry Andric 
202*700637cbSDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
203*700637cbSDimitry Andric template <class _Codecvt, class _Elem, class _Tr>
overflow(int_type __c)204*700637cbSDimitry Andric typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c) {
205*700637cbSDimitry Andric   _LIBCPP_SUPPRESS_DEPRECATED_POP
206*700637cbSDimitry Andric   if (__cv_ == 0 || !__bufptr_)
207*700637cbSDimitry Andric     return traits_type::eof();
208*700637cbSDimitry Andric   __write_mode();
209*700637cbSDimitry Andric   char_type __1buf;
210*700637cbSDimitry Andric   char_type* __pb_save  = this->pbase();
211*700637cbSDimitry Andric   char_type* __epb_save = this->epptr();
212*700637cbSDimitry Andric   if (!traits_type::eq_int_type(__c, traits_type::eof())) {
213*700637cbSDimitry Andric     if (this->pptr() == 0)
214*700637cbSDimitry Andric       this->setp(std::addressof(__1buf), std::addressof(__1buf) + 1);
215*700637cbSDimitry Andric     *this->pptr() = traits_type::to_char_type(__c);
216*700637cbSDimitry Andric     this->pbump(1);
217*700637cbSDimitry Andric   }
218*700637cbSDimitry Andric   if (this->pptr() != this->pbase()) {
219*700637cbSDimitry Andric     if (__always_noconv_) {
220*700637cbSDimitry Andric       streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
221*700637cbSDimitry Andric       if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
222*700637cbSDimitry Andric         return traits_type::eof();
223*700637cbSDimitry Andric     } else {
224*700637cbSDimitry Andric       char* __extbe = __extbuf_;
225*700637cbSDimitry Andric       codecvt_base::result __r;
226*700637cbSDimitry Andric       do {
227*700637cbSDimitry Andric         const char_type* __e;
228*700637cbSDimitry Andric         __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e, __extbuf_, __extbuf_ + __ebs_, __extbe);
229*700637cbSDimitry Andric         if (__e == this->pbase())
230*700637cbSDimitry Andric           return traits_type::eof();
231*700637cbSDimitry Andric         if (__r == codecvt_base::noconv) {
232*700637cbSDimitry Andric           streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
233*700637cbSDimitry Andric           if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
234*700637cbSDimitry Andric             return traits_type::eof();
235*700637cbSDimitry Andric         } else if (__r == codecvt_base::ok || __r == codecvt_base::partial) {
236*700637cbSDimitry Andric           streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
237*700637cbSDimitry Andric           if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
238*700637cbSDimitry Andric             return traits_type::eof();
239*700637cbSDimitry Andric           if (__r == codecvt_base::partial) {
240*700637cbSDimitry Andric             this->setp(const_cast<char_type*>(__e), this->pptr());
241*700637cbSDimitry Andric             this->__pbump(this->epptr() - this->pbase());
242*700637cbSDimitry Andric           }
243*700637cbSDimitry Andric         } else
244*700637cbSDimitry Andric           return traits_type::eof();
245*700637cbSDimitry Andric       } while (__r == codecvt_base::partial);
246*700637cbSDimitry Andric     }
247*700637cbSDimitry Andric     this->setp(__pb_save, __epb_save);
248*700637cbSDimitry Andric   }
249*700637cbSDimitry Andric   return traits_type::not_eof(__c);
250*700637cbSDimitry Andric }
251*700637cbSDimitry Andric 
252*700637cbSDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
253*700637cbSDimitry Andric template <class _Codecvt, class _Elem, class _Tr>
setbuf(char_type * __s,streamsize __n)254*700637cbSDimitry Andric basic_streambuf<_Elem, _Tr>* wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n) {
255*700637cbSDimitry Andric   _LIBCPP_SUPPRESS_DEPRECATED_POP
256*700637cbSDimitry Andric   this->setg(0, 0, 0);
257*700637cbSDimitry Andric   this->setp(0, 0);
258*700637cbSDimitry Andric   if (__owns_eb_)
259*700637cbSDimitry Andric     delete[] __extbuf_;
260*700637cbSDimitry Andric   if (__owns_ib_)
261*700637cbSDimitry Andric     delete[] __intbuf_;
262*700637cbSDimitry Andric   __ebs_ = __n;
263*700637cbSDimitry Andric   if (__ebs_ > sizeof(__extbuf_min_)) {
264*700637cbSDimitry Andric     if (__always_noconv_ && __s) {
265*700637cbSDimitry Andric       __extbuf_  = (char*)__s;
266*700637cbSDimitry Andric       __owns_eb_ = false;
267*700637cbSDimitry Andric     } else {
268*700637cbSDimitry Andric       __extbuf_  = new char[__ebs_];
269*700637cbSDimitry Andric       __owns_eb_ = true;
270*700637cbSDimitry Andric     }
271*700637cbSDimitry Andric   } else {
272*700637cbSDimitry Andric     __extbuf_  = __extbuf_min_;
273*700637cbSDimitry Andric     __ebs_     = sizeof(__extbuf_min_);
274*700637cbSDimitry Andric     __owns_eb_ = false;
275*700637cbSDimitry Andric   }
276*700637cbSDimitry Andric   if (!__always_noconv_) {
277*700637cbSDimitry Andric     __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
278*700637cbSDimitry Andric     if (__s && __ibs_ >= sizeof(__extbuf_min_)) {
279*700637cbSDimitry Andric       __intbuf_  = __s;
280*700637cbSDimitry Andric       __owns_ib_ = false;
281*700637cbSDimitry Andric     } else {
282*700637cbSDimitry Andric       __intbuf_  = new char_type[__ibs_];
283*700637cbSDimitry Andric       __owns_ib_ = true;
284*700637cbSDimitry Andric     }
285*700637cbSDimitry Andric   } else {
286*700637cbSDimitry Andric     __ibs_     = 0;
287*700637cbSDimitry Andric     __intbuf_  = 0;
288*700637cbSDimitry Andric     __owns_ib_ = false;
289*700637cbSDimitry Andric   }
290*700637cbSDimitry Andric   return this;
291*700637cbSDimitry Andric }
292*700637cbSDimitry Andric 
293*700637cbSDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
294*700637cbSDimitry Andric template <class _Codecvt, class _Elem, class _Tr>
295*700637cbSDimitry Andric typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
seekoff(off_type __off,ios_base::seekdir __way,ios_base::openmode __om)296*700637cbSDimitry Andric wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __om) {
297*700637cbSDimitry Andric   int __width = __cv_->encoding();
298*700637cbSDimitry Andric   if (__cv_ == 0 || !__bufptr_ || (__width <= 0 && __off != 0) || sync())
299*700637cbSDimitry Andric     return pos_type(off_type(-1));
300*700637cbSDimitry Andric   // __width > 0 || __off == 0, now check __way
301*700637cbSDimitry Andric   if (__way != ios_base::beg && __way != ios_base::cur && __way != ios_base::end)
302*700637cbSDimitry Andric     return pos_type(off_type(-1));
303*700637cbSDimitry Andric   pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
304*700637cbSDimitry Andric   __r.state(__st_);
305*700637cbSDimitry Andric   return __r;
306*700637cbSDimitry Andric }
307*700637cbSDimitry Andric 
308*700637cbSDimitry Andric template <class _Codecvt, class _Elem, class _Tr>
309*700637cbSDimitry Andric typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
seekpos(pos_type __sp,ios_base::openmode __wch)310*700637cbSDimitry Andric wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch) {
311*700637cbSDimitry Andric   if (__cv_ == 0 || !__bufptr_ || sync())
312*700637cbSDimitry Andric     return pos_type(off_type(-1));
313*700637cbSDimitry Andric   if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
314*700637cbSDimitry Andric     return pos_type(off_type(-1));
315*700637cbSDimitry Andric   return __sp;
316*700637cbSDimitry Andric }
317*700637cbSDimitry Andric 
318*700637cbSDimitry Andric template <class _Codecvt, class _Elem, class _Tr>
sync()319*700637cbSDimitry Andric int wbuffer_convert<_Codecvt, _Elem, _Tr>::sync() {
320*700637cbSDimitry Andric   _LIBCPP_SUPPRESS_DEPRECATED_POP
321*700637cbSDimitry Andric   if (__cv_ == 0 || !__bufptr_)
322*700637cbSDimitry Andric     return 0;
323*700637cbSDimitry Andric   if (__cm_ & ios_base::out) {
324*700637cbSDimitry Andric     if (this->pptr() != this->pbase())
325*700637cbSDimitry Andric       if (overflow() == traits_type::eof())
326*700637cbSDimitry Andric         return -1;
327*700637cbSDimitry Andric     codecvt_base::result __r;
328*700637cbSDimitry Andric     do {
329*700637cbSDimitry Andric       char* __extbe;
330*700637cbSDimitry Andric       __r                = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
331*700637cbSDimitry Andric       streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
332*700637cbSDimitry Andric       if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
333*700637cbSDimitry Andric         return -1;
334*700637cbSDimitry Andric     } while (__r == codecvt_base::partial);
335*700637cbSDimitry Andric     if (__r == codecvt_base::error)
336*700637cbSDimitry Andric       return -1;
337*700637cbSDimitry Andric     if (__bufptr_->pubsync())
338*700637cbSDimitry Andric       return -1;
339*700637cbSDimitry Andric   } else if (__cm_ & ios_base::in) {
340*700637cbSDimitry Andric     off_type __c;
341*700637cbSDimitry Andric     if (__always_noconv_)
342*700637cbSDimitry Andric       __c = this->egptr() - this->gptr();
343*700637cbSDimitry Andric     else {
344*700637cbSDimitry Andric       int __width = __cv_->encoding();
345*700637cbSDimitry Andric       __c         = __extbufend_ - __extbufnext_;
346*700637cbSDimitry Andric       if (__width > 0)
347*700637cbSDimitry Andric         __c += __width * (this->egptr() - this->gptr());
348*700637cbSDimitry Andric       else {
349*700637cbSDimitry Andric         if (this->gptr() != this->egptr()) {
350*700637cbSDimitry Andric           std::reverse(this->gptr(), this->egptr());
351*700637cbSDimitry Andric           codecvt_base::result __r;
352*700637cbSDimitry Andric           const char_type* __e = this->gptr();
353*700637cbSDimitry Andric           char* __extbe;
354*700637cbSDimitry Andric           do {
355*700637cbSDimitry Andric             __r = __cv_->out(__st_, __e, this->egptr(), __e, __extbuf_, __extbuf_ + __ebs_, __extbe);
356*700637cbSDimitry Andric             switch (__r) {
357*700637cbSDimitry Andric             case codecvt_base::noconv:
358*700637cbSDimitry Andric               __c += this->egptr() - this->gptr();
359*700637cbSDimitry Andric               break;
360*700637cbSDimitry Andric             case codecvt_base::ok:
361*700637cbSDimitry Andric             case codecvt_base::partial:
362*700637cbSDimitry Andric               __c += __extbe - __extbuf_;
363*700637cbSDimitry Andric               break;
364*700637cbSDimitry Andric             default:
365*700637cbSDimitry Andric               return -1;
366*700637cbSDimitry Andric             }
367*700637cbSDimitry Andric           } while (__r == codecvt_base::partial);
368*700637cbSDimitry Andric         }
369*700637cbSDimitry Andric       }
370*700637cbSDimitry Andric     }
371*700637cbSDimitry Andric     if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
372*700637cbSDimitry Andric       return -1;
373*700637cbSDimitry Andric     this->setg(0, 0, 0);
374*700637cbSDimitry Andric     __cm_ = 0;
375*700637cbSDimitry Andric   }
376*700637cbSDimitry Andric   return 0;
377*700637cbSDimitry Andric }
378*700637cbSDimitry Andric 
379*700637cbSDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH
380*700637cbSDimitry Andric template <class _Codecvt, class _Elem, class _Tr>
__read_mode()381*700637cbSDimitry Andric bool wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode() {
382*700637cbSDimitry Andric   if (!(__cm_ & ios_base::in)) {
383*700637cbSDimitry Andric     this->setp(0, 0);
384*700637cbSDimitry Andric     if (__always_noconv_)
385*700637cbSDimitry Andric       this->setg((char_type*)__extbuf_, (char_type*)__extbuf_ + __ebs_, (char_type*)__extbuf_ + __ebs_);
386*700637cbSDimitry Andric     else
387*700637cbSDimitry Andric       this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
388*700637cbSDimitry Andric     __cm_ = ios_base::in;
389*700637cbSDimitry Andric     return true;
390*700637cbSDimitry Andric   }
391*700637cbSDimitry Andric   return false;
392*700637cbSDimitry Andric }
393*700637cbSDimitry Andric 
394*700637cbSDimitry Andric template <class _Codecvt, class _Elem, class _Tr>
__write_mode()395*700637cbSDimitry Andric void wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode() {
396*700637cbSDimitry Andric   if (!(__cm_ & ios_base::out)) {
397*700637cbSDimitry Andric     this->setg(0, 0, 0);
398*700637cbSDimitry Andric     if (__ebs_ > sizeof(__extbuf_min_)) {
399*700637cbSDimitry Andric       if (__always_noconv_)
400*700637cbSDimitry Andric         this->setp((char_type*)__extbuf_, (char_type*)__extbuf_ + (__ebs_ - 1));
401*700637cbSDimitry Andric       else
402*700637cbSDimitry Andric         this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
403*700637cbSDimitry Andric     } else
404*700637cbSDimitry Andric       this->setp(0, 0);
405*700637cbSDimitry Andric     __cm_ = ios_base::out;
406*700637cbSDimitry Andric   }
407*700637cbSDimitry Andric }
408*700637cbSDimitry Andric 
409*700637cbSDimitry Andric template <class _Codecvt, class _Elem, class _Tr>
__close()410*700637cbSDimitry Andric wbuffer_convert<_Codecvt, _Elem, _Tr>* wbuffer_convert<_Codecvt, _Elem, _Tr>::__close() {
411*700637cbSDimitry Andric   wbuffer_convert* __rt = nullptr;
412*700637cbSDimitry Andric   if (__cv_ != nullptr && __bufptr_ != nullptr) {
413*700637cbSDimitry Andric     __rt = this;
414*700637cbSDimitry Andric     if ((__cm_ & ios_base::out) && sync())
415*700637cbSDimitry Andric       __rt = nullptr;
416*700637cbSDimitry Andric   }
417*700637cbSDimitry Andric   return __rt;
418*700637cbSDimitry Andric }
419*700637cbSDimitry Andric 
420*700637cbSDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP
421*700637cbSDimitry Andric 
422*700637cbSDimitry Andric _LIBCPP_END_NAMESPACE_STD
423*700637cbSDimitry Andric 
424*700637cbSDimitry Andric _LIBCPP_POP_MACROS
425*700637cbSDimitry Andric 
426*700637cbSDimitry Andric #  endif // _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT)
427*700637cbSDimitry Andric 
428*700637cbSDimitry Andric #endif // _LIBCPP_HAS_LOCALIZATION
429*700637cbSDimitry Andric 
430*700637cbSDimitry Andric #endif // _LIBCPP___LOCALE_DIR_WBUFFER_CONVERT_H
431