source: mainline/uspace/lib/cpp/include/impl/streambuf.hpp@ 74b03e3

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 74b03e3 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
RevLine 
[4d30bcd9]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
[6648ab33]43 template<class Char, class Traits>
[4d30bcd9]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()
[990b85d]54 { /* DUMMY BODY */ }
[4d30bcd9]55
56 /**
57 * 27.6.3.2.1, locales:
58 */
59
60 locale pubimbue(const locale& loc)
61 {
[990b85d]62 return imbue(loc);
[4d30bcd9]63 }
64
65 locale& getloc() const
66 {
[990b85d]67 return locale_;
[4d30bcd9]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 {
[990b85d]76 return setbuf(s, n);
[4d30bcd9]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 {
[990b85d]82 return seekoff(off, way, which);
[4d30bcd9]83 }
84
85 pos_type pubseekpos(pos_type pos, ios_base::openmode which =
86 ios_base::in | ios_base::out)
87 {
[990b85d]88 return seekpos(pos, which);
[4d30bcd9]89 }
90
91 int pubsync()
92 {
[990b85d]93 return sync();
[4d30bcd9]94 }
95
96 /**
97 * 27.6.3.2.3, get area:
98 */
99
100 streamsize in_avail()
101 {
[990b85d]102 if (read_avail_())
103 return egptr() - gptr();
104 else
105 return showmanyc();
[4d30bcd9]106 }
107
108 int_type snextc()
109 {
[94cb686]110 if (traits_type::eq(sbumpc(), traits_type::eof()))
[990b85d]111 return traits_type::eof();
112 else
113 return sgetc();
[4d30bcd9]114 }
115
116 int_type sbumpc()
117 {
[990b85d]118 if (read_avail_())
[94cb686]119 return traits_type::to_int_type(*input_next_++);
[990b85d]120 else
121 return uflow();
[4d30bcd9]122 }
123
124 int_type sgetc()
125 {
[990b85d]126 if (read_avail_())
[94cb686]127 return traits_type::to_int_type(*input_next_);
[990b85d]128 else
129 return underflow();
[4d30bcd9]130 }
131
132 streamsize sgetn(char_type* s, streamsize n)
133 {
[990b85d]134 return xsgetn(s, n);
[4d30bcd9]135 }
136
137 /**
138 * 27.6.2.4, putback:
139 */
140
141 int_type sputbackc(char_type c)
142 {
[990b85d]143 if (!putback_avail_() || traits_type::eq(c, gptr()[-1]))
144 return pbackfail(traits_type::to_int_type(c));
145 else
[94cb686]146 return traits_type::to_int_type(*(--input_next_));
[4d30bcd9]147 }
148
149 int_type sungetc()
150 {
[990b85d]151 if (!putback_avail_())
152 return pbackfail();
153 else
[94cb686]154 return traits_type::to_int_type(*(--input_next_));
[4d30bcd9]155 }
156
157 /**
158 * 27.6.2.5, put area:
159 */
160
161 int_type sputc(char_type c)
162 {
[990b85d]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 }
[4d30bcd9]171 }
172
173 streamsize sputn(const char_type* s, streamsize n)
174 {
[990b85d]175 return xsputn(s, n);
[4d30bcd9]176 }
177
178 protected:
179 basic_streambuf()
[990b85d]180 : input_begin_{}, input_next_{}, input_end_{},
181 output_begin_{}, output_next_{}, output_end_{},
182 locale_{locale()}
183 { /* DUMMY BODY */ }
[4d30bcd9]184
185 basic_streambuf(const basic_streambuf& rhs)
186 {
[990b85d]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_;
[4d30bcd9]196 }
197
[94cb686]198 basic_streambuf& operator=(const basic_streambuf& rhs)
[4d30bcd9]199 {
[990b85d]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;
[4d30bcd9]211 }
212
213 void swap(basic_streambuf& rhs)
214 {
[990b85d]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_);
[4d30bcd9]224 }
225
226 /**
227 * 27.6.3.3.2, get area:
228 */
229
230 char_type* eback() const
231 {
[990b85d]232 return input_begin_;
[4d30bcd9]233 }
234
235 char_type* gptr() const
236 {
[990b85d]237 return input_next_;
[4d30bcd9]238 }
239
240 char_type* egptr() const
241 {
[990b85d]242 return input_end_;
[4d30bcd9]243 }
244
245 void gbump(int n)
246 {
[990b85d]247 input_next_ += n;
[4d30bcd9]248 }
249
250 void setg(char_type* gbeg, char_type* gnext, char_type* gend)
251 {
[990b85d]252 input_begin_ = gbeg;
253 input_next_ = gnext;
254 input_end_ = gend;
[4d30bcd9]255 }
256
257 /**
258 * 27.6.3.3.3, put area:
259 */
260
261 char_type* pbase() const
262 {
[990b85d]263 return output_begin_;
[4d30bcd9]264 }
265
266 char_type* pptr() const
267 {
[990b85d]268 return output_next_;
[4d30bcd9]269 }
270
271 char_type* epptr() const
272 {
[990b85d]273 return output_end_;
[4d30bcd9]274 }
275
276 void pbump(int n)
277 {
[990b85d]278 output_next_ += n;
[4d30bcd9]279 }
280
281 void setp(char_type* pbeg, char_type* pend)
282 {
[990b85d]283 output_begin_ = pbeg;
284 output_next_ = pbeg;
285 output_end_ = pend;
[4d30bcd9]286 }
287
288 /**
289 * 27.6.3.4.1, locales:
290 */
291
292 virtual void imbue(const locale& loc)
[990b85d]293 { /* DUMMY BODY */ }
[4d30bcd9]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 {
[94cb686]302 return this;
[4d30bcd9]303 }
304
305 virtual pos_type seekoff(off_type off, ios_base::seekdir way,
[94cb686]306 ios_base::openmode which = ios_base::in | ios_base::out)
[4d30bcd9]307 {
[990b85d]308 return pos_type(off_type(-1));
[4d30bcd9]309 }
310
311 virtual pos_type seekpos(pos_type pos, ios_base::openmode which =
312 ios_base::in | ios_base::out)
313 {
[990b85d]314 return pos_type(off_type(-1));
[4d30bcd9]315 }
316
317 virtual int sync()
318 {
[990b85d]319 return 0;
[4d30bcd9]320 }
321
322 /**
323 * 27.6.3.4.3, get area:
324 */
325
326 virtual streamsize showmanyc()
327 {
[990b85d]328 return 0;
[4d30bcd9]329 }
330
331 virtual streamsize xsgetn(char_type* s, streamsize n)
332 {
[990b85d]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
[94cb686]343 *s++ = *input_next_++;
[990b85d]344 }
345
346 return i;
[4d30bcd9]347 }
348
349 virtual int_type underflow()
350 {
[990b85d]351 return traits_type::eof();
[4d30bcd9]352 }
353
354 virtual int_type uflow()
355 {
[990b85d]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_++);
[4d30bcd9]361 }
362
363 /**
364 * 27.6.3.4.4, putback:
365 */
366
367 virtual int_type pbackfail(int_type c = traits_type::eof())
368 {
[990b85d]369 return traits_type::eof();
[4d30bcd9]370 }
371
372 /**
373 * 27.6.3.4.5, put area:
374 */
375
376 virtual streamsize xsputn(const char_type* s, streamsize n)
377 {
[990b85d]378 if (!s || n == 0)
379 return 0;
380
381 streamsize i{0};
382 for (; i <= n; ++i)
383 {
[94cb686]384 if (!write_avail_() && traits_type::eq_int_type(overflow(), traits_type::eof()))
[990b85d]385 break;
386
[94cb686]387 *output_next_++ = *s++;
[990b85d]388 }
389
390 return i;
[4d30bcd9]391 }
392
393 virtual int_type overflow(int_type c = traits_type::eof())
394 {
[990b85d]395 return traits_type::eof();
[4d30bcd9]396 }
397
[94cb686]398 protected:
399 char_type* input_begin_;
400 char_type* input_next_;
401 char_type* input_end_;
[990b85d]402
[94cb686]403 char_type* output_begin_;
404 char_type* output_next_;
405 char_type* output_end_;
[990b85d]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 }
[4d30bcd9]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.