home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /*
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
- /*
- * Robin J. Maxwell 11-22-96
- */
-
- #include "prstrms.h"
- #ifdef SVR4
- #include <string.h> // memmove
- #endif
-
- //
- // Definition of macros _PRSTR_BP, _PRSTR_DELBUF, and _PRSTR_DELBUF_C.
- //
- // _PRSTR_BP is the protected member of class ios that is returned
- // by the public method rdbuf().
- //
- // _PRSTR_DELBUF is the method or data member of class ios, if available,
- // with which we can ensure that the ios destructor does not delete
- // the associated streambuf. If such a method or data member does not
- // exist, define _PRSTR_DELBUF to be empty.
- //
- // _PRSTR_DELBUF_C is just _PRSTR_DELBUF qualified by a base class.
- //
-
- #if defined(__GNUC__)
- #define _PRSTR_BP _strbuf
- #define _PRSTR_DELBUF(x) /* as nothing */
- #define _PRSTR_DELBUF_C(c, x) /* as nothing */
- #elif defined(WIN32)
- #define _PRSTR_BP bp
- #define _PRSTR_DELBUF(x) delbuf(x)
- #define _PRSTR_DELBUF_C(c, x) c::_PRSTR_DELBUF(x)
- #elif defined(OSF1)
- #define _PRSTR_BP m_psb
- #define _PRSTR_DELBUF(x) /* as nothing */
- #define _PRSTR_DELBUF_C(c, x) /* as nothing */
- #else
- #define _PRSTR_BP bp
- // Unix compilers don't believe in encapsulation
- // At least on Solaris this is also ignored
- #define _PRSTR_DELBUF(x) delbuf = x
- #define _PRSTR_DELBUF_C(c, x) c::_PRSTR_DELBUF(x)
- #endif
-
- const PRIntn STRM_BUFSIZ = 8192;
-
- #if !defined (PRFSTREAMS_BROKEN)
-
- PRfilebuf::PRfilebuf():
- _fd(0),
- _opened(PR_FALSE),
- _allocated(PR_FALSE)
- {
- }
-
- PRfilebuf::PRfilebuf(PRFileDesc *fd):
- streambuf(),
- _fd(fd),
- _opened(PR_FALSE),
- _allocated(PR_FALSE)
- {
- }
-
- PRfilebuf::PRfilebuf(PRFileDesc *fd, char * buffptr, int bufflen):
- _fd(fd),
- _opened(PR_FALSE),
- _allocated(PR_FALSE)
- {
- PRfilebuf::setbuf(buffptr, bufflen);
- }
-
- PRfilebuf::~PRfilebuf()
- {
- if (_opened){
- close();
- }else
- sync();
- if (_allocated)
- delete base();
- }
-
- PRfilebuf*
- PRfilebuf::open(const char *name, int mode, int flags)
- {
- if (_fd != 0)
- return 0; // error if already open
- PRIntn PRmode = 0;
- // translate mode argument
- if (!(mode & ios::nocreate))
- PRmode |= PR_CREATE_FILE;
- //if (mode & ios::noreplace)
- // PRmode |= O_EXCL;
- if (mode & ios::app){
- mode |= ios::out;
- PRmode |= PR_APPEND;
- }
- if (mode & ios::trunc){
- mode |= ios::out; // IMPLIED
- PRmode |= PR_TRUNCATE;
- }
- if (mode & ios::out){
- if (mode & ios::in)
- PRmode |= PR_RDWR;
- else
- PRmode |= PR_WRONLY;
- if (!(mode & (ios::in|ios::app|ios::ate|ios::noreplace))){
- mode |= ios::trunc; // IMPLIED
- PRmode |= PR_TRUNCATE;
- }
- }else if (mode & ios::in)
- PRmode |= PR_RDONLY;
- else
- return 0; // error if not ios:in or ios::out
-
-
- //
- // The usual portable across unix crap...
- // NT gets a hokey piece of junk layer that prevents
- // access to the API.
- #ifdef WIN32
- _fd = PR_Open(name, PRmode, PRmode);
- #else
- _fd = PR_Open(name, PRmode, flags);
- #endif
- if (_fd == 0)
- return 0;
- _opened = PR_TRUE;
- if ((!unbuffered()) && (!ebuf())){
- char * sbuf = new char[STRM_BUFSIZ];
- if (!sbuf)
- unbuffered(1);
- else{
- _allocated = PR_TRUE;
- streambuf::setb(sbuf,sbuf+STRM_BUFSIZ,0);
- }
- }
- if (mode & ios::ate){
- if (seekoff(0,ios::end,mode)==EOF){
- close();
- return 0;
- }
- }
- return this;
- }
-
- PRfilebuf*
- PRfilebuf::attach(PRFileDesc *fd)
- {
- _opened = PR_FALSE;
- _fd = fd;
- return this;
- }
-
- int
- PRfilebuf::overflow(int c)
- {
- if (allocate()==EOF) // make sure there is a reserve area
- return EOF;
- if (PRfilebuf::sync()==EOF) // sync before new buffer created below
- return EOF;
-
- if (!unbuffered())
- setp(base(),ebuf());
-
- if (c!=EOF){
- if ((!unbuffered()) && (pptr() < epptr())) // guard against recursion
- sputc(c);
- else{
- if (PR_Write(_fd, &c, 1)!=1)
- return(EOF);
- }
- }
- return(1); // return something other than EOF if successful
- }
-
- int
- PRfilebuf::underflow()
- {
- int count;
- unsigned char tbuf;
-
- if (in_avail())
- return (int)(unsigned char) *gptr();
-
- if (allocate()==EOF) // make sure there is a reserve area
- return EOF;
- if (PRfilebuf::sync()==EOF)
- return EOF;
-
- if (unbuffered())
- {
- if (PR_Read(_fd,(void *)&tbuf,1)<=0)
- return EOF;
- return (int)tbuf;
- }
-
- if ((count=PR_Read(_fd,(void *)base(),blen())) <= 0)
- return EOF; // reached EOF
- setg(base(),base(),base()+count);
- return (int)(unsigned char) *gptr();
- }
-
- streambuf*
- PRfilebuf::setbuf(char *buffptr, int bufflen)
- {
- if (is_open() && (ebuf()))
- return 0;
- if ((!buffptr) || (bufflen <= 0))
- unbuffered(1);
- else
- setb(buffptr, buffptr+bufflen, 0);
- return this;
- }
-
- streampos
- PRfilebuf::seekoff(streamoff offset, ios::seek_dir dir, int /* mode */)
- {
- if (PR_GetDescType(_fd) == PR_DESC_FILE){
- PRSeekWhence fdir;
- PRInt32 retpos;
- switch (dir) {
- case ios::beg :
- fdir = PR_SEEK_SET;
- break;
- case ios::cur :
- fdir = PR_SEEK_CUR;
- break;
- case ios::end :
- fdir = PR_SEEK_END;
- break;
- default:
- // error
- return(EOF);
- }
-
- if (PRfilebuf::sync()==EOF)
- return EOF;
- if ((retpos=PR_Seek(_fd, offset, fdir))==-1L)
- return (EOF);
- return((streampos)retpos);
- }else
- return (EOF);
- }
-
-
- int
- PRfilebuf::sync()
- {
- PRInt32 count;
-
- if (_fd==0)
- return(EOF);
-
- if (!unbuffered()){
- // Sync write area
- if ((count=out_waiting())!=0){
- PRInt32 nout;
- if ((nout =PR_Write(_fd,
- (void *) pbase(),
- (unsigned int)count)) != count){
- if (nout > 0) {
- // should set _pptr -= nout
- pbump(-(int)nout);
- memmove(pbase(), pbase()+nout, (int)(count-nout));
- }
- return(EOF);
- }
- }
- setp(0,0); // empty put area
-
- if (PR_GetDescType(_fd) == PR_DESC_FILE){
- // Sockets can't seek; don't need this
- if ((count=in_avail()) > 0){
- if (PR_Seek(_fd, -count, PR_SEEK_CUR)!=-1L)
- {
- return (EOF);
- }
- }
- }
- setg(0,0,0); // empty get area
- }
- return(0);
- }
-
- PRfilebuf *
- PRfilebuf::close()
- {
- int retval;
- if (_fd==0)
- return 0;
-
- retval = sync();
-
- if ((PR_Close(_fd)==0) || (retval==EOF))
- return 0;
- _fd = 0;
- return this;
- }
-
- PRifstream::PRifstream():
- istream(new PRfilebuf)
- {
- _PRSTR_DELBUF(0);
- }
-
- PRifstream::PRifstream(PRFileDesc *fd):
- istream(new PRfilebuf(fd))
- {
- _PRSTR_DELBUF(0);
- }
-
- PRifstream::PRifstream(PRFileDesc *fd, char *buff, int bufflen):
- istream(new PRfilebuf(fd, buff, bufflen))
- {
- _PRSTR_DELBUF(0);
- }
-
- PRifstream::PRifstream(const char * name, int mode, int flags):
- istream(new PRfilebuf)
- {
- _PRSTR_DELBUF(0);
- if (!rdbuf()->open(name, (mode|ios::in), flags))
- clear(rdstate() | ios::failbit);
- }
-
- PRifstream::~PRifstream()
- {
- sync();
-
- delete rdbuf();
- #ifdef _PRSTR_BP
- _PRSTR_BP = 0;
- #endif
- }
-
- streambuf *
- PRifstream::setbuf(char * ptr, int len)
- {
- if ((is_open()) || (!(rdbuf()->setbuf(ptr, len)))){
- clear(rdstate() | ios::failbit);
- return 0;
- }
- return rdbuf();
- }
-
- void
- PRifstream::attach(PRFileDesc *fd)
- {
- if (!(rdbuf()->attach(fd)))
- clear(rdstate() | ios::failbit);
- }
-
- void
- PRifstream::open(const char * name, int mode, int flags)
- {
- if (is_open() || !(rdbuf()->open(name, (mode|ios::in), flags)))
- clear(rdstate() | ios::failbit);
- }
-
- void
- PRifstream::close()
- {
- clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit));
- }
-
- PRofstream::PRofstream():
- ostream(new PRfilebuf)
- {
- _PRSTR_DELBUF(0);
- }
-
- PRofstream::PRofstream(PRFileDesc *fd):
- ostream(new PRfilebuf(fd))
- {
- _PRSTR_DELBUF(0);
- }
-
- PRofstream::PRofstream(PRFileDesc *fd, char *buff, int bufflen):
- ostream(new PRfilebuf(fd, buff, bufflen))
- {
- _PRSTR_DELBUF(0);
- }
-
- PRofstream::PRofstream(const char *name, int mode, int flags):
- ostream(new PRfilebuf)
- {
- _PRSTR_DELBUF(0);
- if (!rdbuf()->open(name, (mode|ios::out), flags))
- clear(rdstate() | ios::failbit);
- }
-
- PRofstream::~PRofstream()
- {
- flush();
-
- delete rdbuf();
- #ifdef _PRSTR_BP
- _PRSTR_BP = 0;
- #endif
- }
-
- streambuf *
- PRofstream::setbuf(char * ptr, int len)
- {
- if ((is_open()) || (!(rdbuf()->setbuf(ptr, len)))){
- clear(rdstate() | ios::failbit);
- return 0;
- }
- return rdbuf();
- }
-
- void
- PRofstream::attach(PRFileDesc *fd)
- {
- if (!(rdbuf()->attach(fd)))
- clear(rdstate() | ios::failbit);
- }
-
- void
- PRofstream::open(const char * name, int mode, int flags)
- {
- if (is_open() || !(rdbuf()->open(name, (mode|ios::out), flags)))
- clear(rdstate() | ios::failbit);
- }
-
- void
- PRofstream::close()
- {
- clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit));
- }
-
- PRfstream::PRfstream():
- iostream(new PRfilebuf)
- {
- _PRSTR_DELBUF_C(istream, 0);
- _PRSTR_DELBUF_C(ostream, 0);
- }
-
- PRfstream::PRfstream(PRFileDesc *fd):
- iostream(new PRfilebuf(fd))
- {
- _PRSTR_DELBUF_C(istream, 0);
- _PRSTR_DELBUF_C(ostream, 0);
- }
-
- PRfstream::PRfstream(PRFileDesc *fd, char *buff, int bufflen):
- iostream(new PRfilebuf(fd, buff, bufflen))
- {
- _PRSTR_DELBUF_C(istream, 0);
- _PRSTR_DELBUF_C(ostream, 0);
- }
-
- PRfstream::PRfstream(const char *name, int mode, int flags):
- iostream(new PRfilebuf)
- {
- _PRSTR_DELBUF_C(istream, 0);
- _PRSTR_DELBUF_C(ostream, 0);
- if (!rdbuf()->open(name, (mode|(ios::in|ios::out)), flags))
- clear(rdstate() | ios::failbit);
- }
-
- PRfstream::~PRfstream()
- {
- sync();
- flush();
-
- delete rdbuf();
- #ifdef _PRSTR_BP
- istream::_PRSTR_BP = 0;
- ostream::_PRSTR_BP = 0;
- #endif
- }
-
- streambuf *
- PRfstream::setbuf(char * ptr, int len)
- {
- if ((is_open()) || (!(rdbuf()->setbuf(ptr, len)))){
- clear(rdstate() | ios::failbit);
- return 0;
- }
- return rdbuf();
- }
-
- void
- PRfstream::attach(PRFileDesc *fd)
- {
- if (!(rdbuf()->attach(fd)))
- clear(rdstate() | ios::failbit);
- }
-
- void
- PRfstream::open(const char * name, int mode, int flags)
- {
- if (is_open() || !(rdbuf()->open(name, (mode|(ios::in|ios::out)), flags)))
- clear(rdstate() | ios::failbit);
- }
-
- void
- PRfstream::close()
- {
- clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit));
- }
-
- #else
-
- // fix it sometime
-
- int fix_prfstreams () { return 0; }
-
- #endif
-