source: mainline/uspace/lib/cpp/include/impl/streambuf.hpp@ 47203ee3

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 47203ee3 was 47203ee3, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: fixed return value of streambuf::imbue

  • Property mode set to 100644
File size: 11.7 KB
Line 
1/*
2 * Copyright (c) 2017 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_STREAMBUF
30#define LIBCPP_STREAMBUF
31
32#include <ios>
33#include <iosfwd>
34#include <locale>
35
36namespace std
37{
38
39 /**
40 * 27.6.3, class template basic_streambuf:
41 */
42
43 template<class Char, class Traits>
44 class basic_streambuf
45 {
46 public:
47 using traits_type = Traits;
48 using char_type = Char;
49 using int_type = typename traits_type::int_type;
50 using pos_type = typename traits_type::pos_type;
51 using off_type = typename traits_type::off_type;
52
53 virtual ~basic_streambuf()
54 { /* DUMMY BODY */ }
55
56 /**
57 * 27.6.3.2.1, locales:
58 */
59
60 locale pubimbue(const locale& loc)
61 {
62 imbue(loc);
63
64 return locale_;
65 }
66
67 locale& getloc() const
68 {
69 return locale_;
70 }
71
72 /**
73 * 27.6.3.2.2, buffer and positioning:
74 */
75
76 basic_streambuf<Char, Traits>* pubsetbuf(char_type* s, streamsize n)
77 {
78 return setbuf(s, n);
79 }
80
81 pos_type pubseekoff(off_type off, ios_base::seekdir way,
82 ios_base::openmode which = ios_base::in | ios_base::out)
83 {
84 return seekoff(off, way, which);
85 }
86
87 pos_type pubseekpos(pos_type pos, ios_base::openmode which =
88 ios_base::in | ios_base::out)
89 {
90 return seekpos(pos, which);
91 }
92
93 int pubsync()
94 {
95 return sync();
96 }
97
98 /**
99 * 27.6.3.2.3, get area:
100 */
101
102 streamsize in_avail()
103 {
104 if (read_avail_())
105 return egptr() - gptr();
106 else
107 return showmanyc();
108 }
109
110 int_type snextc()
111 {
112 if (traits_type::eq(sbumpc(), traits_type::eof()))
113 return traits_type::eof();
114 else
115 return sgetc();
116 }
117
118 int_type sbumpc()
119 {
120 if (read_avail_())
121 return traits_type::to_int_type(*input_next_++);
122 else
123 return uflow();
124 }
125
126 int_type sgetc()
127 {
128 if (read_avail_())
129 return traits_type::to_int_type(*input_next_);
130 else
131 return underflow();
132 }
133
134 streamsize sgetn(char_type* s, streamsize n)
135 {
136 return xsgetn(s, n);
137 }
138
139 /**
140 * 27.6.2.4, putback:
141 */
142
143 int_type sputbackc(char_type c)
144 {
145 if (!putback_avail_() || traits_type::eq(c, gptr()[-1]))
146 return pbackfail(traits_type::to_int_type(c));
147 else
148 return traits_type::to_int_type(*(--input_next_));
149 }
150
151 int_type sungetc()
152 {
153 if (!putback_avail_())
154 return pbackfail();
155 else
156 return traits_type::to_int_type(*(--input_next_));
157 }
158
159 /**
160 * 27.6.2.5, put area:
161 */
162
163 int_type sputc(char_type c)
164 {
165 if (!write_avail_())
166 return overflow(traits_type::to_int_type(c));
167 else
168 {
169 traits_type::assign(*output_next_++, c);
170
171 return traits_type::to_int_type(c);
172 }
173 }
174
175 streamsize sputn(const char_type* s, streamsize n)
176 {
177 return xsputn(s, n);
178 }
179
180 protected:
181 basic_streambuf()
182 : input_begin_{}, input_next_{}, input_end_{},
183 output_begin_{}, output_next_{}, output_end_{},
184 locale_{locale()}
185 { /* DUMMY BODY */ }
186
187 basic_streambuf(const basic_streambuf& rhs)
188 {
189 input_begin_ = rhs.input_begin_;
190 input_next_ = rhs.input_next_;
191 input_end_ = rhs.input_end_;
192
193 output_begin_ = rhs.output_begin_;
194 output_next_ = rhs.output_next_;
195 output_end_ = rhs.output_end_;
196
197 locale_ = rhs.locale_;
198 }
199
200 basic_streambuf& operator=(const basic_streambuf& rhs)
201 {
202 input_begin_ = rhs.input_begin_;
203 input_next_ = rhs.input_next_;
204 input_end_ = rhs.input_end_;
205
206 output_begin_ = rhs.output_begin_;
207 output_next_ = rhs.output_next_;
208 output_end_ = rhs.output_end_;
209
210 locale_ = rhs.locale_;
211
212 return *this;
213 }
214
215 void swap(basic_streambuf& rhs)
216 {
217 swap(input_begin_, rhs.input_begin_);
218 swap(input_next_, rhs.input_next_);
219 swap(input_end_, rhs.input_end_);
220
221 swap(output_begin_, rhs.output_begin_);
222 swap(output_next_, rhs.output_next_);
223 swap(output_end_, rhs.output_end_);
224
225 swap(locale_, rhs.locale_);
226 }
227
228 /**
229 * 27.6.3.3.2, get area:
230 */
231
232 char_type* eback() const
233 {
234 return input_begin_;
235 }
236
237 char_type* gptr() const
238 {
239 return input_next_;
240 }
241
242 char_type* egptr() const
243 {
244 return input_end_;
245 }
246
247 void gbump(int n)
248 {
249 input_next_ += n;
250 }
251
252 void setg(char_type* gbeg, char_type* gnext, char_type* gend)
253 {
254 input_begin_ = gbeg;
255 input_next_ = gnext;
256 input_end_ = gend;
257 }
258
259 /**
260 * 27.6.3.3.3, put area:
261 */
262
263 char_type* pbase() const
264 {
265 return output_begin_;
266 }
267
268 char_type* pptr() const
269 {
270 return output_next_;
271 }
272
273 char_type* epptr() const
274 {
275 return output_end_;
276 }
277
278 void pbump(int n)
279 {
280 output_next_ += n;
281 }
282
283 void setp(char_type* pbeg, char_type* pend)
284 {
285 output_begin_ = pbeg;
286 output_next_ = pbeg;
287 output_end_ = pend;
288 }
289
290 /**
291 * 27.6.3.4.1, locales:
292 */
293
294 virtual void imbue(const locale& loc)
295 { /* DUMMY BODY */ }
296
297 /**
298 * 27.6.3.4.2, buffer management and positioning:
299 */
300
301 virtual basic_streambuf<Char, Traits>*
302 setbuf(char_type* s, streamsize n)
303 {
304 return this;
305 }
306
307 virtual pos_type seekoff(off_type off, ios_base::seekdir way,
308 ios_base::openmode which = ios_base::in | ios_base::out)
309 {
310 return pos_type(off_type(-1));
311 }
312
313 virtual pos_type seekpos(pos_type pos, ios_base::openmode which =
314 ios_base::in | ios_base::out)
315 {
316 return pos_type(off_type(-1));
317 }
318
319 virtual int sync()
320 {
321 return 0;
322 }
323
324 /**
325 * 27.6.3.4.3, get area:
326 */
327
328 virtual streamsize showmanyc()
329 {
330 return 0;
331 }
332
333 virtual streamsize xsgetn(char_type* s, streamsize n)
334 {
335 if (!s || n == 0)
336 return 0;
337
338 streamsize i{0};
339 auto eof = traits_type::eof();
340 for (; i <= n; ++i)
341 {
342 if (!read_avail_() && traits_type::eq_int_type(uflow(), eof))
343 break;
344
345 *s++ = *input_next_++;
346 }
347
348 return i;
349 }
350
351 virtual int_type underflow()
352 {
353 return traits_type::eof();
354 }
355
356 virtual int_type uflow()
357 {
358 auto res = underflow();
359 if (traits_type::eq_int_type(res, traits_type::eof()))
360 return traits_type::eof();
361 else
362 return traits_type::to_int_type(*input_next_++);
363 }
364
365 /**
366 * 27.6.3.4.4, putback:
367 */
368
369 virtual int_type pbackfail(int_type c = traits_type::eof())
370 {
371 return traits_type::eof();
372 }
373
374 /**
375 * 27.6.3.4.5, put area:
376 */
377
378 virtual streamsize xsputn(const char_type* s, streamsize n)
379 {
380 if (!s || n == 0)
381 return 0;
382
383 streamsize i{0};
384 for (; i <= n; ++i)
385 {
386 if (!write_avail_() && traits_type::eq_int_type(overflow(), traits_type::eof()))
387 break;
388
389 *output_next_++ = *s++;
390 }
391
392 return i;
393 }
394
395 virtual int_type overflow(int_type c = traits_type::eof())
396 {
397 return traits_type::eof();
398 }
399
400 protected:
401 char_type* input_begin_;
402 char_type* input_next_;
403 char_type* input_end_;
404
405 char_type* output_begin_;
406 char_type* output_next_;
407 char_type* output_end_;
408
409 locale locale_;
410
411 bool write_avail_() const
412 {
413 return output_next_ && output_next_ < output_end_;
414 }
415
416 bool putback_avail_() const
417 {
418 return input_next_ && input_begin_ < input_next_;
419 }
420
421 bool read_avail_() const
422 {
423 return input_next_ && input_next_ < input_end_;
424 }
425 };
426
427 using streambuf = basic_streambuf<char>;
428 using wstreambuf = basic_streambuf<wchar_t>;
429}
430
431#endif
Note: See TracBrowser for help on using the repository browser.