New Ticket     Wiki     Browse Source     Timeline     Roadmap     Ticket Reports     Search

Ticket #20979: MacOSPlatformUtils.cpp.patch

File MacOSPlatformUtils.cpp.patch, 28.5 KB (added by docfaraday@…, 3 years ago)

Better patch (removed a lot of useless code)

  • src/xercesc/util/Platforms/MacOS/MacOSPlatformUtils.cpp

    old new  
    5555#include <xercesc/util/XMLUni.hpp> 
    5656#include <xercesc/util/XMLString.hpp> 
    5757#include <xercesc/util/Platforms/MacOS/MacOSPlatformUtils.hpp> 
    58 #include <xercesc/util/Platforms/MacOS/MacCarbonFile.hpp> 
    5958#include <xercesc/util/Platforms/MacOS/MacPosixFile.hpp> 
    6059#include <xercesc/util/PanicHandler.hpp> 
    6160#include <xercesc/util/OutOfMemoryException.hpp> 
    6261 
     62#include <time.h> 
     63#include <sys/time.h> 
     64#include <libkern/OSAtomic.h> 
     65 
    6366#if (defined(XML_USE_INMEMORY_MSGLOADER) || defined(XML_USE_INMEM_MESSAGELOADER)) 
    6467   #include <xercesc/util/MsgLoaders/InMemory/InMemMsgLoader.hpp> 
    6568#endif 
     
    9497XMLCh*  ConvertSlashToColon(XMLCh* p, std::size_t charCount); 
    9598char*   ConvertSlashToColon(char* p, std::size_t charCount); 
    9699 
    97 XMLCh*  XMLCreateFullPathFromFSRef_X(const FSRef& startingRef, MemoryManager* const manager); 
    98 XMLCh*  XMLCreateFullPathFromFSRef_Classic(const FSRef& startingRef, MemoryManager* const manager); 
    99 XMLCh*  XMLCreateFullPathFromFSSpec_Classic(const FSSpec& startingSpec, 
    100                                             MemoryManager* const manager); 
    101 bool    XMLParsePathToFSRef_X(const XMLCh* const pathName, FSRef& ref, MemoryManager* const manager); 
    102 bool    XMLParsePathToFSRef_Classic(const XMLCh* const pathName, FSRef& ref, MemoryManager* const manager); 
    103 bool    XMLParsePathToFSSpec_Classic(const XMLCh* const pathName, FSSpec& spec, MemoryManager* const manager); 
    104  
    105  
    106100//---------------------------------------------------------------------------- 
    107101//  Local Data 
    108102// 
     
    152146bool gHasFSPathAPIs                     = false; 
    153147bool gPathAPIsUsePosixPaths     = false; 
    154148bool gHasMPAPIs                         = false; 
    155 bool gUsePosixFiles                     = false; 
     149bool gUsePosixFiles                     = true; 
    156150bool gUseGETCWD                         = false; 
    157151 
    158152 
     
    294288XMLPlatformUtils::getFullPath(const XMLCh* const srcPath, 
    295289                              MemoryManager* const manager) 
    296290{ 
    297     XMLCh* path = NULL; 
     291    // 
     292    //  NOTE: The path provided has always already been opened successfully, 
     293    //  so we know that its not some pathological freaky path. It comes in 
     294    //  in native format, and goes out as Unicode always 
     295    // 
     296    char* newSrc = XMLString::transcode(srcPath, manager); 
     297    ArrayJanitor<char> janText(newSrc, manager); 
    298298 
    299     if (gHasHFSPlusAPIs) 
    300     { 
    301         FSRef ref; 
    302         if (   !XMLParsePathToFSRef(srcPath, ref, manager) 
    303                         || (path = XMLCreateFullPathFromFSRef(ref, manager)) == NULL 
    304                    ) 
    305             path = XMLString::replicate(srcPath, manager); 
    306     } 
    307     else 
    308     { 
    309         FSSpec spec; 
    310         if (   !XMLParsePathToFSSpec(srcPath, spec, manager) 
    311                     || (path = XMLCreateFullPathFromFSSpec(spec, manager)) == NULL 
    312                    ) 
    313             path = XMLString::replicate(srcPath, manager); 
    314     } 
     299    // Use a local buffer that is big enough for the largest legal path 
     300    char absPath[PATH_MAX + 1]; 
     301     
     302    // get the absolute path 
     303    if (!realpath(newSrc, absPath)) 
     304                ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetBasePathName, manager); 
    315305 
    316     return path; 
     306    return XMLString::transcode(absPath, manager); 
    317307} 
    318308 
    319309 
     
    321311XMLPlatformUtils::isRelative(const XMLCh* const toCheck 
    322312                             , MemoryManager* const manager) 
    323313{ 
    324     return (toCheck[0] != L'/'); 
     314    // Check for pathological case of empty path 
     315    if (!toCheck || !toCheck[0]) 
     316        return false; 
     317 
     318    // 
     319    //  If it starts with a slash, then it cannot be relative. 
     320    // 
     321    return toCheck[0] != XMLCh('/'); 
    325322} 
    326323 
    327324 
    328325XMLCh* XMLPlatformUtils::getCurrentDirectory(MemoryManager* const manager) 
    329326{ 
    330         //      Get a newly allocated path to the current directory 
    331         FSSpec spec; 
     327    char dirBuf[PATH_MAX + 2]; 
     328    char *curDir = getcwd(&dirBuf[0], PATH_MAX + 1); 
     329 
     330    if (!curDir) 
     331        ThrowXMLwithMemMgr(XMLPlatformUtilsException, 
     332                 XMLExcepts::File_CouldNotGetBasePathName, manager); 
    332333 
    333         //  Parse to path to determine current directory: this allows the 
    334         //  path parsing routines to determine best way to find the current 
    335         //  directory. 
    336         XMLCh curDirPath[] = { '.', 0 }; 
    337         XMLCh* path = 
    338                 (XMLParsePathToFSSpec(curDirPath, spec, manager)) 
    339                         ? XMLCreateFullPathFromFSSpec(spec, manager) 
    340                         : NULL; 
    341                          
    342     if (!path) 
    343                  ThrowXMLwithMemMgr(XMLPlatformUtilsException, 
    344                    XMLExcepts::File_CouldNotGetBasePathName, manager); 
    345                     
    346         return path; 
     334    return XMLString::transcode(curDir, manager); 
    347335} 
    348336 
    349337 
     
    360348unsigned long 
    361349XMLPlatformUtils::getCurrentMillis() 
    362350{ 
    363         if ((void*)kUnresolvedCFragSymbolAddress != UpTime) 
    364         { 
    365                 // Use Driver services routines, now in Carbon, 
    366                 // to get the elapsed milliseconds. 
    367                 AbsoluteTime time = UpTime(); 
    368                 return AbsoluteToDuration(time); 
    369         } 
    370         else 
    371                 return TickCount() * 100 / 6; 
     351        unsigned long ms = 0; 
     352 
     353   struct timeval aTime; 
     354   gettimeofday(&aTime, NULL); 
     355   ms = (unsigned long) (aTime.tv_sec * 1000 + aTime.tv_usec / 1000); 
     356 
     357        return ms; 
    372358} 
    373359 
    374360 
     
    462448    // Replace *toFill with newValue iff *toFill == toCompare, 
    463449    // returning previous value of *toFill 
    464450 
    465     Boolean success = CompareAndSwap( 
    466         reinterpret_cast<UInt32>(toCompare), 
    467         reinterpret_cast<UInt32>(newValue), 
    468         reinterpret_cast<UInt32*>(toFill)); 
     451    Boolean success = OSAtomicCompareAndSwapPtrBarrier( 
     452                                 const_cast<void*>(toCompare), 
     453                                 const_cast<void*>(newValue), 
     454                                 toFill); 
    469455 
    470456    return (success) ? const_cast<void*>(toCompare) : *toFill; 
    471457} 
     
    482468int 
    483469XMLPlatformUtils::atomicIncrement(int &location) 
    484470{ 
    485     return IncrementAtomic(reinterpret_cast<long*>(&location)) + 1; 
     471    return OSAtomicIncrement32(reinterpret_cast<int32_t*>(&location)) + 1; 
    486472} 
    487473 
    488474 
    489475int 
    490476XMLPlatformUtils::atomicDecrement(int &location) 
    491477{ 
    492     return DecrementAtomic(reinterpret_cast<long*>(&location)) - 1; 
     478    return OSAtomicDecrement32(reinterpret_cast<int32_t*>(&location)) - 1; 
    493479} 
    494480 
    495481 
     
    503489void 
    504490XMLPlatformUtils::platformInit() 
    505491{ 
    506         long value = 0; 
     492        int32_t value = 0; 
    507493 
    508494        //      Detect available functions 
    509495         
     
    519505        gHasFS2TBAPIs           = (value & (1 << gestaltFSSupports2TBVols)) != 0; 
    520506        gHasHFSPlusAPIs         = (value & (1 << gestaltHasHFSPlusAPIs)) != 0; 
    521507 
    522         #if TARGET_API_MAC_CARBON 
    523         gHasFSPathAPIs          = ((void*)kUnresolvedCFragSymbolAddress != FSPathMakeRef); 
    524         #else 
    525         gHasFSPathAPIs          = false; 
    526         #endif 
    527  
    528         gPathAPIsUsePosixPaths = gHasFSPathAPIs 
    529                                                                  && (value & (1 << gestaltFSUsesPOSIXPathsForConversion)); 
     508        gPathAPIsUsePosixPaths = true; 
    530509    } 
    531510 
    532511        //      We require FSSpecs at a minimum 
    533512    gFileSystemCompatible       = gHasFSSpecAPIs; 
    534513 
    535         //      Determine which file system to use (posix or carbon file access) 
    536         //      If we're using Metrowerks MSL, we surely don't want posix paths, 
    537         //      as MSL doesn't use them. 
    538         #if __MSL__ && (__MSL__ < 0x08000 || _MSL_CARBON_FILE_APIS) 
    539         gUsePosixFiles                  = false; 
    540         #else 
    541         gUsePosixFiles                  = gMacOSXOrBetter; 
    542         #endif 
    543          
    544514        //  Determine whether to use getcwd or not. We use it only if we're not using MSL, 
    545515        //  and we're on a Mac OS X system. 
    546516        #if __MSL__ 
     
    754724{ 
    755725        XMLMacAbstractFile* result = NULL; 
    756726         
    757         if (gUsePosixFiles) 
    758727                result = new (manager) XMLMacPosixFile; 
    759         else 
    760                 result = new (manager) XMLMacCarbonFile; 
    761                  
    762         return result; 
    763 } 
    764  
    765  
    766 bool 
    767 XMLParsePathToFSRef(const XMLCh* const pathName, FSRef& ref, MemoryManager* const manager) 
    768 { 
    769         bool result; 
    770          
    771         //      If FSPathMakeRef is available, we use it to parse the 
    772         //      path: this gives us "standard" path support under MacOS X. 
    773         //      Without this, our paths in that environment would always 
    774         //      have a volume name at their root...which would look 
    775         //      "normal" to Mac users, but not normal to unix users. Since 
    776         //      we're making "unix" paths, we'll stick with the unix 
    777         //      style paths. This also allows us to easilly take paths 
    778         //      off the command line. 
    779         // 
    780         //      FSPathMakeRef is available on Mac OS X and in CarbonLib 1.1 
    781         //      and greater. But on classic under CarbonLib, it expects paths 
    782         //      to contain ':' separators, for which we're not prepared. Since 
    783         //      this isn't a case where we need to use it, we drop back to the 
    784         //      classic case for this. 
    785                  
    786         if (TARGET_API_MAC_CARBON && gHasFSPathAPIs && gPathAPIsUsePosixPaths) 
    787                 result = XMLParsePathToFSRef_X(pathName, ref, manager); 
    788         else 
    789                 result = XMLParsePathToFSRef_Classic(pathName, ref, manager); 
    790                  
    791         return result; 
    792 } 
    793  
    794  
    795 bool 
    796 XMLParsePathToFSRef_X(const XMLCh* const pathName, FSRef& ref, MemoryManager* const manager) 
    797 { 
    798         //      Parse Path to FSRef using FSPathMakeRef as available under 
    799         //      Mac OS X and CarbonLib 1.1 and greater. 
    800          
    801         OSStatus err = noErr;    
    802         std::size_t pathLen = XMLString::stringLen(pathName); 
    803  
    804     //  Transcode XMLCh into UniChar 
    805         UniChar uniBuf[kMaxMacStaticPathChars]; 
    806         CopyXMLChsToUniChars(pathName, uniBuf, pathLen, kMaxMacStaticPathChars); 
    807          
    808         //      Transcode Unicode to UTF-8 
    809         char utf8Buf[kMaxMacStaticPathChars]; 
    810         pathLen = TranscodeUniCharsToUTF8(uniBuf, utf8Buf, pathLen, kMaxMacStaticPathChars-1); 
    811          
    812         //      Terminate the path 
    813         char* p = utf8Buf; 
    814         p[pathLen++] = '\0'; 
    815          
    816         //      If it's a relative path, pre-pend the current directory to the path. 
    817         //      FSPathMakeRef doesn't deal with relativity on the front of the path 
    818         if (*p != '/' && kMaxMacStaticPathChars > pathLen) 
    819         { 
    820                 //      Right justify the user path to make room for the pre-pended path 
    821                 std::memmove(p + kMaxMacStaticPathChars - pathLen, p, pathLen); 
    822                 *p = '\0'; 
    823                                  
    824                 //      Get the current directory 
    825                 if (gUseGETCWD) 
    826                 { 
    827                         //      Get current directory path, leaving room for one '/' after 
    828                         if (err == noErr) 
    829                                 getcwd(p, kMaxMacStaticPathChars - pathLen - 1); 
    830                 } 
    831                 else 
    832                 { 
    833                         //      Get current directory path, leaving room for one '/' after 
    834  
    835                         //      We quiz the carbon file manager for the current directory. 
    836                         //      Note that carbon defaults its concept of the current directory 
    837                         //  to the location of the executable. 
    838                 FSSpec spec; 
    839                         if (err == noErr) 
    840                                 err = FSMakeFSSpec(0, 0, NULL, &spec); 
    841                 if (err == noErr) 
    842                     err = FSpMakeFSRef(&spec, &ref); 
    843                          
    844                         //      Get current directory path, leaving room for one '/' after 
    845                         if (err == noErr) 
    846                                 err = FSRefMakePath(&ref, reinterpret_cast<UInt8*>(p), kMaxMacStaticPathChars - pathLen - 1); 
    847                 } 
    848                                          
    849                 //      Now munge the two paths back together 
    850                 std::size_t prefixLen = std::strlen(p); 
    851                 p[prefixLen++] = '/'; 
    852                 std::memmove(p + prefixLen, p + kMaxMacStaticPathChars - pathLen, pathLen); 
    853                  
    854                 //      We now have a path from an absolute starting point 
    855         } 
    856          
    857         //      Let the OS discover the location 
    858         Boolean isDirectory = false; 
    859         if (err == noErr) 
    860                 err = FSPathMakeRef(reinterpret_cast<UInt8*>(p), &ref, &isDirectory); 
    861                  
    862         //      Return true on success 
    863         return (err == noErr); 
    864 } 
    865  
    866  
    867 bool 
    868 XMLParsePathToFSRef_Classic(const XMLCh* const pathName, FSRef& ref, MemoryManager* const manager) 
    869 { 
    870         //      Parse Path to FSRef by stepping manually through path components. 
    871          
    872         //      Path's parsed in this way must always begin with a volume name. 
    873         //      This assumption would fail for standard unix paths under Mac OS X, 
    874         //      so for those cases we use the routine XMLParsePathToFSRef_Carbon 
    875         //      above. 
    876          
    877     const XMLCh* p = pathName; 
    878     const XMLCh* pEnd; 
    879     std::size_t segLen; 
    880          
    881         const std::size_t kXMLBufCount = 256; 
    882         XMLCh xmlBuf[kXMLBufCount]; 
    883  
    884     OSErr err = noErr; 
    885  
    886     if (*p == L'/') 
    887     { 
    888         // Absolute name: grab the first component as volume name 
    889  
    890         // Find the end of the path segment 
    891         for (pEnd = ++p; *pEnd && *pEnd != L'/'; ++pEnd) ; 
    892         segLen = pEnd - p; 
    893  
    894         // Try to find a volume that matches this name 
    895         for (ItemCount volIndex = 1; err == noErr; ++volIndex) 
    896         { 
    897             HFSUniStr255 hfsStr; 
    898             hfsStr.length = 0; 
    899  
    900             // Get the volume name 
    901             err = FSGetVolumeInfo( 
    902                 0, 
    903                 volIndex, 
    904                 static_cast<FSVolumeRefNum*>(NULL), 
    905                 0, 
    906                 static_cast<FSVolumeInfo*>(NULL), 
    907                 &hfsStr, 
    908                 &ref 
    909                 ); 
    910  
    911             // Compare against our path segment 
    912             if (err == noErr && segLen == hfsStr.length) 
    913             { 
    914                 //      Case-insensitive compare 
    915                 if (XMLString::compareNIString( 
    916                                                                         ConvertSlashToColon( 
    917                                                                                 CopyUniCharsToXMLChs(hfsStr.unicode, xmlBuf, segLen, kXMLBufCount), 
    918                                                                                 segLen), 
    919                                                                         p, segLen) == 0) 
    920                     break;  // we found our volume 
    921             } 
    922         } 
    923  
    924         p = pEnd; 
    925     } 
    926     else 
    927     { 
    928         // Relative name, so get the default directory as parent ref 
    929         FSSpec spec; 
    930         err = FSMakeFSSpec(0, 0, NULL, &spec); 
    931         if (err == noErr) 
    932             err = FSpMakeFSRef(&spec, &ref); 
    933     } 
    934  
    935     // ref now refers to the parent directory: parse the rest of the path 
    936     while (err == noErr && *p) 
    937     { 
    938         switch (*p) 
    939         { 
    940         case L'/':   // Just skip any number of path separators 
    941             ++p; 
    942             break; 
    943  
    944         case L'.':   // Potentially "current directory" or "parent directory" 
    945             if (p[1] == L'/' || p[1] == 0)       // "current directory" 
    946             { 
    947                 ++p; 
    948                 break; 
    949             } 
    950             else if (p[1] == L'.' && (p[2] == L'/' || p[2] == 0)) // "parent directory" 
    951             { 
    952                 p += 2;  // Get the parent of our parent 
    953  
    954                 FSCatalogInfo catalogInfo; 
    955                 err = FSGetCatalogInfo( 
    956                     &ref, 
    957                     kFSCatInfoParentDirID, 
    958                     &catalogInfo, 
    959                     static_cast<HFSUniStr255*>(NULL), 
    960                     static_cast<FSSpec*>(NULL), 
    961                     &ref 
    962                     ); 
    963  
    964                 // Check that we didn't go too far 
    965                 if (err != noErr || catalogInfo.parentDirID == fsRtParID) 
    966                     return false; 
    967  
    968                 break; 
    969             } 
    970             else // some other sequence of periods...fall through and treat as segment 
    971                 ; 
    972  
    973         default: 
    974             // Find the end of the path segment 
    975             for (pEnd = p; *pEnd && *pEnd != L'/'; ++pEnd) ; 
    976             segLen = pEnd - p; 
    977                          
    978             // pEnd now points either to '/' or NUL 
    979             // Create a new ref using this path segment 
    980             err = FSMakeFSRefUnicode( 
    981                 &ref, 
    982                 segLen, 
    983                 ConvertColonToSlash( 
    984                         CopyXMLChsToUniChars(p, reinterpret_cast<UniChar*>(xmlBuf), segLen, kXMLBufCount), 
    985                         segLen), 
    986                 kTextEncodingUnknown, 
    987                 &ref 
    988                 ); 
    989  
    990             p = pEnd; 
    991             break; 
    992         } 
    993     } 
    994  
    995     return err == noErr; 
    996 } 
    997  
    998  
    999 bool 
    1000 XMLParsePathToFSSpec(const XMLCh* const pathName, FSSpec& spec, 
    1001                             MemoryManager* const manager) 
    1002 { 
    1003         //      Parse Path to an FSSpec 
    1004  
    1005         //      If we've got HFS+ APIs, do this in terms of refs so that 
    1006         //      we can grandfather in the use of FSPathMakeRef under Mac OS X 
    1007         //      and CarbonLib 1.1. Otherwise, do it the hard way. 
    1008          
    1009         bool result = false; 
    1010          
    1011         if (gHasHFSPlusAPIs) 
    1012         { 
    1013                 //      Parse to a ref 
    1014                 FSRef ref; 
    1015                 result = XMLParsePathToFSRef(pathName, ref, manager); 
    1016728                 
    1017                 //      Down convert to a spec 
    1018                 if (result) 
    1019                         result = (noErr == FSGetCatalogInfo(&ref, 
    1020                                                                 kFSCatInfoNone, 
    1021                                                                 static_cast<FSCatalogInfo*>(NULL),      // catalogInfo 
    1022                                                                 static_cast<HFSUniStr255*>(NULL),       // outName 
    1023                                                                 &spec, 
    1024                                                                 static_cast<FSRef*>(NULL)                       // parentRef 
    1025                                                                 )); 
    1026         } 
    1027         else 
    1028                 result = XMLParsePathToFSSpec_Classic(pathName, spec, manager); 
    1029                  
    1030         //      Return true on success 
    1031729        return result; 
    1032730} 
    1033731 
    1034732 
    1035 bool 
    1036 XMLParsePathToFSSpec_Classic(const XMLCh* const pathName, FSSpec& spec, 
    1037                             MemoryManager* const manager) 
    1038 { 
    1039         //      Manually parse the path using FSSpec APIs. 
    1040          
    1041     //  Transcode the path into ascii 
    1042     const char* p = XMLString::transcode(pathName, manager); 
    1043     ArrayJanitor<const char> janPath(p, manager); 
    1044     const char* pEnd; 
    1045     std::size_t segLen; 
    1046  
    1047     OSStatus err = noErr; 
    1048     Str255 name;  // Must be long enough for a partial pathname consisting of two segments (64 bytes) 
    1049  
    1050     if (*p == '/') 
    1051     { 
    1052         // Absolute name: grab the first component as volume name 
    1053  
    1054         // Find the end of the path segment 
    1055         for (pEnd = ++p; *pEnd && *pEnd != '/'; ++pEnd) ; 
    1056         segLen = pEnd - p; 
    1057  
    1058         // Try to find a volume that matches this name 
    1059         for (ItemCount volIndex = 1; err == noErr; ++volIndex) 
    1060         { 
    1061             FSVolumeRefNum volRefNum; 
    1062  
    1063             if (gHasFS2TBAPIs) 
    1064             { 
    1065                 XVolumeParam xVolParam; 
    1066                 name[0] = 0; 
    1067                 xVolParam.ioNamePtr  = name; 
    1068                 xVolParam.ioVRefNum  = 0; 
    1069                 xVolParam.ioXVersion = 0; 
    1070                 xVolParam.ioVolIndex = volIndex; 
    1071                 err = PBXGetVolInfoSync(&xVolParam); 
    1072                 volRefNum = xVolParam.ioVRefNum; 
    1073             } 
    1074             else 
    1075             { 
    1076 #if !TARGET_API_MAC_CARBON 
    1077                 HParamBlockRec hfsParams; 
    1078                 name[0] = 0; 
    1079                 hfsParams.volumeParam.ioNamePtr  = name; 
    1080                 hfsParams.volumeParam.ioVRefNum  = 0; 
    1081                 hfsParams.volumeParam.ioVolIndex = volIndex; 
    1082                 err = PBHGetVInfoSync(&hfsParams); 
    1083                 volRefNum = hfsParams.volumeParam.ioVRefNum; 
    1084 #else 
    1085                 err = nsvErr; 
    1086 #endif 
    1087             } 
    1088  
    1089             // Compare against our path segment 
    1090             if (err == noErr && segLen == StrLength(name)) 
    1091             { 
    1092                 //      Case-insensitive compare 
    1093                 if (XMLString::compareNIString( 
    1094                                 ConvertSlashToColon(reinterpret_cast<char*>(&name[1]), segLen), 
    1095                                 p, segLen) == 0) 
    1096                 { 
    1097                     // we found our volume: fill in the spec 
    1098                     err = FSMakeFSSpec(volRefNum, fsRtDirID, NULL, &spec); 
    1099                     break; 
    1100                 } 
    1101             } 
    1102         } 
    1103  
    1104         p = pEnd; 
    1105     } 
    1106     else 
    1107     { 
    1108         // Relative name, so get the default directory as parent spec 
    1109         err = FSMakeFSSpec(0, 0, NULL, &spec); 
    1110     } 
    1111  
    1112     // We now have a parent directory in the spec. 
    1113     while (err == noErr && *p) 
    1114     { 
    1115         switch (*p) 
    1116         { 
    1117         case '/':       // Just skip any number of path separators 
    1118             ++p; 
    1119             break; 
    1120  
    1121         case L'.':      // Potentially "current directory" or "parent directory" 
    1122             if (p[1] == '/' || p[1] == 0)      // "current directory" 
    1123             { 
    1124                 ++p; 
    1125                 break; 
    1126             } 
    1127             else if (p[1] == '.' && (p[2] == '/' || p[2] == 0)) // "parent directory" 
    1128             { 
    1129                 p += 2;  // Get the parent of our parent 
    1130  
    1131                 CInfoPBRec catInfo; 
    1132                 catInfo.dirInfo.ioNamePtr = NULL; 
    1133                 catInfo.dirInfo.ioVRefNum = spec.vRefNum; 
    1134                 catInfo.dirInfo.ioFDirIndex = -1; 
    1135                 catInfo.dirInfo.ioDrDirID = spec.parID; 
    1136                 err = PBGetCatInfoSync(&catInfo); 
    1137  
    1138                 // Check that we didn't go too far 
    1139                 if (err != noErr || catInfo.dirInfo.ioDrParID == fsRtParID) 
    1140                     return false; 
    1141  
    1142                 // Update our spec 
    1143                 if (err == noErr) 
    1144                     err = FSMakeFSSpec(spec.vRefNum, catInfo.dirInfo.ioDrDirID, NULL, &spec); 
    1145  
    1146                 break; 
    1147             } 
    1148             else // some other sequence of periods...fall through and treat as segment 
    1149                 ; 
    1150  
    1151         default: 
    1152             { 
    1153                 // Find the end of the path segment 
    1154                 for (pEnd = p; *pEnd && *pEnd != '/'; ++pEnd) ; 
    1155                 segLen = pEnd - p; 
    1156  
    1157                 // Check for name length overflow 
    1158                 if (segLen > 31) 
    1159                     return false; 
    1160  
    1161                 // Make a partial pathname from our current spec to the new object 
    1162                 unsigned char* partial = &name[1]; 
    1163  
    1164                 *partial++ = ':';       // Partial leads with : 
    1165                 const unsigned char* specName = spec.name; // Copy in spec name 
    1166                 for (int specCnt = *specName++; specCnt > 0; --specCnt) 
    1167                     *partial++ = *specName++; 
    1168  
    1169                 *partial++ = ':';       // Separator 
    1170                 while (p != pEnd)       // Copy in new element 
    1171                 { 
    1172                         if (*p == ':')                          // Convert : to / 
    1173                         { 
    1174                                 *partial++ = '/'; 
    1175                                 p++; 
    1176                         } 
    1177                         else 
    1178                                 *partial++ = *p++; 
    1179                                 } 
    1180                                  
    1181                 name[0] = partial - &name[1];   // Set the name length 
    1182  
    1183                 // Update the spec 
    1184                 err = FSMakeFSSpec(spec.vRefNum, spec.parID, name, &spec); 
    1185             } 
    1186             break; 
    1187         } 
    1188     } 
    1189  
    1190     return err == noErr; 
    1191 } 
    1192  
    1193  
    1194 XMLCh* 
    1195 XMLCreateFullPathFromFSRef(const FSRef& startingRef, 
    1196                             MemoryManager* const manager) 
    1197 { 
    1198         XMLCh* result = NULL; 
    1199          
    1200         //      If FSRefMakePath is available, we use it to create the 
    1201         //      path: this gives us "standard" path support under MacOS X. 
    1202         //      Without this, our paths in that environment would always 
    1203         //      have a volume name at their root...which would look 
    1204         //      "normal" to Mac users, but not normal to unix users. Since 
    1205         //      we're making "unix" paths, we'll stick with the unix 
    1206         //      style paths. This also allows us to easilly take paths 
    1207         //      off the command line. 
    1208         // 
    1209         //      FSRefMakePath is available on Mac OS X and in CarbonLib 1.1 
    1210         //      and greater. But we use it only on X since on Classic it 
    1211         //      makes paths with ':' separators, which really confuses us! 
    1212          
    1213         if (TARGET_API_MAC_CARBON && gHasFSPathAPIs && gPathAPIsUsePosixPaths) 
    1214                 result = XMLCreateFullPathFromFSRef_X(startingRef, manager); 
    1215         else 
    1216                 result = XMLCreateFullPathFromFSRef_Classic(startingRef, manager); 
    1217                  
    1218         return result; 
    1219 } 
    1220  
    1221  
    1222 XMLCh* 
    1223 XMLCreateFullPathFromFSRef_X(const FSRef& startingRef, 
    1224                             MemoryManager* const manager) 
    1225 { 
    1226         //      Create the path using FSRefMakePath as available on Mac OS X 
    1227         //      and under CarbonLib 1.1 and greater. 
    1228         OSStatus err = noErr; 
    1229          
    1230         //      Make the path in utf8 form 
    1231         char utf8Buf[kMaxMacStaticPathChars]; 
    1232         utf8Buf[0] = '\0'; 
    1233          
    1234         if (err == noErr) 
    1235                 err = FSRefMakePath(&startingRef, reinterpret_cast<UInt8*>(utf8Buf), kMaxMacStaticPathChars); 
    1236                  
    1237         //      Bail if path conversion failed 
    1238         if (err != noErr) 
    1239                 return NULL; 
    1240          
    1241         //      Transcode into UniChars 
    1242         UniChar uniBuf[kMaxMacStaticPathChars]; 
    1243         std::size_t pathLen = TranscodeUTF8ToUniChars(utf8Buf, uniBuf, kMaxMacStaticPathChars-1); 
    1244         uniBuf[pathLen++] = 0; 
    1245          
    1246         //      Transcode into a dynamically allocated buffer of XMLChs 
    1247         ArrayJanitor<XMLCh> result((XMLCh*) manager->allocate(pathLen * sizeof(XMLCh))/*new XMLCh[pathLen]*/, 
    1248                         manager); 
    1249         if (result.get() != NULL) 
    1250                 CopyUniCharsToXMLChs(uniBuf, result.get(), pathLen, pathLen); 
    1251                  
    1252         return result.release(); 
    1253 } 
    1254  
    1255  
    1256 XMLCh* 
    1257 XMLCreateFullPathFromFSRef_Classic(const FSRef& startingRef, 
    1258                             MemoryManager* const manager) 
    1259 { 
    1260         //      Manually create the path using FSRef APIs. 
    1261     OSStatus err = noErr; 
    1262     FSCatalogInfo catalogInfo; 
    1263     HFSUniStr255 name; 
    1264     FSRef ref = startingRef; 
    1265  
    1266     XMLCh buf[kMaxMacStaticPathChars]; 
    1267     std::size_t bufPos   = kMaxMacStaticPathChars; 
    1268     std::size_t bufCnt   = 0; 
    1269  
    1270     ArrayJanitor<XMLCh> result(NULL); 
    1271     std::size_t resultLen = 0; 
    1272  
    1273     buf[--bufPos] = L'\0'; 
    1274     ++bufCnt; 
    1275  
    1276         do 
    1277         { 
    1278                 err = FSGetCatalogInfo( 
    1279                         &ref, 
    1280                         kFSCatInfoParentDirID, 
    1281                         &catalogInfo, 
    1282                         &name, 
    1283                         static_cast<FSSpec*>(NULL), 
    1284                         &ref 
    1285                         ); 
    1286                  
    1287                 if (err == noErr) 
    1288                 { 
    1289                         // If there's not room in our static buffer for the new 
    1290                         // name plus separator, dump it to the dynamic result buffer. 
    1291                         if (bufPos < (std::size_t)name.length + 1) 
    1292                         { 
    1293                                 ArrayJanitor<XMLCh> temp 
    1294                 ( 
    1295                     (XMLCh*) manager->allocate((bufCnt + resultLen) * sizeof(XMLCh)) //new XMLCh[bufCnt + resultLen] 
    1296                     , manager 
    1297                 ); 
    1298                                  
    1299                                 // Copy in the static buffer 
    1300                                 std::memcpy(temp.get(), &buf[bufPos], bufCnt * sizeof(XMLCh)); 
    1301                                  
    1302                                 // Copy in the old buffer 
    1303                                 if (resultLen > 0) 
    1304                                         std::memcpy(temp.get() + bufCnt, result.get(), resultLen * sizeof(XMLCh)); 
    1305                                  
    1306                                 result.reset(temp.release()); 
    1307                                 resultLen += bufCnt; 
    1308                                  
    1309                                 bufPos = kMaxMacStaticPathChars; 
    1310                                 bufCnt = 0; 
    1311                         } 
    1312                          
    1313                         // Prepend our new name and a '/' 
    1314                         bufPos -= name.length; 
    1315                         ConvertSlashToColon( 
    1316                                 CopyUniCharsToXMLChs(name.unicode, &buf[bufPos], name.length, name.length), 
    1317                                 name.length); 
    1318                         buf[--bufPos] = L'/'; 
    1319                         bufCnt += (name.length + 1); 
    1320                 } 
    1321         } 
    1322         while (err == noErr && catalogInfo.parentDirID != fsRtParID); 
    1323          
    1324         // Composite existing buffer + any previous result buffer 
    1325         ArrayJanitor<XMLCh> final 
    1326     ( 
    1327         (XMLCh*) manager->allocate((bufCnt + resultLen) * sizeof(XMLCh))//new XMLCh[bufCnt + resultLen] 
    1328         , manager 
    1329     ); 
    1330          
    1331         // Copy in the static buffer 
    1332         std::memcpy(final.get(), &buf[bufPos], bufCnt * sizeof(XMLCh)); 
    1333          
    1334         // Copy in the old buffer 
    1335         if (resultLen > 0) 
    1336                 std::memcpy(final.get() + bufCnt, result.get(), resultLen * sizeof(XMLCh)); 
    1337          
    1338     return final.release(); 
    1339 } 
    1340  
    1341  
    1342 XMLCh* 
    1343 XMLCreateFullPathFromFSSpec(const FSSpec& startingSpec, 
    1344                             MemoryManager* const manager) 
    1345 { 
    1346         XMLCh* result = NULL; 
    1347          
    1348         //      If FSRefs are available, do this operation in terms of refs...this 
    1349         //      allows us to grandfather in the use of FSPathMakeRef and FSRefMakePath 
    1350         //      if possible. 
    1351         if (gHasHFSPlusAPIs) 
    1352         { 
    1353                 OSStatus err = noErr; 
    1354                 FSRef ref; 
    1355                  
    1356                 //      Up convert to FSRef 
    1357                 if (err == noErr) 
    1358                         err = FSpMakeFSRef(&startingSpec, &ref); 
    1359                          
    1360                 //      Create the path 
    1361                 if (err == noErr) 
    1362                         result = XMLCreateFullPathFromFSRef(ref, manager); 
    1363         } 
    1364         else 
    1365         { 
    1366                 //      Create using FSSpecs only 
    1367                 result = XMLCreateFullPathFromFSSpec_Classic(startingSpec, manager); 
    1368         } 
    1369                  
    1370         return result; 
    1371 } 
    1372  
    1373  
    1374 XMLCh* 
    1375 XMLCreateFullPathFromFSSpec_Classic(const FSSpec& startingSpec, 
    1376                                     MemoryManager* const manager) 
    1377 { 
    1378         //      Manually create the path using FSSpec APIs. 
    1379     OSStatus err = noErr; 
    1380     FSSpec spec = startingSpec; 
    1381  
    1382     char buf[kMaxMacStaticPathChars]; 
    1383     std::size_t bufPos   = kMaxMacStaticPathChars; 
    1384     std::size_t bufCnt   = 0; 
    1385  
    1386     ArrayJanitor<char> result(NULL); 
    1387     std::size_t resultLen = 0; 
    1388  
    1389     buf[--bufPos] = '\0'; 
    1390     ++bufCnt; 
    1391  
    1392         short index = 0; 
    1393         do 
    1394         { 
    1395                 CInfoPBRec catInfo; 
    1396                 catInfo.dirInfo.ioNamePtr = spec.name; 
    1397                 catInfo.dirInfo.ioVRefNum = spec.vRefNum; 
    1398                 catInfo.dirInfo.ioFDirIndex = index; 
    1399                 catInfo.dirInfo.ioDrDirID = spec.parID; 
    1400                 err = PBGetCatInfoSync(&catInfo); 
    1401                  
    1402                 if (err == noErr) 
    1403                 { 
    1404                         std::size_t nameLen = StrLength(spec.name); 
    1405                          
    1406                         // If there's not room in our static buffer for the new 
    1407                         // name plus separator, dump it to the dynamic result buffer. 
    1408                         if (bufPos < nameLen + 1) 
    1409                         { 
    1410                                 ArrayJanitor<char> temp 
    1411                 ( 
    1412                     (char*) manager->allocate((bufCnt + resultLen) * sizeof(char))//new char[bufCnt + resultLen] 
    1413                     , manager 
    1414                 ); 
    1415                                  
    1416                                 // Copy in the static buffer 
    1417                                 std::memcpy(temp.get(), &buf[bufPos], bufCnt); 
    1418                                  
    1419                                 // Copy in the old buffer 
    1420                                 if (resultLen > 0) 
    1421                                         std::memcpy(temp.get() + bufCnt, result.get(), resultLen); 
    1422                                  
    1423                                 result.reset(temp.release()); 
    1424                                 resultLen += bufCnt; 
    1425                                  
    1426                                 bufPos = kMaxMacStaticPathChars; 
    1427                                 bufCnt = 0; 
    1428                         } 
    1429                          
    1430                         // Prepend our new name and a '/' 
    1431                         bufPos -= nameLen; 
    1432                         ConvertSlashToColon((char*)std::memcpy(&buf[bufPos], &spec.name[1], nameLen), nameLen); 
    1433                         buf[--bufPos] = '/'; 
    1434                         bufCnt += (nameLen + 1); 
    1435                          
    1436                         // From here on out, ignore the input file name 
    1437                         index = -1; 
    1438                          
    1439                         // Move up to the parent 
    1440                         spec.parID = catInfo.dirInfo.ioDrParID; 
    1441                 } 
    1442         } 
    1443         while (err == noErr && spec.parID != fsRtParID); 
    1444          
    1445         // Composite existing buffer with any previous result buffer 
    1446         ArrayJanitor<char> final 
    1447     ( 
    1448         (char*) manager->allocate((bufCnt + resultLen) * sizeof(char))//new char[bufCnt + resultLen] 
    1449         , manager 
    1450     ); 
    1451          
    1452         // Copy in the static buffer 
    1453         std::memcpy(final.get(), &buf[bufPos], bufCnt); 
    1454          
    1455         // Copy in the old buffer 
    1456         if (resultLen > 0) 
    1457                 std::memcpy(final.get() + bufCnt, result.get(), resultLen); 
    1458  
    1459     // Cleanup and transcode to unicode 
    1460     return XMLString::transcode(final.get(), manager); 
    1461 } 
    1462  
    1463733 
    1464734std::size_t 
    1465735TranscodeUniCharsToUTF8(const UniChar* src, char* dst, std::size_t srcCnt, std::size_t maxChars)