Added a directory iterator class. Added canonification and recursive directory creation, and some other handy methods. Eventual goal: replace xp_file.h entirely.

git-svn-id: svn://10.0.0.236/trunk@17274 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
mcmullen%netscape.com
1999-01-06 23:38:21 +00:00
parent 507c25df08
commit 67a2f24b86
12 changed files with 2162 additions and 412 deletions

View File

@@ -127,6 +127,10 @@
#ifdef XP_MAC
#include <Files.h>
#elif defined(XP_UNIX) || defined (XP_OS2)
#include <dirent.h>
#elif 0 // defined(XP_PC)
#include "winfile.h"
#endif
//========================================================================================
@@ -150,7 +154,7 @@ class NS_BASE nsNativeFileSpec
{
public:
nsNativeFileSpec();
explicit nsNativeFileSpec(const char* inString);
explicit nsNativeFileSpec(const char* inString, bool inCreateDirs = false);
explicit nsNativeFileSpec(const nsFilePath& inPath);
explicit nsNativeFileSpec(const nsFileURL& inURL);
nsNativeFileSpec(const nsNativeFileSpec& inPath);
@@ -177,12 +181,12 @@ class NS_BASE nsNativeFileSpec
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.
// 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);
// Called for the spec of an alias. Modifies the spec to
// point to the original. Sets mError.
// Called for the spec of an alias. Modifies the spec to
// point to the original. Sets mError.
void MakeUnique(ConstStr255Param inSuggestedLeafName);
StringPtr GetLeafPName() { return mSpec.name; }
ConstStr255Param GetLeafPName() const { return mSpec.name; }
@@ -194,14 +198,58 @@ class NS_BASE nsNativeFileSpec
bool Valid() const { return true; } // Fixme.
#endif // XP_MAC
friend NS_BASE nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec& spec);
friend NS_BASE nsOutputFileStream& operator << (
nsOutputFileStream& s,
const nsNativeFileSpec& spec);
//--------------------------------------------------
// Queries and path algebra. These do not modify the disk.
//--------------------------------------------------
char* GetLeafName() const; // Allocated. Use delete [].
void SetLeafName(const char* inLeafName);
bool Exists() const;
// inLeafName can be a relative path, so this allows
// one kind of concatenation of "paths".
void GetParent(nsNativeFileSpec& 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,
// however, that the top node is still not a name,
// but a spec. Volumes on Macintosh can have identical
// names. Perhaps could be used for an operator --() ?
nsNativeFileSpec 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.
// This must be a directory for this to work. This differs
// from SetLeafName(), since the latter will work
// starting with a sibling of the directory and throws
// away its leaf information, whereas this one assumes
// this is a directory, and the relative path starts
// "below" this.
void MakeUnique();
void MakeUnique(const char* inSuggestedLeafName);
bool IsDirectory() const;
// More stringent than Exists()
bool IsFile() const;
// More stringent than Exists()
bool Exists() const;
//--------------------------------------------------
// Creation and deletion of objects. These can modify the disk.
//--------------------------------------------------
void CreateDirectory(int mode = 0700 /* for unix */);
void Delete(bool inRecursive);
//--------------------------------------------------
// Data
//--------------------------------------------------
private:
friend class nsFilePath;
#ifdef XP_MAC
@@ -221,7 +269,7 @@ class NS_BASE nsFileURL
{
public:
nsFileURL(const nsFileURL& inURL);
explicit nsFileURL(const char* inString);
explicit nsFileURL(const char* inString, bool inCreateDirs = false);
explicit nsFileURL(const nsFilePath& inPath);
explicit nsFileURL(const nsNativeFileSpec& inPath);
virtual ~nsFileURL();
@@ -247,7 +295,7 @@ class NS_BASE nsFileURL
operator char* ();
operator const char* const ();
private:
friend class nsFilePath; // to allow construction of nsFilePath
friend class nsFilePath; // to allow construction of nsFilePath
char* mURL;
#ifdef XP_MAC
// Since the path on the macintosh does not uniquely specify a file (volumes
@@ -264,7 +312,7 @@ class NS_BASE nsFilePath
{
public:
nsFilePath(const nsFilePath& inPath);
explicit nsFilePath(const char* inString);
explicit nsFilePath(const char* inString, bool inCreateDirs = false);
explicit nsFilePath(const nsFileURL& inURL);
explicit nsFilePath(const nsNativeFileSpec& inPath);
virtual ~nsFilePath();
@@ -292,7 +340,7 @@ class NS_BASE nsFilePath
private:
char* mPath;
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.
@@ -300,4 +348,52 @@ class NS_BASE nsFilePath
#endif
}; // class nsFilePath
//========================================================================================
class nsDirectoryIterator
// Example:
//
// nsNativeFileSpec parentDir(...); // directory over whose children we shall iterate
// for (nsDirectoryIterator i(parentDir); i; i++)
// {
// // do something with (const nsNativeFileSpec&)i
// }
//
// or:
//
// for (nsDirectoryIterator i(parentDir, false); i; i--)
// {
// // do something with (const nsNativeFileSpec&)i
// }
//
// Currently, the only platform on which backwards iteration actually goes backwards
// is Macintosh. On other platforms, both styles will work, but will go forwards.
//========================================================================================
{
public:
nsDirectoryIterator(
const nsNativeFileSpec& 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; }
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; }
private:
nsNativeFileSpec mCurrent;
bool mExists;
#if defined(XP_UNIX) // || defined(XP_PC) add when ready
DIR* mDir;
#elif defined(XP_MAC)
OSErr SetToIndex();
short mIndex;
short mMaxIndex;
#endif
}; // class nsDirectoryIterator
#endif // _FILESPEC_H_

View File

@@ -21,6 +21,7 @@
#include "FullPath.h"
#include "FileCopy.h"
#include "MoreFilesExtras.h"
#include "nsEscape.h"
#include <Aliases.h>
@@ -39,14 +40,16 @@ namespace MacFileHelpers
memcpy(dst, src, 1 + src[0]);
}
void PLstrcpy(Str255 dst, const char* src, int inMaxLen);
void PLstrcpy(Str255 dst, const char* src, int inMaxLen=255);
void PLstrncpy(Str255 dst, const char* src, int inMaxLen);
void SwapSlashColon(char * s);
OSErr FSSpecFromFullUnixPath(
const char * unixPath,
FSSpec& outSpec,
Boolean resolveAlias,
Boolean allowPartial = false);
Boolean allowPartial = false,
Boolean createDirs = false);
char* MacPathFromUnixPath(const char* unixPath);
char* EncodeMacPath(
char* inPath, // NOT const - gets clobbered
@@ -54,7 +57,8 @@ namespace MacFileHelpers
Boolean doEscape );
OSErr FSSpecFromPathname(
const char* inPathNamePtr,
FSSpec& outSpec);
FSSpec& outSpec,
Boolean inCreateDirs);
char* PathNameFromFSSpec(
const FSSpec& inSpec,
Boolean wantLeafName );
@@ -81,7 +85,7 @@ namespace MacFileHelpers
//----------------------------------------------------------------------------------------
void MacFileHelpers::PLstrcpy(Str255 dst, const char* src, int inMax)
//========================================================================================
//----------------------------------------------------------------------------------------
{
int srcLength = strlen(src);
NS_ASSERTION(srcLength <= inMax, "Oops, string is too long!");
@@ -91,6 +95,17 @@ void MacFileHelpers::PLstrcpy(Str255 dst, const char* src, int inMax)
memcpy(&dst[1], src, srcLength);
}
//----------------------------------------------------------------------------------------
void MacFileHelpers::PLstrncpy(Str255 dst, const char* src, int inMax)
//----------------------------------------------------------------------------------------
{
int srcLength = strlen(src);
if (srcLength > inMax)
srcLength = inMax;
dst[0] = srcLength;
memcpy(&dst[1], src, srcLength);
}
//-----------------------------------
void MacFileHelpers::SwapSlashColon(char * s)
//-----------------------------------
@@ -218,7 +233,10 @@ char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath)
} // MacFileHelpers::MacPathFromUnixPath
//----------------------------------------------------------------------------------------
OSErr MacFileHelpers::FSSpecFromPathname(const char* inPathNamePtr, FSSpec& outSpec)
OSErr MacFileHelpers::FSSpecFromPathname(
const char* inPathNamePtr,
FSSpec& outSpec,
Boolean inCreateDirs)
// FSSpecFromPathname reverses PathNameFromFSSpec.
// It returns a FSSpec given a c string which is a mac pathname.
//----------------------------------------------------------------------------------------
@@ -226,22 +244,55 @@ OSErr MacFileHelpers::FSSpecFromPathname(const char* inPathNamePtr, FSSpec& outS
OSErr err;
// Simplify this routine to use FSMakeFSSpec if length < 255. Otherwise use the MoreFiles
// routine FSpLocationFromFullPath, which allocates memory, to handle longer pathnames.
if (strlen(inPathNamePtr) < 255)
size_t inLength = strlen(inPathNamePtr);
if (inLength < 255)
{
Str255 path;
int pos = 0;
while ( (path[++pos] = *inPathNamePtr++) != 0 )
;
path[0] = pos-1; // save the length of the string (pos is the next open spot)
err = ::FSMakeFSSpec(0, 0, path, &outSpec);
Str255 ppath;
MacFileHelpers::PLstrcpy(ppath, inPathNamePtr);
err = ::FSMakeFSSpec(0, 0, ppath, &outSpec);
}
else
err = FSpLocationFromFullPath(strlen(inPathNamePtr), inPathNamePtr, &outSpec);
err = FSpLocationFromFullPath(inLength, inPathNamePtr, &outSpec);
if (err == dirNFErr && inCreateDirs)
{
const char* path = inPathNamePtr;
outSpec.vRefNum = 0;
outSpec.parID = 0;
do {
// Locate the colon that terminates the node.
// But if we've a partial path (starting with a colon), find the second one.
const char* nextColon = strchr(path + (*path == ':'), ':');
// Well, if there are no more colons, point to the end of the string.
if (!nextColon)
nextColon = path + strlen(path);
// Make a pascal string out of this node. Include initial
// and final colon, if any!
Str255 ppath;
MacFileHelpers::PLstrncpy(ppath, path, nextColon - path + 1);
// Use this string as a relative path using the directory created
// on the previous round (or directory 0,0 on the first round).
err = ::FSMakeFSSpec(outSpec.vRefNum, outSpec.parID, ppath, &outSpec);
// If this was the leaf node, then we are done.
if (!*nextColon)
break;
// If we got "file not found", then
// we need to create a directory.
if (err == fnfErr && *nextColon)
err = FSpDirCreate(&outSpec, smCurrentScript, &outSpec.parID);
// For some reason, this usually returns fnfErr, even though it works.
if (err != noErr && err != fnfErr)
return err;
path = nextColon; // next round
} while (1);
}
return err;
}
} // MacFileHelpers::FSSpecFromPathname
//----------------------------------------------------------------------------------------
OSErr MacFileHelpers::CreateFolderInFolder(
@@ -320,7 +371,8 @@ OSErr MacFileHelpers::FSSpecFromFullUnixPath(
const char * unixPath,
FSSpec& outSpec,
Boolean resolveAlias,
Boolean allowPartial)
Boolean allowPartial,
Boolean createDirs)
// File spec from URL. Reverses GetURLFromFileSpec
// Its input is only the <path> part of the URL
// JRM 97/01/08 changed this so that if it's a partial path (doesn't start with '/'),
@@ -338,7 +390,7 @@ OSErr MacFileHelpers::FSSpecFromFullUnixPath(
{
NS_ASSERTION(*unixPath == '/' /*full path*/, "Not a full Unix path!");
}
err = FSSpecFromPathname(macPath, outSpec);
err = FSSpecFromPathname(macPath, outSpec, createDirs);
if (err == fnfErr)
err = noErr;
Boolean dummy;
@@ -468,11 +520,12 @@ nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec)
}
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const char* inString)
nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs)
//----------------------------------------------------------------------------------------
{
mError = MacFileHelpers::FSSpecFromFullUnixPath(inString, mSpec, true, true);
// allow a partial path
mError = MacFileHelpers::FSSpecFromFullUnixPath(
inString, mSpec, true, true, inCreateDirs);
// allow a partial path, create as necessary
if (mError == fnfErr)
mError = noErr;
} // nsNativeFileSpec::nsNativeFileSpec
@@ -537,9 +590,13 @@ bool nsNativeFileSpec::Exists() const
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::SetLeafName(const char* inLeafName)
// In leaf name can actually be a partial path...
//----------------------------------------------------------------------------------------
{
MacFileHelpers::PLstrcpy(mSpec.name, inLeafName, nsFileSpecHelpers::kMaxFilenameLength);
// what about long relative paths? Hmm?
Str255 partialPath;
MacFileHelpers::PLstrcpy(partialPath, inLeafName);
mError = FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec);
} // nsNativeFileSpec::SetLeafName
//----------------------------------------------------------------------------------------
@@ -579,10 +636,86 @@ void nsNativeFileSpec::ResolveAlias(bool& wasAliased)
wasAliased = (wasAliased2 != false);
} // nsNativeFileSpec::ResolveAlias
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsFile() const
//----------------------------------------------------------------------------------------
{
long dirID;
Boolean isDirectory;
return (noErr == FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && !isDirectory);
} // nsNativeFileSpec::IsFile
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsDirectory() const
//----------------------------------------------------------------------------------------
{
long dirID;
Boolean isDirectory;
return (noErr == FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && isDirectory);
} // nsNativeFileSpec::IsDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const
//----------------------------------------------------------------------------------------
{
if (mError == noErr)
outSpec.mError = FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, NULL, outSpec);
} // nsNativeFileSpec::GetParent
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator += (const char* inRelativePath)
//----------------------------------------------------------------------------------------
{
long dirID;
Boolean isDirectory;
mError = FSpGetDirectoryID(&mSpec, &dirID, &isDirectory);
if (mError == noErr && isDirectory)
{
mError = FSMakeFSSpec(mSpec.vRefNum, dirID, "\pG'day", *this);
if (mError == noErr)
SetLeafName(inRelativePath);
}
} // nsNativeFileSpec::operator +=
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::CreateDirectory(int /* unix mode */)
//----------------------------------------------------------------------------------------
{
long ignoredDirID;
FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID);
} // nsNativeFileSpec::CreateDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::Delete(bool inRecursive)
//----------------------------------------------------------------------------------------
{
if (inRecursive)
{
// MoreFilesExtras
mError = DeleteDirectory(
mSpec.vRefNum,
mSpec.parID,
const_cast<unsigned char*>(mSpec.name));
}
else
mError = FSpDelete(&mSpec);
} // nsNativeFileSpec::Delete
//========================================================================================
// Macintosh nsFilePath implementation
//========================================================================================
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const char* inString, bool inCreateDirs)
//----------------------------------------------------------------------------------------
: mPath(nsnull)
, mNativeFileSpec(inString, inCreateDirs)
{
// Make canonical and absolute.
char * path = MacFileHelpers::PathNameFromFSSpec( mNativeFileSpec, TRUE );
mPath = MacFileHelpers::EncodeMacPath(path, true, true);
}
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const nsNativeFileSpec& inSpec)
//----------------------------------------------------------------------------------------
@@ -601,3 +734,118 @@ void nsFilePath::operator = (const nsNativeFileSpec& inSpec)
mPath = MacFileHelpers::EncodeMacPath(path, true, true);
mNativeFileSpec = inSpec;
} // nsFilePath::operator =
//========================================================================================
// nsFileURL implementation
//========================================================================================
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const char* inString, bool inCreateDirs)
//----------------------------------------------------------------------------------------
: mURL(nsnull)
, mNativeFileSpec(inString + kFileURLPrefixLength, inCreateDirs)
{
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
// Make canonical and absolute.
char* path = MacFileHelpers::PathNameFromFSSpec( mNativeFileSpec, TRUE );
char* escapedPath = MacFileHelpers::EncodeMacPath(path, true, true);
mURL = nsFileSpecHelpers::StringDup(kFileURLPrefix, kFileURLPrefixLength + strlen(escapedPath));
strcat(mURL, escapedPath);
delete [] escapedPath;
} // nsFileURL::nsFileURL
//========================================================================================
// nsDirectoryIterator
//========================================================================================
//----------------------------------------------------------------------------------------
nsDirectoryIterator::nsDirectoryIterator(
const nsNativeFileSpec& inDirectory
, int inIterateDirection)
//----------------------------------------------------------------------------------------
: mCurrent(inDirectory)
, mExists(false)
, mIndex(-1)
{
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&();
Str255 outName;
MacFileHelpers::PLstrcpy(outName, inSpec.name);
pb.hFileInfo.ioNamePtr = outName;
pb.hFileInfo.ioVRefNum = inSpec.vRefNum;
pb.hFileInfo.ioDirID = inSpec.parID;
pb.hFileInfo.ioFDirIndex = 0; // use ioNamePtr and ioDirID
OSErr err = PBGetCatInfoSync( &pb );
// test that we have got a directory back, not a file
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&();
currentSpec.vRefNum = inSpec.vRefNum;
currentSpec.parID = dipb->ioDrDirID;
mMaxIndex = pb.dirInfo.ioDrNmFls;
if (inIterateDirection > 0)
{
mIndex = 0; // ready to increment
++(*this); // the pre-increment operator
}
else
{
mIndex = mMaxIndex + 1; // ready to decrement
--(*this); // the pre-decrement operator
}
} // nsDirectoryIterator::nsDirectoryIterator
//----------------------------------------------------------------------------------------
OSErr nsDirectoryIterator::SetToIndex()
//----------------------------------------------------------------------------------------
{
CInfoPBRec cipb;
DirInfo *dipb=(DirInfo *)&cipb;
Str255 objectName;
dipb->ioCompletion = NULL;
dipb->ioFDirIndex = mIndex;
// Sorry about this, there seems to be a bug in CWPro 4:
FSSpec& currentSpec = mCurrent.nsNativeFileSpec::operator FSSpec&();
dipb->ioVRefNum = currentSpec.vRefNum; /* Might need to use vRefNum, not sure*/
dipb->ioDrDirID = currentSpec.parID;
dipb->ioNamePtr = objectName;
OSErr err = PBGetCatInfoSync(&cipb);
if (err == noErr)
err = FSMakeFSSpec(currentSpec.vRefNum, currentSpec.parID, objectName, &currentSpec);
mExists = err == noErr;
return err;
} // nsDirectoryIterator::SetToIndex()
//----------------------------------------------------------------------------------------
nsDirectoryIterator& nsDirectoryIterator::operator -- ()
//----------------------------------------------------------------------------------------
{
mExists = false;
while (--mIndex > 0)
{
OSErr err = SetToIndex();
if (err == noErr)
break;
}
return *this;
} // nsDirectoryIterator::operator --
//----------------------------------------------------------------------------------------
nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
//----------------------------------------------------------------------------------------
{
mExists = false;
if (mIndex >= 0) // probably trying to use a file as a directory!
while (++mIndex <= mMaxIndex)
{
OSErr err = SetToIndex();
if (err == noErr)
break;
}
return *this;
} // nsDirectoryIterator::operator ++

