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