Merging branch BASE_19_FEB_99 to tip. These are extensive changes

to nsFileSpec and and nsFileStream.  See dougt@netscape.com or
John McMullen for futher information.


git-svn-id: svn://10.0.0.236/trunk@21977 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
dougt%netscape.com
1999-02-25 20:49:47 +00:00
parent f1b059f18d
commit 451b4db4af
33 changed files with 4238 additions and 1526 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -5,6 +5,7 @@
nsAutoLock.h
nsISizeOfHandler.h
nsFileStream.h
nsIFileStream.h
nsFileSpec.h
nsRepeater.h
nsIProperties.h

View File

@@ -32,6 +32,7 @@ EXPORTS = \
nsEscape.h \
nsFileSpec.h \
nsFileStream.h \
nsIFileStream.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))

View File

@@ -28,6 +28,7 @@ EXPORTS = \
nsEscape.h \
nsFileSpec.h \
nsFileStream.h \
nsIFileStream.h \
$(NULL)
MODULE = raptor

View File

@@ -24,7 +24,16 @@
//
// Classes defined:
//
// nsFilePath, nsFileURL, nsNativeFileSpec.
// nsFilePath, nsFileURL, nsFileSpec, nsPersistentFileDescriptor.
//
// Q. How should I represent files at run time?
// A. Use nsFileSpec. Using char* will lose information on some platforms.
//
// Q. Then what are nsFilePath and nsFileURL for?
// A. Only when you need a char* parameter for legacy code.
//
// Q. How should I represent files in a persistent way (eg, in a disk file)?
// A. Use nsPersistentFileDescriptor. Convert to and from nsFileSpec at run time.
//
// This suite provides the following services:
//
@@ -63,7 +72,7 @@
//
// Initialize a native file spec from a URL
//
// nsNativeFileSpec fileSpec(fileURL);
// nsFileSpec fileSpec(fileURL);
//
// Make the spec unique (this one has no suffix).
//
@@ -103,6 +112,7 @@
#define _FILESPEC_H_
#include "nscore.h"
#include "nsError.h"
//========================================================================================
// Compiler-specific macros, as needed
@@ -116,11 +126,13 @@
#define NS_NAMESPACE_PROTOTYPE
#define NS_NAMESPACE namespace
#define NS_NAMESPACE_END
#define NS_EXPLICIT explicit
#else
#define NS_NAMESPACE_PROTOTYPE static
#define NS_NAMESPACE struct
#define NS_NAMESPACE_END ;
#define NS_EXPLICIT
#endif
//=========================== End Compiler-specific macros ===============================
@@ -137,33 +149,50 @@
// Here are the allowable ways to describe a file.
//========================================================================================
class nsFilePath; // This can be passed to NSPR file I/O routines.
class nsFileSpec; // Preferred. For i/o use nsInputFileStream, nsOutputFileStream
class nsFilePath; // This can be passed to NSPR file I/O routines, if you must.
class nsFileURL;
class nsNativeFileSpec;
class nsPersistentFileDescriptor; // Used for storage across program launches.
#define kFileURLPrefix "file://"
#define kFileURLPrefixLength (7)
class nsBasicOutStream;
class nsOutputStream;
class nsInputStream;
class nsOutputFileStream;
class nsInputFileStream;
//========================================================================================
class NS_BASE nsNativeFileSpec
// Conversion of native file errors to nsresult values. These are really only for use
// in the file module, clients of this interface shouldn't really need them.
// Error results returned from this interface have, in the low-order 16 bits,
// native errors that are masked to 16 bits. Assumption: a native error of 0 is success
// on all platforms. Note the way we define this using an inline function. This
// avoids multiple evaluation if people go NS_FILE_RESULT(function_call()).
#define NS_FILE_RESULT(x) ns_file_convert_result((PRInt32)x)
nsresult ns_file_convert_result(PRInt32 nativeErr);
#define NS_FILE_FAILURE NS_FILE_RESULT(-1)
//========================================================================================
class NS_BASE nsFileSpec
// This is whatever each platform really prefers to describe files as. Declared first
// because the other two types have an embeded nsNativeFileSpec object.
// because the other two types have an embeded nsFileSpec object.
//========================================================================================
{
public:
nsNativeFileSpec();
explicit nsNativeFileSpec(const char* inString, bool inCreateDirs = false);
explicit nsNativeFileSpec(const nsFilePath& inPath);
explicit nsNativeFileSpec(const nsFileURL& inURL);
nsNativeFileSpec(const nsNativeFileSpec& inPath);
virtual ~nsNativeFileSpec();
nsFileSpec();
NS_EXPLICIT nsFileSpec(const char* inString, PRBool inCreateDirs = PR_FALSE);
NS_EXPLICIT nsFileSpec(const nsFilePath& inPath);
NS_EXPLICIT nsFileSpec(const nsFileURL& inURL);
NS_EXPLICIT nsFileSpec(const nsPersistentFileDescriptor& inURL);
nsFileSpec(const nsFileSpec& inPath);
virtual ~nsFileSpec();
void operator = (const char* inPath);
void operator = (const nsFilePath& inPath);
void operator = (const nsFileURL& inURL);
void operator = (const nsNativeFileSpec& inOther);
void operator = (const nsFileSpec& inOther);
void operator = (const nsPersistentFileDescriptor& inOther);
#ifndef XP_MAC
operator const char* () const { return mPath; }
@@ -175,23 +204,22 @@ class NS_BASE nsNativeFileSpec
#ifdef XP_MAC
// For Macintosh people, this is meant to be useful in its own right as a C++ version
// of the FSSpec struct.
nsNativeFileSpec(
nsFileSpec(
short vRefNum,
long parID,
ConstStr255Param name);
nsNativeFileSpec(const FSSpec& inSpec)
: mSpec(inSpec), mError(noErr) {}
nsFileSpec(const FSSpec& inSpec)
: mSpec(inSpec), mError(NS_OK) {}
operator FSSpec* () { return &mSpec; }
operator const FSSpec* const () { return &mSpec; }
operator FSSpec& () { return mSpec; }
operator const FSSpec& () const { return mSpec; }
OSErr Error() const { return mError; }
void MakeAliasSafe();
// Called for the spec of an alias. Copies the alias to
// a secret temp directory and modifies the spec to point
// to it. Sets mError.
void ResolveAlias(bool& wasAliased);
void ResolveAlias(PRBool& wasAliased);
// Called for the spec of an alias. Modifies the spec to
// point to the original. Sets mError.
void MakeUnique(ConstStr255Param inSuggestedLeafName);
@@ -199,15 +227,15 @@ class NS_BASE nsNativeFileSpec
ConstStr255Param GetLeafPName() const { return mSpec.name; }
#endif // end of Macintosh utility methods.
#ifdef XP_MAC
bool Valid() const { return mError == noErr; }
#else
bool Valid() const { return true; } // Fixme.
#endif // XP_MAC
PRBool Valid() const { return NS_SUCCEEDED(Error()); }
nsresult Error() const { return mError; }
friend NS_BASE nsBasicOutStream& operator << (
nsBasicOutStream& s,
const nsNativeFileSpec& spec);
#if DEBUG
friend NS_BASE nsOutputStream& operator << (
nsOutputStream& s,
const nsFileSpec& spec); // THIS IS FOR DEBUGGING ONLY.
// see PersistentFileDescriptor for the real deal.
#endif
//--------------------------------------------------
// Queries and path algebra. These do not modify the disk.
@@ -218,7 +246,7 @@ class NS_BASE nsNativeFileSpec
// inLeafName can be a relative path, so this allows
// one kind of concatenation of "paths".
void GetParent(nsNativeFileSpec& outSpec) const;
void GetParent(nsFileSpec& outSpec) const;
// Return the filespec of the parent directory. Used
// in conjunction with GetLeafName(), this lets you
// parse a path into a list of node names. Beware,
@@ -226,7 +254,7 @@ class NS_BASE nsNativeFileSpec
// but a spec. Volumes on Macintosh can have identical
// names. Perhaps could be used for an operator --() ?
nsNativeFileSpec operator + (const char* inRelativePath) const;
nsFileSpec operator + (const char* inRelativePath) const;
void operator += (const char* inRelativePath);
// Concatenate the relative path to this directory.
// Used for constructing the filespec of a descendant.
@@ -240,19 +268,24 @@ class NS_BASE nsNativeFileSpec
void MakeUnique();
void MakeUnique(const char* inSuggestedLeafName);
bool IsDirectory() const;
PRBool IsDirectory() const;
// More stringent than Exists()
bool IsFile() const;
PRBool IsFile() const;
// More stringent than Exists()
bool Exists() const;
PRBool Exists() const;
//--------------------------------------------------
// Creation and deletion of objects. These can modify the disk.
//--------------------------------------------------
void CreateDirectory(int mode = 0700 /* for unix */);
void Delete(bool inRecursive);
void Delete(PRBool inRecursive);
nsresult Rename(const char* inNewName); // not const: gets updated
nsresult Copy(const nsFileSpec& inNewParentDirectory) const;
nsresult Move(const nsFileSpec& inNewParentDirectory) const;
nsresult Execute(const char* args) const;
//--------------------------------------------------
// Data
//--------------------------------------------------
@@ -261,11 +294,15 @@ class NS_BASE nsNativeFileSpec
friend class nsFilePath;
#ifdef XP_MAC
FSSpec mSpec;
OSErr mError;
#else
char* mPath;
#endif
}; // class nsNativeFileSpec
nsresult mError;
}; // class nsFileSpec
// FOR HISTORICAL REASONS:
typedef nsFileSpec nsNativeFileSpec;
//========================================================================================
class NS_BASE nsFileURL
@@ -276,9 +313,9 @@ class NS_BASE nsFileURL
{
public:
nsFileURL(const nsFileURL& inURL);
explicit nsFileURL(const char* inString, bool inCreateDirs = false);
explicit nsFileURL(const nsFilePath& inPath);
explicit nsFileURL(const nsNativeFileSpec& inPath);
NS_EXPLICIT nsFileURL(const char* inString, PRBool inCreateDirs = PR_FALSE);
NS_EXPLICIT nsFileURL(const nsFilePath& inPath);
NS_EXPLICIT nsFileURL(const nsFileSpec& inPath);
virtual ~nsFileURL();
// nsString GetString() const { return mPath; }
@@ -288,14 +325,14 @@ class NS_BASE nsFileURL
void operator = (const nsFileURL& inURL);
void operator = (const char* inString);
void operator = (const nsFilePath& inOther);
void operator = (const nsNativeFileSpec& inOther);
void operator = (const nsFileSpec& inOther);
friend NS_BASE nsBasicOutStream& operator << (
nsBasicOutStream& s, const nsFileURL& spec);
friend NS_BASE nsOutputStream& operator << (
nsOutputStream& s, const nsFileURL& spec);
#ifdef XP_MAC
// Accessor to allow quick assignment to a mNativeFileSpec
const nsNativeFileSpec& GetNativeSpec() const { return mNativeFileSpec; }
// Accessor to allow quick assignment to a mFileSpec
const nsFileSpec& GetFileSpec() const { return mFileSpec; }
#endif
private:
// Should not be defined (only nsFilePath is to be treated as strings.
@@ -306,8 +343,8 @@ class NS_BASE nsFileURL
char* mURL;
#ifdef XP_MAC
// Since the path on the macintosh does not uniquely specify a file (volumes
// can have the same name), stash the secret nsNativeFileSpec, too.
nsNativeFileSpec mNativeFileSpec;
// can have the same name), stash the secret nsFileSpec, too.
nsFileSpec mFileSpec;
#endif
}; // class nsFileURL
@@ -319,9 +356,9 @@ class NS_BASE nsFilePath
{
public:
nsFilePath(const nsFilePath& inPath);
explicit nsFilePath(const char* inString, bool inCreateDirs = false);
explicit nsFilePath(const nsFileURL& inURL);
explicit nsFilePath(const nsNativeFileSpec& inPath);
NS_EXPLICIT nsFilePath(const char* inString, PRBool inCreateDirs = PR_FALSE);
NS_EXPLICIT nsFilePath(const nsFileURL& inURL);
NS_EXPLICIT nsFilePath(const nsFileSpec& inPath);
virtual ~nsFilePath();
@@ -337,12 +374,12 @@ class NS_BASE nsFilePath
void operator = (const nsFilePath& inPath);
void operator = (const char* inString);
void operator = (const nsFileURL& inURL);
void operator = (const nsNativeFileSpec& inOther);
void operator = (const nsFileSpec& inOther);
#ifdef XP_MAC
public:
// Accessor to allow quick assignment to a mNativeFileSpec
const nsNativeFileSpec& GetNativeSpec() const { return mNativeFileSpec; }
// Accessor to allow quick assignment to a mFileSpec
const nsFileSpec& GetFileSpec() const { return mFileSpec; }
#endif
private:
@@ -350,26 +387,59 @@ class NS_BASE nsFilePath
char* mPath;
#ifdef XP_MAC
// Since the path on the macintosh does not uniquely specify a file (volumes
// can have the same name), stash the secret nsNativeFileSpec, too.
nsNativeFileSpec mNativeFileSpec;
// can have the same name), stash the secret nsFileSpec, too.
nsFileSpec mFileSpec;
#endif
}; // class nsFilePath
//========================================================================================
class NS_BASE nsPersistentFileDescriptor
//========================================================================================
{
public:
nsPersistentFileDescriptor() : mDescriptorString(nsnull) {}
// For use prior to reading in from a stream
nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inPath);
virtual ~nsPersistentFileDescriptor();
void operator = (const nsPersistentFileDescriptor& inPath);
// Conversions
nsPersistentFileDescriptor(const nsFileSpec& inPath);
void operator = (const nsFileSpec& inPath);
friend NS_BASE nsInputStream& operator >> (nsInputStream&, nsPersistentFileDescriptor&);
// reads the data from a file
friend NS_BASE nsOutputStream& operator << (nsOutputStream&, const nsPersistentFileDescriptor&);
// writes the data to a file
friend class nsFileSpec;
private:
// Here are the ways to get data in and out of a file.
void GetData(void*& outData, PRInt32& outSize) const;
// DON'T FREE the returned data!
void SetData(const void* inData, PRInt32 inSize);
private:
char* mDescriptorString;
}; // class nsPersistentFileDescriptor
//========================================================================================
class NS_BASE nsDirectoryIterator
// Example:
//
// nsNativeFileSpec parentDir(...); // directory over whose children we shall iterate
// nsFileSpec parentDir(...); // directory over whose children we shall iterate
// for (nsDirectoryIterator i(parentDir); i; i++)
// {
// // do something with (const nsNativeFileSpec&)i
// // do something with (const nsFileSpec&)i
// }
//
// or:
//
// for (nsDirectoryIterator i(parentDir, false); i; i--)
// for (nsDirectoryIterator i(parentDir, PR_FALSE); i; i--)
// {
// // do something with (const nsNativeFileSpec&)i
// // do something with (const nsFileSpec&)i
// }
//
// Currently, the only platform on which backwards iteration actually goes backwards
@@ -378,21 +448,21 @@ class NS_BASE nsDirectoryIterator
{
public:
nsDirectoryIterator(
const nsNativeFileSpec& parent,
const nsFileSpec& parent,
int iterateDirection = +1);
#ifndef XP_MAC
// Macintosh currently doesn't allocate, so needn't clean up.
virtual ~nsDirectoryIterator();
#endif
operator bool() const { return mExists; }
PRBool Exists() const { return mExists; }
nsDirectoryIterator& operator ++(); // moves to the next item, if any.
nsDirectoryIterator& operator ++(int) { return ++(*this); } // post-increment.
nsDirectoryIterator& operator --(); // moves to the previous item, if any.
nsDirectoryIterator& operator --(int) { return --(*this); } // post-decrement.
operator nsNativeFileSpec&() { return mCurrent; }
operator nsFileSpec&() { return mCurrent; }
private:
nsNativeFileSpec mCurrent;
bool mExists;
nsFileSpec mCurrent;
bool mExists; // MUST be bool.
#if defined(XP_UNIX)
DIR* mDir;

View File

@@ -19,14 +19,31 @@
// 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.
// Completely rewritten to integrate with nsIInputStream and nsIOutputStream (the
// xpcom stream objects.
//========================================================================================
//
// Classes defined:
//
// single-byte char:
//
// nsInputStream, nsOutputStream
// These are the lightweight STATICALLY LINKED wrappers for
// the xpcom objects nsIInputStream and nsIOutputstream.
// Possible uses:
// If you are implementing a function that accepts one of these xpcom
// streams, just make one of these little jobbies on the stack, and
// the handy << or >> notation can be yours.
//
// nsInputFileStream, nsOutputFileStream
// These are the STATICALLY LINKED versions of the file i/o streams,
// which wrap the NSPR file i/o plus console i/o.
//
// Related files:
// prio.h the NSPR file i/o C API), which is wrapped by
// THIS FILE statically linked C++ wrappers, which in turn are wrapped by
// nsIFileStream.h COM wrappers for this file, which are wrapped by
// nsAutoFileStream.h more easily used, nicer syntax wrappers for the
// COMified ones. Wrapper of a wrapper of a wrapper.
//
// This suite provide the following services:
//
@@ -41,13 +58,13 @@
//
// Basic example:
//
// nsFilePath myPath("/Development/iotest.txt");
// nsFileSpec 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
// 4. Requires streams to be constructed using typesafe nsFileSpec specifier
// (not the notorious and bug prone const char*), namely nsFileSpec. See
// nsFileSpec.h for more details.
//
// 5. Fixes a bug that have been there for a long time, and
@@ -73,7 +90,13 @@
#else
#include "prio.h"
#endif
#include "nsFileSpec.h"
#include "nsIFileStream.h"
#include "nsCOMPtr.h"
class nsFileSpec;
class nsInputFileStream;
class nsOutputFileStream;
//========================================================================================
// Compiler-specific macros, as needed
@@ -133,201 +156,392 @@ using std::ostream;
//=========================== End Compiler-specific macros ===============================
//========================================================================================
class NS_BASE nsBasicFileStream
class NS_BASE nsInputStream
// This is a convenience class, for use on the STACK ("new" junkies: get detoxed first).
// Given a COM-style stream, this allows you to use the >> operators. It also acquires and
// reference counts its stream.
// Please read the comments at the top of this file
//========================================================================================
{
public:
nsBasicFileStream();
nsBasicFileStream(PRFileDesc* desc, int nsprMode);
nsBasicFileStream(
const nsFilePath& inFile,
int nsprMode,
PRIntn accessMode);
virtual ~nsBasicFileStream();
nsInputStream(nsIInputStream* inStream)
: mInputStream(do_QueryInterface(inStream))
, mEOF(PR_FALSE)
{}
virtual ~nsInputStream();
nsCOMPtr<nsIInputStream> GetIStream() const
{
return mInputStream;
}
char eof() const { return mEOF; }
char get();
PRInt32 read(void* s, PRInt32 n)
{
if (!mInputStream)
return 0;
PRInt32 result = 0;
mInputStream->Read((char*)s, 0, n, (PRUint32*)&result);
if (result < n)
mEOF = PR_TRUE;
return result;
}
// Input streamers. Add more as needed (int&, unsigned int& etc). (but you have to
// add delegators to the derived classes, too, because these operators don't inherit).
nsInputStream& operator >> (char& ch);
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&))
// Support manipulators
nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
{
return pf(*this);
}
void get(char& c);
PRInt32 read(void* s, PRInt32 n);
}
private:
nsInputStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE.
// DATA
protected:
nsCOMPtr<nsIInputStream> mInputStream;
PRBool mEOF;
}; // class nsInputStream
typedef nsInputStream nsBasicInStream; // historic support for this name
//========================================================================================
class NS_BASE nsOutputStream
// This is a convenience class, for use on the STACK ("new" junkies, get detoxed first).
// Given a COM-style stream, this allows you to use the << operators. It also acquires and
// reference counts its stream.
// Please read the comments at the top of this file
//========================================================================================
{
public:
nsOutputStream() {}
nsOutputStream(nsIOutputStream* inStream)
: mOutputStream(do_QueryInterface(inStream))
{}
virtual ~nsOutputStream();
nsCOMPtr<nsIOutputStream> GetIStream() const
{
return mOutputStream;
}
void put(char c);
PRInt32 write(const void* s, PRInt32 n)
{
if (!mOutputStream)
return 0;
PRInt32 result = 0;
mOutputStream->Write((char*)s, 0, n, (PRUint32*)&result);
return result;
}
virtual void flush();
// Output streamers. Add more as needed (but you have to add delegators to the derived
// classes, too, because these operators don't inherit).
nsOutputStream& operator << (const char* buf);
nsOutputStream& operator << (char ch);
nsOutputStream& operator << (short val);
nsOutputStream& operator << (unsigned short val);
nsOutputStream& operator << (long val);
nsOutputStream& operator << (unsigned long val);
// Support manipulators
nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
{
return pf(*this);
}
// DATA
protected:
nsCOMPtr<nsIOutputStream> mOutputStream;
}; // class nsOutputStream
typedef nsOutputStream nsBasicOutStream; // Historic support for this name
//========================================================================================
class NS_BASE nsFileClient
// Because COM does not allow us to write functions which return a boolean value etc,
// this class is here to take care of the tedious "declare variable then call with
// the address of the variable" chores.
//========================================================================================
{
public:
nsFileClient() // for delayed opening
: mResult(NS_OK)
{
}
nsFileClient(const nsCOMPtr<nsIFile>& inFile)
: mFile(do_QueryInterface(inFile))
, mResult(NS_OK)
{
}
PRBool is_file() const
{
return mFile ? PR_TRUE : PR_FALSE;
}
void open(
const nsFileSpec& inFile,
int nsprMode,
PRIntn accessMode)
{
if (mFile)
mResult = mFile->Open(inFile, nsprMode, accessMode);
}
PRBool is_open() const
{
PRBool result = PR_FALSE;
if (mFile)
mFile->GetIsOpen(&result);
return result;
}
PRBool failed() const
{
return NS_FAILED(mResult);
}
void seek(PRInt32 offset)
{
seek(PR_SEEK_SET, offset);
}
void seek(PRSeekWhence whence, PRInt32 offset)
{
if (mFile)
mResult = mFile->Seek(whence, offset);
}
PRIntn tell()
{
PRIntn result = -1;
if (mFile)
mResult = mFile->Tell(&result);
return result;
}
// DATA
protected:
nsCOMPtr<nsIFile> mFile;
PRBool mResult;
}; // class nsFileClient
//========================================================================================
class NS_BASE nsInputFileStream
// Please read the comments at the top of this file
//========================================================================================
: public nsInputStream
, public nsFileClient
{
public:
enum { kDefaultMode = PR_RDONLY };
nsInputFileStream(nsIInputStream* inStream)
: nsInputStream(inStream)
, nsFileClient(do_QueryInterface(inStream))
, mFileInputStream(do_QueryInterface(inStream))
{
}
nsInputFileStream(
const nsFileSpec& inFile,
int nsprMode = kDefaultMode,
PRIntn accessMode = 00700) // <- OCTAL
: nsInputStream(nsnull)
{
nsISupports* stream;
NS_NewIOFileStream(
&stream,
inFile, nsprMode, accessMode);
mFile = nsQueryInterface(stream);
mInputStream = nsQueryInterface(stream);
mFileInputStream = nsQueryInterface(stream);
}
PRBool readline(char* s, PRInt32 n);
// Result always null-terminated.
// Check eof() before each call.
// CAUTION: false result only indicates line was truncated
// to fit buffer, or an error occurred (OTHER THAN eof).
// 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,
void Open(
const nsFileSpec& inFile,
int nsprMode = kDefaultMode,
PRIntn accessMode = 00700) // <- OCTAL
{
nsBasicFileStream::open(inFile, nsprMode, accessMode);
if (mFile)
mFile->Open(inFile, nsprMode, accessMode);
}
private:
nsInputFileStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE.
// Input streamers. Unfortunately, they don't inherit!
nsInputStream& operator >> (char& ch)
{ return nsInputStream::operator >>(ch); }
nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
{ return nsInputStream::operator >>(pf); }
// DATA
protected:
nsCOMPtr<nsIFileInputStream> mFileInputStream;
}; // class nsInputFileStream
//========================================================================================
class NS_BASE nsOutputFileStream
// Please read the comments at the top of this file
//========================================================================================
: public nsBasicFileStream
, public nsBasicOutStream
: public nsOutputStream
, public nsFileClient
{
public:
enum { kDefaultMode = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE) };
nsOutputFileStream(ostream* stream = CONSOLE_OUT);
nsOutputFileStream() {}
nsOutputFileStream(nsIOutputStream* inStream)
: nsOutputStream(inStream)
, nsFileClient(do_QueryInterface(inStream))
, mFileOutputStream(do_QueryInterface(inStream))
{
}
nsOutputFileStream(
const nsFilePath& inFile,
const nsFileSpec& 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
: nsOutputStream(nsnull)
{
nsBasicFileStream::open(inFile, nsprMode, accessMode);
nsISupports* stream;
if (NS_FAILED(NS_NewIOFileStream(
&stream,
inFile, nsprMode, accessMode)))
return;
mFile = nsQueryInterface(stream);
mOutputStream = nsQueryInterface(stream);
mFileOutputStream = nsQueryInterface(stream);
}
virtual void flush();
// Output streamers. Unfortunately, they don't inherit!
nsOutputStream& operator << (const char* buf)
{ return nsOutputStream::operator << (buf); }
nsOutputStream& operator << (char ch)
{ return nsOutputStream::operator << (ch); }
nsOutputStream& operator << (short val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (unsigned short val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (long val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (unsigned long val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
{ return nsOutputStream::operator << (pf); }
// DATA
protected:
nsCOMPtr<nsIFileOutputStream> mFileOutputStream;
}; // class nsOutputFileStream
//========================================================================================
class NS_BASE nsIOFileStream
class NS_BASE nsOutputConsoleStream
// Please read the comments at the top of this file
//========================================================================================
: public nsBasicFileStream
, public nsBasicOutStream
, public nsBasicInStream
: public nsOutputFileStream
{
public:
nsOutputConsoleStream()
{
nsISupports* stream;
if (NS_FAILED(NS_NewOutputConsoleStream(&stream)))
return;
mFile = nsQueryInterface(stream);
mOutputStream = nsQueryInterface(stream);
mFileOutputStream = nsQueryInterface(stream);
}
// Output streamers. Unfortunately, they don't inherit!
nsOutputStream& operator << (const char* buf)
{ return nsOutputStream::operator << (buf); }
nsOutputStream& operator << (char ch)
{ return nsOutputStream::operator << (ch); }
nsOutputStream& operator << (short val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (unsigned short val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (long val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (unsigned long val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
{ return nsOutputStream::operator << (pf); }
}; // class nsOutputConsoleStream
//========================================================================================
class NS_BASE nsIOFileStream
// Please read the comments at the top of this file
//========================================================================================
: public nsInputFileStream
, public nsOutputStream
{
public:
enum { kDefaultMode = (PR_RDWR | PR_CREATE_FILE) };
nsIOFileStream(
const nsFilePath& inFile,
nsIInputStream* inInputStream
, nsIOutputStream* inOutputStream)
: nsInputFileStream(inInputStream)
, nsOutputStream(inOutputStream)
, mFileOutputStream(do_QueryInterface(inOutputStream))
{
}
nsIOFileStream(
const nsFileSpec& 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
: nsInputFileStream(nsnull)
, nsOutputStream(nsnull)
{
nsBasicFileStream::open(inFile, nsprMode, accessMode);
nsISupports* stream;
if (NS_FAILED(NS_NewIOFileStream(
&stream,
inFile, nsprMode, accessMode)))
return;
mFile = nsQueryInterface(stream);
mInputStream = nsQueryInterface(stream);
mOutputStream = nsQueryInterface(stream);
mFileInputStream = nsQueryInterface(stream);
mFileOutputStream = nsQueryInterface(stream);
}
}; // class nsIOFileStream
// Output streamers. Unfortunately, they don't inherit!
nsOutputStream& operator << (const char* buf)
{ return nsOutputStream::operator << (buf); }
nsOutputStream& operator << (char ch)
{ return nsOutputStream::operator << (ch); }
nsOutputStream& operator << (short val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (unsigned short val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (long val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (unsigned long val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
{ return nsOutputStream::operator << (pf); }
// Input streamers. Unfortunately, they don't inherit!
nsInputStream& operator >> (char& ch)
{ return nsInputStream::operator >>(ch); }
nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
{ return nsInputStream::operator >>(pf); }
// DATA
protected:
nsCOMPtr<nsIFileOutputStream> mFileOutputStream;
}; // class nsIOFileStream
//========================================================================================
// Manipulators
//========================================================================================
NS_BASE nsBasicOutStream& nsEndl(nsBasicOutStream& os);
NS_BASE nsOutputStream& nsEndl(nsOutputStream& os); // outputs and FLUSHES.
#endif /* _FILESTREAM_H_ */

View File

@@ -0,0 +1,127 @@
/* -*- 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.
*/
#ifndef nsIFileStream_h___
#define nsIFileStream_h___
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "prio.h"
class nsFileSpec;
/* a6cf90e8-15b3-11d2-932e-00805f8add32 */
#define NS_IFILE_IID \
{ 0xa6cf90e8, 0x15b3, 0x11d2, \
{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
//========================================================================================
class nsIFile
// Represents a file, and supports Open, Tell etc.
//========================================================================================
: public nsISupports
{
public:
static const nsIID& IID() { static nsIID iid = NS_IFILE_IID; return iid; }
NS_IMETHOD Open(
const nsFileSpec& inFile,
int nsprMode,
PRIntn accessMode) = 0;
// Note: Open() is only needed after
// an explicit Close(). All file streams
// are automatically opened on construction.
NS_IMETHOD Seek(PRSeekWhence whence, PRInt32 offset) = 0;
NS_IMETHOD GetIsOpen(PRBool* outOpen) = 0;
NS_IMETHOD Tell(PRIntn* outWhere) = 0;
}; // class nsIFile
/* a6cf90e6-15b3-11d2-932e-00805f8add32 */
#define NS_IFILEINPUTSTREAM_IID \
{ 0xa6cf90e6, 0x15b3, 0x11d2, \
{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
//========================================================================================
class nsIFileInputStream
// These are additional file-specific methods that files have, above what
// nsIInputStream supports. The current implementation supports both
// interfaces.
//========================================================================================
: public nsISupports
{
public:
static const nsIID& IID() { static nsIID iid = NS_IFILEINPUTSTREAM_IID; return iid; }
}; // class nsIFileInputStream
/* a6cf90e7-15b3-11d2-932e-00805f8add32 */
#define NS_IFILEOUTPUTSTREAM_IID \
{ 0xa6cf90e7, 0x15b3, 0x11d2, \
{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
//========================================================================================
class nsIFileOutputStream
// These are additional file-specific methods that files have, above what
// nsIOutputStream supports. The current implementation supports both
// interfaces.
//========================================================================================
: public nsISupports
{
public:
static const nsIID& IID() { static nsIID iid = NS_IFILEOUTPUTSTREAM_IID; return iid; }
NS_IMETHOD Flush() = 0;
// Forces a write to disk.
}; // class nsIFileOutputStream
//----------------------------------------------------------------------------------------
NS_BASE nsresult NS_NewTypicalInputFileStream(
nsISupports** aStreamResult,
const nsFileSpec& inFile
/*Default nsprMode == PR_RDONLY*/
/*Default accessmode = 0700 (octal)*/);
// Factory method to get an nsInputStream from a file, using most common options
//----------------------------------------------------------------------------------------
extern "C" NS_BASE nsresult NS_NewOutputConsoleStream(
nsISupports** aStreamResult);
// Factory method to get an nsOutputStream to the console.
//----------------------------------------------------------------------------------------
extern "C" NS_BASE nsresult NS_NewTypicalOutputFileStream(
nsISupports** aStreamResult, // will implement all the above interfaces
const nsFileSpec& inFile
/*default nsprMode= (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/
/*Default accessMode= 0700 (octal)*/);
// Factory method to get an nsOutputStream to a file - most common case.
//----------------------------------------------------------------------------------------
extern "C" NS_BASE nsresult NS_NewTypicalIOFileStream(
nsISupports** aStreamResult, // will implement all the above interfaces
const nsFileSpec& inFile
/*default nsprMode = (PR_RDWR | PR_CREATE_FILE)*/
/*Default accessMode = 0700 (octal)*/);
// Factory method to get an object that implements both nsIInputStream
// and nsIOutputStream, associated with a single file.
//----------------------------------------------------------------------------------------
extern "C" NS_BASE nsresult NS_NewIOFileStream(
nsISupports** aStreamResult, // will implement all the above interfaces
const nsFileSpec& inFile,
PRInt32 nsprMode,
PRInt32 accessMode);
// Factory method to get an object that implements both nsIInputStream
// and nsIOutputStream, associated with a single file.
#endif /* nsIFileStream_h___ */

View File

@@ -39,6 +39,7 @@ CPPSRCS = \
nsEscape.cpp \
nsFileSpec.cpp \
nsFileStream.cpp \
nsIFileStream.cpp \
nsProperties.cpp \
nsRBTree.cpp \
nsSizeOfHandler.cpp \

View File

@@ -28,6 +28,7 @@
#include <Folders.h>
#include <Errors.h>
#include <TextUtils.h>
#include <Processes.h>
const unsigned char* kAliasHavenFolderName = "\pnsAliasHaven";
@@ -74,7 +75,7 @@ namespace MacFileHelpers
// to support attaching of aliases in mail.
void EnsureAliasHaven();
void SetNoResolve(Boolean inResolve);
bool IsAliasSafe(const FSSpec& inSpec);
PRBool IsAliasSafe(const FSSpec& inSpec);
OSErr MakeAliasSafe(FSSpec& inOutSpec);
OSErr ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased);
@@ -131,8 +132,8 @@ char* MacFileHelpers::EncodeMacPath(
// Method: Swap ':' and '/', hex escape the result
//-----------------------------------
{
if (inPath == NULL)
return NULL;
if (inPath == nsnull)
return nsnull;
int pathSize = strlen(inPath);
// XP code sometimes chokes if there's a final slash in the unix path.
@@ -145,8 +146,8 @@ char* MacFileHelpers::EncodeMacPath(
pathSize--;
}
char * newPath = NULL;
char * finalPath = NULL;
char * newPath = nsnull;
char * finalPath = nsnull;
if (prependSlash)
{
@@ -188,10 +189,10 @@ OSErr MacFileHelpers::MakeAliasSafe(FSSpec& inOutSpec)
//----------------------------------------------------------------------------------------
{
EnsureAliasHaven();
nsNativeFileSpec dstDirSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\p");
nsFileSpec dstDirSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\p");
// Make sure its name is unique
nsNativeFileSpec havenSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\pG'day");
nsFileSpec havenSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\pG'day");
if (havenSpec.Valid())
havenSpec.MakeUnique(inOutSpec.name);
// Copy the file into the haven directory
@@ -221,9 +222,9 @@ char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath)
{
char* dst = result;
const char* src = unixPath;
if (*src == '/') // ¥ full path
if (*src == '/') // * full path
src++;
else if (strchr(src, '/')) // ¥ partial path, and not just a leaf name
else if (strchr(src, '/')) // * partial path, and not just a leaf name
*dst++ = ':';
strcpy(dst, src);
nsUnescape(dst); // Hex Decode
@@ -346,7 +347,7 @@ void MacFileHelpers::EnsureAliasHaven()
} // MacFileHelpers::EnsureAliasHaven
//----------------------------------------------------------------------------------------
bool MacFileHelpers::IsAliasSafe(const FSSpec& inSpec)
PRBool MacFileHelpers::IsAliasSafe(const FSSpec& inSpec)
// Returns true if the alias is in the alias haven directory, or if alias resolution
// has been turned off.
//----------------------------------------------------------------------------------------
@@ -379,7 +380,7 @@ OSErr MacFileHelpers::FSSpecFromFullUnixPath(
// then it is combined with inOutSpec's vRefNum and parID to form a new spec.
//-----------------------------------
{
if (unixPath == NULL)
if (unixPath == nsnull)
return badFidErr;
char* macPath = MacPathFromUnixPath(unixPath);
if (!macPath)
@@ -413,7 +414,7 @@ char* MacFileHelpers::PathNameFromFSSpec( const FSSpec& inSpec, Boolean wantLeaf
OSErr err = noErr;
short fullPathLength = 0;
Handle fullPath = NULL;
Handle fullPath = nsnull;
FSSpec tempSpec = inSpec;
if ( tempSpec.parID == fsRtParID )
@@ -471,7 +472,7 @@ char* MacFileHelpers::PathNameFromFSSpec( const FSSpec& inSpec, Boolean wantLeaf
tempSpec.name[tempSpec.name[0]] = ':';
/* Add directory name to beginning of fullPath */
(void) Munger(fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]);
(void) Munger(fullPath, 0, nsnull, 0, &tempSpec.name[1], tempSpec.name[0]);
err = MemError();
}
} while ( err == noErr && pb.dirInfo.ioDrDirID != fsRtDirID );
@@ -500,19 +501,19 @@ Clean:
} // MacFileHelpers::PathNameFromFSSpec
//========================================================================================
// Macintosh nsNativeFileSpec implementation
// Macintosh nsFileSpec implementation
//========================================================================================
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec()
nsFileSpec::nsFileSpec()
//----------------------------------------------------------------------------------------
: mError(noErr)
: mError(NS_OK)
{
mSpec.name[0] = '\0';
}
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec)
nsFileSpec::nsFileSpec(const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
: mSpec(inSpec.mSpec)
, mError(inSpec.Error())
@@ -520,87 +521,90 @@ nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec)
}
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs)
nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs)
//----------------------------------------------------------------------------------------
{
mError = MacFileHelpers::FSSpecFromFullUnixPath(
inString, mSpec, true, true, inCreateDirs);
mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromFullUnixPath(
inString, mSpec, false, true, inCreateDirs));
// allow a partial path, create as necessary
if (mError == fnfErr)
mError = noErr;
} // nsNativeFileSpec::nsNativeFileSpec
if (mError == NS_FILE_RESULT(fnfErr))
mError = NS_OK;
} // nsFileSpec::nsFileSpec
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(
nsFileSpec::nsFileSpec(
short vRefNum,
long parID,
ConstStr255Param name)
//----------------------------------------------------------------------------------------
{
mError = ::FSMakeFSSpec(vRefNum, parID, name, &mSpec);
if (mError == fnfErr)
mError = NS_FILE_RESULT(::FSMakeFSSpec(vRefNum, parID, name, &mSpec));
if (mError == NS_FILE_RESULT(fnfErr))
mError = noErr;
}
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath)
nsFileSpec::nsFileSpec(const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
{
*this = inPath.GetNativeSpec();
*this = inPath.GetFileSpec();
}
#if DEBUG
//----------------------------------------------------------------------------------------
nsBasicOutStream& operator << (nsBasicOutStream& s, const nsNativeFileSpec& spec)
nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec)
//----------------------------------------------------------------------------------------
{
s << spec.mSpec.vRefNum << ", " << spec.mSpec.parID << ", \"";
s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]);
return s << "\"";
} // nsOutputFileStream& operator << (nsOutputFileStream&, const nsNativeFileSpec&)
} // nsOutputStream& operator << (nsOutputStream&, const nsFileSpec&)
#endif
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const char* inString)
void nsFileSpec::operator = (const char* inString)
//----------------------------------------------------------------------------------------
{
mError = MacFileHelpers::FSSpecFromFullUnixPath(inString, mSpec, true);
} // nsNativeFileSpec::operator =
mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromFullUnixPath(inString, mSpec, false));
} // nsFileSpec::operator =
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const nsNativeFileSpec& inSpec)
void nsFileSpec::operator = (const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
{
mSpec = inSpec.mSpec;
mError = inSpec.Error();
} // nsNativeFileSpec::operator =
} // nsFileSpec::operator =
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const nsFilePath& inPath)
void nsFileSpec::operator = (const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
{
*this = inPath.GetNativeSpec();
} // nsNativeFileSpec::operator =
*this = inPath.GetFileSpec();
} // nsFileSpec::operator =
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::Exists() const
PRBool nsFileSpec::Exists() const
//----------------------------------------------------------------------------------------
{
FSSpec temp;
return ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &temp) == noErr;
} // nsNativeFileSpec::operator =
} // nsFileSpec::operator =
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::SetLeafName(const char* inLeafName)
void nsFileSpec::SetLeafName(const char* inLeafName)
// In leaf name can actually be a partial path...
//----------------------------------------------------------------------------------------
{
// what about long relative paths? Hmm?
Str255 partialPath;
MacFileHelpers::PLstrcpy(partialPath, inLeafName);
mError = FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec);
} // nsNativeFileSpec::SetLeafName
mError = NS_FILE_RESULT(
::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec));
} // nsFileSpec::SetLeafName
//----------------------------------------------------------------------------------------
char* nsNativeFileSpec::GetLeafName() const
char* nsFileSpec::GetLeafName() const
// Result needs to be delete[]ed.
//----------------------------------------------------------------------------------------
{
@@ -608,133 +612,206 @@ char* nsNativeFileSpec::GetLeafName() const
memcpy(leaf, &mSpec.name[1], mSpec.name[0]);
leaf[mSpec.name[0]] = '\0';
return nsFileSpecHelpers::StringDup(leaf);
} // nsNativeFileSpec::GetLeafName
} // nsFileSpec::GetLeafName
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::MakeAliasSafe()
void nsFileSpec::MakeAliasSafe()
//----------------------------------------------------------------------------------------
{
mError = MacFileHelpers::MakeAliasSafe(mSpec);
} // nsNativeFileSpec::MakeAliasSafe
mError = NS_FILE_RESULT(MacFileHelpers::MakeAliasSafe(mSpec));
} // nsFileSpec::MakeAliasSafe
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName)
void nsFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName)
//----------------------------------------------------------------------------------------
{
if (inSuggestedLeafName[0] > 0)
MacFileHelpers::PLstrcpy(mSpec.name, inSuggestedLeafName);
MakeUnique();
} // nsNativeFileSpec::MakeUnique
} // nsFileSpec::MakeUnique
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::ResolveAlias(bool& wasAliased)
void nsFileSpec::ResolveAlias(PRBool& wasAliased)
//----------------------------------------------------------------------------------------
{
Boolean wasAliased2;
mError = MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2);
mError = NS_FILE_RESULT(MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2));
wasAliased = (wasAliased2 != false);
} // nsNativeFileSpec::ResolveAlias
} // nsFileSpec::ResolveAlias
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsFile() const
PRBool nsFileSpec::IsFile() const
//----------------------------------------------------------------------------------------
{
long dirID;
Boolean isDirectory;
return (noErr == FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && !isDirectory);
} // nsNativeFileSpec::IsFile
} // nsFileSpec::IsFile
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsDirectory() const
PRBool nsFileSpec::IsDirectory() const
//----------------------------------------------------------------------------------------
{
long dirID;
Boolean isDirectory;
return (noErr == FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && isDirectory);
} // nsNativeFileSpec::IsDirectory
} // nsFileSpec::IsDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const
void nsFileSpec::GetParent(nsFileSpec& outSpec) const
//----------------------------------------------------------------------------------------
{
if (mError == noErr)
outSpec.mError = FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, NULL, outSpec);
} // nsNativeFileSpec::GetParent
if (NS_SUCCEEDED(mError))
outSpec.mError
= NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, nsnull, outSpec));
} // nsFileSpec::GetParent
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator += (const char* inRelativePath)
void nsFileSpec::operator += (const char* inRelativePath)
//----------------------------------------------------------------------------------------
{
long dirID;
Boolean isDirectory;
mError = FSpGetDirectoryID(&mSpec, &dirID, &isDirectory);
if (mError == noErr && isDirectory)
mError = NS_FILE_RESULT(::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory));
if (NS_SUCCEEDED(mError) && isDirectory)
{
Str255 partialPath;
MacFileHelpers::PLstrcpy(partialPath, inRelativePath);
mError = FSMakeFSSpec(mSpec.vRefNum, dirID, partialPath, *this);
//if (mError == noErr)
mError = NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, dirID, partialPath, *this));
//if (NS_SUCCEEDED(mError))
// SetLeafName(inRelativePath);
}
} // nsNativeFileSpec::operator +=
} // nsFileSpec::operator +=
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::CreateDirectory(int /* unix mode */)
void nsFileSpec::CreateDirectory(int /* unix mode */)
//----------------------------------------------------------------------------------------
{
long ignoredDirID;
FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID);
} // nsNativeFileSpec::CreateDirectory
} // nsFileSpec::CreateDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::Delete(bool inRecursive)
void nsFileSpec::Delete(PRBool inRecursive)
//----------------------------------------------------------------------------------------
{
if (inRecursive)
{
// MoreFilesExtras
mError = DeleteDirectory(
mError = NS_FILE_RESULT(::DeleteDirectory(
mSpec.vRefNum,
mSpec.parID,
const_cast<unsigned char*>(mSpec.name));
const_cast<unsigned char*>(mSpec.name)));
}
else
mError = FSpDelete(&mSpec);
} // nsNativeFileSpec::Delete
mError = NS_FILE_RESULT(FSpDelete(&mSpec));
} // nsFileSpec::Delete
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Rename(const char* inNewName)
//----------------------------------------------------------------------------------------
{
if (strchr(inNewName, '/'))
return -1; // no relative paths here!
Str255 pName;
MacFileHelpers::PLstrcpy(pName, inNewName);
if (FSpRename(&mSpec, pName) != noErr)
return -1;
SetLeafName(inNewName);
return 0;
} // nsFileSpec::Rename
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Copy(const nsFileSpec& newParentDir) const
//----------------------------------------------------------------------------------------
{
// We can only copy into a directory, and (for now) can not copy entire directories
if (!newParentDir.IsDirectory() || (IsDirectory() ) )
return NS_FILE_FAILURE;
nsresult result = NS_FILE_RESULT(::FSpFileCopy( &mSpec,
&newParentDir.mSpec,
const_cast<StringPtr>(GetLeafPName()),
nsnull,
0,
true));
return result;
} // nsFileSpec::Copy
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Move(const nsFileSpec& newParentDir) const
//----------------------------------------------------------------------------------------
{
// We can only move into a directory
if (!newParentDir.IsDirectory())
return NS_FILE_FAILURE;
nsresult result = NS_FILE_RESULT(::FSpMoveRenameCompat(&mSpec,
&newParentDir.mSpec,
const_cast<StringPtr>(GetLeafPName())));
return result;
} // nsFileSpec::Move
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Execute(const char* /*args - how can this be cross-platform? problem! */ ) const
//----------------------------------------------------------------------------------------
{
if (IsDirectory())
return NS_FILE_FAILURE;
LaunchParamBlockRec launchThis;
launchThis.launchAppSpec = const_cast<FSSpec*>(&mSpec);
launchThis.launchAppParameters = nsnull; // args;
/* launch the thing */
launchThis.launchBlockID = extendedBlock;
launchThis.launchEPBLength = extendedBlockLen;
launchThis.launchFileFlags = nsnull;
launchThis.launchControlFlags = launchContinue + launchNoFileFlags + launchUseMinimum;
launchThis.launchControlFlags += launchDontSwitch;
nsresult result = NS_FILE_RESULT(::LaunchApplication(&launchThis));
return result;
} // nsFileSpec::Execute
//========================================================================================
// Macintosh nsFilePath implementation
//========================================================================================
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const char* inString, bool inCreateDirs)
nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs)
//----------------------------------------------------------------------------------------
: mPath(nsnull)
, mNativeFileSpec(inString, inCreateDirs)
, mFileSpec(inString, inCreateDirs)
{
// Make canonical and absolute.
char * path = MacFileHelpers::PathNameFromFSSpec( mNativeFileSpec, TRUE );
char * path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE );
mPath = MacFileHelpers::EncodeMacPath(path, true, true);
}
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const nsNativeFileSpec& inSpec)
nsFilePath::nsFilePath(const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
: mNativeFileSpec(inSpec)
: mFileSpec(inSpec)
{
char * path = MacFileHelpers::PathNameFromFSSpec( inSpec.mSpec, TRUE );
mPath = MacFileHelpers::EncodeMacPath(path, true, true);
}
//----------------------------------------------------------------------------------------
void nsFilePath::operator = (const nsNativeFileSpec& inSpec)
void nsFilePath::operator = (const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
{
delete [] mPath;
char * path = MacFileHelpers::PathNameFromFSSpec( inSpec.mSpec, TRUE );
mPath = MacFileHelpers::EncodeMacPath(path, true, true);
mNativeFileSpec = inSpec;
mFileSpec = inSpec;
} // nsFilePath::operator =
//========================================================================================
@@ -742,14 +819,14 @@ void nsFilePath::operator = (const nsNativeFileSpec& inSpec)
//========================================================================================
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const char* inString, bool inCreateDirs)
nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs)
//----------------------------------------------------------------------------------------
: mURL(nsnull)
, mNativeFileSpec(inString + kFileURLPrefixLength, inCreateDirs)
, mFileSpec(inString + kFileURLPrefixLength, inCreateDirs)
{
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
// Make canonical and absolute.
char* path = MacFileHelpers::PathNameFromFSSpec( mNativeFileSpec, TRUE );
char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE );
char* escapedPath = MacFileHelpers::EncodeMacPath(path, true, true);
mURL = nsFileSpecHelpers::StringDup(kFileURLPrefix, kFileURLPrefixLength + strlen(escapedPath));
strcat(mURL, escapedPath);
@@ -762,7 +839,7 @@ nsFileURL::nsFileURL(const char* inString, bool inCreateDirs)
//----------------------------------------------------------------------------------------
nsDirectoryIterator::nsDirectoryIterator(
const nsNativeFileSpec& inDirectory
const nsFileSpec& inDirectory
, int inIterateDirection)
//----------------------------------------------------------------------------------------
: mCurrent(inDirectory)
@@ -772,7 +849,7 @@ nsDirectoryIterator::nsDirectoryIterator(
CInfoPBRec pb;
DirInfo* dipb = (DirInfo*)&pb;
// Sorry about this, there seems to be a bug in CWPro 4:
const FSSpec& inSpec = inDirectory.nsNativeFileSpec::operator const FSSpec&();
const FSSpec& inSpec = inDirectory.nsFileSpec::operator const FSSpec&();
Str255 outName;
MacFileHelpers::PLstrcpy(outName, inSpec.name);
pb.hFileInfo.ioNamePtr = outName;
@@ -786,7 +863,7 @@ nsDirectoryIterator::nsDirectoryIterator(
if ( (err != noErr ) || !( dipb->ioFlAttrib & 0x0010 ) )
return;
// Sorry about this, there seems to be a bug in CWPro 4:
FSSpec& currentSpec = mCurrent.nsNativeFileSpec::operator FSSpec&();
FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&();
currentSpec.vRefNum = inSpec.vRefNum;
currentSpec.parID = dipb->ioDrDirID;
mMaxIndex = pb.dirInfo.ioDrNmFls;
@@ -809,10 +886,10 @@ OSErr nsDirectoryIterator::SetToIndex()
CInfoPBRec cipb;
DirInfo *dipb=(DirInfo *)&cipb;
Str255 objectName;
dipb->ioCompletion = NULL;
dipb->ioCompletion = nsnull;
dipb->ioFDirIndex = mIndex;
// Sorry about this, there seems to be a bug in CWPro 4:
FSSpec& currentSpec = mCurrent.nsNativeFileSpec::operator FSSpec&();
FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&();
dipb->ioVRefNum = currentSpec.vRefNum; /* Might need to use vRefNum, not sure*/
dipb->ioDrDirID = currentSpec.parID;
dipb->ioNamePtr = objectName;

View File

@@ -41,6 +41,7 @@ CPPSRCS = \
nsFileSpec.cpp \
nsFileStream.cpp \
nsEscape.cpp \
nsIFileStream.cpp \
$(NULL)
CPP_OBJS = \
@@ -61,6 +62,7 @@ CPP_OBJS = \
.\$(OBJDIR)\nsFileSpec.obj \
.\$(OBJDIR)\nsFileStream.obj \
.\$(OBJDIR)\nsEscape.obj \
.\$(OBJDIR)\nsIFileStream.obj \
$(NULL)
EXPORTS=nscore.h nsIArena.h nsIAtom.h nsIByteBuffer.h \

View File

@@ -22,6 +22,9 @@
#include "nsDebug.h"
#include "prtypes.h"
#include "plstr.h"
#include "plbase64.h"
#include "prmem.h"
#include <string.h>
#include <stdio.h>
@@ -40,7 +43,7 @@ NS_NAMESPACE nsFileSpecHelpers
char inSeparator,
const char* inLeafName);
#ifndef XP_MAC
NS_NAMESPACE_PROTOTYPE void Canonify(char*& ioPath, bool inMakeDirs);
NS_NAMESPACE_PROTOTYPE void Canonify(char*& ioPath, PRBool inMakeDirs);
NS_NAMESPACE_PROTOTYPE void MakeAllDirectories(const char* inPath, int mode);
#endif
NS_NAMESPACE_PROTOTYPE char* GetLeaf(const char* inPath, char inSeparator); // allocated
@@ -54,6 +57,14 @@ NS_NAMESPACE nsFileSpecHelpers
#endif
} NS_NAMESPACE_END
//----------------------------------------------------------------------------------------
nsresult ns_file_convert_result(PRInt32 nativeErr)
//----------------------------------------------------------------------------------------
{
return nativeErr ?
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES,((nativeErr)&0xFFFF))
: NS_OK;
}
//----------------------------------------------------------------------------------------
char* nsFileSpecHelpers::StringDup(
@@ -65,7 +76,7 @@ char* nsFileSpecHelpers::StringDup(
allocLength = strlen(inString);
char* newPath = inString || allocLength ? new char[allocLength + 1] : nsnull;
if (!newPath)
return NULL;
return nsnull;
strcpy(newPath, inString);
return newPath;
} // nsFileSpecHelpers::StringDup
@@ -77,7 +88,7 @@ char* nsFileSpecHelpers::AllocCat(
//----------------------------------------------------------------------------------------
{
if (!inString1)
return inString2 ? StringDup(inString2) : (char*)NULL;
return inString2 ? StringDup(inString2) : (char*)nsnull;
if (!inString2)
return StringDup(inString1);
char* outString = StringDup(inString1, strlen(inString1) + strlen(inString2));
@@ -95,7 +106,7 @@ char* nsFileSpecHelpers::StringAssign(
if (!inString2)
{
delete [] ioString;
ioString = (char*)NULL;
ioString = (char*)nsnull;
return ioString;
}
if (!ioString || (strlen(inString2) > strlen(ioString)))
@@ -125,8 +136,19 @@ void nsFileSpecHelpers::LeafReplace(
}
char* lastSeparator = strrchr(ioPath, inSeparator);
int oldLength = strlen(ioPath);
*(++lastSeparator) = '\0'; // strip the current leaf name
int newLength = lastSeparator - ioPath + strlen(inLeafName);
PRBool trailingSeparator = (lastSeparator + 1 == ioPath + oldLength);
if (trailingSeparator)
{
*lastSeparator = '\0';
lastSeparator = strrchr(ioPath, inSeparator);
}
if (lastSeparator)
lastSeparator++; // point at the trailing string
else
lastSeparator = ioPath; // the full monty
*lastSeparator = '\0'; // strip the current leaf name
int newLength = (lastSeparator - ioPath) + strlen(inLeafName) + int(trailingSeparator);
if (newLength > oldLength)
{
char* newPath = StringDup(ioPath, newLength + 1);
@@ -134,7 +156,14 @@ void nsFileSpecHelpers::LeafReplace(
ioPath = newPath;
}
strcat(ioPath, inLeafName);
} // nsNativeFileSpec::LeafReplace
if (trailingSeparator)
{
// If the original ended in a slash, then the new one should, too.
char sepStr[2] = "/";
*sepStr = inSeparator;
strcat(ioPath, sepStr);
}
} // nsFileSpecHelpers::LeafReplace
//----------------------------------------------------------------------------------------
char* nsFileSpecHelpers::GetLeaf(const char* inPath, char inSeparator)
@@ -142,12 +171,32 @@ char* nsFileSpecHelpers::GetLeaf(const char* inPath, char inSeparator)
//----------------------------------------------------------------------------------------
{
if (!inPath)
return NULL;
char* lastSeparator = strrchr(inPath, inSeparator);
if (lastSeparator)
return StringDup(++lastSeparator);
return StringDup(inPath);
} // nsNativeFileSpec::GetLeaf
return nsnull;
const char* lastSeparator = strrchr(inPath, inSeparator);
// If there was no separator, then return a copy of the caller's path.
if (!lastSeparator)
return StringDup(inPath);
// So there's at least one separator. What's just after it?
// If the separator was not the last character, return the trailing string.
const char* leafPointer = lastSeparator + 1;
if (*leafPointer)
return StringDup(leafPointer);
// So now, separator was the last character. Poke in a null instead.
*(char*)lastSeparator = '\0'; // Should use const_cast, but Unix has old compiler.
leafPointer = strrchr(inPath, inSeparator);
char* result = leafPointer ? StringDup(leafPointer++) : StringDup(inPath);
// Restore the poked null before returning.
*(char*)lastSeparator = inSeparator;
#ifdef XP_PC
// If it's a drive letter use the colon notation.
if (!leafPointer && strlen(result) == 2 && result[1] == '|')
result[1] = ':';
#endif
return result;
} // nsFileSpecHelpers::GetLeaf
#if defined(XP_UNIX) || defined(XP_PC)
@@ -177,7 +226,7 @@ void nsFileSpecHelpers::MakeAllDirectories(const char* inPath, int mode)
if (currentEnd)
{
*currentEnd = '\0';
nsNativeFileSpec spec(nsFilePath(pathCopy, false));
nsFileSpec spec(nsFilePath(pathCopy, PR_FALSE));
do
{
// If the node doesn't exist, and it is not the initial node in a full path,
@@ -209,7 +258,7 @@ char* nsFileSpecHelpers::ReallocCat(char*& ioString, const char* inString1)
delete [] ioString;
ioString = newString;
return ioString;
} // nsNativeFileSpec::ReallocCat
} // nsFileSpecHelpers::ReallocCat
#if defined(XP_PC)
#include "windows/nsFileSpecWin.cpp" // Windows-specific implementations
@@ -225,7 +274,7 @@ char* nsFileSpecHelpers::ReallocCat(char*& ioString, const char* inString1)
#ifndef XP_MAC
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const char* inString, bool inCreateDirs)
nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs)
//----------------------------------------------------------------------------------------
: mURL(nsnull)
{
@@ -243,7 +292,7 @@ nsFileURL::nsFileURL(const nsFileURL& inOther)
//----------------------------------------------------------------------------------------
: mURL(nsFileSpecHelpers::StringDup(inOther.mURL))
#ifdef XP_MAC
, mNativeFileSpec(inOther.GetNativeSpec())
, mFileSpec(inOther.GetFileSpec())
#endif
{
} // nsFileURL::nsFileURL
@@ -253,16 +302,16 @@ nsFileURL::nsFileURL(const nsFilePath& inOther)
//----------------------------------------------------------------------------------------
: mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther))
#ifdef XP_MAC
, mNativeFileSpec(inOther.GetNativeSpec())
, mFileSpec(inOther.GetFileSpec())
#endif
{
} // nsFileURL::nsFileURL
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const nsNativeFileSpec& inOther)
nsFileURL::nsFileURL(const nsFileSpec& inOther)
: mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther)))
#ifdef XP_MAC
, mNativeFileSpec(inOther)
, mFileSpec(inOther)
#endif
//----------------------------------------------------------------------------------------
{
@@ -282,7 +331,7 @@ void nsFileURL::operator = (const char* inString)
nsFileSpecHelpers::StringAssign(mURL, inString);
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
#ifdef XP_MAC
mNativeFileSpec = inString + kFileURLPrefixLength;
mFileSpec = inString + kFileURLPrefixLength;
#endif
} // nsFileURL::operator =
@@ -292,7 +341,7 @@ void nsFileURL::operator = (const nsFileURL& inOther)
{
mURL = nsFileSpecHelpers::StringAssign(mURL, inOther.mURL);
#ifdef XP_MAC
mNativeFileSpec = inOther.GetNativeSpec();
mFileSpec = inOther.GetFileSpec();
#endif
} // nsFileURL::operator =
@@ -303,27 +352,29 @@ void nsFileURL::operator = (const nsFilePath& inOther)
delete [] mURL;
mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther);
#ifdef XP_MAC
mNativeFileSpec = inOther.GetNativeSpec();
mFileSpec = inOther.GetFileSpec();
#endif
} // nsFileURL::operator =
//----------------------------------------------------------------------------------------
void nsFileURL::operator = (const nsNativeFileSpec& inOther)
void nsFileURL::operator = (const nsFileSpec& inOther)
//----------------------------------------------------------------------------------------
{
delete [] mURL;
mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther));
#ifdef XP_MAC
mNativeFileSpec = inOther;
mFileSpec = inOther;
#endif
} // nsFileURL::operator =
#if DEBUG
//----------------------------------------------------------------------------------------
nsBasicOutStream& operator << (nsBasicOutStream& s, const nsFileURL& url)
nsOutputStream& operator << (nsOutputStream& s, const nsFileURL& url)
//----------------------------------------------------------------------------------------
{
return (s << url.mURL);
}
#endif
//========================================================================================
// nsFilePath implementation
@@ -332,14 +383,14 @@ nsBasicOutStream& operator << (nsBasicOutStream& s, const nsFileURL& url)
nsFilePath::nsFilePath(const nsFilePath& inPath)
: mPath(nsFileSpecHelpers::StringDup(inPath.mPath))
#ifdef XP_MAC
, mNativeFileSpec(inPath.mNativeFileSpec)
, mFileSpec(inPath.mFileSpec)
#endif
{
}
#ifndef XP_MAC
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const char* inString, bool inCreateDirs)
nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inString))
{
@@ -362,14 +413,14 @@ nsFilePath::nsFilePath(const nsFileURL& inOther)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inOther.mURL + kFileURLPrefixLength))
#ifdef XP_MAC
, mNativeFileSpec(inOther.GetNativeSpec())
, mFileSpec(inOther.GetFileSpec())
#endif
{
}
#ifdef XP_UNIX
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const nsNativeFileSpec& inOther)
nsFilePath::nsFilePath(const nsFileSpec& inOther)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inOther.mPath))
{
@@ -385,7 +436,7 @@ nsFilePath::~nsFilePath()
#ifdef XP_UNIX
//----------------------------------------------------------------------------------------
void nsFilePath::operator = (const nsNativeFileSpec& inOther)
void nsFilePath::operator = (const nsFileSpec& inOther)
//----------------------------------------------------------------------------------------
{
mPath = nsFileSpecHelpers::StringAssign(mPath, inOther.mPath);
@@ -398,14 +449,14 @@ void nsFilePath::operator = (const char* inString)
{
NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
#ifdef XP_MAC
mNativeFileSpec = inString;
nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(mNativeFileSpec));
mFileSpec = inString;
nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(mFileSpec));
#else
#ifdef XP_PC
nsFileSpecHelpers::UnixToNative(mPath);
#endif
// Make canonical and absolute.
nsFileSpecHelpers::Canonify(mPath, false /* XXX? */);
nsFileSpecHelpers::Canonify(mPath, PR_FALSE /* XXX? */);
#ifdef XP_PC
nsFileSpecHelpers::NativeToUnix(mPath);
#endif
@@ -418,7 +469,7 @@ void nsFilePath::operator = (const nsFileURL& inOther)
{
nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(inOther));
#ifdef XP_MAC
mNativeFileSpec = inOther.GetNativeSpec();
mFileSpec = inOther.GetFileSpec();
#endif
}
@@ -433,40 +484,51 @@ void nsFilePath::operator = (const nsFilePath& inOther)
}
//========================================================================================
// nsNativeFileSpec implementation
// nsFileSpec implementation
//========================================================================================
#ifndef XP_MAC
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec()
nsFileSpec::nsFileSpec()
//----------------------------------------------------------------------------------------
: mPath(NULL)
: mPath(nsnull)
, mError(NS_OK)
{
}
#endif
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const nsFileURL& inURL)
nsFileSpec::nsFileSpec(const nsPersistentFileDescriptor& inDescriptor)
//----------------------------------------------------------------------------------------
#ifndef XP_MAC
: mPath(NULL)
: mPath(nsnull)
#endif
{
*this = inDescriptor;
}
//----------------------------------------------------------------------------------------
nsFileSpec::nsFileSpec(const nsFileURL& inURL)
//----------------------------------------------------------------------------------------
#ifndef XP_MAC
: mPath(nsnull)
#endif
{
*this = nsFilePath(inURL); // convert to unix path first
}
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::MakeUnique(const char* inSuggestedLeafName)
void nsFileSpec::MakeUnique(const char* inSuggestedLeafName)
//----------------------------------------------------------------------------------------
{
if (inSuggestedLeafName && *inSuggestedLeafName)
SetLeafName(inSuggestedLeafName);
MakeUnique();
} // nsNativeFileSpec::MakeUnique
} // nsFileSpec::MakeUnique
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::MakeUnique()
void nsFileSpec::MakeUnique()
//----------------------------------------------------------------------------------------
{
if (!Exists())
@@ -497,51 +559,82 @@ void nsNativeFileSpec::MakeUnique()
if (*suffix)
delete [] suffix;
delete [] leafName;
} // nsNativeFileSpec::MakeUnique
} // nsFileSpec::MakeUnique
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const nsFileURL& inURL)
void nsFileSpec::operator = (const nsFileURL& inURL)
//----------------------------------------------------------------------------------------
{
*this = nsFilePath(inURL); // convert to unix path first
}
//----------------------------------------------------------------------------------------
void nsFileSpec::operator = (const nsPersistentFileDescriptor& inDescriptor)
//----------------------------------------------------------------------------------------
{
void* data;
PRInt32 dataSize;
inDescriptor.GetData(data, dataSize);
#ifdef XP_MAC
char* decodedData = PL_Base64Decode((const char*)data, (int)dataSize, nsnull);
// Cast to an alias record and resolve.
AliasHandle aliasH = nsnull;
mError = NS_FILE_RESULT(PtrToHand(decodedData, &(Handle)aliasH, (dataSize * 3) / 4));
PR_Free(decodedData);
if (NS_SUCCEEDED(mError))
return; // not enough memory?
Boolean changed;
mError = NS_FILE_RESULT(::ResolveAlias(nsnull, aliasH, &mSpec, &changed));
DisposeHandle((Handle) aliasH);
#else
nsFileSpecHelpers::StringAssign(mPath, (char*)data);
mError = NS_OK;
#endif
}
//========================================================================================
// UNIX & WIN nsNativeFileSpec implementation
// UNIX & WIN nsFileSpec implementation
//========================================================================================
#ifdef XP_UNIX
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath)
nsFileSpec::nsFileSpec(const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup((const char*)inPath))
, mError(NS_OK)
{
}
#endif // XP_UNIX
#ifdef XP_UNIX
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const nsFilePath& inPath)
void nsFileSpec::operator = (const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(mPath, (const char*)inPath);
mError = NS_OK;
}
#endif //XP_UNIX
#if defined(XP_UNIX) || defined(XP_PC)
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec)
nsFileSpec::nsFileSpec(const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inSpec.mPath))
, mError(NS_OK)
{
}
#endif //XP_UNIX
#if defined(XP_UNIX) || defined(XP_PC)
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs)
nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inString))
, mError(NS_OK)
{
// Make canonical and absolute.
nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
@@ -549,7 +642,7 @@ nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs)
#endif //XP_UNIX,PC
//----------------------------------------------------------------------------------------
nsNativeFileSpec::~nsNativeFileSpec()
nsFileSpec::~nsFileSpec()
//----------------------------------------------------------------------------------------
{
#ifndef XP_MAC
@@ -559,39 +652,160 @@ nsNativeFileSpec::~nsNativeFileSpec()
#if defined(XP_UNIX) || defined(XP_PC)
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const nsNativeFileSpec& inSpec)
void nsFileSpec::operator = (const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
{
mPath = nsFileSpecHelpers::StringAssign(mPath, inSpec.mPath);
mError = inSpec.Error();
}
#endif //XP_UNIX
#if defined(XP_UNIX) || defined(XP_PC)
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const char* inString)
void nsFileSpec::operator = (const char* inString)
//----------------------------------------------------------------------------------------
{
mPath = nsFileSpecHelpers::StringAssign(mPath, inString);
// Make canonical and absolute.
nsFileSpecHelpers::Canonify(mPath, true /* XXX? */);
nsFileSpecHelpers::Canonify(mPath, PR_TRUE /* XXX? */);
mError = NS_OK;
}
#endif //XP_UNIX
#if DEBUG
#if (defined(XP_UNIX) || defined(XP_PC))
//----------------------------------------------------------------------------------------
nsBasicOutStream& operator << (nsBasicOutStream& s, const nsNativeFileSpec& spec)
nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec)
//----------------------------------------------------------------------------------------
{
return (s << (const char*)spec.mPath);
}
#endif // DEBUG && XP_UNIX
#endif
//----------------------------------------------------------------------------------------
nsNativeFileSpec nsNativeFileSpec::operator + (const char* inRelativePath) const
nsFileSpec nsFileSpec::operator + (const char* inRelativePath) const
//----------------------------------------------------------------------------------------
{
nsNativeFileSpec result = *this;
nsFileSpec result = *this;
result += inRelativePath;
return result;
} // nsNativeFileSpec::operator +
} // nsFileSpec::operator +
//========================================================================================
// class nsPersistentFileDescriptor
//========================================================================================
//----------------------------------------------------------------------------------------
nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inDesc)
//----------------------------------------------------------------------------------------
: mDescriptorString(nsFileSpecHelpers::StringDup(inDesc.mDescriptorString))
{
} // nsPersistentFileDescriptor::nsPersistentFileDescriptor
//----------------------------------------------------------------------------------------
void nsPersistentFileDescriptor::operator = (const nsPersistentFileDescriptor& inDesc)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(mDescriptorString, inDesc.mDescriptorString);
} // nsPersistentFileDescriptor::operator =
//----------------------------------------------------------------------------------------
nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
: mDescriptorString(nsnull)
{
*this = inSpec;
} // nsPersistentFileDescriptor::nsPersistentFileDescriptor
//----------------------------------------------------------------------------------------
void nsPersistentFileDescriptor::operator = (const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
{
#ifdef XP_MAC
if (inSpec.Error())
return;
AliasHandle aliasH;
OSErr err = NewAlias(nil, inSpec.operator const FSSpec* const (), &aliasH);
if (err != noErr)
return;
PRUint32 bytes = GetHandleSize((Handle) aliasH);
HLock((Handle) aliasH);
char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull);
DisposeHandle((Handle) aliasH);
nsFileSpecHelpers::StringAssign(mDescriptorString, buf);
PR_Free(buf);
#else
nsFileSpecHelpers::StringAssign(mDescriptorString, inSpec);
#endif // XP_MAC
} // nsPersistentFileDescriptor::operator =
//----------------------------------------------------------------------------------------
nsPersistentFileDescriptor::~nsPersistentFileDescriptor()
//----------------------------------------------------------------------------------------
{
delete [] mDescriptorString;
} // nsPersistentFileDescriptor::~nsPersistentFileDescriptor
//----------------------------------------------------------------------------------------
void nsPersistentFileDescriptor::GetData(void*& outData, PRInt32& outSize) const
//----------------------------------------------------------------------------------------
{
outSize = PL_strlen(mDescriptorString);
outData = mDescriptorString;
}
//----------------------------------------------------------------------------------------
void nsPersistentFileDescriptor::SetData(const void* inData, PRInt32 inSize)
//----------------------------------------------------------------------------------------
{
delete [] mDescriptorString;
mDescriptorString = new char[1 + inSize];
if (!mDescriptorString)
return;
memcpy(mDescriptorString, inData, inSize);
mDescriptorString[inSize] = '\0';
}
#define MAX_PERSISTENT_DATA_SIZE 1000
//----------------------------------------------------------------------------------------
nsInputStream& operator >> (nsInputStream& s, nsPersistentFileDescriptor& d)
// reads the data from a file
//----------------------------------------------------------------------------------------
{
char bigBuffer[MAX_PERSISTENT_DATA_SIZE + 1];
// The first 8 bytes of the data should be a hex version of the data size to follow.
PRInt32 bytesRead = 8;
bytesRead = s.read(bigBuffer, bytesRead);
if (bytesRead != 8)
return (nsInputFileStream&)s;
bigBuffer[8] = '\0';
sscanf(bigBuffer, "%lx", &bytesRead);
if (bytesRead > MAX_PERSISTENT_DATA_SIZE)
return (nsInputFileStream&)s; // preposterous.
// Now we know how many bytes to read, do it.
s.read(bigBuffer, bytesRead);
d.SetData(bigBuffer, bytesRead);
return (nsInputFileStream&)s;
}
//----------------------------------------------------------------------------------------
nsOutputStream& operator << (nsOutputStream& s, const nsPersistentFileDescriptor& d)
// writes the data to a file
//----------------------------------------------------------------------------------------
{
char littleBuf[9];
PRInt32 dataSize;
void* data;
d.GetData(data, dataSize);
// First write (in hex) the length of the data to follow. Exactly 8 bytes
sprintf(littleBuf, "%0.8x", dataSize);
s << littleBuf;
// Now write the data itself
s << d.mDescriptorString;
return s;
}

