LogicalPath.c
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:7k
源码类别:

词法分析

开发平台:

Visual C++

  1. #if !defined(WEAVEPATH_CPP)
  2. #define WEAVEPATH_CPP
  3. /***
  4.  *
  5.  *  Previously, each <OS>PlatformUtils.cpp has its onw copy of the
  6.  *  method weavePaths(), and almost of them implemented the same logic,
  7.  *  with few platform specific difference, and unfortunately that 
  8.  *  implementation was wrong.
  9.  *  
  10.  *  The only platform specific issue is slash character.
  11.  *  On all platforms other than Windows, chForwardSlash and chBackSlash 
  12.  *  are considered slash, while on Windows, two additional characters, 
  13.  *  chYenSign and chWonSign are slash as well.
  14.  *
  15.  *  The idea is to maintain a SINGLE copy of this method rather than
  16.  *  each <OS>PlatformUtils.cpp has its own copy, we introduce a new
  17.  *  method, XMLPlatformUtils::isAnySlash(), to replace the direct checking
  18.  *  code ( if ( c == chForwardSlash || c == chBackSlash).
  19.  *
  20.  *  With this approach, we might have a performance hit since isAnySlash() 
  21.  *  is so frequently used in this implementation, so we intend to make it 
  22.  *  inline. Then we face a complier issue.
  23.  *
  24.  *  There are two compilation units involved, one is PlatformUtils.cpp and 
  25.  *  the other <OS>PlatformUtils.cpp. When PlatformUtils.cp get compiled,
  26.  *  the weavePath(), remove**Slash() have dependency upon isAnySlash() which
  27.  *  is in <OS>PlatformUtils.cpp (and what is worse, it is inlined), so we have
  28.  *  undefined/unresolved symbol: isAnySlash() on AIX/xlc_r, Solaris/cc and 
  29.  *  Linux/gcc, while MSVC and HP/aCC are fine with this.
  30.  *  
  31.  *  That means we can not place these new methods in PlatformUtils.cpp with
  32.  *  inlined XMLPlatformUtils::isAnySlash() in <OS>PlatformUtils.cpp.
  33.  *
  34.  *  The solution to this is <os>PlatformUtils.cpp will include this file so that
  35.  *  we have only one copy of these methods while get compiled in <os>PlatformUtils
  36.  *  inlined isAnySlash().
  37.  *
  38.  ***/
  39. XMLCh* XMLPlatformUtils::weavePaths(const XMLCh* const    basePath
  40.                                   , const XMLCh* const    relativePath)
  41. {
  42.     // Create a buffer as large as both parts and empty it
  43.     XMLCh* tmpBuf = (XMLCh*) fgMemoryManager->allocate
  44.     (
  45.         (XMLString::stringLen(basePath)
  46.          + XMLString::stringLen(relativePath) + 2) * sizeof(XMLCh)
  47.     );//new XMLCh[XMLString::stringLen(basePath) + XMLString::stringLen(relativePath) + 2];
  48.     *tmpBuf = 0;
  49.     //
  50.     //  If we have no base path, then just take the relative path as is.
  51.     //
  52.     if ((!basePath) || (!*basePath))
  53.     {
  54.         XMLString::copyString(tmpBuf, relativePath);
  55.         return tmpBuf;
  56.     }
  57.     //
  58.     // Remove anything after the last slash
  59.     //
  60.     const XMLCh* basePtr = basePath + (XMLString::stringLen(basePath) - 1);
  61.     while ((basePtr >= basePath)  &&  ((isAnySlash(*basePtr) == false)))
  62.     {
  63.         basePtr--;
  64.     }
  65.     // There is no relevant base path, so just take the relative part
  66.     if (basePtr < basePath)
  67.     {
  68.         XMLString::copyString(tmpBuf, relativePath);
  69.         return tmpBuf;
  70.     }
  71.     //
  72.     // 1. concatenate the base and relative
  73.     // 2. remove all occurences of "/./"
  74.     // 3. remove all occurences of segment/../ where segment is not ../
  75. // 
  76.     XMLString::subString(tmpBuf, basePath, 0, (basePtr - basePath + 1));
  77.     tmpBuf[basePtr - basePath + 1] = 0;
  78.     XMLString::catString(tmpBuf, relativePath);
  79.     removeDotSlash(tmpBuf);
  80.     removeDotDotSlash(tmpBuf);
  81.     return tmpBuf;
  82. }
  83. //
  84. // Remove all occurences of './' when it is part of '/./'
  85. //
  86. // Since it could be '.' or other combination on windows ( eg, '.'+chYanSign)
  87. // we can't make use of patterMatch().
  88. //
  89. //
  90. void XMLPlatformUtils::removeDotSlash(XMLCh* const path)
  91. {
  92.     if ((!path) || (!*path))
  93.         return;
  94.     XMLCh* srcPtr = XMLString::replicate(path, fgMemoryManager);
  95.     int    srcLen = XMLString::stringLen(srcPtr);
  96.     ArrayJanitor<XMLCh>   janName(srcPtr, fgMemoryManager);   
  97.     XMLCh* tarPtr = path;
  98.     while (*srcPtr)
  99.     {
  100.         if ( 3 <= srcLen )
  101.         {
  102.             if ( (isAnySlash(*srcPtr))     &&
  103.                 (chPeriod == *(srcPtr+1)) &&
  104.                 (isAnySlash(*(srcPtr+2)))  )
  105.             {
  106.                 // ".x" seen
  107.                 // skip the first two, and start from the 3rd,
  108.                 // since "x" could be another "."
  109.                 srcPtr+=2;              
  110.                 srcLen-=2;
  111.             }
  112.             else
  113.             {
  114.                 *tarPtr++ = *srcPtr++;  // eat the current char
  115.                 srcLen--;
  116.             }
  117.         }
  118.         else if ( 1 == srcLen )
  119.         {
  120.             *tarPtr++ = *srcPtr++;
  121.         }
  122.         else if ( 2 == srcLen)
  123.         {
  124.             *tarPtr++ = *srcPtr++;
  125.             *tarPtr++ = *srcPtr++;
  126.         }
  127.     }
  128.     *tarPtr = 0;
  129.     return;
  130. }
  131. //
  132. // Remove all occurences of '/segment/../' when segment is not '..'
  133. //
  134. // Cases with extra /../ is left to the underlying file system.
  135. //
  136. void XMLPlatformUtils::removeDotDotSlash(XMLCh* const path)
  137. {
  138.     int pathLen = XMLString::stringLen(path);
  139.     XMLCh* tmp1 = (XMLCh*) fgMemoryManager->allocate
  140.     (
  141.         (pathLen+1) * sizeof(XMLCh)
  142.     );//new XMLCh [pathLen+1];
  143.     ArrayJanitor<XMLCh>   tmp1Name(tmp1, fgMemoryManager);
  144.     XMLCh* tmp2 = (XMLCh*) fgMemoryManager->allocate
  145.     (
  146.         (pathLen+1) * sizeof(XMLCh)
  147.     );//new XMLCh [pathLen+1];
  148.     ArrayJanitor<XMLCh>   tmp2Name(tmp2, fgMemoryManager);
  149.     // remove all "<segment>/../" where "<segment>" is a complete
  150.     // path segment not equal to ".."
  151.     int index = -1;
  152.     int segIndex = -1;
  153.     int offset = 1;
  154.     while ((index = searchSlashDotDotSlash(&(path[offset]))) != -1)
  155.     {
  156.         // Undo offset
  157.         index += offset;
  158.         // Find start of <segment> within substring ending at found point.
  159.         XMLString::subString(tmp1, path, 0, index-1);
  160.         segIndex = index - 1;
  161.         while ((segIndex >= 0) && (!isAnySlash(tmp1[segIndex])))
  162.         {
  163.             segIndex--;
  164.         }
  165.         // Ensure <segment> exists and != ".."
  166.         if (segIndex >= 0                 &&
  167.             (path[segIndex+1] != chPeriod ||
  168.              path[segIndex+2] != chPeriod ||
  169.              segIndex + 3 != index))
  170.         {
  171.             XMLString::subString(tmp1, path, 0, segIndex);
  172.             XMLString::subString(tmp2, path, index+3, XMLString::stringLen(path));
  173.             path[0] = 0;
  174.             XMLString::catString(path, tmp1);
  175.             XMLString::catString(path, tmp2);
  176.             offset = (segIndex == 0 ? 1 : segIndex);
  177.         }
  178.         else
  179.         {
  180.             offset += 4;
  181.         }
  182.     }// while
  183. }
  184. int XMLPlatformUtils::searchSlashDotDotSlash(XMLCh* const srcPath)
  185. {
  186.     if ((!srcPath) || (!*srcPath))
  187.         return -1;
  188.     XMLCh* srcPtr = srcPath;
  189.     int    srcLen = XMLString::stringLen(srcPath);
  190.     int    retVal = -1;
  191.     while (*srcPtr)
  192.     {
  193.         if ( 4 <= srcLen )
  194.         {
  195.             if ( (isAnySlash(*srcPtr))     &&
  196.                  (chPeriod == *(srcPtr+1)) &&
  197.                  (chPeriod == *(srcPtr+2)) &&
  198.                  (isAnySlash(*(srcPtr+3)))  )
  199.             {
  200.                 retVal = (srcPtr - srcPath);
  201.                 break;
  202.             }
  203.             else
  204.             {
  205.                 srcPtr++;
  206.                 srcLen--;
  207.             }
  208.         }
  209.         else 
  210.         {
  211.             break;
  212.         }
  213.     } // while
  214.     return retVal;
  215. }
  216. #endif