View File

@@ -30,115 +30,180 @@
NS_NAMESPACE nsFileSpecHelpers
//========================================================================================
{
enum
{ kMaxFilenameLength = 31 // should work on Macintosh, Unix, and Win32.
, kMaxAltDigitLength = 5
, kMaxCoreLeafNameLength = (kMaxFilenameLength - (kMaxAltDigitLength + 1))
};
NS_NAMESPACE_PROTOTYPE void LeafReplace(
char*& ioPath,
char inSeparator,
const char* inLeafName);
NS_NAMESPACE_PROTOTYPE char* GetLeaf(const char* inPath, char inSeparator); // allocated
NS_NAMESPACE_PROTOTYPE char* StringDup(const char* inString, int allocLength = 0);
NS_NAMESPACE_PROTOTYPE char* AllocCat(const char* inString1, const char* inString2);
NS_NAMESPACE_PROTOTYPE char* StringAssign(char*& ioString, const char* inOther);
enum
{ kMaxFilenameLength = 31 // should work on Macintosh, Unix, and Win32.
, kMaxAltDigitLength = 5
, kMaxCoreLeafNameLength = (kMaxFilenameLength - (kMaxAltDigitLength + 1))
};
NS_NAMESPACE_PROTOTYPE void LeafReplace(
char*& ioPath,
char inSeparator,
const char* inLeafName);
#ifndef XP_MAC
NS_NAMESPACE_PROTOTYPE void Canonify(char*& ioPath, bool inMakeDirs);
NS_NAMESPACE_PROTOTYPE void MakeAllDirectories(const char* inPath, int mode);
#endif
NS_NAMESPACE_PROTOTYPE char* GetLeaf(const char* inPath, char inSeparator); // allocated
NS_NAMESPACE_PROTOTYPE char* StringDup(const char* inString, int allocLength = 0);
NS_NAMESPACE_PROTOTYPE char* AllocCat(const char* inString1, const char* inString2);
NS_NAMESPACE_PROTOTYPE char* StringAssign(char*& ioString, const char* inOther);
NS_NAMESPACE_PROTOTYPE char* ReallocCat(char*& ioString, const char* inString1);
} NS_NAMESPACE_END
//----------------------------------------------------------------------------------------
char* nsFileSpecHelpers::StringDup(
const char* inString,
int allocLength)
const char* inString,
int allocLength)
//----------------------------------------------------------------------------------------
{
if (!allocLength && inString)
allocLength = strlen(inString);
char* newPath = inString || allocLength ? new char[allocLength + 1] : 0;
if (!newPath)
return NULL;
strcpy(newPath, inString);
return newPath;
if (!allocLength && inString)
allocLength = strlen(inString);
char* newPath = inString || allocLength ? new char[allocLength + 1] : nsnull;
if (!newPath)
return NULL;
strcpy(newPath, inString);
return newPath;
} // nsFileSpecHelpers::StringDup
//----------------------------------------------------------------------------------------
char* nsFileSpecHelpers::AllocCat(
const char* inString1,
const char* inString2)
const char* inString1,
const char* inString2)
//----------------------------------------------------------------------------------------
{
if (!inString1)
return inString2 ? StringDup(inString2) : (char*)NULL;
if (!inString2)
return StringDup(inString1);
char* outString = StringDup(inString1, strlen(inString1) + strlen(inString2));
if (outString)
strcat(outString, inString2);
return outString;
if (!inString1)
return inString2 ? StringDup(inString2) : (char*)NULL;
if (!inString2)
return StringDup(inString1);
char* outString = StringDup(inString1, strlen(inString1) + strlen(inString2));
if (outString)
strcat(outString, inString2);
return outString;
} // nsFileSpecHelpers::StringDup
//----------------------------------------------------------------------------------------
char* nsFileSpecHelpers::StringAssign(
char*& ioString,
const char* inString2)
char*& ioString,
const char* inString2)
//----------------------------------------------------------------------------------------
{
if (!inString2)
{
delete [] ioString;
ioString = (char*)NULL;
return ioString;
}
if (!ioString || (strlen(inString2) > strlen(ioString)))
{
delete [] ioString;
ioString = StringDup(inString2);
return ioString;
}
strcpy(ioString, inString2);
return ioString;
if (!inString2)
{
delete [] ioString;
ioString = (char*)NULL;
return ioString;
}
if (!ioString || (strlen(inString2) > strlen(ioString)))
{
delete [] ioString;
ioString = StringDup(inString2);
return ioString;
}
strcpy(ioString, inString2);
return ioString;
} // nsFileSpecHelpers::StringAssign
//----------------------------------------------------------------------------------------
void nsFileSpecHelpers::LeafReplace(
char*& ioPath,
char inSeparator,
const char* inLeafName)
char*& ioPath,
char inSeparator,
const char* inLeafName)
//----------------------------------------------------------------------------------------
{
// Find the existing leaf name
if (!ioPath)
return;
if (!inLeafName)
{
*ioPath = '\0';
return;
}
char* lastSeparator = strrchr(ioPath, inSeparator);
int oldLength = strlen(ioPath);
*(++lastSeparator) = '\0'; // strip the current leaf name
int newLength = lastSeparator - ioPath + strlen(inLeafName);
if (newLength > oldLength)
{
char* newPath = StringDup(ioPath, newLength + 1);
delete [] ioPath;
ioPath = newPath;
}
strcat(ioPath, inLeafName);
} // nsNativeFileSpec::SetLeafName
// Find the existing leaf name
if (!ioPath)
return;
if (!inLeafName)
{
*ioPath = '\0';
return;
}
char* lastSeparator = strrchr(ioPath, inSeparator);
int oldLength = strlen(ioPath);
*(++lastSeparator) = '\0'; // strip the current leaf name
int newLength = lastSeparator - ioPath + strlen(inLeafName);
if (newLength > oldLength)
{
char* newPath = StringDup(ioPath, newLength + 1);
delete [] ioPath;
ioPath = newPath;
}
strcat(ioPath, inLeafName);
} // nsNativeFileSpec::LeafReplace
//----------------------------------------------------------------------------------------
char* nsFileSpecHelpers::GetLeaf(const char* inPath, char inSeparator)
// Returns a pointer to an allocated string representing the leaf.
//----------------------------------------------------------------------------------------
{
if (!inPath)
return NULL;
char* lastSeparator = strrchr(inPath, inSeparator);
if (lastSeparator)
return StringDup(lastSeparator);
return StringDup(inPath);
if (!inPath)
return NULL;
char* lastSeparator = strrchr(inPath, inSeparator);
if (lastSeparator)
return StringDup(++lastSeparator);
return StringDup(inPath);
} // nsNativeFileSpec::GetLeaf
#if defined(XP_UNIX) || defined(XP_PC)
//----------------------------------------------------------------------------------------
void nsFileSpecHelpers::MakeAllDirectories(const char* inPath, int mode)
// Make the path a valid one by creating all the intermediate directories. Does NOT
// make the leaf into a directory. This should be a unix path.
//----------------------------------------------------------------------------------------
{
if (!inPath)
return;
char* pathCopy = nsFileSpecHelpers::StringDup( inPath );
if (!pathCopy)
return;
const char kSeparator = '/'; // I repeat: this should be a unix-style path.
const int kSkipFirst = 1;
#ifdef XP_WIN
NS_ASSERTION( pathCopy[2] == '|', "No drive letter!" );
#endif
char* currentStart = pathCopy;
char* currentEnd = strchr(currentStart + kSkipFirst, kSeparator);
if (currentEnd)
{
*currentEnd = '\0';
nsNativeFileSpec spec(nsFilePath(pathCopy, false));
do
{
// If the node doesn't exist, and it is not the initial node in a full path,
// then make a directory (We cannot make the initial (volume) node).
if (!spec.Exists() && *currentStart != kSeparator)
spec.CreateDirectory(mode);
if (!spec.Exists())
{
NS_ASSERTION(spec.Exists(), "Could not create the directory?");
break;
}
currentStart = ++currentEnd;
currentEnd = strchr(currentStart, kSeparator);
if (!currentEnd)
break;
spec += currentStart; // "lengthen" the path, adding the next node.
} while (currentEnd);
}
delete [] pathCopy;
} // nsFileSpecHelpers::MakeAllDirectories
#endif // XP_PC || XP_UNIX
//----------------------------------------------------------------------------------------
char* nsFileSpecHelpers::ReallocCat(char*& ioString, const char* inString1)
//----------------------------------------------------------------------------------------
{
char* newString = AllocCat(ioString, inString1);
delete [] ioString;
ioString = newString;
return ioString;
} // nsNativeFileSpec::ReallocCat
#if defined(XP_PC)
#include "windows/nsFileSpecWin.cpp" // Windows-specific implementations
@@ -149,26 +214,30 @@ char* nsFileSpecHelpers::GetLeaf(const char* inPath, char inSeparator)
#endif
//========================================================================================
// nsFileURL implementation
// nsFileURL implementation
//========================================================================================
#ifndef XP_MAC
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const char* inString)
nsFileURL::nsFileURL(const char* inString, bool inCreateDirs)
//----------------------------------------------------------------------------------------
: mURL(nsFileSpecHelpers::StringDup(inString))
#ifdef XP_MAC
, mNativeFileSpec(inString + kFileURLPrefixLength)
#endif
: mURL(nsnull)
{
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
if (!inString)
return;
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
// Make canonical and absolute.
nsFilePath path(inString + kFileURLPrefixLength, inCreateDirs);
*this = path;
} // nsFileURL::nsFileURL
#endif
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const nsFileURL& inOther)
//----------------------------------------------------------------------------------------
: mURL(nsFileSpecHelpers::StringDup(inOther.mURL))
: mURL(nsFileSpecHelpers::StringDup(inOther.mURL))
#ifdef XP_MAC
, mNativeFileSpec(inOther.GetNativeSpec())
, mNativeFileSpec(inOther.GetNativeSpec())
#endif
{
} // nsFileURL::nsFileURL
@@ -176,18 +245,18 @@ nsFileURL::nsFileURL(const nsFileURL& inOther)
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const nsFilePath& inOther)
//----------------------------------------------------------------------------------------
: mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther))
: mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther))
#ifdef XP_MAC
, mNativeFileSpec(inOther.GetNativeSpec())
, mNativeFileSpec(inOther.GetNativeSpec())
#endif
{
} // nsFileURL::nsFileURL
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const nsNativeFileSpec& inOther)
: mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther)))
: mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther)))
#ifdef XP_MAC
, mNativeFileSpec(inOther)
, mNativeFileSpec(inOther)
#endif
//----------------------------------------------------------------------------------------
{
@@ -197,17 +266,17 @@ nsFileURL::nsFileURL(const nsNativeFileSpec& inOther)
nsFileURL::~nsFileURL()
//----------------------------------------------------------------------------------------
{
delete [] mURL;
delete [] mURL;
}
//----------------------------------------------------------------------------------------
void nsFileURL::operator = (const char* inString)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(mURL, inString);
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
nsFileSpecHelpers::StringAssign(mURL, inString);
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
#ifdef XP_MAC
mNativeFileSpec = inString + kFileURLPrefixLength;
mNativeFileSpec = inString + kFileURLPrefixLength;
#endif
} // nsFileURL::operator =
@@ -215,9 +284,9 @@ void nsFileURL::operator = (const char* inString)
void nsFileURL::operator = (const nsFileURL& inOther)
//----------------------------------------------------------------------------------------
{
mURL = nsFileSpecHelpers::StringAssign(mURL, inOther.mURL);
mURL = nsFileSpecHelpers::StringAssign(mURL, inOther.mURL);
#ifdef XP_MAC
mNativeFileSpec = inOther.GetNativeSpec();
mNativeFileSpec = inOther.GetNativeSpec();
#endif
} // nsFileURL::operator =
@@ -225,10 +294,10 @@ void nsFileURL::operator = (const nsFileURL& inOther)
void nsFileURL::operator = (const nsFilePath& inOther)
//----------------------------------------------------------------------------------------
{
delete [] mURL;
mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther);
delete [] mURL;
mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther);
#ifdef XP_MAC
mNativeFileSpec = inOther.GetNativeSpec();
mNativeFileSpec = inOther.GetNativeSpec();
#endif
} // nsFileURL::operator =
@@ -236,10 +305,10 @@ void nsFileURL::operator = (const nsFilePath& inOther)
void nsFileURL::operator = (const nsNativeFileSpec& inOther)
//----------------------------------------------------------------------------------------
{
delete [] mURL;
mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther));
delete [] mURL;
mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther));
#ifdef XP_MAC
mNativeFileSpec = inOther;
mNativeFileSpec = inOther;
#endif
} // nsFileURL::operator =
@@ -251,26 +320,27 @@ nsOutputFileStream& operator << (nsOutputFileStream& s, const nsFileURL& url)
}
//========================================================================================
// nsFilePath implementation
// nsFilePath implementation
//========================================================================================
#ifndef XP_MAC
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const char* inString)
nsFilePath::nsFilePath(const char* inString, bool inCreateDirs)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inString))
#ifdef XP_MAC
, mNativeFileSpec(inString)
#endif
: mPath(nsFileSpecHelpers::StringDup(inString))
{
NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
// Make canonical and absolute.
nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
}
#endif
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const nsFileURL& inOther)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inOther.mURL + kFileURLPrefixLength))
: mPath(nsFileSpecHelpers::StringDup(inOther.mURL + kFileURLPrefixLength))
#ifdef XP_MAC
, mNativeFileSpec(inOther.GetNativeSpec())
, mNativeFileSpec(inOther.GetNativeSpec())
#endif
{
}
@@ -288,7 +358,7 @@ nsFilePath::nsFilePath(const nsNativeFileSpec& inOther)
nsFilePath::~nsFilePath()
//----------------------------------------------------------------------------------------
{
delete [] mPath;
delete [] mPath;
}
#ifdef XP_UNIX
@@ -304,10 +374,13 @@ void nsFilePath::operator = (const nsNativeFileSpec& inOther)
void nsFilePath::operator = (const char* inString)
//----------------------------------------------------------------------------------------
{
NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
nsFileSpecHelpers::StringAssign(mPath, inString);
NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
#ifdef XP_MAC
mNativeFileSpec = inString;
mNativeFileSpec = inString;
nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(mNativeFileSpec));
#else
nsFileSpecHelpers::StringAssign(mPath, inString);
nsFileSpecHelpers::Canonify(mPath, true);
#endif
}
@@ -315,21 +388,21 @@ void nsFilePath::operator = (const char* inString)
void nsFilePath::operator = (const nsFileURL& inOther)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(inOther));
nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(inOther));
#ifdef XP_MAC
mNativeFileSpec = inOther.GetNativeSpec();
mNativeFileSpec = inOther.GetNativeSpec();
#endif
}
//========================================================================================
// nsNativeFileSpec implementation
// nsNativeFileSpec implementation
//========================================================================================
#ifndef XP_MAC
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec()
//----------------------------------------------------------------------------------------
: mPath(NULL)
: mPath(NULL)
{
}
#endif
@@ -338,7 +411,7 @@ nsNativeFileSpec::nsNativeFileSpec()
nsNativeFileSpec::nsNativeFileSpec(const nsFileURL& inURL)
//----------------------------------------------------------------------------------------
#ifndef XP_MAC
: mPath(NULL)
: mPath(NULL)
#endif
{
*this = nsFilePath(inURL); // convert to unix path first
@@ -348,44 +421,44 @@ nsNativeFileSpec::nsNativeFileSpec(const nsFileURL& inURL)
void nsNativeFileSpec::MakeUnique(const char* inSuggestedLeafName)
//----------------------------------------------------------------------------------------
{
if (inSuggestedLeafName && *inSuggestedLeafName)
SetLeafName(inSuggestedLeafName);
if (inSuggestedLeafName && *inSuggestedLeafName)
SetLeafName(inSuggestedLeafName);
MakeUnique();
MakeUnique();
} // nsNativeFileSpec::MakeUnique
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::MakeUnique()
//----------------------------------------------------------------------------------------
{
if (!Exists())
return;
if (!Exists())
return;
char* leafName = GetLeafName();
if (!leafName)
return;
char* leafName = GetLeafName();
if (!leafName)
return;
char* lastDot = strrchr(leafName, '.');
char* suffix = "";
if (lastDot)
{
suffix = nsFileSpecHelpers::StringDup(lastDot); // include '.'
*lastDot = '\0'; // strip suffix and dot.
}
const int kMaxRootLength
= nsFileSpecHelpers::kMaxCoreLeafNameLength - strlen(suffix) - 1;
if (strlen(leafName) > kMaxRootLength)
leafName[kMaxRootLength] = '\0';
for (short index = 1; index < 1000 && Exists(); index++)
{
// start with "Picture-1.jpg" after "Picture.jpg" exists
char newName[nsFileSpecHelpers::kMaxFilenameLength + 1];
sprintf(newName, "%s-%d%s", leafName, index, suffix);
SetLeafName(newName);
}
if (*suffix)
delete [] suffix;
delete [] leafName;
char* lastDot = strrchr(leafName, '.');
char* suffix = "";
if (lastDot)
{
suffix = nsFileSpecHelpers::StringDup(lastDot); // include '.'
*lastDot = '\0'; // strip suffix and dot.
}
const int kMaxRootLength
= nsFileSpecHelpers::kMaxCoreLeafNameLength - strlen(suffix) - 1;
if (strlen(leafName) > kMaxRootLength)
leafName[kMaxRootLength] = '\0';
for (short index = 1; index < 1000 && Exists(); index++)
{
// start with "Picture-1.jpg" after "Picture.jpg" exists
char newName[nsFileSpecHelpers::kMaxFilenameLength + 1];
sprintf(newName, "%s-%d%s", leafName, index, suffix);
SetLeafName(newName);
}
if (*suffix)
delete [] suffix;
delete [] leafName;
} // nsNativeFileSpec::MakeUnique
//----------------------------------------------------------------------------------------
@@ -428,10 +501,12 @@ nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec)
#if defined(XP_UNIX) || defined(XP_PC)
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const char* inString)
nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inString))
{
// Make canonical and absolute.
nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
}
#endif //XP_UNIX,PC
@@ -440,7 +515,7 @@ nsNativeFileSpec::~nsNativeFileSpec()
//----------------------------------------------------------------------------------------
{
#ifndef XP_MAC
delete [] mPath;
delete [] mPath;
#endif
}
@@ -472,3 +547,12 @@ nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec&
}
#endif // DEBUG && XP_UNIX
//----------------------------------------------------------------------------------------
nsNativeFileSpec nsNativeFileSpec::operator + (const char* inRelativePath) const
//----------------------------------------------------------------------------------------
{
nsNativeFileSpec result = *this;
result += inRelativePath;
return result;
} // nsNativeFileSpec::operator +