View File

@@ -22,332 +22,78 @@
#include "nsFileStream.h"
#include <string.h>
#include <stdio.h>
#ifdef XP_MAC
#include <Errors.h>
#endif
//========================================================================================
// nsBasicFileStream
// nsInputStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsBasicFileStream::nsBasicFileStream()
nsInputStream::~nsInputStream()
//----------------------------------------------------------------------------------------
: mFileDesc(0)
, mNSPRMode(0)
, mFailed(false)
, mEOF(false)
{
mInputStream->Close();
}
//----------------------------------------------------------------------------------------
nsBasicFileStream::nsBasicFileStream(
const nsFilePath& inFile,
int nsprMode,
PRIntn accessMode)
char nsInputStream::get()
//----------------------------------------------------------------------------------------
: mFileDesc(0)
, mNSPRMode(0)
, mFailed(false)
, mEOF(false)
{
open(inFile, nsprMode, accessMode);
char c;
read(&c, sizeof(c));
return c;
}
//----------------------------------------------------------------------------------------
nsBasicFileStream::nsBasicFileStream(PRFileDesc* desc, int nsprMode)
static void TidyEndOfLine(char*& cp)
// Assumes that cp is pointing at \n or \r. Nulls out the character, checks for
// a second terminator (of the opposite persuasion), and returns cp pointing past the
// entire eol construct (one or two characters).
//----------------------------------------------------------------------------------------
: mFileDesc(desc)
, mNSPRMode(nsprMode)
, mFailed(false)
, mEOF(false)
{
char ch = *cp;
*cp++ = '\0'; // terminate at the newline, then skip past it
if ((ch == '\n' && *cp == '\r') || (ch == '\r' && *cp == '\n'))
cp++; // possibly a pair.
}
//----------------------------------------------------------------------------------------
nsBasicFileStream::~nsBasicFileStream()
nsInputStream& nsInputStream::operator >> (char& c)
//----------------------------------------------------------------------------------------
{
close();
}
//----------------------------------------------------------------------------------------
void nsBasicFileStream::open(
const nsFilePath& inFile,
int nsprMode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
{
if (mFileDesc)
return;
const int nspr_modes[]={
PR_WRONLY | PR_CREATE_FILE,
PR_WRONLY | PR_CREATE_FILE | PR_APPEND,
PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
PR_RDONLY,
PR_RDONLY | PR_APPEND,
PR_RDWR | PR_CREATE_FILE,
PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE,
// "wb",
// "ab",
// "wb",
// "rb",
// "r+b",
// "w+b",
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).
mFileDesc = 0;
if (inFile.GetNativeSpec().Error() != noErr)
return;
OSErr err = noErr;
#if DEBUG
const OSType kCreator = 'CWIE';
#else
const OSType kCreator = 'MOSS';
#endif
nsNativeFileSpec nativeSpec = inFile.GetNativeSpec();
FSSpec* spec = (FSSpec*)nativeSpec;
if (nsprMode & PR_CREATE_FILE)
err = FSpCreate(spec, kCreator, 'TEXT', 0);
if (err == dupFNErr)
err = noErr;
if (err != noErr)
return;
SInt8 perm;
if (nsprMode & PR_RDWR)
perm = fsRdWrPerm;
else if (nsprMode & PR_WRONLY)
perm = fsWrPerm;
else
perm = fsRdPerm;
short refnum;
err = FSpOpenDF(spec, perm, &refnum);
if (err == noErr && (nsprMode & PR_TRUNCATE))
err = SetEOF(refnum, 0);
if (err == noErr && (nsprMode & PR_APPEND))
err = SetFPos(refnum, fsFromLEOF, 0);
if (err != noErr)
return;
if ((mFileDesc = PR_ImportFile(refnum)) == 0)
return;
#else
// Platforms other than Macintosh...
// Another bug in NSPR: Mac PR_Open assumes a unix style path, but Win PR_Open assumes
// a windows path.
if ((mFileDesc = PR_Open((const char*)nsNativeFileSpec(inFile), nsprMode, accessMode)) == 0)
return;
#endif
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
//========================================================================================
// nsBasicInStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsBasicInStream::nsBasicInStream(nsBasicFileStream& inBasicStream, istream* inStream)
//----------------------------------------------------------------------------------------
: mBase(inBasicStream)
, mStdStream(inStream)
{
}
//----------------------------------------------------------------------------------------
void nsBasicInStream::get(char& c)
//----------------------------------------------------------------------------------------
{
read(&c, sizeof(char));
}
//----------------------------------------------------------------------------------------
PRBool nsBasicInStream::readline(char* s, PRInt32 n)
// This will truncate if the buffer is too small. Result will always be null-terminated.
//----------------------------------------------------------------------------------------
{
PRBool bufferLargeEnough = true; // result
if (!s || !n)
return true;
PRIntn position = mBase.tell();
if (position < 0)
return false;
PRInt32 bytesRead = read(s, n - 1);
if (mBase.failed())
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 (!mBase.eof())
bufferLargeEnough = false;
position += bytesRead;
mBase.seek(position);
return bufferLargeEnough;
} // nsBasicInStream::getline
//----------------------------------------------------------------------------------------
PRInt32 nsBasicInStream::read(void* s, PRInt32 n)
//----------------------------------------------------------------------------------------
{
#ifndef NS_USE_PR_STDIO
// Calling PR_Read on stdin is sure suicide on Macintosh.
if (GetStandardStream())
{
GetStandardStream()->read((char*)s, n);
return n;
}
#endif
if (!mBase.is_open() || mBase.failed())
return -1;
PRInt32 bytesRead = PR_Read(mBase.GetFileDescriptor(), s, n);
if (bytesRead < 0)
mBase.mFailed = true;
else if (bytesRead < n)
mBase.mEOF = true;
return bytesRead;
}
//----------------------------------------------------------------------------------------
nsBasicInStream& nsBasicInStream::operator >> (char& c)
//----------------------------------------------------------------------------------------
{
get(c);
c = get();
return *this;
}
//========================================================================================
// nsInputFileStream
// nsOutputStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsInputFileStream::nsInputFileStream(istream* stream)
nsOutputStream::~nsOutputStream()
//----------------------------------------------------------------------------------------
#ifndef NS_USE_PR_STDIO
: nsBasicFileStream(0, kDefaultMode)
, nsBasicInStream(*this, stream)
#else
: nsBasicFileStream(PR_STDIN, kDefaultMode)
, nsBasicInStream(*this, 0)
#endif
{
}
//========================================================================================
// nsBasicOutStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsBasicOutStream::nsBasicOutStream(nsBasicFileStream& inBase, ostream* stream)
//----------------------------------------------------------------------------------------
: mBase(inBase)
, mStdStream(stream)
{
mOutputStream->Close();
}
//----------------------------------------------------------------------------------------
void nsBasicOutStream::put(char c)
void nsOutputStream::put(char c)
//----------------------------------------------------------------------------------------
{
write(&c, sizeof(c));
}
//----------------------------------------------------------------------------------------
PRInt32 nsBasicOutStream::write(const void* s, PRInt32 n)
void nsOutputStream::flush()
//----------------------------------------------------------------------------------------
{
#ifndef NS_USE_PR_STDIO
// Calling PR_Write on stdout is sure suicide.
if (mStdStream)
{
mStdStream->write((const char*)s, n);
return n;
}
#endif
if (!mBase.mFileDesc || mBase.failed())
return -1;
PRInt32 bytesWrit = PR_Write(mBase.mFileDesc, s, n);
if (bytesWrit != n)
mBase.mFailed = true;
return bytesWrit;
}
//----------------------------------------------------------------------------------------
nsBasicOutStream& nsBasicOutStream::operator << (char c)
nsOutputStream& nsOutputStream::operator << (char c)
//----------------------------------------------------------------------------------------
{
put(c);
@@ -355,7 +101,7 @@ nsBasicOutStream& nsBasicOutStream::operator << (char c)
}
//----------------------------------------------------------------------------------------
nsBasicOutStream& nsBasicOutStream::operator << (const char* s)
nsOutputStream& nsOutputStream::operator << (const char* s)
//----------------------------------------------------------------------------------------
{
write(s, strlen(s));
@@ -363,78 +109,84 @@ nsBasicOutStream& nsBasicOutStream::operator << (const char* s)
}
//----------------------------------------------------------------------------------------
nsBasicOutStream& nsBasicOutStream::operator << (short val)
nsOutputStream& nsOutputStream::operator << (short val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%d", val);
return *this << buf;
return (*this << buf);
}
//----------------------------------------------------------------------------------------
nsBasicOutStream& nsBasicOutStream::operator << (unsigned short val)
nsOutputStream& nsOutputStream::operator << (unsigned short val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%ud", val);
return *this << buf;
return (*this << buf);
}
//----------------------------------------------------------------------------------------
nsBasicOutStream& nsBasicOutStream::operator << (long val)
nsOutputStream& nsOutputStream::operator << (long val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%ld", val);
return *this << buf;
return (*this << buf);
}
//----------------------------------------------------------------------------------------
nsBasicOutStream& nsBasicOutStream::operator << (unsigned long val)
nsOutputStream& nsOutputStream::operator << (unsigned long val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%uld", val);
return *this << buf;
return (*this << buf);
}
//========================================================================================
// nsInputFileStream
//========================================================================================
//----------------------------------------------------------------------------------------
void nsBasicOutStream::flush()
// Must precede the destructor because both are inline.
PRBool nsInputFileStream::readline(char* s, PRInt32 n)
// This will truncate if the buffer is too small. Result will always be null-terminated.
//----------------------------------------------------------------------------------------
{
#ifndef NS_USE_PR_STDIO
if (mStdStream)
PRBool bufferLargeEnough = PR_TRUE; // result
if (!s || !n)
return PR_TRUE;
PRIntn position = tell();
if (position < 0)
return PR_FALSE;
PRInt32 bytesRead = read(s, n - 1);
if (failed())
return PR_FALSE;
s[bytesRead] = '\0'; // always terminate at the end of the buffer
char* tp = strpbrk(s, "\n\r");
if (tp)
{
mStdStream->flush();
return;
TidyEndOfLine(tp);
bytesRead = (tp - s);
}
#endif
if (mBase.mFileDesc == 0)
return;
PRBool itFailed = PR_Sync(mBase.mFileDesc) != PR_SUCCESS;
#ifdef XP_MAC
// On unix, it seems to fail always.
if (itFailed)
mBase.mFailed = true;
#endif
} // nsBasicOutStream::flush
else if (!eof())
bufferLargeEnough = PR_FALSE;
position += bytesRead;
seek(position);
return bufferLargeEnough;
} // nsInputStream::readline
//========================================================================================
// nsOutputFileStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsOutputFileStream::nsOutputFileStream(ostream* stream)
void nsOutputFileStream::flush()
//----------------------------------------------------------------------------------------
#ifndef NS_USE_PR_STDIO
: nsBasicFileStream(0, kDefaultMode)
, nsBasicOutStream(*this, stream)
#else
: nsBasicFileStream(PR_STDOUT, kDefaultMode)
, nsBasicOutStream(*this, 0)
#endif
{
if (mFileOutputStream)
mFileOutputStream->Flush();
}
//========================================================================================
@@ -442,19 +194,10 @@ nsOutputFileStream::nsOutputFileStream(ostream* stream)
//========================================================================================
//----------------------------------------------------------------------------------------
nsBasicOutStream& nsEndl(nsBasicOutStream& os)
nsOutputStream& nsEndl(nsOutputStream& os)
//----------------------------------------------------------------------------------------
{
#ifndef NS_USE_PR_STDIO
// Calling PR_Write on stdout is sure suicide on Macintosh.
ostream* stream = os.GetStandardStream();
if (stream)
{
*stream << std::endl;
return os;
}
#endif
os.put('\n');
os.flush();
return os;
}
os.put('\n');
os.flush();
return os;
} // nsEndl

