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