View File

@@ -16,27 +16,205 @@
* Reserved.
*/
// This file is included by nsFileSpec.cpp, and includes the Unix-specific
// implementations.
// This file is included by nsFileSpec.cpp, and includes the Unix-specific
// implementations.
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/dir.h>
#include <unistd.h>
#include <stdlib.h>
//----------------------------------------------------------------------------------------
void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs)
// Canonify, make absolute, and check whether directories exist
//----------------------------------------------------------------------------------------
{
if (!ioPath)
return;
if (inMakeDirs)
{
const mode_t mode = 0700;
nsFileSpecHelpers::MakeAllDirectories(ioPath, mode);
}
char buffer[MAXPATHLEN];
errno = 0;
*buffer = '\0';
char* canonicalPath = realpath(ioPath, buffer);
if (!canonicalPath)
{
// Linux's realpath() is pathetically buggy. If the reason for the nil
// result is just that the leaf does not exist, strip the leaf off,
// process that, and then add the leaf back.
char* allButLeaf = nsFileSpecHelpers::StringDup(ioPath);
if (!allButLeaf)
return;
char* lastSeparator = strrchr(allButLeaf, '/');
if (lastSeparator)
{
*lastSeparator = '\0';
canonicalPath = realpath(allButLeaf, buffer);
strcat(buffer, "/");
// Add back the leaf
strcat(buffer, ++lastSeparator);
}
delete [] allButLeaf;
}
if (!canonicalPath && *ioPath != '/' && !inMakeDirs)
{
// Well, if it's a relative path, hack it ourselves.
canonicalPath = realpath(".", buffer);
if (canonicalPath)
{
strcat(canonicalPath, "/");
strcat(canonicalPath, ioPath);
}
}
if (canonicalPath)
nsFileSpecHelpers::StringAssign(ioPath, canonicalPath);
} // nsFileSpecHelpers::Canonify
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::SetLeafName(const char* inLeafName)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::LeafReplace(mPath, '/', inLeafName);
nsFileSpecHelpers::LeafReplace(mPath, '/', inLeafName);
} // nsNativeFileSpec::SetLeafName
//----------------------------------------------------------------------------------------
char* nsNativeFileSpec::GetLeafName() const
//----------------------------------------------------------------------------------------
{
return nsFileSpecHelpers::GetLeaf(mPath, '/');
return nsFileSpecHelpers::GetLeaf(mPath, '/');
} // nsNativeFileSpec::GetLeafName
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::Exists() const
//----------------------------------------------------------------------------------------
{
return false; // fixme
struct stat st;
return 0 == stat(mPath, &st);
} // nsNativeFileSpec::Exists
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsFile() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && S_ISREG(st.st_mode);
} // nsNativeFileSpec::IsFile
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsDirectory() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && S_ISDIR(st.st_mode);
} // nsNativeFileSpec::IsDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(outSpec.mPath, mPath);
char* cp = strrchr(outSpec.mPath, '/');
if (cp)
*cp = '\0';
} // nsNativeFileSpec::GetParent
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator += (const char* inRelativePath)
//----------------------------------------------------------------------------------------
{
if (!inRelativePath || !mPath)
return;
if (mPath[strlen(mPath) - 1] != '/')
char* newPath = nsFileSpecHelpers::ReallocCat(mPath, "/");
SetLeafName(inRelativePath);
} // nsNativeFileSpec::operator +=
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::CreateDirectory(int mode)
//----------------------------------------------------------------------------------------
{
// Note that mPath is canonical!
mkdir(mPath, mode);
} // nsNativeFileSpec::CreateDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::Delete(bool inRecursive)
// To check if this worked, call Exists() afterwards, see?
//----------------------------------------------------------------------------------------
{
if (IsDirectory())
{
if (inRecursive)
{
for (nsDirectoryIterator i(*this); i; i++)
{
nsNativeFileSpec& child = (nsNativeFileSpec&)i;
child.Delete(inRecursive);
}
}
rmdir(mPath);
}
else
remove(mPath);
} // nsNativeFileSpec::Delete
//========================================================================================
// nsDirectoryIterator
//========================================================================================
//----------------------------------------------------------------------------------------
nsDirectoryIterator::nsDirectoryIterator(
const nsNativeFileSpec& inDirectory
, int inIterateDirection)
//----------------------------------------------------------------------------------------
: mCurrent(inDirectory)
, mDir(nsnull)
, mExists(false)
{
mCurrent += "sysygy"; // prepare the path for SetLeafName
mDir = opendir((const char*)nsFilePath(inDirectory));
++(*this);
} // nsDirectoryIterator::nsDirectoryIterator
//----------------------------------------------------------------------------------------
nsDirectoryIterator::~nsDirectoryIterator()
//----------------------------------------------------------------------------------------
{
if (mDir)
closedir(mDir);
} // nsDirectoryIterator::nsDirectoryIterator
//----------------------------------------------------------------------------------------
nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
//----------------------------------------------------------------------------------------
{
mExists = false;
if (!mDir)
return *this;
char* dot = ".";
char* dotdot = "..";
struct dirent* entry = readdir(mDir);
if (entry && strcmp(entry->d_name, dot) == 0)
entry = readdir(mDir);
if (entry && strcmp(entry->d_name, dotdot) == 0)
entry = readdir(mDir);
if (entry)
{
mExists = true;
mCurrent.SetLeafName(entry->d_name);
}
return *this;
} // nsDirectoryIterator::operator ++
//----------------------------------------------------------------------------------------
nsDirectoryIterator& nsDirectoryIterator::operator -- ()
//----------------------------------------------------------------------------------------
{
return ++(*this); // can't do it backwards.
} // nsDirectoryIterator::operator --