View File

@@ -31,6 +31,8 @@
class nsIBaseStream : public nsISupports {
public:
static const nsIID& IID() { static nsIID iid = NS_IBASESTREAM_IID; return iid; }
/** Close the stream. */
NS_IMETHOD
Close(void) = 0;

View File

@@ -0,0 +1,451 @@
#include "nsIFileStream.h"
#include "nsFileSpec.h"
#include "prerror.h"
#ifdef XP_MAC
#include "pprio.h" // To get PR_ImportFile
#else
#include "prio.h"
#endif
#ifdef XP_MAC
#include <Errors.h>
#include <iostream>
#endif
//========================================================================================
class FileImpl
: public nsIOutputStream
, public nsIInputStream
, public nsIFileOutputStream
, public nsIFileInputStream
, public nsIFile
//========================================================================================
{
public:
FileImpl(PRFileDesc* inDesc)
: mFileDesc(inDesc)
, mFailed(PR_FALSE)
, mEOF(PR_FALSE)
, mLength(-1)
{
NS_INIT_REFCNT();
}
FileImpl(
const nsFileSpec& inFile,
int nsprMode,
PRIntn accessMode)
: mFileDesc(nsnull)
, mFailed(PR_FALSE)
, mEOF(PR_FALSE)
{
NS_INIT_REFCNT();
Open(inFile, nsprMode, accessMode);
}
virtual ~FileImpl()
{
Close();
}
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIFile interface
NS_IMETHOD Open(
const nsFileSpec& inFile,
int nsprMode,
PRIntn accessMode);
NS_IMETHOD Close();
NS_IMETHOD Seek(PRSeekWhence whence, PRInt32 offset);
NS_IMETHOD GetIsOpen(PRBool* outOpen)
{
*outOpen = (mFileDesc != nsnull);
return NS_OK;
}
NS_IMETHOD Tell(PRIntn* outWhere);
// nsIInputStream interface
NS_IMETHOD GetLength(PRUint32 *aLength)
{
NS_PRECONDITION(aLength != nsnull, "null ptr");
if (!aLength)
return NS_ERROR_NULL_POINTER;
if (mLength < 0)
return NS_FILE_RESULT(NS_ERROR_UNEXPECTED);
*aLength = mLength;
return NS_OK;
}
NS_IMETHOD Read(char* aBuf,
PRUint32 aOffset,
PRUint32 aCount,
PRUint32 *aReadCount)
{
NS_PRECONDITION(aBuf != nsnull, "null ptr");
if (!aBuf)
return NS_ERROR_NULL_POINTER;
NS_PRECONDITION(aReadCount != nsnull, "null ptr");
if (!aReadCount)
return NS_ERROR_NULL_POINTER;
if (!mFileDesc)
return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
if (mFailed)
return NS_ERROR_FAILURE;
if (aOffset)
PR_Seek(mFileDesc, aOffset, PR_SEEK_CUR);
PRInt32 bytesRead = PR_Read(mFileDesc, aBuf, aCount);
if (bytesRead < 0)
{
*aReadCount = 0;
mFailed = PR_TRUE;
return NS_FILE_RESULT(PR_GetError());
}
*aReadCount = bytesRead;
return NS_OK;
}
// nsIOutputStream interface
NS_IMETHOD Write(const char* aBuf,
PRUint32 aOffset,
PRUint32 aCount,
PRUint32 *aWriteCount)
{
NS_PRECONDITION(aBuf != nsnull, "null ptr");
NS_PRECONDITION(aWriteCount != nsnull, "null ptr");
#ifdef XP_MAC
// Calling PR_Write on stdout is sure suicide.
if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR)
{
cout.write(aBuf, aCount);
*aWriteCount = aCount;
return NS_OK;
}
#endif
if (!mFileDesc)
return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
if (mFailed)
return NS_ERROR_FAILURE;
if (aOffset)
PR_Seek(mFileDesc, aOffset, PR_SEEK_CUR);
PRInt32 bytesWrit = PR_Write(mFileDesc, aBuf, aCount);
if (bytesWrit != aCount)
{
mFailed = PR_TRUE;
*aWriteCount = 0;
return NS_FILE_RESULT(PR_GetError());
}
*aWriteCount = bytesWrit;
return NS_OK;
}
NS_IMETHOD Flush();
protected:
PRFileDesc* mFileDesc;
int mNSPRMode;
PRBool mFailed;
PRBool mEOF;
PRInt32 mLength;
}; // class FileImpl
#define SAY_I_IMPLEMENT(classname) \
if (aIID.Equals(classname::IID())) \
{ \
*aInstancePtr = (void*)((classname*)this); \
NS_ADDREF_THIS(); \
return NS_OK; \
}
NS_IMPL_RELEASE(FileImpl)
NS_IMPL_ADDREF(FileImpl)
//----------------------------------------------------------------------------------------
NS_IMETHODIMP FileImpl::QueryInterface(REFNSIID aIID, void** aInstancePtr)
//----------------------------------------------------------------------------------------
{
if (!aInstancePtr)
return NS_ERROR_NULL_POINTER;
*aInstancePtr = nsnull;
SAY_I_IMPLEMENT(nsIFile)
SAY_I_IMPLEMENT(nsIOutputStream)
SAY_I_IMPLEMENT(nsIInputStream)
SAY_I_IMPLEMENT(nsIFileInputStream)
SAY_I_IMPLEMENT(nsIFileOutputStream)
// Note that we derive from two copies of nsIBaseStream (and hence
// of nsISupports), one through
// nsIOutputStream, the other through nsIInputStream. Resolve this
// by giving them a specific one
if (aIID.Equals(((nsIBaseStream*)(nsIOutputStream*)this)->IID()))
{
*aInstancePtr = (void*)((nsIBaseStream*)(nsIOutputStream*)this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(((nsISupports*)(nsIOutputStream*)this)->IID()))
{
*aInstancePtr = (void*)((nsISupports*)(nsIOutputStream*)this);
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
} // FileImpl::QueryInterface
//----------------------------------------------------------------------------------------
NS_IMETHODIMP FileImpl::Open(
const nsFileSpec& inFile,
int nsprMode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
{
if (mFileDesc)
if ((nsprMode & mNSPRMode) == nsprMode)
return NS_OK;
else
return NS_FILE_RESULT(PR_ILLEGAL_ACCESS_ERROR);
const int nspr_modes[]={
PR_WRONLY | PR_CREATE_FILE,
PR_WRONLY | PR_CREATE_FILE | PR_APPEND,
PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
PR_RDONLY,
PR_RDONLY | PR_APPEND,
PR_RDWR | PR_CREATE_FILE,
PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE,
// "wb",
// "ab",
// "wb",
// "rb",
// "r+b",
// "w+b",
0 };
const int* currentLegalMode = nspr_modes;
while (*currentLegalMode && nsprMode != *currentLegalMode)
++currentLegalMode;
if (!*currentLegalMode)
return NS_FILE_RESULT(PR_ILLEGAL_ACCESS_ERROR);
#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).
mFileDesc = 0;
if (inFile.Error() != noErr)
return NS_FILE_RESULT(inFile.Error());
OSErr err = noErr;
#if DEBUG
const OSType kCreator = 'CWIE';
#else
const OSType kCreator = 'MOSS';
#endif
// Resolve the alias to the original file.
nsFileSpec original = inFile;
PRBool ignoredResult;
original.ResolveAlias(ignoredResult);
const FSSpec& spec = original.operator const FSSpec&();
if (nsprMode & PR_CREATE_FILE)
err = FSpCreate(&spec, kCreator, 'TEXT', 0);
if (err == dupFNErr)
err = noErr;
if (err != noErr)
return NS_FILE_RESULT(err);
SInt8 perm;
if (nsprMode & PR_RDWR)
perm = fsRdWrPerm;
else if (nsprMode & PR_WRONLY)
perm = fsWrPerm;
else
perm = fsRdPerm;
short refnum;
err = FSpOpenDF(&spec, perm, &refnum);
if (err == noErr && (nsprMode & PR_TRUNCATE))
err = SetEOF(refnum, 0);
if (err == noErr && (nsprMode & PR_APPEND))
err = SetFPos(refnum, fsFromLEOF, 0);
if (err != noErr)
return NS_FILE_RESULT(err);
if ((mFileDesc = PR_ImportFile(refnum)) == 0)
return NS_FILE_RESULT(PR_GetError());
#else
// Platforms other than Macintosh...
// Another bug in NSPR: Mac PR_Open assumes a unix style path, but Win PR_Open assumes
// a windows path.
if ((mFileDesc = PR_Open((const char*)nsFileSpec(inFile), nsprMode, accessMode)) == 0)
return NS_FILE_RESULT(PR_GetError());
#endif
mNSPRMode = nsprMode;
mLength = PR_Available(mFileDesc);
return NS_OK;
} // FileImpl::Open
//----------------------------------------------------------------------------------------
NS_IMETHODIMP FileImpl::Seek(PRSeekWhence whence, PRInt32 offset)
//----------------------------------------------------------------------------------------
{
if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
mFailed = PR_FALSE; // reset on a seek.
mEOF = PR_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 = PR_TRUE;
}
else if (newPosition >= fileSize)
{
newPosition = fileSize;
mEOF = PR_TRUE;
}
if (PR_Seek(mFileDesc, newPosition, PR_SEEK_SET) < 0)
mFailed = PR_TRUE;
return NS_OK;
} // FileImpl::Seek
//----------------------------------------------------------------------------------------
NS_IMETHODIMP FileImpl::Tell(PRIntn* outWhere)
//----------------------------------------------------------------------------------------
{
if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
*outWhere = PR_Seek(mFileDesc, 0, PR_SEEK_CUR);
return NS_OK;
} // FileImpl::Tell
//----------------------------------------------------------------------------------------
NS_IMETHODIMP FileImpl::Close()
//----------------------------------------------------------------------------------------
{
if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
return NS_OK;
if (PR_Close(mFileDesc) == PR_SUCCESS)
mFileDesc = 0;
else
return NS_FILE_RESULT(PR_GetError());
return NS_OK;
} // FileImpl::close
//----------------------------------------------------------------------------------------
NS_IMETHODIMP FileImpl::Flush()
//----------------------------------------------------------------------------------------
{
#ifdef XP_MAC
if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR)
{
cout.flush();
return NS_OK;
}
#endif
if (!mFileDesc)
return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
PRBool itFailed = PR_Sync(mFileDesc) != PR_SUCCESS;
#ifdef XP_MAC
// On unix, it seems to fail always.
if (itFailed)
mFailed = PR_TRUE;
#endif
return NS_OK;
} // FileImpl::flush
//----------------------------------------------------------------------------------------
NS_BASE nsresult NS_NewTypicalInputFileStream(
nsISupports** aResult,
const nsFileSpec& inFile
/*Default nsprMode == PR_RDONLY*/
/*Default accessmode = 0700 (octal)*/)
// Factory method to get an nsInputStream from a file, using most common options
//----------------------------------------------------------------------------------------
{
return NS_NewIOFileStream(aResult, inFile, PR_RDONLY, 0700);
}
//----------------------------------------------------------------------------------------
NS_BASE nsresult NS_NewOutputConsoleStream(
nsISupports** aResult)
// Factory method to get an nsOutputStream to the console.
//----------------------------------------------------------------------------------------
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
FileImpl* stream = new FileImpl(PR_STDOUT);
if (! stream)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(stream);
*aResult = (nsISupports*)(void*)stream;
return NS_OK;
}
//----------------------------------------------------------------------------------------
NS_BASE nsresult NS_NewTypicalOutputFileStream(
nsISupports** aResult,
const nsFileSpec& inFile
/*default nsprMode= (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/
/*Default accessMode= 0700 (octal)*/)
// Factory method to get an nsOutputStream to a file - most common case.
//----------------------------------------------------------------------------------------
{
return NS_NewIOFileStream(
aResult,
inFile,
(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE),
0700);
}
//----------------------------------------------------------------------------------------
NS_BASE nsresult NS_NewIOFileStream(
nsISupports** aResult,
const nsFileSpec& inFile,
PRInt32 nsprMode /*default = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/,
PRInt32 accessMode /*Default = 0700 (octal)*/)
// Factory method to get an object that implements both nsIInputStream
// and nsIOutputStream, associated with a file.
//----------------------------------------------------------------------------------------
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (!aResult)
return NS_ERROR_NULL_POINTER;
FileImpl* stream = new FileImpl(inFile, nsprMode, accessMode);
if (! stream)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(stream);
*aResult = (nsISupports*)(void*)stream;
return NS_OK;
}
//----------------------------------------------------------------------------------------
NS_BASE nsresult NS_NewTypicalIOFileStream(
nsISupports** aResult,
const nsFileSpec& inFile
/*default nsprMode= (PR_RDWR | PR_CREATE_FILE)*/
/*Default accessMode= 0700 (octal)*/)
// Factory method to get an object that implements both nsIInputStream
// and nsIOutputStream, associated with a single file.
//----------------------------------------------------------------------------------------
{
return NS_NewIOFileStream(
aResult,
inFile,
(PR_RDWR | PR_CREATE_FILE),
0700);
}

