diff options
Diffstat (limited to 'nsprpub/lib/prstreams')
-rw-r--r-- | nsprpub/lib/prstreams/Makefile.in | 148 | ||||
-rw-r--r-- | nsprpub/lib/prstreams/plvrsion.c | 93 | ||||
-rw-r--r-- | nsprpub/lib/prstreams/prstrms.cpp | 516 | ||||
-rw-r--r-- | nsprpub/lib/prstreams/prstrms.h | 140 | ||||
-rw-r--r-- | nsprpub/lib/prstreams/prstrms.rc | 69 | ||||
-rw-r--r-- | nsprpub/lib/prstreams/tests/testprstrm/Makefile.in | 168 | ||||
-rw-r--r-- | nsprpub/lib/prstreams/tests/testprstrm/testprstrm.cpp | 171 |
7 files changed, 1305 insertions, 0 deletions
diff --git a/nsprpub/lib/prstreams/Makefile.in b/nsprpub/lib/prstreams/Makefile.in new file mode 100644 index 000000000..aeb29440f --- /dev/null +++ b/nsprpub/lib/prstreams/Makefile.in @@ -0,0 +1,148 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#! gmake + +MOD_DEPTH = ../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(MOD_DEPTH)/config/autoconf.mk + +include $(topsrcdir)/config/config.mk + +ifeq ($(OS_ARCH), IRIX) + ifneq ($(OS_RELEASE),5.3) + CCC_ONLY_FLAGS += -exceptions + endif +endif + +ifeq ($(OS_ARCH), BeOS) + CFLAGS += -frtti -fexceptions +endif + +INCLUDES = -I$(dist_includedir) + +HEADERS = $(wildcard $(srcdir)/*.h) + +CSRCS = \ + plvrsion.c \ + $(NULL) + +CXXSRCS = \ + prstrms.cpp \ + $(NULL) + +OBJS = $(addprefix $(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX)) $(CXXSRCS:.cpp=.$(OBJ_SUFFIX))) + +ifeq ($(OS_ARCH), WINNT) + RES=$(OBJDIR)/prstrms.res + RESNAME=prstrms.rc + OS_LIBS = user32.lib +else + ifeq ($(OS_ARCH),OS2) + OS_LIBS = -lstdcpp + else + ifeq ($(OS_ARCH), AIX) + ifeq ($(OS_RELEASE), 4.1) + ifeq ($(CLASSIC_NSPR),1) + OS_LIBS += -lC -lc + else + OS_LIBS += -lC_r -lc_r + endif + else + # makeC++SharedLib(_r) is in either /usr/lpp/xlC/bin + # or /usr/ibmcxx/bin. + ifeq ($(CLASSIC_NSPR),1) + MKSHLIB = makeC++SharedLib -p 0 + else + MKSHLIB = makeC++SharedLib_r -p 0 + endif + OS_LIBS += -ldl + endif + endif + endif +endif + +ifeq ($(OS_ARCH),BeOS) + OS_LIBS = -lstdc++.r4 +endif + +ifeq ($(OS_ARCH), UNIXWARE) + OS_LIBS += -lC +endif + +EXTRA_LIBS = $(LIBNSPR) + +# On SCOOS, we can't link with extra libraries when +# we build a shared library. If we do so, the linker doesn't +# complain, but we would run into weird problems at run-time. +# Therefore on these platforms, we link just the object files. +ifeq ($(OS_ARCH),SCOOS) + EXTRA_LIBS = +endif + +ifdef RESOLVE_LINK_SYMBOLS +EXTRA_LIBS += $(OS_LIBS) +endif + +LIBRARY_NAME = prstrms +LIBRARY_VERSION = $(MOD_MAJOR_VERSION) + +RELEASE_HEADERS = $(HEADERS) +RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR) +RELEASE_LIBS = $(TARGETS) + +include $(topsrcdir)/config/rules.mk + +# +# Version information generation (begin) +# +ECHO = echo +TINC = $(OBJDIR)/_pl_bld.h +PROD = $(notdir $(SHARED_LIBRARY)) +NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now +SH_DATE = $(shell date "+%Y-%m-%d %T") +SH_NOW = $(shell $(NOW)) + +ifeq ($(OS_ARCH), WINNT) + SUF = i64 +else + SUF = LL +endif + +$(TINC): + @$(MAKE_OBJDIR) + @$(ECHO) '#define _BUILD_STRING "$(SH_DATE)"' > $(TINC) + @if test ! -z "$(SH_NOW)"; then \ + $(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \ + else \ + true; \ + fi + @$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC) + + +$(OBJDIR)/plvrsion.$(OBJ_SUFFIX): plvrsion.c $(TINC) +ifeq ($(OS_ARCH), WINNT) + $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $< +else + $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $< +endif +# +# Version information generation (end) +# + +export:: $(TARGETS) $(HEADERS) + $(INSTALL) -m 444 $(HEADERS) $(dist_includedir) + $(INSTALL) -m 444 $(TARGETS) $(dist_libdir) +ifeq ($(OS_ARCH),OS2) + $(INSTALL) -m 444 $(TARGETS) $(dist_bindir) +endif +ifeq ($(OS_ARCH),HP-UX) +ifdef SHARED_LIBRARY + $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir) +endif +endif diff --git a/nsprpub/lib/prstreams/plvrsion.c b/nsprpub/lib/prstreams/plvrsion.c new file mode 100644 index 000000000..511e4c4f6 --- /dev/null +++ b/nsprpub/lib/prstreams/plvrsion.c @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "prinit.h" +#include "prvrsion.h" + +/************************************************************************/ +/**************************IDENTITY AND VERSIONING***********************/ +/************************************************************************/ +#include "_pl_bld.h" +#if !defined(_BUILD_TIME) +#ifdef HAVE_LONG_LONG +#define _BUILD_TIME 0 +#else +#define _BUILD_TIME {0, 0} +#endif +#endif +#if !defined(_BUILD_STRING) +#define _BUILD_STRING "" +#endif +#if !defined(_PRODUCTION) +#define _PRODUCTION "" +#endif +#if defined(DEBUG) +#define _DEBUG_STRING " (debug)" +#else +#define _DEBUG_STRING "" +#endif + +/* + * A trick to expand the PR_VMAJOR macro before concatenation. + */ +#define CONCAT(x, y) x ## y +#define CONCAT2(x, y) CONCAT(x, y) +#define VERSION_DESC_NAME CONCAT2(prVersionDescription_libprstrms, PR_VMAJOR) + +PRVersionDescription VERSION_DESC_NAME = +{ + /* version */ 2, /* this is the only one supported */ + /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */ + /* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */ + /* vMajor */ PR_VMAJOR, /* NSPR's version number */ + /* vMinor */ PR_VMINOR, /* and minor version */ + /* vPatch */ PR_VPATCH, /* and patch */ + /* beta */ PR_BETA, /* beta build boolean */ +#if defined(DEBUG) + /* debug */ PR_TRUE, /* a debug build */ +#else + /* debug */ PR_FALSE, /* an optomized build */ +#endif + /* special */ PR_FALSE, /* they're all special, but ... */ + /* filename */ _PRODUCTION, /* the produced library name */ + /* description */ "Portable runtime", /* what we are */ + /* security */ "N/A", /* not applicable here */ + /* copywrite */ "Copyright (c) 1998 Netscape Communications Corporation. All Rights Reserved", + /* comment */ "http://www.mozilla.org/MPL/", + /* specialString */ "" +}; + +#ifdef XP_UNIX + +/* + * Version information for the 'ident' and 'what commands + * + * NOTE: the first component of the concatenated rcsid string + * must not end in a '$' to prevent rcs keyword substitution. + */ +static char rcsid[] = "$Header: NSPR " PR_VERSION _DEBUG_STRING + " " _BUILD_STRING " $"; +static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING + " " _BUILD_STRING; + +#endif /* XP_UNIX */ + +PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint() +{ +#ifdef XP_UNIX + /* + * Add dummy references to rcsid and sccsid to prevent them + * from being optimized away as unused variables. + */ + const char *dummy; + + dummy = rcsid; + dummy = sccsid; +#endif + return &VERSION_DESC_NAME; +} /* versionEntryPointType */ + +/* plvrsion.c */ + diff --git a/nsprpub/lib/prstreams/prstrms.cpp b/nsprpub/lib/prstreams/prstrms.cpp new file mode 100644 index 000000000..d601fce23 --- /dev/null +++ b/nsprpub/lib/prstreams/prstrms.cpp @@ -0,0 +1,516 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Robin J. Maxwell 11-22-96 + * Fredrik Roubert <roubert@google.com> 2010-07-23 + * Matt Austern <austern@google.com> 2010-07-23 + */ + +#include "prstrms.h" + +#include <cstdio> +#include <cstring> +#include <ios> +#include <new> + +using std::ios_base; +using std::iostream; +using std::istream; +using std::nothrow; +using std::ostream; +using std::streambuf; +using std::streamsize; + + +PRfilebuf::PRfilebuf(): + _fd(NULL), + _opened(false), + _allocated(false), + _unbuffered(false), + _user_buf(false), + _buf_base(NULL), + _buf_end(NULL) { } + + +PRfilebuf::PRfilebuf(PRFileDesc *fd): + _fd(fd), + _opened(false), + _allocated(false), + _unbuffered(false), + _user_buf(false), + _buf_base(NULL), + _buf_end(NULL) { } + + +PRfilebuf::PRfilebuf(PRFileDesc *fd, char_type *ptr, streamsize len): + _fd(fd), + _opened(false), + _allocated(false), + _unbuffered(false), + _user_buf(false), + _buf_base(NULL), + _buf_end(NULL) +{ + setbuf(ptr, len); +} + + +PRfilebuf::~PRfilebuf() +{ + if (_opened) { + close(); + } else { + sync(); + } + if (_allocated) { + delete _buf_base; + } +} + + +PRfilebuf *PRfilebuf::open( + const char *name, ios_base::openmode flags, PRIntn mode) +{ + if (_fd != NULL) { + return NULL; // Error if already open. + } + + // Translate flags argument. + PRIntn prflags = 0; + bool ate = (flags & ios_base::ate) != 0; + flags &= ~(ios_base::ate | ios_base::binary); + + // TODO: The flag PR_CREATE_FILE should probably be used for the cases + // (out), (out|app), (out|trunc) and (in|out|trunc) as the C++ standard + // specifies that these cases should open files 'as if by using fopen with + // "w"'. But adding that flag here will cause the unit test to leave files + // behind after running (which might or might not be an error in the unit + // test) so the matter needs further investigation before any changes are + // made. The old prstreams implementation used the non-standard flag + // ios::nocreate to control the use of PR_CREATE_FILE. + + if (flags == (ios_base::out)) { + prflags = PR_WRONLY | PR_TRUNCATE; + } else if (flags == (ios_base::out | ios_base::app)) { + prflags = PR_RDWR | PR_APPEND; + } else if (flags == (ios_base::out | ios_base::trunc)) { + prflags = PR_WRONLY | PR_TRUNCATE; + } else if (flags == (ios_base::in)) { + prflags = PR_RDONLY; + } else if (flags == (ios_base::in | ios_base::out)) { + prflags = PR_RDWR; + } else if (flags == (ios_base::in | ios_base::out | ios_base::trunc)) { + prflags = PR_RDWR | PR_TRUNCATE; + } else { + return NULL; // Unrecognized flag combination. + } + + if ((_fd = PR_Open(name, prflags, mode)) == NULL) { + return NULL; + } + + _opened = true; + + if (ate && + seekoff(0, ios_base::end, flags) == pos_type(traits_type::eof())) { + close(); + return NULL; + } + + return this; +} + + +PRfilebuf *PRfilebuf::attach(PRFileDesc *fd) +{ + if (_fd != NULL) { + return NULL; // Error if already open. + } + + _opened = false; + _fd = fd; + return this; +} + + +PRfilebuf *PRfilebuf::close() +{ + if (_fd == NULL) + return NULL; + + int status = sync(); + + if (PR_Close(_fd) == PR_FAILURE || + traits_type::eq_int_type(status, traits_type::eof())) { + return NULL; + } + + _fd = NULL; + return this; +} + + +streambuf *PRfilebuf::setbuf(char_type *ptr, streamsize len) +{ + if (is_open() && _buf_end) { + return NULL; + } + + if (!ptr || len <= 0) { + _unbuffered = true; + } else { + setb(ptr, ptr + len, false); + } + + return this; +} + + +streambuf::pos_type PRfilebuf::seekoff( + off_type offset, ios_base::seekdir dir, ios_base::openmode /*flags*/) +{ + if (PR_GetDescType(_fd) != PR_DESC_FILE) { + return traits_type::eof(); + } + + PRSeekWhence whence; + PRInt64 pos; + + switch (dir) { + case ios_base::beg: whence = PR_SEEK_SET; break; + case ios_base::cur: whence = PR_SEEK_CUR; break; + case ios_base::end: whence = PR_SEEK_END; break; + default: + return traits_type::eof(); // This should never happen. + } + + if (traits_type::eq_int_type(sync(), traits_type::eof())) { + return traits_type::eof(); + } + + if ((pos = PR_Seek64(_fd, offset, whence)) == -1) { + return traits_type::eof(); + } + + return pos; +} + + +int PRfilebuf::sync() +{ + if (_fd == NULL) { + return traits_type::eof(); + } + + if (!_unbuffered) { + // Sync write area. + PRInt32 waiting; + if ((waiting = pptr() - pbase()) != 0) { + PRInt32 nout; + if ((nout = PR_Write(_fd, pbase(), waiting)) != waiting) { + if (nout > 0) { + // Should set _pptr -= nout. + pbump(-nout); + memmove(pbase(), pbase() + nout, waiting - nout); + } + return traits_type::eof(); + } + } + setp(NULL, NULL); // Empty put area. + + if (PR_GetDescType(_fd) == PR_DESC_FILE) { + // Sockets can't seek; don't need this. + PROffset64 avail; + if ((avail = in_avail()) > 0) { + if (PR_Seek64(_fd, -avail, PR_SEEK_CUR) != -1) { + return traits_type::eof(); + } + } + } + setg(NULL, NULL, NULL); // Empty get area. + } + + return 0; +} + + +streambuf::int_type PRfilebuf::underflow() +{ + PRInt32 count; + char_type byte; + + if (gptr() != NULL && gptr() < egptr()) { + return traits_type::to_int_type(*gptr()); + } + + // Make sure there is a reserve area. + if (!_unbuffered && _buf_base == NULL && !allocate()) { + return traits_type::eof(); + } + + // Sync before new buffer created below. + if (traits_type::eq_int_type(sync(), traits_type::eof())) { + return traits_type::eof(); + } + + if (_unbuffered) { + if (PR_Read(_fd, &byte, 1) <= 0) { + return traits_type::eof(); + } + + return traits_type::to_int_type(byte); + } + + if ((count = PR_Read(_fd, _buf_base, _buf_end - _buf_base)) <= 0) { + return traits_type::eof(); // Reached EOF. + } + + setg(_buf_base, _buf_base, _buf_base + count); + return traits_type::to_int_type(*gptr()); +} + + +streambuf::int_type PRfilebuf::overflow(int_type c) +{ + // Make sure there is a reserve area. + if (!_unbuffered && _buf_base == NULL && !allocate()) { + return traits_type::eof(); + } + + // Sync before new buffer created below. + if (traits_type::eq_int_type(sync(), traits_type::eof())) { + return traits_type::eof(); + } + + if (!_unbuffered) { + setp(_buf_base, _buf_end); + } + + if (!traits_type::eq_int_type(c, traits_type::eof())) { + // Extract the byte to be written. + // (Required on big-endian architectures.) + char_type byte = traits_type::to_char_type(c); + if (!_unbuffered && pptr() < epptr()) { // Guard against recursion. + return sputc(byte); + } else { + if (PR_Write(_fd, &byte, 1) != 1) { + return traits_type::eof(); + } + } + } + + return traits_type::not_eof(c); +} + + +bool PRfilebuf::allocate() +{ + char_type *buf = new(nothrow) char_type[BUFSIZ]; + if (buf == NULL) { + return false; + } + + setb(buf, buf + BUFSIZ, true); + return true; +} + + +void PRfilebuf::setb(char_type *buf_base, char_type *buf_end, bool user_buf) +{ + if (_buf_base && !_user_buf) { + delete[] _buf_base; + } + + _buf_base = buf_base; + _buf_end = buf_end; + _user_buf = user_buf; +} + + +PRifstream::PRifstream(): + istream(NULL), + _filebuf() +{ + init(&_filebuf); +} + + +PRifstream::PRifstream(PRFileDesc *fd): + istream(NULL), + _filebuf(fd) +{ + init(&_filebuf); +} + + +PRifstream::PRifstream(PRFileDesc *fd, char_type *ptr, streamsize len): + istream(NULL), + _filebuf(fd, ptr, len) +{ + init(&_filebuf); +} + + +PRifstream::PRifstream(const char *name, openmode flags, PRIntn mode): + istream(NULL), + _filebuf() +{ + init(&_filebuf); + if (!_filebuf.open(name, flags | in, mode)) { + setstate(failbit); + } +} + + +PRifstream::~PRifstream() { } + + +void PRifstream::open(const char *name, openmode flags, PRIntn mode) +{ + if (is_open() || !_filebuf.open(name, flags | in, mode)) { + setstate(failbit); + } +} + + +void PRifstream::attach(PRFileDesc *fd) +{ + if (!_filebuf.attach(fd)) { + setstate(failbit); + } +} + + +void PRifstream::close() +{ + if (_filebuf.close() == NULL) { + setstate(failbit); + } +} + + +PRofstream::PRofstream(): + ostream(NULL), + _filebuf() +{ + init(&_filebuf); +} + + +PRofstream::PRofstream(PRFileDesc *fd): + ostream(NULL), + _filebuf(fd) +{ + init(&_filebuf); +} + + +PRofstream::PRofstream(PRFileDesc *fd, char_type *ptr, streamsize len): + ostream(NULL), + _filebuf(fd, ptr, len) +{ + init(&_filebuf); +} + + +PRofstream::PRofstream(const char *name, openmode flags, PRIntn mode): + ostream(NULL), + _filebuf() +{ + init(&_filebuf); + if (!_filebuf.open(name, flags | out, mode)) { + setstate(failbit); + } +} + + +PRofstream::~PRofstream() { } + + +void PRofstream::open(const char *name, openmode flags, PRIntn mode) +{ + if (is_open() || !_filebuf.open(name, flags | out, mode)) { + setstate(failbit); + } +} + + +void PRofstream::attach(PRFileDesc *fd) +{ + if (!_filebuf.attach(fd)) { + setstate(failbit); + } +} + + +void PRofstream::close() +{ + if (_filebuf.close() == NULL) { + setstate(failbit); + } +} + + +PRfstream::PRfstream(): + iostream(NULL), + _filebuf() +{ + init(&_filebuf); +} + + +PRfstream::PRfstream(PRFileDesc *fd): + iostream(NULL), + _filebuf(fd) +{ + init(&_filebuf); +} + + +PRfstream::PRfstream(PRFileDesc *fd, char_type *ptr, streamsize len): + iostream(NULL), + _filebuf(fd, ptr, len) +{ + init(&_filebuf); +} + + +PRfstream::PRfstream(const char *name, openmode flags, PRIntn mode): + iostream(NULL), + _filebuf() +{ + init(&_filebuf); + if (!_filebuf.open(name, flags | in | out, mode)) { + setstate(failbit); + } +} + + +PRfstream::~PRfstream() { } + + +void PRfstream::open(const char *name, openmode flags, PRIntn mode) +{ + if (is_open() || !_filebuf.open(name, flags | in | out, mode)) { + setstate(failbit); + } +} + + +void PRfstream::attach(PRFileDesc *fd) +{ + if (!_filebuf.attach(fd)) { + setstate(failbit); + } +} + + +void PRfstream::close() +{ + if (_filebuf.close() == NULL) { + setstate(failbit); + } +} diff --git a/nsprpub/lib/prstreams/prstrms.h b/nsprpub/lib/prstreams/prstrms.h new file mode 100644 index 000000000..319dbf9de --- /dev/null +++ b/nsprpub/lib/prstreams/prstrms.h @@ -0,0 +1,140 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Robin J. Maxwell 11-22-96 + * Fredrik Roubert <roubert@google.com> 2010-07-23 + * Matt Austern <austern@google.com> 2010-07-23 + */ + +#ifndef _PRSTRMS_H +#define _PRSTRMS_H + +#include <cstddef> +#include <istream> +#include <ostream> +#include <streambuf> + +#include "prio.h" + +#ifdef _MSC_VER +// http://support.microsoft.com/kb/q168958/ +class PR_IMPLEMENT(std::_Mutex); +class PR_IMPLEMENT(std::ios_base); +#endif + + +class PR_IMPLEMENT(PRfilebuf): public std::streambuf +{ +public: + PRfilebuf(); + PRfilebuf(PRFileDesc *fd); + PRfilebuf(PRFileDesc *fd, char_type *ptr, std::streamsize len); + virtual ~PRfilebuf(); + + bool is_open() const { return _fd != NULL; } + + PRfilebuf *open( + const char *name, + std::ios_base::openmode flags, + PRIntn mode); + PRfilebuf *attach(PRFileDesc *fd); + PRfilebuf *close(); + +protected: + virtual std::streambuf *setbuf(char_type *ptr, std::streamsize len); + virtual pos_type seekoff( + off_type offset, + std::ios_base::seekdir dir, + std::ios_base::openmode flags); + virtual pos_type seekpos( + pos_type pos, + std::ios_base::openmode flags) { + return seekoff(pos, std::ios_base::beg, flags); + } + virtual int sync(); + virtual int_type underflow(); + virtual int_type overflow(int_type c = traits_type::eof()); + + // TODO: Override pbackfail(), showmanyc(), uflow(), xsgetn(), and xsputn(). + +private: + bool allocate(); + void setb(char_type *buf_base, char_type *buf_end, bool user_buf); + + PRFileDesc *_fd; + bool _opened; + bool _allocated; + bool _unbuffered; + bool _user_buf; + char_type *_buf_base; + char_type *_buf_end; +}; + + +class PR_IMPLEMENT(PRifstream): public std::istream +{ +public: + PRifstream(); + PRifstream(PRFileDesc *fd); + PRifstream(PRFileDesc *fd, char_type *ptr, std::streamsize len); + PRifstream(const char *name, openmode flags = in, PRIntn mode = 0); + virtual ~PRifstream(); + + PRfilebuf *rdbuf() const { return &_filebuf; } + bool is_open() const { return _filebuf.is_open(); } + + void open(const char *name, openmode flags = in, PRIntn mode = 0); + void attach(PRFileDesc *fd); + void close(); + +private: + mutable PRfilebuf _filebuf; +}; + + +class PR_IMPLEMENT(PRofstream): public std::ostream +{ +public: + PRofstream(); + PRofstream(PRFileDesc *fd); + PRofstream(PRFileDesc *fd, char_type *ptr, std::streamsize len); + PRofstream(const char *name, openmode flags = out, PRIntn mode = 0); + virtual ~PRofstream(); + + PRfilebuf *rdbuf() const { return &_filebuf; } + bool is_open() const { return _filebuf.is_open(); } + + void open(const char *name, openmode flags = out, PRIntn mode = 0); + void attach(PRFileDesc *fd); + void close(); + +private: + mutable PRfilebuf _filebuf; +}; + + +class PR_IMPLEMENT(PRfstream): public std::iostream +{ +public: + PRfstream(); + PRfstream(PRFileDesc *fd); + PRfstream(PRFileDesc *fd, char_type *ptr, std::streamsize len); + PRfstream(const char *name, openmode flags = in | out, PRIntn mode = 0); + virtual ~PRfstream(); + + PRfilebuf *rdbuf() const { return &_filebuf; } + bool is_open() const { return _filebuf.is_open(); } + + void open(const char *name, openmode flags = in | out, PRIntn mode = 0); + void attach(PRFileDesc *fd); + void close(); + +private: + mutable PRfilebuf _filebuf; +}; + + +#endif /* _PRSTRMS_H */ diff --git a/nsprpub/lib/prstreams/prstrms.rc b/nsprpub/lib/prstreams/prstrms.rc new file mode 100644 index 000000000..5f7258378 --- /dev/null +++ b/nsprpub/lib/prstreams/prstrms.rc @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "prinit.h" +#include <winver.h> + +#define MY_LIBNAME "prstrms" +#define MY_FILEDESCRIPTION "PRSTRMS Library" + +#define STRINGIZE(x) #x +#define STRINGIZE2(x) STRINGIZE(x) +#define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR) + +#ifdef _DEBUG +#define MY_DEBUG_STR " (debug)" +#define MY_FILEFLAGS_1 VS_FF_DEBUG +#else +#define MY_DEBUG_STR "" +#define MY_FILEFLAGS_1 0x0L +#endif +#if PR_BETA +#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE +#else +#define MY_FILEFLAGS_2 MY_FILEFLAGS_1 +#endif + +#ifdef WINNT +#define MY_FILEOS VOS_NT_WINDOWS32 +#define MY_INTERNAL_NAME "lib" MY_LIBNAME PR_VMAJOR_STR +#else +#define MY_FILEOS VOS__WINDOWS32 +#define MY_INTERNAL_NAME MY_LIBNAME PR_VMAJOR_STR +#endif + +///////////////////////////////////////////////////////////////////////////// +// +// Version-information resource +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0 + PRODUCTVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS MY_FILEFLAGS_2 + FILEOS MY_FILEOS + FILETYPE VFT_DLL + FILESUBTYPE 0x0L // not used + +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" // Lang=US English, CharSet=Unicode + BEGIN + VALUE "CompanyName", "Mozilla Foundation\0" + VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0" + VALUE "FileVersion", PR_VERSION "\0" + VALUE "InternalName", MY_INTERNAL_NAME "\0" + VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0" + VALUE "ProductName", "Netscape Portable Runtime\0" + VALUE "ProductVersion", PR_VERSION "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/nsprpub/lib/prstreams/tests/testprstrm/Makefile.in b/nsprpub/lib/prstreams/tests/testprstrm/Makefile.in new file mode 100644 index 000000000..1271f94b2 --- /dev/null +++ b/nsprpub/lib/prstreams/tests/testprstrm/Makefile.in @@ -0,0 +1,168 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#! gmake + +MOD_DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(MOD_DEPTH)/config/autoconf.mk + +include $(topsrcdir)/config/config.mk + +CXXSRCS = \ + testprstrm.cpp \ + $(NULL) + +OBJS = $(addprefix $(OBJDIR)/,$(CXXSRCS:.cpp=.$(OBJ_SUFFIX))) + +ifeq (,$(filter-out WINNT OS2,$(OS_ARCH))) +PROG_SUFFIX = .exe +else +PROG_SUFFIX = +endif + +PROGS = $(addprefix $(OBJDIR)/, $(CXXSRCS:.cpp=$(PROG_SUFFIX))) + +TARGETS = $(PROGS) $(OBJS) + +INCLUDES = -I$(dist_includedir) + +# Setting the variables LDOPTS and LIBPR. We first initialize +# them to the default values, then adjust them for some platforms. +LDOPTS = -L$(dist_libdir) +LIBPR = -lnspr$(MOD_MAJOR_VERSION) +LIBPRSTRMS = -lprstrms$(MOD_MAJOR_VERSION) + +ifeq ($(OS_ARCH), WINNT) + LDOPTS = -NOLOGO -DEBUG -INCREMENTAL:NO + ifeq ($(OS_TARGET), WIN95) + LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) + LIBPRSTRMS = $(dist_libdir)/prstrms$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) + else + LIBPR = $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) + LIBPRSTRMS = $(dist_libdir)/libprstrms$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) + endif +endif + +ifeq ($(OS_ARCH),OS2) +LDOPTS += -Zomf -Zlinker /PM:VIO -lstdcpp +endif + +ifneq ($(OS_ARCH), WINNT) +PWD = $(shell pwd) +endif + +ifeq ($(OS_ARCH), IRIX) +LDOPTS += -rpath $(PWD)/$(dist_libdir) +endif + +ifeq ($(OS_ARCH), OSF1) +LDOPTS += -rpath $(PWD)/$(dist_libdir) +endif + +ifeq ($(OS_ARCH), HP-UX) +LDOPTS += -Wl,+s,+b,$(PWD)/$(dist_libdir) +endif + +# AIX +ifeq ($(OS_ARCH),AIX) +LDOPTS += -blibpath:$(PWD)/$(dist_libdir):/usr/lib:/lib +ifeq ($(OS_ARCH)$(OS_RELEASE),AIX4.1) +LIBPR = -lnspr$(MOD_MAJOR_VERSION)_shr +LIBPRSTRMS = -lprstrms$(MOD_MAJOR_VERSION)_shr +else +LDOPTS += -brtl +EXTRA_LIBS = -ldl +endif +endif + +# Solaris +ifeq ($(OS_ARCH), SunOS) +ifdef NS_USE_GCC +LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(dist_libdir) +else +LDOPTS += -R $(PWD)/$(dist_libdir) +# CC on SunOS 5.5.x needs to link with -lpthread even though we already +# linked with this system library when we built libnspr.so. +ifdef USE_PTHREADS +EXTRA_LIBS = -lpthread +endif # USE_PTHREADS +endif # NS_USE_GCC +endif # SunOS + +ifeq ($(OS_ARCH), SCOOS) +# SCO Unix needs to link against -lsocket again even though we +# already linked with these system libraries when we built libnspr.so. +EXTRA_LIBS = -lsocket +# This hardcodes in the executable programs the directory to find +# libnspr.so etc. at program startup. Equivalent to the -R or -rpath +# option for ld on other platforms. +export LD_RUN_PATH = $(PWD)/$(dist_libdir) +endif + +ifeq ($(OS_ARCH), UNIXWARE) +export LD_RUN_PATH = $(PWD)/$(dist_libdir) +endif + +##################################################### +# +# The rules +# +##################################################### + +include $(topsrcdir)/config/rules.mk + +AIX_PRE_4_2 = 0 +ifeq ($(OS_ARCH),AIX) +ifneq ($(OS_RELEASE),4.2) +ifneq ($(USE_PTHREADS), 1) +#AIX_PRE_4_2 = 1 +endif +endif +endif + +ifeq ($(AIX_PRE_4_2),1) + +# AIX releases prior to 4.2 need a special two-step linking hack +# in order to both override the system select() and be able to +# get at the original system select(). +# +# We use a pattern rule in ns/nspr20/config/rules.mk to generate +# the .$(OBJ_SUFFIX) file from the .c source file, then do the +# two-step linking hack below. + +$(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX) + @$(MAKE_OBJDIR) + rm -f $@ $(AIX_TMP) + $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a + $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP) + rm -f $(AIX_TMP) + +else + +# All platforms that are not AIX pre-4.2. + +$(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX) + @$(MAKE_OBJDIR) +ifeq ($(OS_ARCH), WINNT) + link $(LDOPTS) $< $(LIBPR) $(LIBPRSTRMS) ws2_32.lib -out:$@ +else +ifeq ($(OS_ARCH),OS2) + $(LINK) $(EXEFLAGS) $(LDOPTS) $< $(LIBPR) $(LIBPRSTRMS) $(OS_LIBS) $(EXTRA_LIBS) +else + $(CCC) $(XCFLAGS) $< $(LDOPTS) $(LIBPR) $(LIBPRSTRMS) $(EXTRA_LIBS) -o $@ +endif +endif +endif + +export:: $(TARGETS) +clean:: + rm -f $(TARGETS) + +testlinker: + echo $(LINK) diff --git a/nsprpub/lib/prstreams/tests/testprstrm/testprstrm.cpp b/nsprpub/lib/prstreams/tests/testprstrm/testprstrm.cpp new file mode 100644 index 000000000..12011c8a6 --- /dev/null +++ b/nsprpub/lib/prstreams/tests/testprstrm/testprstrm.cpp @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "prstrms.h" + +#include "prinit.h" +#include "prio.h" +#include "prthread.h" + +#include <cstring> +#include <iostream> + +#ifdef XP_UNIX +#include <sys/stat.h> +#endif + +using std::cout; +using std::endl; +using std::ios; + +const unsigned int MaxCnt = 1; + +typedef struct threadarg { + const char *mytag; +} threadarg; + +void threadwork(threadarg *arg); + +void +threadmain(void *mytag) +{ + threadarg arg; + + arg.mytag = static_cast<const char *>(mytag); + + threadwork(&arg); +} + +void +threadwork(threadarg *arg) +{ + unsigned int i; + + char fname1[256]; + char fname2[256]; + + strcpy(fname1, arg->mytag); + strcpy(fname2, arg->mytag); + strcat(fname2, "2"); + PR_Delete(fname1); + PR_Delete(fname2); + + PRfilebuf *fb[MaxCnt]; + PRifstream *ifs[MaxCnt]; + PRofstream *ofs[MaxCnt]; + int mode = 0; +#ifdef XP_UNIX + mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; +#endif + + // + // Allocate a bunch + cout << "Testing unused filebufs ----------------" << endl; + for (i=0; i < MaxCnt; i++){ + fb[i] = new PRfilebuf; + } + // Delete them + for (i=0; i < MaxCnt; i++){ + delete fb[i]; + } + cout << "Unused filebufs complete ---------------" << endl; + + // + // Allocate a bunch + cout << "Testing unused ifstream -----------------" << endl; + for (i=0; i < MaxCnt; i++){ + ifs[i] = new PRifstream; + } + // + // Delete them + for (i=0; i < MaxCnt; i++){ + delete ifs[i]; + } + cout << "Unused ifstream complete ----------------" << endl; + // + // Allocate a bunch + cout << "Testing unused ofstream -----------------" << endl; + for (i=0; i < MaxCnt; i++){ + ofs[i] = new PRofstream; + } + for (i=0; i < MaxCnt; i++){ + *(ofs[i]) << "A"; // Write a bit + delete ofs[i]; // Delete it. + } + cout << "Unused ofstream complete ----------------" << endl; + + cout << "Testing use of ofstream 1 (extra filebuf allocated) ---------" << endl; + PRofstream *aos = new PRofstream(fname1, ios::out|ios::ate, mode); + for (i=0; i < MaxCnt; i++){ + for (int j=0; j < 8192; j++) + *aos << "AaBbCcDdEeFfGg" << endl; + fb[i] = new PRfilebuf; // Allocate as we go to hack at the heap + } + // + // Delete the extra foo we allocated + for (i=0; i < MaxCnt; i++){ + delete fb[i]; + } + aos->flush(); // Explicit flush + delete aos; + cout << "Testing use of ofstream 1 complete (extra filebuf deleted) --" << endl; + cout << "Testing use of ofstream 2 (extra filebuf allocated) ---------" << endl; + PRofstream *aos2 = new PRofstream(fname2, ios::out, mode); + + for (i=0; i < MaxCnt; i++){ + *aos2 << "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; + } + // Force flushing in the dtor + delete aos2; + cout << "Testing use of ofstream 2 complete (extra filebuf deleted) --" << endl; + char line[1024]; + cout << "Testing use of ifstream 1 (stack allocation) -------------" << endl; + PRifstream ais(fname1); + for (i=0; i < MaxCnt; i++){ + ais >> line; + } + cout << "Testing use of ifstream 1 complete -----------------------" << endl; + cout << "Testing use of ifstream 2 ----------------------" << endl; + PRifstream *ais2 = new PRifstream(fname2); + char achar; + for (i=0; i < MaxCnt*10; i++){ + *ais2 >> achar; + } + delete ais2; + cout << "Testing use of ifstream 2 complete -------------" << endl; +} + +#define STACKSIZE 1024*1024 +int +main() +{ + PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 256); + threadmain(const_cast<char *>("TestFile")); + PRThread *thr1 = PR_CreateThread(PR_SYSTEM_THREAD, + threadmain, + const_cast<char *>("TestFile1"), + PR_PRIORITY_NORMAL, + PR_GLOBAL_THREAD, + PR_JOINABLE_THREAD, + STACKSIZE); + PRThread *thr2 = PR_CreateThread(PR_SYSTEM_THREAD, + threadmain, + const_cast<char *>("TestFile2"), + PR_PRIORITY_NORMAL, + PR_GLOBAL_THREAD, + PR_JOINABLE_THREAD, + STACKSIZE); + PRThread *thr3 = PR_CreateThread(PR_SYSTEM_THREAD, + threadmain, + const_cast<char *>("TestFile3"), + PR_PRIORITY_NORMAL, + PR_GLOBAL_THREAD, + PR_JOINABLE_THREAD, + STACKSIZE); + PR_JoinThread(thr1); + PR_JoinThread(thr2); + PR_JoinThread(thr3); + return 0; +} |