View File

@@ -19,6 +19,17 @@
// This file is included by nsFileSpec.cp, and includes the Windows-specific
// implementations.
#include <stat.h>
//----------------------------------------------------------------------------------------
void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs)
// Canonify, make absolute, and check whether directories exist
//----------------------------------------------------------------------------------------
{
NS_NOTYETIMPLEMENTED("Please, some Winhead please write this!");
return ioPath;
}
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
@@ -31,9 +42,17 @@ nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath)
void nsNativeFileSpec::operator = (const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
{
// Convert '/' to '\'
nsFileSpecHelpers::StringAssign(mPath, (const char*)inPath);
for (char* cp = mPath; *cp; cp++)
// Strip the leading slash, which should
// leave us pointing to a drive letter.
nsFileSpecHelpers::StringAssign(mPath, (const char*)inPath + 1);
// Convert the vertical slash to a colon
char* cp = mPath + 1;
if (strstr(cp, "|/") == cp)
*cp = ':';
// Convert '/' to '\'.
while (*++cp)
{
if (*cp == '/')
*cp = '\\';
@@ -79,6 +98,138 @@ char* nsNativeFileSpec::GetLeafName() const
bool nsNativeFileSpec::Exists() const
//----------------------------------------------------------------------------------------
{
return false; // fixme
struct stat st;
return 0 == stat(mPath, &st);
} // nsNativeFileSpec::Exists
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsFile() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && S_ISREG(st.st_mode);
} // nsNativeFileSpec::IsFile
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsDirectory() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && S_ISDIR(st.st_mode);
} // nsNativeFileSpec::IsDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(outSpec.mPath, mPath);
char* cp = strrchr(outSpec.mPath, '\\');
if (cp)
*cp = '\0';
} // nsNativeFileSpec::GetParent
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator += (const char* inRelativePath)
//----------------------------------------------------------------------------------------
{
if (!inRelativePath || !mPath)
return;
if (mPath[strlen(mPath) - 1] != '\\')
char* newPath = nsFileSpecHelpers::ReallocCat(mPath, "\\");
SetLeafName(inRelativePath);
} // nsNativeFileSpec::operator +=
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::CreateDirectory()
//----------------------------------------------------------------------------------------
{
// Note that mPath is canonical!
NS_NOTYETIMPLEMENTED("Please, some Winhead please fix this!");
mkdir(mPath, mode);
} // nsNativeFileSpec::CreateDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::Delete(bool inRecursive)
//----------------------------------------------------------------------------------------
{
if (IsDirectory())
{
if (inRecursive)
{
for (nsDirectoryIterator i(*this); i; i++)
{
const nsNativeFileSpec& child = (nsNativeFileSpec&)i;
child.Delete(inRecursive);
}
}
NS_NOTYETIMPLEMENTED("Please, some Winhead please fix this!");
rmdir(mPath);
}
else
{
NS_NOTYETIMPLEMENTED("Please, some Winhead please write this!");
remove(mPath);
}
} // nsNativeFileSpec::Delete
//========================================================================================
// nsDirectoryIterator
//========================================================================================
//----------------------------------------------------------------------------------------
nsDirectoryIterator::nsDirectoryIterator(
const nsNativeFileSpec& inDirectory
, int inIterateDirection)
//----------------------------------------------------------------------------------------
: mCurrent(inDirectory)
#if 0 // Some kind winhead please build, test, and remove when ready.
, mDir(nsnull)
#endif // XP_PC -- ifdef to be removed.
, mExists(false)
{
NS_NOTYETIMPLEMENTED("Please, some kind Winhead please check this!");
mCurrent += "foo";
#if 0 // Some kind winhead please build, test, and remove when ready.
mDir = opendir(mPath);
#endif // XP_PC -- ifdef to be removed.
++(*this);
} // nsDirectoryIterator::nsDirectoryIterator
//----------------------------------------------------------------------------------------
nsDirectoryIterator::~nsDirectoryIterator()
//----------------------------------------------------------------------------------------
{
NS_NOTYETIMPLEMENTED("Please, some kind Winhead please check this!");
#if 0 // Some kind winhead please build, test, and remove when ready.
if (mDir)
closedir(mDir);
#endif // XP_PC -- ifdef to be removed.
} // nsDirectoryIterator::nsDirectoryIterator
//----------------------------------------------------------------------------------------
nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
//----------------------------------------------------------------------------------------
{
mExists = false;
NS_NOTYETIMPLEMENTED("Please, some kind Winhead please check this!");
#if 0 // Some kind winhead please build, test, and remove when ready.
if (!mDir)
return *this;
struct dirent* entry = readdir(mDir);
if (entry)
{
mExists = true;
mCurrent.SetLeafName(entry->d_name);
}
#endif // XP_PC -- ifdef to be removed.
return *this;
} // nsDirectoryIterator::operator ++
//----------------------------------------------------------------------------------------
nsDirectoryIterator& nsDirectoryIterator::operator -- ()
//----------------------------------------------------------------------------------------
{
return ++(*this); // can't do it backwards.
} // nsDirectoryIterator::operator --

View File

@@ -11,7 +11,7 @@ void FilesTest::WriteStuff(nsOutputFileStream& s)
//----------------------------------------------------------------------------------------
{
// Initialize a URL from a string without suffix. Change the path to suit your machine.
nsFileURL fileURL("file:///Development/MPW/MPW%20Shell");
nsFileURL fileURL("file:///Development/MPW/MPW%20Shell", false);
s << "File URL initialized to: \"" << fileURL << "\""<< nsEndl;
// Initialize a Unix path from a URL
@@ -44,7 +44,7 @@ void FilesTest::WriteStuff(nsOutputFileStream& s)
} // WriteStuff
//----------------------------------------------------------------------------------------
void main()
int main()
// For use with DEBUG defined.
//----------------------------------------------------------------------------------------
{
@@ -59,38 +59,59 @@ void main()
FilesTest::WriteStuff(nsOut);
nsOut << nsEndl << nsEndl;
// Test of nsOutputFileStream
nsFilePath myTextFilePath("iotest.txt");
// - Test of nsOutputFileStream
nsFilePath myTextFilePath("mumble/iotest.txt", true); // relative path.
const char* pathAsString = (const char*)myTextFilePath;
if (*pathAsString != '/')
{
nsOut << "WRITING IDENTICAL OUTPUT TO " << (const char*)myTextFilePath << nsEndl << nsEndl;
nsOut
<< "ERROR: after initializing the path object with a relative path,"
<< "\n the path consisted of the string "
<< "\n\t" << pathAsString
<< "\n which is not a canonical full path!"
<< nsEndl;
return -1;
}
nsNativeFileSpec mySpec(myTextFilePath);
{
nsOut << "WRITING IDENTICAL OUTPUT TO " << pathAsString << nsEndl << nsEndl;
nsOutputFileStream testStream(myTextFilePath);
if (!testStream.is_open())
{
nsOut
<< "ERROR: File "
<< (const char*)myTextFilePath
<< pathAsString
<< " could not be opened for output"
<< nsEndl;
return;
return -1;
}
FilesTest::WriteStuff(testStream);
} // <-- Scope closes the stream (and the file).
// Test of nsInputFileStream
if (!mySpec.Exists() || mySpec.IsDirectory() || !mySpec.IsFile())
{
nsOut
<< "ERROR: File "
<< pathAsString
<< " is not a file (cela n'est pas un pipe)"
<< nsEndl;
return -1;
}
// - Test of nsInputFileStream
{
nsOut << "READING BACK DATA FROM " << (const char*)myTextFilePath << nsEndl << nsEndl;
nsOut << "READING BACK DATA FROM " << pathAsString << nsEndl << nsEndl;
nsInputFileStream testStream2(myTextFilePath);
if (!testStream2.is_open())
{
nsOut
<< "ERROR: File "
<< (const char*)myTextFilePath
<< pathAsString
<< " could not be opened for input"
<< nsEndl;
return;
return -1;
}
char line[1000];
@@ -101,4 +122,101 @@ void main()
nsOut << line << nsEndl;
}
} // <-- Scope closes the stream (and the file).
// - Test of GetParent()
nsNativeFileSpec parent;
mySpec.GetParent(parent);
nsFilePath parentPath(parent);
nsOut
<< "GetParent() on "
<< "\n\t" << pathAsString
<< "\n yields "
<< "\n\t" << (const char*)parentPath
<< nsEndl;
// - Test of non-recursive delete
nsOut
<< "Attempting to delete "
<< "\n\t" << (const char*)parentPath
<< "\n without recursive option (should fail)"
<< nsEndl;
parent.Delete(false);
if (parent.Exists())
nsOut << "Test passed." << nsEndl;
else
{
nsOut
<< "ERROR: File "
<< "\n\t" << (const char*)parentPath
<< "\n has been deleted without the recursion option,"
<< "\n and is a nonempty directory!"
<< nsEndl;
return -1;
}
// - Test of recursive delete
nsOut
<< "Deleting "
<< "\n\t" << (const char*)parentPath
<< "\n with recursive option"
<< nsEndl;
parent.Delete(true);
if (parent.Exists())
{
nsOut
<< "ERROR: Directory "
<< "\n\t" << (const char*)parentPath
<< "\n has NOT been deleted despite the recursion option!"
<< nsEndl;
return -1;
}
else
nsOut << "Test passed." << nsEndl;
// - Test of CreateDirectory
nsOut
<< "Testing CreateDirectory() using"
<< "\n\t" << (const char*)parentPath
<< nsEndl;
parent.CreateDirectory();
if (parent.Exists())
nsOut << "Test passed." << nsEndl;
else
{
nsOut << "ERROR: Test failed." << nsEndl;
return -1;
}
parent.Delete(true);
#ifndef XP_PC // uncomment when tested and ready.
// - Test of directory iterator
nsNativeFileSpec grandparent;
parent.GetParent(grandparent); // should be the original default directory.
nsFilePath grandparentPath(grandparent);
nsOut << "Forwards listing of " << (const char*)grandparentPath << ":" << nsEndl;
for (nsDirectoryIterator i(grandparent, +1); i; i++)
{
char* itemName = ((nsNativeFileSpec&)i).GetLeafName();
nsOut << '\t' << itemName << nsEndl;
delete [] itemName;
}
nsOut << "Backwards listing of " << (const char*)grandparentPath << ":" << nsEndl;
for (nsDirectoryIterator i(grandparent, -1); i; i--)
{
char* itemName = ((nsNativeFileSpec&)i).GetLeafName();
nsOut << '\t' << itemName << nsEndl;
delete [] itemName;
}
#endif
return 0;
} // main

View File

