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.

This commit is contained in:
mcmullen%netscape.com 1998-12-18 23:06:54 +00:00
Родитель bb8d115fc2
Коммит 9cdd955cd4
12 изменённых файлов: 984 добавлений и 1758 удалений

Просмотреть файл

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

Просмотреть файл

@ -26,11 +26,7 @@
// //
// single-byte char: // single-byte char:
// //
// nsInputFileStream, nsOutputFileStream, nsIOFileStream // nsInputFileStream, nsOutputFileStream
//
// wide char:
//
// nsWideInputFileStream, nsWideOutputFileStream, nsWideIOFileStream
// //
// This suite provide the following services: // This suite provide the following services:
// //
@ -41,16 +37,14 @@
// native performance. This performance difference is especially large on // native performance. This performance difference is especially large on
// macintosh. // macintosh.
// //
// 3. Allows all the power of the ansi stream syntax: these streams // 3. Allows all the power of the ansi stream syntax.
// ARE derived classes of ostream, istream, and iostream. ALL METHODS OF
// istream, ostream, AND iostream ARE AVAILABLE!
// //
// Basic example: // Basic example:
// //
// nsFilePath myPath("/Development/iotest.txt"); // nsFilePath myPath("/Development/iotest.txt");
// //
// nsOutputFileStream testStream(myPath); // nsOutputFileStream testStream(myPath);
// testStream << "Hello World" << endl; // testStream << "Hello World" << nsEndl;
// //
// 4. Requires streams to be constructed using typesafe nsFilePath specifier // 4. Requires streams to be constructed using typesafe nsFilePath specifier
// (not the notorious and bug prone const char*), namely nsFilePath. See // (not the notorious and bug prone const char*), namely nsFilePath. See
@ -107,831 +101,151 @@
#endif // NS_USING_NAMESPACE #endif // NS_USING_NAMESPACE
#ifdef NS_USING_STL #ifdef NS_USING_STL
#include <iostream>
// Macintosh and Windows use this section. using std::istream;
// using std::ostream;
// 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()
#else #else
#include <iostream.h>
// 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
#endif #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 =============================== //=========================== End Compiler-specific macros ===============================
//======================================================================================== //========================================================================================
NS_NAMESPACE nsFileStreamHelpers class NS_BASE nsBasicFileStream
// Prototypes for common (non-template) implementations in the .cpp file which do not
// need the template args (charT, traits).
//======================================================================================== //========================================================================================
{ {
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: public:
typedef charT char_type; nsBasicFileStream();
typedef typename traits::pos_type pos_type; nsBasicFileStream(PRFileDesc* desc, int nsprMode);
typedef typename traits::off_type off_type; nsBasicFileStream(
typedef typename traits::int_type int_type; const nsFilePath& inFile,
typedef traits traits_type; int nsprMode,
typedef typename traits::state_type state_type; PRIntn accessMode);
virtual ~nsBasicFileStream();
typedef codecvt<charT, char, state_type> ofacet_type;
typedef codecvt<char, charT, state_type> ifacet_type;
#endif
public: inline bool is_open() const { return mFileDesc != 0; }
nsFileBufferT(); void open(
nsFileBufferT(PRFileDesc* pfile_arg);
virtual ~nsFileBufferT();
bool is_open() const;
FILE_BUFFER_TYPE* open(
const nsFilePath& inFile, const nsFilePath& inFile,
IOS_BASE::openmode mode, int nsprMode,
PRIntn accessMode); 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: protected:
virtual int_type overflow(int_type c=EOF_VALUE); PRFileDesc* mFileDesc;
virtual int_type pbackfail(int_type c=EOF_VALUE); int mNSPRMode;
virtual int_type underflow(); bool mFailed;
virtual pos_type seekoff( bool mEOF;
off_type off, SEEK_DIR way, }; // class nsBasicFileStream
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
//======================================================================================== //========================================================================================
TEMPLATE_DEF class NS_BASE nsInputFileStream
class nsInputFileStreamT
//======================================================================================== //========================================================================================
: public BASIC_ISTREAM : public nsBasicFileStream
{ {
#ifdef NS_USING_STL
public: public:
typedef charT char_type; enum { kDefaultMode = PR_RDONLY };
typedef typename traits::pos_type pos_type; nsInputFileStream()
typedef typename traits::off_type off_type; : nsBasicFileStream()
typedef typename traits::int_type int_type; , mStdStream(0) {}
typedef traits traits_type; nsInputFileStream(
#endif istream& stream);
nsInputFileStream(
public:
nsInputFileStreamT();
explicit nsInputFileStreamT(
const nsFilePath& inFile, const nsFilePath& inFile,
IOS_BASE::openmode mode=IOS_BASE::in, int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00400); 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; // Output streamers. Add more as needed
inline bool is_open(); nsInputFileStream& operator >> (char& ch);
inline void open(
void open(
const nsFilePath& inFile, const nsFilePath& inFile,
IOS_BASE::openmode mode=IOS_BASE::in, int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00400); PRIntn accessMode = 0x00400)
inline void close(); {
nsBasicFileStream::open(inFile, nsprMode, accessMode);
}
private: private:
FILE_BUFFER_TYPE mBuffer;
}; // class nsInputFileStreamT nsInputFileStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE.
protected:
istream* mStdStream;
}; // class nsInputFileStream
//======================================================================================== //========================================================================================
TEMPLATE_DEF class NS_BASE nsOutputFileStream
class nsOutputFileStreamT
//======================================================================================== //========================================================================================
: public BASIC_OSTREAM : public nsBasicFileStream
{ {
#ifdef NS_USING_STL
public: public:
typedef charT char_type; enum { kDefaultMode = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE) };
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: nsOutputFileStream()
: nsBasicFileStream()
nsOutputFileStreamT(); , mStdStream(0) {}
explicit nsOutputFileStreamT( nsOutputFileStream(
ostream& stream);
nsOutputFileStream(
const nsFilePath& inFile, const nsFilePath& inFile,
IOS_BASE::openmode mode = IOS_BASE::out|IOS_BASE::trunc, int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00200); PRIntn accessMode = 0x00200)
: nsBasicFileStream(inFile, nsprMode, accessMode)
, mStdStream(0) {}
virtual ~nsOutputFileStreamT(); ostream* GetStandardStream() const { return mStdStream; }
FILE_BUFFER_TYPE* rdbuf() const;
inline bool is_open();
inline void open( inline void open(
const nsFilePath& inFile, const nsFilePath& inFile,
IOS_BASE::openmode mode = IOS_BASE::out|IOS_BASE::trunc, int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00200); PRIntn accessMode = 0x00200)
inline void close(); {
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();
private: // Output streamers. Add more as needed
FILE_BUFFER_TYPE mBuffer; nsOutputFileStream& operator << (const char* buf);
}; // class nsOutputFileStreamT nsOutputFileStream& operator << (char ch);
nsOutputFileStream& operator << (short val);
nsOutputFileStream& operator << (unsigned short val);
nsOutputFileStream& operator << (long val);
nsOutputFileStream& operator << (unsigned long val);
protected:
ostream* mStdStream;
}; // class nsOutputFileStream
//======================================================================================== //========================================================================================
// Implementation of nsFileBufferT // Manipulators
//======================================================================================== //========================================================================================
nsOutputFileStream& nsEndl(nsOutputFileStream& os);
//----------------------------------------------------------------------------------------
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
#endif /* _FILESTREAM_H_ */ #endif /* _FILESTREAM_H_ */

Просмотреть файл

@ -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 << spec.mSpec.vRefNum << ", " << spec.mSpec.parID << ", \"";
s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]); s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]);
return s << "\""; return s << "\"";
} // ostream& operator << (ostream&, const nsNativeFileSpec&) } // nsOutputFileStream& operator << (nsOutputFileStream&, const nsNativeFileSpec&)
//---------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const char* inString) void nsNativeFileSpec::operator = (const char* inString)

