Added Xerces-C++ 3.1.2
This commit is contained in:
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: WindowsFileMgr.cpp 556533 2007-07-16 07:36:41Z amassari $
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <xercesc/util/FileManagers/WindowsFileMgr.hpp>
|
||||
#include <xercesc/util/Janitor.hpp>
|
||||
#include <xercesc/util/XMLString.hpp>
|
||||
#include <xercesc/util/XMLUniDefs.hpp>
|
||||
|
||||
#ifndef INVALID_SET_FILE_POINTER
|
||||
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
||||
#endif
|
||||
|
||||
XERCES_CPP_NAMESPACE_BEGIN
|
||||
|
||||
static bool isBackSlash(XMLCh c) {
|
||||
return c == chBackSlash ||
|
||||
c == chYenSign ||
|
||||
c == chWonSign;
|
||||
}
|
||||
|
||||
WindowsFileMgr::WindowsFileMgr()
|
||||
{
|
||||
// Figure out if we are on NT and save that flag for later use
|
||||
OSVERSIONINFO OSVer;
|
||||
OSVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
::GetVersionEx(&OSVer);
|
||||
_onNT = (OSVer.dwPlatformId == VER_PLATFORM_WIN32_NT);
|
||||
}
|
||||
|
||||
|
||||
WindowsFileMgr::~WindowsFileMgr()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
FileHandle
|
||||
WindowsFileMgr::fileOpen(const XMLCh* fileName, bool toWrite, MemoryManager* const manager)
|
||||
{
|
||||
// Watch for obvious wierdness
|
||||
if (!fileName)
|
||||
return 0;
|
||||
|
||||
//
|
||||
// We have to play a little trick here. If its /x:.....
|
||||
// style fully qualified path, we have to toss the leading /
|
||||
// character.
|
||||
//
|
||||
const XMLCh* nameToOpen = fileName;
|
||||
if (*fileName == chForwardSlash)
|
||||
{
|
||||
if (XMLString::stringLen(fileName) > 3)
|
||||
{
|
||||
if (*(fileName + 2) == chColon)
|
||||
{
|
||||
const XMLCh chDrive = *(fileName + 1);
|
||||
if (((chDrive >= chLatin_A) && (chDrive <= chLatin_Z))
|
||||
|| ((chDrive >= chLatin_a) && (chDrive <= chLatin_z)))
|
||||
{
|
||||
nameToOpen = fileName + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Similarly for UNC paths
|
||||
if ( *(fileName + 1) == *(fileName + 2) &&
|
||||
(*(fileName + 1) == chForwardSlash ||
|
||||
*(fileName + 1) == chBackSlash) )
|
||||
{
|
||||
nameToOpen = fileName + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ok, this might look stupid but its a semi-expedient way to deal
|
||||
// with a thorny problem. Shift-JIS and some other Asian encodings
|
||||
// are fundamentally broken and map both the backslash and the Yen
|
||||
// sign to the same code point. Transcoders have to pick one or the
|
||||
// other to map '\' to Unicode and tend to choose the Yen sign.
|
||||
//
|
||||
// Unicode Yen or Won signs as directory separators will fail.
|
||||
//
|
||||
// So, we will check this path name for Yen or won signs and, if they are
|
||||
// there, we'll replace them with slashes.
|
||||
//
|
||||
// A further twist: we replace Yen and Won with forward slashes rather
|
||||
// than back slashes. Either form of slash will work as a directory
|
||||
// separator. On Win 95 and 98, though, Unicode back-slashes may
|
||||
// fail to transode back to 8-bit 0x5C with some Unicode converters
|
||||
// to some of the problematic code pages. Forward slashes always
|
||||
// transcode correctly back to 8 bit char * form.
|
||||
//
|
||||
XMLCh *tmpUName = 0;
|
||||
|
||||
const XMLCh* srcPtr = nameToOpen;
|
||||
while (*srcPtr)
|
||||
{
|
||||
if (*srcPtr == chYenSign ||
|
||||
*srcPtr == chWonSign)
|
||||
break;
|
||||
srcPtr++;
|
||||
}
|
||||
|
||||
//
|
||||
// If we found a yen, then we have to create a temp file name. Else
|
||||
// go with the file name as is and save the overhead.
|
||||
//
|
||||
if (*srcPtr)
|
||||
{
|
||||
tmpUName = XMLString::replicate(nameToOpen, manager);
|
||||
|
||||
XMLCh* tmpPtr = tmpUName;
|
||||
while (*tmpPtr)
|
||||
{
|
||||
if (*tmpPtr == chYenSign ||
|
||||
*tmpPtr == chWonSign)
|
||||
*tmpPtr = chForwardSlash;
|
||||
tmpPtr++;
|
||||
}
|
||||
nameToOpen = tmpUName;
|
||||
}
|
||||
FileHandle retVal = 0;
|
||||
if (_onNT)
|
||||
{
|
||||
retVal = ::CreateFileW
|
||||
(
|
||||
(LPCWSTR) nameToOpen
|
||||
, toWrite?GENERIC_WRITE:GENERIC_READ
|
||||
, FILE_SHARE_READ
|
||||
, 0
|
||||
, toWrite?CREATE_ALWAYS:OPEN_EXISTING
|
||||
, toWrite?FILE_ATTRIBUTE_NORMAL:FILE_FLAG_SEQUENTIAL_SCAN
|
||||
, 0
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// We are Win 95 / 98. Take the Unicode file name back to (char *)
|
||||
// so that we can open it.
|
||||
//
|
||||
char* tmpName = XMLString::transcode(nameToOpen, manager);
|
||||
retVal = ::CreateFileA
|
||||
(
|
||||
tmpName
|
||||
, toWrite?GENERIC_WRITE:GENERIC_READ
|
||||
, FILE_SHARE_READ
|
||||
, 0
|
||||
, toWrite?CREATE_ALWAYS:OPEN_EXISTING
|
||||
, toWrite?FILE_ATTRIBUTE_NORMAL:FILE_FLAG_SEQUENTIAL_SCAN
|
||||
, 0
|
||||
);
|
||||
manager->deallocate(tmpName);//delete [] tmpName;
|
||||
}
|
||||
|
||||
if (tmpUName)
|
||||
manager->deallocate(tmpUName);//delete [] tmpUName;
|
||||
|
||||
if (retVal == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
FileHandle
|
||||
WindowsFileMgr::fileOpen(const char* path, bool toWrite, MemoryManager* const manager)
|
||||
{
|
||||
XMLCh* tmpFileName = XMLString::transcode(path, manager);
|
||||
ArrayJanitor<XMLCh> janText(tmpFileName, manager);
|
||||
return fileOpen(tmpFileName, toWrite, manager);
|
||||
}
|
||||
|
||||
|
||||
FileHandle
|
||||
WindowsFileMgr::openStdIn(MemoryManager* const manager)
|
||||
{
|
||||
//
|
||||
// Get the standard input handle. Duplicate it and return that copy
|
||||
// since the outside world cannot tell the difference and will shut
|
||||
// down this handle when its done with it. If we gave out the orignal,
|
||||
// shutting it would prevent any further output.
|
||||
//
|
||||
HANDLE stdInOrg = ::GetStdHandle(STD_INPUT_HANDLE);
|
||||
if (stdInOrg == INVALID_HANDLE_VALUE) {
|
||||
XMLCh stdinStr[] = {chLatin_s, chLatin_t, chLatin_d, chLatin_i, chLatin_n, chNull};
|
||||
ThrowXMLwithMemMgr1(XMLPlatformUtilsException, XMLExcepts::File_CouldNotOpenFile, stdinStr, manager);
|
||||
}
|
||||
|
||||
HANDLE retHandle;
|
||||
if (!::DuplicateHandle
|
||||
(
|
||||
::GetCurrentProcess()
|
||||
, stdInOrg
|
||||
, ::GetCurrentProcess()
|
||||
, &retHandle
|
||||
, 0
|
||||
, FALSE
|
||||
, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotDupHandle, manager);
|
||||
}
|
||||
return retHandle;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WindowsFileMgr::fileClose(FileHandle f, MemoryManager* const manager)
|
||||
{
|
||||
if (!f)
|
||||
ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager);
|
||||
|
||||
if (!::CloseHandle(f))
|
||||
ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile, manager);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WindowsFileMgr::fileReset(FileHandle f, MemoryManager* const manager)
|
||||
{
|
||||
if (!f)
|
||||
ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager);
|
||||
|
||||
// Seek to the start of the file
|
||||
if (::SetFilePointer(f, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
||||
ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotResetFile, manager);
|
||||
}
|
||||
|
||||
|
||||
XMLFilePos
|
||||
WindowsFileMgr::curPos(FileHandle f, MemoryManager* const manager)
|
||||
{
|
||||
if (!f)
|
||||
ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager);
|
||||
|
||||
// Get the current position
|
||||
LONG high=0;
|
||||
DWORD low = ::SetFilePointer(f, 0, &high, FILE_CURRENT);
|
||||
if (low == INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR)
|
||||
ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos, manager);
|
||||
|
||||
return (((XMLFilePos)high) << 32) | low;
|
||||
}
|
||||
|
||||
|
||||
XMLFilePos
|
||||
WindowsFileMgr::fileSize(FileHandle f, MemoryManager* const manager)
|
||||
{
|
||||
if (!f)
|
||||
ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager);
|
||||
|
||||
DWORD high=0;
|
||||
DWORD low=::GetFileSize(f, &high);
|
||||
if(low==INVALID_FILE_SIZE && GetLastError()!=NO_ERROR)
|
||||
// TODO: find a better exception
|
||||
ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos, manager);
|
||||
|
||||
return (((XMLFilePos)high) << 32) | low;
|
||||
}
|
||||
|
||||
|
||||
XMLSize_t
|
||||
WindowsFileMgr::fileRead(FileHandle f, XMLSize_t byteCount, XMLByte* buffer, MemoryManager* const manager)
|
||||
{
|
||||
if (!f || !buffer)
|
||||
ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager);
|
||||
|
||||
DWORD bytesRead = 0;
|
||||
if (!::ReadFile(f, buffer, (DWORD)byteCount, &bytesRead, 0))
|
||||
{
|
||||
//
|
||||
// Check specially for a broken pipe error. If we get this, it just
|
||||
// means no more data from the pipe, so return zero.
|
||||
//
|
||||
if (::GetLastError() != ERROR_BROKEN_PIPE)
|
||||
ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile, manager);
|
||||
}
|
||||
return (unsigned int)bytesRead;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WindowsFileMgr::fileWrite(FileHandle f, XMLSize_t byteCount, const XMLByte* buffer, MemoryManager* const manager)
|
||||
{
|
||||
if (!f || !buffer)
|
||||
ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::CPtr_PointerIsZero, manager);
|
||||
|
||||
const XMLByte* tmpFlush = buffer;
|
||||
|
||||
while (byteCount > 0)
|
||||
{
|
||||
DWORD bytesWritten = 0;
|
||||
if (!::WriteFile(f, tmpFlush, (DWORD)byteCount, &bytesWritten, 0))
|
||||
ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotWriteToFile, manager);
|
||||
|
||||
tmpFlush+=bytesWritten;
|
||||
byteCount-=bytesWritten;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
XMLCh*
|
||||
WindowsFileMgr::getFullPath(const XMLCh* const srcPath, MemoryManager* const manager)
|
||||
{
|
||||
//
|
||||
// If we are on NT, then use wide character APIs, else use ASCII APIs.
|
||||
// We have to do it manually since we are only built in ASCII mode from
|
||||
// the standpoint of the APIs.
|
||||
//
|
||||
if (_onNT)
|
||||
{
|
||||
// Use a local buffer that is big enough for the largest legal path
|
||||
const unsigned int bufSize = 1024;
|
||||
XMLCh tmpPath[bufSize + 1];
|
||||
|
||||
XMLCh* namePart = 0;
|
||||
if (!::GetFullPathNameW((LPCWSTR)srcPath, bufSize, (LPWSTR)tmpPath, (LPWSTR*)&namePart))
|
||||
return 0;
|
||||
|
||||
// Return a copy of the path
|
||||
return XMLString::replicate(tmpPath, manager);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Transcode the incoming string
|
||||
char* tmpSrcPath = XMLString::transcode(srcPath, manager);
|
||||
ArrayJanitor<char> janSrcPath(tmpSrcPath, manager);
|
||||
|
||||
// Use a local buffer that is big enough for the largest legal path
|
||||
const unsigned int bufSize = 511;
|
||||
char tmpPath[511 + 1];
|
||||
|
||||
char* namePart = 0;
|
||||
if (!::GetFullPathNameA(tmpSrcPath, bufSize, tmpPath, &namePart))
|
||||
return 0;
|
||||
|
||||
// Return a transcoded copy of the path
|
||||
return XMLString::transcode(tmpPath, manager);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
XMLCh*
|
||||
WindowsFileMgr::getCurrentDirectory(MemoryManager* const manager)
|
||||
{
|
||||
//
|
||||
// If we are on NT, then use wide character APIs, else use ASCII APIs.
|
||||
// We have to do it manually since we are only built in ASCII mode from
|
||||
// the standpoint of the APIs.
|
||||
//
|
||||
if (_onNT)
|
||||
{
|
||||
// Use a local buffer that is big enough for the largest legal path
|
||||
const unsigned int bufSize = 1024;
|
||||
XMLCh tmpPath[bufSize + 1];
|
||||
|
||||
if (!::GetCurrentDirectoryW(bufSize, (LPWSTR)tmpPath))
|
||||
return 0;
|
||||
|
||||
// Return a copy of the path
|
||||
return XMLString::replicate(tmpPath, manager);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use a local buffer that is big enough for the largest legal path
|
||||
const unsigned int bufSize = 511;
|
||||
char tmpPath[511 + 1];
|
||||
|
||||
if (!::GetCurrentDirectoryA(bufSize, tmpPath))
|
||||
return 0;
|
||||
|
||||
// Return a transcoded copy of the path
|
||||
return XMLString::transcode(tmpPath, manager);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
WindowsFileMgr::isRelative(const XMLCh* const toCheck, MemoryManager* const /*manager*/)
|
||||
{
|
||||
// Check for pathological case of empty path
|
||||
if (!toCheck || !toCheck[0])
|
||||
return false;
|
||||
|
||||
//
|
||||
// If its starts with a drive, then it cannot be relative. Note that
|
||||
// we checked the drive not being empty above, so worst case its one
|
||||
// char long and the check of the 1st char will fail because its really
|
||||
// a null character.
|
||||
//
|
||||
if (toCheck[1] == chColon)
|
||||
{
|
||||
if (((toCheck[0] >= chLatin_A) && (toCheck[0] <= chLatin_Z))
|
||||
|| ((toCheck[0] >= chLatin_a) && (toCheck[0] <= chLatin_z)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If it starts with a double slash, then it cannot be relative since
|
||||
// it's a remote file.
|
||||
//
|
||||
if (isBackSlash(toCheck[0]))
|
||||
return false;
|
||||
|
||||
// Else assume its a relative path
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
XERCES_CPP_NAMESPACE_END
|
||||
|
||||
Reference in New Issue
Block a user