@@ -30,115 +30,180 @@
NS_NAMESPACE nsFileSpecHelpers
//========================================================================================
{
enum
{ kMaxFilenameLength = 31 // should work on Macintosh, Unix, and Win32.
, kMaxAltDigitLength = 5
, kMaxCoreLeafNameLength = (kMaxFilenameLength - (kMaxAltDigitLength + 1))
};
NS_NAMESPACE_PROTOTYPE void LeafReplace(
char*& ioPath,
char inSeparator,
const char* inLeafName);
NS_NAMESPACE_PROTOTYPE char* GetLeaf(const char* inPath, char inSeparator); // allocated
NS_NAMESPACE_PROTOTYPE char* StringDup(const char* inString, int allocLength = 0);
NS_NAMESPACE_PROTOTYPE char* AllocCat(const char* inString1, const char* inString2);
NS_NAMESPACE_PROTOTYPE char* StringAssign(char*& ioString, const char* inOther);
enum
{ kMaxFilenameLength = 31 // should work on Macintosh, Unix, and Win32.
, kMaxAltDigitLength = 5
, kMaxCoreLeafNameLength = (kMaxFilenameLength - (kMaxAltDigitLength + 1))
};
NS_NAMESPACE_PROTOTYPE void LeafReplace(
char*& ioPath,
char inSeparator,
const char* inLeafName);
#ifndef XP_MAC
NS_NAMESPACE_PROTOTYPE void Canonify(char*& ioPath, bool inMakeDirs);
NS_NAMESPACE_PROTOTYPE void MakeAllDirectories(const char* inPath, int mode);
#endif
NS_NAMESPACE_PROTOTYPE char* GetLeaf(const char* inPath, char inSeparator); // allocated
NS_NAMESPACE_PROTOTYPE char* StringDup(const char* inString, int allocLength = 0);
NS_NAMESPACE_PROTOTYPE char* AllocCat(const char* inString1, const char* inString2);
NS_NAMESPACE_PROTOTYPE char* StringAssign(char*& ioString, const char* inOther);
NS_NAMESPACE_PROTOTYPE char* ReallocCat(char*& ioString, const char* inString1);
} NS_NAMESPACE_END
//----------------------------------------------------------------------------------------
char* nsFileSpecHelpers::StringDup(
const char* inString,
int allocLength)
const char* inString,
int allocLength)
//----------------------------------------------------------------------------------------
{
if (!allocLength && inString)
allocLength = strlen(inString);
char* newPath = inString || allocLength ? new char[allocLength + 1] : 0;
if (!newPath)
return NULL;
strcpy(newPath, inString);
return newPath;
if (!allocLength && inString)
allocLength = strlen(inString);
char* newPath = inString || allocLength ? new char[allocLength + 1] : nsnull;
if (!newPath)
return NULL;
strcpy(newPath, inString);
return newPath;
} // nsFileSpecHelpers::StringDup
//----------------------------------------------------------------------------------------
char* nsFileSpecHelpers::AllocCat(
const char* inString1,
const char* inString2)
const char* inString1,
const char* inString2)
//----------------------------------------------------------------------------------------
{
if (!inString1)
return inString2 ? StringDup(inString2) : (char*)NULL;
if (!inString2)
return StringDup(inString1);
char* outString = StringDup(inString1, strlen(inString1) + strlen(inString2));
if (outString)
strcat(outString, inString2);
return outString;
if (!inString1)
return inString2 ? StringDup(inString2) : (char*)NULL;
if (!inString2)
return StringDup(inString1);
char* outString = StringDup(inString1, strlen(inString1) + strlen(inString2));
if (outString)
strcat(outString, inString2);
return outString;
} // nsFileSpecHelpers::StringDup
//----------------------------------------------------------------------------------------
char* nsFileSpecHelpers::StringAssign(
char*& ioString,
const char* inString2)
char*& ioString,
const char* inString2)
//----------------------------------------------------------------------------------------
{
if (!inString2)
{
delete [] ioString;
ioString = (char*)NULL;
return ioString;
}
if (!ioString || (strlen(inString2) > strlen(ioString)))
{
delete [] ioString;
ioString = StringDup(inString2);
return ioString;
}
strcpy(ioString, inString2);
return ioString;
if (!inString2)
{
delete [] ioString;
ioString = (char*)NULL;
return ioString;
}
if (!ioString || (strlen(inString2) > strlen(ioString)))
{
delete [] ioString;
ioString = StringDup(inString2);
return ioString;
}
strcpy(ioString, inString2);
return ioString;
} // nsFileSpecHelpers::StringAssign
//----------------------------------------------------------------------------------------
void nsFileSpecHelpers::LeafReplace(
char*& ioPath,
char inSeparator,
const char* inLeafName)
char*& ioPath,
char inSeparator,
const char* inLeafName)
//----------------------------------------------------------------------------------------
{
// Find the existing leaf name
if (!ioPath)
return;
if (!inLeafName)
{
*ioPath = '\0';
return;
}
char* lastSeparator = strrchr(ioPath, inSeparator);
int oldLength = strlen(ioPath);
*(++lastSeparator) = '\0'; // strip the current leaf name
int newLength = lastSeparator - ioPath + strlen(inLeafName);
if (newLength > oldLength)
{
char* newPath = StringDup(ioPath, newLength + 1);
delete [] ioPath;
ioPath = newPath;
}
strcat(ioPath, inLeafName);
} // nsNativeFileSpec::SetLeafName
// Find the existing leaf name
if (!ioPath)
return;
if (!inLeafName)
{
*ioPath = '\0';
return;
}
char* lastSeparator = strrchr(ioPath, inSeparator);
int oldLength = strlen(ioPath);
*(++lastSeparator) = '\0'; // strip the current leaf name
int newLength = lastSeparator - ioPath + strlen(inLeafName);
if (newLength > oldLength)
{
char* newPath = StringDup(ioPath, newLength + 1);
delete [] ioPath;
ioPath = newPath;
}
strcat(ioPath, inLeafName);
} // nsNativeFileSpec::LeafReplace
//----------------------------------------------------------------------------------------
char* nsFileSpecHelpers::GetLeaf(const char* inPath, char inSeparator)
// Returns a pointer to an allocated string representing the leaf.
//----------------------------------------------------------------------------------------
{
if (!inPath)
return NULL;
char* lastSeparator = strrchr(inPath, inSeparator);
if (lastSeparator)
return StringDup(lastSeparator);
return StringDup(inPath);
if (!inPath)
return NULL;
char* lastSeparator = strrchr(inPath, inSeparator);
if (lastSeparator)
return StringDup(++lastSeparator);
return StringDup(inPath);
} // nsNativeFileSpec::GetLeaf
#if defined(XP_UNIX) || defined(XP_PC)
//----------------------------------------------------------------------------------------
void nsFileSpecHelpers::MakeAllDirectories(const char* inPath, int mode)
// Make the path a valid one by creating all the intermediate directories. Does NOT
// make the leaf into a directory. This should be a unix path.
//----------------------------------------------------------------------------------------
{
if (!inPath)
return;
char* pathCopy = nsFileSpecHelpers::StringDup( inPath );
if (!pathCopy)
return;
const char kSeparator = '/'; // I repeat: this should be a unix-style path.
const int kSkipFirst = 1;
#ifdef XP_WIN
NS_ASSERTION( pathCopy[2] == '|', "No drive letter!" );
#endif
char* currentStart = pathCopy;
char* currentEnd = strchr(currentStart + kSkipFirst, kSeparator);
if (currentEnd)
{
*currentEnd = '\0';
nsNativeFileSpec spec(nsFilePath(pathCopy, false));
do
{
// If the node doesn't exist, and it is not the initial node in a full path,
// then make a directory (We cannot make the initial (volume) node).
if (!spec.Exists() && *currentStart != kSeparator)
spec.CreateDirectory(mode);
if (!spec.Exists())
{
NS_ASSERTION(spec.Exists(), "Could not create the directory?");
break;
}
currentStart = ++currentEnd;
currentEnd = strchr(currentStart, kSeparator);
if (!currentEnd)
break;
spec += currentStart; // "lengthen" the path, adding the next node.
} while (currentEnd);
}
delete [] pathCopy;
} // nsFileSpecHelpers::MakeAllDirectories
#endif // XP_PC || XP_UNIX
//----------------------------------------------------------------------------------------
char* nsFileSpecHelpers::ReallocCat(char*& ioString, const char* inString1)
//----------------------------------------------------------------------------------------
{
char* newString = AllocCat(ioString, inString1);
delete [] ioString;
ioString = newString;
return ioString;
} // nsNativeFileSpec::ReallocCat
#if defined(XP_PC)
#include "windows/nsFileSpecWin.cpp" // Windows-specific implementations
@@ -149,26 +214,30 @@ char* nsFileSpecHelpers::GetLeaf(const char* inPath, char inSeparator)
#endif
//========================================================================================
// nsFileURL implementation
// nsFileURL implementation
//========================================================================================
#ifndef XP_MAC
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const char* inString)
nsFileURL::nsFileURL(const char* inString, bool inCreateDirs)
//----------------------------------------------------------------------------------------
: mURL(nsFileSpecHelpers::StringDup(inString))
#ifdef XP_MAC
, mNativeFileSpec(inString + kFileURLPrefixLength)
#endif
: mURL(nsnull)
{
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
if (!inString)
return;
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
// Make canonical and absolute.
nsFilePath path(inString + kFileURLPrefixLength, inCreateDirs);
*this = path;
} // nsFileURL::nsFileURL
#endif
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const nsFileURL& inOther)
//----------------------------------------------------------------------------------------
: mURL(nsFileSpecHelpers::StringDup(inOther.mURL))
: mURL(nsFileSpecHelpers::StringDup(inOther.mURL))
#ifdef XP_MAC
, mNativeFileSpec(inOther.GetNativeSpec())
, mNativeFileSpec(inOther.GetNativeSpec())
#endif
{
} // nsFileURL::nsFileURL
@@ -176,18 +245,18 @@ nsFileURL::nsFileURL(const nsFileURL& inOther)
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const nsFilePath& inOther)
//----------------------------------------------------------------------------------------
: mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther))
: mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther))
#ifdef XP_MAC
, mNativeFileSpec(inOther.GetNativeSpec())
, mNativeFileSpec(inOther.GetNativeSpec())
#endif
{
} // nsFileURL::nsFileURL
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const nsNativeFileSpec& inOther)
: mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther)))
: mURL(nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther)))
#ifdef XP_MAC
, mNativeFileSpec(inOther)
, mNativeFileSpec(inOther)
#endif
//----------------------------------------------------------------------------------------
{
@@ -197,17 +266,17 @@ nsFileURL::nsFileURL(const nsNativeFileSpec& inOther)
nsFileURL::~nsFileURL()
//----------------------------------------------------------------------------------------
{
delete [] mURL;
delete [] mURL;
}
//----------------------------------------------------------------------------------------
void nsFileURL::operator = (const char* inString)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(mURL, inString);
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
nsFileSpecHelpers::StringAssign(mURL, inString);
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
#ifdef XP_MAC
mNativeFileSpec = inString + kFileURLPrefixLength;
mNativeFileSpec = inString + kFileURLPrefixLength;
#endif
} // nsFileURL::operator =
@@ -215,9 +284,9 @@ void nsFileURL::operator = (const char* inString)
void nsFileURL::operator = (const nsFileURL& inOther)
//----------------------------------------------------------------------------------------
{
mURL = nsFileSpecHelpers::StringAssign(mURL, inOther.mURL);
mURL = nsFileSpecHelpers::StringAssign(mURL, inOther.mURL);
#ifdef XP_MAC
mNativeFileSpec = inOther.GetNativeSpec();
mNativeFileSpec = inOther.GetNativeSpec();
#endif
} // nsFileURL::operator =
@@ -225,10 +294,10 @@ void nsFileURL::operator = (const nsFileURL& inOther)
void nsFileURL::operator = (const nsFilePath& inOther)
//----------------------------------------------------------------------------------------
{
delete [] mURL;
mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther);
delete [] mURL;
mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)inOther);
#ifdef XP_MAC
mNativeFileSpec = inOther.GetNativeSpec();
mNativeFileSpec = inOther.GetNativeSpec();
#endif
} // nsFileURL::operator =
@@ -236,10 +305,10 @@ void nsFileURL::operator = (const nsFilePath& inOther)
void nsFileURL::operator = (const nsNativeFileSpec& inOther)
//----------------------------------------------------------------------------------------
{
delete [] mURL;
mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther));
delete [] mURL;
mURL = nsFileSpecHelpers::AllocCat(kFileURLPrefix, (const char*)nsFilePath(inOther));
#ifdef XP_MAC
mNativeFileSpec = inOther;
mNativeFileSpec = inOther;
#endif
} // nsFileURL::operator =
@@ -251,26 +320,27 @@ nsOutputFileStream& operator << (nsOutputFileStream& s, const nsFileURL& url)
}
//========================================================================================
// nsFilePath implementation
// nsFilePath implementation
//========================================================================================
#ifndef XP_MAC
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const char* inString)
nsFilePath::nsFilePath(const char* inString, bool inCreateDirs)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inString))
#ifdef XP_MAC
, mNativeFileSpec(inString)
#endif
: mPath(nsFileSpecHelpers::StringDup(inString))
{
NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
// Make canonical and absolute.
nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
}
#endif
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const nsFileURL& inOther)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inOther.mURL + kFileURLPrefixLength))
: mPath(nsFileSpecHelpers::StringDup(inOther.mURL + kFileURLPrefixLength))
#ifdef XP_MAC
, mNativeFileSpec(inOther.GetNativeSpec())
, mNativeFileSpec(inOther.GetNativeSpec())
#endif
{
}
@@ -288,7 +358,7 @@ nsFilePath::nsFilePath(const nsNativeFileSpec& inOther)
nsFilePath::~nsFilePath()
//----------------------------------------------------------------------------------------
{
delete [] mPath;
delete [] mPath;
}
#ifdef XP_UNIX
@@ -304,10 +374,13 @@ void nsFilePath::operator = (const nsNativeFileSpec& inOther)
void nsFilePath::operator = (const char* inString)
//----------------------------------------------------------------------------------------
{
NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
nsFileSpecHelpers::StringAssign(mPath, inString);
NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
#ifdef XP_MAC
mNativeFileSpec = inString;
mNativeFileSpec = inString;
nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(mNativeFileSpec));
#else
nsFileSpecHelpers::StringAssign(mPath, inString);
nsFileSpecHelpers::Canonify(mPath, true);
#endif
}
@@ -315,21 +388,21 @@ void nsFilePath::operator = (const char* inString)
void nsFilePath::operator = (const nsFileURL& inOther)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(inOther));
nsFileSpecHelpers::StringAssign(mPath, (const char*)nsFilePath(inOther));
#ifdef XP_MAC
mNativeFileSpec = inOther.GetNativeSpec();
mNativeFileSpec = inOther.GetNativeSpec();
#endif
}
//========================================================================================
// nsNativeFileSpec implementation
// nsNativeFileSpec implementation
//========================================================================================
#ifndef XP_MAC
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec()
//----------------------------------------------------------------------------------------
: mPath(NULL)
: mPath(NULL)
{
}
#endif
@@ -338,7 +411,7 @@ nsNativeFileSpec::nsNativeFileSpec()
nsNativeFileSpec::nsNativeFileSpec(const nsFileURL& inURL)
//----------------------------------------------------------------------------------------
#ifndef XP_MAC
: mPath(NULL)
: mPath(NULL)
#endif
{
*this = nsFilePath(inURL); // convert to unix path first
@@ -348,44 +421,44 @@ nsNativeFileSpec::nsNativeFileSpec(const nsFileURL& inURL)
void nsNativeFileSpec::MakeUnique(const char* inSuggestedLeafName)
//----------------------------------------------------------------------------------------
{
if (inSuggestedLeafName && *inSuggestedLeafName)
SetLeafName(inSuggestedLeafName);
if (inSuggestedLeafName && *inSuggestedLeafName)
SetLeafName(inSuggestedLeafName);
MakeUnique();
MakeUnique();
} // nsNativeFileSpec::MakeUnique
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::MakeUnique()
//----------------------------------------------------------------------------------------
{
if (!Exists())
return;
if (!Exists())
return;
char* leafName = GetLeafName();
if (!leafName)
return;
char* leafName = GetLeafName();
if (!leafName)
return;
char* lastDot = strrchr(leafName, '.');
char* suffix = "";
if (lastDot)
{
suffix = nsFileSpecHelpers::StringDup(lastDot); // include '.'
*lastDot = '\0'; // strip suffix and dot.
}
const int kMaxRootLength
= nsFileSpecHelpers::kMaxCoreLeafNameLength - strlen(suffix) - 1;
if (strlen(leafName) > kMaxRootLength)
leafName[kMaxRootLength] = '\0';
for (short index = 1; index < 1000 && Exists(); index++)
{
// start with "Picture-1.jpg" after "Picture.jpg" exists
char newName[nsFileSpecHelpers::kMaxFilenameLength + 1];
sprintf(newName, "%s-%d%s", leafName, index, suffix);
SetLeafName(newName);
}
if (*suffix)
delete [] suffix;
delete [] leafName;
char* lastDot = strrchr(leafName, '.');
char* suffix = "";
if (lastDot)
{
suffix = nsFileSpecHelpers::StringDup(lastDot); // include '.'
*lastDot = '\0'; // strip suffix and dot.
}
const int kMaxRootLength
= nsFileSpecHelpers::kMaxCoreLeafNameLength - strlen(suffix) - 1;
if (strlen(leafName) > kMaxRootLength)
leafName[kMaxRootLength] = '\0';
for (short index = 1; index < 1000 && Exists(); index++)
{
// start with "Picture-1.jpg" after "Picture.jpg" exists
char newName[nsFileSpecHelpers::kMaxFilenameLength + 1];
sprintf(newName, "%s-%d%s", leafName, index, suffix);
SetLeafName(newName);
}
if (*suffix)
delete [] suffix;
delete [] leafName;
} // nsNativeFileSpec::MakeUnique
//----------------------------------------------------------------------------------------
@@ -428,10 +501,12 @@ nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec)
#if defined(XP_UNIX) || defined(XP_PC)
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const char* inString)
nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs)
//----------------------------------------------------------------------------------------
: mPath(nsFileSpecHelpers::StringDup(inString))
{
// Make canonical and absolute.
nsFileSpecHelpers::Canonify(mPath, inCreateDirs);
}
#endif //XP_UNIX,PC
@@ -440,7 +515,7 @@ nsNativeFileSpec::~nsNativeFileSpec()
//----------------------------------------------------------------------------------------
{
#ifndef XP_MAC
delete [] mPath;
delete [] mPath;
#endif
}
@@ -472,3 +547,12 @@ nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec&
}
#endif // DEBUG && XP_UNIX
//----------------------------------------------------------------------------------------
nsNativeFileSpec nsNativeFileSpec::operator + (const char* inRelativePath) const
//----------------------------------------------------------------------------------------
{
nsNativeFileSpec result = *this;
result += inRelativePath;
return result;
} // nsNativeFileSpec::operator +