Просмотреть файл

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

Просмотреть файл

@ -27,34 +27,68 @@
#include "nsFileStream.h" #include "nsFileStream.h"
#include <string.h>
#include <stdio.h>
#ifdef XP_MAC #ifdef XP_MAC
#include <Errors.h> #include <Errors.h>
#endif #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, const nsFilePath& inFile,
IOS_BASE::openmode mode, int nsprMode,
PRIntn accessMode) PRIntn accessMode)
//---------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------
{ {
PRFileDesc* descriptor = 0; if (mFileDesc)
const IOS_BASE::openmode valid_modes[]= return;
{
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
};
const int nspr_modes[]={ const int nspr_modes[]={
PR_WRONLY | PR_CREATE_FILE, PR_WRONLY | PR_CREATE_FILE,
@ -71,19 +105,19 @@ PRFileDesc* nsFileStreamHelpers::open(
// "r+b", // "r+b",
// "w+b", // "w+b",
0 }; 0 };
int ind=0; const int* currentLegalMode = nspr_modes;
while (valid_modes[ind] && valid_modes[ind] != (mode&~IOS_BASE::ate)) while (*currentLegalMode && nsprMode != *currentLegalMode)
++ind; ++currentLegalMode;
if (!nspr_modes[ind]) if (!*currentLegalMode)
return 0; return;
#ifdef XP_MAC #ifdef XP_MAC
// Use the file spec to open the file, because one path can be common to // 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 // several files on the Macintosh (you can have several volumes with the
// same name, see). // same name, see).
descriptor = 0; mFileDesc = 0;
if (inFile.GetNativeSpec().Error() != noErr) if (inFile.GetNativeSpec().Error() != noErr)
return 0; return;
OSErr err = noErr; OSErr err = noErr;
#if DEBUG #if DEBUG
const OSType kCreator = 'CWIE'; const OSType kCreator = 'CWIE';
@ -92,17 +126,17 @@ PRFileDesc* nsFileStreamHelpers::open(
#endif #endif
nsNativeFileSpec nativeSpec = inFile.GetNativeSpec(); nsNativeFileSpec nativeSpec = inFile.GetNativeSpec();
FSSpec* spec = (FSSpec*)nativeSpec; FSSpec* spec = (FSSpec*)nativeSpec;
if (nspr_modes[ind] & PR_CREATE_FILE) if (nsprMode & PR_CREATE_FILE)
err = FSpCreate(spec, kCreator, 'TEXT', 0); err = FSpCreate(spec, kCreator, 'TEXT', 0);
if (err == dupFNErr) if (err == dupFNErr)
err = noErr; err = noErr;
if (err != noErr) if (err != noErr)
return 0; return;
SInt8 perm; SInt8 perm;
if (nspr_modes[ind] & PR_RDWR) if (nsprMode & PR_RDWR)
perm = fsRdWrPerm; perm = fsRdWrPerm;
else if (nspr_modes[ind] & PR_WRONLY) else if (nsprMode & PR_WRONLY)
perm = fsWrPerm; perm = fsWrPerm;
else else
perm = fsRdPerm; perm = fsRdPerm;
@ -110,24 +144,292 @@ PRFileDesc* nsFileStreamHelpers::open(
short refnum; short refnum;
err = FSpOpenDF(spec, perm, &refnum); err = FSpOpenDF(spec, perm, &refnum);
if (err == noErr && (nspr_modes[ind] & PR_TRUNCATE)) if (err == noErr && (nsprMode & PR_TRUNCATE))
err = SetEOF(refnum, 0); err = SetEOF(refnum, 0);
if (err == noErr && (nspr_modes[ind] & PR_APPEND)) if (err == noErr && (nsprMode & PR_APPEND))
err = SetFPos(refnum, fsFromLEOF, 0); err = SetFPos(refnum, fsFromLEOF, 0);
if (err != noErr) if (err != noErr)
return 0; return;
if ((descriptor = PR_ImportFile(refnum)) == 0) if ((mFileDesc = PR_ImportFile(refnum)) == 0)
return 0; return;
#else #else
// Platforms other than Macintosh... // Platforms other than Macintosh...
if ((descriptor = PR_Open(inFile, nspr_modes[ind], accessMode)) != 0) if ((mFileDesc = PR_Open(inFile, nsprMode, accessMode)) == 0)
return;
#endif #endif
if (mode&IOS_BASE::ate && PR_Seek(descriptor, 0, PR_SEEK_END) >= 0) mNSPRMode = nsprMode;
{
PR_Close(descriptor);
descriptor = 0;
return 0;
}
return descriptor;
} // nsFileStreamHelpers::open } // 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;
}

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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 << spec.mSpec.vRefNum << ", " << spec.mSpec.parID << ", \"";
s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]); s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]);
return s << "\""; return s << "\"";
} // ostream& operator << (ostream&, const nsNativeFileSpec&) } // nsOutputFileStream& operator << (nsOutputFileStream&, const nsNativeFileSpec&)
//---------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const char* inString) void nsNativeFileSpec::operator = (const char* inString)

