Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:15:12

0001 /*
0002  * Licensed to the Apache Software Foundation (ASF) under one or more
0003  * contributor license agreements.  See the NOTICE file distributed with
0004  * this work for additional information regarding copyright ownership.
0005  * The ASF licenses this file to You under the Apache License, Version 2.0
0006  * (the "License"); you may not use this file except in compliance with
0007  * the License.  You may obtain a copy of the License at
0008  * 
0009  *      http://www.apache.org/licenses/LICENSE-2.0
0010  * 
0011  * Unless required by applicable law or agreed to in writing, software
0012  * distributed under the License is distributed on an "AS IS" BASIS,
0013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014  * See the License for the specific language governing permissions and
0015  * limitations under the License.
0016  */
0017 
0018 /*
0019  * $Id$
0020  */
0021 
0022 #if !defined(XERCESC_INCLUDE_GUARD_WEAVEPATH_CPP)
0023 #define XERCESC_INCLUDE_GUARD_WEAVEPATH_CPP
0024 
0025 /***
0026  *
0027  *  Previously, each <OS>PlatformUtils.cpp has its onw copy of the
0028  *  method weavePaths(), and almost of them implemented the same logic,
0029  *  with few platform specific difference, and unfortunately that 
0030  *  implementation was wrong.
0031  *  
0032  *  The only platform specific issue is slash character.
0033  *  On all platforms other than Windows, chForwardSlash and chBackSlash 
0034  *  are considered slash, while on Windows, two additional characters, 
0035  *  chYenSign and chWonSign are slash as well.
0036  *
0037  *  The idea is to maintain a SINGLE copy of this method rather than
0038  *  each <OS>PlatformUtils.cpp has its own copy, we introduce a new
0039  *  method, XMLPlatformUtils::isAnySlash(), to replace the direct checking
0040  *  code ( if ( c == chForwardSlash || c == chBackSlash).
0041  *
0042  *  With this approach, we might have a performance hit since isAnySlash() 
0043  *  is so frequently used in this implementation, so we intend to make it 
0044  *  inline. Then we face a complier issue.
0045  *
0046  *  There are two compilation units involved, one is PlatformUtils.cpp and 
0047  *  the other <OS>PlatformUtils.cpp. When PlatformUtils.cp get compiled,
0048  *  the weavePath(), remove**Slash() have dependency upon isAnySlash() which
0049  *  is in <OS>PlatformUtils.cpp (and what is worse, it is inlined), so we have
0050  *  undefined/unresolved symbol: isAnySlash() on AIX/xlc_r, Solaris/cc and 
0051  *  Linux/gcc, while MSVC and HP/aCC are fine with this.
0052  *  
0053  *  That means we can not place these new methods in PlatformUtils.cpp with
0054  *  inlined XMLPlatformUtils::isAnySlash() in <OS>PlatformUtils.cpp.
0055  *
0056  *  The solution to this is <os>PlatformUtils.cpp will include this file so that
0057  *  we have only one copy of these methods while get compiled in <os>PlatformUtils
0058  *  inlined isAnySlash().
0059  *
0060  ***/
0061 XMLCh* XMLPlatformUtils::weavePaths(const XMLCh* const    basePath
0062                                   , const XMLCh* const    relativePath
0063                                   , MemoryManager* const  manager)
0064 
0065 {
0066     // Create a buffer as large as both parts and empty it
0067     XMLCh* tmpBuf = (XMLCh*) manager->allocate
0068     (
0069         (XMLString::stringLen(basePath)
0070          + XMLString::stringLen(relativePath) + 2) * sizeof(XMLCh)
0071     );//new XMLCh[XMLString::stringLen(basePath) + XMLString::stringLen(relativePath) + 2];
0072     *tmpBuf = 0;
0073 
0074     //
0075     //  If we have no base path, then just take the relative path as is.
0076     //
0077     if ((!basePath) || (!*basePath))
0078     {
0079         XMLString::copyString(tmpBuf, relativePath);
0080         return tmpBuf;
0081     }
0082 
0083     //
0084     // Remove anything after the last slash
0085     //
0086     const XMLCh* basePtr = basePath + (XMLString::stringLen(basePath) - 1);
0087     while ((basePtr >= basePath)  &&  ((isAnySlash(*basePtr) == false)))
0088     {
0089         basePtr--;
0090     }
0091 
0092     // There is no relevant base path, so just take the relative part
0093     if (basePtr < basePath)
0094     {
0095         XMLString::copyString(tmpBuf, relativePath);
0096         return tmpBuf;
0097     }
0098 
0099     //
0100     // 1. concatenate the base and relative
0101     // 2. remove all occurrences of "/./"
0102     // 3. remove all occurrences of segment/../ where segment is not ../
0103     // 
0104 
0105     XMLString::subString(tmpBuf, basePath, 0, (basePtr - basePath + 1), manager);
0106     tmpBuf[basePtr - basePath + 1] = 0;
0107     XMLString::catString(tmpBuf, relativePath);
0108 
0109     removeDotSlash(tmpBuf, manager);
0110 
0111     removeDotDotSlash(tmpBuf, manager);
0112 
0113     return tmpBuf;
0114 
0115 }
0116 
0117 //
0118 // Remove all occurrences of './' when it is part of '/./'
0119 //
0120 // Since it could be '.\' or other combination on windows ( eg, '.'+chYanSign)
0121 // we can't make use of patterMatch().
0122 //
0123 //
0124 void XMLPlatformUtils::removeDotSlash(XMLCh* const path
0125                                       , MemoryManager* const manager)
0126 {
0127     if ((!path) || (!*path))
0128         return;
0129 
0130     XMLCh* srcPtr = XMLString::replicate(path, manager);
0131     int    srcLen = XMLString::stringLen(srcPtr);
0132     ArrayJanitor<XMLCh>   janName(srcPtr, manager);   
0133     XMLCh* tarPtr = path;
0134 
0135     while (*srcPtr)
0136     {
0137         if ( 3 <= srcLen )
0138         {
0139             if ( (isAnySlash(*srcPtr))     &&
0140                 (chPeriod == *(srcPtr+1)) &&
0141                 (isAnySlash(*(srcPtr+2)))  )
0142             {
0143                 // "\.\x" seen
0144                 // skip the first two, and start from the 3rd,
0145                 // since "\x" could be another "\."
0146                 srcPtr+=2;              
0147                 srcLen-=2;
0148             }
0149             else
0150             {
0151                 *tarPtr++ = *srcPtr++;  // eat the current char
0152                 srcLen--;
0153             }
0154         }
0155         else if ( 1 == srcLen )
0156         {
0157             *tarPtr++ = *srcPtr++;
0158         }
0159         else if ( 2 == srcLen)
0160         {
0161             *tarPtr++ = *srcPtr++;
0162             *tarPtr++ = *srcPtr++;
0163         }
0164 
0165     }
0166 
0167     *tarPtr = 0;
0168 
0169     return;
0170 }
0171 
0172 //
0173 // Remove all occurrences of '/segment/../' when segment is not '..'
0174 //
0175 // Cases with extra /../ is left to the underlying file system.
0176 //
0177 void XMLPlatformUtils::removeDotDotSlash(XMLCh* const path
0178                                          , MemoryManager* const manager)
0179 {
0180     int pathLen = XMLString::stringLen(path);
0181     XMLCh* tmp1 = (XMLCh*) manager->allocate
0182     (
0183         (pathLen+1) * sizeof(XMLCh)
0184     );//new XMLCh [pathLen+1];
0185     ArrayJanitor<XMLCh>   tmp1Name(tmp1, manager);
0186 
0187     XMLCh* tmp2 = (XMLCh*) manager->allocate
0188     (
0189         (pathLen+1) * sizeof(XMLCh)
0190     );//new XMLCh [pathLen+1];
0191     ArrayJanitor<XMLCh>   tmp2Name(tmp2, manager);
0192 
0193     // remove all "<segment>/../" where "<segment>" is a complete
0194     // path segment not equal to ".."
0195     int index = -1;
0196     int segIndex = -1;
0197     int offset = 1;
0198 
0199     while ((index = searchSlashDotDotSlash(&(path[offset]))) != -1)
0200     {
0201         // Undo offset
0202         index += offset;
0203 
0204         // Find start of <segment> within substring ending at found point.
0205         XMLString::subString(tmp1, path, 0, index-1, manager);
0206         segIndex = index - 1;
0207         while ((segIndex >= 0) && (!isAnySlash(tmp1[segIndex])))
0208         {
0209             segIndex--;
0210         }
0211 
0212         // Ensure <segment> exists and != ".."
0213         if (segIndex >= 0                 &&
0214             (path[segIndex+1] != chPeriod ||
0215              path[segIndex+2] != chPeriod ||
0216              segIndex + 3 != index))
0217         {
0218 
0219             XMLString::subString(tmp1, path, 0, segIndex, manager);
0220             XMLString::subString(tmp2, path, index+3, XMLString::stringLen(path), manager);
0221 
0222             path[0] = 0;
0223             XMLString::catString(path, tmp1);
0224             XMLString::catString(path, tmp2);
0225 
0226             offset = (segIndex == 0 ? 1 : segIndex);
0227         }
0228         else
0229         {
0230             offset += 4;
0231         }
0232 
0233     }// while
0234 
0235 }
0236 
0237 int XMLPlatformUtils::searchSlashDotDotSlash(XMLCh* const srcPath)
0238 {
0239     if ((!srcPath) || (!*srcPath))
0240         return -1;
0241 
0242     XMLCh* srcPtr = srcPath;
0243     int    srcLen = XMLString::stringLen(srcPath);
0244     int    retVal = -1;
0245 
0246     while (*srcPtr)
0247     {
0248         if ( 4 <= srcLen )
0249         {
0250             if ( (isAnySlash(*srcPtr))     &&
0251                  (chPeriod == *(srcPtr+1)) &&
0252                  (chPeriod == *(srcPtr+2)) &&
0253                  (isAnySlash(*(srcPtr+3)))  )
0254             {
0255                 retVal = (srcPtr - srcPath);
0256                 break;
0257             }
0258             else
0259             {
0260                 srcPtr++;
0261                 srcLen--;
0262             }
0263         }
0264         else 
0265         {
0266             break;
0267         }
0268 
0269     } // while
0270 
0271     return retVal;
0272 
0273 }
0274 
0275 #endif