View File

@@ -127,6 +127,10 @@
#ifdef XP_MAC
#include <Files.h>
#elif defined(XP_UNIX) || defined (XP_OS2)
#include <dirent.h>
#elif 0 // defined(XP_PC)
#include "winfile.h"
#endif
//========================================================================================
@@ -150,7 +154,7 @@ class NS_BASE nsNativeFileSpec
{
public:
nsNativeFileSpec();
explicit nsNativeFileSpec(const char* inString);
explicit nsNativeFileSpec(const char* inString, bool inCreateDirs = false);
explicit nsNativeFileSpec(const nsFilePath& inPath);
explicit nsNativeFileSpec(const nsFileURL& inURL);
nsNativeFileSpec(const nsNativeFileSpec& inPath);
@@ -177,12 +181,12 @@ class NS_BASE nsNativeFileSpec
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.
// 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);
// Called for the spec of an alias. Modifies the spec to
// point to the original. Sets mError.
// Called for the spec of an alias. Modifies the spec to
// point to the original. Sets mError.
void MakeUnique(ConstStr255Param inSuggestedLeafName);
StringPtr GetLeafPName() { return mSpec.name; }
ConstStr255Param GetLeafPName() const { return mSpec.name; }
@@ -194,14 +198,58 @@ class NS_BASE nsNativeFileSpec
bool Valid() const { return true; } // Fixme.
#endif // XP_MAC
friend NS_BASE nsOutputFileStream& operator << (nsOutputFileStream& s, const nsNativeFileSpec& spec);
friend NS_BASE nsOutputFileStream& operator << (
nsOutputFileStream& s,
const nsNativeFileSpec& spec);
//--------------------------------------------------
// Queries and path algebra. These do not modify the disk.
//--------------------------------------------------
char* GetLeafName() const; // Allocated. Use delete [].
void SetLeafName(const char* inLeafName);
bool Exists() const;
// inLeafName can be a relative path, so this allows
// one kind of concatenation of "paths".
void GetParent(nsNativeFileSpec& 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,
// however, that the top node is still not a name,
// but a spec. Volumes on Macintosh can have identical
// names. Perhaps could be used for an operator --() ?
nsNativeFileSpec 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.
// This must be a directory for this to work. This differs
// from SetLeafName(), since the latter will work
// starting with a sibling of the directory and throws
// away its leaf information, whereas this one assumes
// this is a directory, and the relative path starts
// "below" this.
void MakeUnique();
void MakeUnique(const char* inSuggestedLeafName);
bool IsDirectory() const;
// More stringent than Exists()
bool IsFile() const;
// More stringent than Exists()
bool Exists() const;
//--------------------------------------------------
// Creation and deletion of objects. These can modify the disk.
//--------------------------------------------------
void CreateDirectory(int mode = 0700 /* for unix */);
void Delete(bool inRecursive);
//--------------------------------------------------
// Data
//--------------------------------------------------
private:
friend class nsFilePath;
#ifdef XP_MAC
@@ -221,7 +269,7 @@ class NS_BASE nsFileURL
{
public:
nsFileURL(const nsFileURL& inURL);
explicit nsFileURL(const char* inString);
explicit nsFileURL(const char* inString, bool inCreateDirs = false);
explicit nsFileURL(const nsFilePath& inPath);
explicit nsFileURL(const nsNativeFileSpec& inPath);
virtual ~nsFileURL();
@@ -247,7 +295,7 @@ class NS_BASE nsFileURL
operator char* ();
operator const char* const ();
private:
friend class nsFilePath; // to allow construction of nsFilePath
friend class nsFilePath; // to allow construction of nsFilePath
char* mURL;
#ifdef XP_MAC
// Since the path on the macintosh does not uniquely specify a file (volumes
@@ -264,7 +312,7 @@ class NS_BASE nsFilePath
{
public:
nsFilePath(const nsFilePath& inPath);
explicit nsFilePath(const char* inString);
explicit nsFilePath(const char* inString, bool inCreateDirs = false);
explicit nsFilePath(const nsFileURL& inURL);
explicit nsFilePath(const nsNativeFileSpec& inPath);
virtual ~nsFilePath();
@@ -292,7 +340,7 @@ class NS_BASE nsFilePath
private:
char* mPath;
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.
@@ -300,4 +348,52 @@ class NS_BASE nsFilePath
#endif
}; // class nsFilePath
//========================================================================================
class nsDirectoryIterator
// Example:
//
// nsNativeFileSpec parentDir(...); // directory over whose children we shall iterate
// for (nsDirectoryIterator i(parentDir); i; i++)
// {
// // do something with (const nsNativeFileSpec&)i
// }
//
// or:
//
// for (nsDirectoryIterator i(parentDir, false); i; i--)
// {
// // do something with (const nsNativeFileSpec&)i
// }
//
// Currently, the only platform on which backwards iteration actually goes backwards
// is Macintosh. On other platforms, both styles will work, but will go forwards.
//========================================================================================
{
public:
nsDirectoryIterator(
const nsNativeFileSpec& 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; }
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; }
private:
nsNativeFileSpec mCurrent;
bool mExists;
#if defined(XP_UNIX) // || defined(XP_PC) add when ready
DIR* mDir;
#elif defined(XP_MAC)
OSErr SetToIndex();
short mIndex;
short mMaxIndex;
#endif
}; // class nsDirectoryIterator
#endif // _FILESPEC_H_

View File

@@ -21,6 +21,7 @@
#include "FullPath.h"
#include "FileCopy.h"
#include "MoreFilesExtras.h"
#include "nsEscape.h"
#include <Aliases.h>
@@ -39,14 +40,16 @@ namespace MacFileHelpers
memcpy(dst, src, 1 + src[0]);
}
void PLstrcpy(Str255 dst, const char* src, int inMaxLen);
void PLstrcpy(Str255 dst, const char* src, int inMaxLen=255);
void PLstrncpy(Str255 dst, const char* src, int inMaxLen);
void SwapSlashColon(char * s);
OSErr FSSpecFromFullUnixPath(
const char * unixPath,
FSSpec& outSpec,
Boolean resolveAlias,
Boolean allowPartial = false);
Boolean allowPartial = false,
Boolean createDirs = false);
char* MacPathFromUnixPath(const char* unixPath);
char* EncodeMacPath(
char* inPath, // NOT const - gets clobbered
@@ -54,7 +57,8 @@ namespace MacFileHelpers
Boolean doEscape );
OSErr FSSpecFromPathname(
const char* inPathNamePtr,
FSSpec& outSpec);
FSSpec& outSpec,
Boolean inCreateDirs);
char* PathNameFromFSSpec(
const FSSpec& inSpec,
Boolean wantLeafName );
@@ -81,7 +85,7 @@ namespace MacFileHelpers
//----------------------------------------------------------------------------------------
void MacFileHelpers::PLstrcpy(Str255 dst, const char* src, int inMax)
//========================================================================================
//----------------------------------------------------------------------------------------
{
int srcLength = strlen(src);
NS_ASSERTION(srcLength <= inMax, "Oops, string is too long!");
@@ -91,6 +95,17 @@ void MacFileHelpers::PLstrcpy(Str255 dst, const char* src, int inMax)
memcpy(&dst[1], src, srcLength);
}
//----------------------------------------------------------------------------------------
void MacFileHelpers::PLstrncpy(Str255 dst, const char* src, int inMax)
//----------------------------------------------------------------------------------------
{
int srcLength = strlen(src);
if (srcLength > inMax)
srcLength = inMax;
dst[0] = srcLength;
memcpy(&dst[1], src, srcLength);
}
//-----------------------------------
void MacFileHelpers::SwapSlashColon(char * s)
//-----------------------------------
@@ -218,7 +233,10 @@ char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath)
} // MacFileHelpers::MacPathFromUnixPath
//----------------------------------------------------------------------------------------
OSErr MacFileHelpers::FSSpecFromPathname(const char* inPathNamePtr, FSSpec& outSpec)
OSErr MacFileHelpers::FSSpecFromPathname(
const char* inPathNamePtr,
FSSpec& outSpec,
Boolean inCreateDirs)
// FSSpecFromPathname reverses PathNameFromFSSpec.
// It returns a FSSpec given a c string which is a mac pathname.
//----------------------------------------------------------------------------------------
@@ -226,22 +244,55 @@ OSErr MacFileHelpers::FSSpecFromPathname(const char* inPathNamePtr, FSSpec& outS
OSErr err;
// Simplify this routine to use FSMakeFSSpec if length < 255. Otherwise use the MoreFiles
// routine FSpLocationFromFullPath, which allocates memory, to handle longer pathnames.
if (strlen(inPathNamePtr) < 255)
size_t inLength = strlen(inPathNamePtr);
if (inLength < 255)
{
Str255 path;
int pos = 0;
while ( (path[++pos] = *inPathNamePtr++) != 0 )
;
path[0] = pos-1; // save the length of the string (pos is the next open spot)
err = ::FSMakeFSSpec(0, 0, path, &outSpec);
Str255 ppath;
MacFileHelpers::PLstrcpy(ppath, inPathNamePtr);
err = ::FSMakeFSSpec(0, 0, ppath, &outSpec);
}
else
err = FSpLocationFromFullPath(strlen(inPathNamePtr), inPathNamePtr, &outSpec);
err = FSpLocationFromFullPath(inLength, inPathNamePtr, &outSpec);
if (err == dirNFErr && inCreateDirs)
{
const char* path = inPathNamePtr;
outSpec.vRefNum = 0;
outSpec.parID = 0;
do {
// Locate the colon that terminates the node.
// But if we've a partial path (starting with a colon), find the second one.
const char* nextColon = strchr(path + (*path == ':'), ':');
// Well, if there are no more colons, point to the end of the string.
if (!nextColon)
nextColon = path + strlen(path);
// Make a pascal string out of this node. Include initial
// and final colon, if any!
Str255 ppath;
MacFileHelpers::PLstrncpy(ppath, path, nextColon - path + 1);
// Use this string as a relative path using the directory created
// on the previous round (or directory 0,0 on the first round).
err = ::FSMakeFSSpec(outSpec.vRefNum, outSpec.parID, ppath, &outSpec);
// If this was the leaf node, then we are done.
if (!*nextColon)
break;
// If we got "file not found", then
// we need to create a directory.
if (err == fnfErr && *nextColon)
err = FSpDirCreate(&outSpec, smCurrentScript, &outSpec.parID);
// For some reason, this usually returns fnfErr, even though it works.
if (err != noErr && err != fnfErr)
return err;
path = nextColon; // next round
} while (1);
}
return err;
}
} // MacFileHelpers::FSSpecFromPathname
//----------------------------------------------------------------------------------------
OSErr MacFileHelpers::CreateFolderInFolder(
@@ -320,7 +371,8 @@ OSErr MacFileHelpers::FSSpecFromFullUnixPath(
const char * unixPath,
FSSpec& outSpec,
Boolean resolveAlias,
Boolean allowPartial)
Boolean allowPartial,
Boolean createDirs)
// File spec from URL. Reverses GetURLFromFileSpec
// Its input is only the <path> part of the URL
// JRM 97/01/08 changed this so that if it's a partial path (doesn't start with '/'),
@@ -338,7 +390,7 @@ OSErr MacFileHelpers::FSSpecFromFullUnixPath(
{
NS_ASSERTION(*unixPath == '/' /*full path*/, "Not a full Unix path!");
}
err = FSSpecFromPathname(macPath, outSpec);
err = FSSpecFromPathname(macPath, outSpec, createDirs);
if (err == fnfErr)
err = noErr;
Boolean dummy;
@@ -468,11 +520,12 @@ nsNativeFileSpec::nsNativeFileSpec(const nsNativeFileSpec& inSpec)
}
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const char* inString)
nsNativeFileSpec::nsNativeFileSpec(const char* inString, bool inCreateDirs)
//----------------------------------------------------------------------------------------
{
mError = MacFileHelpers::FSSpecFromFullUnixPath(inString, mSpec, true, true);
// allow a partial path
mError = MacFileHelpers::FSSpecFromFullUnixPath(
inString, mSpec, true, true, inCreateDirs);
// allow a partial path, create as necessary
if (mError == fnfErr)
mError = noErr;
} // nsNativeFileSpec::nsNativeFileSpec
@@ -537,9 +590,13 @@ bool nsNativeFileSpec::Exists() const
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::SetLeafName(const char* inLeafName)
// In leaf name can actually be a partial path...
//----------------------------------------------------------------------------------------
{
MacFileHelpers::PLstrcpy(mSpec.name, inLeafName, nsFileSpecHelpers::kMaxFilenameLength);
// what about long relative paths? Hmm?
Str255 partialPath;
MacFileHelpers::PLstrcpy(partialPath, inLeafName);
mError = FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec);
} // nsNativeFileSpec::SetLeafName
//----------------------------------------------------------------------------------------
@@ -579,10 +636,86 @@ void nsNativeFileSpec::ResolveAlias(bool& wasAliased)
wasAliased = (wasAliased2 != false);
} // nsNativeFileSpec::ResolveAlias
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsFile() const
//----------------------------------------------------------------------------------------
{
long dirID;
Boolean isDirectory;
return (noErr == FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && !isDirectory);
} // nsNativeFileSpec::IsFile
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsDirectory() const
//----------------------------------------------------------------------------------------
{
long dirID;
Boolean isDirectory;
return (noErr == FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && isDirectory);
} // nsNativeFileSpec::IsDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const
//----------------------------------------------------------------------------------------
{
if (mError == noErr)
outSpec.mError = FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, NULL, outSpec);
} // nsNativeFileSpec::GetParent
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator += (const char* inRelativePath)
//----------------------------------------------------------------------------------------
{
long dirID;
Boolean isDirectory;
mError = FSpGetDirectoryID(&mSpec, &dirID, &isDirectory);
if (mError == noErr && isDirectory)
{
mError = FSMakeFSSpec(mSpec.vRefNum, dirID, "\pG'day", *this);
if (mError == noErr)
SetLeafName(inRelativePath);
}
} // nsNativeFileSpec::operator +=
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::CreateDirectory(int /* unix mode */)
//----------------------------------------------------------------------------------------
{
long ignoredDirID;
FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID);
} // nsNativeFileSpec::CreateDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::Delete(bool inRecursive)
//----------------------------------------------------------------------------------------
{
if (inRecursive)
{
// MoreFilesExtras
mError = DeleteDirectory(
mSpec.vRefNum,
mSpec.parID,
const_cast<unsigned char*>(mSpec.name));
}
else
mError = FSpDelete(&mSpec);
} // nsNativeFileSpec::Delete
//========================================================================================
// Macintosh nsFilePath implementation
//========================================================================================
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const char* inString, bool inCreateDirs)
//----------------------------------------------------------------------------------------
: mPath(nsnull)
, mNativeFileSpec(inString, inCreateDirs)
{
// Make canonical and absolute.
char * path = MacFileHelpers::PathNameFromFSSpec( mNativeFileSpec, TRUE );
mPath = MacFileHelpers::EncodeMacPath(path, true, true);
}
//----------------------------------------------------------------------------------------
nsFilePath::nsFilePath(const nsNativeFileSpec& inSpec)
//----------------------------------------------------------------------------------------
@@ -601,3 +734,118 @@ void nsFilePath::operator = (const nsNativeFileSpec& inSpec)
mPath = MacFileHelpers::EncodeMacPath(path, true, true);
mNativeFileSpec = inSpec;
} // nsFilePath::operator =
//========================================================================================
// nsFileURL implementation
//========================================================================================
//----------------------------------------------------------------------------------------
nsFileURL::nsFileURL(const char* inString, bool inCreateDirs)
//----------------------------------------------------------------------------------------
: mURL(nsnull)
, mNativeFileSpec(inString + kFileURLPrefixLength, inCreateDirs)
{
NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
// Make canonical and absolute.
char* path = MacFileHelpers::PathNameFromFSSpec( mNativeFileSpec, TRUE );
char* escapedPath = MacFileHelpers::EncodeMacPath(path, true, true);
mURL = nsFileSpecHelpers::StringDup(kFileURLPrefix, kFileURLPrefixLength + strlen(escapedPath));
strcat(mURL, escapedPath);
delete [] escapedPath;
} // nsFileURL::nsFileURL
//========================================================================================
// nsDirectoryIterator
//========================================================================================
//----------------------------------------------------------------------------------------
nsDirectoryIterator::nsDirectoryIterator(
const nsNativeFileSpec& inDirectory
, int inIterateDirection)
//----------------------------------------------------------------------------------------
: mCurrent(inDirectory)
, mExists(false)
, mIndex(-1)
{
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&();
Str255 outName;
MacFileHelpers::PLstrcpy(outName, inSpec.name);
pb.hFileInfo.ioNamePtr = outName;
pb.hFileInfo.ioVRefNum = inSpec.vRefNum;
pb.hFileInfo.ioDirID = inSpec.parID;
pb.hFileInfo.ioFDirIndex = 0; // use ioNamePtr and ioDirID
OSErr err = PBGetCatInfoSync( &pb );
// test that we have got a directory back, not a file
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&();
currentSpec.vRefNum = inSpec.vRefNum;
currentSpec.parID = dipb->ioDrDirID;
mMaxIndex = pb.dirInfo.ioDrNmFls;
if (inIterateDirection > 0)
{
mIndex = 0; // ready to increment
++(*this); // the pre-increment operator
}
else
{
mIndex = mMaxIndex + 1; // ready to decrement
--(*this); // the pre-decrement operator
}
} // nsDirectoryIterator::nsDirectoryIterator
//----------------------------------------------------------------------------------------
OSErr nsDirectoryIterator::SetToIndex()
//----------------------------------------------------------------------------------------
{
CInfoPBRec cipb;
DirInfo *dipb=(DirInfo *)&cipb;
Str255 objectName;
dipb->ioCompletion = NULL;
dipb->ioFDirIndex = mIndex;
// Sorry about this, there seems to be a bug in CWPro 4:
FSSpec& currentSpec = mCurrent.nsNativeFileSpec::operator FSSpec&();
dipb->ioVRefNum = currentSpec.vRefNum; /* Might need to use vRefNum, not sure*/
dipb->ioDrDirID = currentSpec.parID;
dipb->ioNamePtr = objectName;
OSErr err = PBGetCatInfoSync(&cipb);
if (err == noErr)
err = FSMakeFSSpec(currentSpec.vRefNum, currentSpec.parID, objectName, &currentSpec);
mExists = err == noErr;
return err;
} // nsDirectoryIterator::SetToIndex()
//----------------------------------------------------------------------------------------
nsDirectoryIterator& nsDirectoryIterator::operator -- ()
//----------------------------------------------------------------------------------------
{
mExists = false;
while (--mIndex > 0)
{
OSErr err = SetToIndex();
if (err == noErr)
break;
}
return *this;
} // nsDirectoryIterator::operator --
//----------------------------------------------------------------------------------------
nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
//----------------------------------------------------------------------------------------
{
mExists = false;
if (mIndex >= 0) // probably trying to use a file as a directory!
while (++mIndex <= mMaxIndex)
{
OSErr err = SetToIndex();
if (err == noErr)
break;
}
return *this;
} // nsDirectoryIterator::operator ++

