Back to index

lightning-sunbird  0.9+nobinonly
prstrms.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039  * Robin J. Maxwell 11-22-96
00040  */
00041 
00042 #include "prstrms.h"
00043 #include <string.h> // memmove
00044 
00045 //
00046 // Definition of macros _PRSTR_BP, _PRSTR_DELBUF, and _PRSTR_DELBUF_C.
00047 //
00048 // _PRSTR_BP is the protected member of class ios that is returned
00049 // by the public method rdbuf().
00050 //
00051 // _PRSTR_DELBUF is the method or data member of class ios, if available,
00052 // with which we can ensure that the ios destructor does not delete
00053 // the associated streambuf.  If such a method or data member does not
00054 // exist, define _PRSTR_DELBUF to be empty.
00055 //
00056 // _PRSTR_DELBUF_C is just _PRSTR_DELBUF qualified by a base class.
00057 //
00058 
00059 #if defined(__GNUC__)
00060 #define _PRSTR_BP _strbuf
00061 #define _PRSTR_DELBUF(x)    /* as nothing */
00062 #define _PRSTR_DELBUF_C(c, x)  /* as nothing */
00063 #elif defined(WIN32)
00064 #define _PRSTR_BP bp
00065 #define _PRSTR_DELBUF(x)    delbuf(x)
00066 #define _PRSTR_DELBUF_C(c, x)      c::_PRSTR_DELBUF(x)
00067 #elif defined(VMS)
00068 #undef  _PRSTR_BP
00069 #define _PRSTR_DELBUF(x) /* as nothing */
00070 #define _PRSTR_DELBUF_C(c, x)      /* as nothing */
00071 #elif defined(OSF1)
00072 #define _PRSTR_BP m_psb
00073 #define _PRSTR_DELBUF(x) /* as nothing */
00074 #define _PRSTR_DELBUF_C(c, x)      /* as nothing */
00075 #elif defined(QNX)
00076 #define PRFSTREAMS_BROKEN
00077 #else
00078 #define _PRSTR_BP bp
00079 // Unix compilers don't believe in encapsulation
00080 // At least on Solaris this is also ignored
00081 #define _PRSTR_DELBUF(x)    delbuf = x
00082 #define _PRSTR_DELBUF_C(c, x)      c::_PRSTR_DELBUF(x)
00083 #endif
00084 
00085 const PRIntn STRM_BUFSIZ = 8192;
00086 
00087 #if !defined (PRFSTREAMS_BROKEN)   
00088 
00089 PRfilebuf::PRfilebuf():
00090 _fd(0),
00091 _opened(PR_FALSE),
00092 _allocated(PR_FALSE)
00093 {
00094 }
00095 
00096 PRfilebuf::PRfilebuf(PRFileDesc *fd):
00097 streambuf(),
00098 _fd(fd),
00099 _opened(PR_FALSE),
00100 _allocated(PR_FALSE)
00101 {
00102 }
00103 
00104 PRfilebuf::PRfilebuf(PRFileDesc *fd, char * buffptr, int bufflen):
00105 _fd(fd),
00106 _opened(PR_FALSE),
00107 _allocated(PR_FALSE)
00108 {
00109     PRfilebuf::setbuf(buffptr, bufflen);
00110 }
00111 
00112 PRfilebuf::~PRfilebuf()
00113 {
00114     if (_opened){
00115         close();
00116     }else
00117         sync();
00118        if (_allocated)
00119               delete base();
00120 }
00121 
00122 PRfilebuf*    
00123 PRfilebuf::open(const char *name, int mode, int flags)
00124 {
00125      if (_fd != 0)
00126         return 0;    // error if already open
00127      PRIntn PRmode = 0;
00128     // translate mode argument
00129     if (!(mode & ios::nocreate))
00130         PRmode |= PR_CREATE_FILE;
00131     //if (mode & ios::noreplace)
00132     //    PRmode |= O_EXCL;
00133     if (mode & ios::app){
00134         mode |= ios::out;
00135         PRmode |= PR_APPEND;
00136     }
00137     if (mode & ios::trunc){
00138         mode |= ios::out;  // IMPLIED
00139         PRmode |= PR_TRUNCATE;
00140     }
00141     if (mode & ios::out){
00142         if (mode & ios::in)
00143             PRmode |= PR_RDWR;
00144         else
00145             PRmode |= PR_WRONLY;
00146         if (!(mode & (ios::in|ios::app|ios::ate|ios::noreplace))){
00147             mode |= ios::trunc; // IMPLIED
00148             PRmode |= PR_TRUNCATE;
00149         }
00150     }else if (mode & ios::in)
00151         PRmode |= PR_RDONLY;
00152     else
00153         return 0;    // error if not ios:in or ios::out
00154 
00155 
00156     //
00157     // The usual portable across unix crap...
00158     // NT gets a hokey piece of junk layer that prevents
00159     // access to the API.
00160 #ifdef WIN32
00161     _fd = PR_Open(name, PRmode, PRmode);
00162 #else
00163     _fd = PR_Open(name, PRmode, flags);
00164 #endif
00165     if (_fd == 0)
00166         return 0;
00167     _opened = PR_TRUE;
00168     if ((!unbuffered()) && (!ebuf())){
00169         char * sbuf = new char[STRM_BUFSIZ];
00170         if (!sbuf)
00171             unbuffered(1);
00172         else{
00173                      _allocated = PR_TRUE;
00174             streambuf::setb(sbuf,sbuf+STRM_BUFSIZ,0);
00175               }
00176     }
00177     if (mode & ios::ate){
00178         if (seekoff(0,ios::end,mode)==EOF){
00179             close();
00180             return 0;
00181         }
00182     }
00183     return this;
00184 }
00185 
00186 PRfilebuf*    
00187 PRfilebuf::attach(PRFileDesc *fd)
00188 {
00189     _opened = PR_FALSE;
00190     _fd = fd;
00191     return this;
00192 }
00193 
00194 int    
00195 PRfilebuf::overflow(int c)
00196 {
00197     if (allocate()==EOF)        // make sure there is a reserve area
00198         return EOF;
00199     if (PRfilebuf::sync()==EOF) // sync before new buffer created below
00200         return EOF;
00201 
00202     if (!unbuffered())
00203         setp(base(),ebuf());
00204 
00205     if (c!=EOF){
00206         if ((!unbuffered()) && (pptr() < epptr())) // guard against recursion
00207             sputc(c);
00208         else{
00209             if (PR_Write(_fd, &c, 1)!=1)
00210                 return(EOF);
00211         }
00212     }
00213     return(1);  // return something other than EOF if successful
00214 }
00215 
00216 int    
00217 PRfilebuf::underflow()
00218 {
00219     int count;
00220     unsigned char tbuf;
00221 
00222     if (in_avail())
00223         return (int)(unsigned char) *gptr();
00224 
00225     if (allocate()==EOF)        // make sure there is a reserve area
00226         return EOF;
00227     if (PRfilebuf::sync()==EOF)
00228         return EOF;
00229 
00230     if (unbuffered())
00231         {
00232         if (PR_Read(_fd,(void *)&tbuf,1)<=0)
00233             return EOF;
00234         return (int)tbuf;
00235         }
00236 
00237     if ((count=PR_Read(_fd,(void *)base(),blen())) <= 0)
00238         return EOF;     // reached EOF
00239     setg(base(),base(),base()+count);
00240     return (int)(unsigned char) *gptr();
00241 }
00242 
00243 streambuf*    
00244 PRfilebuf::setbuf(char *buffptr, PRstreambuflen bufflen)
00245 {
00246     if (is_open() && (ebuf()))
00247         return 0;
00248     if ((!buffptr) || (bufflen <= 0))
00249         unbuffered(1);
00250     else
00251         setb(buffptr, buffptr+bufflen, 0);
00252     return this;
00253 }
00254 
00255 streampos     
00256 PRfilebuf::seekoff(streamoff offset, ios::seek_dir dir, int /* mode */)
00257 {
00258     if (PR_GetDescType(_fd) == PR_DESC_FILE){
00259         PRSeekWhence fdir;
00260         PRInt32 retpos;
00261         switch (dir) {
00262             case ios::beg :
00263                 fdir = PR_SEEK_SET;
00264                 break;
00265             case ios::cur :
00266                 fdir = PR_SEEK_CUR;
00267                 break;
00268             case ios::end :
00269                 fdir = PR_SEEK_END;
00270                 break;
00271             default:
00272             // error
00273                 return(EOF);
00274             }
00275 
00276         if (PRfilebuf::sync()==EOF)
00277             return EOF;
00278         if ((retpos=PR_Seek(_fd, offset, fdir))==-1L)
00279             return (EOF);
00280         return((streampos)retpos);
00281     }else
00282         return (EOF);
00283 }
00284 
00285 
00286 int 
00287 PRfilebuf::sync()
00288 {
00289     PRInt32 count; 
00290 
00291     if (_fd==0)
00292         return(EOF);
00293 
00294     if (!unbuffered()){
00295         // Sync write area
00296         if ((count=out_waiting())!=0){
00297             PRInt32 nout;
00298             if ((nout =PR_Write(_fd,
00299                                (void *) pbase(),
00300                                (unsigned int)count)) != count){
00301                 if (nout > 0) {
00302                     // should set _pptr -= nout
00303                     pbump(-(int)nout);
00304                     memmove(pbase(), pbase()+nout, (int)(count-nout));
00305                 }
00306                 return(EOF);
00307             }
00308         }
00309         setp(0,0); // empty put area
00310 
00311         if (PR_GetDescType(_fd) == PR_DESC_FILE){
00312             // Sockets can't seek; don't need this
00313             if ((count=in_avail()) > 0){
00314                 if (PR_Seek(_fd, -count, PR_SEEK_CUR)!=-1L)
00315                 {
00316                     return (EOF);
00317                 }
00318             }
00319         }
00320         setg(0,0,0); // empty get area
00321     }
00322     return(0);
00323 }
00324 
00325 PRfilebuf * 
00326 PRfilebuf::close()
00327 {
00328     int retval;
00329     if (_fd==0)
00330         return 0;
00331 
00332     retval = sync();
00333 
00334     if ((PR_Close(_fd)==0) || (retval==EOF))
00335         return 0;
00336     _fd = 0;
00337     return this;
00338 }
00339 
00340 PRifstream::PRifstream():
00341 istream(new PRfilebuf)
00342 {
00343     _PRSTR_DELBUF(0);
00344 }
00345 
00346 PRifstream::PRifstream(PRFileDesc *fd):
00347 istream(new PRfilebuf(fd))
00348 {
00349     _PRSTR_DELBUF(0);
00350 }
00351 
00352 PRifstream::PRifstream(PRFileDesc *fd, char *buff, int bufflen):
00353 istream(new PRfilebuf(fd, buff, bufflen))
00354 {
00355     _PRSTR_DELBUF(0);
00356 }
00357 
00358 PRifstream::PRifstream(const char * name, int mode, int flags):
00359 istream(new PRfilebuf)
00360 {
00361     _PRSTR_DELBUF(0);
00362     if (!rdbuf()->open(name, (mode|ios::in), flags))
00363         clear(rdstate() | ios::failbit);
00364 }
00365 
00366 PRifstream::~PRifstream()
00367 {
00368        sync();
00369 
00370        delete rdbuf();
00371 #ifdef _PRSTR_BP
00372        _PRSTR_BP = 0;
00373 #endif
00374 }
00375 
00376 streambuf * 
00377 PRifstream::setbuf(char * ptr, int len)
00378 {
00379     if ((is_open()) || (!(rdbuf()->setbuf(ptr, len)))){
00380         clear(rdstate() | ios::failbit);
00381         return 0;
00382     }
00383     return rdbuf();
00384 }
00385 
00386 void 
00387 PRifstream::attach(PRFileDesc *fd)
00388 {
00389     if (!(rdbuf()->attach(fd)))
00390         clear(rdstate() | ios::failbit);
00391 }
00392 
00393 void 
00394 PRifstream::open(const char * name, int mode, int flags)
00395 {
00396     if (is_open() || !(rdbuf()->open(name, (mode|ios::in), flags)))
00397         clear(rdstate() | ios::failbit);
00398 }
00399 
00400 void 
00401 PRifstream::close()
00402 {
00403     clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit));
00404 }
00405 
00406 PRofstream::PRofstream():
00407 ostream(new PRfilebuf)
00408 {
00409     _PRSTR_DELBUF(0);
00410 }
00411 
00412 PRofstream::PRofstream(PRFileDesc *fd):
00413 ostream(new PRfilebuf(fd))
00414 {
00415     _PRSTR_DELBUF(0);
00416 }
00417 
00418 PRofstream::PRofstream(PRFileDesc *fd, char *buff, int bufflen):
00419 ostream(new PRfilebuf(fd, buff, bufflen))
00420 {
00421     _PRSTR_DELBUF(0);
00422 }
00423 
00424 PRofstream::PRofstream(const char *name, int mode, int flags):
00425 ostream(new PRfilebuf)
00426 {
00427     _PRSTR_DELBUF(0);
00428     if (!rdbuf()->open(name, (mode|ios::out), flags))
00429         clear(rdstate() | ios::failbit);
00430 }
00431 
00432 PRofstream::~PRofstream()
00433 {
00434        flush();
00435 
00436        delete rdbuf();
00437 #ifdef _PRSTR_BP
00438        _PRSTR_BP = 0;
00439 #endif
00440 }
00441 
00442 streambuf * 
00443 PRofstream::setbuf(char * ptr, int len)
00444 {
00445     if ((is_open()) || (!(rdbuf()->setbuf(ptr, len)))){
00446         clear(rdstate() | ios::failbit);
00447         return 0;
00448     }
00449     return rdbuf();
00450 }
00451 
00452 void 
00453 PRofstream::attach(PRFileDesc *fd)
00454 {
00455     if (!(rdbuf()->attach(fd)))
00456         clear(rdstate() | ios::failbit);
00457 }
00458 
00459 void 
00460 PRofstream::open(const char * name, int mode, int flags)
00461 {
00462     if (is_open() || !(rdbuf()->open(name, (mode|ios::out), flags)))
00463         clear(rdstate() | ios::failbit);
00464 }
00465 
00466 void 
00467 PRofstream::close()
00468 {
00469     clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit));
00470 }
00471 
00472 PRfstream::PRfstream():
00473 iostream(new PRfilebuf)
00474 {
00475        _PRSTR_DELBUF_C(istream, 0);
00476        _PRSTR_DELBUF_C(ostream, 0);
00477 }
00478 
00479 PRfstream::PRfstream(PRFileDesc *fd):
00480 iostream(new PRfilebuf(fd))
00481 {
00482        _PRSTR_DELBUF_C(istream, 0);
00483        _PRSTR_DELBUF_C(ostream, 0);
00484 }
00485 
00486 PRfstream::PRfstream(PRFileDesc *fd, char *buff, int bufflen):
00487 iostream(new PRfilebuf(fd, buff, bufflen))
00488 {
00489        _PRSTR_DELBUF_C(istream, 0);
00490        _PRSTR_DELBUF_C(ostream, 0);
00491 }
00492 
00493 PRfstream::PRfstream(const char *name, int mode, int flags):
00494 iostream(new PRfilebuf)
00495 {
00496        _PRSTR_DELBUF_C(istream, 0);
00497        _PRSTR_DELBUF_C(ostream, 0);
00498     if (!rdbuf()->open(name, (mode|(ios::in|ios::out)), flags))
00499         clear(rdstate() | ios::failbit);
00500 }
00501 
00502 PRfstream::~PRfstream()
00503 {
00504        sync();
00505        flush();
00506 
00507        delete rdbuf();
00508 #ifdef _PRSTR_BP
00509        istream::_PRSTR_BP = 0;
00510        ostream::_PRSTR_BP = 0;
00511 #endif
00512 }
00513 
00514 streambuf * 
00515 PRfstream::setbuf(char * ptr, int len)
00516 {
00517     if ((is_open()) || (!(rdbuf()->setbuf(ptr, len)))){
00518         clear(rdstate() | ios::failbit);
00519         return 0;
00520     }
00521     return rdbuf();
00522 }
00523 
00524 void 
00525 PRfstream::attach(PRFileDesc *fd)
00526 {
00527     if (!(rdbuf()->attach(fd)))
00528         clear(rdstate() | ios::failbit);
00529 }
00530 
00531 void 
00532 PRfstream::open(const char * name, int mode, int flags)
00533 {
00534     if (is_open() || !(rdbuf()->open(name, (mode|(ios::in|ios::out)), flags)))
00535         clear(rdstate() | ios::failbit);
00536 }
00537 
00538 void 
00539 PRfstream::close()
00540 {
00541     clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit));
00542 }
00543 
00544 #else
00545 
00546 // fix it sometime
00547 
00548 int fix_prfstreams ()       {      return 0; }
00549 
00550 #endif