gecko-dev/xpcom/io/nsFileStream.h

333 lines
13 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0(the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright(C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
// First checked in on 98/11/20 by John R. McMullen in the wrong directory.
// Checked in again 98/12/04.
// Polished version 98/12/08.
//========================================================================================
//
// Classes defined:
//
// single-byte char:
//
// nsInputFileStream, nsOutputFileStream
//
// This suite provide the following services:
//
// 1. Encapsulates all platform-specific file details, so that file i/o
// can be done correctly without any platform #ifdefs
//
// 2. Uses NSPR file services (NOT ansi file I/O), in order to get best
// native performance. This performance difference is especially large on
// macintosh.
//
// 3. Allows all the power of the ansi stream syntax.
//
// Basic example:
//
// nsFilePath myPath("/Development/iotest.txt");
//
// nsOutputFileStream testStream(myPath);
// 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
// nsFileSpec.h for more details.
//
// 5. Fixes a bug that have been there for a long time, and
// is inevitable if you use NSPR alone:
//
// The problem on platforms (Macintosh) in which a path does not fully
// specify a file, because two volumes can have the same name.
//
// Not yet provided:
//
// Endian-awareness for reading and writing crossplatform binary files. At this
// time there seems to be no demand for this.
//
//========================================================================================
#ifndef _FILESTREAM_H_
#define _FILESTREAM_H_
#include "nscore.h"
#ifdef XP_MAC
#include "pprio.h" // To get PR_ImportFile
#else
#include "prio.h"
#endif
#include "nsFileSpec.h"
//========================================================================================
// Compiler-specific macros, as needed
//========================================================================================
#if !defined(NS_USING_NAMESPACE) && (defined(__MWERKS__) || defined(XP_PC))
#define NS_USING_NAMESPACE
#endif
#if !defined(NS_USING_STL) && (defined(__MWERKS__) || defined(XP_PC))
#define NS_USING_STL
#endif
#ifdef NS_USING_NAMESPACE
#define NS_NAMESPACE_PROTOTYPE
#define NS_NAMESPACE namespace
#define NS_NAMESPACE_END
#else
#define NS_NAMESPACE_PROTOTYPE static
#define NS_NAMESPACE struct
#define NS_NAMESPACE_END ;
#endif // NS_USING_NAMESPACE
#ifndef XP_MAC
// PR_STDOUT and PR_STDIN are fatal on Macintosh. So for console i/o, we must use the std
// stream stuff instead. However, we have to require that cout and cin are passed in
// to the constructor because in the current build, there is a copy in the base.shlb,
// and another in the caller's file. Passing it in as a parameter ensures that the
// caller and this library are using the same global object. Groan.
//
// Unix currently does not support iostreams at all. Their compilers do not support
// ANSI C++, or even ARM C++.
//
// Windows supports them, but only if you turn on the -GX compile flag, to support
// exceptions.
// Catch 22.
#define NS_USE_PR_STDIO
#endif
#ifdef NS_USE_PR_STDIO
class istream;
class ostream;
#define CONSOLE_IN 0
#define CONSOLE_OUT 0
#else
#include <iostream>
using std::istream;
using std::ostream;
#define CONSOLE_IN &std::cin
#define CONSOLE_OUT &std::cout
#endif
//=========================== End Compiler-specific macros ===============================
//========================================================================================
class NS_BASE nsBasicFileStream
//========================================================================================
{
public:
nsBasicFileStream();
nsBasicFileStream(PRFileDesc* desc, int nsprMode);
nsBasicFileStream(
const nsFilePath& inFile,
int nsprMode,
PRIntn accessMode);
virtual ~nsBasicFileStream();
inline PRBool is_open() const { return mFileDesc != 0; }
void open(
const nsFilePath& inFile,
int nsprMode,
PRIntn accessMode);
void close();
PRIntn tell() const;
void seek(PRInt32 offset) { seek(PR_SEEK_SET, offset); }
void seek(PRSeekWhence whence, PRInt32 offset);
PRBool eof() const { return mEOF; }
PRBool failed() const { return mFailed; }
// call PR_GetError() for details
protected:
PRFileDesc* GetFileDescriptor() const { return mFileDesc; }
protected:
friend class nsBasicInStream;
friend class nsBasicOutStream;
PRFileDesc* mFileDesc;
int mNSPRMode;
PRBool mFailed;
PRBool mEOF;
}; // class nsBasicFileStream
//========================================================================================
class NS_BASE nsBasicInStream
//========================================================================================
{
protected:
nsBasicInStream(nsBasicFileStream& inStream, istream* stream);
public:
nsBasicInStream& operator >> (nsBasicInStream& (*pf)(nsBasicInStream&))
{
return pf(*this);
}
void get(char& c);
PRInt32 read(void* s, PRInt32 n);
PRBool readline(char* s, PRInt32 n);
// Result always null-terminated
// false result indicates line was truncated
// to fit buffer, or an error occurred.
// Input streamers. Add more as needed
nsBasicInStream& operator >> (char& ch);
istream* GetStandardStream() const { return mStdStream; }
protected:
nsBasicFileStream& mBase;
istream* mStdStream;
}; // class nsBasicInStream
//========================================================================================
class NS_BASE nsBasicOutStream
//========================================================================================
{
protected:
nsBasicOutStream(nsBasicFileStream& inStream, ostream* stream);
public:
nsBasicOutStream& operator << (nsBasicOutStream& (*pf)(nsBasicOutStream&))
{
return pf(*this);
}
void put(char c);
PRInt32 write(const void* s, PRInt32 n);
void flush();
// Output streamers. Add more as needed
nsBasicOutStream& operator << (const char* buf);
nsBasicOutStream& operator << (char ch);
nsBasicOutStream& operator << (short val);
nsBasicOutStream& operator << (unsigned short val);
nsBasicOutStream& operator << (long val);
nsBasicOutStream& operator << (unsigned long val);
ostream* GetStandardStream() const { return mStdStream; }
protected:
nsBasicFileStream& mBase;
ostream* mStdStream;
}; // class nsBasicOutStream
//========================================================================================
class NS_BASE nsInputFileStream
//========================================================================================
: public nsBasicFileStream
, public nsBasicInStream
{
public:
enum { kDefaultMode = PR_RDONLY };
nsInputFileStream(istream* stream = CONSOLE_IN);
nsInputFileStream(
const nsFilePath& inFile,
int nsprMode = kDefaultMode,
PRIntn accessMode = 00700) // <- OCTAL
: nsBasicFileStream(inFile, nsprMode, accessMode)
, nsBasicInStream(*this, 0)
{}
void open(
const nsFilePath& inFile,
int nsprMode = kDefaultMode,
PRIntn accessMode = 00700) // <- OCTAL
{
nsBasicFileStream::open(inFile, nsprMode, accessMode);
}
private:
nsInputFileStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE.
}; // class nsInputFileStream
//========================================================================================
class NS_BASE nsOutputFileStream
//========================================================================================
: public nsBasicFileStream
, public nsBasicOutStream
{
public:
enum { kDefaultMode = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE) };
nsOutputFileStream(ostream* stream = CONSOLE_OUT);
nsOutputFileStream(
const nsFilePath& inFile,
int nsprMode = kDefaultMode,
PRIntn accessMode = 00700) // <- OCTAL
: nsBasicFileStream(inFile, nsprMode, accessMode)
, nsBasicOutStream(*this, 0)
{}
inline void open(
const nsFilePath& inFile,
int nsprMode = kDefaultMode,
PRIntn accessMode = 00700) // <- OCTAL
{
nsBasicFileStream::open(inFile, nsprMode, accessMode);
}
}; // class nsOutputFileStream
//========================================================================================
class NS_BASE nsIOFileStream
//========================================================================================
: public nsBasicFileStream
, public nsBasicOutStream
, public nsBasicInStream
{
public:
enum { kDefaultMode = (PR_RDWR | PR_CREATE_FILE) };
nsIOFileStream(
const nsFilePath& inFile,
int nsprMode = kDefaultMode,
PRIntn accessMode = 00700) // <- OCTAL
: nsBasicFileStream(inFile, nsprMode, accessMode)
, nsBasicInStream(*this, 0)
, nsBasicOutStream(*this, 0)
{}
inline void open(
const nsFilePath& inFile,
int nsprMode = kDefaultMode,
PRIntn accessMode = 00700) // <- OCTAL
{
nsBasicFileStream::open(inFile, nsprMode, accessMode);
}
}; // class nsIOFileStream
//========================================================================================
// Manipulators
//========================================================================================
NS_BASE nsBasicOutStream& nsEndl(nsBasicOutStream& os);
#endif /* _FILESTREAM_H_ */