From 9cdd955cd4963168db1530ceb0b77707405ca51d Mon Sep 17 00:00:00 2001 From: "mcmullen%netscape.com" Date: Fri, 18 Dec 1998 23:06:54 +0000 Subject: [PATCH] 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. --- base/public/nsFileSpec.h | 15 +- base/public/nsFileStream.h | 906 ++++----------------------------- base/src/mac/nsFileSpecMac.cpp | 4 +- base/src/nsFileSpec.cpp | 8 +- base/src/nsFileStream.cpp | 390 ++++++++++++-- base/tests/FilesTest.cpp | 48 +- xpcom/io/nsFileSpec.cpp | 8 +- xpcom/io/nsFileSpec.h | 15 +- xpcom/io/nsFileSpecMac.cpp | 4 +- xpcom/io/nsFileStream.cpp | 390 ++++++++++++-- xpcom/io/nsFileStream.h | 906 ++++----------------------------- xpcom/tests/FilesTest.cpp | 48 +- 12 files changed, 984 insertions(+), 1758 deletions(-) diff --git a/base/public/nsFileSpec.h b/base/public/nsFileSpec.h index 823d2eeb962..1c73419c631 100644 --- a/base/public/nsFileSpec.h +++ b/base/public/nsFileSpec.h @@ -37,15 +37,14 @@ // to the moment Communicator 4.5 shipped. // // 3. Used in conjunction with nsFileStream.h (q.v.), this supports all the power -// and readability of the ansi stream syntax. ALL METHODS OF istream, ostream, -// AND iostream ARE AVAILABLE! +// and readability of the ansi stream syntax. // // Basic example: // // nsFilePath myPath("/Development/iotest.txt"); // // nsOutputFileStream testStream(myPath); -// testStream << "Hello World" << endl; +// testStream << "Hello World" << nsEndl; // // 4. Handy methods for manipulating file specifiers safely, e.g. MakeUnique(), // SetLeafName(), Exists(). @@ -117,14 +116,11 @@ #define NS_NAMESPACE_PROTOTYPE #define NS_NAMESPACE namespace #define NS_NAMESPACE_END -#include - using std::ostream; #else #define NS_NAMESPACE_PROTOTYPE static #define NS_NAMESPACE struct #define NS_NAMESPACE_END ; -#include #endif //=========================== End Compiler-specific macros =============================== @@ -144,6 +140,8 @@ class nsNativeFileSpec; #define kFileURLPrefix "file://" #define kFileURLPrefixLength (7) +class nsOutputFileStream; + //======================================================================================== class NS_BASE nsNativeFileSpec // This is whatever each platform really prefers to describe files as. Declared first @@ -196,7 +194,7 @@ class NS_BASE nsNativeFileSpec bool Valid() const { return true; } // Fixme. #endif // XP_MAC - friend NS_BASE ostream& operator << (ostream& s, const nsNativeFileSpec& spec); + friend NS_BASE nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec& spec); char* GetLeafName() const; // Allocated. Use delete []. void SetLeafName(const char* inLeafName); @@ -237,7 +235,8 @@ class NS_BASE nsFileURL void operator = (const nsFilePath& inOther); void operator = (const nsNativeFileSpec& inOther); - friend NS_BASE ostream& operator << (ostream& s, const nsFileURL& spec); + friend NS_BASE nsOutputFileStream& operator << ( + nsOutputFileStream& s, const nsFileURL& spec); #ifdef XP_MAC // Accessor to allow quick assignment to a mNativeFileSpec diff --git a/base/public/nsFileStream.h b/base/public/nsFileStream.h index 4be4f1552de..2d39d675f0e 100644 --- a/base/public/nsFileStream.h +++ b/base/public/nsFileStream.h @@ -26,11 +26,7 @@ // // single-byte char: // -// nsInputFileStream, nsOutputFileStream, nsIOFileStream -// -// wide char: -// -// nsWideInputFileStream, nsWideOutputFileStream, nsWideIOFileStream +// nsInputFileStream, nsOutputFileStream // // This suite provide the following services: // @@ -41,16 +37,14 @@ // native performance. This performance difference is especially large on // macintosh. // -// 3. Allows all the power of the ansi stream syntax: these streams -// ARE derived classes of ostream, istream, and iostream. ALL METHODS OF -// istream, ostream, AND iostream ARE AVAILABLE! +// 3. Allows all the power of the ansi stream syntax. // // Basic example: // // nsFilePath myPath("/Development/iotest.txt"); // // nsOutputFileStream testStream(myPath); -// testStream << "Hello World" << endl; +// testStream << "Hello World" << nsEndl; // // 4. Requires streams to be constructed using typesafe nsFilePath specifier // (not the notorious and bug prone const char*), namely nsFilePath. See @@ -107,831 +101,151 @@ #endif // NS_USING_NAMESPACE #ifdef NS_USING_STL - -// Macintosh and Windows use this section. -// -// Here's where the party is. When Unix wants to join in (by supporting -// a build system with STL headers), what fun we'll have! Meanwhile, I've used -// macros to make this build on all our platforms. Unix doesn't have support for -// STL, and therefore we could not use the template forms of these classes on Unix. -// (it's a long story). Therefore, Unix supports no stream char types except 1-byte -// characters, and therefore nobody else does now either, until Unix catches up. - - -#define DEFINING_FILE_STREAM // templateers define this when this file is included. -#define IOS_BASE ios_base -#include - 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 -#define FILE_BUFFER_TYPE nsFileBufferT -#define INPUT_FILE_STREAM nsInputFileStreamT -#define OUTPUT_FILE_STREAM nsOutputFileStreamT -#define IO_FILE_STREAM nsIOFileStreamT -#define BASIC_STREAMBUF basic_streambuf -#define BASIC_ISTREAM basic_istream -#define BASIC_OSTREAM basic_ostream -#define BASIC_IOSTREAM basic_iostream -#define INT_TYPE FILE_BUFFER_TYPE::int_type -#define POS_TYPE FILE_BUFFER_TYPE::pos_type -#define OFF_TYPE FILE_BUFFER_TYPE::off_type -#define SEEK_DIR IOS_BASE::seekdir -#define EOF_VALUE traits::eof() - +#include +using std::istream; +using std::ostream; #else - -// Unix uses this section until it supports STL. This means no locales, no traits, -// no wide chars, etc. Also, the stream classes are the original ARM-style ones, -// and are not templatized. - -#define IOS_BASE ios -#include -#define TEMPLATE_DEF -#define FILE_BUFFER_TYPE nsFileBufferT -#define INPUT_FILE_STREAM nsInputFileStreamT -#define OUTPUT_FILE_STREAM nsOutputFileStreamT -#define IO_FILE_STREAM nsIOFileStreamT -#define BASIC_STREAMBUF streambuf -#define BASIC_ISTREAM istream -#define BASIC_OSTREAM ostream -#define BASIC_IOSTREAM iostream -#define INT_TYPE int -#define POS_TYPE long -#define OFF_TYPE long -#define SEEK_DIR ios::seek_dir -#define int_type int -#define pos_type long -#define off_type long -#define char_type char -#define EOF_VALUE EOF - -#endif // NS_USING_STL - -#ifdef __MWERKS__ - -#ifdef MSIPL_WCHART -#define NS_USING_WIDE_CHAR +#include #endif -#ifdef MSIPL_EXPLICIT_FUNC_TEMPLATE_ARG -#define NS_EXPLICIT_FUNC_TEMPLATE_ARG -#endif -#define NS_READ_LOCK(mut) READ_LOCK(mut) -#define NS_WRITE_LOCK(mut) WRITE_LOCK(mut) - -#else - -// Fix me, if necessary, for thread-safety. -#define NS_READ_LOCK(mut) -#define NS_WRITE_LOCK(mut) - -#endif // __MWERKS__ //=========================== End Compiler-specific macros =============================== //======================================================================================== -NS_NAMESPACE nsFileStreamHelpers -// Prototypes for common (non-template) implementations in the .cpp file which do not -// need the template args (charT, traits). +class NS_BASE nsBasicFileStream //======================================================================================== { - NS_NAMESPACE_PROTOTYPE NS_BASE PRFileDesc* open( - const nsFilePath& inFile, - IOS_BASE::openmode mode, - PRIntn accessMode); -} NS_NAMESPACE_END // nsFileStreamHelpers - -//======================================================================================== -// Template declarations -//======================================================================================== - -//======================================================================================== -TEMPLATE_DEF -class nsFileBufferT -//======================================================================================== -: public BASIC_STREAMBUF -{ -#ifdef NS_USING_STL - typedef codecvt_base::result result; - public: - typedef charT char_type; - typedef typename traits::pos_type pos_type; - typedef typename traits::off_type off_type; - typedef typename traits::int_type int_type; - typedef traits traits_type; - typedef typename traits::state_type state_type; + nsBasicFileStream(); + nsBasicFileStream(PRFileDesc* desc, int nsprMode); + nsBasicFileStream( + const nsFilePath& inFile, + int nsprMode, + PRIntn accessMode); + virtual ~nsBasicFileStream(); - typedef codecvt ofacet_type; - typedef codecvt ifacet_type; -#endif -public: - nsFileBufferT(); - nsFileBufferT(PRFileDesc* pfile_arg); - virtual ~nsFileBufferT(); - bool is_open() const; - FILE_BUFFER_TYPE* open( + inline bool is_open() const { return mFileDesc != 0; } + void open( const nsFilePath& inFile, - IOS_BASE::openmode mode, + int nsprMode, PRIntn accessMode); - FILE_BUFFER_TYPE* close(); - + void close(); + PRIntn tell() const; + void seek(PRInt32 offset) { seek(PR_SEEK_SET, offset); } + void seek(PRSeekWhence whence, PRInt32 offset); + bool eof() const { return mEOF; } + bool failed() const { return mFailed; } + // call PR_GetError() for details + protected: - virtual int_type overflow(int_type c=EOF_VALUE); - virtual int_type pbackfail(int_type c=EOF_VALUE); - virtual int_type underflow(); - virtual pos_type seekoff( - off_type off, SEEK_DIR way, - IOS_BASE::openmode which=IOS_BASE::in|IOS_BASE::out); - virtual pos_type seekpos(pos_type sp, - IOS_BASE::openmode which=IOS_BASE::in|IOS_BASE::out); - virtual BASIC_STREAMBUF* setbuf(char_type* s, streamsize n); - virtual int sync(); - virtual int_type uflow(); -#ifdef NS_USING_STL - virtual void imbue(const locale& loc); -#endif - virtual streamsize showmanyc(); - virtual streamsize xsgetn(char_type* s, streamsize n); - virtual streamsize xsputn(const char_type* s, streamsize n); - -private: - PRFileDesc* mFileDesc; - IOS_BASE::openmode mode_; -}; // class nsFileBufferT + PRFileDesc* mFileDesc; + int mNSPRMode; + bool mFailed; + bool mEOF; +}; // class nsBasicFileStream //======================================================================================== -TEMPLATE_DEF -class nsInputFileStreamT +class NS_BASE nsInputFileStream //======================================================================================== -: public BASIC_ISTREAM +: public nsBasicFileStream { -#ifdef NS_USING_STL public: - typedef charT char_type; - typedef typename traits::pos_type pos_type; - typedef typename traits::off_type off_type; - typedef typename traits::int_type int_type; - typedef traits traits_type; -#endif - -public: - nsInputFileStreamT(); - explicit nsInputFileStreamT( + enum { kDefaultMode = PR_RDONLY }; + nsInputFileStream() + : nsBasicFileStream() + , mStdStream(0) {} + nsInputFileStream( + istream& stream); + nsInputFileStream( const nsFilePath& inFile, - IOS_BASE::openmode mode=IOS_BASE::in, - PRIntn accessMode = 0x00400); + int nsprMode = kDefaultMode, + PRIntn accessMode = 0x00400) + : nsBasicFileStream(inFile, nsprMode, accessMode) + , mStdStream(0) {} - virtual ~nsInputFileStreamT(); + nsInputFileStream& operator >> (nsInputFileStream& (*pf)(nsInputFileStream&)) + { + return pf(*this); + } + void get(char& c); + PRInt32 read(void* s, PRInt32 n); + bool readline(char* s, PRInt32 n); + // Result always null-terminated + // false result indicates line was truncated + // to fit buffer, or an error occurred. - FILE_BUFFER_TYPE* rdbuf() const; - inline bool is_open(); - inline void open( + // Output streamers. Add more as needed + nsInputFileStream& operator >> (char& ch); + + void open( const nsFilePath& inFile, - IOS_BASE::openmode mode=IOS_BASE::in, - PRIntn accessMode = 0x00400); - inline void close(); - + int nsprMode = kDefaultMode, + PRIntn accessMode = 0x00400) + { + nsBasicFileStream::open(inFile, nsprMode, accessMode); + } private: - FILE_BUFFER_TYPE mBuffer; -}; // class nsInputFileStreamT + + nsInputFileStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE. + +protected: + + istream* mStdStream; +}; // class nsInputFileStream //======================================================================================== -TEMPLATE_DEF -class nsOutputFileStreamT +class NS_BASE nsOutputFileStream //======================================================================================== -: public BASIC_OSTREAM +: public nsBasicFileStream { -#ifdef NS_USING_STL -public: - typedef charT char_type; - typedef typename traits::pos_type pos_type; - typedef typename traits::off_type off_type; - typedef typename traits::int_type int_type; - typedef traits traits_type; -#endif - public: + enum { kDefaultMode = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE) }; - nsOutputFileStreamT(); - explicit nsOutputFileStreamT( + nsOutputFileStream() + : nsBasicFileStream() + , mStdStream(0) {} + nsOutputFileStream( + ostream& stream); + nsOutputFileStream( const nsFilePath& inFile, - IOS_BASE::openmode mode = IOS_BASE::out|IOS_BASE::trunc, - PRIntn accessMode = 0x00200); + int nsprMode = kDefaultMode, + PRIntn accessMode = 0x00200) + : nsBasicFileStream(inFile, nsprMode, accessMode) + , mStdStream(0) {} - virtual ~nsOutputFileStreamT(); - - FILE_BUFFER_TYPE* rdbuf() const; - inline bool is_open(); + ostream* GetStandardStream() const { return mStdStream; } inline void open( const nsFilePath& inFile, - IOS_BASE::openmode mode = IOS_BASE::out|IOS_BASE::trunc, - PRIntn accessMode = 0x00200); - inline void close(); + int nsprMode = kDefaultMode, + PRIntn accessMode = 0x00200) + { + nsBasicFileStream::open(inFile, nsprMode, accessMode); + } + nsOutputFileStream& operator << (nsOutputFileStream& (*pf)(nsOutputFileStream&)) + { + return pf(*this); + } + void put(char c); + PRInt32 write(const void* s, PRInt32 n); + void flush(); + + // Output streamers. Add more as needed + nsOutputFileStream& operator << (const char* buf); + nsOutputFileStream& operator << (char ch); + nsOutputFileStream& operator << (short val); + nsOutputFileStream& operator << (unsigned short val); + nsOutputFileStream& operator << (long val); + nsOutputFileStream& operator << (unsigned long val); -private: - FILE_BUFFER_TYPE mBuffer; -}; // class nsOutputFileStreamT +protected: + ostream* mStdStream; +}; // class nsOutputFileStream //======================================================================================== -// Implementation of nsFileBufferT +// Manipulators //======================================================================================== - -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -inline FILE_BUFFER_TYPE::nsFileBufferT() - : BASIC_STREAMBUF(), mFileDesc(NULL) -//---------------------------------------------------------------------------------------- -{ -} - -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -inline FILE_BUFFER_TYPE::nsFileBufferT(PRFileDesc* pfarg) - : BASIC_STREAMBUF(), mFileDesc(pfarg) -//---------------------------------------------------------------------------------------- -{ -} - -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -inline FILE_BUFFER_TYPE* FILE_BUFFER_TYPE::close() -// Must precede the destructor because both are inline. -//---------------------------------------------------------------------------------------- -{ - if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR) - return this; - NS_WRITE_LOCK(_mutex); - return (mFileDesc && PR_Close(mFileDesc) == PR_SUCCESS) ? mFileDesc = 0, this : 0; -} - -#if defined(DEFINING_FILE_STREAM) -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -FILE_BUFFER_TYPE::~nsFileBufferT() -//---------------------------------------------------------------------------------------- -{ - close(); -} -#endif // #if defined(DEFINING_FILE_STREAM) - -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -inline bool -FILE_BUFFER_TYPE::is_open() const -//---------------------------------------------------------------------------------------- -{ - NS_READ_LOCK(_mutex); - return bool(mFileDesc); // in case it is typedefed to int -} - -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -inline FILE_BUFFER_TYPE* FILE_BUFFER_TYPE::open( - const nsFilePath& inFile, - IOS_BASE::openmode mode, - PRIntn accessMode) -//---------------------------------------------------------------------------------------- -{ - if (mFileDesc) - return 0; - NS_WRITE_LOCK(_mutex); - mFileDesc = nsFileStreamHelpers::open(inFile, mode, accessMode); - if (!mFileDesc) - return 0; - mode_ = mode; - return this; -} // FILE_BUFFER_TYPE::open - -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -inline int FILE_BUFFER_TYPE:: sync() -//---------------------------------------------------------------------------------------- -{ - return (mFileDesc ? (int)PR_Sync(mFileDesc) : 0); -} - -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -inline BASIC_STREAMBUF* FILE_BUFFER_TYPE::setbuf(char_type*, streamsize) -//---------------------------------------------------------------------------------------- -{ - return (!mFileDesc) ? 0 : this; -} - -#if defined(DEFINING_FILE_STREAM) -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -INT_TYPE FILE_BUFFER_TYPE::overflow(int_type c) -//---------------------------------------------------------------------------------------- -{ -#ifndef NS_USING_STL - char ch = c; - PRInt32 bytesWrit1 = PR_Write(mFileDesc, &ch, sizeof(ch)); - return bytesWrit1 < sizeof(ch) ? EOF_VALUE : c; -#else -#ifdef NS_EXPLICIT_FUNC_TEMPLATE_ARG - const ofacet_type& ft=use_facet(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(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(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 > nsFileBuffer; -typedef nsInputFileStreamT > nsInputFileStream; -typedef nsOutputFileStreamT > nsOutputFileStream; -typedef nsIOFileStreamT > nsIOFileStream; - -#ifdef NS_USING_WIDE_CHAR -typedef nsFileBufferT > nsWideFileBuffer; -typedef nsInputFileStreamT > nsWideInputFileStream; -typedef nsOutputFileStreamT > nsWideOutputFileStream; -typedef nsIOFileStreamT > nsWideIOFileStream; -#endif // NS_USING_WIDE_CHAR - -#else - -typedef nsFileBufferT nsFileBuffer; -typedef nsInputFileStreamT nsInputFileStream; -typedef nsOutputFileStreamT nsOutputFileStream; -typedef nsIOFileStreamT nsIOFileStream; - -#endif +nsOutputFileStream& nsEndl(nsOutputFileStream& os); + #endif /* _FILESTREAM_H_ */ diff --git a/base/src/mac/nsFileSpecMac.cpp b/base/src/mac/nsFileSpecMac.cpp index 60336496c34..7bc58093f1f 100644 --- a/base/src/mac/nsFileSpecMac.cpp +++ b/base/src/mac/nsFileSpecMac.cpp @@ -491,13 +491,13 @@ nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath) } //---------------------------------------------------------------------------------------- -ostream& operator << (ostream& s, const nsNativeFileSpec& spec) +nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec& spec) //---------------------------------------------------------------------------------------- { s << spec.mSpec.vRefNum << ", " << spec.mSpec.parID << ", \""; s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]); return s << "\""; -} // ostream& operator << (ostream&, const nsNativeFileSpec&) +} // nsOutputFileStream& operator << (nsOutputFileStream&, const nsNativeFileSpec&) //---------------------------------------------------------------------------------------- void nsNativeFileSpec::operator = (const char* inString) diff --git a/base/src/nsFileSpec.cpp b/base/src/nsFileSpec.cpp index 873ebcada1d..953dbbe3834 100644 --- a/base/src/nsFileSpec.cpp +++ b/base/src/nsFileSpec.cpp @@ -18,9 +18,11 @@ #include "nsFileSpec.h" +#include "nsFileStream.h" + #include "prtypes.h" -#ifdef NS_USING_NAMESPACE +#ifdef NS_USING_STL #include @@ -257,7 +259,7 @@ void nsFileURL::operator = (const nsNativeFileSpec& inOther) } // nsFileURL::operator = //---------------------------------------------------------------------------------------- -ostream& operator << (ostream& s, const nsFileURL& url) +nsOutputFileStream& operator << (nsOutputFileStream& s, const nsFileURL& url) //---------------------------------------------------------------------------------------- { return (s << url.mURL); @@ -479,7 +481,7 @@ void nsNativeFileSpec::operator = (const char* inString) #if (defined(XP_UNIX) || defined(XP_PC)) //---------------------------------------------------------------------------------------- -ostream& operator << (ostream& s, const nsNativeFileSpec& spec) +nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec& spec) //---------------------------------------------------------------------------------------- { return (s << (const char*)spec.mPath); diff --git a/base/src/nsFileStream.cpp b/base/src/nsFileStream.cpp index f74b46209e4..0569bb4b23a 100644 --- a/base/src/nsFileStream.cpp +++ b/base/src/nsFileStream.cpp @@ -27,35 +27,69 @@ #include "nsFileStream.h" +#include +#include + #ifdef XP_MAC #include #endif + +//======================================================================================== +// nsBasicFileStream +//======================================================================================== + //---------------------------------------------------------------------------------------- -PRFileDesc* nsFileStreamHelpers::open( +nsBasicFileStream::nsBasicFileStream() +//---------------------------------------------------------------------------------------- + : mFileDesc(0) + , mNSPRMode(0) + , mFailed(false) + , mEOF(false) +{ +} + +//---------------------------------------------------------------------------------------- +nsBasicFileStream::nsBasicFileStream( + const nsFilePath& inFile, + int nsprMode, + PRIntn accessMode) +//---------------------------------------------------------------------------------------- + : mFileDesc(0) + , mNSPRMode(0) + , mFailed(false) + , mEOF(false) +{ + open(inFile, nsprMode, accessMode); +} + +//---------------------------------------------------------------------------------------- +nsBasicFileStream::nsBasicFileStream(PRFileDesc* desc, int nsprMode) +//---------------------------------------------------------------------------------------- + : mFileDesc(desc) + , mNSPRMode(nsprMode) + , mFailed(false) + , mEOF(false) +{ +} + +//---------------------------------------------------------------------------------------- +nsBasicFileStream::~nsBasicFileStream() +//---------------------------------------------------------------------------------------- +{ + close(); +} + +//---------------------------------------------------------------------------------------- +void nsBasicFileStream::open( const nsFilePath& inFile, - IOS_BASE::openmode mode, + int nsprMode, PRIntn accessMode) //---------------------------------------------------------------------------------------- { - PRFileDesc* descriptor = 0; - const IOS_BASE::openmode valid_modes[]= - { - IOS_BASE::out, - IOS_BASE::out | IOS_BASE::app, - IOS_BASE::out | IOS_BASE::trunc, - IOS_BASE::in, - IOS_BASE::in | IOS_BASE::out, - IOS_BASE::in | IOS_BASE::out | IOS_BASE::trunc, -// IOS_BASE::out | IOS_BASE::binary, -// IOS_BASE::out | IOS_BASE::app | IOS_BASE::binary, -// IOS_BASE::out | IOS_BASE::trunc | IOS_BASE::binary, -// IOS_BASE::in | IOS_BASE::binary, -// IOS_BASE::in | IOS_BASE::out | IOS_BASE::binary, -// IOS_BASE::in | IOS_BASE::out | IOS_BASE::trunc | IOS_BASE::binary, - 0 - }; - + if (mFileDesc) + return; + const int nspr_modes[]={ PR_WRONLY | PR_CREATE_FILE, PR_WRONLY | PR_CREATE_FILE | PR_APPEND, @@ -71,19 +105,19 @@ PRFileDesc* nsFileStreamHelpers::open( // "r+b", // "w+b", 0 }; - int ind=0; - while (valid_modes[ind] && valid_modes[ind] != (mode&~IOS_BASE::ate)) - ++ind; - if (!nspr_modes[ind]) - return 0; + const int* currentLegalMode = nspr_modes; + while (*currentLegalMode && nsprMode != *currentLegalMode) + ++currentLegalMode; + if (!*currentLegalMode) + return; #ifdef XP_MAC // Use the file spec to open the file, because one path can be common to // several files on the Macintosh (you can have several volumes with the // same name, see). - descriptor = 0; + mFileDesc = 0; if (inFile.GetNativeSpec().Error() != noErr) - return 0; + return; OSErr err = noErr; #if DEBUG const OSType kCreator = 'CWIE'; @@ -92,17 +126,17 @@ PRFileDesc* nsFileStreamHelpers::open( #endif nsNativeFileSpec nativeSpec = inFile.GetNativeSpec(); FSSpec* spec = (FSSpec*)nativeSpec; - if (nspr_modes[ind] & PR_CREATE_FILE) + if (nsprMode & PR_CREATE_FILE) err = FSpCreate(spec, kCreator, 'TEXT', 0); if (err == dupFNErr) err = noErr; if (err != noErr) - return 0; + return; SInt8 perm; - if (nspr_modes[ind] & PR_RDWR) + if (nsprMode & PR_RDWR) perm = fsRdWrPerm; - else if (nspr_modes[ind] & PR_WRONLY) + else if (nsprMode & PR_WRONLY) perm = fsWrPerm; else perm = fsRdPerm; @@ -110,24 +144,292 @@ PRFileDesc* nsFileStreamHelpers::open( short refnum; err = FSpOpenDF(spec, perm, &refnum); - if (err == noErr && (nspr_modes[ind] & PR_TRUNCATE)) + if (err == noErr && (nsprMode & PR_TRUNCATE)) err = SetEOF(refnum, 0); - if (err == noErr && (nspr_modes[ind] & PR_APPEND)) + if (err == noErr && (nsprMode & PR_APPEND)) err = SetFPos(refnum, fsFromLEOF, 0); if (err != noErr) - return 0; + return; - if ((descriptor = PR_ImportFile(refnum)) == 0) - return 0; + if ((mFileDesc = PR_ImportFile(refnum)) == 0) + return; #else // Platforms other than Macintosh... - if ((descriptor = PR_Open(inFile, nspr_modes[ind], accessMode)) != 0) + if ((mFileDesc = PR_Open(inFile, nsprMode, accessMode)) == 0) + return; #endif - if (mode&IOS_BASE::ate && PR_Seek(descriptor, 0, PR_SEEK_END) >= 0) - { - PR_Close(descriptor); - descriptor = 0; - return 0; - } - return descriptor; + mNSPRMode = nsprMode; } // nsFileStreamHelpers::open + +//---------------------------------------------------------------------------------------- +void nsBasicFileStream::close() +// Must precede the destructor because both are inline. +//---------------------------------------------------------------------------------------- +{ + if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0) + return; + if (PR_Close(mFileDesc) == PR_SUCCESS) + mFileDesc = 0; +} // nsBasicFileStream::close + +//---------------------------------------------------------------------------------------- +void nsBasicFileStream::seek(PRSeekWhence whence, PRInt32 offset) +// Must precede the destructor because both are inline. +//---------------------------------------------------------------------------------------- +{ + if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0) + return; + mFailed = false; // reset on a seek. + mEOF = false; // reset on a seek. + PRInt32 position = PR_Seek(mFileDesc, 0, PR_SEEK_CUR); + PRInt32 available = PR_Available(mFileDesc); + PRInt32 fileSize = position + available; + PRInt32 newPosition; + switch (whence) + { + case PR_SEEK_CUR: newPosition = position + offset; break; + case PR_SEEK_SET: newPosition = offset; break; + case PR_SEEK_END: newPosition = fileSize + offset; break; + } + if (newPosition < 0) + { + newPosition = 0; + mFailed = true; + } + else if (newPosition >= fileSize) + { + newPosition = fileSize; + mEOF = true; + } + if (PR_Seek(mFileDesc, newPosition, PR_SEEK_SET) < 0) + mFailed = true; +} // nsBasicFileStream::seek + +//---------------------------------------------------------------------------------------- +PRIntn nsBasicFileStream::tell() const +// Must precede the destructor because both are inline. +//---------------------------------------------------------------------------------------- +{ + if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0) + return -1; + return PR_Seek(mFileDesc, 0, PR_SEEK_CUR); +} // nsBasicFileStream::tell + +//======================================================================================== +// nsInputFileStream +//======================================================================================== + +//---------------------------------------------------------------------------------------- +nsInputFileStream::nsInputFileStream( + istream& stream) +//---------------------------------------------------------------------------------------- +#ifdef XP_MAC + : nsBasicFileStream(0, kDefaultMode) + , mStdStream(&stream) +#else + : nsBasicFileStream(PR_STDIN, kDefaultMode) + , mStdStream(0) +#endif +{ +} + +//---------------------------------------------------------------------------------------- +void nsInputFileStream::get(char& c) +//---------------------------------------------------------------------------------------- +{ + read(&c, sizeof(char)); +} + +//---------------------------------------------------------------------------------------- +bool nsInputFileStream::readline(char* s, PRInt32 n) +// This will truncate if the buffer is too small. Result will always be null-terminated. +//---------------------------------------------------------------------------------------- +{ + bool bufferLargeEnough = true; // result + if (!s || !n) + return true; + PRIntn position = tell(); + if (position < 0) + return false; + PRInt32 bytesRead = read(s, n - 1); + if (mFailed) + return false; + s[bytesRead] = '\0'; // always terminate at the end of the buffer + char* tp = strpbrk(s, "\n\r"); + if (tp) + { + char ch = *tp; + *tp++ = '\0'; // terminate at the newline, then skip past it + if ((ch == '\n' && *tp == '\r') || (ch == '\r' && *tp == '\n')) + tp++; // possibly a pair. + bytesRead = (tp - s); + } + else if (!eof()) + bufferLargeEnough = false; + position += bytesRead; + seek(position); + return bufferLargeEnough; +} // nsInputFileStream::getline + +//---------------------------------------------------------------------------------------- +PRInt32 nsInputFileStream::read(void* s, PRInt32 n) +//---------------------------------------------------------------------------------------- +{ + // Calling PR_Read on stdin is sure suicide on Macintosh. + if (mStdStream) + { + mStdStream->read((char*)s, n); + return n; + } + if (!mFileDesc || mFailed) + return -1; + PRInt32 bytesRead = PR_Read(mFileDesc, s, n); + if (bytesRead < 0) + mFailed = true; + else if (bytesRead < n) + mEOF = true; + return bytesRead; +} + +//---------------------------------------------------------------------------------------- +nsInputFileStream& nsInputFileStream::operator >> (char& c) +//---------------------------------------------------------------------------------------- +{ + get(c); + return *this; +} + +//======================================================================================== +// nsOutputFileStream +//======================================================================================== + +//---------------------------------------------------------------------------------------- +nsOutputFileStream::nsOutputFileStream( + ostream& stream) +//---------------------------------------------------------------------------------------- +#ifdef XP_MAC + : nsBasicFileStream(0, kDefaultMode) + , mStdStream(&stream) +#else + : nsBasicFileStream(PR_STDOUT, kDefaultMode) + , mStdStream(0) +#endif +{ +} + +//---------------------------------------------------------------------------------------- +void nsOutputFileStream::put(char c) +//---------------------------------------------------------------------------------------- +{ + write(&c, sizeof(c)); +} + +//---------------------------------------------------------------------------------------- +PRInt32 nsOutputFileStream::write(const void* s, PRInt32 n) +//---------------------------------------------------------------------------------------- +{ + // Calling PR_Write on stdout is sure suicide. + if (mStdStream) + { + mStdStream->write((const char*)s, n); + return n; + } + if (!mFileDesc || mFailed) + return -1; + PRInt32 bytesWrit = PR_Write(mFileDesc, s, n); + if (bytesWrit != n) + mFailed = true; + return bytesWrit; +} + +//---------------------------------------------------------------------------------------- +nsOutputFileStream& nsOutputFileStream::operator << (char c) +//---------------------------------------------------------------------------------------- +{ + put(c); + return *this; +} + +//---------------------------------------------------------------------------------------- +nsOutputFileStream& nsOutputFileStream::operator << (const char* s) +//---------------------------------------------------------------------------------------- +{ + write(s, strlen(s)); + return *this; +} + +//---------------------------------------------------------------------------------------- +nsOutputFileStream& nsOutputFileStream::operator << (short val) +//---------------------------------------------------------------------------------------- +{ + char buf[30]; + sprintf(buf, "%d", val); + return *this << buf; +} + +//---------------------------------------------------------------------------------------- +nsOutputFileStream& nsOutputFileStream::operator << (unsigned short val) +//---------------------------------------------------------------------------------------- +{ + char buf[30]; + sprintf(buf, "%ud", val); + return *this << buf; +} + +//---------------------------------------------------------------------------------------- +nsOutputFileStream& nsOutputFileStream::operator << (long val) +//---------------------------------------------------------------------------------------- +{ + char buf[30]; + sprintf(buf, "%ld", val); + return *this << buf; +} + +//---------------------------------------------------------------------------------------- +nsOutputFileStream& nsOutputFileStream::operator << (unsigned long val) +//---------------------------------------------------------------------------------------- +{ + char buf[30]; + sprintf(buf, "%uld", val); + return *this << buf; +} + +//---------------------------------------------------------------------------------------- +void nsOutputFileStream::flush() +// Must precede the destructor because both are inline. +//---------------------------------------------------------------------------------------- +{ + if (mStdStream) + { + mStdStream->flush(); + return; + } + if (mFileDesc == 0) + return; + bool itFailed = PR_Sync(mFileDesc) != PR_SUCCESS; +#ifdef XP_MAC + // On unix, it seems to fail always. + if (itFailed) + mFailed = true; +#endif +} // nsOutputFileStream::flush + +//======================================================================================== +// Manipulators +//======================================================================================== + +//---------------------------------------------------------------------------------------- +nsOutputFileStream& nsEndl(nsOutputFileStream& os) +//---------------------------------------------------------------------------------------- +{ + // Calling PR_Write on stdout is sure suicide on Macintosh. + ostream* stream = os.GetStandardStream(); + if (stream) + { + *stream << endl; + return os; + } + os.put('\n'); + os.flush(); + return os; +} diff --git a/base/tests/FilesTest.cpp b/base/tests/FilesTest.cpp index 396bec6f47e..b810e8a8b06 100644 --- a/base/tests/FilesTest.cpp +++ b/base/tests/FilesTest.cpp @@ -1,53 +1,46 @@ #include "nsFileSpec.h" #include "nsFileStream.h" -#ifdef NS_USING_STL -#include - using namespace std; -#else -#include -#endif - NS_NAMESPACE FileTest { - NS_NAMESPACE_PROTOTYPE void WriteStuff(ostream& s); + NS_NAMESPACE_PROTOTYPE void WriteStuff(nsOutputFileStream& s); } NS_NAMESPACE_END //---------------------------------------------------------------------------------------- -void FileTest::WriteStuff(ostream& s) +void FileTest::WriteStuff(nsOutputFileStream& s) //---------------------------------------------------------------------------------------- { // Initialize a URL from a string without suffix. Change the path to suit your machine. nsFileURL fileURL("file:///Development/MPW/MPW%20Shell"); - s << "File URL initialized to: \"" << fileURL << "\""<< endl; + s << "File URL initialized to: \"" << fileURL << "\""<< nsEndl; // Initialize a Unix path from a URL nsFilePath filePath(fileURL); - s << "As a unix path: \"" << (const char*)filePath << "\""<< endl; + s << "As a unix path: \"" << (const char*)filePath << "\""<< nsEndl; // Initialize a native file spec from a URL nsNativeFileSpec fileSpec(fileURL); - s << "As a file spec: " << fileSpec << endl; + s << "As a file spec: " << fileSpec << nsEndl; // Make the spec unique (this one has no suffix). fileSpec.MakeUnique(); - s << "Unique file spec: " << fileSpec << endl; + s << "Unique file spec: " << fileSpec << nsEndl; // Assign the spec to a URL fileURL = fileSpec; - s << "File URL assigned from spec: \"" << fileURL << "\""<< endl; + s << "File URL assigned from spec: \"" << fileURL << "\""<< nsEndl; // Assign a unix path using a string with a suffix. filePath = "/Development/MPW/SysErrs.err"; - s << "File path reassigned to: \"" << (const char*)filePath << "\""<< endl; + s << "File path reassigned to: \"" << (const char*)filePath << "\""<< nsEndl; // Assign to a file spec using a unix path. fileSpec = filePath; - s << "File spec reassigned to: " << fileSpec << endl; + s << "File spec reassigned to: " << fileSpec << nsEndl; // Make this unique (this one has a suffix). fileSpec.MakeUnique(); - s << "File spec made unique: " << fileSpec << endl; + s << "File spec made unique: " << fileSpec << nsEndl; } // WriteStuff //---------------------------------------------------------------------------------------- @@ -58,33 +51,36 @@ void main() // Test of nsFileSpec - cout << "WRITING TEST OUTPUT TO cout" << endl << endl; - FileTest::WriteStuff(cout); - cout << endl << endl; + nsOutputFileStream nsOut(cout); + nsOut << "WRITING TEST OUTPUT TO cout" << nsEndl << nsEndl; + + FileTest::WriteStuff(nsOut); + nsOut << nsEndl << nsEndl; // Test of nsOutputFileStream nsFilePath myTextFilePath("/Development/iotest.txt"); { - cout << "WRITING IDENTICAL OUTPUT TO " << (const char*)myTextFilePath << endl << endl; + nsOut << "WRITING IDENTICAL OUTPUT TO " << (const char*)myTextFilePath << nsEndl << nsEndl; nsOutputFileStream testStream(myTextFilePath); + NS_ASSERTION(testStream.is_open(), "File could not be opened"); FileTest::WriteStuff(testStream); } // <-- Scope closes the stream (and the file). // Test of nsInputFileStream { - cout << "READING BACK DATA FROM " << (const char*)myTextFilePath << endl << endl; + nsOut << "READING BACK DATA FROM " << (const char*)myTextFilePath << nsEndl << nsEndl; nsInputFileStream testStream2(myTextFilePath); + NS_ASSERTION(testStream2.is_open(), "File could not be opened"); char line[1000]; - testStream2.seekg(0); // check that the seek template compiles + testStream2.seek(0); // check that the seek compiles while (!testStream2.eof()) { - testStream2.getline(line, sizeof(line), '\n'); - cout << line << endl; + testStream2.readline(line, sizeof(line)); + nsOut << line << nsEndl; } } - } // main diff --git a/xpcom/io/nsFileSpec.cpp b/xpcom/io/nsFileSpec.cpp index 873ebcada1d..953dbbe3834 100644 --- a/xpcom/io/nsFileSpec.cpp +++ b/xpcom/io/nsFileSpec.cpp @@ -18,9 +18,11 @@ #include "nsFileSpec.h" +#include "nsFileStream.h" + #include "prtypes.h" -#ifdef NS_USING_NAMESPACE +#ifdef NS_USING_STL #include @@ -257,7 +259,7 @@ void nsFileURL::operator = (const nsNativeFileSpec& inOther) } // nsFileURL::operator = //---------------------------------------------------------------------------------------- -ostream& operator << (ostream& s, const nsFileURL& url) +nsOutputFileStream& operator << (nsOutputFileStream& s, const nsFileURL& url) //---------------------------------------------------------------------------------------- { return (s << url.mURL); @@ -479,7 +481,7 @@ void nsNativeFileSpec::operator = (const char* inString) #if (defined(XP_UNIX) || defined(XP_PC)) //---------------------------------------------------------------------------------------- -ostream& operator << (ostream& s, const nsNativeFileSpec& spec) +nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec& spec) //---------------------------------------------------------------------------------------- { return (s << (const char*)spec.mPath); diff --git a/xpcom/io/nsFileSpec.h b/xpcom/io/nsFileSpec.h index 823d2eeb962..1c73419c631 100644 --- a/xpcom/io/nsFileSpec.h +++ b/xpcom/io/nsFileSpec.h @@ -37,15 +37,14 @@ // to the moment Communicator 4.5 shipped. // // 3. Used in conjunction with nsFileStream.h (q.v.), this supports all the power -// and readability of the ansi stream syntax. ALL METHODS OF istream, ostream, -// AND iostream ARE AVAILABLE! +// and readability of the ansi stream syntax. // // Basic example: // // nsFilePath myPath("/Development/iotest.txt"); // // nsOutputFileStream testStream(myPath); -// testStream << "Hello World" << endl; +// testStream << "Hello World" << nsEndl; // // 4. Handy methods for manipulating file specifiers safely, e.g. MakeUnique(), // SetLeafName(), Exists(). @@ -117,14 +116,11 @@ #define NS_NAMESPACE_PROTOTYPE #define NS_NAMESPACE namespace #define NS_NAMESPACE_END -#include - using std::ostream; #else #define NS_NAMESPACE_PROTOTYPE static #define NS_NAMESPACE struct #define NS_NAMESPACE_END ; -#include #endif //=========================== End Compiler-specific macros =============================== @@ -144,6 +140,8 @@ class nsNativeFileSpec; #define kFileURLPrefix "file://" #define kFileURLPrefixLength (7) +class nsOutputFileStream; + //======================================================================================== class NS_BASE nsNativeFileSpec // This is whatever each platform really prefers to describe files as. Declared first @@ -196,7 +194,7 @@ class NS_BASE nsNativeFileSpec bool Valid() const { return true; } // Fixme. #endif // XP_MAC - friend NS_BASE ostream& operator << (ostream& s, const nsNativeFileSpec& spec); + friend NS_BASE nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec& spec); char* GetLeafName() const; // Allocated. Use delete []. void SetLeafName(const char* inLeafName); @@ -237,7 +235,8 @@ class NS_BASE nsFileURL void operator = (const nsFilePath& inOther); void operator = (const nsNativeFileSpec& inOther); - friend NS_BASE ostream& operator << (ostream& s, const nsFileURL& spec); + friend NS_BASE nsOutputFileStream& operator << ( + nsOutputFileStream& s, const nsFileURL& spec); #ifdef XP_MAC // Accessor to allow quick assignment to a mNativeFileSpec diff --git a/xpcom/io/nsFileSpecMac.cpp b/xpcom/io/nsFileSpecMac.cpp index 60336496c34..7bc58093f1f 100644 --- a/xpcom/io/nsFileSpecMac.cpp +++ b/xpcom/io/nsFileSpecMac.cpp @@ -491,13 +491,13 @@ nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath) } //---------------------------------------------------------------------------------------- -ostream& operator << (ostream& s, const nsNativeFileSpec& spec) +nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec& spec) //---------------------------------------------------------------------------------------- { s << spec.mSpec.vRefNum << ", " << spec.mSpec.parID << ", \""; s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]); return s << "\""; -} // ostream& operator << (ostream&, const nsNativeFileSpec&) +} // nsOutputFileStream& operator << (nsOutputFileStream&, const nsNativeFileSpec&) //---------------------------------------------------------------------------------------- void nsNativeFileSpec::operator = (const char* inString) diff --git a/xpcom/io/nsFileStream.cpp b/xpcom/io/nsFileStream.cpp index f74b46209e4..0569bb4b23a 100644 --- a/xpcom/io/nsFileStream.cpp +++ b/xpcom/io/nsFileStream.cpp @@ -27,35 +27,69 @@ #include "nsFileStream.h" +#include +#include + #ifdef XP_MAC #include #endif + +//======================================================================================== +// nsBasicFileStream +//======================================================================================== + //---------------------------------------------------------------------------------------- -PRFileDesc* nsFileStreamHelpers::open( +nsBasicFileStream::nsBasicFileStream() +//---------------------------------------------------------------------------------------- + : mFileDesc(0) + , mNSPRMode(0) + , mFailed(false) + , mEOF(false) +{ +} + +//---------------------------------------------------------------------------------------- +nsBasicFileStream::nsBasicFileStream( + const nsFilePath& inFile, + int nsprMode, + PRIntn accessMode) +//---------------------------------------------------------------------------------------- + : mFileDesc(0) + , mNSPRMode(0) + , mFailed(false) + , mEOF(false) +{ + open(inFile, nsprMode, accessMode); +} + +//---------------------------------------------------------------------------------------- +nsBasicFileStream::nsBasicFileStream(PRFileDesc* desc, int nsprMode) +//---------------------------------------------------------------------------------------- + : mFileDesc(desc) + , mNSPRMode(nsprMode) + , mFailed(false) + , mEOF(false) +{ +} + +//---------------------------------------------------------------------------------------- +nsBasicFileStream::~nsBasicFileStream() +//---------------------------------------------------------------------------------------- +{ + close(); +} + +//---------------------------------------------------------------------------------------- +void nsBasicFileStream::open( const nsFilePath& inFile, - IOS_BASE::openmode mode, + int nsprMode, PRIntn accessMode) //---------------------------------------------------------------------------------------- { - PRFileDesc* descriptor = 0; - const IOS_BASE::openmode valid_modes[]= - { - IOS_BASE::out, - IOS_BASE::out | IOS_BASE::app, - IOS_BASE::out | IOS_BASE::trunc, - IOS_BASE::in, - IOS_BASE::in | IOS_BASE::out, - IOS_BASE::in | IOS_BASE::out | IOS_BASE::trunc, -// IOS_BASE::out | IOS_BASE::binary, -// IOS_BASE::out | IOS_BASE::app | IOS_BASE::binary, -// IOS_BASE::out | IOS_BASE::trunc | IOS_BASE::binary, -// IOS_BASE::in | IOS_BASE::binary, -// IOS_BASE::in | IOS_BASE::out | IOS_BASE::binary, -// IOS_BASE::in | IOS_BASE::out | IOS_BASE::trunc | IOS_BASE::binary, - 0 - }; - + if (mFileDesc) + return; + const int nspr_modes[]={ PR_WRONLY | PR_CREATE_FILE, PR_WRONLY | PR_CREATE_FILE | PR_APPEND, @@ -71,19 +105,19 @@ PRFileDesc* nsFileStreamHelpers::open( // "r+b", // "w+b", 0 }; - int ind=0; - while (valid_modes[ind] && valid_modes[ind] != (mode&~IOS_BASE::ate)) - ++ind; - if (!nspr_modes[ind]) - return 0; + const int* currentLegalMode = nspr_modes; + while (*currentLegalMode && nsprMode != *currentLegalMode) + ++currentLegalMode; + if (!*currentLegalMode) + return; #ifdef XP_MAC // Use the file spec to open the file, because one path can be common to // several files on the Macintosh (you can have several volumes with the // same name, see). - descriptor = 0; + mFileDesc = 0; if (inFile.GetNativeSpec().Error() != noErr) - return 0; + return; OSErr err = noErr; #if DEBUG const OSType kCreator = 'CWIE'; @@ -92,17 +126,17 @@ PRFileDesc* nsFileStreamHelpers::open( #endif nsNativeFileSpec nativeSpec = inFile.GetNativeSpec(); FSSpec* spec = (FSSpec*)nativeSpec; - if (nspr_modes[ind] & PR_CREATE_FILE) + if (nsprMode & PR_CREATE_FILE) err = FSpCreate(spec, kCreator, 'TEXT', 0); if (err == dupFNErr) err = noErr; if (err != noErr) - return 0; + return; SInt8 perm; - if (nspr_modes[ind] & PR_RDWR) + if (nsprMode & PR_RDWR) perm = fsRdWrPerm; - else if (nspr_modes[ind] & PR_WRONLY) + else if (nsprMode & PR_WRONLY) perm = fsWrPerm; else perm = fsRdPerm; @@ -110,24 +144,292 @@ PRFileDesc* nsFileStreamHelpers::open( short refnum; err = FSpOpenDF(spec, perm, &refnum); - if (err == noErr && (nspr_modes[ind] & PR_TRUNCATE)) + if (err == noErr && (nsprMode & PR_TRUNCATE)) err = SetEOF(refnum, 0); - if (err == noErr && (nspr_modes[ind] & PR_APPEND)) + if (err == noErr && (nsprMode & PR_APPEND)) err = SetFPos(refnum, fsFromLEOF, 0); if (err != noErr) - return 0; + return; - if ((descriptor = PR_ImportFile(refnum)) == 0) - return 0; + if ((mFileDesc = PR_ImportFile(refnum)) == 0) + return; #else // Platforms other than Macintosh... - if ((descriptor = PR_Open(inFile, nspr_modes[ind], accessMode)) != 0) + if ((mFileDesc = PR_Open(inFile, nsprMode, accessMode)) == 0) + return; #endif - if (mode&IOS_BASE::ate && PR_Seek(descriptor, 0, PR_SEEK_END) >= 0) - { - PR_Close(descriptor); - descriptor = 0; - return 0; - } - return descriptor; + mNSPRMode = nsprMode; } // nsFileStreamHelpers::open + +//---------------------------------------------------------------------------------------- +void nsBasicFileStream::close() +// Must precede the destructor because both are inline. +//---------------------------------------------------------------------------------------- +{ + if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0) + return; + if (PR_Close(mFileDesc) == PR_SUCCESS) + mFileDesc = 0; +} // nsBasicFileStream::close + +//---------------------------------------------------------------------------------------- +void nsBasicFileStream::seek(PRSeekWhence whence, PRInt32 offset) +// Must precede the destructor because both are inline. +//---------------------------------------------------------------------------------------- +{ + if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0) + return; + mFailed = false; // reset on a seek. + mEOF = false; // reset on a seek. + PRInt32 position = PR_Seek(mFileDesc, 0, PR_SEEK_CUR); + PRInt32 available = PR_Available(mFileDesc); + PRInt32 fileSize = position + available; + PRInt32 newPosition; + switch (whence) + { + case PR_SEEK_CUR: newPosition = position + offset; break; + case PR_SEEK_SET: newPosition = offset; break; + case PR_SEEK_END: newPosition = fileSize + offset; break; + } + if (newPosition < 0) + { + newPosition = 0; + mFailed = true; + } + else if (newPosition >= fileSize) + { + newPosition = fileSize; + mEOF = true; + } + if (PR_Seek(mFileDesc, newPosition, PR_SEEK_SET) < 0) + mFailed = true; +} // nsBasicFileStream::seek + +//---------------------------------------------------------------------------------------- +PRIntn nsBasicFileStream::tell() const +// Must precede the destructor because both are inline. +//---------------------------------------------------------------------------------------- +{ + if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || mFileDesc == 0) + return -1; + return PR_Seek(mFileDesc, 0, PR_SEEK_CUR); +} // nsBasicFileStream::tell + +//======================================================================================== +// nsInputFileStream +//======================================================================================== + +//---------------------------------------------------------------------------------------- +nsInputFileStream::nsInputFileStream( + istream& stream) +//---------------------------------------------------------------------------------------- +#ifdef XP_MAC + : nsBasicFileStream(0, kDefaultMode) + , mStdStream(&stream) +#else + : nsBasicFileStream(PR_STDIN, kDefaultMode) + , mStdStream(0) +#endif +{ +} + +//---------------------------------------------------------------------------------------- +void nsInputFileStream::get(char& c) +//---------------------------------------------------------------------------------------- +{ + read(&c, sizeof(char)); +} + +//---------------------------------------------------------------------------------------- +bool nsInputFileStream::readline(char* s, PRInt32 n) +// This will truncate if the buffer is too small. Result will always be null-terminated. +//---------------------------------------------------------------------------------------- +{ + bool bufferLargeEnough = true; // result + if (!s || !n) + return true; + PRIntn position = tell(); + if (position < 0) + return false; + PRInt32 bytesRead = read(s, n - 1); + if (mFailed) + return false; + s[bytesRead] = '\0'; // always terminate at the end of the buffer + char* tp = strpbrk(s, "\n\r"); + if (tp) + { + char ch = *tp; + *tp++ = '\0'; // terminate at the newline, then skip past it + if ((ch == '\n' && *tp == '\r') || (ch == '\r' && *tp == '\n')) + tp++; // possibly a pair. + bytesRead = (tp - s); + } + else if (!eof()) + bufferLargeEnough = false; + position += bytesRead; + seek(position); + return bufferLargeEnough; +} // nsInputFileStream::getline + +//---------------------------------------------------------------------------------------- +PRInt32 nsInputFileStream::read(void* s, PRInt32 n) +//---------------------------------------------------------------------------------------- +{ + // Calling PR_Read on stdin is sure suicide on Macintosh. + if (mStdStream) + { + mStdStream->read((char*)s, n); + return n; + } + if (!mFileDesc || mFailed) + return -1; + PRInt32 bytesRead = PR_Read(mFileDesc, s, n); + if (bytesRead < 0) + mFailed = true; + else if (bytesRead < n) + mEOF = true; + return bytesRead; +} + +//---------------------------------------------------------------------------------------- +nsInputFileStream& nsInputFileStream::operator >> (char& c) +//---------------------------------------------------------------------------------------- +{ + get(c); + return *this; +} + +//======================================================================================== +// nsOutputFileStream +//======================================================================================== + +//---------------------------------------------------------------------------------------- +nsOutputFileStream::nsOutputFileStream( + ostream& stream) +//---------------------------------------------------------------------------------------- +#ifdef XP_MAC + : nsBasicFileStream(0, kDefaultMode) + , mStdStream(&stream) +#else + : nsBasicFileStream(PR_STDOUT, kDefaultMode) + , mStdStream(0) +#endif +{ +} + +//---------------------------------------------------------------------------------------- +void nsOutputFileStream::put(char c) +//---------------------------------------------------------------------------------------- +{ + write(&c, sizeof(c)); +} + +//---------------------------------------------------------------------------------------- +PRInt32 nsOutputFileStream::write(const void* s, PRInt32 n) +//---------------------------------------------------------------------------------------- +{ + // Calling PR_Write on stdout is sure suicide. + if (mStdStream) + { + mStdStream->write((const char*)s, n); + return n; + } + if (!mFileDesc || mFailed) + return -1; + PRInt32 bytesWrit = PR_Write(mFileDesc, s, n); + if (bytesWrit != n) + mFailed = true; + return bytesWrit; +} + +//---------------------------------------------------------------------------------------- +nsOutputFileStream& nsOutputFileStream::operator << (char c) +//---------------------------------------------------------------------------------------- +{ + put(c); + return *this; +} + +//---------------------------------------------------------------------------------------- +nsOutputFileStream& nsOutputFileStream::operator << (const char* s) +//---------------------------------------------------------------------------------------- +{ + write(s, strlen(s)); + return *this; +} + +//---------------------------------------------------------------------------------------- +nsOutputFileStream& nsOutputFileStream::operator << (short val) +//---------------------------------------------------------------------------------------- +{ + char buf[30]; + sprintf(buf, "%d", val); + return *this << buf; +} + +//---------------------------------------------------------------------------------------- +nsOutputFileStream& nsOutputFileStream::operator << (unsigned short val) +//---------------------------------------------------------------------------------------- +{ + char buf[30]; + sprintf(buf, "%ud", val); + return *this << buf; +} + +//---------------------------------------------------------------------------------------- +nsOutputFileStream& nsOutputFileStream::operator << (long val) +//---------------------------------------------------------------------------------------- +{ + char buf[30]; + sprintf(buf, "%ld", val); + return *this << buf; +} + +//---------------------------------------------------------------------------------------- +nsOutputFileStream& nsOutputFileStream::operator << (unsigned long val) +//---------------------------------------------------------------------------------------- +{ + char buf[30]; + sprintf(buf, "%uld", val); + return *this << buf; +} + +//---------------------------------------------------------------------------------------- +void nsOutputFileStream::flush() +// Must precede the destructor because both are inline. +//---------------------------------------------------------------------------------------- +{ + if (mStdStream) + { + mStdStream->flush(); + return; + } + if (mFileDesc == 0) + return; + bool itFailed = PR_Sync(mFileDesc) != PR_SUCCESS; +#ifdef XP_MAC + // On unix, it seems to fail always. + if (itFailed) + mFailed = true; +#endif +} // nsOutputFileStream::flush + +//======================================================================================== +// Manipulators +//======================================================================================== + +//---------------------------------------------------------------------------------------- +nsOutputFileStream& nsEndl(nsOutputFileStream& os) +//---------------------------------------------------------------------------------------- +{ + // Calling PR_Write on stdout is sure suicide on Macintosh. + ostream* stream = os.GetStandardStream(); + if (stream) + { + *stream << endl; + return os; + } + os.put('\n'); + os.flush(); + return os; +} diff --git a/xpcom/io/nsFileStream.h b/xpcom/io/nsFileStream.h index 4be4f1552de..2d39d675f0e 100644 --- a/xpcom/io/nsFileStream.h +++ b/xpcom/io/nsFileStream.h @@ -26,11 +26,7 @@ // // single-byte char: // -// nsInputFileStream, nsOutputFileStream, nsIOFileStream -// -// wide char: -// -// nsWideInputFileStream, nsWideOutputFileStream, nsWideIOFileStream +// nsInputFileStream, nsOutputFileStream // // This suite provide the following services: // @@ -41,16 +37,14 @@ // native performance. This performance difference is especially large on // macintosh. // -// 3. Allows all the power of the ansi stream syntax: these streams -// ARE derived classes of ostream, istream, and iostream. ALL METHODS OF -// istream, ostream, AND iostream ARE AVAILABLE! +// 3. Allows all the power of the ansi stream syntax. // // Basic example: // // nsFilePath myPath("/Development/iotest.txt"); // // nsOutputFileStream testStream(myPath); -// testStream << "Hello World" << endl; +// testStream << "Hello World" << nsEndl; // // 4. Requires streams to be constructed using typesafe nsFilePath specifier // (not the notorious and bug prone const char*), namely nsFilePath. See @@ -107,831 +101,151 @@ #endif // NS_USING_NAMESPACE #ifdef NS_USING_STL - -// Macintosh and Windows use this section. -// -// Here's where the party is. When Unix wants to join in (by supporting -// a build system with STL headers), what fun we'll have! Meanwhile, I've used -// macros to make this build on all our platforms. Unix doesn't have support for -// STL, and therefore we could not use the template forms of these classes on Unix. -// (it's a long story). Therefore, Unix supports no stream char types except 1-byte -// characters, and therefore nobody else does now either, until Unix catches up. - - -#define DEFINING_FILE_STREAM // templateers define this when this file is included. -#define IOS_BASE ios_base -#include - 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 -#define FILE_BUFFER_TYPE nsFileBufferT -#define INPUT_FILE_STREAM nsInputFileStreamT -#define OUTPUT_FILE_STREAM nsOutputFileStreamT -#define IO_FILE_STREAM nsIOFileStreamT -#define BASIC_STREAMBUF basic_streambuf -#define BASIC_ISTREAM basic_istream -#define BASIC_OSTREAM basic_ostream -#define BASIC_IOSTREAM basic_iostream -#define INT_TYPE FILE_BUFFER_TYPE::int_type -#define POS_TYPE FILE_BUFFER_TYPE::pos_type -#define OFF_TYPE FILE_BUFFER_TYPE::off_type -#define SEEK_DIR IOS_BASE::seekdir -#define EOF_VALUE traits::eof() - +#include +using std::istream; +using std::ostream; #else - -// Unix uses this section until it supports STL. This means no locales, no traits, -// no wide chars, etc. Also, the stream classes are the original ARM-style ones, -// and are not templatized. - -#define IOS_BASE ios -#include -#define TEMPLATE_DEF -#define FILE_BUFFER_TYPE nsFileBufferT -#define INPUT_FILE_STREAM nsInputFileStreamT -#define OUTPUT_FILE_STREAM nsOutputFileStreamT -#define IO_FILE_STREAM nsIOFileStreamT -#define BASIC_STREAMBUF streambuf -#define BASIC_ISTREAM istream -#define BASIC_OSTREAM ostream -#define BASIC_IOSTREAM iostream -#define INT_TYPE int -#define POS_TYPE long -#define OFF_TYPE long -#define SEEK_DIR ios::seek_dir -#define int_type int -#define pos_type long -#define off_type long -#define char_type char -#define EOF_VALUE EOF - -#endif // NS_USING_STL - -#ifdef __MWERKS__ - -#ifdef MSIPL_WCHART -#define NS_USING_WIDE_CHAR +#include #endif -#ifdef MSIPL_EXPLICIT_FUNC_TEMPLATE_ARG -#define NS_EXPLICIT_FUNC_TEMPLATE_ARG -#endif -#define NS_READ_LOCK(mut) READ_LOCK(mut) -#define NS_WRITE_LOCK(mut) WRITE_LOCK(mut) - -#else - -// Fix me, if necessary, for thread-safety. -#define NS_READ_LOCK(mut) -#define NS_WRITE_LOCK(mut) - -#endif // __MWERKS__ //=========================== End Compiler-specific macros =============================== //======================================================================================== -NS_NAMESPACE nsFileStreamHelpers -// Prototypes for common (non-template) implementations in the .cpp file which do not -// need the template args (charT, traits). +class NS_BASE nsBasicFileStream //======================================================================================== { - NS_NAMESPACE_PROTOTYPE NS_BASE PRFileDesc* open( - const nsFilePath& inFile, - IOS_BASE::openmode mode, - PRIntn accessMode); -} NS_NAMESPACE_END // nsFileStreamHelpers - -//======================================================================================== -// Template declarations -//======================================================================================== - -//======================================================================================== -TEMPLATE_DEF -class nsFileBufferT -//======================================================================================== -: public BASIC_STREAMBUF -{ -#ifdef NS_USING_STL - typedef codecvt_base::result result; - public: - typedef charT char_type; - typedef typename traits::pos_type pos_type; - typedef typename traits::off_type off_type; - typedef typename traits::int_type int_type; - typedef traits traits_type; - typedef typename traits::state_type state_type; + nsBasicFileStream(); + nsBasicFileStream(PRFileDesc* desc, int nsprMode); + nsBasicFileStream( + const nsFilePath& inFile, + int nsprMode, + PRIntn accessMode); + virtual ~nsBasicFileStream(); - typedef codecvt ofacet_type; - typedef codecvt ifacet_type; -#endif -public: - nsFileBufferT(); - nsFileBufferT(PRFileDesc* pfile_arg); - virtual ~nsFileBufferT(); - bool is_open() const; - FILE_BUFFER_TYPE* open( + inline bool is_open() const { return mFileDesc != 0; } + void open( const nsFilePath& inFile, - IOS_BASE::openmode mode, + int nsprMode, PRIntn accessMode); - FILE_BUFFER_TYPE* close(); - + void close(); + PRIntn tell() const; + void seek(PRInt32 offset) { seek(PR_SEEK_SET, offset); } + void seek(PRSeekWhence whence, PRInt32 offset); + bool eof() const { return mEOF; } + bool failed() const { return mFailed; } + // call PR_GetError() for details + protected: - virtual int_type overflow(int_type c=EOF_VALUE); - virtual int_type pbackfail(int_type c=EOF_VALUE); - virtual int_type underflow(); - virtual pos_type seekoff( - off_type off, SEEK_DIR way, - IOS_BASE::openmode which=IOS_BASE::in|IOS_BASE::out); - virtual pos_type seekpos(pos_type sp, - IOS_BASE::openmode which=IOS_BASE::in|IOS_BASE::out); - virtual BASIC_STREAMBUF* setbuf(char_type* s, streamsize n); - virtual int sync(); - virtual int_type uflow(); -#ifdef NS_USING_STL - virtual void imbue(const locale& loc); -#endif - virtual streamsize showmanyc(); - virtual streamsize xsgetn(char_type* s, streamsize n); - virtual streamsize xsputn(const char_type* s, streamsize n); - -private: - PRFileDesc* mFileDesc; - IOS_BASE::openmode mode_; -}; // class nsFileBufferT + PRFileDesc* mFileDesc; + int mNSPRMode; + bool mFailed; + bool mEOF; +}; // class nsBasicFileStream //======================================================================================== -TEMPLATE_DEF -class nsInputFileStreamT +class NS_BASE nsInputFileStream //======================================================================================== -: public BASIC_ISTREAM +: public nsBasicFileStream { -#ifdef NS_USING_STL public: - typedef charT char_type; - typedef typename traits::pos_type pos_type; - typedef typename traits::off_type off_type; - typedef typename traits::int_type int_type; - typedef traits traits_type; -#endif - -public: - nsInputFileStreamT(); - explicit nsInputFileStreamT( + enum { kDefaultMode = PR_RDONLY }; + nsInputFileStream() + : nsBasicFileStream() + , mStdStream(0) {} + nsInputFileStream( + istream& stream); + nsInputFileStream( const nsFilePath& inFile, - IOS_BASE::openmode mode=IOS_BASE::in, - PRIntn accessMode = 0x00400); + int nsprMode = kDefaultMode, + PRIntn accessMode = 0x00400) + : nsBasicFileStream(inFile, nsprMode, accessMode) + , mStdStream(0) {} - virtual ~nsInputFileStreamT(); + nsInputFileStream& operator >> (nsInputFileStream& (*pf)(nsInputFileStream&)) + { + return pf(*this); + } + void get(char& c); + PRInt32 read(void* s, PRInt32 n); + bool readline(char* s, PRInt32 n); + // Result always null-terminated + // false result indicates line was truncated + // to fit buffer, or an error occurred. - FILE_BUFFER_TYPE* rdbuf() const; - inline bool is_open(); - inline void open( + // Output streamers. Add more as needed + nsInputFileStream& operator >> (char& ch); + + void open( const nsFilePath& inFile, - IOS_BASE::openmode mode=IOS_BASE::in, - PRIntn accessMode = 0x00400); - inline void close(); - + int nsprMode = kDefaultMode, + PRIntn accessMode = 0x00400) + { + nsBasicFileStream::open(inFile, nsprMode, accessMode); + } private: - FILE_BUFFER_TYPE mBuffer; -}; // class nsInputFileStreamT + + nsInputFileStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE. + +protected: + + istream* mStdStream; +}; // class nsInputFileStream //======================================================================================== -TEMPLATE_DEF -class nsOutputFileStreamT +class NS_BASE nsOutputFileStream //======================================================================================== -: public BASIC_OSTREAM +: public nsBasicFileStream { -#ifdef NS_USING_STL -public: - typedef charT char_type; - typedef typename traits::pos_type pos_type; - typedef typename traits::off_type off_type; - typedef typename traits::int_type int_type; - typedef traits traits_type; -#endif - public: + enum { kDefaultMode = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE) }; - nsOutputFileStreamT(); - explicit nsOutputFileStreamT( + nsOutputFileStream() + : nsBasicFileStream() + , mStdStream(0) {} + nsOutputFileStream( + ostream& stream); + nsOutputFileStream( const nsFilePath& inFile, - IOS_BASE::openmode mode = IOS_BASE::out|IOS_BASE::trunc, - PRIntn accessMode = 0x00200); + int nsprMode = kDefaultMode, + PRIntn accessMode = 0x00200) + : nsBasicFileStream(inFile, nsprMode, accessMode) + , mStdStream(0) {} - virtual ~nsOutputFileStreamT(); - - FILE_BUFFER_TYPE* rdbuf() const; - inline bool is_open(); + ostream* GetStandardStream() const { return mStdStream; } inline void open( const nsFilePath& inFile, - IOS_BASE::openmode mode = IOS_BASE::out|IOS_BASE::trunc, - PRIntn accessMode = 0x00200); - inline void close(); + int nsprMode = kDefaultMode, + PRIntn accessMode = 0x00200) + { + nsBasicFileStream::open(inFile, nsprMode, accessMode); + } + nsOutputFileStream& operator << (nsOutputFileStream& (*pf)(nsOutputFileStream&)) + { + return pf(*this); + } + void put(char c); + PRInt32 write(const void* s, PRInt32 n); + void flush(); + + // Output streamers. Add more as needed + nsOutputFileStream& operator << (const char* buf); + nsOutputFileStream& operator << (char ch); + nsOutputFileStream& operator << (short val); + nsOutputFileStream& operator << (unsigned short val); + nsOutputFileStream& operator << (long val); + nsOutputFileStream& operator << (unsigned long val); -private: - FILE_BUFFER_TYPE mBuffer; -}; // class nsOutputFileStreamT +protected: + ostream* mStdStream; +}; // class nsOutputFileStream //======================================================================================== -// Implementation of nsFileBufferT +// Manipulators //======================================================================================== - -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -inline FILE_BUFFER_TYPE::nsFileBufferT() - : BASIC_STREAMBUF(), mFileDesc(NULL) -//---------------------------------------------------------------------------------------- -{ -} - -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -inline FILE_BUFFER_TYPE::nsFileBufferT(PRFileDesc* pfarg) - : BASIC_STREAMBUF(), mFileDesc(pfarg) -//---------------------------------------------------------------------------------------- -{ -} - -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -inline FILE_BUFFER_TYPE* FILE_BUFFER_TYPE::close() -// Must precede the destructor because both are inline. -//---------------------------------------------------------------------------------------- -{ - if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR) - return this; - NS_WRITE_LOCK(_mutex); - return (mFileDesc && PR_Close(mFileDesc) == PR_SUCCESS) ? mFileDesc = 0, this : 0; -} - -#if defined(DEFINING_FILE_STREAM) -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -FILE_BUFFER_TYPE::~nsFileBufferT() -//---------------------------------------------------------------------------------------- -{ - close(); -} -#endif // #if defined(DEFINING_FILE_STREAM) - -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -inline bool -FILE_BUFFER_TYPE::is_open() const -//---------------------------------------------------------------------------------------- -{ - NS_READ_LOCK(_mutex); - return bool(mFileDesc); // in case it is typedefed to int -} - -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -inline FILE_BUFFER_TYPE* FILE_BUFFER_TYPE::open( - const nsFilePath& inFile, - IOS_BASE::openmode mode, - PRIntn accessMode) -//---------------------------------------------------------------------------------------- -{ - if (mFileDesc) - return 0; - NS_WRITE_LOCK(_mutex); - mFileDesc = nsFileStreamHelpers::open(inFile, mode, accessMode); - if (!mFileDesc) - return 0; - mode_ = mode; - return this; -} // FILE_BUFFER_TYPE::open - -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -inline int FILE_BUFFER_TYPE:: sync() -//---------------------------------------------------------------------------------------- -{ - return (mFileDesc ? (int)PR_Sync(mFileDesc) : 0); -} - -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -inline BASIC_STREAMBUF* FILE_BUFFER_TYPE::setbuf(char_type*, streamsize) -//---------------------------------------------------------------------------------------- -{ - return (!mFileDesc) ? 0 : this; -} - -#if defined(DEFINING_FILE_STREAM) -//---------------------------------------------------------------------------------------- -TEMPLATE_DEF -INT_TYPE FILE_BUFFER_TYPE::overflow(int_type c) -//---------------------------------------------------------------------------------------- -{ -#ifndef NS_USING_STL - char ch = c; - PRInt32 bytesWrit1 = PR_Write(mFileDesc, &ch, sizeof(ch)); - return bytesWrit1 < sizeof(ch) ? EOF_VALUE : c; -#else -#ifdef NS_EXPLICIT_FUNC_TEMPLATE_ARG - const ofacet_type& ft=use_facet(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(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(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 > nsFileBuffer; -typedef nsInputFileStreamT > nsInputFileStream; -typedef nsOutputFileStreamT > nsOutputFileStream; -typedef nsIOFileStreamT > nsIOFileStream; - -#ifdef NS_USING_WIDE_CHAR -typedef nsFileBufferT > nsWideFileBuffer; -typedef nsInputFileStreamT > nsWideInputFileStream; -typedef nsOutputFileStreamT > nsWideOutputFileStream; -typedef nsIOFileStreamT > nsWideIOFileStream; -#endif // NS_USING_WIDE_CHAR - -#else - -typedef nsFileBufferT nsFileBuffer; -typedef nsInputFileStreamT nsInputFileStream; -typedef nsOutputFileStreamT nsOutputFileStream; -typedef nsIOFileStreamT nsIOFileStream; - -#endif +nsOutputFileStream& nsEndl(nsOutputFileStream& os); + #endif /* _FILESTREAM_H_ */ diff --git a/xpcom/tests/FilesTest.cpp b/xpcom/tests/FilesTest.cpp index 396bec6f47e..b810e8a8b06 100644 --- a/xpcom/tests/FilesTest.cpp +++ b/xpcom/tests/FilesTest.cpp @@ -1,53 +1,46 @@ #include "nsFileSpec.h" #include "nsFileStream.h" -#ifdef NS_USING_STL -#include - using namespace std; -#else -#include -#endif - NS_NAMESPACE FileTest { - NS_NAMESPACE_PROTOTYPE void WriteStuff(ostream& s); + NS_NAMESPACE_PROTOTYPE void WriteStuff(nsOutputFileStream& s); } NS_NAMESPACE_END //---------------------------------------------------------------------------------------- -void FileTest::WriteStuff(ostream& s) +void FileTest::WriteStuff(nsOutputFileStream& s) //---------------------------------------------------------------------------------------- { // Initialize a URL from a string without suffix. Change the path to suit your machine. nsFileURL fileURL("file:///Development/MPW/MPW%20Shell"); - s << "File URL initialized to: \"" << fileURL << "\""<< endl; + s << "File URL initialized to: \"" << fileURL << "\""<< nsEndl; // Initialize a Unix path from a URL nsFilePath filePath(fileURL); - s << "As a unix path: \"" << (const char*)filePath << "\""<< endl; + s << "As a unix path: \"" << (const char*)filePath << "\""<< nsEndl; // Initialize a native file spec from a URL nsNativeFileSpec fileSpec(fileURL); - s << "As a file spec: " << fileSpec << endl; + s << "As a file spec: " << fileSpec << nsEndl; // Make the spec unique (this one has no suffix). fileSpec.MakeUnique(); - s << "Unique file spec: " << fileSpec << endl; + s << "Unique file spec: " << fileSpec << nsEndl; // Assign the spec to a URL fileURL = fileSpec; - s << "File URL assigned from spec: \"" << fileURL << "\""<< endl; + s << "File URL assigned from spec: \"" << fileURL << "\""<< nsEndl; // Assign a unix path using a string with a suffix. filePath = "/Development/MPW/SysErrs.err"; - s << "File path reassigned to: \"" << (const char*)filePath << "\""<< endl; + s << "File path reassigned to: \"" << (const char*)filePath << "\""<< nsEndl; // Assign to a file spec using a unix path. fileSpec = filePath; - s << "File spec reassigned to: " << fileSpec << endl; + s << "File spec reassigned to: " << fileSpec << nsEndl; // Make this unique (this one has a suffix). fileSpec.MakeUnique(); - s << "File spec made unique: " << fileSpec << endl; + s << "File spec made unique: " << fileSpec << nsEndl; } // WriteStuff //---------------------------------------------------------------------------------------- @@ -58,33 +51,36 @@ void main() // Test of nsFileSpec - cout << "WRITING TEST OUTPUT TO cout" << endl << endl; - FileTest::WriteStuff(cout); - cout << endl << endl; + nsOutputFileStream nsOut(cout); + nsOut << "WRITING TEST OUTPUT TO cout" << nsEndl << nsEndl; + + FileTest::WriteStuff(nsOut); + nsOut << nsEndl << nsEndl; // Test of nsOutputFileStream nsFilePath myTextFilePath("/Development/iotest.txt"); { - cout << "WRITING IDENTICAL OUTPUT TO " << (const char*)myTextFilePath << endl << endl; + nsOut << "WRITING IDENTICAL OUTPUT TO " << (const char*)myTextFilePath << nsEndl << nsEndl; nsOutputFileStream testStream(myTextFilePath); + NS_ASSERTION(testStream.is_open(), "File could not be opened"); FileTest::WriteStuff(testStream); } // <-- Scope closes the stream (and the file). // Test of nsInputFileStream { - cout << "READING BACK DATA FROM " << (const char*)myTextFilePath << endl << endl; + nsOut << "READING BACK DATA FROM " << (const char*)myTextFilePath << nsEndl << nsEndl; nsInputFileStream testStream2(myTextFilePath); + NS_ASSERTION(testStream2.is_open(), "File could not be opened"); char line[1000]; - testStream2.seekg(0); // check that the seek template compiles + testStream2.seek(0); // check that the seek compiles while (!testStream2.eof()) { - testStream2.getline(line, sizeof(line), '\n'); - cout << line << endl; + testStream2.readline(line, sizeof(line)); + nsOut << line << nsEndl; } } - } // main