From b01ade9e83fa83347fc994a1cd3783aea15802bd Mon Sep 17 00:00:00 2001 From: "ccarlen%netscape.com" Date: Tue, 9 Apr 2002 14:12:24 +0000 Subject: [PATCH] Bug 12911 - use relative file descriptors. This adds the needed methods to nsILocalFile. r=dougt/sr=alecf/a=asa/adt=jaime git-svn-id: svn://10.0.0.236/trunk@118544 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/xpcom/io/nsILocalFile.idl | 37 ++++++ mozilla/xpcom/io/nsLocalFileCommon.cpp | 149 ++++++++++++++++++++++- mozilla/xpcom/io/nsLocalFileMac.cpp | 51 +++++--- mozilla/xpcom/io/nsLocalFileMac.h | 3 + mozilla/xpcom/tools/registry/Makefile.in | 3 +- 5 files changed, 227 insertions(+), 16 deletions(-) diff --git a/mozilla/xpcom/io/nsILocalFile.idl b/mozilla/xpcom/io/nsILocalFile.idl index 7aefb62ed84..b6fb4656e8f 100644 --- a/mozilla/xpcom/io/nsILocalFile.idl +++ b/mozilla/xpcom/io/nsILocalFile.idl @@ -33,6 +33,7 @@ #include "prio.h" #include "prlink.h" #include +#include "nsAString.h" %} [ptr] native PRFileDescStar(PRFileDesc); @@ -62,6 +63,18 @@ interface nsILocalFile : nsIFile void initWithPath([const] in string filePath); void initWithUnicodePath([const] in wstring filePath); + /** + * initWithFile + * + * Initialize this object with another file + * + * @param aFile + * the file this becomes equivalent to + * + */ + void initWithFile(in nsILocalFile aFile); + + /** * followLinks * @@ -119,6 +132,30 @@ interface nsILocalFile : nsIFile * This routine only works on platforms which support this functionality. */ void launch(); + + /** + * getRelativeDescriptor + * + * Returns a utf-8 encoded relative file path in an XP format. + * It is therefore not a native path. + * + * @param fromFile + * the file from which the descriptor is relative + */ + AUTF8String getRelativeDescriptor(in nsILocalFile fromFile); + + + /** + * setRelativeDescriptor + * + * Initializes the file to the location relative to fromFile using + * a string returned by getRelativeDescriptor. + * + * @param fromFile + * the file to which the descriptor is relative + */ + void setRelativeDescriptor(in nsILocalFile fromFile, in AUTF8String relativeDesc); + }; %{C++ diff --git a/mozilla/xpcom/io/nsLocalFileCommon.cpp b/mozilla/xpcom/io/nsLocalFileCommon.cpp index f3e42c80262..ba0056e6d55 100644 --- a/mozilla/xpcom/io/nsLocalFileCommon.cpp +++ b/mozilla/xpcom/io/nsLocalFileCommon.cpp @@ -42,7 +42,7 @@ #include "nsString.h" #include "nsCOMPtr.h" #include "nsXPIDLString.h" - +#include "nsReadableUtils.h" void NS_StartupLocalFile() @@ -62,6 +62,20 @@ void NS_ShutdownLocalFile() #endif } +#if !defined(XP_MAC) +NS_IMETHODIMP +nsLocalFile::InitWithFile(nsILocalFile *aFile) +{ + NS_ENSURE_ARG(aFile); + + nsXPIDLCString path; + aFile->GetPath(getter_Copies(path)); + if (!path) + return NS_ERROR_FAILURE; + return InitWithPath(path.get()); +} +#endif + // should work on Macintosh, Unix, and Win32. #define kMaxFilenameLength 31 @@ -114,7 +128,140 @@ nsLocalFile::CreateUnique(PRUint32 type, PRUint32 attributes) return NS_ERROR_FILE_TOO_BIG; } +#if defined(XP_MAC) +const PRUnichar kPathSeparatorChar = ':'; +#elif defined(XP_WIN) || defined(XP_OS2) +const PRUnichar kPathSeparatorChar = '\\'; +#elif defined(XP_UNIX) || defined(XP_BEOS) +const PRUnichar kPathSeparatorChar = '/'; +#else +#error Need to define file path separator for your platform +#endif + +#if defined(XP_MAC) +const char* kSlashStr = "/"; +const char* kESCSlashStr = "%2F"; +#endif + +static PRInt32 SplitPath(PRUnichar *path, PRUnichar **nodeArray, PRInt32 arrayLen) +{ + if (*path == 0) + return 0; + + PRUnichar **nodePtr = nodeArray; + if (*path == kPathSeparatorChar) + path++; + *nodePtr++ = path; + + for (PRUnichar *cp = path; *cp != 0; cp++) { + if (*cp == kPathSeparatorChar) { + *cp++ = 0; + if (*cp != 0) { + if (nodePtr - nodeArray >= arrayLen) + return -1; + *nodePtr++ = cp; + } + } + } + return nodePtr - nodeArray; +} + +NS_IMETHODIMP +nsLocalFile::GetRelativeDescriptor(nsILocalFile *fromFile, nsACString& _retval) +{ + const PRInt32 kMaxNodesInPath = 32; + + nsresult rv; + _retval.Truncate(0); + PRUnichar *thisPath = nsnull, *fromPath = nsnull; + PRUnichar *thisNodes[kMaxNodesInPath], *fromNodes[kMaxNodesInPath]; + PRInt32 thisNodeCnt, fromNodeCnt, nodeIndex; + + rv = GetUnicodePath(&thisPath); + if (NS_FAILED(rv)) + return rv; + rv = fromFile->GetUnicodePath(&fromPath); + if (NS_FAILED(rv)) { + nsMemory::Free(thisPath); + return rv; + } + + thisNodeCnt = SplitPath(thisPath, thisNodes, kMaxNodesInPath); + fromNodeCnt = SplitPath(fromPath, fromNodes, kMaxNodesInPath); + if (thisNodeCnt < 0 || fromNodeCnt < 0) { + nsMemory::Free(thisPath); + nsMemory::Free(fromPath); + return NS_ERROR_FAILURE; + } + + for (nodeIndex = 0; nodeIndex < thisNodeCnt && nodeIndex < fromNodeCnt; nodeIndex++) { + if (!(nsDependentString(thisNodes[nodeIndex])).Equals(nsDependentString(fromNodes[nodeIndex]))) + break; + } + + PRInt32 branchIndex = nodeIndex; + for (nodeIndex = branchIndex; nodeIndex < fromNodeCnt; nodeIndex++) + _retval.Append("../"); + for (nodeIndex = branchIndex; nodeIndex < thisNodeCnt; nodeIndex++) { + NS_ConvertUCS2toUTF8 nodeStr(thisNodes[nodeIndex]); +#ifdef XP_MAC + nodeStr.ReplaceSubstring(kSlashStr, kESCSlashStr); +#endif + _retval.Append(nodeStr.get()); + if (nodeIndex + 1 < thisNodeCnt) + _retval.Append('/'); + } + + nsMemory::Free(thisPath); + nsMemory::Free(fromPath); + + return NS_OK; +} +NS_IMETHODIMP +nsLocalFile::SetRelativeDescriptor(nsILocalFile *fromFile, const nsACString& relativeDesc) +{ + NS_NAMED_LITERAL_CSTRING(kParentDirStr, "../"); + + nsCOMPtr targetFile; + nsresult rv = fromFile->Clone(getter_AddRefs(targetFile)); + if (NS_FAILED(rv)) + return rv; + nsCString::const_iterator strBegin, strEnd; + relativeDesc.BeginReading(strBegin); + relativeDesc.EndReading(strEnd); + + nsCString::const_iterator nodeBegin(strBegin), nodeEnd(strEnd); + nsCString::const_iterator pos(strBegin); + + nsCOMPtr parentDir; + while (FindInReadable(kParentDirStr, nodeBegin, nodeEnd)) { + rv = targetFile->GetParent(getter_AddRefs(parentDir)); + if (NS_FAILED(rv)) + return rv; + targetFile = parentDir; + + nodeBegin = nodeEnd; + pos = nodeEnd; + nodeEnd = strEnd; + } + + nodeBegin = nodeEnd = pos; + while (nodeEnd != strEnd) { + FindCharInReadable('/', nodeEnd, strEnd); + nsCAutoString nodeString(Substring(nodeBegin, nodeEnd)); +#ifdef XP_MAC + nodeString.ReplaceSubstring(kESCSlashStr, kSlashStr); +#endif + targetFile->AppendUnicode((NS_ConvertUTF8toUCS2(nodeString)).get()); + if (nodeEnd != strEnd) // If there's more left in the string, inc over the '/' nodeEnd is on. + ++nodeEnd; + nodeBegin = nodeEnd; + } + + nsCOMPtr targetLocalFile(do_QueryInterface(targetFile)); + return InitWithFile(targetLocalFile); +} diff --git a/mozilla/xpcom/io/nsLocalFileMac.cpp b/mozilla/xpcom/io/nsLocalFileMac.cpp index 3def254eb9b..c69aaa39c2c 100644 --- a/mozilla/xpcom/io/nsLocalFileMac.cpp +++ b/mozilla/xpcom/io/nsLocalFileMac.cpp @@ -1067,21 +1067,10 @@ nsLocalFile::nsLocalFile() : mCreator = sCurrentProcessSignature; } -nsLocalFile::nsLocalFile(const nsLocalFile& srcFile) : - mFollowLinks(srcFile.mFollowLinks), - mFollowLinksDirty(srcFile.mFollowLinksDirty), - mSpecDirty(srcFile.mSpecDirty), - mSpec(srcFile.mSpec), - mAppendedPath(srcFile.mAppendedPath), - mTargetSpec(srcFile.mTargetSpec), - mCatInfoDirty(srcFile.mCatInfoDirty), - mType(srcFile.mType), - mCreator(srcFile.mCreator) +nsLocalFile::nsLocalFile(const nsLocalFile& srcFile) { NS_INIT_REFCNT(); - - if (!mCatInfoDirty) - mCachedCatInfo = srcFile.mCachedCatInfo; + *this = srcFile; } nsLocalFile::nsLocalFile(const FSSpec& aSpec, const nsACString& aAppendedPath) : @@ -1103,13 +1092,35 @@ nsLocalFile::nsLocalFile(const FSSpec& aSpec, const nsACString& aAppendedPath) : mCreator = sCurrentProcessSignature; } +nsLocalFile& nsLocalFile::operator=(const nsLocalFile& rhs) +{ + mFollowLinks = rhs.mFollowLinks; + mFollowLinksDirty = rhs.mFollowLinksDirty; + mSpecDirty = rhs.mSpecDirty; + mSpec = rhs.mSpec; + mAppendedPath = rhs.mAppendedPath; + mTargetSpec = rhs.mTargetSpec; + mCatInfoDirty = rhs.mCatInfoDirty; + mType = rhs.mType; + mCreator = rhs.mCreator; + + if (!rhs.mCatInfoDirty) + mCachedCatInfo = rhs.mCachedCatInfo; + + return *this; +} + nsLocalFile::~nsLocalFile() { } #pragma mark - #pragma mark [nsISupports interface implementation] -NS_IMPL_THREADSAFE_ISUPPORTS3(nsLocalFile, nsILocalFileMac, nsILocalFile, nsIFile) + +NS_IMPL_THREADSAFE_ISUPPORTS3(nsLocalFile, + nsILocalFileMac, + nsILocalFile, + nsIFile) NS_METHOD nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr) @@ -1291,6 +1302,17 @@ nsLocalFile::InitWithUnicodePath(const PRUnichar *filePath) return rv; } +NS_IMETHODIMP +nsLocalFile::InitWithFile(nsILocalFile *aFile) +{ + NS_ENSURE_ARG(aFile); + nsLocalFile *asLocalFile = dynamic_cast(aFile); + if (!asLocalFile) + return NS_ERROR_NO_INTERFACE; // Well, sort of. + *this = *asLocalFile; + return NS_OK; +} + NS_IMETHODIMP nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval) { @@ -3105,6 +3127,7 @@ NS_IMETHODIMP nsLocalFile::InitWithFSSpec(const FSSpec *fileSpec) return NS_OK; } + NS_IMETHODIMP nsLocalFile::InitToAppWithCreatorCode(OSType aAppCreator) { FSSpec appSpec; diff --git a/mozilla/xpcom/io/nsLocalFileMac.h b/mozilla/xpcom/io/nsLocalFileMac.h index 378bf3d6df0..e2460b1264f 100644 --- a/mozilla/xpcom/io/nsLocalFileMac.h +++ b/mozilla/xpcom/io/nsLocalFileMac.h @@ -84,6 +84,9 @@ protected: private: nsLocalFile(const nsLocalFile& srcFile); nsLocalFile(const FSSpec& aSpec, const nsACString& aAppendedPath); + + // Copies all members except mRefCnt, copies mCachedCatInfo only if it's valid. + nsLocalFile& operator=(const nsLocalFile& rhs); PRPackedBool mFollowLinks; PRPackedBool mFollowLinksDirty; diff --git a/mozilla/xpcom/tools/registry/Makefile.in b/mozilla/xpcom/tools/registry/Makefile.in index 8925ec336cc..40ddf61e964 100644 --- a/mozilla/xpcom/tools/registry/Makefile.in +++ b/mozilla/xpcom/tools/registry/Makefile.in @@ -28,7 +28,8 @@ include $(DEPTH)/config/autoconf.mk MODULE = xpcom CPPSRCS = regExport.cpp regxpcom.cpp -REQUIRES = $(NULL) +REQUIRES = string \ + $(NULL) SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))