Rewrote the stream stuff to be simple, since Unix build environment cannot even handle ostream and istream. This builds and runs correctly on Linux and Macintosh now.

git-svn-id: svn://10.0.0.236/trunk@16688 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
mcmullen%netscape.com 1998-12-18 23:06:54 +00:00
parent fe18aadf26
commit a4ac66b40a
12 changed files with 984 additions and 1758 deletions

View File

@ -37,15 +37,14 @@
// to the moment Communicator 4.5 shipped.
//
// 3. Used in conjunction with nsFileStream.h (q.v.), this supports all the power
// and readability of the ansi stream syntax. ALL METHODS OF istream, ostream,
// AND iostream ARE AVAILABLE!
// and readability of the ansi stream syntax.
//
// Basic example:
//
// nsFilePath myPath("/Development/iotest.txt");
//
// nsOutputFileStream testStream(myPath);
// testStream << "Hello World" << endl;
// testStream << "Hello World" << nsEndl;
//
// 4. Handy methods for manipulating file specifiers safely, e.g. MakeUnique(),
// SetLeafName(), Exists().
@ -117,14 +116,11 @@
#define NS_NAMESPACE_PROTOTYPE
#define NS_NAMESPACE namespace
#define NS_NAMESPACE_END
#include <ostream>
using std::ostream;
#else
#define NS_NAMESPACE_PROTOTYPE static
#define NS_NAMESPACE struct
#define NS_NAMESPACE_END ;
#include <ostream.h>
#endif
//=========================== End Compiler-specific macros ===============================
@ -144,6 +140,8 @@ class nsNativeFileSpec;
#define kFileURLPrefix "file://"
#define kFileURLPrefixLength (7)
class nsOutputFileStream;
//========================================================================================
class NS_BASE nsNativeFileSpec
// This is whatever each platform really prefers to describe files as. Declared first
@ -196,7 +194,7 @@ class NS_BASE nsNativeFileSpec
bool Valid() const { return true; } // Fixme.
#endif // XP_MAC
friend NS_BASE ostream& operator << (ostream& s, const nsNativeFileSpec& spec);
friend NS_BASE nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec& spec);
char* GetLeafName() const; // Allocated. Use delete [].
void SetLeafName(const char* inLeafName);
@ -237,7 +235,8 @@ class NS_BASE nsFileURL
void operator = (const nsFilePath& inOther);
void operator = (const nsNativeFileSpec& inOther);
friend NS_BASE ostream& operator << (ostream& s, const nsFileURL& spec);
friend NS_BASE nsOutputFileStream& operator << (
nsOutputFileStream& s, const nsFileURL& spec);
#ifdef XP_MAC
// Accessor to allow quick assignment to a mNativeFileSpec

View File

