nsprpub/lib/prstreams/prstrms.cpp

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

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

mercurial