View File

@@ -28,6 +28,8 @@
class nsIInputStream : public nsIBaseStream {
public:
static const nsIID& IID() { static nsIID iid = NS_IINPUTSTREAM_IID; return iid; }
/** Return the number of bytes in the stream
* @param aLength out parameter to hold the length
* of the stream. if an error occurs, the length

View File

@@ -29,6 +29,8 @@
class nsIOutputStream : public nsIBaseStream {
public:
static const nsIID& IID() { static nsIID iid = NS_IOUTPUTSTREAM_IID; return iid; }
/** Write data into the stream.
* @param aBuf the buffer into which the data is read
* @param aOffset the start offset of the data

View File

@@ -25,9 +25,10 @@
#include <dirent.h>
#include <unistd.h>
#include <stdlib.h>
#include "nsError.h"
//----------------------------------------------------------------------------------------
void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs)
void nsFileSpecHelpers::Canonify(char*& ioPath, PRBool inMakeDirs)
// Canonify, make absolute, and check whether directories exist
//----------------------------------------------------------------------------------------
{
@@ -76,75 +77,78 @@ void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs)
} // nsFileSpecHelpers::Canonify
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::SetLeafName(const char* inLeafName)
void nsFileSpec::SetLeafName(const char* inLeafName)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::LeafReplace(mPath, '/', inLeafName);
} // nsNativeFileSpec::SetLeafName
} // nsFileSpec::SetLeafName
//----------------------------------------------------------------------------------------
char* nsNativeFileSpec::GetLeafName() const
char* nsFileSpec::GetLeafName() const
//----------------------------------------------------------------------------------------
{
return nsFileSpecHelpers::GetLeaf(mPath, '/');
} // nsNativeFileSpec::GetLeafName
} // nsFileSpec::GetLeafName
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::Exists() const
PRBool nsFileSpec::Exists() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st);
} // nsNativeFileSpec::Exists
} // nsFileSpec::Exists
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsFile() const
PRBool nsFileSpec::IsFile() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && S_ISREG(st.st_mode);
} // nsNativeFileSpec::IsFile
} // nsFileSpec::IsFile
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsDirectory() const
PRBool nsFileSpec::IsDirectory() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && S_ISDIR(st.st_mode);
} // nsNativeFileSpec::IsDirectory
} // nsFileSpec::IsDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const
void nsFileSpec::GetParent(nsFileSpec& outSpec) const
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(outSpec.mPath, mPath);
char* cp = strrchr(outSpec.mPath, '/');
if (cp)
*cp = '\0';
} // nsNativeFileSpec::GetParent
} // nsFileSpec::GetParent
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator += (const char* inRelativePath)
void nsFileSpec::operator += (const char* inRelativePath)
//----------------------------------------------------------------------------------------
{
if (!inRelativePath || !mPath)
return;
if (mPath[strlen(mPath) - 1] != '/')
char* newPath = nsFileSpecHelpers::ReallocCat(mPath, "/");
char endChar = mPath[strlen(mPath) - 1];
if (endChar == '/')
nsFileSpecHelpers::ReallocCat(mPath, "x");
else
nsFileSpecHelpers::ReallocCat(mPath, "/x");
SetLeafName(inRelativePath);
} // nsNativeFileSpec::operator +=
} // nsFileSpec::operator +=
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::CreateDirectory(int mode)
void nsFileSpec::CreateDirectory(int mode)
//----------------------------------------------------------------------------------------
{
// Note that mPath is canonical!
mkdir(mPath, mode);
} // nsNativeFileSpec::CreateDirectory
} // nsFileSpec::CreateDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::Delete(bool inRecursive)
void nsFileSpec::Delete(PRBool inRecursive)
// To check if this worked, call Exists() afterwards, see?
//----------------------------------------------------------------------------------------
{
@@ -152,9 +156,9 @@ void nsNativeFileSpec::Delete(bool inRecursive)
{
if (inRecursive)
{
for (nsDirectoryIterator i(*this); i; i++)
for (nsDirectoryIterator i(*this); i.Exists(); i++)
{
nsNativeFileSpec& child = (nsNativeFileSpec&)i;
nsFileSpec& child = (nsFileSpec&)i;
child.Delete(inRecursive);
}
}
@@ -162,7 +166,148 @@ void nsNativeFileSpec::Delete(bool inRecursive)
}
else
remove(mPath);
} // nsNativeFileSpec::Delete
} // nsFileSpec::Delete
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Rename(const char* inNewName)
//----------------------------------------------------------------------------------------
{
// This function should not be used to move a file on disk.
if (strchr(inNewName, '/'))
return NS_FILE_FAILURE;
if (PR_Rename(mPath, inNewName) != 0)
{
return NS_FILE_FAILURE;
}
SetLeafName(inNewName);
return NS_OK;
} // nsFileSpec::Rename
static int CrudeFileCopy(const char* in, const char* out)
{
struct stat in_stat;
int stat_result = -1;
char buf [1024];
FILE *ifp, *ofp;
int rbytes, wbytes;
if (!in || !out)
return -1;
stat_result = stat (in, &in_stat);
ifp = fopen (in, "r");
if (!ifp)
{
return -1;
}
ofp = fopen (out, "w");
if (!ofp)
{
fclose (ifp);
return -1;
}
while ((rbytes = fread (buf, 1, sizeof(buf), ifp)) > 0)
{
while (rbytes > 0)
{
if ( (wbytes = fwrite (buf, 1, rbytes, ofp)) < 0 )
{
fclose (ofp);
fclose (ifp);
unlink(out);
return -1;
}
rbytes -= wbytes;
}
}
fclose (ofp);
fclose (ifp);
if (stat_result == 0)
{
chmod (out, in_stat.st_mode & 0777);
}
return 0;
} // nsFileSpec::Rename
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Copy(const nsFileSpec& inParentDirectory) const
//----------------------------------------------------------------------------------------
{
// We can only copy into a directory, and (for now) can not copy entire directories
nsresult result = NS_FILE_FAILURE;
if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
{
char *leafname = GetLeafName();
char* destPath = nsFileSpecHelpers::StringDup(inParentDirectory, ( strlen(inParentDirectory) + 1 + strlen(leafname) ) );
strcat(destPath, "/");
strcat(destPath, leafname);
delete [] leafname;
result = NS_FILE_RESULT(CrudeFileCopy(*this, destPath));
delete [] destPath;
}
return result;
} // nsFileSpec::Copy
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Move(const nsFileSpec& inNewParentDirectory) const
//----------------------------------------------------------------------------------------
{
// We can only copy into a directory, and (for now) can not copy entire directories
nsresult result = NS_FILE_FAILURE;
if (inNewParentDirectory.IsDirectory() && (! IsDirectory() ) )
{
char *leafname = GetLeafName();
char* destPath
= nsFileSpecHelpers::StringDup(
inNewParentDirectory,
strlen(inNewParentDirectory) + 1 + strlen(leafname));
strcat(destPath, "/");
strcat(destPath, leafname);
delete [] leafname;
result = NS_FILE_RESULT(CrudeFileCopy(*this, destPath));
if (result == NS_OK)
{
Delete(PR_FALSE);
}
delete [] destPath;
}
return result;
}
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Execute(const char* inArgs ) const
//----------------------------------------------------------------------------------------
{
nsresult result = NS_FILE_FAILURE;
if (! IsDirectory())
{
char* fileNameWithArgs
= nsFileSpecHelpers::StringDup(mPath, strlen(mPath) + 1 + strlen(inArgs));
strcat(fileNameWithArgs, " ");
strcat(fileNameWithArgs, inArgs);
result = NS_FILE_RESULT(system(fileNameWithArgs));
delete [] fileNameWithArgs;
}
return result;
} // nsFileSpec::Execute
//========================================================================================
// nsDirectoryIterator
@@ -170,7 +315,7 @@ void nsNativeFileSpec::Delete(bool inRecursive)
//----------------------------------------------------------------------------------------
nsDirectoryIterator::nsDirectoryIterator(
const nsNativeFileSpec& inDirectory
const nsFileSpec& inDirectory
, int inIterateDirection)
//----------------------------------------------------------------------------------------
: mCurrent(inDirectory)

View File

@@ -23,9 +23,18 @@
#include <direct.h>
#include <stdlib.h>
#include "prio.h"
#include "nsError.h"
#include "windows.h"
#ifdef UNICODE
#define CreateDirectoryW CreateDirectory
#else
#define CreateDirectoryA CreateDirectory
#endif
//----------------------------------------------------------------------------------------
void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs)
void nsFileSpecHelpers::Canonify(char*& ioPath, PRBool inMakeDirs)
// Canonify, make absolute, and check whether directories exist. This
// takes a (possibly relative) native path and converts it into a
// fully qualified native path.
@@ -125,7 +134,7 @@ void nsFileSpecHelpers::NativeToUnix(char*& ioPath)
}
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath)
nsFileSpec::nsFileSpec(const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
: mPath(NULL)
{
@@ -133,15 +142,16 @@ nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath)
}
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const nsFilePath& inPath)
void nsFileSpec::operator = (const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(mPath, (const char*)inPath);
nsFileSpecHelpers::UnixToNative(mPath);
} // nsNativeFileSpec::operator =
mError = NS_OK;
} // nsFileSpec::operator =
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const nsNativeFileSpec& inSpec)
nsFilePath::nsFilePath(const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
: mPath(NULL)
{
@@ -149,7 +159,7 @@ nsFilePath::nsFilePath(const nsNativeFileSpec& inSpec)
} // nsFilePath::nsFilePath
//----------------------------------------------------------------------------------------
void nsFilePath::operator = (const nsNativeFileSpec& inSpec)
void nsFilePath::operator = (const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(mPath, inSpec.mPath);
@@ -157,84 +167,86 @@ void nsFilePath::operator = (const nsNativeFileSpec& inSpec)
} // nsFilePath::operator =
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::SetLeafName(const char* inLeafName)
void nsFileSpec::SetLeafName(const char* inLeafName)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::LeafReplace(mPath, '\\', inLeafName);
} // nsNativeFileSpec::SetLeafName
} // nsFileSpec::SetLeafName
//----------------------------------------------------------------------------------------
char* nsNativeFileSpec::GetLeafName() const
char* nsFileSpec::GetLeafName() const
//----------------------------------------------------------------------------------------
{
return nsFileSpecHelpers::GetLeaf(mPath, '\\');
} // nsNativeFileSpec::GetLeafName
} // nsFileSpec::GetLeafName
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::Exists() const
PRBool nsFileSpec::Exists() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st);
} // nsNativeFileSpec::Exists
} // nsFileSpec::Exists
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsFile() const
PRBool nsFileSpec::IsFile() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && (_S_IFREG & st.st_mode);
} // nsNativeFileSpec::IsFile
} // nsFileSpec::IsFile
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsDirectory() const
PRBool nsFileSpec::IsDirectory() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && (_S_IFDIR & st.st_mode);
} // nsNativeFileSpec::IsDirectory
} // nsFileSpec::IsDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const
void nsFileSpec::GetParent(nsFileSpec& outSpec) const
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(outSpec.mPath, mPath);
char* cp = strrchr(outSpec.mPath, '\\');
if (cp)
*cp = '\0';
} // nsNativeFileSpec::GetParent
} // nsFileSpec::GetParent
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator += (const char* inRelativePath)
void nsFileSpec::operator += (const char* inRelativePath)
//----------------------------------------------------------------------------------------
{
if (!inRelativePath || !mPath)
return;
if (mPath[strlen(mPath) - 1] != '\\')
char* newPath = nsFileSpecHelpers::ReallocCat(mPath, "\\");
if (mPath[strlen(mPath) - 1] == '\\')
nsFileSpecHelpers::ReallocCat(mPath, "x");
else
nsFileSpecHelpers::ReallocCat(mPath, "\\x");
SetLeafName(inRelativePath);
} // nsNativeFileSpec::operator +=
} // nsFileSpec::operator +=
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::CreateDirectory(int /*mode*/)
void nsFileSpec::CreateDirectory(int /*mode*/)
//----------------------------------------------------------------------------------------
{
// Note that mPath is canonical!
mkdir(mPath);
} // nsNativeFileSpec::CreateDirectory
} // nsFileSpec::CreateDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::Delete(bool inRecursive)
void nsFileSpec::Delete(PRBool inRecursive)
//----------------------------------------------------------------------------------------
{
if (IsDirectory())
{
if (inRecursive)
{
for (nsDirectoryIterator i(*this); i; i++)
for (nsDirectoryIterator i(*this); i.Exists(); i++)
{
nsNativeFileSpec& child = (nsNativeFileSpec&)i;
nsFileSpec& child = (nsFileSpec&)i;
child.Delete(inRecursive);
}
}
@@ -244,7 +256,106 @@ void nsNativeFileSpec::Delete(bool inRecursive)
{
remove(mPath);
}
} // nsNativeFileSpec::Delete
} // nsFileSpec::Delete
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Rename(const char* inNewName)
//----------------------------------------------------------------------------------------
{
// This function should not be used to move a file on disk.
if (strchr(inNewName, '/'))
return NS_FILE_FAILURE;
if (PR_Rename(*this, inNewName) != NS_OK)
{
return NS_FILE_FAILURE;
}
SetLeafName(inNewName);
return NS_OK;
} // nsFileSpec::Rename
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Copy(const nsFileSpec& inParentDirectory) const
//----------------------------------------------------------------------------------------
{
// We can only copy into a directory, and (for now) can not copy entire directories
if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
{
char *leafname = GetLeafName();
char* destPath = nsFileSpecHelpers::StringDup(inParentDirectory, ( strlen(inParentDirectory) + 1 + strlen(leafname) ) );
strcat(destPath, "\\");
strcat(destPath, leafname);
delete [] leafname;
// CopyFile returns non-zero if succeeds
int copyOK = CopyFile(*this, destPath, true);
delete[] destPath;
if (copyOK)
{
return NS_OK;
}
}
return NS_FILE_FAILURE;
} // nsFileSpec::Copy
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Move(const nsFileSpec& nsNewParentDirectory) const
//----------------------------------------------------------------------------------------
{
// We can only copy into a directory, and (for now) can not copy entire directories
if (nsNewParentDirectory.IsDirectory() && (! IsDirectory() ) )
{
char *leafname = GetLeafName();
char *destPath = nsFileSpecHelpers::StringDup(nsNewParentDirectory, ( strlen(nsNewParentDirectory) + 1 + strlen(leafname) ));
strcat(destPath, "\\");
strcat(destPath, leafname);
delete [] leafname;
// MoveFile returns non-zero if succeeds
int copyOK = MoveFile(*this, destPath);
delete [] destPath;
if (copyOK)
{
return NS_OK;
}
}
return NS_FILE_FAILURE;
} // nsFileSpec::Move
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Execute(const char* inArgs ) const
//----------------------------------------------------------------------------------------
{
if (! IsDirectory())
{
char* fileNameWithArgs = NULL;
fileNameWithArgs = nsFileSpecHelpers::StringDup(mPath, ( strlen(mPath) + 1 + strlen(inArgs) ) );
strcat(fileNameWithArgs, " ");
strcat(fileNameWithArgs, inArgs);
int execResult = WinExec( fileNameWithArgs, SW_NORMAL );
delete [] fileNameWithArgs;
if (execResult > 31)
{
return NS_OK;
}
}
return NS_FILE_FAILURE;
} // nsFileSpec::Execute
//========================================================================================
// nsDirectoryIterator
@@ -252,7 +363,7 @@ void nsNativeFileSpec::Delete(bool inRecursive)
//----------------------------------------------------------------------------------------
nsDirectoryIterator::nsDirectoryIterator(
const nsNativeFileSpec& inDirectory
const nsFileSpec& inDirectory
, int inIterateDirection)
//----------------------------------------------------------------------------------------
: mCurrent(inDirectory)

View File