View File

@@ -16,27 +16,205 @@
* Reserved.
*/
// This file is included by nsFileSpec.cpp, and includes the Unix-specific
// implementations.
// This file is included by nsFileSpec.cpp, and includes the Unix-specific
// implementations.
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/dir.h>
#include <unistd.h>
#include <stdlib.h>
//----------------------------------------------------------------------------------------
void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs)
// Canonify, make absolute, and check whether directories exist
//----------------------------------------------------------------------------------------
{
if (!ioPath)
return;
if (inMakeDirs)
{
const mode_t mode = 0700;
nsFileSpecHelpers::MakeAllDirectories(ioPath, mode);
}
char buffer[MAXPATHLEN];
errno = 0;
*buffer = '\0';
char* canonicalPath = realpath(ioPath, buffer);
if (!canonicalPath)
{
// Linux's realpath() is pathetically buggy. If the reason for the nil
// result is just that the leaf does not exist, strip the leaf off,
// process that, and then add the leaf back.
char* allButLeaf = nsFileSpecHelpers::StringDup(ioPath);
if (!allButLeaf)
return;
char* lastSeparator = strrchr(allButLeaf, '/');
if (lastSeparator)
{
*lastSeparator = '\0';
canonicalPath = realpath(allButLeaf, buffer);
strcat(buffer, "/");
// Add back the leaf
strcat(buffer, ++lastSeparator);
}
delete [] allButLeaf;
}
if (!canonicalPath && *ioPath != '/' && !inMakeDirs)
{
// Well, if it's a relative path, hack it ourselves.
canonicalPath = realpath(".", buffer);
if (canonicalPath)
{
strcat(canonicalPath, "/");
strcat(canonicalPath, ioPath);
}
}
if (canonicalPath)
nsFileSpecHelpers::StringAssign(ioPath, canonicalPath);
} // nsFileSpecHelpers::Canonify
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::SetLeafName(const char* inLeafName)
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::LeafReplace(mPath, '/', inLeafName);
nsFileSpecHelpers::LeafReplace(mPath, '/', inLeafName);
} // nsNativeFileSpec::SetLeafName
//----------------------------------------------------------------------------------------
char* nsNativeFileSpec::GetLeafName() const
//----------------------------------------------------------------------------------------
{
return nsFileSpecHelpers::GetLeaf(mPath, '/');
return nsFileSpecHelpers::GetLeaf(mPath, '/');
} // nsNativeFileSpec::GetLeafName
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::Exists() const
//----------------------------------------------------------------------------------------
{
return false; // fixme
struct stat st;
return 0 == stat(mPath, &st);
} // nsNativeFileSpec::Exists
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsFile() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && S_ISREG(st.st_mode);
} // nsNativeFileSpec::IsFile
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsDirectory() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && S_ISDIR(st.st_mode);
} // nsNativeFileSpec::IsDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(outSpec.mPath, mPath);
char* cp = strrchr(outSpec.mPath, '/');
if (cp)
*cp = '\0';
} // nsNativeFileSpec::GetParent
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator += (const char* inRelativePath)
//----------------------------------------------------------------------------------------
{
if (!inRelativePath || !mPath)
return;
if (mPath[strlen(mPath) - 1] != '/')
char* newPath = nsFileSpecHelpers::ReallocCat(mPath, "/");
SetLeafName(inRelativePath);
} // nsNativeFileSpec::operator +=
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::CreateDirectory(int mode)
//----------------------------------------------------------------------------------------
{
// Note that mPath is canonical!
mkdir(mPath, mode);
} // nsNativeFileSpec::CreateDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::Delete(bool inRecursive)
// To check if this worked, call Exists() afterwards, see?
//----------------------------------------------------------------------------------------
{
if (IsDirectory())
{
if (inRecursive)
{
for (nsDirectoryIterator i(*this); i; i++)
{
nsNativeFileSpec& child = (nsNativeFileSpec&)i;
child.Delete(inRecursive);
}
}
rmdir(mPath);
}
else
remove(mPath);
} // nsNativeFileSpec::Delete
//========================================================================================
// nsDirectoryIterator
//========================================================================================
//----------------------------------------------------------------------------------------
nsDirectoryIterator::nsDirectoryIterator(
const nsNativeFileSpec& inDirectory
, int inIterateDirection)
//----------------------------------------------------------------------------------------
: mCurrent(inDirectory)
, mDir(nsnull)
, mExists(false)
{
mCurrent += "sysygy"; // prepare the path for SetLeafName
mDir = opendir((const char*)nsFilePath(inDirectory));
++(*this);
} // nsDirectoryIterator::nsDirectoryIterator
//----------------------------------------------------------------------------------------
nsDirectoryIterator::~nsDirectoryIterator()
//----------------------------------------------------------------------------------------
{
if (mDir)
closedir(mDir);
} // nsDirectoryIterator::nsDirectoryIterator
//----------------------------------------------------------------------------------------
nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
//----------------------------------------------------------------------------------------
{
mExists = false;
if (!mDir)
return *this;
char* dot = ".";
char* dotdot = "..";
struct dirent* entry = readdir(mDir);
if (entry && strcmp(entry->d_name, dot) == 0)
entry = readdir(mDir);
if (entry && strcmp(entry->d_name, dotdot) == 0)
entry = readdir(mDir);
if (entry)
{
mExists = true;
mCurrent.SetLeafName(entry->d_name);
}
return *this;
} // nsDirectoryIterator::operator ++
//----------------------------------------------------------------------------------------
nsDirectoryIterator& nsDirectoryIterator::operator -- ()
//----------------------------------------------------------------------------------------
{
return ++(*this); // can't do it backwards.
} // nsDirectoryIterator::operator --

