Ticket #20979: MacOSPlatformUtils.cpp.patch

File MacOSPlatformUtils.cpp.patch, 28.5 KB (added by docfaraday@…, 12 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)