@@ -16,10 +16,11 @@
* Reserved.
*/
#include "string.h"
#include "nsFileSpec.h"
#include "nsFileStream.h"
//#include "string.h"
struct FilesTest
{
FilesTest() : mConsole() {}
@@ -30,18 +31,25 @@ struct FilesTest
int InputStream(const char* relativePath);
int OutputStream(const char* relativePath);
int IOStream(const char* relativePath);
int Parent(const char* relativePath, nsNativeFileSpec& outParent);
int Delete(nsNativeFileSpec& victim);
int CreateDirectory(nsNativeFileSpec& victim);
int IterateDirectoryChildren(nsNativeFileSpec& startChild);
int Parent(const char* relativePath, nsFileSpec& outParent);
int Delete(nsFileSpec& victim);
int CreateDirectory(nsFileSpec& victim);
int IterateDirectoryChildren(nsFileSpec& startChild);
int CanonicalPath(const char* relativePath);
int Persistence(const char* relativePath);
int Copy(const char* sourceFile, const char* targDir);
int Move(const char* sourceFile, const char* targDir);
int Rename(const char* sourceFile, const char* newName);
int Execute(const char* appName, const char* args);
void Banner(const char* bannerString);
void Passed();
void Failed();
void Inspect();
nsOutputFileStream mConsole;
nsOutputConsoleStream mConsole;
};
//----------------------------------------------------------------------------------------
@@ -59,7 +67,8 @@ void FilesTest::Banner(const char* bannerString)
void FilesTest::Passed()
//----------------------------------------------------------------------------------------
{
mConsole << "Test passed." << nsEndl;
((nsOutputStream&)mConsole) << "Test passed.";
mConsole << nsEndl;
}
//----------------------------------------------------------------------------------------
@@ -89,7 +98,7 @@ void FilesTest::WriteStuff(nsOutputFileStream& s)
s << "As a unix path: \"" << (const char*)filePath << "\""<< nsEndl;
// Initialize a native file spec from a URL
nsNativeFileSpec fileSpec(fileURL);
nsFileSpec fileSpec(fileURL);
s << "As a file spec: " << fileSpec << nsEndl;
// Make the spec unique (this one has no suffix).
@@ -119,10 +128,10 @@ int FilesTest::OutputStream(const char* relativePath)
{
nsFilePath myTextFilePath(relativePath, true); // relative path.
const char* pathAsString = (const char*)myTextFilePath;
nsNativeFileSpec mySpec(myTextFilePath);
nsFileSpec mySpec(myTextFilePath);
{
mConsole << "WRITING IDENTICAL OUTPUT TO " << pathAsString << nsEndl << nsEndl;
nsOutputFileStream testStream(myTextFilePath);
nsOutputFileStream testStream(mySpec);
if (!testStream.is_open())
{
mConsole
@@ -154,9 +163,10 @@ int FilesTest::IOStream(const char* relativePath)
{
nsFilePath myTextFilePath(relativePath, true); // relative path.
const char* pathAsString = (const char*)myTextFilePath;
nsFileSpec mySpec(myTextFilePath);
mConsole
<< "Replacing \"path\" by \"ZUUL\" in " << pathAsString << nsEndl << nsEndl;
nsIOFileStream testStream(myTextFilePath);
nsIOFileStream testStream(mySpec);
if (!testStream.is_open())
{
mConsole
@@ -183,6 +193,57 @@ int FilesTest::IOStream(const char* relativePath)
return 0;
}
//----------------------------------------------------------------------------------------
int FilesTest::Persistence(
const char* relativePathToWrite)
//----------------------------------------------------------------------------------------
{
nsFilePath myTextFilePath(relativePathToWrite, true);
const char* pathAsString = (const char*)myTextFilePath;
nsFileSpec mySpec(myTextFilePath);
nsIOFileStream testStream(mySpec, (PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE));
if (!testStream.is_open())
{
mConsole
<< "ERROR: File "
<< pathAsString
<< " could not be opened for input+output"
<< nsEndl;
return -1;
}
nsPersistentFileDescriptor myPersistent(mySpec);
mConsole
<< "Writing persistent file data " << pathAsString << nsEndl << nsEndl;
testStream.seek(0); // check that the seek compiles
testStream << myPersistent;
testStream.seek(0);
nsPersistentFileDescriptor mySecondPersistent;
testStream >> mySecondPersistent;
mySpec = mySecondPersistent;
#ifdef XP_MAC
if (mySpec.Error())
{
Failed();
return -1;
}
#endif
if (!mySpec.Exists())
{
Failed();
return -1;
}
Passed();
return 0;
}
//----------------------------------------------------------------------------------------
int FilesTest::InputStream(const char* relativePath)
//----------------------------------------------------------------------------------------
@@ -190,7 +251,8 @@ int FilesTest::InputStream(const char* relativePath)
nsFilePath myTextFilePath(relativePath, true);
const char* pathAsString = (const char*)myTextFilePath;
mConsole << "READING BACK DATA FROM " << pathAsString << nsEndl << nsEndl;
nsInputFileStream testStream2(myTextFilePath);
nsFileSpec mySpec(myTextFilePath);
nsInputFileStream testStream2(mySpec);
if (!testStream2.is_open())
{
mConsole
@@ -215,12 +277,12 @@ int FilesTest::InputStream(const char* relativePath)
//----------------------------------------------------------------------------------------
int FilesTest::Parent(
const char* relativePath,
nsNativeFileSpec& outParent)
nsFileSpec& outParent)
//----------------------------------------------------------------------------------------
{
nsFilePath myTextFilePath(relativePath, true);
const char* pathAsString = (const char*)myTextFilePath;
nsNativeFileSpec mySpec(myTextFilePath);
nsFileSpec mySpec(myTextFilePath);
mySpec.GetParent(outParent);
nsFilePath parentPath(outParent);
@@ -235,7 +297,7 @@ int FilesTest::Parent(
}
//----------------------------------------------------------------------------------------
int FilesTest::Delete(nsNativeFileSpec& victim)
int FilesTest::Delete(nsFileSpec& victim)
//----------------------------------------------------------------------------------------
{
// - Test of non-recursive delete
@@ -284,7 +346,7 @@ int FilesTest::Delete(nsNativeFileSpec& victim)
}
//----------------------------------------------------------------------------------------
int FilesTest::CreateDirectory(nsNativeFileSpec& dirSpec)
int FilesTest::CreateDirectory(nsFileSpec& dirSpec)
//----------------------------------------------------------------------------------------
{
nsFilePath dirPath(dirSpec);
@@ -306,27 +368,27 @@ int FilesTest::CreateDirectory(nsNativeFileSpec& dirSpec)
}
//----------------------------------------------------------------------------------------
int FilesTest::IterateDirectoryChildren(nsNativeFileSpec& startChild)
int FilesTest::IterateDirectoryChildren(nsFileSpec& startChild)
//----------------------------------------------------------------------------------------
{
// - Test of directory iterator
nsNativeFileSpec grandparent;
nsFileSpec grandparent;
startChild.GetParent(grandparent); // should be the original default directory.
nsFilePath grandparentPath(grandparent);
mConsole << "Forwards listing of " << (const char*)grandparentPath << ":" << nsEndl;
for (nsDirectoryIterator i(grandparent, +1); i; i++)
for (nsDirectoryIterator i(grandparent, +1); i.Exists(); i++)
{
char* itemName = ((nsNativeFileSpec&)i).GetLeafName();
char* itemName = ((nsFileSpec&)i).GetLeafName();
mConsole << '\t' << itemName << nsEndl;
delete [] itemName;
}
mConsole << "Backwards listing of " << (const char*)grandparentPath << ":" << nsEndl;
for (nsDirectoryIterator j(grandparent, -1); j; j--)
for (nsDirectoryIterator j(grandparent, -1); j.Exists(); j--)
{
char* itemName = ((nsNativeFileSpec&)j).GetLeafName();
char* itemName = ((nsFileSpec&)j).GetLeafName();
mConsole << '\t' << itemName << nsEndl;
delete [] itemName;
}
@@ -355,6 +417,110 @@ int FilesTest::CanonicalPath(
return 0;
}
//----------------------------------------------------------------------------------------
int FilesTest::Copy(const char* file, const char* dir)
//----------------------------------------------------------------------------------------
{
nsFileSpec dirPath(dir, true);
dirPath.CreateDirectory();
if (! dirPath.Exists())
{
Failed();
return -1;
}
nsFileSpec mySpec(file, true); // relative path.
{
nsIOFileStream testStream(mySpec); // creates the file
// Scope ends here, file gets closed
}
nsFileSpec filePath(file);
if (! filePath.Exists())
{
Failed();
return -1;
}
nsresult error = filePath.Copy(dirPath);
dirPath += filePath.GetLeafName();
if (! dirPath.Exists() || ! filePath.Exists() || NS_FAILED(error))
{
Failed();
return -1;
}
Passed();
return 0;
}
//----------------------------------------------------------------------------------------
int FilesTest::Move(const char* file, const char* dir)
//----------------------------------------------------------------------------------------
{
nsFileSpec dirPath(dir, true);
dirPath.CreateDirectory();
if (! dirPath.Exists())
{
Failed();
return -1;
}
nsFileSpec srcSpec(file, true); // relative path.
{
nsIOFileStream testStream(srcSpec); // creates the file
// file gets closed here because scope ends here.
};
if (! srcSpec.Exists())
{
Failed();
return -1;
}
nsresult error = srcSpec.Move(dirPath);
dirPath += srcSpec.GetLeafName();
if (! dirPath.Exists() || srcSpec.Exists() || NS_FAILED(error))
{
Failed();
return -1;
}
Passed();
return 0;
}
//----------------------------------------------------------------------------------------
int FilesTest::Execute(const char* appName, const char* args)
//----------------------------------------------------------------------------------------
{
nsFileSpec appPath(appName, false);
if (!appPath.Exists())
{
Failed();
return -1;
}
nsresult error = appPath.Execute(args);
if (NS_FAILED(error))
{
Failed();
return -1;
}
Passed();
return 0;
}
//----------------------------------------------------------------------------------------
int FilesTest::RunAllTests()
// For use with DEBUG defined.
@@ -389,7 +555,7 @@ int FilesTest::RunAllTests()
return -1;
Banner("Parent");
nsNativeFileSpec parent;
nsFileSpec parent;
if (Parent("mumble/iotest.txt", parent) != 0)
return -1;
@@ -405,6 +571,36 @@ int FilesTest::RunAllTests()
if (IterateDirectoryChildren(parent) != 0)
return -1;
Banner("Copy");
if (Copy("mumble/copyfile.txt", "mumble/copy") != 0)
return -1;
Banner("Move");
if (Move("mumble/moveFile.txt", "mumble/move") != 0)
return -1;
Banner("Execute");
#ifdef XP_MAC
// This path is hard-coded to test on jrm's machine. Finding an app
// on an arbitrary Macintosh would cost more trouble than it's worth.
// Change path to suit.
if NS_FAILED(Execute("/Projects/Nav45_BRANCH/ns/cmd/macfe/"\
"projects/client45/Client45PPC", ""))
#elif XP_PC
if NS_FAILED(Execute("c:\\windows\\notepad.exe", ""))
#else
if NS_FAILED(Execute("/bin/ls", "/"))
#endif
return -1;
Banner("Persistence");
if (Persistence("mumble/filedesc.dat") != 0)
return -1;
Banner("Delete again (to clean up our mess)");
if (Delete(parent) != 0)
return -1;
return 0;
}
@@ -413,7 +609,6 @@ int main()
// For use with DEBUG defined.
//----------------------------------------------------------------------------------------
{
FilesTest tester;
return tester.RunAllTests();
} // main

View File

@@ -22,6 +22,9 @@
#include "nsDebug.h"
#include "prtypes.h"
#include "plstr.h"
#include "plbase64.h"
#include "prmem.h"
#include <string.h>
#include <stdio.h>
@@ -40,7 +43,7 @@ NS_NAMESPACE nsFileSpecHelpers
char inSeparator,
const char* inLeafName);
#ifndef XP_MAC
NS_NAMESPACE_PROTOTYPE void Canonify(char*& ioPath, bool inMakeDirs);
NS_NAMESPACE_PROTOTYPE void Canonify(char*& ioPath, PRBool inMakeDirs);
NS_NAMESPACE_PROTOTYPE void MakeAllDirectories(const char* inPath, int mode);
#endif
NS_NAMESPACE_PROTOTYPE char* GetLeaf(const char* inPath, char inSeparator); // allocated
@@ -54,6 +57,14 @@ NS_NAMESPACE nsFileSpecHelpers
#endif
} NS_NAMESPACE_END
//----------------------------------------------------------------------------------------
nsresult ns_file_convert_result(PRInt32 nativeErr)
//----------------------------------------------------------------------------------------
{
return nativeErr ?
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES,((nativeErr)&0xFFFF))
: NS_OK;
}
//----------------------------------------------------------------------------------------
char* nsFileSpecHelpers::StringDup(
@@ -65,7 +76,7 @@ char* nsFileSpecHelpers::StringDup(
allocLength = strlen(inString);
char* newPath = inString || allocLength ? new char[allocLength + 1] : nsnull;
if (!newPath)
return NULL;
return nsnull;
strcpy(newPath, inString);
return newPath;
} // nsFileSpecHelpers::StringDup
@@ -77,7 +88,7 @@ char* nsFileSpecHelpers::AllocCat(
//----------------------------------------------------------------------------------------
{
if (!inString1)
return inString2 ? StringDup(inString2) : (char*)NULL;
return inString2 ? StringDup(inString2) : (char*)nsnull;
if (!inString2)
return StringDup(inString1);
char* outString = StringDup(inString1, strlen(inString1) + strlen(inString2));
@@ -95,7 +106,7 @@ char* nsFileSpecHelpers::StringAssign(
if (!inString2)
{
delete [] ioString;
ioString = (char*)NULL;
ioString = (char*)nsnull;
return ioString;
}
if (!ioString || (strlen(inString2) > strlen(ioString)))
@@ -125,8 +136,19 @@ void nsFileSpecHelpers::LeafReplace(
}
char* lastSeparator = strrchr(ioPath, inSeparator);
int oldLength = strlen(ioPath);
*(++lastSeparator) = '\0'; // strip the current leaf name
int newLength = lastSeparator - ioPath + strlen(inLeafName);
PRBool trailingSeparator = (lastSeparator + 1 == ioPath + oldLength);
if (trailingSeparator)
{
*lastSeparator = '\0';
lastSeparator = strrchr(ioPath, inSeparator);
}
if (lastSeparator)
lastSeparator++; // point at the trailing string
else
lastSeparator = ioPath; // the full monty
*lastSeparator = '\0'; // strip the current leaf name
int newLength = (lastSeparator - ioPath) + strlen(inLeafName) + int(trailingSeparator);
if (newLength > oldLength)
{
char* newPath = StringDup(ioPath, newLength + 1);
@@ -134,7 +156,14 @@ void nsFileSpecHelpers::LeafReplace(
ioPath = newPath;
}
strcat(ioPath, inLeafName);
} // nsNativeFileSpec::LeafReplace
if (trailingSeparator)
{
// If the original ended in a slash, then the new one should, too.
char sepStr[2] = "/";
*sepStr = inSeparator;
strcat(ioPath, sepStr);
}
} // nsFileSpecHelpers::LeafReplace
//----------------------------------------------------------------------------------------
char* nsFileSpecHelpers::GetLeaf(const char* inPath, char inSeparator)
@@ -142,12 +171,32 @@ char* nsFileSpecHelpers::GetLeaf(const char* inPath, char inSeparator)
//----------------------------------------------------------------------------------------
{
if (!inPath)
return NULL;
char* lastSeparator = strrchr(inPath, inSeparator);
if (lastSeparator)
return StringDup(++lastSeparator);
return StringDup(inPath);
} // nsNativeFileSpec::GetLeaf
return nsnull;
const char* lastSeparator = strrchr(inPath, inSeparator);
// If there was no separator, then return a copy of the caller's path.
if (!lastSeparator)
return StringDup(inPath);
// So there's at least one separator. What's just after it?
// If the separator was not the last character, return the trailing string.
const char* leafPointer = lastSeparator + 1;
if (*leafPointer)
return StringDup(leafPointer);
// So now, separator was the last character. Poke in a null instead.
*(char*)lastSeparator = '\0'; // Should use const_cast, but Unix has old compiler.
leafPointer = strrchr(inPath, inSeparator);
char* result = leafPointer ? StringDup(leafPointer++) : StringDup(inPath);
// Restore the poked null before returning.
*(char*)lastSeparator = inSeparator;
#ifdef XP_PC
// If it's a drive letter use the colon notation.
if (!leafPointer && strlen(result) == 2 && result[1] == '|')
result[1] = ':';
#endif
return result;
} // nsFileSpecHelpers::GetLeaf
#if defined(XP_UNIX) || defined(XP_PC)
@@ -177,7 +226,7 @@ void nsFileSpecHelpers::MakeAllDirectories(const char* inPath, int mode)
if (currentEnd)
{
*currentEnd = '\0';
nsNativeFileSpec spec(nsFilePath(pathCopy, false));
nsFileSpec spec(nsFilePath(pathCopy, PR_FALSE));
do
{
// If the node doesn't exist, and it is not the initial node in a full path,
@@ -209,7 +258,7 @@ char* nsFileSpecHelpers::ReallocCat(char*& ioString, const char* inString1)
delete [] ioString;
ioString = newString;
return ioString;
} // nsNativeFileSpec::ReallocCat
} // nsFileSpecHelpers::ReallocCat
#if defined(XP_PC)
#include "windows/nsFileSpecWin.cpp" // Windows-specific implementations
@@ -225,7 +274,7 @@ char* nsFileSpecHelpers::ReallocCat(char*& ioString, const char* inString1)
#ifndef XP_MAC
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const char* inString, bool inCreateDirs)
nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs)
//----------------------------------------------------------------------------------------
: mURL(nsnull)
{
@@ -243,7 +292,7 @@ nsFileURL::nsFileURL(const nsFileURL& inOther)
//----------------------------------------------------------------------------------------
: mURL(nsFileSpecHelpers::StringDup(inOther.mURL))
#ifdef XP_MAC
, mNativeFileSpec(inOther.GetNativeSpec())
, mFileSpec(inOther.GetFileSpec())
#endif
{
} // nsFileURL::nsFileURL
@@ -253,16 +302,16 @@ nsFileURL::nsFileURL(const nsFilePath& inOther)
//----------------------------------------------------------------------------------------
: mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther))
#ifdef XP_MAC
, mNativeFileSpec(inOther.GetNativeSpec())
, mFileSpec(inOther.GetFileSpec())
#endif
{
} // nsFileURL::nsFileURL
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const nsNativeFileSpec& inOther)
nsFileURL::nsFileURL(const nsFileSpec& inOther)
: mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther)))
#ifdef XP_MAC
, mNativeFileSpec(inOther)
, mFileSpec(inOther)
#endif
//----------------------------------------------------------------------------------------
{
@@ -282,7 +331,7 @@ void nsFileURL::operator = (const char* inString)
nsFileSpecHelpers::StringAssign(mURL, inString);
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
#ifdef XP_MAC
mNativeFileSpec = inString + kFileURLPrefixLength;
mFileSpec = inString + kFileURLPrefixLength;
#endif
} // nsFileURL::operator =
@@ -292,7 +341,7 @@ void nsFileURL::operator = (const nsFileURL& inOther)
{
mURL = nsFileSpecHelpers::StringAssign(mURL, inOther.mURL);
#ifdef XP_MAC
mNativeFileSpec = inOther.GetNativeSpec();
mFileSpec = inOther.GetFileSpec();
#endif
} // nsFileURL::operator =
@@ -303,27 +352,29 @@ void nsFileURL::operator = (const nsFilePath& inOther)
delete [] mURL;
mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther);
#ifdef XP_MAC
mNativeFileSpec = inOther.GetNativeSpec();
mFileSpec = inOther.GetFileSpec();
#endif
} // nsFileURL::operator =
//----------------------------------------------------------------------------------------
void nsFileURL::operator = (const nsNativeFileSpec& inOther)
void nsFileURL::operator = (const nsFileSpec& inOther)
//----------------------------------------------------------------------------------------
{
delete [] mURL;
mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther));
#ifdef XP_MAC
mNativeFileSpec = inOther;
mFileSpec = inOther;
#endif
} // nsFileURL::operator =
#if DEBUG
//----------------------------------------------------------------------------------------
nsBasicOutStream& operator << (nsBasicOutStream& s, const nsFileURL& url)
nsOutputStream& operator << (nsOutputStream& s, const nsFileURL& url)
//----------------------------------------------------------------------------------------
{
return (s << url.mURL);
}
#endif
//========================================================================================
// nsFilePath implementation
@@ -332,14 +383,14 @@ nsBasicOutStream& operator << (nsBasicOutStream& s, const nsFileURL& url)
nsFilePath::nsFilePath(const nsFilePath& inPath)
: mPath(nsFileSpecHelpers::StringDup(inPath.mPath))
#ifdef XP_MAC
, mNativeFileSpec(inPath.mNativeFileSpec)
, mFileSpec(inPath.mFileSpec)
#endif
{
}
#ifndef XP_MAC
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const char* inString, bool inCreateDirs)
nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inString))
{
@@ -362,14 +413,14 @@ nsFilePath::nsFilePath(const nsFileURL& inOther)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inOther.mURL + kFileURLPrefixLength))
#ifdef XP_MAC
, mNativeFileSpec(inOther.GetNativeSpec())
, mFileSpec(inOther.GetFileSpec())
#endif
{
}
#ifdef XP_UNIX
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const nsNativeFileSpec& inOther)
nsFilePath::nsFilePath(const nsFileSpec& inOther)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inOther.mPath))
{
@@ -385,7 +436,7 @@ nsFilePath::~nsFilePath()
#ifdef XP_UNIX
//----------------------------------------------------------------------------------------
void nsFilePath::operator = (const nsNativeFileSpec& inOther)
void nsFilePath::operator = (const nsFileSpec& inOther)
//----------------------------------------------------------------------------------------
{
mPath = nsFileSpecHelpers::StringAssign(mPath, inOther.mPath);
@@ -398,14 +449,14 @@ void nsFilePath::operator = (const char* inString)
{
NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
#ifdef XP_MAC
mNativeFileSpec = inString;
nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(mNativeFileSpec));
mFileSpec = inString;
nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(mFileSpec));
#else
#ifdef XP_PC
nsFileSpecHelpers::UnixToNative(mPath);
#endif
// Make canonical and absolute.
nsFileSpecHelpers::Canonify(mPath, false /* XXX? */);
nsFileSpecHelpers::Canonify(mPath, PR_FALSE /* XXX? */);
#ifdef XP_PC
nsFileSpecHelpers::NativeToUnix(mPath);
#endif
@@ -418,7 +469,7 @@ void nsFilePath::operator = (const nsFileURL& inOther)
{
nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(inOther));
#ifdef XP_MAC
mNativeFileSpec = inOther.GetNativeSpec();
mFileSpec = inOther.GetFileSpec();
#endif
}
@@ -433,40 +484,51 @@ void nsFilePath::operator = (const nsFilePath& inOther)
}
//========================================================================================
// nsNativeFileSpec implementation
// nsFileSpec implementation
//========================================================================================
#ifndef XP_MAC
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec()
nsFileSpec::nsFileSpec()
//----------------------------------------------------------------------------------------
: mPath(NULL)
: mPath(nsnull)
, mError(NS_OK)
{
}
#endif
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const nsFileURL& inURL)
nsFileSpec::nsFileSpec(const nsPersistentFileDescriptor& inDescriptor)
//----------------------------------------------------------------------------------------
#ifndef XP_MAC
: mPath(NULL)
: mPath(nsnull)
#endif
{
*this = inDescriptor;
}
//----------------------------------------------------------------------------------------
nsFileSpec::nsFileSpec(const nsFileURL& inURL)
//----------------------------------------------------------------------------------------
#ifndef XP_MAC
: mPath(nsnull)
#endif
{
*this = nsFilePath(inURL); // convert to unix path first
}
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::MakeUnique(const char* inSuggestedLeafName)
void nsFileSpec::MakeUnique(const char* inSuggestedLeafName)
//----------------------------------------------------------------------------------------
{
if (inSuggestedLeafName && *inSuggestedLeafName)
SetLeafName(inSuggestedLeafName);
MakeUnique();
} // nsNativeFileSpec::MakeUnique
} // nsFileSpec::MakeUnique
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::MakeUnique()
void nsFileSpec::MakeUnique()
//----------------------------------------------------------------------------------------
{
if (!Exists())
@@ -497,51 +559,82 @@ void nsNativeFileSpec::MakeUnique()
if (*suffix)
delete [] suffix;
delete [] leafName;
} // nsNativeFileSpec::MakeUnique
} // nsFileSpec::MakeUnique
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const nsFileURL& inURL)
void nsFileSpec::operator = (const nsFileURL& inURL)
//----------------------------------------------------------------------------------------
{
*this = nsFilePath(inURL); // convert to unix path first
}
//----------------------------------------------------------------------------------------
void nsFileSpec::operator = (const nsPersistentFileDescriptor& inDescriptor)
//----------------------------------------------------------------------------------------
{
void* data;
PRInt32 dataSize;
inDescriptor.GetData(data, dataSize);
#ifdef XP_MAC
char* decodedData = PL_Base64Decode((const char*)data, (int)dataSize, nsnull);
// Cast to an alias record and resolve.
AliasHandle aliasH = nsnull;
mError = NS_FILE_RESULT(PtrToHand(decodedData, &(Handle)aliasH, (dataSize * 3) / 4));
PR_Free(decodedData);
if (NS_SUCCEEDED(mError))
return; // not enough memory?
Boolean changed;
mError = NS_FILE_RESULT(::ResolveAlias(nsnull, aliasH, &mSpec, &changed));
DisposeHandle((Handle) aliasH);
#else
nsFileSpecHelpers::StringAssign(mPath, (char*)data);
mError = NS_OK;
#endif
}
//========================================================================================
// UNIX & WIN nsNativeFileSpec implementation
// UNIX & WIN nsFileSpec implementation
//========================================================================================
#ifdef XP_UNIX
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath)
nsFileSpec::nsFileSpec(const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup((const char*)inPath))
, mError(NS_OK)
{
}
#endif // XP_UNIX
#ifdef XP_UNIX
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const nsFilePath& inPath)
void nsFileSpec::operator = (const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(mPath, (const char*)inPath);
mError = NS_OK;
}
#endif //XP_UNIX
#if defined(XP_UNIX) || defined(XP_PC)
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec)
nsFileSpec::nsFileSpec(const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inSpec.mPath))
, mError(NS_OK)
{
}
#endif //XP_UNIX
#if defined(XP_UNIX) || defined(XP_PC)
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs)
nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inString))
, mError(NS_OK)
{
// Make canonical and absolute.
nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
@@ -549,7 +642,7 @@ nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs)
#endif //XP_UNIX,PC
//----------------------------------------------------------------------------------------
nsNativeFileSpec::~nsNativeFileSpec()
nsFileSpec::~nsFileSpec()
//----------------------------------------------------------------------------------------
{
#ifndef XP_MAC
@@ -559,39 +652,160 @@ nsNativeFileSpec::~nsNativeFileSpec()
#if defined(XP_UNIX) || defined(XP_PC)
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const nsNativeFileSpec& inSpec)
void nsFileSpec::operator = (const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
{
mPath = nsFileSpecHelpers::StringAssign(mPath, inSpec.mPath);
mError = inSpec.Error();
}
#endif //XP_UNIX
#if defined(XP_UNIX) || defined(XP_PC)
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const char* inString)
void nsFileSpec::operator = (const char* inString)
//----------------------------------------------------------------------------------------
{
mPath = nsFileSpecHelpers::StringAssign(mPath, inString);
// Make canonical and absolute.
nsFileSpecHelpers::Canonify(mPath, true /* XXX? */);
nsFileSpecHelpers::Canonify(mPath, PR_TRUE /* XXX? */);
mError = NS_OK;
}
#endif //XP_UNIX
#if DEBUG
#if (defined(XP_UNIX) || defined(XP_PC))
//----------------------------------------------------------------------------------------
nsBasicOutStream& operator << (nsBasicOutStream& s, const nsNativeFileSpec& spec)
nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec)
//----------------------------------------------------------------------------------------
{
return (s << (const char*)spec.mPath);
}
#endif // DEBUG && XP_UNIX
#endif
//----------------------------------------------------------------------------------------
nsNativeFileSpec nsNativeFileSpec::operator + (const char* inRelativePath) const
nsFileSpec nsFileSpec::operator + (const char* inRelativePath) const
//----------------------------------------------------------------------------------------
{
nsNativeFileSpec result = *this;
nsFileSpec result = *this;
result += inRelativePath;
return result;
} // nsNativeFileSpec::operator +
} // nsFileSpec::operator +
//========================================================================================
// class nsPersistentFileDescriptor
//========================================================================================
//----------------------------------------------------------------------------------------
nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inDesc)
//----------------------------------------------------------------------------------------
: mDescriptorString(nsFileSpecHelpers::StringDup(inDesc.mDescriptorString))
{
} // nsPersistentFileDescriptor::nsPersistentFileDescriptor
//----------------------------------------------------------------------------------------
void nsPersistentFileDescriptor::operator = (const nsPersistentFileDescriptor& inDesc)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(mDescriptorString, inDesc.mDescriptorString);
} // nsPersistentFileDescriptor::operator =
//----------------------------------------------------------------------------------------
nsPersistentFileDescriptor::nsPersistentFileDescriptor(const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
: mDescriptorString(nsnull)
{
*this = inSpec;
} // nsPersistentFileDescriptor::nsPersistentFileDescriptor
//----------------------------------------------------------------------------------------
void nsPersistentFileDescriptor::operator = (const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
{
#ifdef XP_MAC
if (inSpec.Error())
return;
AliasHandle aliasH;
OSErr err = NewAlias(nil, inSpec.operator const FSSpec* const (), &aliasH);
if (err != noErr)
return;
PRUint32 bytes = GetHandleSize((Handle) aliasH);
HLock((Handle) aliasH);
char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull);
DisposeHandle((Handle) aliasH);
nsFileSpecHelpers::StringAssign(mDescriptorString, buf);
PR_Free(buf);
#else
nsFileSpecHelpers::StringAssign(mDescriptorString, inSpec);
#endif // XP_MAC
} // nsPersistentFileDescriptor::operator =
//----------------------------------------------------------------------------------------
nsPersistentFileDescriptor::~nsPersistentFileDescriptor()
//----------------------------------------------------------------------------------------
{
delete [] mDescriptorString;
} // nsPersistentFileDescriptor::~nsPersistentFileDescriptor
//----------------------------------------------------------------------------------------
void nsPersistentFileDescriptor::GetData(void*& outData, PRInt32& outSize) const
//----------------------------------------------------------------------------------------
{
outSize = PL_strlen(mDescriptorString);
outData = mDescriptorString;
}
//----------------------------------------------------------------------------------------
void nsPersistentFileDescriptor::SetData(const void* inData, PRInt32 inSize)
//----------------------------------------------------------------------------------------
{
delete [] mDescriptorString;
mDescriptorString = new char[1 + inSize];
if (!mDescriptorString)
return;
memcpy(mDescriptorString, inData, inSize);
mDescriptorString[inSize] = '\0';
}
#define MAX_PERSISTENT_DATA_SIZE 1000
//----------------------------------------------------------------------------------------
nsInputStream& operator >> (nsInputStream& s, nsPersistentFileDescriptor& d)
// reads the data from a file
//----------------------------------------------------------------------------------------
{
char bigBuffer[MAX_PERSISTENT_DATA_SIZE + 1];
// The first 8 bytes of the data should be a hex version of the data size to follow.
PRInt32 bytesRead = 8;
bytesRead = s.read(bigBuffer, bytesRead);
if (bytesRead != 8)
return (nsInputFileStream&)s;
bigBuffer[8] = '\0';
sscanf(bigBuffer, "%lx", &bytesRead);
if (bytesRead > MAX_PERSISTENT_DATA_SIZE)
return (nsInputFileStream&)s; // preposterous.
// Now we know how many bytes to read, do it.
s.read(bigBuffer, bytesRead);
d.SetData(bigBuffer, bytesRead);
return (nsInputFileStream&)s;
}
//----------------------------------------------------------------------------------------
nsOutputStream& operator << (nsOutputStream& s, const nsPersistentFileDescriptor& d)
// writes the data to a file
//----------------------------------------------------------------------------------------
{
char littleBuf[9];
PRInt32 dataSize;
void* data;
d.GetData(data, dataSize);
// First write (in hex) the length of the data to follow. Exactly 8 bytes
sprintf(littleBuf, "%0.8x", dataSize);
s << littleBuf;
// Now write the data itself
s << d.mDescriptorString;
return s;
}

View File

@@ -24,7 +24,16 @@
//
// Classes defined:
//
// nsFilePath, nsFileURL, nsNativeFileSpec.
// nsFilePath, nsFileURL, nsFileSpec, nsPersistentFileDescriptor.
//
// Q. How should I represent files at run time?
// A. Use nsFileSpec. Using char* will lose information on some platforms.
//
// Q. Then what are nsFilePath and nsFileURL for?
// A. Only when you need a char* parameter for legacy code.
//
// Q. How should I represent files in a persistent way (eg, in a disk file)?
// A. Use nsPersistentFileDescriptor. Convert to and from nsFileSpec at run time.
//
// This suite provides the following services:
//
@@ -63,7 +72,7 @@
//
// Initialize a native file spec from a URL
//
// nsNativeFileSpec fileSpec(fileURL);
// nsFileSpec fileSpec(fileURL);
//
// Make the spec unique (this one has no suffix).
//
@@ -103,6 +112,7 @@
#define _FILESPEC_H_
#include "nscore.h"
#include "nsError.h"
//========================================================================================
// Compiler-specific macros, as needed
@@ -116,11 +126,13 @@
#define NS_NAMESPACE_PROTOTYPE
#define NS_NAMESPACE namespace
#define NS_NAMESPACE_END
#define NS_EXPLICIT explicit
#else
#define NS_NAMESPACE_PROTOTYPE static
#define NS_NAMESPACE struct
#define NS_NAMESPACE_END ;
#define NS_EXPLICIT
#endif
//=========================== End Compiler-specific macros ===============================
@@ -137,33 +149,50 @@
// Here are the allowable ways to describe a file.
//========================================================================================
class nsFilePath; // This can be passed to NSPR file I/O routines.
class nsFileSpec; // Preferred. For i/o use nsInputFileStream, nsOutputFileStream
class nsFilePath; // This can be passed to NSPR file I/O routines, if you must.
class nsFileURL;
class nsNativeFileSpec;
class nsPersistentFileDescriptor; // Used for storage across program launches.
#define kFileURLPrefix "file://"
#define kFileURLPrefixLength (7)
class nsBasicOutStream;
class nsOutputStream;
class nsInputStream;
class nsOutputFileStream;
class nsInputFileStream;
//========================================================================================
class NS_BASE nsNativeFileSpec
// Conversion of native file errors to nsresult values. These are really only for use
// in the file module, clients of this interface shouldn't really need them.
// Error results returned from this interface have, in the low-order 16 bits,
// native errors that are masked to 16 bits. Assumption: a native error of 0 is success
// on all platforms. Note the way we define this using an inline function. This
// avoids multiple evaluation if people go NS_FILE_RESULT(function_call()).
#define NS_FILE_RESULT(x) ns_file_convert_result((PRInt32)x)
nsresult ns_file_convert_result(PRInt32 nativeErr);
#define NS_FILE_FAILURE NS_FILE_RESULT(-1)
//========================================================================================
class NS_BASE nsFileSpec
// This is whatever each platform really prefers to describe files as. Declared first
// because the other two types have an embeded nsNativeFileSpec object.
// because the other two types have an embeded nsFileSpec object.
//========================================================================================
{
public:
nsNativeFileSpec();
explicit nsNativeFileSpec(const char* inString, bool inCreateDirs = false);
explicit nsNativeFileSpec(const nsFilePath& inPath);
explicit nsNativeFileSpec(const nsFileURL& inURL);
nsNativeFileSpec(const nsNativeFileSpec& inPath);
virtual ~nsNativeFileSpec();
nsFileSpec();
NS_EXPLICIT nsFileSpec(const char* inString, PRBool inCreateDirs = PR_FALSE);
NS_EXPLICIT nsFileSpec(const nsFilePath& inPath);
NS_EXPLICIT nsFileSpec(const nsFileURL& inURL);
NS_EXPLICIT nsFileSpec(const nsPersistentFileDescriptor& inURL);
nsFileSpec(const nsFileSpec& inPath);
virtual ~nsFileSpec();
void operator = (const char* inPath);
void operator = (const nsFilePath& inPath);
void operator = (const nsFileURL& inURL);
void operator = (const nsNativeFileSpec& inOther);
void operator = (const nsFileSpec& inOther);
void operator = (const nsPersistentFileDescriptor& inOther);
#ifndef XP_MAC
operator const char* () const { return mPath; }
@@ -175,23 +204,22 @@ class NS_BASE nsNativeFileSpec
#ifdef XP_MAC
// For Macintosh people, this is meant to be useful in its own right as a C++ version
// of the FSSpec struct.
nsNativeFileSpec(
nsFileSpec(
short vRefNum,
long parID,
ConstStr255Param name);
nsNativeFileSpec(const FSSpec& inSpec)
: mSpec(inSpec), mError(noErr) {}
nsFileSpec(const FSSpec& inSpec)
: mSpec(inSpec), mError(NS_OK) {}
operator FSSpec* () { return &mSpec; }
operator const FSSpec* const () { return &mSpec; }
operator FSSpec& () { return mSpec; }
operator const FSSpec& () const { return mSpec; }
OSErr Error() const { return mError; }
void MakeAliasSafe();
// Called for the spec of an alias. Copies the alias to
// a secret temp directory and modifies the spec to point
// to it. Sets mError.
void ResolveAlias(bool& wasAliased);
void ResolveAlias(PRBool& wasAliased);
// Called for the spec of an alias. Modifies the spec to
// point to the original. Sets mError.
void MakeUnique(ConstStr255Param inSuggestedLeafName);
@@ -199,15 +227,15 @@ class NS_BASE nsNativeFileSpec
ConstStr255Param GetLeafPName() const { return mSpec.name; }
#endif // end of Macintosh utility methods.
#ifdef XP_MAC
bool Valid() const { return mError == noErr; }
#else
bool Valid() const { return true; } // Fixme.
#endif // XP_MAC
PRBool Valid() const { return NS_SUCCEEDED(Error()); }
nsresult Error() const { return mError; }
friend NS_BASE nsBasicOutStream& operator << (
nsBasicOutStream& s,
const nsNativeFileSpec& spec);
#if DEBUG
friend NS_BASE nsOutputStream& operator << (
nsOutputStream& s,
const nsFileSpec& spec); // THIS IS FOR DEBUGGING ONLY.
// see PersistentFileDescriptor for the real deal.
#endif
//--------------------------------------------------
// Queries and path algebra. These do not modify the disk.
@@ -218,7 +246,7 @@ class NS_BASE nsNativeFileSpec
// inLeafName can be a relative path, so this allows
// one kind of concatenation of "paths".
void GetParent(nsNativeFileSpec& outSpec) const;
void GetParent(nsFileSpec& outSpec) const;
// Return the filespec of the parent directory. Used
// in conjunction with GetLeafName(), this lets you
// parse a path into a list of node names. Beware,
@@ -226,7 +254,7 @@ class NS_BASE nsNativeFileSpec
// but a spec. Volumes on Macintosh can have identical
// names. Perhaps could be used for an operator --() ?
nsNativeFileSpec operator + (const char* inRelativePath) const;
nsFileSpec operator + (const char* inRelativePath) const;
void operator += (const char* inRelativePath);
// Concatenate the relative path to this directory.
// Used for constructing the filespec of a descendant.
@@ -240,19 +268,24 @@ class NS_BASE nsNativeFileSpec
void MakeUnique();
void MakeUnique(const char* inSuggestedLeafName);
bool IsDirectory() const;
PRBool IsDirectory() const;
// More stringent than Exists()
bool IsFile() const;
PRBool IsFile() const;
// More stringent than Exists()
bool Exists() const;
PRBool Exists() const;
//--------------------------------------------------
// Creation and deletion of objects. These can modify the disk.
//--------------------------------------------------
void CreateDirectory(int mode = 0700 /* for unix */);
void Delete(bool inRecursive);
void Delete(PRBool inRecursive);
nsresult Rename(const char* inNewName); // not const: gets updated
nsresult Copy(const nsFileSpec& inNewParentDirectory) const;
nsresult Move(const nsFileSpec& inNewParentDirectory) const;
nsresult Execute(const char* args) const;
//--------------------------------------------------
// Data
//--------------------------------------------------
@@ -261,11 +294,15 @@ class NS_BASE nsNativeFileSpec
friend class nsFilePath;
#ifdef XP_MAC
FSSpec mSpec;
OSErr mError;
#else
char* mPath;
#endif
}; // class nsNativeFileSpec
nsresult mError;
}; // class nsFileSpec
// FOR HISTORICAL REASONS:
typedef nsFileSpec nsNativeFileSpec;
//========================================================================================
class NS_BASE nsFileURL
@@ -276,9 +313,9 @@ class NS_BASE nsFileURL
{
public:
nsFileURL(const nsFileURL& inURL);
explicit nsFileURL(const char* inString, bool inCreateDirs = false);
explicit nsFileURL(const nsFilePath& inPath);
explicit nsFileURL(const nsNativeFileSpec& inPath);
NS_EXPLICIT nsFileURL(const char* inString, PRBool inCreateDirs = PR_FALSE);
NS_EXPLICIT nsFileURL(const nsFilePath& inPath);
NS_EXPLICIT nsFileURL(const nsFileSpec& inPath);
virtual ~nsFileURL();
// nsString GetString() const { return mPath; }
@@ -288,14 +325,14 @@ class NS_BASE nsFileURL
void operator = (const nsFileURL& inURL);
void operator = (const char* inString);
void operator = (const nsFilePath& inOther);
void operator = (const nsNativeFileSpec& inOther);
void operator = (const nsFileSpec& inOther);
friend NS_BASE nsBasicOutStream& operator << (
nsBasicOutStream& s, const nsFileURL& spec);
friend NS_BASE nsOutputStream& operator << (
nsOutputStream& s, const nsFileURL& spec);
#ifdef XP_MAC
// Accessor to allow quick assignment to a mNativeFileSpec
const nsNativeFileSpec& GetNativeSpec() const { return mNativeFileSpec; }
// Accessor to allow quick assignment to a mFileSpec
const nsFileSpec& GetFileSpec() const { return mFileSpec; }
#endif
private:
// Should not be defined (only nsFilePath is to be treated as strings.
@@ -306,8 +343,8 @@ class NS_BASE nsFileURL
char* mURL;
#ifdef XP_MAC
// Since the path on the macintosh does not uniquely specify a file (volumes
// can have the same name), stash the secret nsNativeFileSpec, too.
nsNativeFileSpec mNativeFileSpec;
// can have the same name), stash the secret nsFileSpec, too.
nsFileSpec mFileSpec;
#endif
}; // class nsFileURL
@@ -319,9 +356,9 @@ class NS_BASE nsFilePath
{
public:
nsFilePath(const nsFilePath& inPath);
explicit nsFilePath(const char* inString, bool inCreateDirs = false);
explicit nsFilePath(const nsFileURL& inURL);
explicit nsFilePath(const nsNativeFileSpec& inPath);
NS_EXPLICIT nsFilePath(const char* inString, PRBool inCreateDirs = PR_FALSE);
NS_EXPLICIT nsFilePath(const nsFileURL& inURL);
NS_EXPLICIT nsFilePath(const nsFileSpec& inPath);
virtual ~nsFilePath();
@@ -337,12 +374,12 @@ class NS_BASE nsFilePath
void operator = (const nsFilePath& inPath);
void operator = (const char* inString);
void operator = (const nsFileURL& inURL);
void operator = (const nsNativeFileSpec& inOther);
void operator = (const nsFileSpec& inOther);
#ifdef XP_MAC
public:
// Accessor to allow quick assignment to a mNativeFileSpec
const nsNativeFileSpec& GetNativeSpec() const { return mNativeFileSpec; }
// Accessor to allow quick assignment to a mFileSpec
const nsFileSpec& GetFileSpec() const { return mFileSpec; }
#endif
private:
@@ -350,26 +387,59 @@ class NS_BASE nsFilePath
char* mPath;
#ifdef XP_MAC
// Since the path on the macintosh does not uniquely specify a file (volumes
// can have the same name), stash the secret nsNativeFileSpec, too.
nsNativeFileSpec mNativeFileSpec;
// can have the same name), stash the secret nsFileSpec, too.
nsFileSpec mFileSpec;
#endif
}; // class nsFilePath
//========================================================================================
class NS_BASE nsPersistentFileDescriptor
//========================================================================================
{
public:
nsPersistentFileDescriptor() : mDescriptorString(nsnull) {}
// For use prior to reading in from a stream
nsPersistentFileDescriptor(const nsPersistentFileDescriptor& inPath);
virtual ~nsPersistentFileDescriptor();
void operator = (const nsPersistentFileDescriptor& inPath);
// Conversions
nsPersistentFileDescriptor(const nsFileSpec& inPath);
void operator = (const nsFileSpec& inPath);
friend NS_BASE nsInputStream& operator >> (nsInputStream&, nsPersistentFileDescriptor&);
// reads the data from a file
friend NS_BASE nsOutputStream& operator << (nsOutputStream&, const nsPersistentFileDescriptor&);
// writes the data to a file
friend class nsFileSpec;
private:
// Here are the ways to get data in and out of a file.
void GetData(void*& outData, PRInt32& outSize) const;
// DON'T FREE the returned data!
void SetData(const void* inData, PRInt32 inSize);
private:
char* mDescriptorString;
}; // class nsPersistentFileDescriptor
//========================================================================================
class NS_BASE nsDirectoryIterator
// Example:
//
// nsNativeFileSpec parentDir(...); // directory over whose children we shall iterate
// nsFileSpec parentDir(...); // directory over whose children we shall iterate
// for (nsDirectoryIterator i(parentDir); i; i++)
// {
// // do something with (const nsNativeFileSpec&)i
// // do something with (const nsFileSpec&)i
// }
//
// or:
//
// for (nsDirectoryIterator i(parentDir, false); i; i--)
// for (nsDirectoryIterator i(parentDir, PR_FALSE); i; i--)
// {
// // do something with (const nsNativeFileSpec&)i
// // do something with (const nsFileSpec&)i
// }
//
// Currently, the only platform on which backwards iteration actually goes backwards
@@ -378,21 +448,21 @@ class NS_BASE nsDirectoryIterator
{
public:
nsDirectoryIterator(
const nsNativeFileSpec& parent,
const nsFileSpec& parent,
int iterateDirection = +1);
#ifndef XP_MAC
// Macintosh currently doesn't allocate, so needn't clean up.
virtual ~nsDirectoryIterator();
#endif
operator bool() const { return mExists; }
PRBool Exists() const { return mExists; }
nsDirectoryIterator& operator ++(); // moves to the next item, if any.
nsDirectoryIterator& operator ++(int) { return ++(*this); } // post-increment.
nsDirectoryIterator& operator --(); // moves to the previous item, if any.
nsDirectoryIterator& operator --(int) { return --(*this); } // post-decrement.
operator nsNativeFileSpec&() { return mCurrent; }
operator nsFileSpec&() { return mCurrent; }
private:
nsNativeFileSpec mCurrent;
bool mExists;
nsFileSpec mCurrent;
bool mExists; // MUST be bool.
#if defined(XP_UNIX)
DIR* mDir;

View File

@@ -28,6 +28,7 @@
#include <Folders.h>
#include <Errors.h>
#include <TextUtils.h>
#include <Processes.h>
const unsigned char* kAliasHavenFolderName = "\pnsAliasHaven";
@@ -74,7 +75,7 @@ namespace MacFileHelpers
// to support attaching of aliases in mail.
void EnsureAliasHaven();
void SetNoResolve(Boolean inResolve);
bool IsAliasSafe(const FSSpec& inSpec);
PRBool IsAliasSafe(const FSSpec& inSpec);
OSErr MakeAliasSafe(FSSpec& inOutSpec);
OSErr ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased);
@@ -131,8 +132,8 @@ char* MacFileHelpers::EncodeMacPath(
// Method: Swap ':' and '/', hex escape the result
//-----------------------------------
{
if (inPath == NULL)
return NULL;
if (inPath == nsnull)
return nsnull;
int pathSize = strlen(inPath);
// XP code sometimes chokes if there's a final slash in the unix path.
@@ -145,8 +146,8 @@ char* MacFileHelpers::EncodeMacPath(
pathSize--;
}
char * newPath = NULL;
char * finalPath = NULL;
char * newPath = nsnull;
char * finalPath = nsnull;
if (prependSlash)
{
@@ -188,10 +189,10 @@ OSErr MacFileHelpers::MakeAliasSafe(FSSpec& inOutSpec)
//----------------------------------------------------------------------------------------
{
EnsureAliasHaven();
nsNativeFileSpec dstDirSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\p");
nsFileSpec dstDirSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\p");
// Make sure its name is unique
nsNativeFileSpec havenSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\pG'day");
nsFileSpec havenSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\pG'day");
if (havenSpec.Valid())
havenSpec.MakeUnique(inOutSpec.name);
// Copy the file into the haven directory
@@ -221,9 +222,9 @@ char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath)
{
char* dst = result;
const char* src = unixPath;
if (*src == '/') // ¥ full path
if (*src == '/') // * full path
src++;
else if (strchr(src, '/')) // ¥ partial path, and not just a leaf name
else if (strchr(src, '/')) // * partial path, and not just a leaf name
*dst++ = ':';
strcpy(dst, src);
nsUnescape(dst); // Hex Decode
@@ -346,7 +347,7 @@ void MacFileHelpers::EnsureAliasHaven()
} // MacFileHelpers::EnsureAliasHaven
//----------------------------------------------------------------------------------------
bool MacFileHelpers::IsAliasSafe(const FSSpec& inSpec)
PRBool MacFileHelpers::IsAliasSafe(const FSSpec& inSpec)
// Returns true if the alias is in the alias haven directory, or if alias resolution
// has been turned off.
//----------------------------------------------------------------------------------------
@@ -379,7 +380,7 @@ OSErr MacFileHelpers::FSSpecFromFullUnixPath(
// then it is combined with inOutSpec's vRefNum and parID to form a new spec.
//-----------------------------------
{
if (unixPath == NULL)
if (unixPath == nsnull)
return badFidErr;
char* macPath = MacPathFromUnixPath(unixPath);
if (!macPath)
@@ -413,7 +414,7 @@ char* MacFileHelpers::PathNameFromFSSpec( const FSSpec& inSpec, Boolean wantLeaf
OSErr err = noErr;
short fullPathLength = 0;
Handle fullPath = NULL;
Handle fullPath = nsnull;
FSSpec tempSpec = inSpec;
if ( tempSpec.parID == fsRtParID )
@@ -471,7 +472,7 @@ char* MacFileHelpers::PathNameFromFSSpec( const FSSpec& inSpec, Boolean wantLeaf
tempSpec.name[tempSpec.name[0]] = ':';
/* Add directory name to beginning of fullPath */
(void) Munger(fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]);
(void) Munger(fullPath, 0, nsnull, 0, &tempSpec.name[1], tempSpec.name[0]);
err = MemError();
}
} while ( err == noErr && pb.dirInfo.ioDrDirID != fsRtDirID );
@@ -500,19 +501,19 @@ Clean:
} // MacFileHelpers::PathNameFromFSSpec
//========================================================================================
// Macintosh nsNativeFileSpec implementation
// Macintosh nsFileSpec implementation
//========================================================================================
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec()
nsFileSpec::nsFileSpec()
//----------------------------------------------------------------------------------------
: mError(noErr)
: mError(NS_OK)
{
mSpec.name[0] = '\0';
}
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec)
nsFileSpec::nsFileSpec(const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
: mSpec(inSpec.mSpec)
, mError(inSpec.Error())
@@ -520,87 +521,90 @@ nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec)
}
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs)
nsFileSpec::nsFileSpec(const char* inString, PRBool inCreateDirs)
//----------------------------------------------------------------------------------------
{
mError = MacFileHelpers::FSSpecFromFullUnixPath(
inString, mSpec, true, true, inCreateDirs);
mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromFullUnixPath(
inString, mSpec, false, true, inCreateDirs));
// allow a partial path, create as necessary
if (mError == fnfErr)
mError = noErr;
} // nsNativeFileSpec::nsNativeFileSpec
if (mError == NS_FILE_RESULT(fnfErr))
mError = NS_OK;
} // nsFileSpec::nsFileSpec
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(
nsFileSpec::nsFileSpec(
short vRefNum,
long parID,
ConstStr255Param name)
//----------------------------------------------------------------------------------------
{
mError = ::FSMakeFSSpec(vRefNum, parID, name, &mSpec);
if (mError == fnfErr)
mError = NS_FILE_RESULT(::FSMakeFSSpec(vRefNum, parID, name, &mSpec));
if (mError == NS_FILE_RESULT(fnfErr))
mError = noErr;
}
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath)
nsFileSpec::nsFileSpec(const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
{
*this = inPath.GetNativeSpec();
*this = inPath.GetFileSpec();
}
#if DEBUG
//----------------------------------------------------------------------------------------
nsBasicOutStream& operator << (nsBasicOutStream& s, const nsNativeFileSpec& spec)
nsOutputStream& operator << (nsOutputStream& s, const nsFileSpec& spec)
//----------------------------------------------------------------------------------------
{
s << spec.mSpec.vRefNum << ", " << spec.mSpec.parID << ", \"";
s.write((const char*)&spec.mSpec.name[1], spec.mSpec.name[0]);
return s << "\"";
} // nsOutputFileStream& operator << (nsOutputFileStream&, const nsNativeFileSpec&)
} // nsOutputStream& operator << (nsOutputStream&, const nsFileSpec&)
#endif
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const char* inString)
void nsFileSpec::operator = (const char* inString)
//----------------------------------------------------------------------------------------
{
mError = MacFileHelpers::FSSpecFromFullUnixPath(inString, mSpec, true);
} // nsNativeFileSpec::operator =
mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromFullUnixPath(inString, mSpec, false));
} // nsFileSpec::operator =
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const nsNativeFileSpec& inSpec)
void nsFileSpec::operator = (const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
{
mSpec = inSpec.mSpec;
mError = inSpec.Error();
} // nsNativeFileSpec::operator =
} // nsFileSpec::operator =
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const nsFilePath& inPath)
void nsFileSpec::operator = (const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
{
*this = inPath.GetNativeSpec();
} // nsNativeFileSpec::operator =
*this = inPath.GetFileSpec();
} // nsFileSpec::operator =
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::Exists() const
PRBool nsFileSpec::Exists() const
//----------------------------------------------------------------------------------------
{
FSSpec temp;
return ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &temp) == noErr;
} // nsNativeFileSpec::operator =
} // nsFileSpec::operator =
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::SetLeafName(const char* inLeafName)
void nsFileSpec::SetLeafName(const char* inLeafName)
// In leaf name can actually be a partial path...
//----------------------------------------------------------------------------------------
{
// what about long relative paths? Hmm?
Str255 partialPath;
MacFileHelpers::PLstrcpy(partialPath, inLeafName);
mError = FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec);
} // nsNativeFileSpec::SetLeafName
mError = NS_FILE_RESULT(
::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec));
} // nsFileSpec::SetLeafName
//----------------------------------------------------------------------------------------
char* nsNativeFileSpec::GetLeafName() const
char* nsFileSpec::GetLeafName() const
// Result needs to be delete[]ed.
//----------------------------------------------------------------------------------------
{
@@ -608,133 +612,206 @@ char* nsNativeFileSpec::GetLeafName() const
memcpy(leaf, &mSpec.name[1], mSpec.name[0]);
leaf[mSpec.name[0]] = '\0';
return nsFileSpecHelpers::StringDup(leaf);
} // nsNativeFileSpec::GetLeafName
} // nsFileSpec::GetLeafName
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::MakeAliasSafe()
void nsFileSpec::MakeAliasSafe()
//----------------------------------------------------------------------------------------
{
mError = MacFileHelpers::MakeAliasSafe(mSpec);
} // nsNativeFileSpec::MakeAliasSafe
mError = NS_FILE_RESULT(MacFileHelpers::MakeAliasSafe(mSpec));
} // nsFileSpec::MakeAliasSafe
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName)
void nsFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName)
//----------------------------------------------------------------------------------------
{
if (inSuggestedLeafName[0] > 0)
MacFileHelpers::PLstrcpy(mSpec.name, inSuggestedLeafName);
MakeUnique();
} // nsNativeFileSpec::MakeUnique
} // nsFileSpec::MakeUnique
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::ResolveAlias(bool& wasAliased)
void nsFileSpec::ResolveAlias(PRBool& wasAliased)
//----------------------------------------------------------------------------------------
{
Boolean wasAliased2;
mError = MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2);
mError = NS_FILE_RESULT(MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2));
wasAliased = (wasAliased2 != false);
} // nsNativeFileSpec::ResolveAlias
} // nsFileSpec::ResolveAlias
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsFile() const
PRBool nsFileSpec::IsFile() const
//----------------------------------------------------------------------------------------
{
long dirID;
Boolean isDirectory;
return (noErr == FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && !isDirectory);
} // nsNativeFileSpec::IsFile
} // nsFileSpec::IsFile
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsDirectory() const
PRBool nsFileSpec::IsDirectory() const
//----------------------------------------------------------------------------------------
{
long dirID;
Boolean isDirectory;
return (noErr == FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && isDirectory);
} // nsNativeFileSpec::IsDirectory
} // nsFileSpec::IsDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const
void nsFileSpec::GetParent(nsFileSpec& outSpec) const
//----------------------------------------------------------------------------------------
{
if (mError == noErr)
outSpec.mError = FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, NULL, outSpec);
} // nsNativeFileSpec::GetParent
if (NS_SUCCEEDED(mError))
outSpec.mError
= NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, nsnull, outSpec));
} // nsFileSpec::GetParent
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator += (const char* inRelativePath)
void nsFileSpec::operator += (const char* inRelativePath)
//----------------------------------------------------------------------------------------
{
long dirID;
Boolean isDirectory;
mError = FSpGetDirectoryID(&mSpec, &dirID, &isDirectory);
if (mError == noErr && isDirectory)
mError = NS_FILE_RESULT(::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory));
if (NS_SUCCEEDED(mError) && isDirectory)
{
Str255 partialPath;
MacFileHelpers::PLstrcpy(partialPath, inRelativePath);
mError = FSMakeFSSpec(mSpec.vRefNum, dirID, partialPath, *this);
//if (mError == noErr)
mError = NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, dirID, partialPath, *this));
//if (NS_SUCCEEDED(mError))
// SetLeafName(inRelativePath);
}
} // nsNativeFileSpec::operator +=
} // nsFileSpec::operator +=
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::CreateDirectory(int /* unix mode */)
void nsFileSpec::CreateDirectory(int /* unix mode */)
//----------------------------------------------------------------------------------------
{
long ignoredDirID;
FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID);
} // nsNativeFileSpec::CreateDirectory
} // nsFileSpec::CreateDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::Delete(bool inRecursive)
void nsFileSpec::Delete(PRBool inRecursive)
//----------------------------------------------------------------------------------------
{
if (inRecursive)
{
// MoreFilesExtras
mError = DeleteDirectory(
mError = NS_FILE_RESULT(::DeleteDirectory(
mSpec.vRefNum,
mSpec.parID,
const_cast<unsigned char*>(mSpec.name));
const_cast<unsigned char*>(mSpec.name)));
}
else
mError = FSpDelete(&mSpec);
} // nsNativeFileSpec::Delete
mError = NS_FILE_RESULT(FSpDelete(&mSpec));
} // nsFileSpec::Delete
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Rename(const char* inNewName)
//----------------------------------------------------------------------------------------
{
if (strchr(inNewName, '/'))
return -1; // no relative paths here!
Str255 pName;
MacFileHelpers::PLstrcpy(pName, inNewName);
if (FSpRename(&mSpec, pName) != noErr)
return -1;
SetLeafName(inNewName);
return 0;
} // nsFileSpec::Rename
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Copy(const nsFileSpec& newParentDir) const
//----------------------------------------------------------------------------------------
{
// We can only copy into a directory, and (for now) can not copy entire directories
if (!newParentDir.IsDirectory() || (IsDirectory() ) )
return NS_FILE_FAILURE;
nsresult result = NS_FILE_RESULT(::FSpFileCopy( &mSpec,
&newParentDir.mSpec,
const_cast<StringPtr>(GetLeafPName()),
nsnull,
0,
true));
return result;
} // nsFileSpec::Copy
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Move(const nsFileSpec& newParentDir) const
//----------------------------------------------------------------------------------------
{
// We can only move into a directory
if (!newParentDir.IsDirectory())
return NS_FILE_FAILURE;
nsresult result = NS_FILE_RESULT(::FSpMoveRenameCompat(&mSpec,
&newParentDir.mSpec,
const_cast<StringPtr>(GetLeafPName())));
return result;
} // nsFileSpec::Move
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Execute(const char* /*args - how can this be cross-platform? problem! */ ) const
//----------------------------------------------------------------------------------------
{
if (IsDirectory())
return NS_FILE_FAILURE;
LaunchParamBlockRec launchThis;
launchThis.launchAppSpec = const_cast<FSSpec*>(&mSpec);
launchThis.launchAppParameters = nsnull; // args;
/* launch the thing */
launchThis.launchBlockID = extendedBlock;
launchThis.launchEPBLength = extendedBlockLen;
launchThis.launchFileFlags = nsnull;
launchThis.launchControlFlags = launchContinue + launchNoFileFlags + launchUseMinimum;
launchThis.launchControlFlags += launchDontSwitch;
nsresult result = NS_FILE_RESULT(::LaunchApplication(&launchThis));
return result;
} // nsFileSpec::Execute
//========================================================================================
// Macintosh nsFilePath implementation
//========================================================================================
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const char* inString, bool inCreateDirs)
nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs)
//----------------------------------------------------------------------------------------
: mPath(nsnull)
, mNativeFileSpec(inString, inCreateDirs)
, mFileSpec(inString, inCreateDirs)
{
// Make canonical and absolute.
char * path = MacFileHelpers::PathNameFromFSSpec( mNativeFileSpec, TRUE );
char * path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE );
mPath = MacFileHelpers::EncodeMacPath(path, true, true);
}
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const nsNativeFileSpec& inSpec)
nsFilePath::nsFilePath(const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
: mNativeFileSpec(inSpec)
: mFileSpec(inSpec)
{
char * path = MacFileHelpers::PathNameFromFSSpec( inSpec.mSpec, TRUE );
mPath = MacFileHelpers::EncodeMacPath(path, true, true);
}
//----------------------------------------------------------------------------------------
void nsFilePath::operator = (const nsNativeFileSpec& inSpec)
void nsFilePath::operator = (const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
{
delete [] mPath;
char * path = MacFileHelpers::PathNameFromFSSpec( inSpec.mSpec, TRUE );
mPath = MacFileHelpers::EncodeMacPath(path, true, true);
mNativeFileSpec = inSpec;
mFileSpec = inSpec;
} // nsFilePath::operator =
//========================================================================================
@@ -742,14 +819,14 @@ void nsFilePath::operator = (const nsNativeFileSpec& inSpec)
//========================================================================================
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const char* inString, bool inCreateDirs)
nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs)
//----------------------------------------------------------------------------------------
: mURL(nsnull)
, mNativeFileSpec(inString + kFileURLPrefixLength, inCreateDirs)
, mFileSpec(inString + kFileURLPrefixLength, inCreateDirs)
{
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
// Make canonical and absolute.
char* path = MacFileHelpers::PathNameFromFSSpec( mNativeFileSpec, TRUE );
char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec, TRUE );
char* escapedPath = MacFileHelpers::EncodeMacPath(path, true, true);
mURL = nsFileSpecHelpers::StringDup(kFileURLPrefix, kFileURLPrefixLength + strlen(escapedPath));
strcat(mURL, escapedPath);
@@ -762,7 +839,7 @@ nsFileURL::nsFileURL(const char* inString, bool inCreateDirs)
//----------------------------------------------------------------------------------------
nsDirectoryIterator::nsDirectoryIterator(
const nsNativeFileSpec& inDirectory
const nsFileSpec& inDirectory
, int inIterateDirection)
//----------------------------------------------------------------------------------------
: mCurrent(inDirectory)
@@ -772,7 +849,7 @@ nsDirectoryIterator::nsDirectoryIterator(
CInfoPBRec pb;
DirInfo* dipb = (DirInfo*)&pb;
// Sorry about this, there seems to be a bug in CWPro 4:
const FSSpec& inSpec = inDirectory.nsNativeFileSpec::operator const FSSpec&();
const FSSpec& inSpec = inDirectory.nsFileSpec::operator const FSSpec&();
Str255 outName;
MacFileHelpers::PLstrcpy(outName, inSpec.name);
pb.hFileInfo.ioNamePtr = outName;
@@ -786,7 +863,7 @@ nsDirectoryIterator::nsDirectoryIterator(
if ( (err != noErr ) || !( dipb->ioFlAttrib & 0x0010 ) )
return;
// Sorry about this, there seems to be a bug in CWPro 4:
FSSpec& currentSpec = mCurrent.nsNativeFileSpec::operator FSSpec&();
FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&();
currentSpec.vRefNum = inSpec.vRefNum;
currentSpec.parID = dipb->ioDrDirID;
mMaxIndex = pb.dirInfo.ioDrNmFls;
@@ -809,10 +886,10 @@ OSErr nsDirectoryIterator::SetToIndex()
CInfoPBRec cipb;
DirInfo *dipb=(DirInfo *)&cipb;
Str255 objectName;
dipb->ioCompletion = NULL;
dipb->ioCompletion = nsnull;
dipb->ioFDirIndex = mIndex;
// Sorry about this, there seems to be a bug in CWPro 4:
FSSpec& currentSpec = mCurrent.nsNativeFileSpec::operator FSSpec&();
FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&();
dipb->ioVRefNum = currentSpec.vRefNum; /* Might need to use vRefNum, not sure*/
dipb->ioDrDirID = currentSpec.parID;
dipb->ioNamePtr = objectName;

View File

@@ -25,9 +25,10 @@
#include <dirent.h>
#include <unistd.h>
#include <stdlib.h>
#include "nsError.h"
//----------------------------------------------------------------------------------------
void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs)
void nsFileSpecHelpers::Canonify(char*& ioPath, PRBool inMakeDirs)
// Canonify, make absolute, and check whether directories exist
//----------------------------------------------------------------------------------------
{
@@ -76,75 +77,78 @@ void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs)
} // nsFileSpecHelpers::Canonify
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::SetLeafName(const char* inLeafName)
void nsFileSpec::SetLeafName(const char* inLeafName)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::LeafReplace(mPath, '/', inLeafName);
} // nsNativeFileSpec::SetLeafName
} // nsFileSpec::SetLeafName
//----------------------------------------------------------------------------------------
char* nsNativeFileSpec::GetLeafName() const
char* nsFileSpec::GetLeafName() const
//----------------------------------------------------------------------------------------
{
return nsFileSpecHelpers::GetLeaf(mPath, '/');
} // nsNativeFileSpec::GetLeafName
} // nsFileSpec::GetLeafName
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::Exists() const
PRBool nsFileSpec::Exists() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st);
} // nsNativeFileSpec::Exists
} // nsFileSpec::Exists
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsFile() const
PRBool nsFileSpec::IsFile() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && S_ISREG(st.st_mode);
} // nsNativeFileSpec::IsFile
} // nsFileSpec::IsFile
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsDirectory() const
PRBool nsFileSpec::IsDirectory() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && S_ISDIR(st.st_mode);
} // nsNativeFileSpec::IsDirectory
} // nsFileSpec::IsDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const
void nsFileSpec::GetParent(nsFileSpec& outSpec) const
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(outSpec.mPath, mPath);
char* cp = strrchr(outSpec.mPath, '/');
if (cp)
*cp = '\0';
} // nsNativeFileSpec::GetParent
} // nsFileSpec::GetParent
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator += (const char* inRelativePath)
void nsFileSpec::operator += (const char* inRelativePath)
//----------------------------------------------------------------------------------------
{
if (!inRelativePath || !mPath)
return;
if (mPath[strlen(mPath) - 1] != '/')
char* newPath = nsFileSpecHelpers::ReallocCat(mPath, "/");
char endChar = mPath[strlen(mPath) - 1];
if (endChar == '/')
nsFileSpecHelpers::ReallocCat(mPath, "x");
else
nsFileSpecHelpers::ReallocCat(mPath, "/x");
SetLeafName(inRelativePath);
} // nsNativeFileSpec::operator +=
} // nsFileSpec::operator +=
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::CreateDirectory(int mode)
void nsFileSpec::CreateDirectory(int mode)
//----------------------------------------------------------------------------------------
{
// Note that mPath is canonical!
mkdir(mPath, mode);
} // nsNativeFileSpec::CreateDirectory
} // nsFileSpec::CreateDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::Delete(bool inRecursive)
void nsFileSpec::Delete(PRBool inRecursive)
// To check if this worked, call Exists() afterwards, see?
//----------------------------------------------------------------------------------------
{
@@ -152,9 +156,9 @@ void nsNativeFileSpec::Delete(bool inRecursive)
{
if (inRecursive)
{
for (nsDirectoryIterator i(*this); i; i++)
for (nsDirectoryIterator i(*this); i.Exists(); i++)
{
nsNativeFileSpec& child = (nsNativeFileSpec&)i;
nsFileSpec& child = (nsFileSpec&)i;
child.Delete(inRecursive);
}
}
@@ -162,7 +166,148 @@ void nsNativeFileSpec::Delete(bool inRecursive)
}
else
remove(mPath);
} // nsNativeFileSpec::Delete
} // nsFileSpec::Delete
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Rename(const char* inNewName)
//----------------------------------------------------------------------------------------
{
// This function should not be used to move a file on disk.
if (strchr(inNewName, '/'))
return NS_FILE_FAILURE;
if (PR_Rename(mPath, inNewName) != 0)
{
return NS_FILE_FAILURE;
}
SetLeafName(inNewName);
return NS_OK;
} // nsFileSpec::Rename
static int CrudeFileCopy(const char* in, const char* out)
{
struct stat in_stat;
int stat_result = -1;
char buf [1024];
FILE *ifp, *ofp;
int rbytes, wbytes;
if (!in || !out)
return -1;
stat_result = stat (in, &in_stat);
ifp = fopen (in, "r");
if (!ifp)
{
return -1;
}
ofp = fopen (out, "w");
if (!ofp)
{
fclose (ifp);
return -1;
}
while ((rbytes = fread (buf, 1, sizeof(buf), ifp)) > 0)
{
while (rbytes > 0)
{
if ( (wbytes = fwrite (buf, 1, rbytes, ofp)) < 0 )
{
fclose (ofp);
fclose (ifp);
unlink(out);
return -1;
}
rbytes -= wbytes;
}
}
fclose (ofp);
fclose (ifp);
if (stat_result == 0)
{
chmod (out, in_stat.st_mode & 0777);
}
return 0;
} // nsFileSpec::Rename
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Copy(const nsFileSpec& inParentDirectory) const
//----------------------------------------------------------------------------------------
{
// We can only copy into a directory, and (for now) can not copy entire directories
nsresult result = NS_FILE_FAILURE;
if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
{
char *leafname = GetLeafName();
char* destPath = nsFileSpecHelpers::StringDup(inParentDirectory, ( strlen(inParentDirectory) + 1 + strlen(leafname) ) );
strcat(destPath, "/");
strcat(destPath, leafname);
delete [] leafname;
result = NS_FILE_RESULT(CrudeFileCopy(*this, destPath));
delete [] destPath;
}
return result;
} // nsFileSpec::Copy
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Move(const nsFileSpec& inNewParentDirectory) const
//----------------------------------------------------------------------------------------
{
// We can only copy into a directory, and (for now) can not copy entire directories
nsresult result = NS_FILE_FAILURE;
if (inNewParentDirectory.IsDirectory() && (! IsDirectory() ) )
{
char *leafname = GetLeafName();
char* destPath
= nsFileSpecHelpers::StringDup(
inNewParentDirectory,
strlen(inNewParentDirectory) + 1 + strlen(leafname));
strcat(destPath, "/");
strcat(destPath, leafname);
delete [] leafname;
result = NS_FILE_RESULT(CrudeFileCopy(*this, destPath));
if (result == NS_OK)
{
Delete(PR_FALSE);
}
delete [] destPath;
}
return result;
}
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Execute(const char* inArgs ) const
//----------------------------------------------------------------------------------------
{
nsresult result = NS_FILE_FAILURE;
if (! IsDirectory())
{
char* fileNameWithArgs
= nsFileSpecHelpers::StringDup(mPath, strlen(mPath) + 1 + strlen(inArgs));
strcat(fileNameWithArgs, " ");
strcat(fileNameWithArgs, inArgs);
result = NS_FILE_RESULT(system(fileNameWithArgs));
delete [] fileNameWithArgs;
}
return result;
} // nsFileSpec::Execute
//========================================================================================
// nsDirectoryIterator
@@ -170,7 +315,7 @@ void nsNativeFileSpec::Delete(bool inRecursive)
//----------------------------------------------------------------------------------------
nsDirectoryIterator::nsDirectoryIterator(
const nsNativeFileSpec& inDirectory
const nsFileSpec& inDirectory
, int inIterateDirection)
//----------------------------------------------------------------------------------------
: mCurrent(inDirectory)

