1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is the Netscape Portable Runtime (NSPR).
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
39 * Robin J. Maxwell 11-22-96
43 #include <string.h> // memmove
46 // Definition of macros _PRSTR_BP, _PRSTR_DELBUF, and _PRSTR_DELBUF_C.
48 // _PRSTR_BP is the protected member of class ios that is returned
49 // by the public method rdbuf().
51 // _PRSTR_DELBUF is the method or data member of class ios, if available,
52 // with which we can ensure that the ios destructor does not delete
53 // the associated streambuf. If such a method or data member does not
54 // exist, define _PRSTR_DELBUF to be empty.
56 // _PRSTR_DELBUF_C is just _PRSTR_DELBUF qualified by a base class.
60 #define _PRSTR_BP _strbuf
61 #define _PRSTR_DELBUF(x) /* as nothing */
62 #define _PRSTR_DELBUF_C(c, x) /* as nothing */
65 #define _PRSTR_DELBUF(x) delbuf(x)
66 #define _PRSTR_DELBUF_C(c, x) c::_PRSTR_DELBUF(x)
69 #define _PRSTR_DELBUF(x) /* as nothing */
70 #define _PRSTR_DELBUF_C(c, x) /* as nothing */
72 #define _PRSTR_BP m_psb
73 #define _PRSTR_DELBUF(x) /* as nothing */
74 #define _PRSTR_DELBUF_C(c, x) /* as nothing */
76 #define PRFSTREAMS_BROKEN
79 // Unix compilers don't believe in encapsulation
80 // At least on Solaris this is also ignored
81 #define _PRSTR_DELBUF(x) delbuf = x
82 #define _PRSTR_DELBUF_C(c, x) c::_PRSTR_DELBUF(x)
85 const PRIntn STRM_BUFSIZ
= 8192;
87 #if !defined (PRFSTREAMS_BROKEN)
89 PRfilebuf::PRfilebuf():
96 PRfilebuf::PRfilebuf(PRFileDesc
*fd
):
104 PRfilebuf::PRfilebuf(PRFileDesc
*fd
, char * buffptr
, int bufflen
):
109 PRfilebuf::setbuf(buffptr
, bufflen
);
112 PRfilebuf::~PRfilebuf()
123 PRfilebuf::open(const char *name
, int mode
, int flags
)
126 return 0; // error if already open
128 // translate mode argument
129 if (!(mode
& ios::nocreate
))
130 PRmode
|= PR_CREATE_FILE
;
131 //if (mode & ios::noreplace)
133 if (mode
& ios::app
){
137 if (mode
& ios::trunc
){
138 mode
|= ios::out
; // IMPLIED
139 PRmode
|= PR_TRUNCATE
;
141 if (mode
& ios::out
){
146 if (!(mode
& (ios::in
|ios::app
|ios::ate
|ios::noreplace
))){
147 mode
|= ios::trunc
; // IMPLIED
148 PRmode
|= PR_TRUNCATE
;
150 }else if (mode
& ios::in
)
153 return 0; // error if not ios:in or ios::out
157 // The usual portable across unix crap...
158 // NT gets a hokey piece of junk layer that prevents
159 // access to the API.
161 _fd
= PR_Open(name
, PRmode
, PRmode
);
163 _fd
= PR_Open(name
, PRmode
, flags
);
168 if ((!unbuffered()) && (!ebuf())){
169 char * sbuf
= new char[STRM_BUFSIZ
];
173 _allocated
= PR_TRUE
;
174 streambuf::setb(sbuf
,sbuf
+STRM_BUFSIZ
,0);
177 if (mode
& ios::ate
){
178 if (seekoff(0,ios::end
,mode
)==EOF
){
187 PRfilebuf::attach(PRFileDesc
*fd
)
195 PRfilebuf::overflow(int c
)
197 if (allocate()==EOF
) // make sure there is a reserve area
199 if (PRfilebuf::sync()==EOF
) // sync before new buffer created below
206 if ((!unbuffered()) && (pptr() < epptr())) // guard against recursion
209 if (PR_Write(_fd
, &c
, 1)!=1)
213 return(1); // return something other than EOF if successful
217 PRfilebuf::underflow()
223 return (int)(unsigned char) *gptr();
225 if (allocate()==EOF
) // make sure there is a reserve area
227 if (PRfilebuf::sync()==EOF
)
232 if (PR_Read(_fd
,(void *)&tbuf
,1)<=0)
237 if ((count
=PR_Read(_fd
,(void *)base(),blen())) <= 0)
238 return EOF
; // reached EOF
239 setg(base(),base(),base()+count
);
240 return (int)(unsigned char) *gptr();
244 PRfilebuf::setbuf(char *buffptr
, PRstreambuflen bufflen
)
246 if (is_open() && (ebuf()))
248 if ((!buffptr
) || (bufflen
<= 0))
251 setb(buffptr
, buffptr
+bufflen
, 0);
256 PRfilebuf::seekoff(streamoff offset
, ios::seek_dir dir
, int /* mode */)
258 if (PR_GetDescType(_fd
) == PR_DESC_FILE
){
276 if (PRfilebuf::sync()==EOF
)
278 if ((retpos
=PR_Seek(_fd
, offset
, fdir
))==-1L)
280 return((streampos
)retpos
);
296 if ((count
=out_waiting())!=0){
298 if ((nout
=PR_Write(_fd
,
300 (unsigned int)count
)) != count
){
302 // should set _pptr -= nout
304 memmove(pbase(), pbase()+nout
, (int)(count
-nout
));
309 setp(0,0); // empty put area
311 if (PR_GetDescType(_fd
) == PR_DESC_FILE
){
312 // Sockets can't seek; don't need this
313 if ((count
=in_avail()) > 0){
314 if (PR_Seek(_fd
, -count
, PR_SEEK_CUR
)!=-1L)
320 setg(0,0,0); // empty get area
334 if ((PR_Close(_fd
)==0) || (retval
==EOF
))
340 PRifstream::PRifstream():
341 istream(new PRfilebuf
)
346 PRifstream::PRifstream(PRFileDesc
*fd
):
347 istream(new PRfilebuf(fd
))
352 PRifstream::PRifstream(PRFileDesc
*fd
, char *buff
, int bufflen
):
353 istream(new PRfilebuf(fd
, buff
, bufflen
))
358 PRifstream::PRifstream(const char * name
, int mode
, int flags
):
359 istream(new PRfilebuf
)
362 if (!rdbuf()->open(name
, (mode
|ios::in
), flags
))
363 clear(rdstate() | ios::failbit
);
366 PRifstream::~PRifstream()
377 PRifstream::setbuf(char * ptr
, int len
)
379 if ((is_open()) || (!(rdbuf()->setbuf(ptr
, len
)))){
380 clear(rdstate() | ios::failbit
);
387 PRifstream::attach(PRFileDesc
*fd
)
389 if (!(rdbuf()->attach(fd
)))
390 clear(rdstate() | ios::failbit
);
394 PRifstream::open(const char * name
, int mode
, int flags
)
396 if (is_open() || !(rdbuf()->open(name
, (mode
|ios::in
), flags
)))
397 clear(rdstate() | ios::failbit
);
403 clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit
));
406 PRofstream::PRofstream():
407 ostream(new PRfilebuf
)
412 PRofstream::PRofstream(PRFileDesc
*fd
):
413 ostream(new PRfilebuf(fd
))
418 PRofstream::PRofstream(PRFileDesc
*fd
, char *buff
, int bufflen
):
419 ostream(new PRfilebuf(fd
, buff
, bufflen
))
424 PRofstream::PRofstream(const char *name
, int mode
, int flags
):
425 ostream(new PRfilebuf
)
428 if (!rdbuf()->open(name
, (mode
|ios::out
), flags
))
429 clear(rdstate() | ios::failbit
);
432 PRofstream::~PRofstream()
443 PRofstream::setbuf(char * ptr
, int len
)
445 if ((is_open()) || (!(rdbuf()->setbuf(ptr
, len
)))){
446 clear(rdstate() | ios::failbit
);
453 PRofstream::attach(PRFileDesc
*fd
)
455 if (!(rdbuf()->attach(fd
)))
456 clear(rdstate() | ios::failbit
);
460 PRofstream::open(const char * name
, int mode
, int flags
)
462 if (is_open() || !(rdbuf()->open(name
, (mode
|ios::out
), flags
)))
463 clear(rdstate() | ios::failbit
);
469 clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit
));
472 PRfstream::PRfstream():
473 iostream(new PRfilebuf
)
475 _PRSTR_DELBUF_C(istream
, 0);
476 _PRSTR_DELBUF_C(ostream
, 0);
479 PRfstream::PRfstream(PRFileDesc
*fd
):
480 iostream(new PRfilebuf(fd
))
482 _PRSTR_DELBUF_C(istream
, 0);
483 _PRSTR_DELBUF_C(ostream
, 0);
486 PRfstream::PRfstream(PRFileDesc
*fd
, char *buff
, int bufflen
):
487 iostream(new PRfilebuf(fd
, buff
, bufflen
))
489 _PRSTR_DELBUF_C(istream
, 0);
490 _PRSTR_DELBUF_C(ostream
, 0);
493 PRfstream::PRfstream(const char *name
, int mode
, int flags
):
494 iostream(new PRfilebuf
)
496 _PRSTR_DELBUF_C(istream
, 0);
497 _PRSTR_DELBUF_C(ostream
, 0);
498 if (!rdbuf()->open(name
, (mode
|(ios::in
|ios::out
)), flags
))
499 clear(rdstate() | ios::failbit
);
502 PRfstream::~PRfstream()
509 istream::_PRSTR_BP
= 0;
510 ostream::_PRSTR_BP
= 0;
515 PRfstream::setbuf(char * ptr
, int len
)
517 if ((is_open()) || (!(rdbuf()->setbuf(ptr
, len
)))){
518 clear(rdstate() | ios::failbit
);
525 PRfstream::attach(PRFileDesc
*fd
)
527 if (!(rdbuf()->attach(fd
)))
528 clear(rdstate() | ios::failbit
);
532 PRfstream::open(const char * name
, int mode
, int flags
)
534 if (is_open() || !(rdbuf()->open(name
, (mode
|(ios::in
|ios::out
)), flags
)))
535 clear(rdstate() | ios::failbit
);
541 clear((rdbuf()->close()) ? 0 : (rdstate() | ios::failbit
));
548 int fix_prfstreams () { return 0; }