Просмотреть файл

@ -27,34 +27,68 @@
#include "nsFileStream.h" #include "nsFileStream.h"
#include <string.h>
#include <stdio.h>
#ifdef XP_MAC #ifdef XP_MAC
#include <Errors.h> #include <Errors.h>
#endif #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, const nsFilePath& inFile,
IOS_BASE::openmode mode, int nsprMode,
PRIntn accessMode) PRIntn accessMode)
//---------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------
{ {
PRFileDesc* descriptor = 0; if (mFileDesc)
const IOS_BASE::openmode valid_modes[]= return;
{
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
};
const int nspr_modes[]={ const int nspr_modes[]={
PR_WRONLY | PR_CREATE_FILE, PR_WRONLY | PR_CREATE_FILE,
@ -71,19 +105,19 @@ PRFileDesc* nsFileStreamHelpers::open(
// "r+b", // "r+b",
// "w+b", // "w+b",
0 }; 0 };
int ind=0; const int* currentLegalMode = nspr_modes;
while (valid_modes[ind] && valid_modes[ind] != (mode&~IOS_BASE::ate)) while (*currentLegalMode && nsprMode != *currentLegalMode)
++ind; ++currentLegalMode;
if (!nspr_modes[ind]) if (!*currentLegalMode)
return 0; return;
#ifdef XP_MAC #ifdef XP_MAC
// Use the file spec to open the file, because one path can be common to // 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 // several files on the Macintosh (you can have several volumes with the
// same name, see). // same name, see).
descriptor = 0; mFileDesc = 0;
if (inFile.GetNativeSpec().Error() != noErr) if (inFile.GetNativeSpec().Error() != noErr)
return 0; return;
OSErr err = noErr; OSErr err = noErr;
#if DEBUG #if DEBUG
const OSType kCreator = 'CWIE'; const OSType kCreator = 'CWIE';
@ -92,17 +126,17 @@ PRFileDesc* nsFileStreamHelpers::open(
#endif #endif
nsNativeFileSpec nativeSpec = inFile.GetNativeSpec(); nsNativeFileSpec nativeSpec = inFile.GetNativeSpec();
FSSpec* spec = (FSSpec*)nativeSpec; FSSpec* spec = (FSSpec*)nativeSpec;
if (nspr_modes[ind] & PR_CREATE_FILE) if (nsprMode & PR_CREATE_FILE)
err = FSpCreate(spec, kCreator, 'TEXT', 0); err = FSpCreate(spec, kCreator, 'TEXT', 0);
if (err == dupFNErr) if (err == dupFNErr)
err = noErr; err = noErr;
if (err != noErr) if (err != noErr)
return 0; return;
SInt8 perm; SInt8 perm;
if (nspr_modes[ind] & PR_RDWR) if (nsprMode & PR_RDWR)
perm = fsRdWrPerm; perm = fsRdWrPerm;
else if (nspr_modes[ind] & PR_WRONLY) else if (nsprMode & PR_WRONLY)
perm = fsWrPerm; perm = fsWrPerm;
else else
perm = fsRdPerm; perm = fsRdPerm;
@ -110,24 +144,292 @@ PRFileDesc* nsFileStreamHelpers::open(
short refnum; short refnum;
err = FSpOpenDF(spec, perm, &refnum); err = FSpOpenDF(spec, perm, &refnum);
if (err == noErr && (nspr_modes[ind] & PR_TRUNCATE)) if (err == noErr && (nsprMode & PR_TRUNCATE))
err = SetEOF(refnum, 0); err = SetEOF(refnum, 0);
if (err == noErr && (nspr_modes[ind] & PR_APPEND)) if (err == noErr && (nsprMode & PR_APPEND))
err = SetFPos(refnum, fsFromLEOF, 0); err = SetFPos(refnum, fsFromLEOF, 0);
if (err != noErr) if (err != noErr)
return 0; return;
if ((descriptor = PR_ImportFile(refnum)) == 0) if ((mFileDesc = PR_ImportFile(refnum)) == 0)
return 0; return;
#else #else
// Platforms other than Macintosh... // Platforms other than Macintosh...
if ((descriptor = PR_Open(inFile, nspr_modes[ind], accessMode)) != 0) if ((mFileDesc = PR_Open(inFile, nsprMode, accessMode)) == 0)
return;
#endif #endif
if (mode&IOS_BASE::ate && PR_Seek(descriptor, 0, PR_SEEK_END) >= 0) mNSPRMode = nsprMode;
{
PR_Close(descriptor);
descriptor = 0;
return 0;
}
return descriptor;
} // nsFileStreamHelpers::open } // 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;
}

Просмотреть файл

@ -26,11 +26,7 @@
// //
// single-byte char: // single-byte char:
// //
// nsInputFileStream, nsOutputFileStream, nsIOFileStream // nsInputFileStream, nsOutputFileStream
//
// wide char:
//
// nsWideInputFileStream, nsWideOutputFileStream, nsWideIOFileStream
// //
// This suite provide the following services: // This suite provide the following services:
// //
@ -41,16 +37,14 @@
// native performance. This performance difference is especially large on // native performance. This performance difference is especially large on
// macintosh. // macintosh.
// //
// 3. Allows all the power of the ansi stream syntax: these streams // 3. Allows all the power of the ansi stream syntax.
// ARE derived classes of ostream, istream, and iostream. ALL METHODS OF
// istream, ostream, AND iostream ARE AVAILABLE!
// //
// Basic example: // Basic example:
// //
// nsFilePath myPath("/Development/iotest.txt"); // nsFilePath myPath("/Development/iotest.txt");
// //
// nsOutputFileStream testStream(myPath); // nsOutputFileStream testStream(myPath);
// testStream << "Hello World" << endl; // testStream << "Hello World" << nsEndl;
// //
// 4. Requires streams to be constructed using typesafe nsFilePath specifier // 4. Requires streams to be constructed using typesafe nsFilePath specifier
// (not the notorious and bug prone const char*), namely nsFilePath. See // (not the notorious and bug prone const char*), namely nsFilePath. See
@ -107,831 +101,151 @@
#endif // NS_USING_NAMESPACE #endif // NS_USING_NAMESPACE
#ifdef NS_USING_STL #ifdef NS_USING_STL
#include <iostream>
// Macintosh and Windows use this section. using std::istream;
// using std::ostream;
// 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()
#else #else
#include <iostream.h>
// 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
#endif #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 =============================== //=========================== End Compiler-specific macros ===============================
//======================================================================================== //========================================================================================
NS_NAMESPACE nsFileStreamHelpers class NS_BASE nsBasicFileStream
// Prototypes for common (non-template) implementations in the .cpp file which do not
// need the template args (charT, traits).
//======================================================================================== //========================================================================================
{ {
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: public:
typedef charT char_type; nsBasicFileStream();
typedef typename traits::pos_type pos_type; nsBasicFileStream(PRFileDesc* desc, int nsprMode);
typedef typename traits::off_type off_type; nsBasicFileStream(
typedef typename traits::int_type int_type; const nsFilePath& inFile,
typedef traits traits_type; int nsprMode,
typedef typename traits::state_type state_type; PRIntn accessMode);
virtual ~nsBasicFileStream();
typedef codecvt<charT, char, state_type> ofacet_type;
typedef codecvt<char, charT, state_type> ifacet_type;
#endif
public: inline bool is_open() const { return mFileDesc != 0; }
nsFileBufferT(); void open(
nsFileBufferT(PRFileDesc* pfile_arg);
virtual ~nsFileBufferT();
bool is_open() const;
FILE_BUFFER_TYPE* open(
const nsFilePath& inFile, const nsFilePath& inFile,
IOS_BASE::openmode mode, int nsprMode,
PRIntn accessMode); 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: protected:
virtual int_type overflow(int_type c=EOF_VALUE); PRFileDesc* mFileDesc;
virtual int_type pbackfail(int_type c=EOF_VALUE); int mNSPRMode;
virtual int_type underflow(); bool mFailed;
virtual pos_type seekoff( bool mEOF;
off_type off, SEEK_DIR way, }; // class nsBasicFileStream
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
//======================================================================================== //========================================================================================
TEMPLATE_DEF class NS_BASE nsInputFileStream
class nsInputFileStreamT
//======================================================================================== //========================================================================================
: public BASIC_ISTREAM : public nsBasicFileStream
{ {
#ifdef NS_USING_STL
public: public:
typedef charT char_type; enum { kDefaultMode = PR_RDONLY };
typedef typename traits::pos_type pos_type; nsInputFileStream()
typedef typename traits::off_type off_type; : nsBasicFileStream()
typedef typename traits::int_type int_type; , mStdStream(0) {}
typedef traits traits_type; nsInputFileStream(
#endif istream& stream);
nsInputFileStream(
public:
nsInputFileStreamT();
explicit nsInputFileStreamT(
const nsFilePath& inFile, const nsFilePath& inFile,
IOS_BASE::openmode mode=IOS_BASE::in, int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00400); 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; // Output streamers. Add more as needed
inline bool is_open(); nsInputFileStream& operator >> (char& ch);
inline void open(
void open(
const nsFilePath& inFile, const nsFilePath& inFile,
IOS_BASE::openmode mode=IOS_BASE::in, int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00400); PRIntn accessMode = 0x00400)
inline void close(); {
nsBasicFileStream::open(inFile, nsprMode, accessMode);
}
private: private:
FILE_BUFFER_TYPE mBuffer;
}; // class nsInputFileStreamT nsInputFileStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE.
protected:
istream* mStdStream;
}; // class nsInputFileStream
//======================================================================================== //========================================================================================
TEMPLATE_DEF class NS_BASE nsOutputFileStream
class nsOutputFileStreamT
//======================================================================================== //========================================================================================
: public BASIC_OSTREAM : public nsBasicFileStream
{ {
#ifdef NS_USING_STL
public: public:
typedef charT char_type; enum { kDefaultMode = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE) };
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: nsOutputFileStream()
: nsBasicFileStream()
nsOutputFileStreamT(); , mStdStream(0) {}
explicit nsOutputFileStreamT( nsOutputFileStream(
ostream& stream);
nsOutputFileStream(
const nsFilePath& inFile, const nsFilePath& inFile,
IOS_BASE::openmode mode = IOS_BASE::out|IOS_BASE::trunc, int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00200); PRIntn accessMode = 0x00200)
: nsBasicFileStream(inFile, nsprMode, accessMode)
, mStdStream(0) {}
virtual ~nsOutputFileStreamT(); ostream* GetStandardStream() const { return mStdStream; }
FILE_BUFFER_TYPE* rdbuf() const;
inline bool is_open();
inline void open( inline void open(
const nsFilePath& inFile, const nsFilePath& inFile,
IOS_BASE::openmode mode = IOS_BASE::out|IOS_BASE::trunc, int nsprMode = kDefaultMode,
PRIntn accessMode = 0x00200); PRIntn accessMode = 0x00200)
inline void close(); {
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();
private: // Output streamers. Add more as needed
FILE_BUFFER_TYPE mBuffer; nsOutputFileStream& operator << (const char* buf);
}; // class nsOutputFileStreamT nsOutputFileStream& operator << (char ch);
nsOutputFileStream& operator << (short val);
nsOutputFileStream& operator << (unsigned short val);
nsOutputFileStream& operator << (long val);
nsOutputFileStream& operator << (unsigned long val);
protected:
ostream* mStdStream;
}; // class nsOutputFileStream
//======================================================================================== //========================================================================================
// Implementation of nsFileBufferT // Manipulators
//======================================================================================== //========================================================================================
nsOutputFileStream& nsEndl(nsOutputFileStream& os);
//----------------------------------------------------------------------------------------
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
#endif /* _FILESTREAM_H_ */ #endif /* _FILESTREAM_H_ */

Просмотреть файл

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