View File

@@ -23,9 +23,18 @@
#include <direct.h>
#include <stdlib.h>
#include "prio.h"
#include "nsError.h"
#include "windows.h"
#ifdef UNICODE
#define CreateDirectoryW CreateDirectory
#else
#define CreateDirectoryA CreateDirectory
#endif
//----------------------------------------------------------------------------------------
void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs)
void nsFileSpecHelpers::Canonify(char*& ioPath, PRBool inMakeDirs)
// Canonify, make absolute, and check whether directories exist. This
// takes a (possibly relative) native path and converts it into a
// fully qualified native path.
@@ -125,7 +134,7 @@ void nsFileSpecHelpers::NativeToUnix(char*& ioPath)
}
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath)
nsFileSpec::nsFileSpec(const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
: mPath(NULL)
{
@@ -133,15 +142,16 @@ nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath)
}
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator = (const nsFilePath& inPath)
void nsFileSpec::operator = (const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(mPath, (const char*)inPath);
nsFileSpecHelpers::UnixToNative(mPath);
} // nsNativeFileSpec::operator =
mError = NS_OK;
} // nsFileSpec::operator =
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const nsNativeFileSpec& inSpec)
nsFilePath::nsFilePath(const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
: mPath(NULL)
{
@@ -149,7 +159,7 @@ nsFilePath::nsFilePath(const nsNativeFileSpec& inSpec)
} // nsFilePath::nsFilePath
//----------------------------------------------------------------------------------------
void nsFilePath::operator = (const nsNativeFileSpec& inSpec)
void nsFilePath::operator = (const nsFileSpec& inSpec)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(mPath, inSpec.mPath);
@@ -157,84 +167,86 @@ void nsFilePath::operator = (const nsNativeFileSpec& inSpec)
} // nsFilePath::operator =
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::SetLeafName(const char* inLeafName)
void nsFileSpec::SetLeafName(const char* inLeafName)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::LeafReplace(mPath, '\\', inLeafName);
} // nsNativeFileSpec::SetLeafName
} // nsFileSpec::SetLeafName
//----------------------------------------------------------------------------------------
char* nsNativeFileSpec::GetLeafName() const
char* nsFileSpec::GetLeafName() const
//----------------------------------------------------------------------------------------
{
return nsFileSpecHelpers::GetLeaf(mPath, '\\');
} // nsNativeFileSpec::GetLeafName
} // nsFileSpec::GetLeafName
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::Exists() const
PRBool nsFileSpec::Exists() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st);
} // nsNativeFileSpec::Exists
} // nsFileSpec::Exists
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsFile() const
PRBool nsFileSpec::IsFile() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && (_S_IFREG & st.st_mode);
} // nsNativeFileSpec::IsFile
} // nsFileSpec::IsFile
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsDirectory() const
PRBool nsFileSpec::IsDirectory() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && (_S_IFDIR & st.st_mode);
} // nsNativeFileSpec::IsDirectory
} // nsFileSpec::IsDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const
void nsFileSpec::GetParent(nsFileSpec& outSpec) const
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(outSpec.mPath, mPath);
char* cp = strrchr(outSpec.mPath, '\\');
if (cp)
*cp = '\0';
} // nsNativeFileSpec::GetParent
} // nsFileSpec::GetParent
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator += (const char* inRelativePath)
void nsFileSpec::operator += (const char* inRelativePath)
//----------------------------------------------------------------------------------------
{
if (!inRelativePath || !mPath)
return;
if (mPath[strlen(mPath) - 1] != '\\')
char* newPath = nsFileSpecHelpers::ReallocCat(mPath, "\\");
if (mPath[strlen(mPath) - 1] == '\\')
nsFileSpecHelpers::ReallocCat(mPath, "x");
else
nsFileSpecHelpers::ReallocCat(mPath, "\\x");
SetLeafName(inRelativePath);
} // nsNativeFileSpec::operator +=
} // nsFileSpec::operator +=
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::CreateDirectory(int /*mode*/)
void nsFileSpec::CreateDirectory(int /*mode*/)
//----------------------------------------------------------------------------------------
{
// Note that mPath is canonical!
mkdir(mPath);
} // nsNativeFileSpec::CreateDirectory
} // nsFileSpec::CreateDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::Delete(bool inRecursive)
void nsFileSpec::Delete(PRBool inRecursive)
//----------------------------------------------------------------------------------------
{
if (IsDirectory())
{
if (inRecursive)
{
for (nsDirectoryIterator i(*this); i; i++)
for (nsDirectoryIterator i(*this); i.Exists(); i++)
{
nsNativeFileSpec& child = (nsNativeFileSpec&)i;
nsFileSpec& child = (nsFileSpec&)i;
child.Delete(inRecursive);
}
}
@@ -244,7 +256,106 @@ void nsNativeFileSpec::Delete(bool inRecursive)
{
remove(mPath);
}
} // nsNativeFileSpec::Delete
} // nsFileSpec::Delete
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Rename(const char* inNewName)
//----------------------------------------------------------------------------------------
{
// This function should not be used to move a file on disk.
if (strchr(inNewName, '/'))
return NS_FILE_FAILURE;
if (PR_Rename(*this, inNewName) != NS_OK)
{
return NS_FILE_FAILURE;
}
SetLeafName(inNewName);
return NS_OK;
} // nsFileSpec::Rename
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Copy(const nsFileSpec& inParentDirectory) const
//----------------------------------------------------------------------------------------
{
// We can only copy into a directory, and (for now) can not copy entire directories
if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
{
char *leafname = GetLeafName();
char* destPath = nsFileSpecHelpers::StringDup(inParentDirectory, ( strlen(inParentDirectory) + 1 + strlen(leafname) ) );
strcat(destPath, "\\");
strcat(destPath, leafname);
delete [] leafname;
// CopyFile returns non-zero if succeeds
int copyOK = CopyFile(*this, destPath, true);
delete[] destPath;
if (copyOK)
{
return NS_OK;
}
}
return NS_FILE_FAILURE;
} // nsFileSpec::Copy
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Move(const nsFileSpec& nsNewParentDirectory) const
//----------------------------------------------------------------------------------------
{
// We can only copy into a directory, and (for now) can not copy entire directories
if (nsNewParentDirectory.IsDirectory() && (! IsDirectory() ) )
{
char *leafname = GetLeafName();
char *destPath = nsFileSpecHelpers::StringDup(nsNewParentDirectory, ( strlen(nsNewParentDirectory) + 1 + strlen(leafname) ));
strcat(destPath, "\\");
strcat(destPath, leafname);
delete [] leafname;
// MoveFile returns non-zero if succeeds
int copyOK = MoveFile(*this, destPath);
delete [] destPath;
if (copyOK)
{
return NS_OK;
}
}
return NS_FILE_FAILURE;
} // nsFileSpec::Move
//----------------------------------------------------------------------------------------
nsresult nsFileSpec::Execute(const char* inArgs ) const
//----------------------------------------------------------------------------------------
{
if (! IsDirectory())
{
char* fileNameWithArgs = NULL;
fileNameWithArgs = nsFileSpecHelpers::StringDup(mPath, ( strlen(mPath) + 1 + strlen(inArgs) ) );
strcat(fileNameWithArgs, " ");
strcat(fileNameWithArgs, inArgs);
int execResult = WinExec( fileNameWithArgs, SW_NORMAL );
delete [] fileNameWithArgs;
if (execResult > 31)
{
return NS_OK;
}
}
return NS_FILE_FAILURE;
} // nsFileSpec::Execute
//========================================================================================
// nsDirectoryIterator
@@ -252,7 +363,7 @@ void nsNativeFileSpec::Delete(bool inRecursive)
//----------------------------------------------------------------------------------------
nsDirectoryIterator::nsDirectoryIterator(
const nsNativeFileSpec& inDirectory
const nsFileSpec& inDirectory
, int inIterateDirection)
//----------------------------------------------------------------------------------------
: mCurrent(inDirectory)

