Author: jberry
Date: Thu May 26 06:47:35 2005
New Revision: 178635
URL: http://svn.apache.org/viewcvs?rev=178635&view=rev
Log:
Reintegrate path-manipulation routines
Modified:
xerces/c/branches/jberry/3.0-unstable/src/xercesc/util/PlatformUtils.cpp
Modified:
xerces/c/branches/jberry/3.0-unstable/src/xercesc/util/PlatformUtils.cpp
URL:
http://svn.apache.org/viewcvs/xerces/c/branches/jberry/3.0-unstable/src/xercesc/util/PlatformUtils.cpp?rev=178635&r1=178634&r2=178635&view=diff
==============================================================================
--- xerces/c/branches/jberry/3.0-unstable/src/xercesc/util/PlatformUtils.cpp
(original)
+++ xerces/c/branches/jberry/3.0-unstable/src/xercesc/util/PlatformUtils.cpp
Thu May 26 06:47:35 2005
@@ -795,4 +795,255 @@
return false;
}
+/***
+ *
+ * Previously, each <OS>PlatformUtils.cpp has its onw copy of the
+ * method weavePaths(), and almost of them implemented the same logic,
+ * with few platform specific difference, and unfortunately that
+ * implementation was wrong.
+ *
+ * The only platform specific issue is slash character.
+ * On all platforms other than Windows, chForwardSlash and chBackSlash
+ * are considered slash, while on Windows, two additional characters,
+ * chYenSign and chWonSign are slash as well.
+ *
+ * The idea is to maintain a SINGLE copy of this method rather than
+ * each <OS>PlatformUtils.cpp has its own copy, we introduce a new
+ * method, XMLPlatformUtils::isAnySlash(), to replace the direct checking
+ * code ( if ( c == chForwardSlash || c == chBackSlash).
+ *
+ * With this approach, we might have a performance hit since isAnySlash()
+ * is so frequently used in this implementation, so we intend to make it
+ * inline. Then we face a complier issue.
+ *
+ * There are two compilation units involved, one is PlatformUtils.cpp and
+ * the other <OS>PlatformUtils.cpp. When PlatformUtils.cp get compiled,
+ * the weavePath(), remove**Slash() have dependency upon isAnySlash() which
+ * is in <OS>PlatformUtils.cpp (and what is worse, it is inlined), so we have
+ * undefined/unresolved symbol: isAnySlash() on AIX/xlc_r, Solaris/cc and
+ * Linux/gcc, while MSVC and HP/aCC are fine with this.
+ *
+ * That means we can not place these new methods in PlatformUtils.cpp with
+ * inlined XMLPlatformUtils::isAnySlash() in <OS>PlatformUtils.cpp.
+ *
+ * The solution to this is <os>PlatformUtils.cpp will include this file so
that
+ * we have only one copy of these methods while get compiled in
<os>PlatformUtils
+ * inlined isAnySlash().
+ *
+ ***/
+XMLCh* XMLPlatformUtils::weavePaths(const XMLCh* const basePath
+ , const XMLCh* const relativePath
+ , MemoryManager* const manager)
+
+{
+ // Create a buffer as large as both parts and empty it
+ XMLCh* tmpBuf = (XMLCh*) manager->allocate
+ (
+ (XMLString::stringLen(basePath)
+ + XMLString::stringLen(relativePath) + 2) * sizeof(XMLCh)
+ );//new XMLCh[XMLString::stringLen(basePath) +
XMLString::stringLen(relativePath) + 2];
+ *tmpBuf = 0;
+
+ //
+ // If we have no base path, then just take the relative path as is.
+ //
+ if ((!basePath) || (!*basePath))
+ {
+ XMLString::copyString(tmpBuf, relativePath);
+ return tmpBuf;
+ }
+
+ //
+ // Remove anything after the last slash
+ //
+ const XMLCh* basePtr = basePath + (XMLString::stringLen(basePath) - 1);
+ while ((basePtr >= basePath) && ((isAnySlash(*basePtr) == false)))
+ {
+ basePtr--;
+ }
+
+ // There is no relevant base path, so just take the relative part
+ if (basePtr < basePath)
+ {
+ XMLString::copyString(tmpBuf, relativePath);
+ return tmpBuf;
+ }
+
+ //
+ // 1. concatenate the base and relative
+ // 2. remove all occurences of "/./"
+ // 3. remove all occurences of segment/../ where segment is not ../
+ //
+
+ XMLString::subString(tmpBuf, basePath, 0, (basePtr - basePath + 1),
manager);
+ tmpBuf[basePtr - basePath + 1] = 0;
+ XMLString::catString(tmpBuf, relativePath);
+
+ removeDotSlash(tmpBuf, manager);
+
+ removeDotDotSlash(tmpBuf, manager);
+
+ return tmpBuf;
+
+}
+
+//
+// Remove all occurences of './' when it is part of '/./'
+//
+// Since it could be '.\' or other combination on windows ( eg, '.'+chYanSign)
+// we can't make use of patterMatch().
+//
+//
+void XMLPlatformUtils::removeDotSlash(XMLCh* const path
+ , MemoryManager* const manager)
+{
+ if ((!path) || (!*path))
+ return;
+
+ XMLCh* srcPtr = XMLString::replicate(path, manager);
+ int srcLen = XMLString::stringLen(srcPtr);
+ ArrayJanitor<XMLCh> janName(srcPtr, manager);
+ XMLCh* tarPtr = path;
+
+ while (*srcPtr)
+ {
+ if ( 3 <= srcLen )
+ {
+ if ( (isAnySlash(*srcPtr)) &&
+ (chPeriod == *(srcPtr+1)) &&
+ (isAnySlash(*(srcPtr+2))) )
+ {
+ // "\.\x" seen
+ // skip the first two, and start from the 3rd,
+ // since "\x" could be another "\."
+ srcPtr+=2;
+ srcLen-=2;
+ }
+ else
+ {
+ *tarPtr++ = *srcPtr++; // eat the current char
+ srcLen--;
+ }
+ }
+ else if ( 1 == srcLen )
+ {
+ *tarPtr++ = *srcPtr++;
+ }
+ else if ( 2 == srcLen)
+ {
+ *tarPtr++ = *srcPtr++;
+ *tarPtr++ = *srcPtr++;
+ }
+
+ }
+
+ *tarPtr = 0;
+
+ return;
+}
+
+//
+// Remove all occurences of '/segment/../' when segment is not '..'
+//
+// Cases with extra /../ is left to the underlying file system.
+//
+void XMLPlatformUtils::removeDotDotSlash(XMLCh* const path
+ , MemoryManager* const manager)
+{
+ int pathLen = XMLString::stringLen(path);
+ XMLCh* tmp1 = (XMLCh*) manager->allocate
+ (
+ (pathLen+1) * sizeof(XMLCh)
+ );//new XMLCh [pathLen+1];
+ ArrayJanitor<XMLCh> tmp1Name(tmp1, manager);
+
+ XMLCh* tmp2 = (XMLCh*) manager->allocate
+ (
+ (pathLen+1) * sizeof(XMLCh)
+ );//new XMLCh [pathLen+1];
+ ArrayJanitor<XMLCh> tmp2Name(tmp2, manager);
+
+ // remove all "<segment>/../" where "<segment>" is a complete
+ // path segment not equal to ".."
+ int index = -1;
+ int segIndex = -1;
+ int offset = 1;
+
+ while ((index = searchSlashDotDotSlash(&(path[offset]))) != -1)
+ {
+ // Undo offset
+ index += offset;
+
+ // Find start of <segment> within substring ending at found point.
+ XMLString::subString(tmp1, path, 0, index-1, manager);
+ segIndex = index - 1;
+ while ((segIndex >= 0) && (!isAnySlash(tmp1[segIndex])))
+ {
+ segIndex--;
+ }
+
+ // Ensure <segment> exists and != ".."
+ if (segIndex >= 0 &&
+ (path[segIndex+1] != chPeriod ||
+ path[segIndex+2] != chPeriod ||
+ segIndex + 3 != index))
+ {
+
+ XMLString::subString(tmp1, path, 0, segIndex, manager);
+ XMLString::subString(tmp2, path, index+3,
XMLString::stringLen(path), manager);
+
+ path[0] = 0;
+ XMLString::catString(path, tmp1);
+ XMLString::catString(path, tmp2);
+
+ offset = (segIndex == 0 ? 1 : segIndex);
+ }
+ else
+ {
+ offset += 4;
+ }
+
+ }// while
+
+}
+
+int XMLPlatformUtils::searchSlashDotDotSlash(XMLCh* const srcPath)
+{
+ if ((!srcPath) || (!*srcPath))
+ return -1;
+
+ XMLCh* srcPtr = srcPath;
+ int srcLen = XMLString::stringLen(srcPath);
+ int retVal = -1;
+
+ while (*srcPtr)
+ {
+ if ( 4 <= srcLen )
+ {
+ if ( (isAnySlash(*srcPtr)) &&
+ (chPeriod == *(srcPtr+1)) &&
+ (chPeriod == *(srcPtr+2)) &&
+ (isAnySlash(*(srcPtr+3))) )
+ {
+ retVal = (srcPtr - srcPath);
+ break;
+ }
+ else
+ {
+ srcPtr++;
+ srcLen--;
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ } // while
+
+ return retVal;
+
+}
+
+
XERCES_CPP_NAMESPACE_END
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]