Win32PlatformUtils.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:28k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: Win32PlatformUtils.cpp,v 1.20 2003/05/15 18:37:49 knoaman Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <xercesc/util/Janitor.hpp>
  63. #include <xercesc/util/PlatformUtils.hpp>
  64. #include <xercesc/util/RuntimeException.hpp>
  65. #include <xercesc/util/XMLExceptMsgs.hpp>
  66. #include <xercesc/util/XMLString.hpp>
  67. #include <xercesc/util/XMLUniDefs.hpp>
  68. #include <xercesc/util/XMLUni.hpp>
  69. #include <xercesc/util/PanicHandler.hpp>
  70. #include <windows.h>
  71. #include <stdio.h>
  72. #include <stdlib.h>
  73. #ifdef _DEBUG
  74.  #ifdef _MSC_VER
  75.     #include <crtdbg.h>
  76.  #else
  77.     #include <assert.h>
  78.  #endif
  79. #endif
  80. //
  81. //  These control which transcoding service is used by the Win32 version.
  82. //  They allow this to be controlled from the build process by just defining
  83. //  one of these values.
  84. //
  85. #if defined (XML_USE_ICU_TRANSCODER)
  86.     #include <xercesc/util/Transcoders/ICU/ICUTransService.hpp>
  87. #elif defined (XML_USE_WIN32_TRANSCODER)
  88.     #include <xercesc/util/Transcoders/Win32/Win32TransService.hpp>
  89. #elif defined (XML_USE_CYGWIN_TRANSCODER)
  90.     #include <xercesc/util/Transcoders/Cygwin/CygwinTransService.hpp>
  91. #else
  92.     #error A transcoding service must be chosen
  93. #endif
  94. //
  95. //  These control which message loading service is used by the Win32 version.
  96. //  They allow this to be controlled from the build process by just defining
  97. //  one of these values.
  98. //
  99. #if defined (XML_USE_INMEM_MESSAGELOADER)
  100.     #include <xercesc/util/MsgLoaders/InMemory/InMemMsgLoader.hpp>
  101. #elif defined (XML_USE_WIN32_MSGLOADER)
  102.     #include <xercesc/util/MsgLoaders/Win32/Win32MsgLoader.hpp>
  103. #elif defined(XML_USE_ICU_MESSAGELOADER)
  104.     #include <xercesc/util/MsgLoaders/ICU/ICUMsgLoader.hpp>
  105. #else
  106.     #error A message loading service must be chosen
  107. #endif
  108. //
  109. //  These control which network access service is used by the Win32 version.
  110. //  They allow this to be controlled from the build process by just defining
  111. //  one of these values.
  112. //
  113. #if defined (XML_USE_NETACCESSOR_LIBWWW)
  114.     #include <xercesc/util/NetAccessors/libWWW/LibWWWNetAccessor.hpp>
  115. #elif defined (XML_USE_NETACCESSOR_WINSOCK)
  116.     #include <xercesc/util/NetAccessors/WinSock/WinSockNetAccessor.hpp>
  117. #endif
  118. XERCES_CPP_NAMESPACE_BEGIN
  119. // ---------------------------------------------------------------------------
  120. //  Local data
  121. //
  122. //  gOnNT
  123. //      We figure out during init if we are on NT or not. If we are, then
  124. //      we can avoid a lot of transcoding in our system services stuff.
  125. // ---------------------------------------------------------------------------
  126. static bool     gOnNT;
  127. // ---------------------------------------------------------------------------
  128. //  XMLPlatformUtils: The panic method
  129. // ---------------------------------------------------------------------------
  130. void XMLPlatformUtils::panic(const PanicHandler::PanicReasons reason)
  131. {
  132.     fgUserPanicHandler? fgUserPanicHandler->panic(reason) : fgDefaultPanicHandler->panic(reason);
  133. }
  134. // ---------------------------------------------------------------------------
  135. //  XMLPlatformUtils: File Methods
  136. // ---------------------------------------------------------------------------
  137. //
  138. //  Functions to look for Unicode forward and back slashes.
  139. //  This operation is complicated by the fact that some Japanese and Korean
  140. //    encodings use the same encoding for both '' and their currency symbol
  141. //    (Yen or Won).  In these encodings, which is meant is context dependent.
  142. //    Unicode converters choose the currency symbols.  But in the context
  143. //    of a Windows file name, '' is generally what was intended.
  144. //
  145. //    So we make a leap of faith, and assume that if we get a Yen or Won
  146. //    here, in the context of a file name, that it originated in one of
  147. //    these encodings, and is really supposed to be a ''.
  148. //
  149. static bool isBackSlash(XMLCh c) {
  150.     return c == chBackSlash ||
  151.            c == chYenSign   ||
  152.            c == chWonSign;
  153. }
  154. unsigned int XMLPlatformUtils::curFilePos(FileHandle theFile)
  155. {
  156.     // Get the current position
  157.     const unsigned int curPos = ::SetFilePointer(theFile, 0, 0, FILE_CURRENT);
  158.     if (curPos == 0xFFFFFFFF)
  159.         ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos);
  160.     return curPos;
  161. }
  162. void XMLPlatformUtils::closeFile(FileHandle theFile)
  163. {
  164.     if (!::CloseHandle(theFile))
  165.         ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile);
  166. }
  167. unsigned int XMLPlatformUtils::fileSize(FileHandle theFile)
  168. {
  169.     // Get the current position
  170.     const unsigned int curPos = ::SetFilePointer(theFile, 0, 0, FILE_CURRENT);
  171.     if (curPos == 0xFFFFFFFF)
  172.         ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos);
  173.     // Seek to the end and save that value for return
  174.     const unsigned int retVal = ::SetFilePointer(theFile, 0, 0, FILE_END);
  175.     if (retVal == 0xFFFFFFFF)
  176.         ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToEnd);
  177.     // And put the pointer back
  178.     if (::SetFilePointer(theFile, curPos, 0, FILE_BEGIN) == 0xFFFFFFFF)
  179.         ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToPos);
  180.     return retVal;
  181. }
  182. FileHandle XMLPlatformUtils::openFile(const char* const fileName)
  183. {
  184.     FileHandle retVal = ::CreateFileA
  185.     (
  186.         fileName
  187.         , GENERIC_READ
  188.         , FILE_SHARE_READ
  189.         , 0
  190.         , OPEN_EXISTING
  191.         , FILE_FLAG_SEQUENTIAL_SCAN
  192.         , 0
  193.     );
  194.     if (retVal == INVALID_HANDLE_VALUE)
  195.         return 0;
  196.     return retVal;
  197. }
  198. FileHandle XMLPlatformUtils::openFile(const XMLCh* const fileName)
  199. {
  200.     // Watch for obvious wierdness
  201.     if (!fileName)
  202.         return 0;
  203.     //
  204.     //  We have to play a little trick here. If its /x:.....
  205.     //  style fully qualified path, we have to toss the leading /
  206.     //  character.
  207.     //
  208.     const XMLCh* nameToOpen = fileName;
  209.     if (*fileName == chForwardSlash)
  210.     {
  211.         if (XMLString::stringLen(fileName) > 3)
  212.         {
  213.             if (*(fileName + 2) == chColon)
  214.             {
  215.                 const XMLCh chDrive = *(fileName + 1);
  216.                 if (((chDrive >= chLatin_A) && (chDrive <= chLatin_Z))
  217.                 ||  ((chDrive >= chLatin_a) && (chDrive <= chLatin_z)))
  218.                 {
  219.                     nameToOpen = fileName + 1;
  220.                 }
  221.             }
  222.             // Similarly for UNC paths
  223.             if ( *(fileName + 1) == *(fileName + 2) &&
  224.                  (*(fileName + 1) == chForwardSlash ||
  225.                   *(fileName + 1) == chBackSlash) )
  226.             {
  227.                 nameToOpen = fileName + 1;
  228.             }
  229.         }
  230.     }
  231.     //  Ok, this might look stupid but its a semi-expedient way to deal
  232.     //  with a thorny problem. Shift-JIS and some other Asian encodings
  233.     //  are fundamentally broken and map both the backslash and the Yen
  234.     //  sign to the same code point. Transcoders have to pick one or the
  235.     //  other to map '' to Unicode and tend to choose the Yen sign.
  236.     //
  237.     //  Unicode Yen or Won signs as directory separators will fail.
  238.     //
  239.     //  So, we will check this path name for Yen or won signs and, if they are
  240.     //  there, we'll replace them with slashes.
  241.     //
  242.     //  A further twist:  we replace Yen and Won with forward slashes rather
  243.     //   than back slashes.  Either form of slash will work as a directory
  244.     //   separator.  On Win 95 and 98, though, Unicode back-slashes may
  245.     //   fail to transode back to 8-bit 0x5C with some Unicode converters
  246.     //   to  some of the problematic code pages.  Forward slashes always
  247.     //   transcode correctly back to 8 bit char * form.
  248.     //
  249.     XMLCh *tmpUName = 0;
  250.     const XMLCh* srcPtr = nameToOpen;
  251.     while (*srcPtr)
  252.     {
  253.         if (*srcPtr == chYenSign ||
  254.             *srcPtr == chWonSign)
  255.             break;
  256.         srcPtr++;
  257.     }
  258.     //
  259.     //  If we found a yen, then we have to create a temp file name. Else
  260.     //  go with the file name as is and save the overhead.
  261.     //
  262.     if (*srcPtr)
  263.     {
  264.         tmpUName = XMLString::replicate(nameToOpen, fgMemoryManager);
  265.         XMLCh* tmpPtr = tmpUName;
  266.         while (*tmpPtr)
  267.         {
  268.             if (*tmpPtr == chYenSign ||
  269.                 *tmpPtr == chWonSign)
  270.                 *tmpPtr = chForwardSlash;
  271.             tmpPtr++;
  272.         }
  273.         nameToOpen = tmpUName;
  274.     }
  275.     FileHandle retVal = 0;
  276.     if (gOnNT)
  277.     {
  278.         retVal = ::CreateFileW
  279.             (
  280.             (LPCWSTR) nameToOpen
  281.             , GENERIC_READ
  282.             , FILE_SHARE_READ
  283.             , 0
  284.             , OPEN_EXISTING
  285.             , FILE_FLAG_SEQUENTIAL_SCAN
  286.             , 0
  287.             );
  288.     }
  289.     else
  290.     {
  291.         //
  292.         //  We are Win 95 / 98.  Take the Unicode file name back to (char *)
  293.         //    so that we can open it.
  294.         //
  295.         char* tmpName = XMLString::transcode(nameToOpen, fgMemoryManager);
  296.         retVal = ::CreateFileA
  297.             (
  298.             tmpName
  299.             , GENERIC_READ
  300.             , FILE_SHARE_READ
  301.             , 0
  302.             , OPEN_EXISTING
  303.             , FILE_FLAG_SEQUENTIAL_SCAN
  304.             , 0
  305.             );
  306.         fgMemoryManager->deallocate(tmpName);//delete [] tmpName;
  307.     }
  308.     if (tmpUName)
  309.         fgMemoryManager->deallocate(tmpUName);//delete [] tmpUName;
  310.     if (retVal == INVALID_HANDLE_VALUE)
  311.         return 0;
  312.     return retVal;
  313. }
  314. FileHandle XMLPlatformUtils::openFileToWrite(const char* const fileName)
  315. {
  316.     FileHandle retVal = ::CreateFileA
  317.     (
  318.         fileName
  319.         , GENERIC_WRITE
  320.         , 0              // no shared write
  321.         , 0
  322.         , CREATE_ALWAYS
  323.         , FILE_ATTRIBUTE_NORMAL
  324.         , 0
  325.     );
  326.     if (retVal == INVALID_HANDLE_VALUE)
  327.         return 0;
  328.     return retVal;
  329. }
  330. FileHandle XMLPlatformUtils::openFileToWrite(const XMLCh* const fileName)
  331. {
  332.     // Watch for obvious wierdness
  333.     if (!fileName)
  334.         return 0;
  335.     //  Ok, this might look stupid but its a semi-expedient way to deal
  336.     //  with a thorny problem. Shift-JIS and some other Asian encodings
  337.     //  are fundamentally broken and map both the backslash and the Yen
  338.     //  sign to the same code point. Transcoders have to pick one or the
  339.     //  other to map '' to Unicode and tend to choose the Yen sign.
  340.     //
  341.     //  Unicode Yen or Won signs as directory separators will fail.
  342.     //
  343.     //  So, we will check this path name for Yen or won signs and, if they are
  344.     //  there, we'll replace them with slashes.
  345.     //
  346.     //  A further twist:  we replace Yen and Won with forward slashes rather
  347.     //   than back slashes.  Either form of slash will work as a directory
  348.     //   separator.  On Win 95 and 98, though, Unicode back-slashes may
  349.     //   fail to transode back to 8-bit 0x5C with some Unicode converters
  350.     //   to  some of the problematic code pages.  Forward slashes always
  351.     //   transcode correctly back to 8 bit char * form.
  352.     //
  353.     XMLCh *tmpUName = 0;
  354.     const XMLCh *nameToOpen = fileName;
  355.     const XMLCh* srcPtr = fileName;
  356.     while (*srcPtr)
  357.     {
  358.         if (*srcPtr == chYenSign ||
  359.             *srcPtr == chWonSign)
  360.             break;
  361.         srcPtr++;
  362.     }
  363.     //
  364.     //  If we found a yen, then we have to create a temp file name. Else
  365.     //  go with the file name as is and save the overhead.
  366.     //
  367.     if (*srcPtr)
  368.     {
  369.         tmpUName = XMLString::replicate(fileName, fgMemoryManager);
  370.         XMLCh* tmpPtr = tmpUName;
  371.         while (*tmpPtr)
  372.         {
  373.             if (*tmpPtr == chYenSign ||
  374.                 *tmpPtr == chWonSign)
  375.                 *tmpPtr = chForwardSlash;
  376.             tmpPtr++;
  377.         }
  378.         nameToOpen = tmpUName;
  379.     }
  380.     FileHandle retVal = 0;
  381.     if (gOnNT)
  382.     {
  383.         retVal = ::CreateFileW
  384.             (
  385.             (LPCWSTR) nameToOpen
  386.             , GENERIC_WRITE
  387.             , 0              // no shared write
  388.             , 0
  389.             , CREATE_ALWAYS
  390.             , FILE_ATTRIBUTE_NORMAL
  391.             , 0
  392.             );
  393.     }
  394.     else
  395.     {
  396.         //
  397.         //  We are Win 95 / 98.  Take the Unicode file name back to (char *)
  398.         //    so that we can open it.
  399.         //
  400.         char* tmpName = XMLString::transcode(nameToOpen, fgMemoryManager);
  401.         retVal = ::CreateFileA
  402.             (
  403.             tmpName
  404.             , GENERIC_WRITE
  405.             , 0              // no shared write
  406.             , 0
  407.             , CREATE_ALWAYS
  408.             , FILE_ATTRIBUTE_NORMAL
  409.             , 0
  410.             );
  411.         fgMemoryManager->deallocate(tmpName);//delete [] tmpName;
  412.     }
  413.     if (tmpUName)
  414.         fgMemoryManager->deallocate(tmpUName);//delete [] tmpUName;
  415.     if (retVal == INVALID_HANDLE_VALUE)
  416.         return 0;
  417.     return retVal;
  418. }
  419. FileHandle XMLPlatformUtils::openStdInHandle()
  420. {
  421.     //
  422.     //  Get the standard input handle. Duplicate it and return that copy
  423.     //  since the outside world cannot tell the difference and will shut
  424.     //  down this handle when its done with it. If we gave out the orignal,
  425.     //  shutting it would prevent any further output.
  426.     //
  427.     HANDLE stdInOrg = ::GetStdHandle(STD_INPUT_HANDLE);
  428.     if (stdInOrg == INVALID_HANDLE_VALUE) {
  429.         XMLCh stdinStr[] = {chLatin_s, chLatin_t, chLatin_d, chLatin_i, chLatin_n, chNull};
  430.         ThrowXML1(XMLPlatformUtilsException, XMLExcepts::File_CouldNotOpenFile, stdinStr);
  431.     }
  432.     HANDLE retHandle;
  433.     if (!::DuplicateHandle
  434.     (
  435.         ::GetCurrentProcess()
  436.         , stdInOrg
  437.         , ::GetCurrentProcess()
  438.         , &retHandle
  439.         , 0
  440.         , FALSE
  441.         , DUPLICATE_SAME_ACCESS))
  442.     {
  443.         ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotDupHandle);
  444.     }
  445.     return retHandle;
  446. }
  447. unsigned int
  448. XMLPlatformUtils::readFileBuffer(       FileHandle      theFile
  449.                                 , const unsigned int    toRead
  450.                                 ,       XMLByte* const  toFill)
  451. {
  452.     unsigned long bytesRead = 0;
  453.     if (!::ReadFile(theFile, toFill, toRead, &bytesRead, 0))
  454.     {
  455.         //
  456.         //  Check specially for a broken pipe error. If we get this, it just
  457.         //  means no more data from the pipe, so return zero.
  458.         //
  459.         if (::GetLastError() != ERROR_BROKEN_PIPE)
  460.             ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile);
  461.     }
  462.     return (unsigned int)bytesRead;
  463. }
  464. void
  465. XMLPlatformUtils::writeBufferToFile( FileHandle     const  theFile
  466.                                    , long                  toWrite
  467.                                    , const XMLByte* const  toFlush)
  468. {
  469.     if (!theFile        ||
  470.         (toWrite <= 0 ) ||
  471.         !toFlush         )
  472.         return;
  473.     const XMLByte* tmpFlush = (const XMLByte*) toFlush;
  474.     unsigned long  bytesWritten = 0;
  475.     while (true)
  476.     {
  477.         if (!::WriteFile(theFile, tmpFlush, toWrite, &bytesWritten, 0))
  478.             ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotWriteToFile);
  479.         if (bytesWritten < (unsigned long) toWrite) //incomplete write
  480.         {
  481.             tmpFlush+=bytesWritten;
  482.             toWrite-=bytesWritten;
  483.             bytesWritten=0;
  484.         }
  485.         else
  486.             return;
  487.     }
  488.     return;
  489. }
  490. void XMLPlatformUtils::resetFile(FileHandle theFile)
  491. {
  492.     // Seek to the start of the file
  493.     if (::SetFilePointer(theFile, 0, 0, FILE_BEGIN) == 0xFFFFFFFF)
  494.         ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotResetFile);
  495. }
  496. // ---------------------------------------------------------------------------
  497. //  XMLPlatformUtils: File system methods
  498. // ---------------------------------------------------------------------------
  499. XMLCh* XMLPlatformUtils::getFullPath(const XMLCh* const srcPath,
  500.                                      MemoryManager* const manager)
  501. {
  502.     //
  503.     //  If we are on NT, then use wide character APIs, else use ASCII APIs.
  504.     //  We have to do it manually since we are only built in ASCII mode from
  505.     //  the standpoint of the APIs.
  506.     //
  507.     if (gOnNT)
  508.     {
  509.         // Use a local buffer that is big enough for the largest legal path
  510.         const unsigned int bufSize = 1024;
  511.         XMLCh tmpPath[bufSize + 1];
  512.         XMLCh* namePart = 0;
  513.         if (!::GetFullPathNameW((LPCWSTR)srcPath, bufSize, (LPWSTR)tmpPath, (LPWSTR*)&namePart))
  514.             return 0;
  515.         // Return a copy of the path
  516.         return XMLString::replicate(tmpPath, manager);
  517.     }
  518.      else
  519.     {
  520.         // Transcode the incoming string
  521.         char* tmpSrcPath = XMLString::transcode(srcPath, fgMemoryManager);
  522.         ArrayJanitor<char> janSrcPath(tmpSrcPath, fgMemoryManager);
  523.         // Use a local buffer that is big enough for the largest legal path
  524.         const unsigned int bufSize = 511;
  525.         char tmpPath[511 + 1];
  526.         char* namePart = 0;
  527.         if (!::GetFullPathNameA(tmpSrcPath, bufSize, tmpPath, &namePart))
  528.             return 0;
  529.         // Return a transcoded copy of the path
  530.         return XMLString::transcode(tmpPath, manager);
  531.     }
  532. }
  533. bool XMLPlatformUtils::isRelative(const XMLCh* const toCheck)
  534. {
  535.     // Check for pathological case of empty path
  536.     if (!toCheck[0])
  537.         return false;
  538.     //
  539.     //  If its starts with a drive, then it cannot be relative. Note that
  540.     //  we checked the drive not being empty above, so worst case its one
  541.     //  char long and the check of the 1st char will fail because its really
  542.     //  a null character.
  543.     //
  544.     if (toCheck[1] == chColon)
  545.     {
  546.         if (((toCheck[0] >= chLatin_A) && (toCheck[0] <= chLatin_Z))
  547.         ||  ((toCheck[0] >= chLatin_a) && (toCheck[0] <= chLatin_z)))
  548.         {
  549.             return false;
  550.         }
  551.     }
  552.     //
  553.     //  If it starts with a double slash, then it cannot be relative since
  554.     //  it's a remote file.
  555.     //
  556.     if (isBackSlash(toCheck[0]) && isBackSlash(toCheck[1]))
  557.         return false;
  558.     // Else assume its a relative path
  559.     return true;
  560. }
  561. XMLCh* XMLPlatformUtils::getCurrentDirectory(MemoryManager* const manager)
  562. {
  563.     //
  564.     //  If we are on NT, then use wide character APIs, else use ASCII APIs.
  565.     //  We have to do it manually since we are only built in ASCII mode from
  566.     //  the standpoint of the APIs.
  567.     //
  568.     if (gOnNT)
  569.     {
  570.         // Use a local buffer that is big enough for the largest legal path
  571.         const unsigned int bufSize = 1024;
  572.         XMLCh tmpPath[bufSize + 1];
  573.         if (!::GetCurrentDirectoryW(bufSize, (LPWSTR)tmpPath))
  574.             return 0;
  575.         // Return a copy of the path
  576.         return XMLString::replicate(tmpPath, manager);
  577.     }
  578.      else
  579.     {
  580.         // Use a local buffer that is big enough for the largest legal path
  581.         const unsigned int bufSize = 511;
  582.         char tmpPath[511 + 1];
  583.         char* namePart = 0;
  584.         if (!::GetCurrentDirectoryA(bufSize, tmpPath))
  585.             return 0;
  586.         // Return a transcoded copy of the path
  587.         return XMLString::transcode(tmpPath, manager);
  588.     }
  589. }
  590. inline bool XMLPlatformUtils::isAnySlash(XMLCh c)
  591. {
  592.     return c == chBackSlash    ||
  593.            c == chForwardSlash ||
  594.            c == chYenSign      ||
  595.            c == chWonSign;
  596. }
  597. // ---------------------------------------------------------------------------
  598. //  XMLPlatformUtils: Timing Methods
  599. // ---------------------------------------------------------------------------
  600. unsigned long XMLPlatformUtils::getCurrentMillis()
  601. {
  602.     return (unsigned long)::GetTickCount();
  603. }
  604. // ---------------------------------------------------------------------------
  605. //  Mutex methods
  606. // ---------------------------------------------------------------------------
  607. void XMLPlatformUtils::closeMutex(void* const mtxHandle)
  608. {
  609.     ::DeleteCriticalSection((LPCRITICAL_SECTION)mtxHandle);
  610.     delete (CRITICAL_SECTION*)mtxHandle;
  611. }
  612. void XMLPlatformUtils::lockMutex(void* const mtxHandle)
  613. {
  614.     ::EnterCriticalSection((LPCRITICAL_SECTION)mtxHandle);
  615. }
  616. void* XMLPlatformUtils::makeMutex()
  617. {
  618.     CRITICAL_SECTION* newCS = new CRITICAL_SECTION;
  619.     InitializeCriticalSection(newCS);
  620.     return newCS;
  621. }
  622. void XMLPlatformUtils::unlockMutex(void* const mtxHandle)
  623. {
  624.     ::LeaveCriticalSection((LPCRITICAL_SECTION)mtxHandle);
  625. }
  626. // ---------------------------------------------------------------------------
  627. //  Miscellaneous synchronization methods
  628. // ---------------------------------------------------------------------------
  629. void*
  630. XMLPlatformUtils::compareAndSwap(       void**      toFill
  631.                                 , const void* const newValue
  632.                                 , const void* const toCompare)
  633. {
  634. #if defined WIN64
  635.     return ::InterlockedCompareExchangePointer(toFill, (void*)newValue, (void*)toCompare);
  636. #else
  637.     //
  638.     //  InterlockedCompareExchange is only supported on Windows 98,
  639.     //  Windows NT 4.0, and newer -- not on Windows 95...
  640.     //  If you are willing to give up Win95 support change this to #if 0
  641.     //  otherwise we are back to using assembler.
  642.     //  (But only if building with compilers that support inline assembler.)
  643.     //
  644.     #if (defined(_MSC_VER) || defined(__BCPLUSPLUS__)) && !defined(XERCES_NO_ASM)
  645.     void*   result;
  646.     __asm
  647.     {
  648.         mov             eax, toCompare;
  649.         mov             ebx, newValue;
  650.         mov             ecx, toFill
  651.         lock cmpxchg    [ecx], ebx;
  652.         mov             result, eax;
  653.     }
  654.     return result;
  655.     #else
  656.     //
  657.     //  Note we have to cast off the constness of some of these because
  658.     //  the system APIs are not C++ aware in all cases.
  659.     //
  660.     return (void*) ::InterlockedCompareExchange((LPLONG)toFill, (LONG)newValue, (LONG)toCompare);
  661.     #endif
  662. #endif
  663. }
  664. // ---------------------------------------------------------------------------
  665. //  Atomic increment and decrement methods
  666. // ---------------------------------------------------------------------------
  667. int XMLPlatformUtils::atomicIncrement(int &location)
  668. {
  669.     return ::InterlockedIncrement(&(long &)location);
  670. }
  671. int XMLPlatformUtils::atomicDecrement(int &location)
  672. {
  673.     return ::InterlockedDecrement(&(long &)location);
  674. }
  675. // ---------------------------------------------------------------------------
  676. //  XMLPlatformUtils: Private Static Methods
  677. // ---------------------------------------------------------------------------
  678. //
  679. //  This method is called by the platform independent part of this class
  680. //  during initialization. We have to create the type of net accessor that
  681. //  we want to use. If none, then just return zero.
  682. //
  683. XMLNetAccessor* XMLPlatformUtils::makeNetAccessor()
  684. {
  685. #if defined (XML_USE_NETACCESSOR_LIBWWW)
  686.     return new LibWWWNetAccessor();
  687. #elif defined (XML_USE_NETACCESSOR_WINSOCK)
  688.     return new WinSockNetAccessor();
  689. #else
  690.     return 0;
  691. #endif
  692. }
  693. //
  694. //  This method is called by the platform independent part of this class
  695. //  when client code asks to have one of the supported message sets loaded.
  696. //  In our case, we use the ICU based message loader mechanism.
  697. //
  698. XMLMsgLoader* XMLPlatformUtils::loadAMsgSet(const XMLCh* const msgDomain)
  699. {
  700. #if defined (XML_USE_INMEM_MESSAGELOADER)
  701.     return new InMemMsgLoader(msgDomain);
  702. #elif defined (XML_USE_WIN32_MSGLOADER)
  703.     return new Win32MsgLoader(msgDomain);
  704. #elif defined (XML_USE_ICU_MESSAGELOADER)
  705.     return new ICUMsgLoader(msgDomain);
  706. #else
  707.     #error You must provide a message loader
  708. #endif
  709. }
  710. //
  711. //  This method is called very early in the bootstrapping process. This guy
  712. //  must create a transcoding service and return it. It cannot use any string
  713. //  methods, any transcoding services, throw any exceptions, etc... It just
  714. //  makes a transcoding service and returns it, or returns zero on failure.
  715. //
  716. XMLTransService* XMLPlatformUtils::makeTransService()
  717. {
  718.     //
  719.     //  Since we are going to use the ICU service, we have to tell it where
  720.     //  its converter files are. If the ICU_DATA environment variable is set,
  721.     //  then its been told. Otherwise, we tell it our default value relative
  722.     //  to our DLL.
  723.     //
  724. #if defined (XML_USE_ICU_TRANSCODER)
  725.     return new ICUTransService;
  726. #elif defined (XML_USE_WIN32_TRANSCODER)
  727.     return new Win32TransService;
  728. #elif defined (XML_USE_CYGWIN_TRANSCODER)
  729.     return new CygwinTransService;
  730. #else
  731.     #error You must provide a transcoding service implementation
  732. #endif
  733. }
  734. //
  735. //  This method handles the Win32 per-platform basic init functions. The
  736. //  primary jobs here are getting the path to our DLL and to get the
  737. //  stdout and stderr file handles setup.
  738. //
  739. void XMLPlatformUtils::platformInit()
  740. {
  741. #if 0 && defined(_DEBUG)
  742.     //  Enable this code for memeory leak testing
  743.    // Send all reports to STDOUT
  744.    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
  745.    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
  746.    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
  747.    _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
  748.    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
  749.    _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
  750.     int tmpDbgFlag;
  751.     tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
  752.     tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF;
  753.     _CrtSetDbgFlag(tmpDbgFlag);
  754. #endif
  755.     // Figure out if we are on NT and save that flag for later use
  756.     OSVERSIONINFO   OSVer;
  757.     OSVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  758.     ::GetVersionEx(&OSVer);
  759.     gOnNT = (OSVer.dwPlatformId == VER_PLATFORM_WIN32_NT);
  760. }
  761. void XMLPlatformUtils::platformTerm()
  762. {
  763.     // We don't have any temrination requirements for win32 at this time
  764. }
  765. #include <xercesc/util/LogicalPath.c>
  766. XERCES_CPP_NAMESPACE_END