View File

@@ -22,332 +22,78 @@
#include "nsFileStream.h"
#include <string.h>
#include <stdio.h>
#ifdef XP_MAC
#include <Errors.h>
#endif
//========================================================================================
// nsBasicFileStream
// nsInputStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsBasicFileStream::nsBasicFileStream()
nsInputStream::~nsInputStream()
//----------------------------------------------------------------------------------------
: mFileDesc(0)
, mNSPRMode(0)
, mFailed(false)
, mEOF(false)
{
mInputStream->Close();
}
//----------------------------------------------------------------------------------------
nsBasicFileStream::nsBasicFileStream(
const nsFilePath& inFile,
int nsprMode,
PRIntn accessMode)
char nsInputStream::get()
//----------------------------------------------------------------------------------------
: mFileDesc(0)
, mNSPRMode(0)
, mFailed(false)
, mEOF(false)
{
open(inFile, nsprMode, accessMode);
char c;
read(&c, sizeof(c));
return c;
}
//----------------------------------------------------------------------------------------
nsBasicFileStream::nsBasicFileStream(PRFileDesc* desc, int nsprMode)
static void TidyEndOfLine(char*& cp)
// Assumes that cp is pointing at \n or \r. Nulls out the character, checks for
// a second terminator (of the opposite persuasion), and returns cp pointing past the
// entire eol construct (one or two characters).
//----------------------------------------------------------------------------------------
: mFileDesc(desc)
, mNSPRMode(nsprMode)
, mFailed(false)
, mEOF(false)
{
char ch = *cp;
*cp++ = '\0'; // terminate at the newline, then skip past it
if ((ch == '\n' && *cp == '\r') || (ch == '\r' && *cp == '\n'))
cp++; // possibly a pair.
}
//----------------------------------------------------------------------------------------
nsBasicFileStream::~nsBasicFileStream()
nsInputStream& nsInputStream::operator >> (char& c)
//----------------------------------------------------------------------------------------
{
close();
}
//----------------------------------------------------------------------------------------
void nsBasicFileStream::open(
const nsFilePath& inFile,
int nsprMode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
{
if (mFileDesc)
return;
const int nspr_modes[]={
PR_WRONLY | PR_CREATE_FILE,
PR_WRONLY | PR_CREATE_FILE | PR_APPEND,
PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
PR_RDONLY,
PR_RDONLY | PR_APPEND,
PR_RDWR | PR_CREATE_FILE,
PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE,
// "wb",
// "ab",
// "wb",
// "rb",
// "r+b",
// "w+b",
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).
mFileDesc = 0;
if (inFile.GetNativeSpec().Error() != noErr)
return;
OSErr err = noErr;
#if DEBUG
const OSType kCreator = 'CWIE';
#else
const OSType kCreator = 'MOSS';
#endif
nsNativeFileSpec nativeSpec = inFile.GetNativeSpec();
FSSpec* spec = (FSSpec*)nativeSpec;
if (nsprMode & PR_CREATE_FILE)
err = FSpCreate(spec, kCreator, 'TEXT', 0);
if (err == dupFNErr)
err = noErr;
if (err != noErr)
return;
SInt8 perm;
if (nsprMode & PR_RDWR)
perm = fsRdWrPerm;
else if (nsprMode & PR_WRONLY)
perm = fsWrPerm;
else
perm = fsRdPerm;
short refnum;
err = FSpOpenDF(spec, perm, &refnum);
if (err == noErr && (nsprMode & PR_TRUNCATE))
err = SetEOF(refnum, 0);
if (err == noErr && (nsprMode & PR_APPEND))
err = SetFPos(refnum, fsFromLEOF, 0);
if (err != noErr)
return;
if ((mFileDesc = PR_ImportFile(refnum)) == 0)
return;
#else
// Platforms other than Macintosh...
// Another bug in NSPR: Mac PR_Open assumes a unix style path, but Win PR_Open assumes
// a windows path.
if ((mFileDesc = PR_Open((const char*)nsNativeFileSpec(inFile), nsprMode, accessMode)) == 0)
return;
#endif
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
//========================================================================================
// nsBasicInStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsBasicInStream::nsBasicInStream(nsBasicFileStream& inBasicStream, istream* inStream)
//----------------------------------------------------------------------------------------
: mBase(inBasicStream)
, mStdStream(inStream)
{
}
//----------------------------------------------------------------------------------------
void nsBasicInStream::get(char& c)
//----------------------------------------------------------------------------------------
{
read(&c, sizeof(char));
}
//----------------------------------------------------------------------------------------
PRBool nsBasicInStream::readline(char* s, PRInt32 n)
// This will truncate if the buffer is too small. Result will always be null-terminated.
//----------------------------------------------------------------------------------------
{
PRBool bufferLargeEnough = true; // result
if (!s || !n)
return true;
PRIntn position = mBase.tell();
if (position < 0)
return false;
PRInt32 bytesRead = read(s, n - 1);
if (mBase.failed())
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 (!mBase.eof())
bufferLargeEnough = false;
position += bytesRead;
mBase.seek(position);
return bufferLargeEnough;
} // nsBasicInStream::getline
//----------------------------------------------------------------------------------------
PRInt32 nsBasicInStream::read(void* s, PRInt32 n)
//----------------------------------------------------------------------------------------
{
#ifndef NS_USE_PR_STDIO
// Calling PR_Read on stdin is sure suicide on Macintosh.
if (GetStandardStream())
{
GetStandardStream()->read((char*)s, n);
return n;
}
#endif
if (!mBase.is_open() || mBase.failed())
return -1;
PRInt32 bytesRead = PR_Read(mBase.GetFileDescriptor(), s, n);
if (bytesRead < 0)
mBase.mFailed = true;
else if (bytesRead < n)
mBase.mEOF = true;
return bytesRead;
}
//----------------------------------------------------------------------------------------
nsBasicInStream& nsBasicInStream::operator >> (char& c)
//----------------------------------------------------------------------------------------
{
get(c);
c = get();
return *this;
}
//========================================================================================
// nsInputFileStream
// nsOutputStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsInputFileStream::nsInputFileStream(istream* stream)
nsOutputStream::~nsOutputStream()
//----------------------------------------------------------------------------------------
#ifndef NS_USE_PR_STDIO
: nsBasicFileStream(0, kDefaultMode)
, nsBasicInStream(*this, stream)
#else
: nsBasicFileStream(PR_STDIN, kDefaultMode)
, nsBasicInStream(*this, 0)
#endif
{
}
//========================================================================================
// nsBasicOutStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsBasicOutStream::nsBasicOutStream(nsBasicFileStream& inBase, ostream* stream)
//----------------------------------------------------------------------------------------
: mBase(inBase)
, mStdStream(stream)
{
mOutputStream->Close();
}
//----------------------------------------------------------------------------------------
void nsBasicOutStream::put(char c)
void nsOutputStream::put(char c)
//----------------------------------------------------------------------------------------
{
write(&c, sizeof(c));
}
//----------------------------------------------------------------------------------------
PRInt32 nsBasicOutStream::write(const void* s, PRInt32 n)
void nsOutputStream::flush()
//----------------------------------------------------------------------------------------
{
#ifndef NS_USE_PR_STDIO
// Calling PR_Write on stdout is sure suicide.
if (mStdStream)
{
mStdStream->write((const char*)s, n);
return n;
}
#endif
if (!mBase.mFileDesc || mBase.failed())
return -1;
PRInt32 bytesWrit = PR_Write(mBase.mFileDesc, s, n);
if (bytesWrit != n)
mBase.mFailed = true;
return bytesWrit;
}
//----------------------------------------------------------------------------------------
nsBasicOutStream& nsBasicOutStream::operator << (char c)
nsOutputStream& nsOutputStream::operator << (char c)
//----------------------------------------------------------------------------------------
{
put(c);
@@ -355,7 +101,7 @@ nsBasicOutStream& nsBasicOutStream::operator << (char c)
}
//----------------------------------------------------------------------------------------
nsBasicOutStream& nsBasicOutStream::operator << (const char* s)
nsOutputStream& nsOutputStream::operator << (const char* s)
//----------------------------------------------------------------------------------------
{
write(s, strlen(s));
@@ -363,78 +109,84 @@ nsBasicOutStream& nsBasicOutStream::operator << (const char* s)
}
//----------------------------------------------------------------------------------------
nsBasicOutStream& nsBasicOutStream::operator << (short val)
nsOutputStream& nsOutputStream::operator << (short val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%d", val);
return *this << buf;
return (*this << buf);
}
//----------------------------------------------------------------------------------------
nsBasicOutStream& nsBasicOutStream::operator << (unsigned short val)
nsOutputStream& nsOutputStream::operator << (unsigned short val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%ud", val);
return *this << buf;
return (*this << buf);
}
//----------------------------------------------------------------------------------------
nsBasicOutStream& nsBasicOutStream::operator << (long val)
nsOutputStream& nsOutputStream::operator << (long val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%ld", val);
return *this << buf;
return (*this << buf);
}
//----------------------------------------------------------------------------------------
nsBasicOutStream& nsBasicOutStream::operator << (unsigned long val)
nsOutputStream& nsOutputStream::operator << (unsigned long val)
//----------------------------------------------------------------------------------------
{
char buf[30];
sprintf(buf, "%uld", val);
return *this << buf;
return (*this << buf);
}
//========================================================================================
// nsInputFileStream
//========================================================================================
//----------------------------------------------------------------------------------------
void nsBasicOutStream::flush()
// Must precede the destructor because both are inline.
PRBool nsInputFileStream::readline(char* s, PRInt32 n)
// This will truncate if the buffer is too small. Result will always be null-terminated.
//----------------------------------------------------------------------------------------
{
#ifndef NS_USE_PR_STDIO
if (mStdStream)
PRBool bufferLargeEnough = PR_TRUE; // result
if (!s || !n)
return PR_TRUE;
PRIntn position = tell();
if (position < 0)
return PR_FALSE;
PRInt32 bytesRead = read(s, n - 1);
if (failed())
return PR_FALSE;
s[bytesRead] = '\0'; // always terminate at the end of the buffer
char* tp = strpbrk(s, "\n\r");
if (tp)
{
mStdStream->flush();
return;
TidyEndOfLine(tp);
bytesRead = (tp - s);
}
#endif
if (mBase.mFileDesc == 0)
return;
PRBool itFailed = PR_Sync(mBase.mFileDesc) != PR_SUCCESS;
#ifdef XP_MAC
// On unix, it seems to fail always.
if (itFailed)
mBase.mFailed = true;
#endif
} // nsBasicOutStream::flush
else if (!eof())
bufferLargeEnough = PR_FALSE;
position += bytesRead;
seek(position);
return bufferLargeEnough;
} // nsInputStream::readline
//========================================================================================
// nsOutputFileStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsOutputFileStream::nsOutputFileStream(ostream* stream)
void nsOutputFileStream::flush()
//----------------------------------------------------------------------------------------
#ifndef NS_USE_PR_STDIO
: nsBasicFileStream(0, kDefaultMode)
, nsBasicOutStream(*this, stream)
#else
: nsBasicFileStream(PR_STDOUT, kDefaultMode)
, nsBasicOutStream(*this, 0)
#endif
{
if (mFileOutputStream)
mFileOutputStream->Flush();
}
//========================================================================================
@@ -442,19 +194,10 @@ nsOutputFileStream::nsOutputFileStream(ostream* stream)
//========================================================================================
//----------------------------------------------------------------------------------------
nsBasicOutStream& nsEndl(nsBasicOutStream& os)
nsOutputStream& nsEndl(nsOutputStream& os)
//----------------------------------------------------------------------------------------
{
#ifndef NS_USE_PR_STDIO
// Calling PR_Write on stdout is sure suicide on Macintosh.
ostream* stream = os.GetStandardStream();
if (stream)
{
*stream << std::endl;
return os;
}
#endif
os.put('\n');
os.flush();
return os;
}
os.put('\n');
os.flush();
return os;
} // nsEndl

View File

