summaryrefslogtreecommitdiffstats
path: root/nsprpub/lib/prstreams
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--nsprpub/lib/prstreams/Makefile.in142
-rw-r--r--nsprpub/lib/prstreams/plvrsion.c100
-rw-r--r--nsprpub/lib/prstreams/prstrms.cpp517
-rw-r--r--nsprpub/lib/prstreams/prstrms.h154
-rw-r--r--nsprpub/lib/prstreams/prstrms.rc69
-rw-r--r--nsprpub/lib/prstreams/tests/testprstrm/Makefile.in160
-rw-r--r--nsprpub/lib/prstreams/tests/testprstrm/testprstrm.cpp172
7 files changed, 1314 insertions, 0 deletions
diff --git a/nsprpub/lib/prstreams/Makefile.in b/nsprpub/lib/prstreams/Makefile.in
new file mode 100644
index 0000000000..a380cab400
--- /dev/null
+++ b/nsprpub/lib/prstreams/Makefile.in
@@ -0,0 +1,142 @@
+#
+# 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), 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 0000000000..a8332ff6f7
--- /dev/null
+++ b/nsprpub/lib/prstreams/plvrsion.c
@@ -0,0 +1,100 @@
+/* -*- 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 */ "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/.",
+ /* 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 */
+
+#ifdef _PR_HAS_PRAGMA_DIAGNOSTIC
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#endif
+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 */
+#ifdef _PR_HAS_PRAGMA_DIAGNOSTIC
+#pragma GCC diagnostic pop
+#endif
+
+/* plvrsion.c */
+
diff --git a/nsprpub/lib/prstreams/prstrms.cpp b/nsprpub/lib/prstreams/prstrms.cpp
new file mode 100644
index 0000000000..878175df5a
--- /dev/null
+++ b/nsprpub/lib/prstreams/prstrms.cpp
@@ -0,0 +1,517 @@
+/* -*- 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 0000000000..113a41627e
--- /dev/null
+++ b/nsprpub/lib/prstreams/prstrms.h
@@ -0,0 +1,154 @@
+/* -*- 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 0000000000..5f72583783
--- /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 0000000000..74ef1ac2c9
--- /dev/null
+++ b/nsprpub/lib/prstreams/tests/testprstrm/Makefile.in
@@ -0,0 +1,160 @@
+#
+# 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), 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 0000000000..236e6ac64c
--- /dev/null
+++ b/nsprpub/lib/prstreams/tests/testprstrm/testprstrm.cpp
@@ -0,0 +1,172 @@
+/* -*- 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;
+}