View File

@@ -19,6 +19,17 @@
// This file is included by nsFileSpec.cp, and includes the Windows-specific
// implementations.
#include <stat.h>
//----------------------------------------------------------------------------------------
void nsFileSpecHelpers::Canonify(char*& ioPath, bool inMakeDirs)
// Canonify, make absolute, and check whether directories exist
//----------------------------------------------------------------------------------------
{
NS_NOTYETIMPLEMENTED("Please, some Winhead please write this!");
return ioPath;
}
//----------------------------------------------------------------------------------------
nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
@@ -31,9 +42,17 @@ nsNativeFileSpec::nsNativeFileSpec(const nsFilePath& inPath)
void nsNativeFileSpec::operator = (const nsFilePath& inPath)
//----------------------------------------------------------------------------------------
{
// Convert '/' to '\'
nsFileSpecHelpers::StringAssign(mPath, (const char*)inPath);
for (char* cp = mPath; *cp; cp++)
// Strip the leading slash, which should
// leave us pointing to a drive letter.
nsFileSpecHelpers::StringAssign(mPath, (const char*)inPath + 1);
// Convert the vertical slash to a colon
char* cp = mPath + 1;
if (strstr(cp, "|/") == cp)
*cp = ':';
// Convert '/' to '\'.
while (*++cp)
{
if (*cp == '/')
*cp = '\\';
@@ -79,6 +98,138 @@ char* nsNativeFileSpec::GetLeafName() const
bool nsNativeFileSpec::Exists() const
//----------------------------------------------------------------------------------------
{
return false; // fixme
struct stat st;
return 0 == stat(mPath, &st);
} // nsNativeFileSpec::Exists
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsFile() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && S_ISREG(st.st_mode);
} // nsNativeFileSpec::IsFile
//----------------------------------------------------------------------------------------
bool nsNativeFileSpec::IsDirectory() const
//----------------------------------------------------------------------------------------
{
struct stat st;
return 0 == stat(mPath, &st) && S_ISDIR(st.st_mode);
} // nsNativeFileSpec::IsDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::GetParent(nsNativeFileSpec& outSpec) const
//----------------------------------------------------------------------------------------
{
nsFileSpecHelpers::StringAssign(outSpec.mPath, mPath);
char* cp = strrchr(outSpec.mPath, '\\');
if (cp)
*cp = '\0';
} // nsNativeFileSpec::GetParent
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::operator += (const char* inRelativePath)
//----------------------------------------------------------------------------------------
{
if (!inRelativePath || !mPath)
return;
if (mPath[strlen(mPath) - 1] != '\\')
char* newPath = nsFileSpecHelpers::ReallocCat(mPath, "\\");
SetLeafName(inRelativePath);
} // nsNativeFileSpec::operator +=
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::CreateDirectory()
//----------------------------------------------------------------------------------------
{
// Note that mPath is canonical!
NS_NOTYETIMPLEMENTED("Please, some Winhead please fix this!");
mkdir(mPath, mode);
} // nsNativeFileSpec::CreateDirectory
//----------------------------------------------------------------------------------------
void nsNativeFileSpec::Delete(bool inRecursive)
//----------------------------------------------------------------------------------------
{
if (IsDirectory())
{
if (inRecursive)
{
for (nsDirectoryIterator i(*this); i; i++)
{
const nsNativeFileSpec& child = (nsNativeFileSpec&)i;
child.Delete(inRecursive);
}
}
NS_NOTYETIMPLEMENTED("Please, some Winhead please fix this!");
rmdir(mPath);
}
else
{
NS_NOTYETIMPLEMENTED("Please, some Winhead please write this!");
remove(mPath);
}
} // nsNativeFileSpec::Delete
//========================================================================================
// nsDirectoryIterator
//========================================================================================
//----------------------------------------------------------------------------------------
nsDirectoryIterator::nsDirectoryIterator(
const nsNativeFileSpec& inDirectory
, int inIterateDirection)
//----------------------------------------------------------------------------------------
: mCurrent(inDirectory)
#if 0 // Some kind winhead please build, test, and remove when ready.
, mDir(nsnull)
#endif // XP_PC -- ifdef to be removed.
, mExists(false)
{
NS_NOTYETIMPLEMENTED("Please, some kind Winhead please check this!");
mCurrent += "foo";
#if 0 // Some kind winhead please build, test, and remove when ready.
mDir = opendir(mPath);
#endif // XP_PC -- ifdef to be removed.
++(*this);
} // nsDirectoryIterator::nsDirectoryIterator
//----------------------------------------------------------------------------------------
nsDirectoryIterator::~nsDirectoryIterator()
//----------------------------------------------------------------------------------------
{
NS_NOTYETIMPLEMENTED("Please, some kind Winhead please check this!");
#if 0 // Some kind winhead please build, test, and remove when ready.
if (mDir)
closedir(mDir);
#endif // XP_PC -- ifdef to be removed.
} // nsDirectoryIterator::nsDirectoryIterator
//----------------------------------------------------------------------------------------
nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
//----------------------------------------------------------------------------------------
{
mExists = false;
NS_NOTYETIMPLEMENTED("Please, some kind Winhead please check this!");
#if 0 // Some kind winhead please build, test, and remove when ready.
if (!mDir)
return *this;
struct dirent* entry = readdir(mDir);
if (entry)
{
mExists = true;
mCurrent.SetLeafName(entry->d_name);
}
#endif // XP_PC -- ifdef to be removed.
return *this;
} // nsDirectoryIterator::operator ++
//----------------------------------------------------------------------------------------
nsDirectoryIterator& nsDirectoryIterator::operator -- ()
//----------------------------------------------------------------------------------------
{
return ++(*this); // can't do it backwards.
} // nsDirectoryIterator::operator --

View File

@@ -11,7 +11,7 @@ void FilesTest::WriteStuff(nsOutputFileStream& s)
//----------------------------------------------------------------------------------------
{
// Initialize a URL from a string without suffix. Change the path to suit your machine.
nsFileURL fileURL("file:///Development/MPW/MPW%20Shell");
nsFileURL fileURL("file:///Development/MPW/MPW%20Shell", false);
s << "File URL initialized to: \"" << fileURL << "\""<< nsEndl;
// Initialize a Unix path from a URL
@@ -44,7 +44,7 @@ void FilesTest::WriteStuff(nsOutputFileStream& s)
} // WriteStuff
//----------------------------------------------------------------------------------------
void main()
int main()
// For use with DEBUG defined.
//----------------------------------------------------------------------------------------
{
@@ -59,38 +59,59 @@ void main()
FilesTest::WriteStuff(nsOut);
nsOut << nsEndl << nsEndl;
// Test of nsOutputFileStream
nsFilePath myTextFilePath("iotest.txt");
// - Test of nsOutputFileStream
nsFilePath myTextFilePath("mumble/iotest.txt", true); // relative path.
const char* pathAsString = (const char*)myTextFilePath;
if (*pathAsString != '/')
{
nsOut << "WRITING IDENTICAL OUTPUT TO " << (const char*)myTextFilePath << nsEndl << nsEndl;
nsOut
<< "ERROR: after initializing the path object with a relative path,"
<< "\n the path consisted of the string "
<< "\n\t" << pathAsString
<< "\n which is not a canonical full path!"
<< nsEndl;
return -1;
}
nsNativeFileSpec mySpec(myTextFilePath);
{
nsOut << "WRITING IDENTICAL OUTPUT TO " << pathAsString << nsEndl << nsEndl;
nsOutputFileStream testStream(myTextFilePath);
if (!testStream.is_open())
{
nsOut
<< "ERROR: File "
<< (const char*)myTextFilePath
<< pathAsString
<< " could not be opened for output"
<< nsEndl;
return;
return -1;
}
FilesTest::WriteStuff(testStream);
} // <-- Scope closes the stream (and the file).
// Test of nsInputFileStream
if (!mySpec.Exists() || mySpec.IsDirectory() || !mySpec.IsFile())
{
nsOut
<< "ERROR: File "
<< pathAsString
<< " is not a file (cela n'est pas un pipe)"
<< nsEndl;
return -1;
}
// - Test of nsInputFileStream
{
nsOut << "READING BACK DATA FROM " << (const char*)myTextFilePath << nsEndl << nsEndl;
nsOut << "READING BACK DATA FROM " << pathAsString << nsEndl << nsEndl;
nsInputFileStream testStream2(myTextFilePath);
if (!testStream2.is_open())
{
nsOut
<< "ERROR: File "
<< (const char*)myTextFilePath
<< pathAsString
<< " could not be opened for input"
<< nsEndl;
return;
return -1;
}
char line[1000];
@@ -101,4 +122,101 @@ void main()
nsOut << line << nsEndl;
}
} // <-- Scope closes the stream (and the file).
// - Test of GetParent()
nsNativeFileSpec parent;
mySpec.GetParent(parent);
nsFilePath parentPath(parent);
nsOut
<< "GetParent() on "
<< "\n\t" << pathAsString
<< "\n yields "
<< "\n\t" << (const char*)parentPath
<< nsEndl;
// - Test of non-recursive delete
nsOut
<< "Attempting to delete "
<< "\n\t" << (const char*)parentPath
<< "\n without recursive option (should fail)"
<< nsEndl;
parent.Delete(false);
if (parent.Exists())
nsOut << "Test passed." << nsEndl;
else
{
nsOut
<< "ERROR: File "
<< "\n\t" << (const char*)parentPath
<< "\n has been deleted without the recursion option,"
<< "\n and is a nonempty directory!"
<< nsEndl;
return -1;
}
// - Test of recursive delete
nsOut
<< "Deleting "
<< "\n\t" << (const char*)parentPath
<< "\n with recursive option"
<< nsEndl;
parent.Delete(true);
if (parent.Exists())
{
nsOut
<< "ERROR: Directory "
<< "\n\t" << (const char*)parentPath
<< "\n has NOT been deleted despite the recursion option!"
<< nsEndl;
return -1;
}
else
nsOut << "Test passed." << nsEndl;
// - Test of CreateDirectory
nsOut
<< "Testing CreateDirectory() using"
<< "\n\t" << (const char*)parentPath
<< nsEndl;
parent.CreateDirectory();
if (parent.Exists())
nsOut << "Test passed." << nsEndl;
else
{
nsOut << "ERROR: Test failed." << nsEndl;
return -1;
}
parent.Delete(true);
#ifndef XP_PC // uncomment when tested and ready.
// - Test of directory iterator
nsNativeFileSpec grandparent;
parent.GetParent(grandparent); // should be the original default directory.
nsFilePath grandparentPath(grandparent);
nsOut << "Forwards listing of " << (const char*)grandparentPath << ":" << nsEndl;
for (nsDirectoryIterator i(grandparent, +1); i; i++)
{
char* itemName = ((nsNativeFileSpec&)i).GetLeafName();
nsOut << '\t' << itemName << nsEndl;
delete [] itemName;
}
nsOut << "Backwards listing of " << (const char*)grandparentPath << ":" << nsEndl;
for (nsDirectoryIterator i(grandparent, -1); i; i--)
{
char* itemName = ((nsNativeFileSpec&)i).GetLeafName();
nsOut << '\t' << itemName << nsEndl;
delete [] itemName;
}
#endif
return 0;
} // main