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