GME  13
PlatformUtils.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  *
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: PlatformUtils.cpp 932877 2010-04-11 12:17:34Z borisk $
00020  *
00021  */
00022 
00023 
00024 // ---------------------------------------------------------------------------
00025 //  Includes
00026 // ---------------------------------------------------------------------------
00027 #if HAVE_CONFIG_H
00028 #       include <config.h>
00029 #endif
00030 
00031 #if HAVE_LIMITS_H
00032 #       include <limits.h>
00033 #endif
00034 #if HAVE_SYS_TIME_H
00035 #       include <sys/time.h>
00036 #endif
00037 #if HAVE_SYS_TIMEB_H
00038 #       include <sys/timeb.h>
00039 #endif
00040 #if HAVE_CPUID_H && !XERCES_HAVE_INTRIN_H
00041 #   include <cpuid.h>
00042 #endif
00043 
00044 #include <xercesc/util/Mutexes.hpp>
00045 #include <xercesc/util/PlatformUtils.hpp>
00046 #include <xercesc/util/RefVectorOf.hpp>
00047 #include <xercesc/util/XMLString.hpp>
00048 #include <xercesc/util/XMLUni.hpp>
00049 #include <xercesc/internal/XMLReader.hpp>
00050 #include <xercesc/util/RuntimeException.hpp>
00051 #include <xercesc/util/OutOfMemoryException.hpp>
00052 #include <xercesc/util/DefaultPanicHandler.hpp>
00053 #include <xercesc/util/XMLInitializer.hpp>
00054 #include <xercesc/internal/MemoryManagerImpl.hpp>
00055 
00056 #if XERCES_HAVE_INTRIN_H
00057 #   include <intrin.h>
00058 #endif
00059 
00060 #include <xercesc/util/XMLFileMgr.hpp>
00061 #if XERCES_USE_FILEMGR_POSIX
00062 #       include <xercesc/util/FileManagers/PosixFileMgr.hpp>
00063 #endif
00064 #if XERCES_USE_FILEMGR_WINDOWS
00065 #       include <xercesc/util/FileManagers/WindowsFileMgr.hpp>
00066 #endif
00067 
00068 #include <xercesc/util/XMLMutexMgr.hpp>
00069 #if XERCES_USE_MUTEXMGR_NOTHREAD
00070 #       include <xercesc/util/MutexManagers/NoThreadMutexMgr.hpp>
00071 #endif
00072 #if XERCES_USE_MUTEXMGR_POSIX
00073 #       include <xercesc/util/MutexManagers/PosixMutexMgr.hpp>
00074 #endif
00075 #if XERCES_USE_MUTEXMGR_WINDOWS
00076 #       include <xercesc/util/MutexManagers/WindowsMutexMgr.hpp>
00077 #endif
00078 
00079 #include <xercesc/util/XMLNetAccessor.hpp>
00080 #if XERCES_USE_NETACCESSOR_CURL
00081 #       include <xercesc/util/NetAccessors/Curl/CurlNetAccessor.hpp>
00082 #endif
00083 #if XERCES_USE_NETACCESSOR_SOCKET
00084 #       include <xercesc/util/NetAccessors/Socket/SocketNetAccessor.hpp>
00085 #endif
00086 #if XERCES_USE_NETACCESSOR_CFURL
00087 #       include <xercesc/util/NetAccessors/MacOSURLAccessCF/MacOSURLAccessCF.hpp>
00088 #endif
00089 #if XERCES_USE_NETACCESSOR_WINSOCK
00090 #       include <xercesc/util/NetAccessors/WinSock/WinSockNetAccessor.hpp>
00091 #endif
00092 
00093 
00094 #include <xercesc/util/XMLMsgLoader.hpp>
00095 #if XERCES_USE_MSGLOADER_ICU
00096 #       include <xercesc/util/MsgLoaders/ICU/ICUMsgLoader.hpp>
00097 #endif
00098 #if XERCES_USE_MSGLOADER_ICONV
00099 #       include <xercesc/util/MsgLoaders/MsgCatalog/MsgCatalogLoader.hpp>
00100 #endif
00101 #if XERCES_USE_MSGLOADER_INMEMORY
00102 #       include <xercesc/util/MsgLoaders/InMemory/InMemMsgLoader.hpp>
00103 #endif
00104 #if XERCES_USE_WIN32_MSGLOADER
00105 #       include <xercesc/util/MsgLoaders/Win32/Win32MsgLoader.hpp>
00106 #endif
00107 
00108 #include <xercesc/util/TransService.hpp>
00109 #if XERCES_USE_TRANSCODER_ICU
00110 #       include <xercesc/util/Transcoders/ICU/ICUTransService.hpp>
00111 #endif
00112 #if XERCES_USE_TRANSCODER_GNUICONV
00113 #       include <xercesc/util/Transcoders/IconvGNU/IconvGNUTransService.hpp>
00114 #endif
00115 #if XERCES_USE_TRANSCODER_ICONV
00116 #       include <xercesc/util/Transcoders/Iconv/IconvTransService.hpp>
00117 #endif
00118 #if XERCES_USE_TRANSCODER_MACOSUNICODECONVERTER
00119 #       include <xercesc/util/Transcoders/MacOSUnicodeConverter/MacOSUnicodeConverter.hpp>
00120 #endif
00121 #if XERCES_USE_TRANSCODER_WINDOWS
00122 #       include <xercesc/util/Transcoders/Win32/Win32TransService.hpp>
00123 #endif
00124 
00125 XERCES_CPP_NAMESPACE_BEGIN
00126 
00127 // ---------------------------------------------------------------------------
00128 //  Local data members
00129 //
00130 //  gSyncMutex
00131 //      This is a mutex that will be used to synchronize access to some of
00132 //      the static data of the platform utilities class and here locally.
00133 // ---------------------------------------------------------------------------
00134 static XMLMutex*                gSyncMutex = 0;
00135 static long                     gInitFlag = 0;
00136 
00137 
00138 // ---------------------------------------------------------------------------
00139 //  XMLPlatformUtils: Static Data Members
00140 // ---------------------------------------------------------------------------
00141 XMLNetAccessor*         XMLPlatformUtils::fgNetAccessor = 0;
00142 XMLTransService*        XMLPlatformUtils::fgTransService = 0;
00143 #ifdef OS390
00144 XMLTransService*        XMLPlatformUtils::fgTransService2 = 0;
00145 #endif
00146 PanicHandler*           XMLPlatformUtils::fgUserPanicHandler = 0;
00147 PanicHandler*           XMLPlatformUtils::fgDefaultPanicHandler = 0;
00148 MemoryManager*          XMLPlatformUtils::fgMemoryManager = 0;
00149 bool                    XMLPlatformUtils::fgMemMgrAdopted = true;
00150 
00151 XMLFileMgr*             XMLPlatformUtils::fgFileMgr = 0;
00152 XMLMutexMgr*            XMLPlatformUtils::fgMutexMgr = 0;
00153 
00154 XMLMutex*               XMLPlatformUtils::fgAtomicMutex = 0;
00155 
00156 bool                    XMLPlatformUtils::fgXMLChBigEndian = true;
00157 bool                    XMLPlatformUtils::fgSSE2ok = false;
00158 
00159 // ---------------------------------------------------------------------------
00160 //  XMLPlatformUtils: Init/term methods
00161 // ---------------------------------------------------------------------------
00162 void XMLPlatformUtils::Initialize(const char*          const locale
00163                                 , const char*          const nlsHome
00164                                 ,       PanicHandler*  const panicHandler
00165                                 ,       MemoryManager* const memoryManager)
00166 {
00167     //
00168     //  Effects of overflow:
00169     //  . resouce re-allocations
00170     //  . consequently resource leaks
00171     //  . potentially terminate() may never get executed
00172     //
00173     //  We got to prevent overflow from happening.
00174     //  no error or exception
00175     //
00176     if (gInitFlag == LONG_MAX)
00177         return;
00178 
00179     //
00180     //  Make sure we haven't already been initialized. Note that this is not
00181     //  thread safe and is not intended for that. Its more for those COM
00182     //  like processes that cannot keep up with whether they have initialized
00183     //  us yet or not.
00184     //
00185     gInitFlag++;
00186 
00187     if (gInitFlag > 1)
00188       return;
00189 
00190     // Set pluggable memory manager
00191     if (!fgMemoryManager)
00192     {
00193         if (memoryManager)
00194         {
00195             fgMemoryManager = memoryManager;
00196             fgMemMgrAdopted = false;
00197         }
00198         else
00199         {
00200             fgMemoryManager = new MemoryManagerImpl();
00201         }
00202     }
00203 
00204     /***
00205      * Panic Handler:
00206      *
00207      ***/
00208     if (!panicHandler)
00209     {
00210         fgDefaultPanicHandler = new DefaultPanicHandler();
00211     }
00212     else
00213     {
00214         fgUserPanicHandler = panicHandler;
00215     }
00216 
00217 
00218     // Determine our endianness (with regard to a XMLCh 16-bit word)
00219     union {
00220         XMLCh ch;
00221         unsigned char ar[sizeof(XMLCh)];
00222     } endianTest;
00223     endianTest.ch = 1;
00224     fgXMLChBigEndian = (endianTest.ar[sizeof(XMLCh)-1] == 1);
00225 
00226     // Determine if we can use SSE2 functions
00227 #if defined(XERCES_HAVE_CPUID_INTRINSIC)
00228     int CPUInfo[4]={0};
00229     __cpuid(CPUInfo, 1);
00230     if(CPUInfo[3] & (1UL << 26))
00231         fgSSE2ok = true;
00232     else
00233         fgSSE2ok = false;
00234 #elif defined(XERCES_HAVE_GETCPUID)
00235     unsigned int eax, ebx, ecx, edx;
00236     if(!__get_cpuid (1, &eax, &ebx, &ecx, &edx) || (edx & (1UL << 26))==0)
00237         fgSSE2ok = false;
00238     else
00239         fgSSE2ok = true;
00240 #elif defined(XERCES_HAVE_SSE2_INTRINSIC)
00241     // if we cannot find out at runtime, assume the define has it right
00242     fgSSE2ok = true;
00243 #else
00244     fgSSE2ok = false;
00245 #endif
00246 
00247     // Initialize the platform-specific mutex and file mgrs
00248     fgMutexMgr          = makeMutexMgr(fgMemoryManager);
00249     fgFileMgr           = makeFileMgr(fgMemoryManager);
00250 
00251 
00252     // Create the local sync mutex
00253     gSyncMutex = new XMLMutex(fgMemoryManager);
00254 
00255     // Create the global "atomic operations" mutex.
00256     fgAtomicMutex = new XMLMutex(fgMemoryManager);
00257 
00258     //
00259     //  Ask the per-platform code to make the desired transcoding service for
00260     //  us to use. This call cannot throw any exceptions or do anything that
00261     //  cause any transcoding to happen. It should create the service and
00262     //  return it or zero if it cannot.
00263     //
00264     //  This one also cannot use any utility services. It can only create a
00265     //  transcoding service object and return it.
00266     //
00267     //  If we cannot make one, then we call panic to end the process.
00268     //
00269     XMLInitializer::initializeTransService(); // TransService static data.
00270 
00271     fgTransService = makeTransService();
00272 
00273     if (!fgTransService)
00274         panic(PanicHandler::Panic_NoTransService);
00275 
00276     // Initialize the transcoder service
00277     fgTransService->initTransService();
00278 
00279     //
00280     //  Try to create a default local code page transcoder. This is the one
00281     //  that will be used internally by the XMLString class. If we cannot
00282     //  create one, then call the panic method.
00283     //
00284     XMLLCPTranscoder* defXCode = XMLPlatformUtils::fgTransService->makeNewLCPTranscoder(fgMemoryManager);
00285     if (!defXCode)
00286         panic(PanicHandler::Panic_NoDefTranscoder);
00287     XMLString::initString(defXCode, fgMemoryManager);
00288 
00289     //
00290     //  Now lets ask the per-platform code to give us an instance of the type
00291     //  of network access implementation he wants to use. This can return
00292     //  a zero pointer if this platform doesn't want to support this.
00293     //
00294     fgNetAccessor = makeNetAccessor();
00295 
00296     /***
00297      * Message Loader:
00298      *
00299      *     Locale setting
00300      *     nlsHome setting
00301      ***/
00302     XMLMsgLoader::setLocale(locale);
00303     XMLMsgLoader::setNLSHome(nlsHome);
00304 
00305     // Initialize static data.
00306     //
00307     XMLInitializer::initializeStaticData();
00308 }
00309 
00310 void XMLPlatformUtils::Initialize(XMLSize_t initialDOMHeapAllocSize
00311                                 , XMLSize_t maxDOMHeapAllocSize
00312                                 , XMLSize_t maxDOMSubAllocationSize
00313                                 , const char*          const locale
00314                                 , const char*          const nlsHome
00315                                 ,       PanicHandler*  const panicHandler
00316                                 ,       MemoryManager* const memoryManager)
00317 {
00318   Initialize (locale, nlsHome, panicHandler, memoryManager);
00319 
00320   // Don't change the parameters unless it is the first time.
00321   //
00322   if (gInitFlag == 1)
00323     XMLInitializer::initializeDOMHeap(initialDOMHeapAllocSize,
00324                                       maxDOMHeapAllocSize,
00325                                       maxDOMSubAllocationSize);
00326 }
00327 
00328 void XMLPlatformUtils::Terminate()
00329 {
00330     //
00331     // To prevent it from running underflow.
00332     // otherwise we come to delete non-existing resources.
00333     //
00334     //  no error or exception
00335     //
00336     if (gInitFlag == 0)
00337         return;
00338 
00339     gInitFlag--;
00340 
00341     if (gInitFlag > 0)
00342         return;
00343 
00344     // Terminate static data.
00345     //
00346     XMLInitializer::terminateStaticData();
00347 
00348     // Delete any net accessor that got installed
00349     delete fgNetAccessor;
00350     fgNetAccessor = 0;
00351 
00352     //
00353     //  Call some other internal modules to give them a chance to clean up.
00354     //  Do the string class last in case something tries to use it during
00355     //  cleanup.
00356     //
00357     XMLString::termString();
00358 
00359     // Clean up the the transcoding service
00360     delete fgTransService;
00361     fgTransService = 0;
00362 
00363     XMLInitializer::terminateTransService(); // TransService static data.
00364 
00365     // Clean up mutexes
00366     delete gSyncMutex;          gSyncMutex = 0;
00367     delete fgAtomicMutex;       fgAtomicMutex = 0;
00368 
00369     // Clean up our mgrs
00370     delete fgFileMgr;           fgFileMgr = 0;
00371     delete fgMutexMgr;          fgMutexMgr = 0;
00372 
00373     /***
00374      *  de-allocate resource
00375      *
00376      *  refer to discussion in the Initialize()
00377      ***/
00378     XMLMsgLoader::setLocale(0);
00379     XMLMsgLoader::setNLSHome(0);
00380 
00381     delete fgDefaultPanicHandler;
00382     fgDefaultPanicHandler = 0;
00383     fgUserPanicHandler = 0;
00384 
00385     // de-allocate default memory manager
00386     if (fgMemMgrAdopted)
00387         delete fgMemoryManager;
00388     else
00389         fgMemMgrAdopted = true;
00390 
00391     // set memory manager to 0
00392     fgMemoryManager = 0;
00393 
00394     // And say we are no longer initialized
00395     gInitFlag = 0;
00396 }
00397 
00398 
00399 
00400 
00401 // ---------------------------------------------------------------------------
00402 //  XMLPlatformUtils: The panic method
00403 // ---------------------------------------------------------------------------
00404 void XMLPlatformUtils::panic(const PanicHandler::PanicReasons reason)
00405 {
00406     fgUserPanicHandler? fgUserPanicHandler->panic(reason) : fgDefaultPanicHandler->panic(reason);
00407 }
00408 
00409 
00410 
00411 // ---------------------------------------------------------------------------
00412 //  XMLPlatformUtils: Private Static Methods
00413 // ---------------------------------------------------------------------------
00414 
00415 XMLNetAccessor* XMLPlatformUtils::makeNetAccessor()
00416 {
00417         XMLNetAccessor* na = 0;
00418 
00419 #if defined (XERCES_USE_NETACCESSOR_CURL)
00420                 na = new CurlNetAccessor();
00421 #elif defined (XERCES_USE_NETACCESSOR_SOCKET)
00422                 na = new SocketNetAccessor();
00423 #elif defined (XERCES_USE_NETACCESSOR_CFURL)
00424                 na = new MacOSURLAccessCF();
00425 #elif defined (XERCES_USE_NETACCESSOR_WINSOCK)
00426                 na = new WinSockNetAccessor();
00427 #endif
00428 
00429         return na;
00430 }
00431 
00432 
00433 //
00434 //  This method is called by the platform independent part of this class
00435 //  when client code asks to have one of the supported message sets loaded.
00436 //
00437 
00438 XMLMsgLoader* XMLPlatformUtils::loadAMsgSet(const XMLCh* const msgDomain)
00439 {
00440     XMLMsgLoader* ms=0;
00441 
00442     try
00443     {
00444         #if defined (XERCES_USE_MSGLOADER_ICU)
00445                 ms = new ICUMsgLoader(msgDomain);
00446         #elif defined (XERCES_USE_MSGLOADER_ICONV)
00447                 ms = new MsgCatalogLoader(msgDomain);
00448     #elif defined (XERCES_USE_WIN32_MSGLOADER)
00449                 ms = new Win32MsgLoader(msgDomain);
00450         #elif defined (XERCES_USE_MSGLOADER_INMEMORY)
00451                 ms = new InMemMsgLoader(msgDomain);
00452         #else
00453                 #error No MsgLoader configured for platform! You must configure it.
00454         #endif
00455     }
00456     catch(const OutOfMemoryException&)
00457     {
00458         throw;
00459     }
00460     catch(...)
00461     {
00462         panic(PanicHandler::Panic_CantLoadMsgDomain);
00463     }
00464 
00465     return ms;
00466 }
00467 
00468 
00469 //
00470 //  This method is called very early in the bootstrapping process. This guy
00471 //  must create a transcoding service and return it. It cannot use any string
00472 //  methods, any transcoding services, throw any exceptions, etc... It just
00473 //  makes a transcoding service and returns it, or returns zero on failure.
00474 //
00475 
00476 XMLTransService* XMLPlatformUtils::makeTransService()
00477 {
00478         XMLTransService* tc = 0;
00479 
00480         #if defined   (XERCES_USE_TRANSCODER_ICU)
00481                 tc = new ICUTransService(fgMemoryManager);
00482         #elif defined (XERCES_USE_TRANSCODER_GNUICONV)
00483                 tc = new IconvGNUTransService(fgMemoryManager);
00484         #elif defined (XERCES_USE_TRANSCODER_ICONV)
00485                 tc = new IconvTransService(fgMemoryManager);
00486         #elif defined (XERCES_USE_TRANSCODER_MACOSUNICODECONVERTER)
00487                 tc = new MacOSUnicodeConverter(fgMemoryManager);
00488         #elif defined (XERCES_USE_TRANSCODER_WINDOWS)
00489                 tc = new Win32TransService(fgMemoryManager);
00490         #else
00491                 #error No Transcoder configured for platform! You must configure it.
00492         #endif
00493 
00494         return tc;
00495 }
00496 
00497 
00498 // ---------------------------------------------------------------------------
00499 //  XMLPlatformUtils: File Methods
00500 // ---------------------------------------------------------------------------
00501 XMLFileMgr*
00502 XMLPlatformUtils::makeFileMgr(MemoryManager* const memmgr)
00503 {
00504         XMLFileMgr* mgr = NULL;
00505 
00506         #if XERCES_USE_FILEMGR_POSIX
00507                 mgr = new (memmgr) PosixFileMgr;
00508         #elif XERCES_USE_FILEMGR_WINDOWS
00509                 mgr = new (memmgr) WindowsFileMgr;
00510         #else
00511                 #error No File Manager configured for platform! You must configure it.
00512         #endif
00513 
00514         return mgr;
00515 }
00516 
00517 
00518 FileHandle
00519 XMLPlatformUtils::openFile(const char* const fileName
00520                            , MemoryManager* const memmgr)
00521 {
00522     if (!fgFileMgr)
00523                 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
00524 
00525         return fgFileMgr->fileOpen(fileName, false, memmgr);
00526 }
00527 
00528 
00529 FileHandle
00530 XMLPlatformUtils::openFile(const XMLCh* const fileName, MemoryManager* const memmgr)
00531 {
00532     if (!fgFileMgr)
00533                 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
00534 
00535         return fgFileMgr->fileOpen(fileName, false, memmgr);
00536 }
00537 
00538 
00539 FileHandle
00540 XMLPlatformUtils::openFileToWrite(const char* const fileName
00541                                   , MemoryManager* const memmgr)
00542 {
00543     if (!fgFileMgr)
00544                 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
00545 
00546         return fgFileMgr->fileOpen(fileName, true, memmgr);
00547 }
00548 
00549 
00550 FileHandle
00551 XMLPlatformUtils::openFileToWrite(const XMLCh* const fileName
00552                                   , MemoryManager* const memmgr)
00553 {
00554     if (!fgFileMgr)
00555                 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
00556 
00557         return fgFileMgr->fileOpen(fileName, true, memmgr);
00558 }
00559 
00560 
00561 FileHandle
00562 XMLPlatformUtils::openStdInHandle(MemoryManager* const memmgr)
00563 {
00564     if (!fgFileMgr)
00565                 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
00566 
00567         return fgFileMgr->openStdIn(memmgr);
00568 }
00569 
00570 
00571 void
00572 XMLPlatformUtils::closeFile(FileHandle theFile
00573                             , MemoryManager* const memmgr)
00574 {
00575     if (!fgFileMgr)
00576                 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
00577 
00578         fgFileMgr->fileClose(theFile, memmgr);
00579 }
00580 
00581 void
00582 XMLPlatformUtils::resetFile(FileHandle theFile
00583                             , MemoryManager* const memmgr)
00584 {
00585     if (!fgFileMgr)
00586                 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
00587 
00588         fgFileMgr->fileReset(theFile, memmgr);
00589 }
00590 
00591 
00592 XMLFilePos
00593 XMLPlatformUtils::curFilePos(FileHandle theFile
00594                              , MemoryManager* const memmgr)
00595 {
00596     if (!fgFileMgr)
00597                 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
00598 
00599         return fgFileMgr->curPos(theFile, memmgr);
00600 }
00601 
00602 XMLFilePos
00603 XMLPlatformUtils::fileSize(FileHandle theFile
00604                            , MemoryManager* const memmgr)
00605 {
00606     if (!fgFileMgr)
00607                 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
00608 
00609         return fgFileMgr->fileSize(theFile, memmgr);
00610 }
00611 
00612 
00613 XMLSize_t
00614 XMLPlatformUtils::readFileBuffer(   FileHandle      theFile
00615                                  ,  const XMLSize_t               toRead
00616                                  ,        XMLByte* const  toFill
00617                                  ,  MemoryManager* const  memmgr)
00618 {
00619     if (!fgFileMgr)
00620                 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
00621 
00622     return fgFileMgr->fileRead(theFile, toRead, toFill, memmgr);
00623 }
00624 
00625 
00626 void
00627 XMLPlatformUtils::writeBufferToFile(   const   FileHandle   theFile
00628                                     ,  XMLSize_t            toWrite
00629                                     ,  const XMLByte* const toFlush
00630                                     ,  MemoryManager* const memmgr)
00631 {
00632     if (!fgFileMgr)
00633                 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
00634 
00635         fgFileMgr->fileWrite(theFile, toWrite, toFlush, memmgr);
00636 }
00637 
00638 
00639 // ---------------------------------------------------------------------------
00640 //  XMLPlatformUtils: File system methods
00641 // ---------------------------------------------------------------------------
00642 XMLCh* XMLPlatformUtils::getFullPath(const XMLCh* const srcPath,
00643                                      MemoryManager* const memmgr)
00644 {
00645     if (!fgFileMgr)
00646                 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
00647 
00648         return fgFileMgr->getFullPath(srcPath, memmgr);
00649 }
00650 
00651 
00652 XMLCh* XMLPlatformUtils::getCurrentDirectory(MemoryManager* const memmgr)
00653 {
00654     if (!fgFileMgr)
00655                 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
00656 
00657     return fgFileMgr->getCurrentDirectory(memmgr);
00658 }
00659 
00660 
00661 bool XMLPlatformUtils::isRelative(const XMLCh* const toCheck
00662                                   , MemoryManager* const memmgr)
00663 {
00664     if (!fgFileMgr)
00665                 ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, memmgr);
00666 
00667     return fgFileMgr->isRelative(toCheck, memmgr);
00668 }
00669 
00670 
00671 inline bool
00672 XMLPlatformUtils::isAnySlash(XMLCh c)
00673 {
00674         // As far as we know, all supported Xerces
00675         // platforms use at least a forward slash
00676         // as a path delimiter. So we always check for
00677         // that.
00678         //
00679         // If XERCES_PATH_DELIMITER_BACKSLASH evaluates to true,
00680         // we also consider that as a slash.
00681         //
00682         // XERCES_PATH_DELIMITER_BACKSLASH may be set in config.h
00683         // by configure, or elsewhere by platform-specific
00684         // code.
00685     return      (
00686                         false
00687                  || chForwardSlash == c
00688         #if XERCES_PATH_DELIMITER_BACKSLASH
00689                  || chBackSlash == c
00690         #endif
00691                 );
00692 }
00693 
00694 
00695 // ---------------------------------------------------------------------------
00696 //  XMLPlatformUtils: Timing Methods
00697 // ---------------------------------------------------------------------------
00698 unsigned long XMLPlatformUtils::getCurrentMillis()
00699 {
00700         unsigned long ms = 0;
00701 
00702         // *** TODO: additional platform support?
00703         #if HAVE_GETTIMEOFDAY
00704                 struct timeval aTime;
00705                 gettimeofday(&aTime, NULL);
00706                 ms = (unsigned long) (aTime.tv_sec * 1000 + aTime.tv_usec / 1000);
00707         #elif HAVE_FTIME
00708                 timeb aTime;
00709                 ftime(&aTime);
00710                 ms = (unsigned long)(aTime.time*1000 + aTime.millitm);
00711         #else
00712                 // Make this a warning instead?
00713                 #error No timing support is configured for this platform. You must configure it.
00714         #endif
00715 
00716         return ms;
00717 }
00718 
00719 
00720 // -----------------------------------------------------------------------
00721 //  Mutex methods
00722 // -----------------------------------------------------------------------
00723 XMLMutexMgr* XMLPlatformUtils::makeMutexMgr(MemoryManager* const memmgr)
00724 {
00725         XMLMutexMgr* mgr = NULL;
00726 
00727         #if XERCES_USE_MUTEXMGR_NOTHREAD
00728                 mgr = new (memmgr) NoThreadMutexMgr;
00729         #elif XERCES_USE_MUTEXMGR_POSIX
00730                 mgr = new (memmgr) PosixMutexMgr;
00731         #elif XERCES_USE_MUTEXMGR_WINDOWS
00732                 mgr = new (memmgr) WindowsMutexMgr;
00733         #else
00734                 #error No Mutex Manager configured for platform! You must configure it.
00735         #endif
00736 
00737         return mgr;
00738 }
00739 
00740 
00741 XMLMutexHandle XMLPlatformUtils::makeMutex(MemoryManager* const memmgr)
00742 {
00743     if (!fgMutexMgr)
00744                 XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr);
00745 
00746         return fgMutexMgr->create(memmgr);
00747 }
00748 
00749 
00750 void XMLPlatformUtils::closeMutex(XMLMutexHandle const mtx, MemoryManager* const memmgr)
00751 {
00752     if (!fgMutexMgr)
00753                 XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr);
00754 
00755         fgMutexMgr->destroy(mtx, memmgr);
00756 }
00757 
00758 
00759 void XMLPlatformUtils::lockMutex(XMLMutexHandle const mtx)
00760 {
00761     if (!fgMutexMgr)
00762                 XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr);
00763 
00764         fgMutexMgr->lock(mtx);
00765 }
00766 
00767 
00768 void XMLPlatformUtils::unlockMutex(XMLMutexHandle const mtx)
00769 {
00770     if (!fgMutexMgr)
00771                 XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr);
00772 
00773         fgMutexMgr->unlock(mtx);
00774 }
00775 
00776 // ---------------------------------------------------------------------------
00777 //  XMLPlatformUtils: Msg support methods
00778 // ---------------------------------------------------------------------------
00779 XMLMsgLoader* XMLPlatformUtils::loadMsgSet(const XMLCh* const msgDomain)
00780 {
00781     //
00782     //  Ask the platform support to load up the correct type of message
00783     //  loader for the indicated message set. We don't check here whether it
00784     //  works or not. That's their decision.
00785     //
00786     return loadAMsgSet(msgDomain);
00787 }
00788 
00789 // ---------------------------------------------------------------------------
00790 //  XMLPlatformUtils: NEL Character Handling
00791 // ---------------------------------------------------------------------------
00792 void XMLPlatformUtils::recognizeNEL(bool state, MemoryManager* const manager) {
00793 
00794     //Make sure initialize has been called
00795     if (gInitFlag == 0) {
00796         return;
00797     }
00798 
00799     if (state) {
00800 
00801         if (!XMLChar1_0::isNELRecognized()) {
00802             XMLChar1_0::enableNELWS();
00803         }
00804     }
00805     else {
00806 
00807         if (XMLChar1_0::isNELRecognized()) {
00808             ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::NEL_RepeatedCalls, manager);
00809         }
00810     }
00811 }
00812 
00813 
00814 bool XMLPlatformUtils::isNELRecognized() {
00815 
00816     return XMLChar1_0::isNELRecognized();
00817 }
00818 
00819 // ---------------------------------------------------------------------------
00820 //  XMLPlatformUtils: IANA Encoding checking setting
00821 // ---------------------------------------------------------------------------
00822 void XMLPlatformUtils::strictIANAEncoding(const bool state) {
00823 
00824     //Make sure initialize has been called
00825     if (gInitFlag == 0) {
00826         return;
00827     }
00828 
00829     fgTransService->strictIANAEncoding(state);
00830 }
00831 
00832 
00833 bool XMLPlatformUtils::isStrictIANAEncoding() {
00834 
00835     if (gInitFlag)
00836         return fgTransService->isStrictIANAEncoding();
00837 
00838     return false;
00839 }
00840 
00841 /***
00842  *
00843  *  Previously, each <OS>PlatformUtils.cpp has its onw copy of the
00844  *  method weavePaths(), and almost of them implemented the same logic,
00845  *  with few platform specific difference, and unfortunately that
00846  *  implementation was wrong.
00847  *
00848  *  The only platform specific issue is slash character.
00849  *  On all platforms other than Windows, chForwardSlash and chBackSlash
00850  *  are considered slash, while on Windows, two additional characters,
00851  *  chYenSign and chWonSign are slash as well.
00852  *
00853  *  The idea is to maintain a SINGLE copy of this method rather than
00854  *  each <OS>PlatformUtils.cpp has its own copy, we introduce a new
00855  *  method, XMLPlatformUtils::isAnySlash(), to replace the direct checking
00856  *  code ( if ( c == chForwardSlash || c == chBackSlash).
00857  *
00858  *  With this approach, we might have a performance hit since isAnySlash()
00859  *  is so frequently used in this implementation, so we intend to make it
00860  *  inline. Then we face a complier issue.
00861  *
00862  *  There are two compilation units involved, one is PlatformUtils.cpp and
00863  *  the other <OS>PlatformUtils.cpp. When PlatformUtils.cp get compiled,
00864  *  the weavePath(), remove**Slash() have dependency upon isAnySlash() which
00865  *  is in <OS>PlatformUtils.cpp (and what is worse, it is inlined), so we have
00866  *  undefined/unresolved symbol: isAnySlash() on AIX/xlc_r, Solaris/cc and
00867  *  Linux/gcc, while MSVC and HP/aCC are fine with this.
00868  *
00869  *  That means we can not place these new methods in PlatformUtils.cpp with
00870  *  inlined XMLPlatformUtils::isAnySlash() in <OS>PlatformUtils.cpp.
00871  *
00872  *  The solution to this is <os>PlatformUtils.cpp will include this file so that
00873  *  we have only one copy of these methods while get compiled in <os>PlatformUtils
00874  *  inlined isAnySlash().
00875  *
00876  ***/
00877 XMLCh* XMLPlatformUtils::weavePaths(const XMLCh* const    basePath
00878                                   , const XMLCh* const    relativePath
00879                                   , MemoryManager* const  manager)
00880 
00881 {
00882     // Create a buffer as large as both parts and empty it
00883     XMLCh* tmpBuf = (XMLCh*) manager->allocate
00884     (
00885         (XMLString::stringLen(basePath)
00886          + XMLString::stringLen(relativePath) + 2) * sizeof(XMLCh)
00887     );//new XMLCh[XMLString::stringLen(basePath) + XMLString::stringLen(relativePath) + 2];
00888     *tmpBuf = 0;
00889 
00890     //
00891     //  If we have no base path, then just take the relative path as is.
00892     //
00893     if ((!basePath) || (!*basePath))
00894     {
00895         XMLString::copyString(tmpBuf, relativePath);
00896         return tmpBuf;
00897     }
00898 
00899     //
00900     // Remove anything after the last slash
00901     //
00902     const XMLCh* basePtr = basePath + (XMLString::stringLen(basePath) - 1);
00903     while ((basePtr >= basePath)  &&  ((isAnySlash(*basePtr) == false)))
00904     {
00905         basePtr--;
00906     }
00907 
00908     // There is no relevant base path, so just take the relative part
00909     if (basePtr < basePath)
00910     {
00911         XMLString::copyString(tmpBuf, relativePath);
00912         return tmpBuf;
00913     }
00914 
00915     //
00916     // 1. concatenate the base and relative
00917     // 2. remove all occurences of "/./"
00918     // 3. remove all occurences of segment/../ where segment is not ../
00919         //
00920 
00921     XMLString::subString(tmpBuf, basePath, 0, (basePtr - basePath + 1), manager);
00922     tmpBuf[basePtr - basePath + 1] = 0;
00923     XMLString::catString(tmpBuf, relativePath);
00924 
00925     removeDotSlash(tmpBuf, manager);
00926 
00927     removeDotDotSlash(tmpBuf, manager);
00928 
00929     return tmpBuf;
00930 
00931 }
00932 
00933 //
00934 // Remove all occurences of './' when it is part of '/./'
00935 //
00936 // Since it could be '.\' or other combination on windows ( eg, '.'+chYanSign)
00937 // we can't make use of patterMatch().
00938 //
00939 //
00940 void XMLPlatformUtils::removeDotSlash(XMLCh* const path
00941                                       , MemoryManager* const manager)
00942 {
00943     if ((!path) || (!*path))
00944         return;
00945 
00946     XMLCh* srcPtr = XMLString::replicate(path, manager);
00947     XMLSize_t srcLen = XMLString::stringLen(srcPtr);
00948     ArrayJanitor<XMLCh>   janName(srcPtr, manager);
00949     XMLCh* tarPtr = path;
00950 
00951     while (*srcPtr)
00952     {
00953         if ( 3 <= srcLen )
00954         {
00955             if ( (isAnySlash(*srcPtr))     &&
00956                 (chPeriod == *(srcPtr+1)) &&
00957                 (isAnySlash(*(srcPtr+2)))  )
00958             {
00959                 // "\.\x" seen
00960                 // skip the first two, and start from the 3rd,
00961                 // since "\x" could be another "\."
00962                 srcPtr+=2;
00963                 srcLen-=2;
00964             }
00965             else
00966             {
00967                 *tarPtr++ = *srcPtr++;  // eat the current char
00968                 srcLen--;
00969             }
00970         }
00971         else if ( 1 == srcLen )
00972         {
00973             *tarPtr++ = *srcPtr++;
00974         }
00975         else if ( 2 == srcLen)
00976         {
00977             *tarPtr++ = *srcPtr++;
00978             *tarPtr++ = *srcPtr++;
00979         }
00980 
00981     }
00982 
00983     *tarPtr = 0;
00984 
00985     return;
00986 }
00987 
00988 //
00989 // Remove all occurences of '/segment/../' when segment is not '..'
00990 //
00991 // Cases with extra /../ is left to the underlying file system.
00992 //
00993 void XMLPlatformUtils::removeDotDotSlash(XMLCh* const path
00994                                          , MemoryManager* const manager)
00995 {
00996     XMLSize_t pathLen = XMLString::stringLen(path);
00997     XMLCh* tmp1 = (XMLCh*) manager->allocate
00998     (
00999         (pathLen+1) * sizeof(XMLCh)
01000     );//new XMLCh [pathLen+1];
01001     ArrayJanitor<XMLCh>   tmp1Name(tmp1, manager);
01002 
01003     XMLCh* tmp2 = (XMLCh*) manager->allocate
01004     (
01005         (pathLen+1) * sizeof(XMLCh)
01006     );//new XMLCh [pathLen+1];
01007     ArrayJanitor<XMLCh>   tmp2Name(tmp2, manager);
01008 
01009     // remove all "<segment>/../" where "<segment>" is a complete
01010     // path segment not equal to ".."
01011     int index = -1;
01012     int segIndex = -1;
01013     int offset = 1;
01014 
01015     while ((index = searchSlashDotDotSlash(&(path[offset]))) != -1)
01016     {
01017         // Undo offset
01018         index += offset;
01019 
01020         // Find start of <segment> within substring ending at found point.
01021         XMLString::subString(tmp1, path, 0, index-1, manager);
01022         segIndex = index - 1;
01023         while ((segIndex >= 0) && (!isAnySlash(tmp1[segIndex])))
01024         {
01025             segIndex--;
01026         }
01027 
01028         // Ensure <segment> exists and != ".."
01029         if (segIndex >= 0                 &&
01030             (path[segIndex+1] != chPeriod ||
01031              path[segIndex+2] != chPeriod ||
01032              segIndex + 3 != index))
01033         {
01034 
01035             XMLString::subString(tmp1, path, 0, segIndex, manager);
01036             XMLString::subString(tmp2, path, index+3, XMLString::stringLen(path), manager);
01037 
01038             path[0] = 0;
01039             XMLString::catString(path, tmp1);
01040             XMLString::catString(path, tmp2);
01041 
01042             offset = (segIndex == 0 ? 1 : segIndex);
01043         }
01044         else
01045         {
01046             offset += 4;
01047         }
01048 
01049     }// while
01050 
01051 }
01052 
01053 int XMLPlatformUtils::searchSlashDotDotSlash(XMLCh* const srcPath)
01054 {
01055     if ((!srcPath) || (!*srcPath))
01056         return -1;
01057 
01058     XMLCh* srcPtr = srcPath;
01059     XMLSize_t srcLen = XMLString::stringLen(srcPath);
01060     int    retVal = -1;
01061 
01062     while (*srcPtr)
01063     {
01064         if ( 4 <= srcLen )
01065         {
01066             if ( (isAnySlash(*srcPtr))     &&
01067                  (chPeriod == *(srcPtr+1)) &&
01068                  (chPeriod == *(srcPtr+2)) &&
01069                  (isAnySlash(*(srcPtr+3)))  )
01070             {
01071                 retVal = (int)(srcPtr - srcPath);
01072                 break;
01073             }
01074             else
01075             {
01076                 srcPtr++;
01077                 srcLen--;
01078             }
01079         }
01080         else
01081         {
01082             break;
01083         }
01084 
01085     } // while
01086 
01087     return retVal;
01088 
01089 }
01090 
01091 
01092 XERCES_CPP_NAMESPACE_END