source: mainline/uspace/lib/cpp/include/impl/streambuf.hpp@ 6b81ca5

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

cpp: private checks of streambuf are now protected and thus available to descendants

  • 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 return imbue(loc);
63 }
64
65 locale& getloc() const
66 {
67 return locale_;
68 }
69
70 /**
71 * 27.6.3.2.2, buffer and positioning:
72 */
73
74 basic_streambuf<Char, Traits>* pubsetbuf(char_type* s, streamsize n)
75 {
76 return setbuf(s, n);
77 }
78
79 pos_type pubseekoff(off_type off, ios_base::seekdir way,
80 ios_base::openmode which = ios_base::in | ios_base::out)
81 {
82 return seekoff(off, way, which);
83 }
84
85 pos_type pubseekpos(pos_type pos, ios_base::openmode which =
86 ios_base::in | ios_base::out)
87 {
88 return seekpos(pos, which);
89 }
90
91 int pubsync()
92 {
93 return sync();
94 }
95
96 /**
97 * 27.6.3.2.3, get area:
98 */
99
100 streamsize in_avail()
101 {
102 if (read_avail_())
103 return egptr() - gptr();
104 else
105 return showmanyc();
106 }
107
108 int_type snextc()
109 {
110 if (traits_type::eq(sbumpc(), traits_type::eof()))
111 return traits_type::eof();
112 else
113 return sgetc();
114 }
115
116 int_type sbumpc()
117 {
118 if (read_avail_())
119 return traits_type::to_int_type(*input_next_++);
120 else
121 return uflow();
122 }
123
124 int_type sgetc()
125 {
126 if (read_avail_())
127 return traits_type::to_int_type(*input_next_);
128 else
129 return underflow();
130 }
131
132 streamsize sgetn(char_type* s, streamsize n)
133 {
134 return xsgetn(s, n);
135 }
136
137 /**
138 * 27.6.2.4, putback:
139 */
140
141 int_type sputbackc(char_type c)
142 {
143 if (!putback_avail_() || traits_type::eq(c, gptr()[-1]))
144 return pbackfail(traits_type::to_int_type(c));
145 else
146 return traits_type::to_int_type(*(--input_next_));
147 }
148
149 int_type sungetc()
150 {
151 if (!putback_avail_())
152 return pbackfail();
153 else
154 return traits_type::to_int_type(*(--input_next_));
155 }
156
157 /**
158 * 27.6.2.5, put area:
159 */
160
161 int_type sputc(char_type c)
162 {
163 if (!write_avail_())
164 return overflow(traits_type::to_int_type(c));
165 else
166 {
167 traits_type::assign(*output_next_++, c);
168
169 return traits_type::to_int_type(c);
170 }
171 }
172
173 streamsize sputn(const char_type* s, streamsize n)
174 {
175 return xsputn(s, n);
176 }
177
178 protected:
179 basic_streambuf()
180 : input_begin_{}, input_next_{}, input_end_{},
181 output_begin_{}, output_next_{}, output_end_{},
182 locale_{locale()}
183 { /* DUMMY BODY */ }
184
185 basic_streambuf(const basic_streambuf& rhs)
186 {
187 input_begin_ = rhs.input_begin_;
188 input_next_ = rhs.input_next_;
189 input_end_ = rhs.input_end_;
190
191 output_begin_ = rhs.output_begin_;
192 output_next_ = rhs.output_next_;
193 output_end_ = rhs.output_end_;
194
195 locale_ = rhs.locale_;
196 }
197
198 basic_streambuf& operator=(const basic_streambuf& rhs)
199 {
200 input_begin_ = rhs.input_begin_;
201 input_next_ = rhs.input_next_;
202 input_end_ = rhs.input_end_;
203
204 output_begin_ = rhs.output_begin_;
205 output_next_ = rhs.output_next_;
206 output_end_ = rhs.output_end_;
207
208 locale_ = rhs.locale_;
209
210 return *this;
211 }
212
213 void swap(basic_streambuf& rhs)
214 {
215 swap(input_begin_, rhs.input_begin_);
216 swap(input_next_, rhs.input_next_);
217 swap(input_end_, rhs.input_end_);
218
219 swap(output_begin_, rhs.output_begin_);
220 swap(output_next_, rhs.output_next_);
221 swap(output_end_, rhs.output_end_);
222
223 swap(locale_, rhs.locale_);
224 }
225
226 /**
227 * 27.6.3.3.2, get area:
228 */
229
230 char_type* eback() const
231 {
232 return input_begin_;
233 }
234
235 char_type* gptr() const
236 {
237 return input_next_;
238 }
239
240 char_type* egptr() const
241 {
242 return input_end_;
243 }
244
245 void gbump(int n)
246 {
247 input_next_ += n;
248 }
249
250 void setg(char_type* gbeg, char_type* gnext, char_type* gend)
251 {
252 input_begin_ = gbeg;
253 input_next_ = gnext;
254 input_end_ = gend;
255 }
256
257 /**
258 * 27.6.3.3.3, put area:
259 */
260
261 char_type* pbase() const
262 {
263 return output_begin_;
264 }
265
266 char_type* pptr() const
267 {
268 return output_next_;
269 }
270
271 char_type* epptr() const
272 {
273 return output_end_;
274 }
275
276 void pbump(int n)
277 {
278 output_next_ += n;
279 }
280
281 void setp(char_type* pbeg, char_type* pend)
282 {
283 output_begin_ = pbeg;
284 output_next_ = pbeg;
285 output_end_ = pend;
286 }
287
288 /**
289 * 27.6.3.4.1, locales:
290 */
291
292 virtual void imbue(const locale& loc)
293 { /* DUMMY BODY */ }
294
295 /**
296 * 27.6.3.4.2, buffer management and positioning:
297 */
298
299 virtual basic_streambuf<Char, Traits>*
300 setbuf(char_type* s, streamsize n)
301 {
302 return this;
303 }
304
305 virtual pos_type seekoff(off_type off, ios_base::seekdir way,
306 ios_base::openmode which = ios_base::in | ios_base::out)
307 {
308 return pos_type(off_type(-1));
309 }
310
311 virtual pos_type seekpos(pos_type pos, ios_base::openmode which =
312 ios_base::in | ios_base::out)
313 {
314 return pos_type(off_type(-1));
315 }
316
317 virtual int sync()
318 {
319 return 0;
320 }
321
322 /**
323 * 27.6.3.4.3, get area:
324 */
325
326 virtual streamsize showmanyc()
327 {
328 return 0;
329 }
330
331 virtual streamsize xsgetn(char_type* s, streamsize n)
332 {
333 if (!s || n == 0)
334 return 0;
335
336 streamsize i{0};
337 auto eof = traits_type::eof();
338 for (; i <= n; ++i)
339 {
340 if (!read_avail_() && traits_type::eq_int_type(uflow(), eof))
341 break;
342
343 *s++ = *input_next_++;
344 }
345
346 return i;
347 }
348
349 virtual int_type underflow()
350 {
351 return traits_type::eof();
352 }
353
354 virtual int_type uflow()
355 {
356 auto res = underflow();
357 if (traits_type::eq_int_type(res, traits_type::eof()))
358 return traits_type::eof();
359 else
360 return traits_type::to_int_type(*input_next_++);
361 }
362
363 /**
364 * 27.6.3.4.4, putback:
365 */
366
367 virtual int_type pbackfail(int_type c = traits_type::eof())
368 {
369 return traits_type::eof();
370 }
371
372 /**
373 * 27.6.3.4.5, put area:
374 */
375
376 virtual streamsize xsputn(const char_type* s, streamsize n)
377 {
378 if (!s || n == 0)
379 return 0;
380
381 streamsize i{0};
382 for (; i <= n; ++i)
383 {
384 if (!write_avail_() && traits_type::eq_int_type(overflow(), traits_type::eof()))
385 break;
386
387 *output_next_++ = *s++;
388 }
389
390 return i;
391 }
392
393 virtual int_type overflow(int_type c = traits_type::eof())
394 {
395 return traits_type::eof();
396 }
397
398 protected:
399 char_type* input_begin_;
400 char_type* input_next_;
401 char_type* input_end_;
402
403 char_type* output_begin_;
404 char_type* output_next_;
405 char_type* output_end_;
406
407 locale locale_;
408
409 bool write_avail_() const
410 {
411 return output_next_ && output_next_ < output_end_;
412 }
413
414 bool putback_avail_() const
415 {
416 return input_next_ && input_begin_ < input_next_;
417 }
418
419 bool read_avail_() const
420 {
421 return input_next_ && input_next_ < input_end_;
422 }
423 };
424
425 using streambuf = basic_streambuf<char>;
426 using wstreambuf = basic_streambuf<wchar_t>;
427}
428
429#endif
Note: See TracBrowser for help on using the repository browser.