nsprpub/lib/prstreams/prstrms.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 * Robin J. Maxwell 11-22-96
michael@0 8 * Fredrik Roubert <roubert@google.com> 2010-07-23
michael@0 9 * Matt Austern <austern@google.com> 2010-07-23
michael@0 10 */
michael@0 11
michael@0 12 #include "prstrms.h"
michael@0 13
michael@0 14 #include <cstdio>
michael@0 15 #include <cstring>
michael@0 16 #include <ios>
michael@0 17 #include <new>
michael@0 18
michael@0 19 using std::ios_base;
michael@0 20 using std::iostream;
michael@0 21 using std::istream;
michael@0 22 using std::nothrow;
michael@0 23 using std::ostream;
michael@0 24 using std::streambuf;
michael@0 25 using std::streamsize;
michael@0 26
michael@0 27
michael@0 28 PRfilebuf::PRfilebuf():
michael@0 29 _fd(NULL),
michael@0 30 _opened(false),
michael@0 31 _allocated(false),
michael@0 32 _unbuffered(false),
michael@0 33 _user_buf(false),
michael@0 34 _buf_base(NULL),
michael@0 35 _buf_end(NULL) { }
michael@0 36
michael@0 37
michael@0 38 PRfilebuf::PRfilebuf(PRFileDesc *fd):
michael@0 39 _fd(fd),
michael@0 40 _opened(false),
michael@0 41 _allocated(false),
michael@0 42 _unbuffered(false),
michael@0 43 _user_buf(false),
michael@0 44 _buf_base(NULL),
michael@0 45 _buf_end(NULL) { }
michael@0 46
michael@0 47
michael@0 48 PRfilebuf::PRfilebuf(PRFileDesc *fd, char_type *ptr, streamsize len):
michael@0 49 _fd(fd),
michael@0 50 _opened(false),
michael@0 51 _allocated(false),
michael@0 52 _unbuffered(false),
michael@0 53 _user_buf(false),
michael@0 54 _buf_base(NULL),
michael@0 55 _buf_end(NULL)
michael@0 56 {
michael@0 57 setbuf(ptr, len);
michael@0 58 }
michael@0 59
michael@0 60
michael@0 61 PRfilebuf::~PRfilebuf()
michael@0 62 {
michael@0 63 if (_opened) {
michael@0 64 close();
michael@0 65 } else {
michael@0 66 sync();
michael@0 67 }
michael@0 68 if (_allocated) {
michael@0 69 delete _buf_base;
michael@0 70 }
michael@0 71 }
michael@0 72
michael@0 73
michael@0 74 PRfilebuf *PRfilebuf::open(
michael@0 75 const char *name, ios_base::openmode flags, PRIntn mode)
michael@0 76 {
michael@0 77 if (_fd != NULL) {
michael@0 78 return NULL; // Error if already open.
michael@0 79 }
michael@0 80
michael@0 81 // Translate flags argument.
michael@0 82 PRIntn prflags = 0;
michael@0 83 bool ate = (flags & ios_base::ate) != 0;
michael@0 84 flags &= ~(ios_base::ate | ios_base::binary);
michael@0 85
michael@0 86 // TODO: The flag PR_CREATE_FILE should probably be used for the cases
michael@0 87 // (out), (out|app), (out|trunc) and (in|out|trunc) as the C++ standard
michael@0 88 // specifies that these cases should open files 'as if by using fopen with
michael@0 89 // "w"'. But adding that flag here will cause the unit test to leave files
michael@0 90 // behind after running (which might or might not be an error in the unit
michael@0 91 // test) so the matter needs further investigation before any changes are
michael@0 92 // made. The old prstreams implementation used the non-standard flag
michael@0 93 // ios::nocreate to control the use of PR_CREATE_FILE.
michael@0 94
michael@0 95 if (flags == (ios_base::out)) {
michael@0 96 prflags = PR_WRONLY | PR_TRUNCATE;
michael@0 97 } else if (flags == (ios_base::out | ios_base::app)) {
michael@0 98 prflags = PR_RDWR | PR_APPEND;
michael@0 99 } else if (flags == (ios_base::out | ios_base::trunc)) {
michael@0 100 prflags = PR_WRONLY | PR_TRUNCATE;
michael@0 101 } else if (flags == (ios_base::in)) {
michael@0 102 prflags = PR_RDONLY;
michael@0 103 } else if (flags == (ios_base::in | ios_base::out)) {
michael@0 104 prflags = PR_RDWR;
michael@0 105 } else if (flags == (ios_base::in | ios_base::out | ios_base::trunc)) {
michael@0 106 prflags = PR_RDWR | PR_TRUNCATE;
michael@0 107 } else {
michael@0 108 return NULL; // Unrecognized flag combination.
michael@0 109 }
michael@0 110
michael@0 111 if ((_fd = PR_Open(name, prflags, mode)) == NULL) {
michael@0 112 return NULL;
michael@0 113 }
michael@0 114
michael@0 115 _opened = true;
michael@0 116
michael@0 117 if (ate &&
michael@0 118 seekoff(0, ios_base::end, flags) == pos_type(traits_type::eof())) {
michael@0 119 close();
michael@0 120 return NULL;
michael@0 121 }
michael@0 122
michael@0 123 return this;
michael@0 124 }
michael@0 125
michael@0 126
michael@0 127 PRfilebuf *PRfilebuf::attach(PRFileDesc *fd)
michael@0 128 {
michael@0 129 if (_fd != NULL) {
michael@0 130 return NULL; // Error if already open.
michael@0 131 }
michael@0 132
michael@0 133 _opened = false;
michael@0 134 _fd = fd;
michael@0 135 return this;
michael@0 136 }
michael@0 137
michael@0 138
michael@0 139 PRfilebuf *PRfilebuf::close()
michael@0 140 {
michael@0 141 if (_fd == NULL)
michael@0 142 return NULL;
michael@0 143
michael@0 144 int status = sync();
michael@0 145
michael@0 146 if (PR_Close(_fd) == PR_FAILURE ||
michael@0 147 traits_type::eq_int_type(status, traits_type::eof())) {
michael@0 148 return NULL;
michael@0 149 }
michael@0 150
michael@0 151 _fd = NULL;
michael@0 152 return this;
michael@0 153 }
michael@0 154
michael@0 155
michael@0 156 streambuf *PRfilebuf::setbuf(char_type *ptr, streamsize len)
michael@0 157 {
michael@0 158 if (is_open() && _buf_end) {
michael@0 159 return NULL;
michael@0 160 }
michael@0 161
michael@0 162 if (!ptr || len <= 0) {
michael@0 163 _unbuffered = true;
michael@0 164 } else {
michael@0 165 setb(ptr, ptr + len, false);
michael@0 166 }
michael@0 167
michael@0 168 return this;
michael@0 169 }
michael@0 170
michael@0 171
michael@0 172 streambuf::pos_type PRfilebuf::seekoff(
michael@0 173 off_type offset, ios_base::seekdir dir, ios_base::openmode /*flags*/)
michael@0 174 {
michael@0 175 if (PR_GetDescType(_fd) != PR_DESC_FILE) {
michael@0 176 return traits_type::eof();
michael@0 177 }
michael@0 178
michael@0 179 PRSeekWhence whence;
michael@0 180 PRInt64 pos;
michael@0 181
michael@0 182 switch (dir) {
michael@0 183 case ios_base::beg: whence = PR_SEEK_SET; break;
michael@0 184 case ios_base::cur: whence = PR_SEEK_CUR; break;
michael@0 185 case ios_base::end: whence = PR_SEEK_END; break;
michael@0 186 default:
michael@0 187 return traits_type::eof(); // This should never happen.
michael@0 188 }
michael@0 189
michael@0 190 if (traits_type::eq_int_type(sync(), traits_type::eof())) {
michael@0 191 return traits_type::eof();
michael@0 192 }
michael@0 193
michael@0 194 if ((pos = PR_Seek64(_fd, offset, whence)) == -1) {
michael@0 195 return traits_type::eof();
michael@0 196 }
michael@0 197
michael@0 198 return pos;
michael@0 199 }
michael@0 200
michael@0 201
michael@0 202 int PRfilebuf::sync()
michael@0 203 {
michael@0 204 if (_fd == NULL) {
michael@0 205 return traits_type::eof();
michael@0 206 }
michael@0 207
michael@0 208 if (!_unbuffered) {
michael@0 209 // Sync write area.
michael@0 210 PRInt32 waiting;
michael@0 211 if ((waiting = pptr() - pbase()) != 0) {
michael@0 212 PRInt32 nout;
michael@0 213 if ((nout = PR_Write(_fd, pbase(), waiting)) != waiting) {
michael@0 214 if (nout > 0) {
michael@0 215 // Should set _pptr -= nout.
michael@0 216 pbump(-nout);
michael@0 217 memmove(pbase(), pbase() + nout, waiting - nout);
michael@0 218 }
michael@0 219 return traits_type::eof();
michael@0 220 }
michael@0 221 }
michael@0 222 setp(NULL, NULL); // Empty put area.
michael@0 223
michael@0 224 if (PR_GetDescType(_fd) == PR_DESC_FILE) {
michael@0 225 // Sockets can't seek; don't need this.
michael@0 226 PROffset64 avail;
michael@0 227 if ((avail = in_avail()) > 0) {
michael@0 228 if (PR_Seek64(_fd, -avail, PR_SEEK_CUR) != -1) {
michael@0 229 return traits_type::eof();
michael@0 230 }
michael@0 231 }
michael@0 232 }
michael@0 233 setg(NULL, NULL, NULL); // Empty get area.
michael@0 234 }
michael@0 235
michael@0 236 return 0;
michael@0 237 }
michael@0 238
michael@0 239
michael@0 240 streambuf::int_type PRfilebuf::underflow()
michael@0 241 {
michael@0 242 PRInt32 count;
michael@0 243 char_type byte;
michael@0 244
michael@0 245 if (gptr() != NULL && gptr() < egptr()) {
michael@0 246 return traits_type::to_int_type(*gptr());
michael@0 247 }
michael@0 248
michael@0 249 // Make sure there is a reserve area.
michael@0 250 if (!_unbuffered && _buf_base == NULL && !allocate()) {
michael@0 251 return traits_type::eof();
michael@0 252 }
michael@0 253
michael@0 254 // Sync before new buffer created below.
michael@0 255 if (traits_type::eq_int_type(sync(), traits_type::eof())) {
michael@0 256 return traits_type::eof();
michael@0 257 }
michael@0 258
michael@0 259 if (_unbuffered) {
michael@0 260 if (PR_Read(_fd, &byte, 1) <= 0) {
michael@0 261 return traits_type::eof();
michael@0 262 }
michael@0 263
michael@0 264 return traits_type::to_int_type(byte);
michael@0 265 }
michael@0 266
michael@0 267 if ((count = PR_Read(_fd, _buf_base, _buf_end - _buf_base)) <= 0) {
michael@0 268 return traits_type::eof(); // Reached EOF.
michael@0 269 }
michael@0 270
michael@0 271 setg(_buf_base, _buf_base, _buf_base + count);
michael@0 272 return traits_type::to_int_type(*gptr());
michael@0 273 }
michael@0 274
michael@0 275
michael@0 276 streambuf::int_type PRfilebuf::overflow(int_type c)
michael@0 277 {
michael@0 278 // Make sure there is a reserve area.
michael@0 279 if (!_unbuffered && _buf_base == NULL && !allocate()) {
michael@0 280 return traits_type::eof();
michael@0 281 }
michael@0 282
michael@0 283 // Sync before new buffer created below.
michael@0 284 if (traits_type::eq_int_type(sync(), traits_type::eof())) {
michael@0 285 return traits_type::eof();
michael@0 286 }
michael@0 287
michael@0 288 if (!_unbuffered) {
michael@0 289 setp(_buf_base, _buf_end);
michael@0 290 }
michael@0 291
michael@0 292 if (!traits_type::eq_int_type(c, traits_type::eof())) {
michael@0 293 // Extract the byte to be written.
michael@0 294 // (Required on big-endian architectures.)
michael@0 295 char_type byte = traits_type::to_char_type(c);
michael@0 296 if (!_unbuffered && pptr() < epptr()) { // Guard against recursion.
michael@0 297 return sputc(byte);
michael@0 298 } else {
michael@0 299 if (PR_Write(_fd, &byte, 1) != 1) {
michael@0 300 return traits_type::eof();
michael@0 301 }
michael@0 302 }
michael@0 303 }
michael@0 304
michael@0 305 return traits_type::not_eof(c);
michael@0 306 }
michael@0 307
michael@0 308
michael@0 309 bool PRfilebuf::allocate()
michael@0 310 {
michael@0 311 char_type *buf = new(nothrow) char_type[BUFSIZ];
michael@0 312 if (buf == NULL) {
michael@0 313 return false;
michael@0 314 }
michael@0 315
michael@0 316 setb(buf, buf + BUFSIZ, true);
michael@0 317 return true;
michael@0 318 }
michael@0 319
michael@0 320
michael@0 321 void PRfilebuf::setb(char_type *buf_base, char_type *buf_end, bool user_buf)
michael@0 322 {
michael@0 323 if (_buf_base && !_user_buf) {
michael@0 324 delete[] _buf_base;
michael@0 325 }
michael@0 326
michael@0 327 _buf_base = buf_base;
michael@0 328 _buf_end = buf_end;
michael@0 329 _user_buf = user_buf;
michael@0 330 }
michael@0 331
michael@0 332
michael@0 333 PRifstream::PRifstream():
michael@0 334 istream(NULL),
michael@0 335 _filebuf()
michael@0 336 {
michael@0 337 init(&_filebuf);
michael@0 338 }
michael@0 339
michael@0 340
michael@0 341 PRifstream::PRifstream(PRFileDesc *fd):
michael@0 342 istream(NULL),
michael@0 343 _filebuf(fd)
michael@0 344 {
michael@0 345 init(&_filebuf);
michael@0 346 }
michael@0 347
michael@0 348
michael@0 349 PRifstream::PRifstream(PRFileDesc *fd, char_type *ptr, streamsize len):
michael@0 350 istream(NULL),
michael@0 351 _filebuf(fd, ptr, len)
michael@0 352 {
michael@0 353 init(&_filebuf);
michael@0 354 }
michael@0 355
michael@0 356
michael@0 357 PRifstream::PRifstream(const char *name, openmode flags, PRIntn mode):
michael@0 358 istream(NULL),
michael@0 359 _filebuf()
michael@0 360 {
michael@0 361 init(&_filebuf);
michael@0 362 if (!_filebuf.open(name, flags | in, mode)) {
michael@0 363 setstate(failbit);
michael@0 364 }
michael@0 365 }
michael@0 366
michael@0 367
michael@0 368 PRifstream::~PRifstream() { }
michael@0 369
michael@0 370
michael@0 371 void PRifstream::open(const char *name, openmode flags, PRIntn mode)
michael@0 372 {
michael@0 373 if (is_open() || !_filebuf.open(name, flags | in, mode)) {
michael@0 374 setstate(failbit);
michael@0 375 }
michael@0 376 }
michael@0 377
michael@0 378
michael@0 379 void PRifstream::attach(PRFileDesc *fd)
michael@0 380 {
michael@0 381 if (!_filebuf.attach(fd)) {
michael@0 382 setstate(failbit);
michael@0 383 }
michael@0 384 }
michael@0 385
michael@0 386
michael@0 387 void PRifstream::close()
michael@0 388 {
michael@0 389 if (_filebuf.close() == NULL) {
michael@0 390 setstate(failbit);
michael@0 391 }
michael@0 392 }
michael@0 393
michael@0 394
michael@0 395 PRofstream::PRofstream():
michael@0 396 ostream(NULL),
michael@0 397 _filebuf()
michael@0 398 {
michael@0 399 init(&_filebuf);
michael@0 400 }
michael@0 401
michael@0 402
michael@0 403 PRofstream::PRofstream(PRFileDesc *fd):
michael@0 404 ostream(NULL),
michael@0 405 _filebuf(fd)
michael@0 406 {
michael@0 407 init(&_filebuf);
michael@0 408 }
michael@0 409
michael@0 410
michael@0 411 PRofstream::PRofstream(PRFileDesc *fd, char_type *ptr, streamsize len):
michael@0 412 ostream(NULL),
michael@0 413 _filebuf(fd, ptr, len)
michael@0 414 {
michael@0 415 init(&_filebuf);
michael@0 416 }
michael@0 417
michael@0 418
michael@0 419 PRofstream::PRofstream(const char *name, openmode flags, PRIntn mode):
michael@0 420 ostream(NULL),
michael@0 421 _filebuf()
michael@0 422 {
michael@0 423 init(&_filebuf);
michael@0 424 if (!_filebuf.open(name, flags | out, mode)) {
michael@0 425 setstate(failbit);
michael@0 426 }
michael@0 427 }
michael@0 428
michael@0 429
michael@0 430 PRofstream::~PRofstream() { }
michael@0 431
michael@0 432
michael@0 433 void PRofstream::open(const char *name, openmode flags, PRIntn mode)
michael@0 434 {
michael@0 435 if (is_open() || !_filebuf.open(name, flags | out, mode)) {
michael@0 436 setstate(failbit);
michael@0 437 }
michael@0 438 }
michael@0 439
michael@0 440
michael@0 441 void PRofstream::attach(PRFileDesc *fd)
michael@0 442 {
michael@0 443 if (!_filebuf.attach(fd)) {
michael@0 444 setstate(failbit);
michael@0 445 }
michael@0 446 }
michael@0 447
michael@0 448
michael@0 449 void PRofstream::close()
michael@0 450 {
michael@0 451 if (_filebuf.close() == NULL) {
michael@0 452 setstate(failbit);
michael@0 453 }
michael@0 454 }
michael@0 455
michael@0 456
michael@0 457 PRfstream::PRfstream():
michael@0 458 iostream(NULL),
michael@0 459 _filebuf()
michael@0 460 {
michael@0 461 init(&_filebuf);
michael@0 462 }
michael@0 463
michael@0 464
michael@0 465 PRfstream::PRfstream(PRFileDesc *fd):
michael@0 466 iostream(NULL),
michael@0 467 _filebuf(fd)
michael@0 468 {
michael@0 469 init(&_filebuf);
michael@0 470 }
michael@0 471
michael@0 472
michael@0 473 PRfstream::PRfstream(PRFileDesc *fd, char_type *ptr, streamsize len):
michael@0 474 iostream(NULL),
michael@0 475 _filebuf(fd, ptr, len)
michael@0 476 {
michael@0 477 init(&_filebuf);
michael@0 478 }
michael@0 479
michael@0 480
michael@0 481 PRfstream::PRfstream(const char *name, openmode flags, PRIntn mode):
michael@0 482 iostream(NULL),
michael@0 483 _filebuf()
michael@0 484 {
michael@0 485 init(&_filebuf);
michael@0 486 if (!_filebuf.open(name, flags | in | out, mode)) {
michael@0 487 setstate(failbit);
michael@0 488 }
michael@0 489 }
michael@0 490
michael@0 491
michael@0 492 PRfstream::~PRfstream() { }
michael@0 493
michael@0 494
michael@0 495 void PRfstream::open(const char *name, openmode flags, PRIntn mode)
michael@0 496 {
michael@0 497 if (is_open() || !_filebuf.open(name, flags | in | out, mode)) {
michael@0 498 setstate(failbit);
michael@0 499 }
michael@0 500 }
michael@0 501
michael@0 502
michael@0 503 void PRfstream::attach(PRFileDesc *fd)
michael@0 504 {
michael@0 505 if (!_filebuf.attach(fd)) {
michael@0 506 setstate(failbit);
michael@0 507 }
michael@0 508 }
michael@0 509
michael@0 510
michael@0 511 void PRfstream::close()
michael@0 512 {
michael@0 513 if (_filebuf.close() == NULL) {
michael@0 514 setstate(failbit);
michael@0 515 }
michael@0 516 }

mercurial