@ -26,11 +26,7 @@
//
// single-byte char:
//
// nsInputFileStream, nsOutputFileStream, nsIOFileStream
//
// wide char:
//
// nsWideInputFileStream, nsWideOutputFileStream, nsWideIOFileStream
// nsInputFileStream, nsOutputFileStream
//
// This suite provide the following services:
//
@ -41,16 +37,14 @@
// native performance. This performance difference is especially large on
// macintosh.
//
// 3. Allows all the power of the ansi stream syntax: these streams
// ARE derived classes of ostream, istream, and iostream. ALL METHODS OF
// istream, ostream, AND iostream ARE AVAILABLE!
// 3. Allows all the power of the ansi stream syntax.
//
// Basic example:
//
// nsFilePath myPath("/Development/iotest.txt");
//
// nsOutputFileStream testStream(myPath);
// testStream << "Hello World" << endl;
// testStream << "Hello World" << nsEndl;
//
// 4. Requires streams to be constructed using typesafe nsFilePath specifier
// (not the notorious and bug prone const char*), namely nsFilePath. See
@ -107,831 +101,151 @@
#endif // NS_USING_NAMESPACE
#ifdef NS_USING_STL
// Macintosh and Windows use this section.
//
// Here's where the party is. When Unix wants to join in (by supporting
// a build system with STL headers), what fun we'll have! Meanwhile, I've used
// macros to make this build on all our platforms. Unix doesn't have support for
// STL, and therefore we could not use the template forms of these classes on Unix.
// (it's a long story). Therefore, Unix supports no stream char types except 1-byte
// characters, and therefore nobody else does now either, until Unix catches up.
#define DEFINING_FILE_STREAM // templateers define this when this file is included.
#define IOS_BASE ios_base
#include <istream>
using std::ios_base;
using std::basic_streambuf;
using std::codecvt_base;
using std::codecvt;
using std::streamsize;
using std::locale;
using std::basic_istream;
using std::basic_ostream;
using std::basic_iostream;
using std::char_traits;
#define TEMPLATE_DEF template<class charT, class traits>
#define FILE_BUFFER_TYPE nsFileBufferT<charT, traits>
#define INPUT_FILE_STREAM nsInputFileStreamT<charT, traits>
#define OUTPUT_FILE_STREAM nsOutputFileStreamT<charT, traits>
#define IO_FILE_STREAM nsIOFileStreamT<charT, traits>
#define BASIC_STREAMBUF basic_streambuf<charT, traits>
#define BASIC_ISTREAM basic_istream<charT, traits>
#define BASIC_OSTREAM basic_ostream<charT, traits>
#define BASIC_IOSTREAM basic_iostream<charT, traits>
#define INT_TYPE FILE_BUFFER_TYPE::int_type
#define POS_TYPE FILE_BUFFER_TYPE::pos_type
#define OFF_TYPE FILE_BUFFER_TYPE::off_type
#define SEEK_DIR IOS_BASE::seekdir
#define EOF_VALUE traits::eof()
#include <iostream>
using std::istream;
using std::ostream;
#else
// Unix uses this section until it supports STL. This means no locales, no traits,
// no wide chars, etc. Also, the stream classes are the original ARM-style ones,
// and are not templatized.
#define IOS_BASE ios
#include <istream.h>
#define TEMPLATE_DEF
#define FILE_BUFFER_TYPE nsFileBufferT
#define INPUT_FILE_STREAM nsInputFileStreamT
#define OUTPUT_FILE_STREAM nsOutputFileStreamT
#define IO_FILE_STREAM nsIOFileStreamT
#define BASIC_STREAMBUF streambuf
#define BASIC_ISTREAM istream
#define BASIC_OSTREAM ostream
#define BASIC_IOSTREAM iostream
#define INT_TYPE int
#define POS_TYPE long
#define OFF_TYPE long
#define SEEK_DIR ios::seek_dir
#define int_type int
#define pos_type long
#define off_type long
#define char_type char
#define EOF_VALUE EOF
#endif // NS_USING_STL
#ifdef __MWERKS__
#ifdef MSIPL_WCHART
#define NS_USING_WIDE_CHAR
#include <iostream.h>
#endif
#ifdef MSIPL_EXPLICIT_FUNC_TEMPLATE_ARG
#define NS_EXPLICIT_FUNC_TEMPLATE_ARG
#endif
#define NS_READ_LOCK(mut) READ_LOCK(mut)
#define NS_WRITE_LOCK(mut) WRITE_LOCK(mut)
#else
// Fix me, if necessary, for thread-safety.
#define NS_READ_LOCK(mut)
#define NS_WRITE_LOCK(mut)
#endif // __MWERKS__
//=========================== End Compiler-specific macros ===============================
//========================================================================================
NS_NAMESPACE nsFileStreamHelpers
// Prototypes for common (non-template) implementations in the .cpp file which do not
// need the template args (charT, traits).
class NS_BASE nsBasicFileStream
//========================================================================================
{
NS_NAMESPACE_PROTOTYPE NS_BASE PRFileDesc* open(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode);
} NS_NAMESPACE_END // nsFileStreamHelpers
//========================================================================================
// Template declarations
//========================================================================================
//========================================================================================
TEMPLATE_DEF
class nsFileBufferT
//========================================================================================
: public BASIC_STREAMBUF
{
#ifdef NS_USING_STL
typedef codecvt_base::result result;
public:
typedef charT char_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
typedef typename traits::int_type int_type;
typedef traits traits_type;
typedef typename traits::state_type state_type;
nsBasicFileStream();
nsBasicFileStream(PRFileDesc* desc, int nsprMode);
nsBasicFileStream(
const nsFilePath& inFile,
int nsprMode,
PRIntn accessMode);
virtual ~nsBasicFileStream();
typedef codecvt<charT, char, state_type> ofacet_type;
typedef codecvt<char, charT, state_type> ifacet_type;
#endif
public:
nsFileBufferT();
nsFileBufferT(PRFileDesc* pfile_arg);
virtual ~nsFileBufferT();
bool is_open() const;
FILE_BUFFER_TYPE* open(
inline bool is_open() const { return mFileDesc != 0; }
void open(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
int nsprMode,
PRIntn accessMode);
FILE_BUFFER_TYPE* close();
void close();
PRIntn tell() const;
void seek(PRInt32 offset) { seek(PR_SEEK_SET, offset); }
void seek(PRSeekWhence whence, PRInt32 offset);
bool eof() const { return mEOF; }
bool failed() const { return mFailed; }
// call PR_GetError() for details
protected:
virtual int_type overflow(int_type c=EOF_VALUE);
virtual int_type pbackfail(int_type c=EOF_VALUE);
virtual int_type underflow();
virtual pos_type seekoff(
off_type off, SEEK_DIR way,
IOS_BASE::openmode which=IOS_BASE::in|IOS_BASE::out);
virtual pos_type seekpos(pos_type sp,
IOS_BASE::openmode which=IOS_BASE::in|IOS_BASE::out);
virtual BASIC_STREAMBUF* setbuf(char_type* s, streamsize n);
virtual int sync();
virtual int_type uflow();
#ifdef NS_USING_STL
virtual void imbue(const locale& loc);
#endif
virtual streamsize showmanyc();
virtual streamsize xsgetn(char_type* s, streamsize n);
virtual streamsize xsputn(const char_type* s, streamsize n);
private:
PRFileDesc* mFileDesc;
IOS_BASE::openmode mode_;
}; // class nsFileBufferT
PRFileDesc* mFileDesc;
int mNSPRMode;
bool mFailed;
bool mEOF;
}; // class nsBasicFileStream
//========================================================================================
TEMPLATE_DEF
class nsInputFileStreamT
class NS_BASE nsInputFileStream
//========================================================================================
: public BASIC_ISTREAM
: public nsBasicFileStream
{
#ifdef NS_USING_STL
public:
typedef charT char_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
typedef typename traits::int_type int_type;
typedef traits traits_type;
#endif
public:
nsInputFileStreamT();
explicit nsInputFileStreamT(
enum { kDefaultMode = PR_RDONLY };
nsInputFileStream()
: nsBasicFileStream()
, mStdStream(0) {}
nsInputFileStream(
istream& stream);
nsInputFileStream(
const nsFilePath& inFile,
IOS_BASE::openmode mode=IOS_BASE::in,
PRIntn accessMode = 0x00400);
int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00400)
: nsBasicFileStream(inFile, nsprMode, accessMode)
, mStdStream(0) {}
virtual ~nsInputFileStreamT();
nsInputFileStream& operator >> (nsInputFileStream& (*pf)(nsInputFileStream&))
{
return pf(*this);
}
void get(char& c);
PRInt32 read(void* s, PRInt32 n);
bool readline(char* s, PRInt32 n);
// Result always null-terminated
// false result indicates line was truncated
// to fit buffer, or an error occurred.
FILE_BUFFER_TYPE* rdbuf() const;
inline bool is_open();
inline void open(
// Output streamers. Add more as needed
nsInputFileStream& operator >> (char& ch);
void open(
const nsFilePath& inFile,
IOS_BASE::openmode mode=IOS_BASE::in,
PRIntn accessMode = 0x00400);
inline void close();
int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00400)
{
nsBasicFileStream::open(inFile, nsprMode, accessMode);
}
private:
FILE_BUFFER_TYPE mBuffer;
}; // class nsInputFileStreamT
nsInputFileStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE.
protected:
istream* mStdStream;
}; // class nsInputFileStream
//========================================================================================
TEMPLATE_DEF
class nsOutputFileStreamT
class NS_BASE nsOutputFileStream
//========================================================================================
: public BASIC_OSTREAM
: public nsBasicFileStream
{
#ifdef NS_USING_STL
public:
typedef charT char_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
typedef typename traits::int_type int_type;
typedef traits traits_type;
#endif
public:
enum { kDefaultMode = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE) };
nsOutputFileStreamT();
explicit nsOutputFileStreamT(
nsOutputFileStream()
: nsBasicFileStream()
, mStdStream(0) {}
nsOutputFileStream(
ostream& stream);
nsOutputFileStream(
const nsFilePath& inFile,
IOS_BASE::openmode mode = IOS_BASE::out|IOS_BASE::trunc,
PRIntn accessMode = 0x00200);
int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00200)
: nsBasicFileStream(inFile, nsprMode, accessMode)
, mStdStream(0) {}
virtual ~nsOutputFileStreamT();
FILE_BUFFER_TYPE* rdbuf() const;
inline bool is_open();
ostream* GetStandardStream() const { return mStdStream; }
inline void open(
const nsFilePath& inFile,
IOS_BASE::openmode mode = IOS_BASE::out|IOS_BASE::trunc,
PRIntn accessMode = 0x00200);
inline void close();
int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00200)
{
nsBasicFileStream::open(inFile, nsprMode, accessMode);
}
nsOutputFileStream& operator << (nsOutputFileStream& (*pf)(nsOutputFileStream&))
{
return pf(*this);
}
void put(char c);
PRInt32 write(const void* s, PRInt32 n);
void flush();
// Output streamers. Add more as needed
nsOutputFileStream& operator << (const char* buf);
nsOutputFileStream& operator << (char ch);
nsOutputFileStream& operator << (short val);
nsOutputFileStream& operator << (unsigned short val);
nsOutputFileStream& operator << (long val);
nsOutputFileStream& operator << (unsigned long val);
private:
FILE_BUFFER_TYPE mBuffer;
}; // class nsOutputFileStreamT
protected:
ostream* mStdStream;
}; // class nsOutputFileStream
//========================================================================================
// Implementation of nsFileBufferT
// Manipulators
//========================================================================================
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline FILE_BUFFER_TYPE::nsFileBufferT()
: BASIC_STREAMBUF(), mFileDesc(NULL)
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline FILE_BUFFER_TYPE::nsFileBufferT(PRFileDesc* pfarg)
: BASIC_STREAMBUF(), mFileDesc(pfarg)
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline FILE_BUFFER_TYPE* FILE_BUFFER_TYPE::close()
// Must precede the destructor because both are inline.
//----------------------------------------------------------------------------------------
{
if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR)
return this;
NS_WRITE_LOCK(_mutex);
return (mFileDesc && PR_Close(mFileDesc) == PR_SUCCESS) ? mFileDesc = 0, this : 0;
}
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
FILE_BUFFER_TYPE::~nsFileBufferT()
//----------------------------------------------------------------------------------------
{
close();
}
#endif // #if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline bool
FILE_BUFFER_TYPE::is_open() const
//----------------------------------------------------------------------------------------
{
NS_READ_LOCK(_mutex);
return bool(mFileDesc); // in case it is typedefed to int
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline FILE_BUFFER_TYPE* FILE_BUFFER_TYPE::open(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
{
if (mFileDesc)
return 0;
NS_WRITE_LOCK(_mutex);
mFileDesc = nsFileStreamHelpers::open(inFile, mode, accessMode);
if (!mFileDesc)
return 0;
mode_ = mode;
return this;
} // FILE_BUFFER_TYPE::open
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline int FILE_BUFFER_TYPE:: sync()
//----------------------------------------------------------------------------------------
{
return (mFileDesc ? (int)PR_Sync(mFileDesc) : 0);
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline BASIC_STREAMBUF* FILE_BUFFER_TYPE::setbuf(char_type*, streamsize)
//----------------------------------------------------------------------------------------
{
return (!mFileDesc) ? 0 : this;
}
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
INT_TYPE FILE_BUFFER_TYPE::overflow(int_type c)
//----------------------------------------------------------------------------------------
{
#ifndef NS_USING_STL
char ch = c;
PRInt32 bytesWrit1 = PR_Write(mFileDesc, &ch, sizeof(ch));
return bytesWrit1 < sizeof(ch) ? EOF_VALUE : c;
#else
#ifdef NS_EXPLICIT_FUNC_TEMPLATE_ARG
const ofacet_type& ft=use_facet<ofacet_type>(getloc());
#elif defined(XP_PC)
const ofacet_type& ft=use_facet(getloc(), (ofacet_type*)0, false);
#else
const ofacet_type& ft=use_facet(getloc(), (ofacet_type*)0);
#endif
char_type ch = traits_type::to_char_type(c);
if (!mFileDesc)
return EOF_VALUE;
if (traits_type::eq_int_type(c, EOF_VALUE))
return traits_type::not_eof(c);
if (ft.always_noconv())
{
PRInt32 bytesWrit1 = PR_Write(mFileDesc, &ch, sizeof(ch));
return bytesWrit1 < sizeof(ch) ? EOF_VALUE : c;
}
{ // <- sic!
state_type fst;
const char_type* end;
char buf[4];
char* ebuf;
result conv;
if ((conv=ft.out(fst, &ch, &ch+1, end, buf, buf+3, ebuf))==
codecvt_base::noconv)
{
PRInt32 bytesWrit2 = PR_Write(mFileDesc, &ch, sizeof(ch));
return bytesWrit2 < sizeof(ch) ? EOF_VALUE : c;
}
if ((conv==codecvt_base::partial)||(conv==codecvt_base::error))
return EOF_VALUE;
*ebuf=0;
PRInt32 bytesWrit3 = strlen(buf);
return PR_Write(mFileDesc, buf, bytesWrit3) < bytesWrit3 ? EOF_VALUE : c;
}
#endif
}
#endif // #if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline INT_TYPE FILE_BUFFER_TYPE::underflow()
//----------------------------------------------------------------------------------------
{
if (!mFileDesc)
return EOF_VALUE;
char_type s;
PRInt32 request = 1;
if (1 != PR_Read(mFileDesc, &s, request))
return EOF_VALUE;
PR_Seek(mFileDesc, -1, PR_SEEK_CUR);
return (int_type)s;
}
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
streamsize FILE_BUFFER_TYPE::xsputn(const char_type* s, streamsize n)
//----------------------------------------------------------------------------------------
{
#ifndef NS_USING_STL
PRInt32 bytesWrit1 = PR_Write(mFileDesc, s, sizeof(char) * size_t(n));
return bytesWrit1 < 0 ? 0 : (streamsize)bytesWrit1;
#else
#ifdef NS_EXPLICIT_FUNC_TEMPLATE_ARG
const ofacet_type& ft=use_facet<ofacet_type>(loc);
#elif defined(XP_PC)
const ofacet_type& ft=use_facet(getloc(), (ofacet_type*)0, false);
#else
const ofacet_type& ft=use_facet(getloc(), (ofacet_type*)0);
#endif
if (!mFileDesc || !n)
return 0;
if (ft.always_noconv())
{
PRInt32 bytesWrit1 = PR_Write(mFileDesc, s, sizeof(char) * size_t(n));
return bytesWrit1 < 0 ? 0 : (streamsize)bytesWrit1;
}
{ // <- sic!
state_type fst;
const char_type* end;
char buf[8];
char* ebuf;
result conv;
#ifdef NS_EXPLICIT_FUNC_TEMPLATE_ARG
if ((conv=use_facet<ofacet_type>(getloc()).
#elif defined(XP_PC)
if ((conv=use_facet(getloc(), (ofacet_type*)0, false).
#else
if ((conv=use_facet(getloc(), (ofacet_type*)0).
#endif
out(fst, s, s+n, end, buf, buf+7, ebuf))==codecvt_base::noconv)
return (streamsize)PR_Write(mFileDesc, s, sizeof(char) * size_t(n));
if ((conv==codecvt_base::partial) ||(conv==codecvt_base::error))
return 0;
*ebuf=0;
PRInt32 bytesWrit2 = strlen(buf);
bytesWrit2 = PR_Write(mFileDesc, buf, bytesWrit2);
return bytesWrit2 < 0 ? 0 : streamsize(bytesWrit2 / sizeof(char_type));
}
#endif
} // FILE_BUFFER_TYPE::xsputn
#endif // #if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline INT_TYPE FILE_BUFFER_TYPE::pbackfail(int_type c)
//----------------------------------------------------------------------------------------
{
if (!mFileDesc)
return EOF_VALUE;
if (PR_Seek(mFileDesc, -1, PR_SEEK_CUR) < 0)
return EOF_VALUE;
#ifdef NS_USING_STL
return (traits::eq_int_type(c, EOF_VALUE)) ? traits::not_eof(c) : c;
#else
return c;
#endif
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline INT_TYPE FILE_BUFFER_TYPE::uflow()
//----------------------------------------------------------------------------------------
{
if (!mFileDesc)
return EOF_VALUE;
char_type s;
if (1 != PR_Read(mFileDesc, &s, 1)) // attempt to read 1 byte, confirm 1 byte
return EOF_VALUE;
return (int_type)s;
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline streamsize FILE_BUFFER_TYPE::xsgetn(char_type* s, streamsize n)
//----------------------------------------------------------------------------------------
{
return mFileDesc ? (streamsize)PR_Read(mFileDesc, s, sizeof(char) * size_t(n)) : 0;
}
#ifdef NS_USING_STL
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline void FILE_BUFFER_TYPE::imbue(const locale& loc_arg)
//----------------------------------------------------------------------------------------
{
#ifdef XP_MAC
loc = loc_arg;
#endif
}
#endif
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline streamsize FILE_BUFFER_TYPE::showmanyc()
//----------------------------------------------------------------------------------------
{
return (streamsize)PR_Available(mFileDesc);
}
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
POS_TYPE FILE_BUFFER_TYPE::seekoff(
OFF_TYPE off,
SEEK_DIR way,
IOS_BASE::openmode /* which */)
//----------------------------------------------------------------------------------------
{
if (!mFileDesc ||
#ifdef NS_USING_STL
((way&IOS_BASE::beg) && off<0) || ((way&IOS_BASE::end) && off > 0)
#else
((way == IOS_BASE::beg) && off<0) || ((way == IOS_BASE::end) && off > 0)
#endif
)
return pos_type(-1);
PRSeekWhence poseek = PR_SEEK_CUR;
switch (way)
{
case IOS_BASE::beg : poseek= PR_SEEK_SET;
break;
case IOS_BASE::end : poseek= PR_SEEK_END;
break;
}
PRInt32 position = PR_Seek(mFileDesc, off, poseek);
if (position < 0)
return pos_type(-1);
return pos_type(position);
}
#endif // #if defined(DEFINING_FILE_STREAM)
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
POS_TYPE FILE_BUFFER_TYPE::seekpos(pos_type sp, IOS_BASE::openmode)
//----------------------------------------------------------------------------------------
{
if (!mFileDesc || sp==pos_type(-1))
return -1;
#if defined(XP_PC) || defined(XP_UNIX)
PRInt32 position = sp;
#else
PRInt32 position = sp.offset();
#endif
position = PR_Seek(mFileDesc, position, PR_SEEK_SET);
if (position < 0)
return pos_type(-1);
return position;
}
#endif // #if defined(DEFINING_FILE_STREAM)
//========================================================================================
// Implementation of nsInputFileStreamT
//========================================================================================
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline INPUT_FILE_STREAM::nsInputFileStreamT()
: BASIC_ISTREAM(&mBuffer)
//----------------------------------------------------------------------------------------
{
// already inited
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline INPUT_FILE_STREAM::nsInputFileStreamT(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
: BASIC_ISTREAM(&mBuffer)
{
// already inited
if (!mBuffer.open(inFile, openmode(mode|in), accessMode))
setstate(failbit);
}
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
INPUT_FILE_STREAM::~nsInputFileStreamT()
//----------------------------------------------------------------------------------------
{
}
#endif // #if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline FILE_BUFFER_TYPE* INPUT_FILE_STREAM::rdbuf() const
//----------------------------------------------------------------------------------------
{
return (FILE_BUFFER_TYPE*)&mBuffer;
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline bool INPUT_FILE_STREAM:: is_open()
//----------------------------------------------------------------------------------------
{
return mBuffer.is_open();
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline void INPUT_FILE_STREAM::open(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
{
if (!mBuffer.open(inFile, openmode(mode|in), accessMode))
setstate(failbit);
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline void INPUT_FILE_STREAM::close()
//----------------------------------------------------------------------------------------
{
if (!mBuffer.close())
setstate(failbit);
}
//========================================================================================
// Implementation of nsOutputFileStreamT
//========================================================================================
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline OUTPUT_FILE_STREAM::nsOutputFileStreamT()
: BASIC_OSTREAM(&mBuffer)
//----------------------------------------------------------------------------------------
{
// already inited
}
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
OUTPUT_FILE_STREAM::nsOutputFileStreamT(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
: BASIC_OSTREAM(&mBuffer)
{
// already inited
if (!mBuffer.open(inFile, openmode(mode|out), accessMode))
setstate(failbit);
}
#endif // #if defined(DEFINING_FILE_STREAM)
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline OUTPUT_FILE_STREAM::~nsOutputFileStreamT()
//----------------------------------------------------------------------------------------
{
}
#endif // #if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline FILE_BUFFER_TYPE*
OUTPUT_FILE_STREAM::rdbuf() const
//----------------------------------------------------------------------------------------
{
return (FILE_BUFFER_TYPE*)&mBuffer;
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline bool OUTPUT_FILE_STREAM:: is_open()
//----------------------------------------------------------------------------------------
{
return mBuffer.is_open();
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline void OUTPUT_FILE_STREAM::open(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
{
if (!mBuffer.open(inFile, openmode(mode | out), accessMode))
setstate(failbit);
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline void OUTPUT_FILE_STREAM:: close()
//----------------------------------------------------------------------------------------
{
if (!mBuffer.close())
setstate(failbit);
}
//========================================================================================
TEMPLATE_DEF
class nsIOFileStreamT : public BASIC_IOSTREAM
//========================================================================================
{
#ifdef NS_USING_STL
public:
typedef charT char_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
typedef typename traits::int_type int_type;
typedef traits traits_type;
#endif
public:
nsIOFileStreamT();
explicit nsIOFileStreamT(
const nsFilePath& inFile,
IOS_BASE::openmode mode = IOS_BASE::in|IOS_BASE::out,
PRIntn accessMode = 0x00600);
virtual ~nsIOFileStreamT();
FILE_BUFFER_TYPE* rdbuf() const;
inline bool is_open();
inline void open(
const nsFilePath& inFile,
IOS_BASE::openmode mode = IOS_BASE::in|IOS_BASE::out,
PRIntn accessMode = 0x00600);
inline void close();
private:
FILE_BUFFER_TYPE mBuffer;
}; // class nsIOFileStreamT
//========================================================================================
// Implementation of nsIOFileStream
//========================================================================================
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline IO_FILE_STREAM::nsIOFileStreamT()
//----------------------------------------------------------------------------------------
: mBuffer(), BASIC_IOSTREAM(&mBuffer)
{
// already inited
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline IO_FILE_STREAM::nsIOFileStreamT(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
: mBuffer(), BASIC_IOSTREAM(&mBuffer)
{
// already inited
if (!mBuffer.open(inFile, mode, accessMode))
setstate(failbit);
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline IO_FILE_STREAM::~nsIOFileStreamT()
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline FILE_BUFFER_TYPE*
IO_FILE_STREAM::rdbuf() const
//----------------------------------------------------------------------------------------
{
return (FILE_BUFFER_TYPE*)&mBuffer;
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline bool IO_FILE_STREAM::is_open()
//----------------------------------------------------------------------------------------
{
return mBuffer.is_open();
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline void IO_FILE_STREAM::open(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
{
if (!mBuffer.open(inFile, mode, accessMode))
setstate(failbit);
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline void IO_FILE_STREAM::close()
//----------------------------------------------------------------------------------------
{
if (!mBuffer.close())
setstate(failbit);
}
//========================================================================================
// Specializations of the stream templates
//========================================================================================
#ifdef NS_USING_STL
typedef nsFileBufferT<char, char_traits<char> > nsFileBuffer;
typedef nsInputFileStreamT<char, char_traits<char> > nsInputFileStream;
typedef nsOutputFileStreamT<char, char_traits<char> > nsOutputFileStream;
typedef nsIOFileStreamT<char, char_traits<char> > nsIOFileStream;
#ifdef NS_USING_WIDE_CHAR
typedef nsFileBufferT<wchar_t, char_traits<wchar_t> > nsWideFileBuffer;
typedef nsInputFileStreamT<wchar_t, char_traits<wchar_t> > nsWideInputFileStream;
typedef nsOutputFileStreamT<wchar_t, char_traits<wchar_t> > nsWideOutputFileStream;
typedef nsIOFileStreamT<wchar_t, char_traits<wchar_t> > nsWideIOFileStream;
#endif // NS_USING_WIDE_CHAR
#else
typedef nsFileBufferT nsFileBuffer;
typedef nsInputFileStreamT nsInputFileStream;
typedef nsOutputFileStreamT nsOutputFileStream;
typedef nsIOFileStreamT nsIOFileStream;
#endif
nsOutputFileStream& nsEndl(nsOutputFileStream& os);
#endif /* _FILESTREAM_H_ */

View File

@ -491,13 +491,13 @@ nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath)
}
//----------------------------------------------------------------------------------------
ostream& operator << (ostream& s, const nsNativeFileSpec& spec)
nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec& spec)
//----------------------------------------------------------------------------------------
{
s << spec.mSpec.vRefNum << ", " << spec.mSpec.parID << ", \"";
s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]);
return s << "\"";
} // ostream& operator << (ostream&, const nsNativeFileSpec&)
} // nsOutputFileStream& operator << (nsOutputFileStream&, const nsNativeFileSpec&)
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const char* inString)

View File

@ -18,9 +18,11 @@
#include "nsFileSpec.h"
#include "nsFileStream.h"
#include "prtypes.h"
#ifdef NS_USING_NAMESPACE
#ifdef NS_USING_STL
#include <strstream>
@ -257,7 +259,7 @@ void nsFileURL::operator = (const nsNativeFileSpec& inOther)
} // nsFileURL::operator =
//----------------------------------------------------------------------------------------
ostream& operator << (ostream& s, const nsFileURL& url)
nsOutputFileStream& operator << (nsOutputFileStream& s, const nsFileURL& url)
//----------------------------------------------------------------------------------------
{
return (s << url.mURL);
@ -479,7 +481,7 @@ void nsNativeFileSpec::operator = (const char* inString)
#if (defined(XP_UNIX) || defined(XP_PC))
//----------------------------------------------------------------------------------------
ostream& operator << (ostream& s, const nsNativeFileSpec& spec)
nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec& spec)
//----------------------------------------------------------------------------------------
{
return (s << (const char*)spec.mPath);

View File

@ -27,35 +27,69 @@
#include "nsFileStream.h"
#include <string.h>
#include <stdio.h>
#ifdef XP_MAC
#include <Errors.h>
#endif
//========================================================================================
// nsBasicFileStream
//========================================================================================
//----------------------------------------------------------------------------------------
PRFileDesc* nsFileStreamHelpers::open(
nsBasicFileStream::nsBasicFileStream()
//----------------------------------------------------------------------------------------
: mFileDesc(0)
, mNSPRMode(0)
, mFailed(false)
, mEOF(false)
{
}
//----------------------------------------------------------------------------------------
nsBasicFileStream::nsBasicFileStream(
const nsFilePath& inFile,
int nsprMode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
: mFileDesc(0)
, mNSPRMode(0)
, mFailed(false)
, mEOF(false)
{
open(inFile, nsprMode, accessMode);
}
//----------------------------------------------------------------------------------------
nsBasicFileStream::nsBasicFileStream(PRFileDesc* desc, int nsprMode)
//----------------------------------------------------------------------------------------
: mFileDesc(desc)
, mNSPRMode(nsprMode)
, mFailed(false)
, mEOF(false)
{
}
//----------------------------------------------------------------------------------------
nsBasicFileStream::~nsBasicFileStream()
//----------------------------------------------------------------------------------------
{
close();
}
//----------------------------------------------------------------------------------------
void nsBasicFileStream::open(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
int nsprMode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
{
PRFileDesc* descriptor = 0;
const IOS_BASE::openmode valid_modes[]=
{
IOS_BASE::out,
IOS_BASE::out | IOS_BASE::app,
IOS_BASE::out | IOS_BASE::trunc,
IOS_BASE::in,
IOS_BASE::in | IOS_BASE::out,
IOS_BASE::in | IOS_BASE::out | IOS_BASE::trunc,
// IOS_BASE::out | IOS_BASE::binary,
// IOS_BASE::out | IOS_BASE::app | IOS_BASE::binary,
// IOS_BASE::out | IOS_BASE::trunc | IOS_BASE::binary,
// IOS_BASE::in | IOS_BASE::binary,
// IOS_BASE::in | IOS_BASE::out | IOS_BASE::binary,
// IOS_BASE::in | IOS_BASE::out | IOS_BASE::trunc | IOS_BASE::binary,
0
};
if (mFileDesc)
return;
const int nspr_modes[]={
PR_WRONLY | PR_CREATE_FILE,
PR_WRONLY | PR_CREATE_FILE | PR_APPEND,
@ -71,19 +105,19 @@ PRFileDesc* nsFileStreamHelpers::open(
// "r+b",
// "w+b",
0 };
int ind=0;
while (valid_modes[ind] && valid_modes[ind] != (mode&~IOS_BASE::ate))
++ind;
if (!nspr_modes[ind])
return 0;
const int* currentLegalMode = nspr_modes;
while (*currentLegalMode && nsprMode != *currentLegalMode)
++currentLegalMode;
if (!*currentLegalMode)
return;
#ifdef XP_MAC
// Use the file spec to open the file, because one path can be common to
// several files on the Macintosh (you can have several volumes with the
// same name, see).
descriptor = 0;
mFileDesc = 0;
if (inFile.GetNativeSpec().Error() != noErr)
return 0;
return;
OSErr err = noErr;
#if DEBUG
const OSType kCreator = 'CWIE';
@ -92,17 +126,17 @@ PRFileDesc* nsFileStreamHelpers::open(
#endif
nsNativeFileSpec nativeSpec = inFile.GetNativeSpec();
FSSpec* spec = (FSSpec*)nativeSpec;
if (nspr_modes[ind] & PR_CREATE_FILE)
if (nsprMode & PR_CREATE_FILE)
err = FSpCreate(spec, kCreator, 'TEXT', 0);
if (err == dupFNErr)
err = noErr;
if (err != noErr)
return 0;
return;
SInt8 perm;
if (nspr_modes[ind] & PR_RDWR)
if (nsprMode & PR_RDWR)
perm = fsRdWrPerm;
else if (nspr_modes[ind] & PR_WRONLY)
else if (nsprMode & PR_WRONLY)
perm = fsWrPerm;
else
perm = fsRdPerm;
@ -110,24 +144,292 @@ PRFileDesc* nsFileStreamHelpers::open(
short refnum;
err = FSpOpenDF(spec, perm, &refnum);
if (err == noErr && (nspr_modes[ind] & PR_TRUNCATE))
if (err == noErr && (nsprMode & PR_TRUNCATE))
err = SetEOF(refnum, 0);
if (err == noErr && (nspr_modes[ind] & PR_APPEND))
if (err == noErr && (nsprMode & PR_APPEND))
err = SetFPos(refnum, fsFromLEOF, 0);
if (err != noErr)
return 0;
return;
if ((descriptor = PR_ImportFile(refnum)) == 0)
return 0;
if ((mFileDesc = PR_ImportFile(refnum)) == 0)
return;
#else
// Platforms other than Macintosh...
if ((descriptor = PR_Open(inFile, nspr_modes[ind], accessMode)) != 0)
if ((mFileDesc = PR_Open(inFile, nsprMode, accessMode)) == 0)
return;
#endif
if (mode&IOS_BASE::ate && PR_Seek(descriptor, 0, PR_SEEK_END) >= 0)
{
PR_Close(descriptor);
descriptor = 0;
return 0;
}
return descriptor;
mNSPRMode = nsprMode;
} // nsFileStreamHelpers::open
//----------------------------------------------------------------------------------------
void nsBasicFileStream::close()
// Must precede the destructor because both are inline.
//----------------------------------------------------------------------------------------
{
if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0)
return;
if (PR_Close(mFileDesc) == PR_SUCCESS)
mFileDesc = 0;
} // nsBasicFileStream::close
//----------------------------------------------------------------------------------------
void nsBasicFileStream::seek(PRSeekWhence whence, PRInt32 offset)
// Must precede the destructor because both are inline.
//----------------------------------------------------------------------------------------
{
if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0)
return;
mFailed = false; // reset on a seek.
mEOF = false; // reset on a seek.
PRInt32 position = PR_Seek(mFileDesc, 0, PR_SEEK_CUR);
PRInt32 available = PR_Available(mFileDesc);
PRInt32 fileSize = position + available;
PRInt32 newPosition;
switch (whence)
{
case PR_SEEK_CUR: newPosition = position + offset; break;
case PR_SEEK_SET: newPosition = offset; break;
case PR_SEEK_END: newPosition = fileSize + offset; break;
}
if (newPosition < 0)
{
newPosition = 0;
mFailed = true;
}
else if (newPosition >= fileSize)
{
newPosition = fileSize;
mEOF = true;
}
if (PR_Seek(mFileDesc, newPosition, PR_SEEK_SET) < 0)
mFailed = true;
} // nsBasicFileStream::seek
//----------------------------------------------------------------------------------------
PRIntn nsBasicFileStream::tell() const
// Must precede the destructor because both are inline.
//----------------------------------------------------------------------------------------
{
if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0)
return -1;
return PR_Seek(mFileDesc, 0, PR_SEEK_CUR);
} // nsBasicFileStream::tell
//========================================================================================
// nsInputFileStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsInputFileStream::nsInputFileStream(
istream& stream)
//----------------------------------------------------------------------------------------
#ifdef XP_MAC
: nsBasicFileStream(0, kDefaultMode)
, mStdStream(&stream)
#else
: nsBasicFileStream(PR_STDIN, kDefaultMode)
, mStdStream(0)
#endif
{
}
//----------------------------------------------------------------------------------------
void nsInputFileStream::get(char& c)
//----------------------------------------------------------------------------------------
{
read(&c, sizeof(char));
}
//----------------------------------------------------------------------------------------
bool nsInputFileStream::readline(char* s, PRInt32 n)
// This will truncate if the buffer is too small. Result will always be null-terminated.
//----------------------------------------------------------------------------------------
{
bool bufferLargeEnough = true; // result
if (!s || !n)
return true;
PRIntn position = tell();
if (position < 0)
return false;
PRInt32 bytesRead = read(s, n - 1);
if (mFailed)
return false;
s[bytesRead] = '\0'; // always terminate at the end of the buffer
char* tp = strpbrk(s, "\n\r");
if (tp)
{
char ch = *tp;
*tp++ = '\0'; // terminate at the newline, then skip past it
if ((ch == '\n' && *tp == '\r') || (ch == '\r' && *tp == '\n'))
tp++; // possibly a pair.
bytesRead = (tp - s);
}
else if (!eof())
bufferLargeEnough = false;
position += bytesRead;
seek(position);
return bufferLargeEnough;
} // nsInputFileStream::getline
//----------------------------------------------------------------------------------------
PRInt32 nsInputFileStream::read(void* s, PRInt32 n)
//----------------------------------------------------------------------------------------
{
// Calling PR_Read on stdin is sure suicide on Macintosh.
if (mStdStream)
{
mStdStream->read((char*)s, n);
return n;
}
if (!mFileDesc || mFailed)
return -1;
PRInt32 bytesRead = PR_Read(mFileDesc, s, n);
if (bytesRead < 0)
mFailed = true;
else if (bytesRead < n)
mEOF = true;
return bytesRead;
}
//----------------------------------------------------------------------------------------
nsInputFileStream& nsInputFileStream::operator >> (char& c)
//----------------------------------------------------------------------------------------
{
get(c);
return *this;
}
//========================================================================================
// nsOutputFileStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsOutputFileStream::nsOutputFileStream(
ostream& stream)
//----------------------------------------------------------------------------------------
#ifdef XP_MAC
: nsBasicFileStream(0, kDefaultMode)
, mStdStream(&stream)
#else
: nsBasicFileStream(PR_STDOUT, kDefaultMode)
, mStdStream(0)
#endif
{
}
//----------------------------------------------------------------------------------------
void nsOutputFileStream::put(char c)
//----------------------------------------------------------------------------------------
{
write(&c, sizeof(c));
}
//----------------------------------------------------------------------------------------
PRInt32 nsOutputFileStream::write(const void* s, PRInt32 n)
//----------------------------------------------------------------------------------------
{
// Calling PR_Write on stdout is sure suicide.
if (mStdStream)
{
mStdStream->write((const char*)s, n);
return n;
}
if (!mFileDesc || mFailed)
return -1;
PRInt32 bytesWrit = PR_Write(mFileDesc, s, n);
if (bytesWrit != n)
mFailed = true;
return bytesWrit;
}
//----------------------------------------------------------------------------------------
nsOutputFileStream& nsOutputFileStream::operator << (char c)
//----------------------------------------------------------------------------------------
{
put(c);
return *this;
}
//----------------------------------------------------------------------------------------
nsOutputFileStream& nsOutputFileStream::operator << (const char* s)
//----------------------------------------------------------------------------------------
{
write(s, strlen(s));
return *this;
}
//----------------------------------------------------------------------------------------
nsOutputFileStream& nsOutputFileStream::operator << (short val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%d", val);
return *this << buf;
}
//----------------------------------------------------------------------------------------
nsOutputFileStream& nsOutputFileStream::operator << (unsigned short val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%ud", val);
return *this << buf;
}
//----------------------------------------------------------------------------------------
nsOutputFileStream& nsOutputFileStream::operator << (long val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%ld", val);
return *this << buf;
}
//----------------------------------------------------------------------------------------
nsOutputFileStream& nsOutputFileStream::operator << (unsigned long val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%uld", val);
return *this << buf;
}
//----------------------------------------------------------------------------------------
void nsOutputFileStream::flush()
// Must precede the destructor because both are inline.
//----------------------------------------------------------------------------------------
{
if (mStdStream)
{
mStdStream->flush();
return;
}
if (mFileDesc == 0)
return;
bool itFailed = PR_Sync(mFileDesc) != PR_SUCCESS;
#ifdef XP_MAC
// On unix, it seems to fail always.
if (itFailed)
mFailed = true;
#endif
} // nsOutputFileStream::flush
//========================================================================================
// Manipulators
//========================================================================================
//----------------------------------------------------------------------------------------
nsOutputFileStream& nsEndl(nsOutputFileStream& os)
//----------------------------------------------------------------------------------------
{
// Calling PR_Write on stdout is sure suicide on Macintosh.
ostream* stream = os.GetStandardStream();
if (stream)
{
*stream << endl;
return os;
}
os.put('\n');
os.flush();
return os;
}

View File

@ -1,53 +1,46 @@
#include "nsFileSpec.h"
#include "nsFileStream.h"
#ifdef NS_USING_STL
#include <iostream>
using namespace std;
#else
#include <iostream.h>
#endif
NS_NAMESPACE FileTest
{
NS_NAMESPACE_PROTOTYPE void WriteStuff(ostream& s);
NS_NAMESPACE_PROTOTYPE void WriteStuff(nsOutputFileStream& s);
} NS_NAMESPACE_END
//----------------------------------------------------------------------------------------
void FileTest::WriteStuff(ostream& s)
void FileTest::WriteStuff(nsOutputFileStream& s)
//----------------------------------------------------------------------------------------
{
// Initialize a URL from a string without suffix. Change the path to suit your machine.
nsFileURL fileURL("file:///Development/MPW/MPW%20Shell");
s << "File URL initialized to: \"" << fileURL << "\""<< endl;
s << "File URL initialized to: \"" << fileURL << "\""<< nsEndl;
// Initialize a Unix path from a URL
nsFilePath filePath(fileURL);
s << "As a unix path: \"" << (const char*)filePath << "\""<< endl;
s << "As a unix path: \"" << (const char*)filePath << "\""<< nsEndl;
// Initialize a native file spec from a URL
nsNativeFileSpec fileSpec(fileURL);
s << "As a file spec: " << fileSpec << endl;
s << "As a file spec: " << fileSpec << nsEndl;
// Make the spec unique (this one has no suffix).
fileSpec.MakeUnique();
s << "Unique file spec: " << fileSpec << endl;
s << "Unique file spec: " << fileSpec << nsEndl;
// Assign the spec to a URL
fileURL = fileSpec;
s << "File URL assigned from spec: \"" << fileURL << "\""<< endl;
s << "File URL assigned from spec: \"" << fileURL << "\""<< nsEndl;
// Assign a unix path using a string with a suffix.
filePath = "/Development/MPW/SysErrs.err";
s << "File path reassigned to: \"" << (const char*)filePath << "\""<< endl;
s << "File path reassigned to: \"" << (const char*)filePath << "\""<< nsEndl;
// Assign to a file spec using a unix path.
fileSpec = filePath;
s << "File spec reassigned to: " << fileSpec << endl;
s << "File spec reassigned to: " << fileSpec << nsEndl;
// Make this unique (this one has a suffix).
fileSpec.MakeUnique();
s << "File spec made unique: " << fileSpec << endl;
s << "File spec made unique: " << fileSpec << nsEndl;
} // WriteStuff
//----------------------------------------------------------------------------------------
@ -58,33 +51,36 @@ void main()
// Test of nsFileSpec
cout << "WRITING TEST OUTPUT TO cout" << endl << endl;
FileTest::WriteStuff(cout);
cout << endl << endl;
nsOutputFileStream nsOut(cout);
nsOut << "WRITING TEST OUTPUT TO cout" << nsEndl << nsEndl;
FileTest::WriteStuff(nsOut);
nsOut << nsEndl << nsEndl;
// Test of nsOutputFileStream
nsFilePath myTextFilePath("/Development/iotest.txt");
{
cout << "WRITING IDENTICAL OUTPUT TO " << (const char*)myTextFilePath << endl << endl;
nsOut << "WRITING IDENTICAL OUTPUT TO " << (const char*)myTextFilePath << nsEndl << nsEndl;
nsOutputFileStream testStream(myTextFilePath);
NS_ASSERTION(testStream.is_open(), "File could not be opened");
FileTest::WriteStuff(testStream);
} // <-- Scope closes the stream (and the file).
// Test of nsInputFileStream
{
cout << "READING BACK DATA FROM " << (const char*)myTextFilePath << endl << endl;
nsOut << "READING BACK DATA FROM " << (const char*)myTextFilePath << nsEndl << nsEndl;
nsInputFileStream testStream2(myTextFilePath);
NS_ASSERTION(testStream2.is_open(), "File could not be opened");
char line[1000];
testStream2.seekg(0); // check that the seek template compiles
testStream2.seek(0); // check that the seek compiles
while (!testStream2.eof())
{
testStream2.getline(line, sizeof(line), '\n');
cout << line << endl;
testStream2.readline(line, sizeof(line));
nsOut << line << nsEndl;
}
}
} // main

View File

@ -18,9 +18,11 @@
#include "nsFileSpec.h"
#include "nsFileStream.h"
#include "prtypes.h"
#ifdef NS_USING_NAMESPACE
#ifdef NS_USING_STL
#include <strstream>
@ -257,7 +259,7 @@ void nsFileURL::operator = (const nsNativeFileSpec& inOther)
} // nsFileURL::operator =
//----------------------------------------------------------------------------------------
ostream& operator << (ostream& s, const nsFileURL& url)
nsOutputFileStream& operator << (nsOutputFileStream& s, const nsFileURL& url)
//----------------------------------------------------------------------------------------
{
return (s << url.mURL);
@ -479,7 +481,7 @@ void nsNativeFileSpec::operator = (const char* inString)
#if (defined(XP_UNIX) || defined(XP_PC))
//----------------------------------------------------------------------------------------
ostream& operator << (ostream& s, const nsNativeFileSpec& spec)
nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec& spec)
//----------------------------------------------------------------------------------------
{
return (s << (const char*)spec.mPath);

View File

@ -37,15 +37,14 @@
// to the moment Communicator 4.5 shipped.
//
// 3. Used in conjunction with nsFileStream.h (q.v.), this supports all the power
// and readability of the ansi stream syntax. ALL METHODS OF istream, ostream,
// AND iostream ARE AVAILABLE!
// and readability of the ansi stream syntax.
//
// Basic example:
//
// nsFilePath myPath("/Development/iotest.txt");
//
// nsOutputFileStream testStream(myPath);
// testStream << "Hello World" << endl;
// testStream << "Hello World" << nsEndl;
//
// 4. Handy methods for manipulating file specifiers safely, e.g. MakeUnique(),
// SetLeafName(), Exists().
@ -117,14 +116,11 @@
#define NS_NAMESPACE_PROTOTYPE
#define NS_NAMESPACE namespace
#define NS_NAMESPACE_END
#include <ostream>
using std::ostream;
#else
#define NS_NAMESPACE_PROTOTYPE static
#define NS_NAMESPACE struct
#define NS_NAMESPACE_END ;
#include <ostream.h>
#endif
//=========================== End Compiler-specific macros ===============================
@ -144,6 +140,8 @@ class nsNativeFileSpec;
#define kFileURLPrefix "file://"
#define kFileURLPrefixLength (7)
class nsOutputFileStream;
//========================================================================================
class NS_BASE nsNativeFileSpec
// This is whatever each platform really prefers to describe files as. Declared first
@ -196,7 +194,7 @@ class NS_BASE nsNativeFileSpec
bool Valid() const { return true; } // Fixme.
#endif // XP_MAC
friend NS_BASE ostream& operator << (ostream& s, const nsNativeFileSpec& spec);
friend NS_BASE nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec& spec);
char* GetLeafName() const; // Allocated. Use delete [].
void SetLeafName(const char* inLeafName);
@ -237,7 +235,8 @@ class NS_BASE nsFileURL
void operator = (const nsFilePath& inOther);
void operator = (const nsNativeFileSpec& inOther);
friend NS_BASE ostream& operator << (ostream& s, const nsFileURL& spec);
friend NS_BASE nsOutputFileStream& operator << (
nsOutputFileStream& s, const nsFileURL& spec);
#ifdef XP_MAC
// Accessor to allow quick assignment to a mNativeFileSpec

View File

@ -491,13 +491,13 @@ nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath)
}
//----------------------------------------------------------------------------------------
ostream& operator << (ostream& s, const nsNativeFileSpec& spec)
nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec& spec)
//----------------------------------------------------------------------------------------
{
s << spec.mSpec.vRefNum << ", " << spec.mSpec.parID << ", \"";
s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]);
return s << "\"";
} // ostream& operator << (ostream&, const nsNativeFileSpec&)
} // nsOutputFileStream& operator << (nsOutputFileStream&, const nsNativeFileSpec&)
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const char* inString)

View File

@ -27,35 +27,69 @@
#include "nsFileStream.h"
#include <string.h>
#include <stdio.h>
#ifdef XP_MAC
#include <Errors.h>
#endif
//========================================================================================
// nsBasicFileStream
//========================================================================================
//----------------------------------------------------------------------------------------
PRFileDesc* nsFileStreamHelpers::open(
nsBasicFileStream::nsBasicFileStream()
//----------------------------------------------------------------------------------------
: mFileDesc(0)
, mNSPRMode(0)
, mFailed(false)
, mEOF(false)
{
}
//----------------------------------------------------------------------------------------
nsBasicFileStream::nsBasicFileStream(
const nsFilePath& inFile,
int nsprMode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
: mFileDesc(0)
, mNSPRMode(0)
, mFailed(false)
, mEOF(false)
{
open(inFile, nsprMode, accessMode);
}
//----------------------------------------------------------------------------------------
nsBasicFileStream::nsBasicFileStream(PRFileDesc* desc, int nsprMode)
//----------------------------------------------------------------------------------------
: mFileDesc(desc)
, mNSPRMode(nsprMode)
, mFailed(false)
, mEOF(false)
{
}
//----------------------------------------------------------------------------------------
nsBasicFileStream::~nsBasicFileStream()
//----------------------------------------------------------------------------------------
{
close();
}
//----------------------------------------------------------------------------------------
void nsBasicFileStream::open(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
int nsprMode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
{
PRFileDesc* descriptor = 0;
const IOS_BASE::openmode valid_modes[]=
{
IOS_BASE::out,
IOS_BASE::out | IOS_BASE::app,
IOS_BASE::out | IOS_BASE::trunc,
IOS_BASE::in,
IOS_BASE::in | IOS_BASE::out,
IOS_BASE::in | IOS_BASE::out | IOS_BASE::trunc,
// IOS_BASE::out | IOS_BASE::binary,
// IOS_BASE::out | IOS_BASE::app | IOS_BASE::binary,
// IOS_BASE::out | IOS_BASE::trunc | IOS_BASE::binary,
// IOS_BASE::in | IOS_BASE::binary,
// IOS_BASE::in | IOS_BASE::out | IOS_BASE::binary,
// IOS_BASE::in | IOS_BASE::out | IOS_BASE::trunc | IOS_BASE::binary,
0
};
if (mFileDesc)
return;
const int nspr_modes[]={
PR_WRONLY | PR_CREATE_FILE,
PR_WRONLY | PR_CREATE_FILE | PR_APPEND,
@ -71,19 +105,19 @@ PRFileDesc* nsFileStreamHelpers::open(
// "r+b",
// "w+b",
0 };
int ind=0;
while (valid_modes[ind] && valid_modes[ind] != (mode&~IOS_BASE::ate))
++ind;
if (!nspr_modes[ind])
return 0;
const int* currentLegalMode = nspr_modes;
while (*currentLegalMode && nsprMode != *currentLegalMode)
++currentLegalMode;
if (!*currentLegalMode)
return;
#ifdef XP_MAC
// Use the file spec to open the file, because one path can be common to
// several files on the Macintosh (you can have several volumes with the
// same name, see).
descriptor = 0;
mFileDesc = 0;
if (inFile.GetNativeSpec().Error() != noErr)
return 0;
return;
OSErr err = noErr;
#if DEBUG
const OSType kCreator = 'CWIE';
@ -92,17 +126,17 @@ PRFileDesc* nsFileStreamHelpers::open(
#endif
nsNativeFileSpec nativeSpec = inFile.GetNativeSpec();
FSSpec* spec = (FSSpec*)nativeSpec;
if (nspr_modes[ind] & PR_CREATE_FILE)
if (nsprMode & PR_CREATE_FILE)
err = FSpCreate(spec, kCreator, 'TEXT', 0);
if (err == dupFNErr)
err = noErr;
if (err != noErr)
return 0;
return;
SInt8 perm;
if (nspr_modes[ind] & PR_RDWR)
if (nsprMode & PR_RDWR)
perm = fsRdWrPerm;
else if (nspr_modes[ind] & PR_WRONLY)
else if (nsprMode & PR_WRONLY)
perm = fsWrPerm;
else
perm = fsRdPerm;
@ -110,24 +144,292 @@ PRFileDesc* nsFileStreamHelpers::open(
short refnum;
err = FSpOpenDF(spec, perm, &refnum);
if (err == noErr && (nspr_modes[ind] & PR_TRUNCATE))
if (err == noErr && (nsprMode & PR_TRUNCATE))
err = SetEOF(refnum, 0);
if (err == noErr && (nspr_modes[ind] & PR_APPEND))
if (err == noErr && (nsprMode & PR_APPEND))
err = SetFPos(refnum, fsFromLEOF, 0);
if (err != noErr)
return 0;
return;
if ((descriptor = PR_ImportFile(refnum)) == 0)
return 0;
if ((mFileDesc = PR_ImportFile(refnum)) == 0)
return;
#else
// Platforms other than Macintosh...
if ((descriptor = PR_Open(inFile, nspr_modes[ind], accessMode)) != 0)
if ((mFileDesc = PR_Open(inFile, nsprMode, accessMode)) == 0)
return;
#endif
if (mode&IOS_BASE::ate && PR_Seek(descriptor, 0, PR_SEEK_END) >= 0)
{
PR_Close(descriptor);
descriptor = 0;
return 0;
}
return descriptor;
mNSPRMode = nsprMode;
} // nsFileStreamHelpers::open
//----------------------------------------------------------------------------------------
void nsBasicFileStream::close()
// Must precede the destructor because both are inline.
//----------------------------------------------------------------------------------------
{
if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0)
return;
if (PR_Close(mFileDesc) == PR_SUCCESS)
mFileDesc = 0;
} // nsBasicFileStream::close
//----------------------------------------------------------------------------------------
void nsBasicFileStream::seek(PRSeekWhence whence, PRInt32 offset)
// Must precede the destructor because both are inline.
//----------------------------------------------------------------------------------------
{
if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0)
return;
mFailed = false; // reset on a seek.
mEOF = false; // reset on a seek.
PRInt32 position = PR_Seek(mFileDesc, 0, PR_SEEK_CUR);
PRInt32 available = PR_Available(mFileDesc);
PRInt32 fileSize = position + available;
PRInt32 newPosition;
switch (whence)
{
case PR_SEEK_CUR: newPosition = position + offset; break;
case PR_SEEK_SET: newPosition = offset; break;
case PR_SEEK_END: newPosition = fileSize + offset; break;
}
if (newPosition < 0)
{
newPosition = 0;
mFailed = true;
}
else if (newPosition >= fileSize)
{
newPosition = fileSize;
mEOF = true;
}
if (PR_Seek(mFileDesc, newPosition, PR_SEEK_SET) < 0)
mFailed = true;
} // nsBasicFileStream::seek
//----------------------------------------------------------------------------------------
PRIntn nsBasicFileStream::tell() const
// Must precede the destructor because both are inline.
//----------------------------------------------------------------------------------------
{
if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0)
return -1;
return PR_Seek(mFileDesc, 0, PR_SEEK_CUR);
} // nsBasicFileStream::tell
//========================================================================================
// nsInputFileStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsInputFileStream::nsInputFileStream(
istream& stream)
//----------------------------------------------------------------------------------------
#ifdef XP_MAC
: nsBasicFileStream(0, kDefaultMode)
, mStdStream(&stream)
#else
: nsBasicFileStream(PR_STDIN, kDefaultMode)
, mStdStream(0)
#endif
{
}
//----------------------------------------------------------------------------------------
void nsInputFileStream::get(char& c)
//----------------------------------------------------------------------------------------
{
read(&c, sizeof(char));
}
//----------------------------------------------------------------------------------------
bool nsInputFileStream::readline(char* s, PRInt32 n)
// This will truncate if the buffer is too small. Result will always be null-terminated.
//----------------------------------------------------------------------------------------
{
bool bufferLargeEnough = true; // result
if (!s || !n)
return true;
PRIntn position = tell();
if (position < 0)
return false;
PRInt32 bytesRead = read(s, n - 1);
if (mFailed)
return false;
s[bytesRead] = '\0'; // always terminate at the end of the buffer
char* tp = strpbrk(s, "\n\r");
if (tp)
{
char ch = *tp;
*tp++ = '\0'; // terminate at the newline, then skip past it
if ((ch == '\n' && *tp == '\r') || (ch == '\r' && *tp == '\n'))
tp++; // possibly a pair.
bytesRead = (tp - s);
}
else if (!eof())
bufferLargeEnough = false;
position += bytesRead;
seek(position);
return bufferLargeEnough;
} // nsInputFileStream::getline
//----------------------------------------------------------------------------------------
PRInt32 nsInputFileStream::read(void* s, PRInt32 n)
//----------------------------------------------------------------------------------------
{
// Calling PR_Read on stdin is sure suicide on Macintosh.
if (mStdStream)
{
mStdStream->read((char*)s, n);
return n;
}
if (!mFileDesc || mFailed)
return -1;
PRInt32 bytesRead = PR_Read(mFileDesc, s, n);
if (bytesRead < 0)
mFailed = true;
else if (bytesRead < n)
mEOF = true;
return bytesRead;
}
//----------------------------------------------------------------------------------------
nsInputFileStream& nsInputFileStream::operator >> (char& c)
//----------------------------------------------------------------------------------------
{
get(c);
return *this;
}
//========================================================================================
// nsOutputFileStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsOutputFileStream::nsOutputFileStream(
ostream& stream)
//----------------------------------------------------------------------------------------
#ifdef XP_MAC
: nsBasicFileStream(0, kDefaultMode)
, mStdStream(&stream)
#else
: nsBasicFileStream(PR_STDOUT, kDefaultMode)
, mStdStream(0)
#endif
{
}
//----------------------------------------------------------------------------------------
void nsOutputFileStream::put(char c)
//----------------------------------------------------------------------------------------
{
write(&c, sizeof(c));
}
//----------------------------------------------------------------------------------------
PRInt32 nsOutputFileStream::write(const void* s, PRInt32 n)
//----------------------------------------------------------------------------------------
{
// Calling PR_Write on stdout is sure suicide.
if (mStdStream)
{
mStdStream->write((const char*)s, n);
return n;
}
if (!mFileDesc || mFailed)
return -1;
PRInt32 bytesWrit = PR_Write(mFileDesc, s, n);
if (bytesWrit != n)
mFailed = true;
return bytesWrit;
}
//----------------------------------------------------------------------------------------
nsOutputFileStream& nsOutputFileStream::operator << (char c)
//----------------------------------------------------------------------------------------
{
put(c);
return *this;
}
//----------------------------------------------------------------------------------------
nsOutputFileStream& nsOutputFileStream::operator << (const char* s)
//----------------------------------------------------------------------------------------
{
write(s, strlen(s));
return *this;
}
//----------------------------------------------------------------------------------------
nsOutputFileStream& nsOutputFileStream::operator << (short val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%d", val);
return *this << buf;
}
//----------------------------------------------------------------------------------------
nsOutputFileStream& nsOutputFileStream::operator << (unsigned short val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%ud", val);
return *this << buf;
}
//----------------------------------------------------------------------------------------
nsOutputFileStream& nsOutputFileStream::operator << (long val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%ld", val);
return *this << buf;
}
//----------------------------------------------------------------------------------------
nsOutputFileStream& nsOutputFileStream::operator << (unsigned long val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%uld", val);
return *this << buf;
}
//----------------------------------------------------------------------------------------
void nsOutputFileStream::flush()
// Must precede the destructor because both are inline.
//----------------------------------------------------------------------------------------
{
if (mStdStream)
{
mStdStream->flush();
return;
}
if (mFileDesc == 0)
return;
bool itFailed = PR_Sync(mFileDesc) != PR_SUCCESS;
#ifdef XP_MAC
// On unix, it seems to fail always.
if (itFailed)
mFailed = true;
#endif
} // nsOutputFileStream::flush
//========================================================================================
// Manipulators
//========================================================================================
//----------------------------------------------------------------------------------------
nsOutputFileStream& nsEndl(nsOutputFileStream& os)
//----------------------------------------------------------------------------------------
{
// Calling PR_Write on stdout is sure suicide on Macintosh.
ostream* stream = os.GetStandardStream();
if (stream)
{
*stream << endl;
return os;
}
os.put('\n');
os.flush();
return os;
}

View File

@ -26,11 +26,7 @@
//
// single-byte char:
//
// nsInputFileStream, nsOutputFileStream, nsIOFileStream
//
// wide char:
//
// nsWideInputFileStream, nsWideOutputFileStream, nsWideIOFileStream
// nsInputFileStream, nsOutputFileStream
//
// This suite provide the following services:
//
@ -41,16 +37,14 @@
// native performance. This performance difference is especially large on
// macintosh.
//
// 3. Allows all the power of the ansi stream syntax: these streams
// ARE derived classes of ostream, istream, and iostream. ALL METHODS OF
// istream, ostream, AND iostream ARE AVAILABLE!
// 3. Allows all the power of the ansi stream syntax.
//
// Basic example:
//
// nsFilePath myPath("/Development/iotest.txt");
//
// nsOutputFileStream testStream(myPath);
// testStream << "Hello World" << endl;
// testStream << "Hello World" << nsEndl;
//
// 4. Requires streams to be constructed using typesafe nsFilePath specifier
// (not the notorious and bug prone const char*), namely nsFilePath. See
@ -107,831 +101,151 @@
#endif // NS_USING_NAMESPACE
#ifdef NS_USING_STL
// Macintosh and Windows use this section.
//
// Here's where the party is. When Unix wants to join in (by supporting
// a build system with STL headers), what fun we'll have! Meanwhile, I've used
// macros to make this build on all our platforms. Unix doesn't have support for
// STL, and therefore we could not use the template forms of these classes on Unix.
// (it's a long story). Therefore, Unix supports no stream char types except 1-byte
// characters, and therefore nobody else does now either, until Unix catches up.
#define DEFINING_FILE_STREAM // templateers define this when this file is included.
#define IOS_BASE ios_base
#include <istream>
using std::ios_base;
using std::basic_streambuf;
using std::codecvt_base;
using std::codecvt;
using std::streamsize;
using std::locale;
using std::basic_istream;
using std::basic_ostream;
using std::basic_iostream;
using std::char_traits;
#define TEMPLATE_DEF template<class charT, class traits>
#define FILE_BUFFER_TYPE nsFileBufferT<charT, traits>
#define INPUT_FILE_STREAM nsInputFileStreamT<charT, traits>
#define OUTPUT_FILE_STREAM nsOutputFileStreamT<charT, traits>
#define IO_FILE_STREAM nsIOFileStreamT<charT, traits>
#define BASIC_STREAMBUF basic_streambuf<charT, traits>
#define BASIC_ISTREAM basic_istream<charT, traits>
#define BASIC_OSTREAM basic_ostream<charT, traits>
#define BASIC_IOSTREAM basic_iostream<charT, traits>
#define INT_TYPE FILE_BUFFER_TYPE::int_type
#define POS_TYPE FILE_BUFFER_TYPE::pos_type
#define OFF_TYPE FILE_BUFFER_TYPE::off_type
#define SEEK_DIR IOS_BASE::seekdir
#define EOF_VALUE traits::eof()
#include <iostream>
using std::istream;
using std::ostream;
#else
// Unix uses this section until it supports STL. This means no locales, no traits,
// no wide chars, etc. Also, the stream classes are the original ARM-style ones,
// and are not templatized.
#define IOS_BASE ios
#include <istream.h>
#define TEMPLATE_DEF
#define FILE_BUFFER_TYPE nsFileBufferT
#define INPUT_FILE_STREAM nsInputFileStreamT
#define OUTPUT_FILE_STREAM nsOutputFileStreamT
#define IO_FILE_STREAM nsIOFileStreamT
#define BASIC_STREAMBUF streambuf
#define BASIC_ISTREAM istream
#define BASIC_OSTREAM ostream
#define BASIC_IOSTREAM iostream
#define INT_TYPE int
#define POS_TYPE long
#define OFF_TYPE long
#define SEEK_DIR ios::seek_dir
#define int_type int
#define pos_type long
#define off_type long
#define char_type char
#define EOF_VALUE EOF
#endif // NS_USING_STL
#ifdef __MWERKS__
#ifdef MSIPL_WCHART
#define NS_USING_WIDE_CHAR
#include <iostream.h>
#endif
#ifdef MSIPL_EXPLICIT_FUNC_TEMPLATE_ARG
#define NS_EXPLICIT_FUNC_TEMPLATE_ARG
#endif
#define NS_READ_LOCK(mut) READ_LOCK(mut)
#define NS_WRITE_LOCK(mut) WRITE_LOCK(mut)
#else
// Fix me, if necessary, for thread-safety.
#define NS_READ_LOCK(mut)
#define NS_WRITE_LOCK(mut)
#endif // __MWERKS__
//=========================== End Compiler-specific macros ===============================
//========================================================================================
NS_NAMESPACE nsFileStreamHelpers
// Prototypes for common (non-template) implementations in the .cpp file which do not
// need the template args (charT, traits).
class NS_BASE nsBasicFileStream
//========================================================================================
{
NS_NAMESPACE_PROTOTYPE NS_BASE PRFileDesc* open(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode);
} NS_NAMESPACE_END // nsFileStreamHelpers
//========================================================================================
// Template declarations
//========================================================================================
//========================================================================================
TEMPLATE_DEF
class nsFileBufferT
//========================================================================================
: public BASIC_STREAMBUF
{
#ifdef NS_USING_STL
typedef codecvt_base::result result;
public:
typedef charT char_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
typedef typename traits::int_type int_type;
typedef traits traits_type;
typedef typename traits::state_type state_type;
nsBasicFileStream();
nsBasicFileStream(PRFileDesc* desc, int nsprMode);
nsBasicFileStream(
const nsFilePath& inFile,
int nsprMode,
PRIntn accessMode);
virtual ~nsBasicFileStream();
typedef codecvt<charT, char, state_type> ofacet_type;
typedef codecvt<char, charT, state_type> ifacet_type;
#endif
public:
nsFileBufferT();
nsFileBufferT(PRFileDesc* pfile_arg);
virtual ~nsFileBufferT();
bool is_open() const;
FILE_BUFFER_TYPE* open(
inline bool is_open() const { return mFileDesc != 0; }
void open(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
int nsprMode,
PRIntn accessMode);
FILE_BUFFER_TYPE* close();
void close();
PRIntn tell() const;
void seek(PRInt32 offset) { seek(PR_SEEK_SET, offset); }
void seek(PRSeekWhence whence, PRInt32 offset);
bool eof() const { return mEOF; }
bool failed() const { return mFailed; }
// call PR_GetError() for details
protected:
virtual int_type overflow(int_type c=EOF_VALUE);
virtual int_type pbackfail(int_type c=EOF_VALUE);
virtual int_type underflow();
virtual pos_type seekoff(
off_type off, SEEK_DIR way,
IOS_BASE::openmode which=IOS_BASE::in|IOS_BASE::out);
virtual pos_type seekpos(pos_type sp,
IOS_BASE::openmode which=IOS_BASE::in|IOS_BASE::out);
virtual BASIC_STREAMBUF* setbuf(char_type* s, streamsize n);
virtual int sync();
virtual int_type uflow();
#ifdef NS_USING_STL
virtual void imbue(const locale& loc);
#endif
virtual streamsize showmanyc();
virtual streamsize xsgetn(char_type* s, streamsize n);
virtual streamsize xsputn(const char_type* s, streamsize n);
private:
PRFileDesc* mFileDesc;
IOS_BASE::openmode mode_;
}; // class nsFileBufferT
PRFileDesc* mFileDesc;
int mNSPRMode;
bool mFailed;
bool mEOF;
}; // class nsBasicFileStream
//========================================================================================
TEMPLATE_DEF
class nsInputFileStreamT
class NS_BASE nsInputFileStream
//========================================================================================
: public BASIC_ISTREAM
: public nsBasicFileStream
{
#ifdef NS_USING_STL
public:
typedef charT char_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
typedef typename traits::int_type int_type;
typedef traits traits_type;
#endif
public:
nsInputFileStreamT();
explicit nsInputFileStreamT(
enum { kDefaultMode = PR_RDONLY };
nsInputFileStream()
: nsBasicFileStream()
, mStdStream(0) {}
nsInputFileStream(
istream& stream);
nsInputFileStream(
const nsFilePath& inFile,
IOS_BASE::openmode mode=IOS_BASE::in,
PRIntn accessMode = 0x00400);
int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00400)
: nsBasicFileStream(inFile, nsprMode, accessMode)
, mStdStream(0) {}
virtual ~nsInputFileStreamT();
nsInputFileStream& operator >> (nsInputFileStream& (*pf)(nsInputFileStream&))
{
return pf(*this);
}
void get(char& c);
PRInt32 read(void* s, PRInt32 n);
bool readline(char* s, PRInt32 n);
// Result always null-terminated
// false result indicates line was truncated
// to fit buffer, or an error occurred.
FILE_BUFFER_TYPE* rdbuf() const;
inline bool is_open();
inline void open(
// Output streamers. Add more as needed
nsInputFileStream& operator >> (char& ch);
void open(
const nsFilePath& inFile,
IOS_BASE::openmode mode=IOS_BASE::in,
PRIntn accessMode = 0x00400);
inline void close();
int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00400)
{
nsBasicFileStream::open(inFile, nsprMode, accessMode);
}
private:
FILE_BUFFER_TYPE mBuffer;
}; // class nsInputFileStreamT
nsInputFileStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE.
protected:
istream* mStdStream;
}; // class nsInputFileStream
//========================================================================================
TEMPLATE_DEF
class nsOutputFileStreamT
class NS_BASE nsOutputFileStream
//========================================================================================
: public BASIC_OSTREAM
: public nsBasicFileStream
{
#ifdef NS_USING_STL
public:
typedef charT char_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
typedef typename traits::int_type int_type;
typedef traits traits_type;
#endif
public:
enum { kDefaultMode = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE) };
nsOutputFileStreamT();
explicit nsOutputFileStreamT(
nsOutputFileStream()
: nsBasicFileStream()
, mStdStream(0) {}
nsOutputFileStream(
ostream& stream);
nsOutputFileStream(
const nsFilePath& inFile,
IOS_BASE::openmode mode = IOS_BASE::out|IOS_BASE::trunc,
PRIntn accessMode = 0x00200);
int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00200)
: nsBasicFileStream(inFile, nsprMode, accessMode)
, mStdStream(0) {}
virtual ~nsOutputFileStreamT();
FILE_BUFFER_TYPE* rdbuf() const;
inline bool is_open();
ostream* GetStandardStream() const { return mStdStream; }
inline void open(
const nsFilePath& inFile,
IOS_BASE::openmode mode = IOS_BASE::out|IOS_BASE::trunc,
PRIntn accessMode = 0x00200);
inline void close();
int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00200)
{
nsBasicFileStream::open(inFile, nsprMode, accessMode);
}
nsOutputFileStream& operator << (nsOutputFileStream& (*pf)(nsOutputFileStream&))
{
return pf(*this);
}
void put(char c);
PRInt32 write(const void* s, PRInt32 n);
void flush();
// Output streamers. Add more as needed
nsOutputFileStream& operator << (const char* buf);
nsOutputFileStream& operator << (char ch);
nsOutputFileStream& operator << (short val);
nsOutputFileStream& operator << (unsigned short val);
nsOutputFileStream& operator << (long val);
nsOutputFileStream& operator << (unsigned long val);
private:
FILE_BUFFER_TYPE mBuffer;
}; // class nsOutputFileStreamT
protected:
ostream* mStdStream;
}; // class nsOutputFileStream
//========================================================================================
// Implementation of nsFileBufferT
// Manipulators
//========================================================================================
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline FILE_BUFFER_TYPE::nsFileBufferT()
: BASIC_STREAMBUF(), mFileDesc(NULL)
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline FILE_BUFFER_TYPE::nsFileBufferT(PRFileDesc* pfarg)
: BASIC_STREAMBUF(), mFileDesc(pfarg)
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline FILE_BUFFER_TYPE* FILE_BUFFER_TYPE::close()
// Must precede the destructor because both are inline.
//----------------------------------------------------------------------------------------
{
if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR)
return this;
NS_WRITE_LOCK(_mutex);
return (mFileDesc && PR_Close(mFileDesc) == PR_SUCCESS) ? mFileDesc = 0, this : 0;
}
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
FILE_BUFFER_TYPE::~nsFileBufferT()
//----------------------------------------------------------------------------------------
{
close();
}
#endif // #if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline bool
FILE_BUFFER_TYPE::is_open() const
//----------------------------------------------------------------------------------------
{
NS_READ_LOCK(_mutex);
return bool(mFileDesc); // in case it is typedefed to int
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline FILE_BUFFER_TYPE* FILE_BUFFER_TYPE::open(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
{
if (mFileDesc)
return 0;
NS_WRITE_LOCK(_mutex);
mFileDesc = nsFileStreamHelpers::open(inFile, mode, accessMode);
if (!mFileDesc)
return 0;
mode_ = mode;
return this;
} // FILE_BUFFER_TYPE::open
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline int FILE_BUFFER_TYPE:: sync()
//----------------------------------------------------------------------------------------
{
return (mFileDesc ? (int)PR_Sync(mFileDesc) : 0);
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline BASIC_STREAMBUF* FILE_BUFFER_TYPE::setbuf(char_type*, streamsize)
//----------------------------------------------------------------------------------------
{
return (!mFileDesc) ? 0 : this;
}
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
INT_TYPE FILE_BUFFER_TYPE::overflow(int_type c)
//----------------------------------------------------------------------------------------
{
#ifndef NS_USING_STL
char ch = c;
PRInt32 bytesWrit1 = PR_Write(mFileDesc, &ch, sizeof(ch));
return bytesWrit1 < sizeof(ch) ? EOF_VALUE : c;
#else
#ifdef NS_EXPLICIT_FUNC_TEMPLATE_ARG
const ofacet_type& ft=use_facet<ofacet_type>(getloc());
#elif defined(XP_PC)
const ofacet_type& ft=use_facet(getloc(), (ofacet_type*)0, false);
#else
const ofacet_type& ft=use_facet(getloc(), (ofacet_type*)0);
#endif
char_type ch = traits_type::to_char_type(c);
if (!mFileDesc)
return EOF_VALUE;
if (traits_type::eq_int_type(c, EOF_VALUE))
return traits_type::not_eof(c);
if (ft.always_noconv())
{
PRInt32 bytesWrit1 = PR_Write(mFileDesc, &ch, sizeof(ch));
return bytesWrit1 < sizeof(ch) ? EOF_VALUE : c;
}
{ // <- sic!
state_type fst;
const char_type* end;
char buf[4];
char* ebuf;
result conv;
if ((conv=ft.out(fst, &ch, &ch+1, end, buf, buf+3, ebuf))==
codecvt_base::noconv)
{
PRInt32 bytesWrit2 = PR_Write(mFileDesc, &ch, sizeof(ch));
return bytesWrit2 < sizeof(ch) ? EOF_VALUE : c;
}
if ((conv==codecvt_base::partial)||(conv==codecvt_base::error))
return EOF_VALUE;
*ebuf=0;
PRInt32 bytesWrit3 = strlen(buf);
return PR_Write(mFileDesc, buf, bytesWrit3) < bytesWrit3 ? EOF_VALUE : c;
}
#endif
}
#endif // #if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline INT_TYPE FILE_BUFFER_TYPE::underflow()
//----------------------------------------------------------------------------------------
{
if (!mFileDesc)
return EOF_VALUE;
char_type s;
PRInt32 request = 1;
if (1 != PR_Read(mFileDesc, &s, request))
return EOF_VALUE;
PR_Seek(mFileDesc, -1, PR_SEEK_CUR);
return (int_type)s;
}
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
streamsize FILE_BUFFER_TYPE::xsputn(const char_type* s, streamsize n)
//----------------------------------------------------------------------------------------
{
#ifndef NS_USING_STL
PRInt32 bytesWrit1 = PR_Write(mFileDesc, s, sizeof(char) * size_t(n));
return bytesWrit1 < 0 ? 0 : (streamsize)bytesWrit1;
#else
#ifdef NS_EXPLICIT_FUNC_TEMPLATE_ARG
const ofacet_type& ft=use_facet<ofacet_type>(loc);
#elif defined(XP_PC)
const ofacet_type& ft=use_facet(getloc(), (ofacet_type*)0, false);
#else
const ofacet_type& ft=use_facet(getloc(), (ofacet_type*)0);
#endif
if (!mFileDesc || !n)
return 0;
if (ft.always_noconv())
{
PRInt32 bytesWrit1 = PR_Write(mFileDesc, s, sizeof(char) * size_t(n));
return bytesWrit1 < 0 ? 0 : (streamsize)bytesWrit1;
}
{ // <- sic!
state_type fst;
const char_type* end;
char buf[8];
char* ebuf;
result conv;
#ifdef NS_EXPLICIT_FUNC_TEMPLATE_ARG
if ((conv=use_facet<ofacet_type>(getloc()).
#elif defined(XP_PC)
if ((conv=use_facet(getloc(), (ofacet_type*)0, false).
#else
if ((conv=use_facet(getloc(), (ofacet_type*)0).
#endif
out(fst, s, s+n, end, buf, buf+7, ebuf))==codecvt_base::noconv)
return (streamsize)PR_Write(mFileDesc, s, sizeof(char) * size_t(n));
if ((conv==codecvt_base::partial) ||(conv==codecvt_base::error))
return 0;
*ebuf=0;
PRInt32 bytesWrit2 = strlen(buf);
bytesWrit2 = PR_Write(mFileDesc, buf, bytesWrit2);
return bytesWrit2 < 0 ? 0 : streamsize(bytesWrit2 / sizeof(char_type));
}
#endif
} // FILE_BUFFER_TYPE::xsputn
#endif // #if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline INT_TYPE FILE_BUFFER_TYPE::pbackfail(int_type c)
//----------------------------------------------------------------------------------------
{
if (!mFileDesc)
return EOF_VALUE;
if (PR_Seek(mFileDesc, -1, PR_SEEK_CUR) < 0)
return EOF_VALUE;
#ifdef NS_USING_STL
return (traits::eq_int_type(c, EOF_VALUE)) ? traits::not_eof(c) : c;
#else
return c;
#endif
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline INT_TYPE FILE_BUFFER_TYPE::uflow()
//----------------------------------------------------------------------------------------
{
if (!mFileDesc)
return EOF_VALUE;
char_type s;
if (1 != PR_Read(mFileDesc, &s, 1)) // attempt to read 1 byte, confirm 1 byte
return EOF_VALUE;
return (int_type)s;
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline streamsize FILE_BUFFER_TYPE::xsgetn(char_type* s, streamsize n)
//----------------------------------------------------------------------------------------
{
return mFileDesc ? (streamsize)PR_Read(mFileDesc, s, sizeof(char) * size_t(n)) : 0;
}
#ifdef NS_USING_STL
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline void FILE_BUFFER_TYPE::imbue(const locale& loc_arg)
//----------------------------------------------------------------------------------------
{
#ifdef XP_MAC
loc = loc_arg;
#endif
}
#endif
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline streamsize FILE_BUFFER_TYPE::showmanyc()
//----------------------------------------------------------------------------------------
{
return (streamsize)PR_Available(mFileDesc);
}
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
POS_TYPE FILE_BUFFER_TYPE::seekoff(
OFF_TYPE off,
SEEK_DIR way,
IOS_BASE::openmode /* which */)
//----------------------------------------------------------------------------------------
{
if (!mFileDesc ||
#ifdef NS_USING_STL
((way&IOS_BASE::beg) && off<0) || ((way&IOS_BASE::end) && off > 0)
#else
((way == IOS_BASE::beg) && off<0) || ((way == IOS_BASE::end) && off > 0)
#endif
)
return pos_type(-1);
PRSeekWhence poseek = PR_SEEK_CUR;
switch (way)
{
case IOS_BASE::beg : poseek= PR_SEEK_SET;
break;
case IOS_BASE::end : poseek= PR_SEEK_END;
break;
}
PRInt32 position = PR_Seek(mFileDesc, off, poseek);
if (position < 0)
return pos_type(-1);
return pos_type(position);
}
#endif // #if defined(DEFINING_FILE_STREAM)
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
POS_TYPE FILE_BUFFER_TYPE::seekpos(pos_type sp, IOS_BASE::openmode)
//----------------------------------------------------------------------------------------
{
if (!mFileDesc || sp==pos_type(-1))
return -1;
#if defined(XP_PC) || defined(XP_UNIX)
PRInt32 position = sp;
#else
PRInt32 position = sp.offset();
#endif
position = PR_Seek(mFileDesc, position, PR_SEEK_SET);
if (position < 0)
return pos_type(-1);
return position;
}
#endif // #if defined(DEFINING_FILE_STREAM)
//========================================================================================
// Implementation of nsInputFileStreamT
//========================================================================================
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline INPUT_FILE_STREAM::nsInputFileStreamT()
: BASIC_ISTREAM(&mBuffer)
//----------------------------------------------------------------------------------------
{
// already inited
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline INPUT_FILE_STREAM::nsInputFileStreamT(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
: BASIC_ISTREAM(&mBuffer)
{
// already inited
if (!mBuffer.open(inFile, openmode(mode|in), accessMode))
setstate(failbit);
}
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
INPUT_FILE_STREAM::~nsInputFileStreamT()
//----------------------------------------------------------------------------------------
{
}
#endif // #if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline FILE_BUFFER_TYPE* INPUT_FILE_STREAM::rdbuf() const
//----------------------------------------------------------------------------------------
{
return (FILE_BUFFER_TYPE*)&mBuffer;
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline bool INPUT_FILE_STREAM:: is_open()
//----------------------------------------------------------------------------------------
{
return mBuffer.is_open();
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline void INPUT_FILE_STREAM::open(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
{
if (!mBuffer.open(inFile, openmode(mode|in), accessMode))
setstate(failbit);
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline void INPUT_FILE_STREAM::close()
//----------------------------------------------------------------------------------------
{
if (!mBuffer.close())
setstate(failbit);
}
//========================================================================================
// Implementation of nsOutputFileStreamT
//========================================================================================
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline OUTPUT_FILE_STREAM::nsOutputFileStreamT()
: BASIC_OSTREAM(&mBuffer)
//----------------------------------------------------------------------------------------
{
// already inited
}
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
OUTPUT_FILE_STREAM::nsOutputFileStreamT(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
: BASIC_OSTREAM(&mBuffer)
{
// already inited
if (!mBuffer.open(inFile, openmode(mode|out), accessMode))
setstate(failbit);
}
#endif // #if defined(DEFINING_FILE_STREAM)
#if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline OUTPUT_FILE_STREAM::~nsOutputFileStreamT()
//----------------------------------------------------------------------------------------
{
}
#endif // #if defined(DEFINING_FILE_STREAM)
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline FILE_BUFFER_TYPE*
OUTPUT_FILE_STREAM::rdbuf() const
//----------------------------------------------------------------------------------------
{
return (FILE_BUFFER_TYPE*)&mBuffer;
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline bool OUTPUT_FILE_STREAM:: is_open()
//----------------------------------------------------------------------------------------
{
return mBuffer.is_open();
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline void OUTPUT_FILE_STREAM::open(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
{
if (!mBuffer.open(inFile, openmode(mode | out), accessMode))
setstate(failbit);
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline void OUTPUT_FILE_STREAM:: close()
//----------------------------------------------------------------------------------------
{
if (!mBuffer.close())
setstate(failbit);
}
//========================================================================================
TEMPLATE_DEF
class nsIOFileStreamT : public BASIC_IOSTREAM
//========================================================================================
{
#ifdef NS_USING_STL
public:
typedef charT char_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
typedef typename traits::int_type int_type;
typedef traits traits_type;
#endif
public:
nsIOFileStreamT();
explicit nsIOFileStreamT(
const nsFilePath& inFile,
IOS_BASE::openmode mode = IOS_BASE::in|IOS_BASE::out,
PRIntn accessMode = 0x00600);
virtual ~nsIOFileStreamT();
FILE_BUFFER_TYPE* rdbuf() const;
inline bool is_open();
inline void open(
const nsFilePath& inFile,
IOS_BASE::openmode mode = IOS_BASE::in|IOS_BASE::out,
PRIntn accessMode = 0x00600);
inline void close();
private:
FILE_BUFFER_TYPE mBuffer;
}; // class nsIOFileStreamT
//========================================================================================
// Implementation of nsIOFileStream
//========================================================================================
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline IO_FILE_STREAM::nsIOFileStreamT()
//----------------------------------------------------------------------------------------
: mBuffer(), BASIC_IOSTREAM(&mBuffer)
{
// already inited
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline IO_FILE_STREAM::nsIOFileStreamT(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
: mBuffer(), BASIC_IOSTREAM(&mBuffer)
{
// already inited
if (!mBuffer.open(inFile, mode, accessMode))
setstate(failbit);
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline IO_FILE_STREAM::~nsIOFileStreamT()
//----------------------------------------------------------------------------------------
{
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline FILE_BUFFER_TYPE*
IO_FILE_STREAM::rdbuf() const
//----------------------------------------------------------------------------------------
{
return (FILE_BUFFER_TYPE*)&mBuffer;
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline bool IO_FILE_STREAM::is_open()
//----------------------------------------------------------------------------------------
{
return mBuffer.is_open();
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline void IO_FILE_STREAM::open(
const nsFilePath& inFile,
IOS_BASE::openmode mode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
{
if (!mBuffer.open(inFile, mode, accessMode))
setstate(failbit);
}
//----------------------------------------------------------------------------------------
TEMPLATE_DEF
inline void IO_FILE_STREAM::close()
//----------------------------------------------------------------------------------------
{
if (!mBuffer.close())
setstate(failbit);
}
//========================================================================================
// Specializations of the stream templates
//========================================================================================
#ifdef NS_USING_STL
typedef nsFileBufferT<char, char_traits<char> > nsFileBuffer;
typedef nsInputFileStreamT<char, char_traits<char> > nsInputFileStream;
typedef nsOutputFileStreamT<char, char_traits<char> > nsOutputFileStream;
typedef nsIOFileStreamT<char, char_traits<char> > nsIOFileStream;
#ifdef NS_USING_WIDE_CHAR
typedef nsFileBufferT<wchar_t, char_traits<wchar_t> > nsWideFileBuffer;
typedef nsInputFileStreamT<wchar_t, char_traits<wchar_t> > nsWideInputFileStream;
typedef nsOutputFileStreamT<wchar_t, char_traits<wchar_t> > nsWideOutputFileStream;
typedef nsIOFileStreamT<wchar_t, char_traits<wchar_t> > nsWideIOFileStream;
#endif // NS_USING_WIDE_CHAR
#else
typedef nsFileBufferT nsFileBuffer;
typedef nsInputFileStreamT nsInputFileStream;
typedef nsOutputFileStreamT nsOutputFileStream;
typedef nsIOFileStreamT nsIOFileStream;
#endif
nsOutputFileStream& nsEndl(nsOutputFileStream& os);
#endif /* _FILESTREAM_H_ */

View File

@ -1,53 +1,46 @@
#include "nsFileSpec.h"
#include "nsFileStream.h"
#ifdef NS_USING_STL
#include <iostream>
using namespace std;
#else
#include <iostream.h>
#endif
NS_NAMESPACE FileTest
{
NS_NAMESPACE_PROTOTYPE void WriteStuff(ostream& s);
NS_NAMESPACE_PROTOTYPE void WriteStuff(nsOutputFileStream& s);
} NS_NAMESPACE_END
//----------------------------------------------------------------------------------------
void FileTest::WriteStuff(ostream& s)
void FileTest::WriteStuff(nsOutputFileStream& s)
//----------------------------------------------------------------------------------------
{
// Initialize a URL from a string without suffix. Change the path to suit your machine.
nsFileURL fileURL("file:///Development/MPW/MPW%20Shell");
s << "File URL initialized to: \"" << fileURL << "\""<< endl;
s << "File URL initialized to: \"" << fileURL << "\""<< nsEndl;
// Initialize a Unix path from a URL
nsFilePath filePath(fileURL);
s << "As a unix path: \"" << (const char*)filePath << "\""<< endl;
s << "As a unix path: \"" << (const char*)filePath << "\""<< nsEndl;
// Initialize a native file spec from a URL
nsNativeFileSpec fileSpec(fileURL);
s << "As a file spec: " << fileSpec << endl;
s << "As a file spec: " << fileSpec << nsEndl;
// Make the spec unique (this one has no suffix).
fileSpec.MakeUnique();
s << "Unique file spec: " << fileSpec << endl;
s << "Unique file spec: " << fileSpec << nsEndl;
// Assign the spec to a URL
fileURL = fileSpec;
s << "File URL assigned from spec: \"" << fileURL << "\""<< endl;
s << "File URL assigned from spec: \"" << fileURL << "\""<< nsEndl;
// Assign a unix path using a string with a suffix.
filePath = "/Development/MPW/SysErrs.err";
s << "File path reassigned to: \"" << (const char*)filePath << "\""<< endl;
s << "File path reassigned to: \"" << (const char*)filePath << "\""<< nsEndl;
// Assign to a file spec using a unix path.
fileSpec = filePath;
s << "File spec reassigned to: " << fileSpec << endl;
s << "File spec reassigned to: " << fileSpec << nsEndl;
// Make this unique (this one has a suffix).
fileSpec.MakeUnique();
s << "File spec made unique: " << fileSpec << endl;
s << "File spec made unique: " << fileSpec << nsEndl;
} // WriteStuff
//----------------------------------------------------------------------------------------
@ -58,33 +51,36 @@ void main()
// Test of nsFileSpec
cout << "WRITING TEST OUTPUT TO cout" << endl << endl;
FileTest::WriteStuff(cout);
cout << endl << endl;
nsOutputFileStream nsOut(cout);
nsOut << "WRITING TEST OUTPUT TO cout" << nsEndl << nsEndl;
FileTest::WriteStuff(nsOut);
nsOut << nsEndl << nsEndl;
// Test of nsOutputFileStream
nsFilePath myTextFilePath("/Development/iotest.txt");
{
cout << "WRITING IDENTICAL OUTPUT TO " << (const char*)myTextFilePath << endl << endl;
nsOut << "WRITING IDENTICAL OUTPUT TO " << (const char*)myTextFilePath << nsEndl << nsEndl;
nsOutputFileStream testStream(myTextFilePath);
NS_ASSERTION(testStream.is_open(), "File could not be opened");
FileTest::WriteStuff(testStream);
} // <-- Scope closes the stream (and the file).
// Test of nsInputFileStream
{
cout << "READING BACK DATA FROM " << (const char*)myTextFilePath << endl << endl;
nsOut << "READING BACK DATA FROM " << (const char*)myTextFilePath << nsEndl << nsEndl;
nsInputFileStream testStream2(myTextFilePath);
NS_ASSERTION(testStream2.is_open(), "File could not be opened");
char line[1000];
testStream2.seekg(0); // check that the seek template compiles
testStream2.seek(0); // check that the seek compiles
while (!testStream2.eof())
{
testStream2.getline(line, sizeof(line), '\n');
cout << line << endl;
testStream2.readline(line, sizeof(line));
nsOut << line << nsEndl;
}
}
} // main