@@ -19,14 +19,31 @@
// 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.
// Completely rewritten to integrate with nsIInputStream and nsIOutputStream (the
// xpcom stream objects.
//========================================================================================
//
// Classes defined:
//
// single-byte char:
//
// nsInputStream, nsOutputStream
// These are the lightweight STATICALLY LINKED wrappers for
// the xpcom objects nsIInputStream and nsIOutputstream.
// Possible uses:
// If you are implementing a function that accepts one of these xpcom
// streams, just make one of these little jobbies on the stack, and
// the handy << or >> notation can be yours.
//
// nsInputFileStream, nsOutputFileStream
// These are the STATICALLY LINKED versions of the file i/o streams,
// which wrap the NSPR file i/o plus console i/o.
//
// Related files:
// prio.h the NSPR file i/o C API), which is wrapped by
// THIS FILE statically linked C++ wrappers, which in turn are wrapped by
// nsIFileStream.h COM wrappers for this file, which are wrapped by
// nsAutoFileStream.h more easily used, nicer syntax wrappers for the
// COMified ones. Wrapper of a wrapper of a wrapper.
//
// This suite provide the following services:
//
@@ -41,13 +58,13 @@
//
// Basic example:
//
// nsFilePath myPath("/Development/iotest.txt");
// nsFileSpec 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
// 4. Requires streams to be constructed using typesafe nsFileSpec specifier
// (not the notorious and bug prone const char*), namely nsFileSpec. See
// nsFileSpec.h for more details.
//
// 5. Fixes a bug that have been there for a long time, and
@@ -73,7 +90,13 @@
#else
#include "prio.h"
#endif
#include "nsFileSpec.h"
#include "nsIFileStream.h"
#include "nsCOMPtr.h"
class nsFileSpec;
class nsInputFileStream;
class nsOutputFileStream;
//========================================================================================
// Compiler-specific macros, as needed
@@ -133,201 +156,392 @@ using std::ostream;
//=========================== End Compiler-specific macros ===============================
//========================================================================================
class NS_BASE nsBasicFileStream
class NS_BASE nsInputStream
// This is a convenience class, for use on the STACK ("new" junkies: get detoxed first).
// Given a COM-style stream, this allows you to use the >> operators. It also acquires and
// reference counts its stream.
// Please read the comments at the top of this file
//========================================================================================
{
public:
nsBasicFileStream();
nsBasicFileStream(PRFileDesc* desc, int nsprMode);
nsBasicFileStream(
const nsFilePath& inFile,
int nsprMode,
PRIntn accessMode);
virtual ~nsBasicFileStream();
nsInputStream(nsIInputStream* inStream)
: mInputStream(do_QueryInterface(inStream))
, mEOF(PR_FALSE)
{}
virtual ~nsInputStream();
nsCOMPtr<nsIInputStream> GetIStream() const
{
return mInputStream;
}
char eof() const { return mEOF; }
char get();
PRInt32 read(void* s, PRInt32 n)
{
if (!mInputStream)
return 0;
PRInt32 result = 0;
mInputStream->Read((char*)s, 0, n, (PRUint32*)&result);
if (result < n)
mEOF = PR_TRUE;
return result;
}
// Input streamers. Add more as needed (int&, unsigned int& etc). (but you have to
// add delegators to the derived classes, too, because these operators don't inherit).
nsInputStream& operator >> (char& ch);
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&))
// Support manipulators
nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
{
return pf(*this);
}
void get(char& c);
PRInt32 read(void* s, PRInt32 n);
}
private:
nsInputStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE.
// DATA
protected:
nsCOMPtr<nsIInputStream> mInputStream;
PRBool mEOF;
}; // class nsInputStream
typedef nsInputStream nsBasicInStream; // historic support for this name
//========================================================================================
class NS_BASE nsOutputStream
// This is a convenience class, for use on the STACK ("new" junkies, get detoxed first).
// Given a COM-style stream, this allows you to use the << operators. It also acquires and
// reference counts its stream.
// Please read the comments at the top of this file
//========================================================================================
{
public:
nsOutputStream() {}
nsOutputStream(nsIOutputStream* inStream)
: mOutputStream(do_QueryInterface(inStream))
{}
virtual ~nsOutputStream();
nsCOMPtr<nsIOutputStream> GetIStream() const
{
return mOutputStream;
}
void put(char c);
PRInt32 write(const void* s, PRInt32 n)
{
if (!mOutputStream)
return 0;
PRInt32 result = 0;
mOutputStream->Write((char*)s, 0, n, (PRUint32*)&result);
return result;
}
virtual void flush();
// Output streamers. Add more as needed (but you have to add delegators to the derived
// classes, too, because these operators don't inherit).
nsOutputStream& operator << (const char* buf);
nsOutputStream& operator << (char ch);
nsOutputStream& operator << (short val);
nsOutputStream& operator << (unsigned short val);
nsOutputStream& operator << (long val);
nsOutputStream& operator << (unsigned long val);
// Support manipulators
nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
{
return pf(*this);
}
// DATA
protected:
nsCOMPtr<nsIOutputStream> mOutputStream;
}; // class nsOutputStream
typedef nsOutputStream nsBasicOutStream; // Historic support for this name
//========================================================================================
class NS_BASE nsFileClient
// Because COM does not allow us to write functions which return a boolean value etc,
// this class is here to take care of the tedious "declare variable then call with
// the address of the variable" chores.
//========================================================================================
{
public:
nsFileClient() // for delayed opening
: mResult(NS_OK)
{
}
nsFileClient(const nsCOMPtr<nsIFile>& inFile)
: mFile(do_QueryInterface(inFile))
, mResult(NS_OK)
{
}
PRBool is_file() const
{
return mFile ? PR_TRUE : PR_FALSE;
}
void open(
const nsFileSpec& inFile,
int nsprMode,
PRIntn accessMode)
{
if (mFile)
mResult = mFile->Open(inFile, nsprMode, accessMode);
}
PRBool is_open() const
{
PRBool result = PR_FALSE;
if (mFile)
mFile->GetIsOpen(&result);
return result;
}
PRBool failed() const
{
return NS_FAILED(mResult);
}
void seek(PRInt32 offset)
{
seek(PR_SEEK_SET, offset);
}
void seek(PRSeekWhence whence, PRInt32 offset)
{
if (mFile)
mResult = mFile->Seek(whence, offset);
}
PRIntn tell()
{
PRIntn result = -1;
if (mFile)
mResult = mFile->Tell(&result);
return result;
}
// DATA
protected:
nsCOMPtr<nsIFile> mFile;
PRBool mResult;
}; // class nsFileClient
//========================================================================================
class NS_BASE nsInputFileStream
// Please read the comments at the top of this file
//========================================================================================
: public nsInputStream
, public nsFileClient
{
public:
enum { kDefaultMode = PR_RDONLY };
nsInputFileStream(nsIInputStream* inStream)
: nsInputStream(inStream)
, nsFileClient(do_QueryInterface(inStream))
, mFileInputStream(do_QueryInterface(inStream))
{
}
nsInputFileStream(
const nsFileSpec& inFile,
int nsprMode = kDefaultMode,
PRIntn accessMode = 00700) // <- OCTAL
: nsInputStream(nsnull)
{
nsISupports* stream;
NS_NewIOFileStream(
&stream,
inFile, nsprMode, accessMode);
mFile = nsQueryInterface(stream);
mInputStream = nsQueryInterface(stream);
mFileInputStream = nsQueryInterface(stream);
}
PRBool readline(char* s, PRInt32 n);
// Result always null-terminated.
// Check eof() before each call.
// CAUTION: false result only indicates line was truncated
// to fit buffer, or an error occurred (OTHER THAN eof).
// 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,
void Open(
const nsFileSpec& inFile,
int nsprMode = kDefaultMode,
PRIntn accessMode = 00700) // <- OCTAL
{
nsBasicFileStream::open(inFile, nsprMode, accessMode);
if (mFile)
mFile->Open(inFile, nsprMode, accessMode);
}
private:
nsInputFileStream& operator >> (char* buf); // TOO DANGEROUS. DON'T DEFINE.
// Input streamers. Unfortunately, they don't inherit!
nsInputStream& operator >> (char& ch)
{ return nsInputStream::operator >>(ch); }
nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
{ return nsInputStream::operator >>(pf); }
// DATA
protected:
nsCOMPtr<nsIFileInputStream> mFileInputStream;
}; // class nsInputFileStream
//========================================================================================
class NS_BASE nsOutputFileStream
// Please read the comments at the top of this file
//========================================================================================
: public nsBasicFileStream
, public nsBasicOutStream
: public nsOutputStream
, public nsFileClient
{
public:
enum { kDefaultMode = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE) };
nsOutputFileStream(ostream* stream = CONSOLE_OUT);
nsOutputFileStream() {}
nsOutputFileStream(nsIOutputStream* inStream)
: nsOutputStream(inStream)
, nsFileClient(do_QueryInterface(inStream))
, mFileOutputStream(do_QueryInterface(inStream))
{
}
nsOutputFileStream(
const nsFilePath& inFile,
const nsFileSpec& 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
: nsOutputStream(nsnull)
{
nsBasicFileStream::open(inFile, nsprMode, accessMode);
nsISupports* stream;
if (NS_FAILED(NS_NewIOFileStream(
&stream,
inFile, nsprMode, accessMode)))
return;
mFile = nsQueryInterface(stream);
mOutputStream = nsQueryInterface(stream);
mFileOutputStream = nsQueryInterface(stream);
}
virtual void flush();
// Output streamers. Unfortunately, they don't inherit!
nsOutputStream& operator << (const char* buf)
{ return nsOutputStream::operator << (buf); }
nsOutputStream& operator << (char ch)
{ return nsOutputStream::operator << (ch); }
nsOutputStream& operator << (short val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (unsigned short val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (long val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (unsigned long val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
{ return nsOutputStream::operator << (pf); }
// DATA
protected:
nsCOMPtr<nsIFileOutputStream> mFileOutputStream;
}; // class nsOutputFileStream
//========================================================================================
class NS_BASE nsIOFileStream
class NS_BASE nsOutputConsoleStream
// Please read the comments at the top of this file
//========================================================================================
: public nsBasicFileStream
, public nsBasicOutStream
, public nsBasicInStream
: public nsOutputFileStream
{
public:
nsOutputConsoleStream()
{
nsISupports* stream;
if (NS_FAILED(NS_NewOutputConsoleStream(&stream)))
return;
mFile = nsQueryInterface(stream);
mOutputStream = nsQueryInterface(stream);
mFileOutputStream = nsQueryInterface(stream);
}
// Output streamers. Unfortunately, they don't inherit!
nsOutputStream& operator << (const char* buf)
{ return nsOutputStream::operator << (buf); }
nsOutputStream& operator << (char ch)
{ return nsOutputStream::operator << (ch); }
nsOutputStream& operator << (short val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (unsigned short val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (long val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (unsigned long val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
{ return nsOutputStream::operator << (pf); }
}; // class nsOutputConsoleStream
//========================================================================================
class NS_BASE nsIOFileStream
// Please read the comments at the top of this file
//========================================================================================
: public nsInputFileStream
, public nsOutputStream
{
public:
enum { kDefaultMode = (PR_RDWR | PR_CREATE_FILE) };
nsIOFileStream(
const nsFilePath& inFile,
nsIInputStream* inInputStream
, nsIOutputStream* inOutputStream)
: nsInputFileStream(inInputStream)
, nsOutputStream(inOutputStream)
, mFileOutputStream(do_QueryInterface(inOutputStream))
{
}
nsIOFileStream(
const nsFileSpec& 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
: nsInputFileStream(nsnull)
, nsOutputStream(nsnull)
{
nsBasicFileStream::open(inFile, nsprMode, accessMode);
nsISupports* stream;
if (NS_FAILED(NS_NewIOFileStream(
&stream,
inFile, nsprMode, accessMode)))
return;
mFile = nsQueryInterface(stream);
mInputStream = nsQueryInterface(stream);
mOutputStream = nsQueryInterface(stream);
mFileInputStream = nsQueryInterface(stream);
mFileOutputStream = nsQueryInterface(stream);
}
}; // class nsIOFileStream
// Output streamers. Unfortunately, they don't inherit!
nsOutputStream& operator << (const char* buf)
{ return nsOutputStream::operator << (buf); }
nsOutputStream& operator << (char ch)
{ return nsOutputStream::operator << (ch); }
nsOutputStream& operator << (short val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (unsigned short val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (long val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (unsigned long val)
{ return nsOutputStream::operator << (val); }
nsOutputStream& operator << (nsOutputStream& (*pf)(nsOutputStream&))
{ return nsOutputStream::operator << (pf); }
// Input streamers. Unfortunately, they don't inherit!
nsInputStream& operator >> (char& ch)
{ return nsInputStream::operator >>(ch); }
nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
{ return nsInputStream::operator >>(pf); }
// DATA
protected:
nsCOMPtr<nsIFileOutputStream> mFileOutputStream;
}; // class nsIOFileStream
//========================================================================================
// Manipulators
//========================================================================================
NS_BASE nsBasicOutStream& nsEndl(nsBasicOutStream& os);
NS_BASE nsOutputStream& nsEndl(nsOutputStream& os); // outputs and FLUSHES.
#endif /* _FILESTREAM_H_ */

View File

@@ -31,6 +31,8 @@
class nsIBaseStream : public nsISupports {
public:
static const nsIID& IID() { static nsIID iid = NS_IBASESTREAM_IID; return iid; }
/** Close the stream. */
NS_IMETHOD
Close(void) = 0;

View File

@@ -0,0 +1,451 @@
#include "nsIFileStream.h"
#include "nsFileSpec.h"
#include "prerror.h"
#ifdef XP_MAC
#include "pprio.h" // To get PR_ImportFile
#else
#include "prio.h"
#endif
#ifdef XP_MAC
#include <Errors.h>
#include <iostream>
#endif
//========================================================================================
class FileImpl
: public nsIOutputStream
, public nsIInputStream
, public nsIFileOutputStream
, public nsIFileInputStream
, public nsIFile
//========================================================================================
{
public:
FileImpl(PRFileDesc* inDesc)
: mFileDesc(inDesc)
, mFailed(PR_FALSE)
, mEOF(PR_FALSE)
, mLength(-1)
{
NS_INIT_REFCNT();
}
FileImpl(
const nsFileSpec& inFile,
int nsprMode,
PRIntn accessMode)
: mFileDesc(nsnull)
, mFailed(PR_FALSE)
, mEOF(PR_FALSE)
{
NS_INIT_REFCNT();
Open(inFile, nsprMode, accessMode);
}
virtual ~FileImpl()
{
Close();
}
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIFile interface
NS_IMETHOD Open(
const nsFileSpec& inFile,
int nsprMode,
PRIntn accessMode);
NS_IMETHOD Close();
NS_IMETHOD Seek(PRSeekWhence whence, PRInt32 offset);
NS_IMETHOD GetIsOpen(PRBool* outOpen)
{
*outOpen = (mFileDesc != nsnull);
return NS_OK;
}
NS_IMETHOD Tell(PRIntn* outWhere);
// nsIInputStream interface
NS_IMETHOD GetLength(PRUint32 *aLength)
{
NS_PRECONDITION(aLength != nsnull, "null ptr");
if (!aLength)
return NS_ERROR_NULL_POINTER;
if (mLength < 0)
return NS_FILE_RESULT(NS_ERROR_UNEXPECTED);
*aLength = mLength;
return NS_OK;
}
NS_IMETHOD Read(char* aBuf,
PRUint32 aOffset,
PRUint32 aCount,
PRUint32 *aReadCount)
{
NS_PRECONDITION(aBuf != nsnull, "null ptr");
if (!aBuf)
return NS_ERROR_NULL_POINTER;
NS_PRECONDITION(aReadCount != nsnull, "null ptr");
if (!aReadCount)
return NS_ERROR_NULL_POINTER;
if (!mFileDesc)
return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
if (mFailed)
return NS_ERROR_FAILURE;
if (aOffset)
PR_Seek(mFileDesc, aOffset, PR_SEEK_CUR);
PRInt32 bytesRead = PR_Read(mFileDesc, aBuf, aCount);
if (bytesRead < 0)
{
*aReadCount = 0;
mFailed = PR_TRUE;
return NS_FILE_RESULT(PR_GetError());
}
*aReadCount = bytesRead;
return NS_OK;
}
// nsIOutputStream interface
NS_IMETHOD Write(const char* aBuf,
PRUint32 aOffset,
PRUint32 aCount,
PRUint32 *aWriteCount)
{
NS_PRECONDITION(aBuf != nsnull, "null ptr");
NS_PRECONDITION(aWriteCount != nsnull, "null ptr");
#ifdef XP_MAC
// Calling PR_Write on stdout is sure suicide.
if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR)
{
cout.write(aBuf, aCount);
*aWriteCount = aCount;
return NS_OK;
}
#endif
if (!mFileDesc)
return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
if (mFailed)
return NS_ERROR_FAILURE;
if (aOffset)
PR_Seek(mFileDesc, aOffset, PR_SEEK_CUR);
PRInt32 bytesWrit = PR_Write(mFileDesc, aBuf, aCount);
if (bytesWrit != aCount)
{
mFailed = PR_TRUE;
*aWriteCount = 0;
return NS_FILE_RESULT(PR_GetError());
}
*aWriteCount = bytesWrit;
return NS_OK;
}
NS_IMETHOD Flush();
protected:
PRFileDesc* mFileDesc;
int mNSPRMode;
PRBool mFailed;
PRBool mEOF;
PRInt32 mLength;
}; // class FileImpl
#define SAY_I_IMPLEMENT(classname) \
if (aIID.Equals(classname::IID())) \
{ \
*aInstancePtr = (void*)((classname*)this); \
NS_ADDREF_THIS(); \
return NS_OK; \
}
NS_IMPL_RELEASE(FileImpl)
NS_IMPL_ADDREF(FileImpl)
//----------------------------------------------------------------------------------------
NS_IMETHODIMP FileImpl::QueryInterface(REFNSIID aIID, void** aInstancePtr)
//----------------------------------------------------------------------------------------
{
if (!aInstancePtr)
return NS_ERROR_NULL_POINTER;
*aInstancePtr = nsnull;
SAY_I_IMPLEMENT(nsIFile)
SAY_I_IMPLEMENT(nsIOutputStream)
SAY_I_IMPLEMENT(nsIInputStream)
SAY_I_IMPLEMENT(nsIFileInputStream)
SAY_I_IMPLEMENT(nsIFileOutputStream)
// Note that we derive from two copies of nsIBaseStream (and hence
// of nsISupports), one through
// nsIOutputStream, the other through nsIInputStream. Resolve this
// by giving them a specific one
if (aIID.Equals(((nsIBaseStream*)(nsIOutputStream*)this)->IID()))
{
*aInstancePtr = (void*)((nsIBaseStream*)(nsIOutputStream*)this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(((nsISupports*)(nsIOutputStream*)this)->IID()))
{
*aInstancePtr = (void*)((nsISupports*)(nsIOutputStream*)this);
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
} // FileImpl::QueryInterface
//----------------------------------------------------------------------------------------
NS_IMETHODIMP FileImpl::Open(
const nsFileSpec& inFile,
int nsprMode,
PRIntn accessMode)
//----------------------------------------------------------------------------------------
{
if (mFileDesc)
if ((nsprMode & mNSPRMode) == nsprMode)
return NS_OK;
else
return NS_FILE_RESULT(PR_ILLEGAL_ACCESS_ERROR);
const int nspr_modes[]={
PR_WRONLY | PR_CREATE_FILE,
PR_WRONLY | PR_CREATE_FILE | PR_APPEND,
PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
PR_RDONLY,
PR_RDONLY | PR_APPEND,
PR_RDWR | PR_CREATE_FILE,
PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE,
// "wb",
// "ab",
// "wb",
// "rb",
// "r+b",
// "w+b",
0 };
const int* currentLegalMode = nspr_modes;
while (*currentLegalMode && nsprMode != *currentLegalMode)
++currentLegalMode;
if (!*currentLegalMode)
return NS_FILE_RESULT(PR_ILLEGAL_ACCESS_ERROR);
#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).
mFileDesc = 0;
if (inFile.Error() != noErr)
return NS_FILE_RESULT(inFile.Error());
OSErr err = noErr;
#if DEBUG
const OSType kCreator = 'CWIE';
#else
const OSType kCreator = 'MOSS';
#endif
// Resolve the alias to the original file.
nsFileSpec original = inFile;
PRBool ignoredResult;
original.ResolveAlias(ignoredResult);
const FSSpec& spec = original.operator const FSSpec&();
if (nsprMode & PR_CREATE_FILE)
err = FSpCreate(&spec, kCreator, 'TEXT', 0);
if (err == dupFNErr)
err = noErr;
if (err != noErr)
return NS_FILE_RESULT(err);
SInt8 perm;
if (nsprMode & PR_RDWR)
perm = fsRdWrPerm;
else if (nsprMode & PR_WRONLY)
perm = fsWrPerm;
else
perm = fsRdPerm;
short refnum;
err = FSpOpenDF(&spec, perm, &refnum);
if (err == noErr && (nsprMode & PR_TRUNCATE))
err = SetEOF(refnum, 0);
if (err == noErr && (nsprMode & PR_APPEND))
err = SetFPos(refnum, fsFromLEOF, 0);
if (err != noErr)
return NS_FILE_RESULT(err);
if ((mFileDesc = PR_ImportFile(refnum)) == 0)
return NS_FILE_RESULT(PR_GetError());
#else
// Platforms other than Macintosh...
// Another bug in NSPR: Mac PR_Open assumes a unix style path, but Win PR_Open assumes
// a windows path.
if ((mFileDesc = PR_Open((const char*)nsFileSpec(inFile), nsprMode, accessMode)) == 0)
return NS_FILE_RESULT(PR_GetError());
#endif
mNSPRMode = nsprMode;
mLength = PR_Available(mFileDesc);
return NS_OK;
} // FileImpl::Open
//----------------------------------------------------------------------------------------
NS_IMETHODIMP FileImpl::Seek(PRSeekWhence whence, PRInt32 offset)
//----------------------------------------------------------------------------------------
{
if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
mFailed = PR_FALSE; // reset on a seek.
mEOF = PR_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 = PR_TRUE;
}
else if (newPosition >= fileSize)
{
newPosition = fileSize;
mEOF = PR_TRUE;
}
if (PR_Seek(mFileDesc, newPosition, PR_SEEK_SET) < 0)
mFailed = PR_TRUE;
return NS_OK;
} // FileImpl::Seek
//----------------------------------------------------------------------------------------
NS_IMETHODIMP FileImpl::Tell(PRIntn* outWhere)
//----------------------------------------------------------------------------------------
{
if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
*outWhere = PR_Seek(mFileDesc, 0, PR_SEEK_CUR);
return NS_OK;
} // FileImpl::Tell
//----------------------------------------------------------------------------------------
NS_IMETHODIMP FileImpl::Close()
//----------------------------------------------------------------------------------------
{
if (mFileDesc==PR_STDIN || mFileDesc==PR_STDOUT || mFileDesc==PR_STDERR || !mFileDesc)
return NS_OK;
if (PR_Close(mFileDesc) == PR_SUCCESS)
mFileDesc = 0;
else
return NS_FILE_RESULT(PR_GetError());
return NS_OK;
} // FileImpl::close
//----------------------------------------------------------------------------------------
NS_IMETHODIMP FileImpl::Flush()
//----------------------------------------------------------------------------------------
{
#ifdef XP_MAC
if (mFileDesc == PR_STDOUT || mFileDesc == PR_STDERR)
{
cout.flush();
return NS_OK;
}
#endif
if (!mFileDesc)
return NS_FILE_RESULT(PR_BAD_DESCRIPTOR_ERROR);
PRBool itFailed = PR_Sync(mFileDesc) != PR_SUCCESS;
#ifdef XP_MAC
// On unix, it seems to fail always.
if (itFailed)
mFailed = PR_TRUE;
#endif
return NS_OK;
} // FileImpl::flush
//----------------------------------------------------------------------------------------
NS_BASE nsresult NS_NewTypicalInputFileStream(
nsISupports** aResult,
const nsFileSpec& inFile
/*Default nsprMode == PR_RDONLY*/
/*Default accessmode = 0700 (octal)*/)
// Factory method to get an nsInputStream from a file, using most common options
//----------------------------------------------------------------------------------------
{
return NS_NewIOFileStream(aResult, inFile, PR_RDONLY, 0700);
}
//----------------------------------------------------------------------------------------
NS_BASE nsresult NS_NewOutputConsoleStream(
nsISupports** aResult)
// Factory method to get an nsOutputStream to the console.
//----------------------------------------------------------------------------------------
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
FileImpl* stream = new FileImpl(PR_STDOUT);
if (! stream)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(stream);
*aResult = (nsISupports*)(void*)stream;
return NS_OK;
}
//----------------------------------------------------------------------------------------
NS_BASE nsresult NS_NewTypicalOutputFileStream(
nsISupports** aResult,
const nsFileSpec& inFile
/*default nsprMode= (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/
/*Default accessMode= 0700 (octal)*/)
// Factory method to get an nsOutputStream to a file - most common case.
//----------------------------------------------------------------------------------------
{
return NS_NewIOFileStream(
aResult,
inFile,
(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE),
0700);
}
//----------------------------------------------------------------------------------------
NS_BASE nsresult NS_NewIOFileStream(
nsISupports** aResult,
const nsFileSpec& inFile,
PRInt32 nsprMode /*default = (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/,
PRInt32 accessMode /*Default = 0700 (octal)*/)
// Factory method to get an object that implements both nsIInputStream
// and nsIOutputStream, associated with a file.
//----------------------------------------------------------------------------------------
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (!aResult)
return NS_ERROR_NULL_POINTER;
FileImpl* stream = new FileImpl(inFile, nsprMode, accessMode);
if (! stream)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(stream);
*aResult = (nsISupports*)(void*)stream;
return NS_OK;
}
//----------------------------------------------------------------------------------------
NS_BASE nsresult NS_NewTypicalIOFileStream(
nsISupports** aResult,
const nsFileSpec& inFile
/*default nsprMode= (PR_RDWR | PR_CREATE_FILE)*/
/*Default accessMode= 0700 (octal)*/)
// Factory method to get an object that implements both nsIInputStream
// and nsIOutputStream, associated with a single file.
//----------------------------------------------------------------------------------------
{
return NS_NewIOFileStream(
aResult,
inFile,
(PR_RDWR | PR_CREATE_FILE),
0700);
}

View File

@@ -0,0 +1,127 @@
/* -*- 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.
*/
#ifndef nsIFileStream_h___
#define nsIFileStream_h___
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "prio.h"
class nsFileSpec;
/* a6cf90e8-15b3-11d2-932e-00805f8add32 */
#define NS_IFILE_IID \
{ 0xa6cf90e8, 0x15b3, 0x11d2, \
{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
//========================================================================================
class nsIFile
// Represents a file, and supports Open, Tell etc.
//========================================================================================
: public nsISupports
{
public:
static const nsIID& IID() { static nsIID iid = NS_IFILE_IID; return iid; }
NS_IMETHOD Open(
const nsFileSpec& inFile,
int nsprMode,
PRIntn accessMode) = 0;
// Note: Open() is only needed after
// an explicit Close(). All file streams
// are automatically opened on construction.
NS_IMETHOD Seek(PRSeekWhence whence, PRInt32 offset) = 0;
NS_IMETHOD GetIsOpen(PRBool* outOpen) = 0;
NS_IMETHOD Tell(PRIntn* outWhere) = 0;
}; // class nsIFile
/* a6cf90e6-15b3-11d2-932e-00805f8add32 */
#define NS_IFILEINPUTSTREAM_IID \
{ 0xa6cf90e6, 0x15b3, 0x11d2, \
{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
//========================================================================================
class nsIFileInputStream
// These are additional file-specific methods that files have, above what
// nsIInputStream supports. The current implementation supports both
// interfaces.
//========================================================================================
: public nsISupports
{
public:
static const nsIID& IID() { static nsIID iid = NS_IFILEINPUTSTREAM_IID; return iid; }
}; // class nsIFileInputStream
/* a6cf90e7-15b3-11d2-932e-00805f8add32 */
#define NS_IFILEOUTPUTSTREAM_IID \
{ 0xa6cf90e7, 0x15b3, 0x11d2, \
{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
//========================================================================================
class nsIFileOutputStream
// These are additional file-specific methods that files have, above what
// nsIOutputStream supports. The current implementation supports both
// interfaces.
//========================================================================================
: public nsISupports
{
public:
static const nsIID& IID() { static nsIID iid = NS_IFILEOUTPUTSTREAM_IID; return iid; }
NS_IMETHOD Flush() = 0;
// Forces a write to disk.
}; // class nsIFileOutputStream
//----------------------------------------------------------------------------------------
NS_BASE nsresult NS_NewTypicalInputFileStream(
nsISupports** aStreamResult,
const nsFileSpec& inFile
/*Default nsprMode == PR_RDONLY*/
/*Default accessmode = 0700 (octal)*/);
// Factory method to get an nsInputStream from a file, using most common options
//----------------------------------------------------------------------------------------
extern "C" NS_BASE nsresult NS_NewOutputConsoleStream(
nsISupports** aStreamResult);
// Factory method to get an nsOutputStream to the console.
//----------------------------------------------------------------------------------------
extern "C" NS_BASE nsresult NS_NewTypicalOutputFileStream(
nsISupports** aStreamResult, // will implement all the above interfaces
const nsFileSpec& inFile
/*default nsprMode= (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)*/
/*Default accessMode= 0700 (octal)*/);
// Factory method to get an nsOutputStream to a file - most common case.
//----------------------------------------------------------------------------------------
extern "C" NS_BASE nsresult NS_NewTypicalIOFileStream(
nsISupports** aStreamResult, // will implement all the above interfaces
const nsFileSpec& inFile
/*default nsprMode = (PR_RDWR | PR_CREATE_FILE)*/
/*Default accessMode = 0700 (octal)*/);
// Factory method to get an object that implements both nsIInputStream
// and nsIOutputStream, associated with a single file.
//----------------------------------------------------------------------------------------
extern "C" NS_BASE nsresult NS_NewIOFileStream(
nsISupports** aStreamResult, // will implement all the above interfaces
const nsFileSpec& inFile,
PRInt32 nsprMode,
PRInt32 accessMode);
// Factory method to get an object that implements both nsIInputStream
// and nsIOutputStream, associated with a single file.
#endif /* nsIFileStream_h___ */

View File

@@ -28,6 +28,8 @@
class nsIInputStream : public nsIBaseStream {
public:
static const nsIID& IID() { static nsIID iid = NS_IINPUTSTREAM_IID; return iid; }
/** Return the number of bytes in the stream
* @param aLength out parameter to hold the length
* of the stream. if an error occurs, the length

View File

@@ -29,6 +29,8 @@
class nsIOutputStream : public nsIBaseStream {
public:
static const nsIID& IID() { static nsIID iid = NS_IOUTPUTSTREAM_IID; return iid; }
/** Write data into the stream.
* @param aBuf the buffer into which the data is read
* @param aOffset the start offset of the data

View File

@@ -16,10 +16,11 @@
* Reserved.
*/
#include "string.h"
#include "nsFileSpec.h"
#include "nsFileStream.h"
//#include "string.h"
struct FilesTest
{
FilesTest() : mConsole() {}
@@ -30,18 +31,25 @@ struct FilesTest
int InputStream(const char* relativePath);
int OutputStream(const char* relativePath);
int IOStream(const char* relativePath);
int Parent(const char* relativePath, nsNativeFileSpec& outParent);
int Delete(nsNativeFileSpec& victim);
int CreateDirectory(nsNativeFileSpec& victim);
int IterateDirectoryChildren(nsNativeFileSpec& startChild);
int Parent(const char* relativePath, nsFileSpec& outParent);
int Delete(nsFileSpec& victim);
int CreateDirectory(nsFileSpec& victim);
int IterateDirectoryChildren(nsFileSpec& startChild);
int CanonicalPath(const char* relativePath);
int Persistence(const char* relativePath);
int Copy(const char* sourceFile, const char* targDir);
int Move(const char* sourceFile, const char* targDir);
int Rename(const char* sourceFile, const char* newName);
int Execute(const char* appName, const char* args);
void Banner(const char* bannerString);
void Passed();
void Failed();
void Inspect();
nsOutputFileStream mConsole;
nsOutputConsoleStream mConsole;
};
//----------------------------------------------------------------------------------------
@@ -59,7 +67,8 @@ void FilesTest::Banner(const char* bannerString)
void FilesTest::Passed()
//----------------------------------------------------------------------------------------
{
mConsole << "Test passed." << nsEndl;
((nsOutputStream&)mConsole) << "Test passed.";
mConsole << nsEndl;
}
//----------------------------------------------------------------------------------------
@@ -89,7 +98,7 @@ void FilesTest::WriteStuff(nsOutputFileStream& s)
s << "As a unix path: \"" << (const char*)filePath << "\""<< nsEndl;
// Initialize a native file spec from a URL
nsNativeFileSpec fileSpec(fileURL);
nsFileSpec fileSpec(fileURL);
s << "As a file spec: " << fileSpec << nsEndl;
// Make the spec unique (this one has no suffix).
@@ -119,10 +128,10 @@ int FilesTest::OutputStream(const char* relativePath)
{
nsFilePath myTextFilePath(relativePath, true); // relative path.
const char* pathAsString = (const char*)myTextFilePath;
nsNativeFileSpec mySpec(myTextFilePath);
nsFileSpec mySpec(myTextFilePath);
{
mConsole << "WRITING IDENTICAL OUTPUT TO " << pathAsString << nsEndl << nsEndl;
nsOutputFileStream testStream(myTextFilePath);
nsOutputFileStream testStream(mySpec);
if (!testStream.is_open())
{
mConsole
@@ -154,9 +163,10 @@ int FilesTest::IOStream(const char* relativePath)
{
nsFilePath myTextFilePath(relativePath, true); // relative path.
const char* pathAsString = (const char*)myTextFilePath;
nsFileSpec mySpec(myTextFilePath);
mConsole
<< "Replacing \"path\" by \"ZUUL\" in " << pathAsString << nsEndl << nsEndl;
nsIOFileStream testStream(myTextFilePath);
nsIOFileStream testStream(mySpec);
if (!testStream.is_open())
{
mConsole
@@ -183,6 +193,57 @@ int FilesTest::IOStream(const char* relativePath)
return 0;
}
//----------------------------------------------------------------------------------------
int FilesTest::Persistence(
const char* relativePathToWrite)
//----------------------------------------------------------------------------------------
{
nsFilePath myTextFilePath(relativePathToWrite, true);
const char* pathAsString = (const char*)myTextFilePath;
nsFileSpec mySpec(myTextFilePath);
nsIOFileStream testStream(mySpec, (PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE));
if (!testStream.is_open())
{
mConsole
<< "ERROR: File "
<< pathAsString
<< " could not be opened for input+output"
<< nsEndl;
return -1;
}
nsPersistentFileDescriptor myPersistent(mySpec);
mConsole
<< "Writing persistent file data " << pathAsString << nsEndl << nsEndl;
testStream.seek(0); // check that the seek compiles
testStream << myPersistent;
testStream.seek(0);
nsPersistentFileDescriptor mySecondPersistent;
testStream >> mySecondPersistent;
mySpec = mySecondPersistent;
#ifdef XP_MAC
if (mySpec.Error())
{
Failed();
return -1;
}
#endif
if (!mySpec.Exists())
{
Failed();
return -1;
}
Passed();
return 0;
}
//----------------------------------------------------------------------------------------
int FilesTest::InputStream(const char* relativePath)
//----------------------------------------------------------------------------------------
@@ -190,7 +251,8 @@ int FilesTest::InputStream(const char* relativePath)
nsFilePath myTextFilePath(relativePath, true);
const char* pathAsString = (const char*)myTextFilePath;
mConsole << "READING BACK DATA FROM " << pathAsString << nsEndl << nsEndl;
nsInputFileStream testStream2(myTextFilePath);
nsFileSpec mySpec(myTextFilePath);
nsInputFileStream testStream2(mySpec);
if (!testStream2.is_open())
{
mConsole
@@ -215,12 +277,12 @@ int FilesTest::InputStream(const char* relativePath)
//----------------------------------------------------------------------------------------
int FilesTest::Parent(
const char* relativePath,
nsNativeFileSpec& outParent)
nsFileSpec& outParent)
//----------------------------------------------------------------------------------------
{
nsFilePath myTextFilePath(relativePath, true);
const char* pathAsString = (const char*)myTextFilePath;
nsNativeFileSpec mySpec(myTextFilePath);
nsFileSpec mySpec(myTextFilePath);
mySpec.GetParent(outParent);
nsFilePath parentPath(outParent);
@@ -235,7 +297,7 @@ int FilesTest::Parent(
}
//----------------------------------------------------------------------------------------
int FilesTest::Delete(nsNativeFileSpec& victim)
int FilesTest::Delete(nsFileSpec& victim)
//----------------------------------------------------------------------------------------
{
// - Test of non-recursive delete
@@ -284,7 +346,7 @@ int FilesTest::Delete(nsNativeFileSpec& victim)
}
//----------------------------------------------------------------------------------------
int FilesTest::CreateDirectory(nsNativeFileSpec& dirSpec)
int FilesTest::CreateDirectory(nsFileSpec& dirSpec)
//----------------------------------------------------------------------------------------
{
nsFilePath dirPath(dirSpec);
@@ -306,27 +368,27 @@ int FilesTest::CreateDirectory(nsNativeFileSpec& dirSpec)
}
//----------------------------------------------------------------------------------------
int FilesTest::IterateDirectoryChildren(nsNativeFileSpec& startChild)
int FilesTest::IterateDirectoryChildren(nsFileSpec& startChild)
//----------------------------------------------------------------------------------------
{
// - Test of directory iterator
nsNativeFileSpec grandparent;
nsFileSpec grandparent;
startChild.GetParent(grandparent); // should be the original default directory.
nsFilePath grandparentPath(grandparent);
mConsole << "Forwards listing of " << (const char*)grandparentPath << ":" << nsEndl;
for (nsDirectoryIterator i(grandparent, +1); i; i++)
for (nsDirectoryIterator i(grandparent, +1); i.Exists(); i++)
{
char* itemName = ((nsNativeFileSpec&)i).GetLeafName();
char* itemName = ((nsFileSpec&)i).GetLeafName();
mConsole << '\t' << itemName << nsEndl;
delete [] itemName;
}
mConsole << "Backwards listing of " << (const char*)grandparentPath << ":" << nsEndl;
for (nsDirectoryIterator j(grandparent, -1); j; j--)
for (nsDirectoryIterator j(grandparent, -1); j.Exists(); j--)
{
char* itemName = ((nsNativeFileSpec&)j).GetLeafName();
char* itemName = ((nsFileSpec&)j).GetLeafName();
mConsole << '\t' << itemName << nsEndl;
delete [] itemName;
}
@@ -355,6 +417,110 @@ int FilesTest::CanonicalPath(
return 0;
}
//----------------------------------------------------------------------------------------
int FilesTest::Copy(const char* file, const char* dir)
//----------------------------------------------------------------------------------------
{
nsFileSpec dirPath(dir, true);
dirPath.CreateDirectory();
if (! dirPath.Exists())
{
Failed();
return -1;
}
nsFileSpec mySpec(file, true); // relative path.
{
nsIOFileStream testStream(mySpec); // creates the file
// Scope ends here, file gets closed
}
nsFileSpec filePath(file);
if (! filePath.Exists())
{
Failed();
return -1;
}
nsresult error = filePath.Copy(dirPath);
dirPath += filePath.GetLeafName();
if (! dirPath.Exists() || ! filePath.Exists() || NS_FAILED(error))
{
Failed();
return -1;
}
Passed();
return 0;
}
//----------------------------------------------------------------------------------------
int FilesTest::Move(const char* file, const char* dir)
//----------------------------------------------------------------------------------------
{
nsFileSpec dirPath(dir, true);
dirPath.CreateDirectory();
if (! dirPath.Exists())
{
Failed();
return -1;
}
nsFileSpec srcSpec(file, true); // relative path.
{
nsIOFileStream testStream(srcSpec); // creates the file
// file gets closed here because scope ends here.
};
if (! srcSpec.Exists())
{
Failed();
return -1;
}
nsresult error = srcSpec.Move(dirPath);
dirPath += srcSpec.GetLeafName();
if (! dirPath.Exists() || srcSpec.Exists() || NS_FAILED(error))
{
Failed();
return -1;
}
Passed();
return 0;
}
//----------------------------------------------------------------------------------------
int FilesTest::Execute(const char* appName, const char* args)
//----------------------------------------------------------------------------------------
{
nsFileSpec appPath(appName, false);
if (!appPath.Exists())
{
Failed();
return -1;
}
nsresult error = appPath.Execute(args);
if (NS_FAILED(error))
{
Failed();
return -1;
}
Passed();
return 0;
}
//----------------------------------------------------------------------------------------
int FilesTest::RunAllTests()
// For use with DEBUG defined.
@@ -389,7 +555,7 @@ int FilesTest::RunAllTests()
return -1;
Banner("Parent");
nsNativeFileSpec parent;
nsFileSpec parent;
if (Parent("mumble/iotest.txt", parent) != 0)
return -1;
@@ -405,6 +571,36 @@ int FilesTest::RunAllTests()
if (IterateDirectoryChildren(parent) != 0)
return -1;
Banner("Copy");
if (Copy("mumble/copyfile.txt", "mumble/copy") != 0)
return -1;
Banner("Move");
if (Move("mumble/moveFile.txt", "mumble/move") != 0)
return -1;
Banner("Execute");
#ifdef XP_MAC
// This path is hard-coded to test on jrm's machine. Finding an app
// on an arbitrary Macintosh would cost more trouble than it's worth.
// Change path to suit.
if NS_FAILED(Execute("/Projects/Nav45_BRANCH/ns/cmd/macfe/"\
"projects/client45/Client45PPC", ""))
#elif XP_PC
if NS_FAILED(Execute("c:\\windows\\notepad.exe", ""))
#else
if NS_FAILED(Execute("/bin/ls", "/"))
#endif
return -1;
Banner("Persistence");
if (Persistence("mumble/filedesc.dat") != 0)
return -1;
Banner("Delete again (to clean up our mess)");
if (Delete(parent) != 0)
return -1;
return 0;
}
@@ -413,7 +609,6 @@ int main()
// For use with DEBUG defined.
//----------------------------------------------------------------------------------------
{
FilesTest tester;
return tester.RunAllTests();
} // main