You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by ro...@locus.apache.org on 2000/03/09 00:40:37 UTC
cvs commit: xml-xerces/c/src/util/Transcoders/Win32 Win32TransService2.cpp
roddey 00/03/08 15:40:37
Added: c/src/util/Transcoders/Win32 Win32TransService2.cpp
Log:
Oops, I think I forgot to commit this new file
Revision Changes Path
1.1 xml-xerces/c/src/util/Transcoders/Win32/Win32TransService2.cpp
Index: Win32TransService2.cpp
===================================================================
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache\@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation, and was
* originally based on software copyright (c) 1999, International
* Business Machines, Inc., http://www.ibm.com . For more information
* on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
/*
* $Log: Win32TransService2.cpp,v $
* Revision 1.1 2000/03/08 23:40:37 roddey
* Oops, I think I forgot to commit this new file
*
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <util/PlatformUtils.hpp>
#include <util/RefHashTableOf.hpp>
#include <util/XMLUni.hpp>
#include "Win32TransService.hpp"
#include <windows.h>
// ---------------------------------------------------------------------------
// This is the simple CPMapEntry class. It just contains an encoding name
// and a code page for that encoding.
// ---------------------------------------------------------------------------
class CPMapEntry
{
public :
// -----------------------------------------------------------------------
// Constructors and Destructor
// -----------------------------------------------------------------------
CPMapEntry
(
const XMLCh* const encodingName
, const unsigned int cpId
, const unsigned int ieId
);
CPMapEntry
(
const char* const encodingName
, const unsigned int cpId
, const unsigned int ieId
);
~CPMapEntry();
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
const XMLCh* getEncodingName() const;
const XMLCh* getKey() const;
unsigned int getWinCP() const;
unsigned int getIEEncoding() const;
private :
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
CPMapEntry();
CPMapEntry(const CPMapEntry&);
void operator=(const CPMapEntry&);
// -----------------------------------------------------------------------
// Private data members
//
// fEncodingName
// This is the encoding name for the code page that this instance
// represents.
//
// fCPId
// This is the Windows specific code page for the encoding that this
// instance represents.
//
// fIEId
// This is the IE encoding id. Its not used at this time, but we
// go ahead and get it and store it just in case for later.
// -----------------------------------------------------------------------
XMLCh* fEncodingName;
unsigned int fCPId;
unsigned int fIEId;
};
// ---------------------------------------------------------------------------
// Local data
//
// gCPMap
// This is hash table of entries which map encoding names to their
// Windows specific code pages. The code page allows us to create
// transcoders for those encodings. The encoding names come from XML
// files.
//
// This map is shared unsynchronized among all threads of the process,
// which is cool since it will be read only once its initialized.
// ---------------------------------------------------------------------------
RefHashTableOf<CPMapEntry> gCPMap(109);
// ---------------------------------------------------------------------------
// CPMapEntry: Constructors and Destructor
// ---------------------------------------------------------------------------
CPMapEntry::CPMapEntry( const char* const encodingName
, const unsigned int cpId
, const unsigned int ieId) :
fEncodingName(0)
, fCPId(cpId)
, fIEId(ieId)
{
// Transcode the name to Unicode and store that copy
const unsigned int srcLen = strlen(encodingName);
const unsigned int targetLen = ::mbstowcs(0, encodingName, srcLen);
fEncodingName = new XMLCh[targetLen + 1];
::mbstowcs(fEncodingName, encodingName, srcLen);
fEncodingName[targetLen] = 0;
//
// Upper case it because we are using a hash table and need to be
// sure that we find all case combinations.
//
::wcsupr(fEncodingName);
}
CPMapEntry::CPMapEntry( const XMLCh* const encodingName
, const unsigned int cpId
, const unsigned int ieId) :
fEncodingName(0)
, fCPId(cpId)
, fIEId(ieId)
{
fEncodingName = XMLString::replicate(encodingName);
//
// Upper case it because we are using a hash table and need to be
// sure that we find all case combinations.
//
::wcsupr(fEncodingName);
}
CPMapEntry::~CPMapEntry()
{
delete [] fEncodingName;
}
// ---------------------------------------------------------------------------
// CPMapEntry: Getter methods
// ---------------------------------------------------------------------------
const XMLCh* CPMapEntry::getEncodingName() const
{
return fEncodingName;
}
const XMLCh* CPMapEntry::getKey() const
{
return fEncodingName;
}
unsigned int CPMapEntry::getWinCP() const
{
return fCPId;
}
unsigned int CPMapEntry::getIEEncoding() const
{
return fIEId;
}
// ---------------------------------------------------------------------------
// Local methods
// ---------------------------------------------------------------------------
static bool isAlias(const HKEY encodingKey
, char* const aliasBuf = 0
, const unsigned int nameBufSz = 0)
{
unsigned long theType;
unsigned long theSize = nameBufSz;
return (::RegQueryValueExA
(
encodingKey
, "AliasForCharset"
, 0
, &theType
, (unsigned char*)aliasBuf
, &theSize
) == ERROR_SUCCESS);
}
// ---------------------------------------------------------------------------
// Win32TransService: The protected virtual transcoding service API
// ---------------------------------------------------------------------------
XMLTranscoder*
Win32TransService::makeNewXMLTranscoder(const XMLCh* const encodingName
, XMLTransService::Codes& resValue
, const unsigned int blockSize)
{
const unsigned int upLen = 1024;
XMLCh upEncoding[upLen + 1];
//
// Get an upper cased copy of the encoding name, since we use a hash
// table and we store them all in upper case.
//
::wcsncpy(upEncoding, encodingName, upLen);
upEncoding[upLen] = 0;
::wcsupr(upEncoding);
// Now to try to find this guy in the CP map
CPMapEntry* theEntry = gCPMap.get(upEncoding);
// If not found, then return a null pointer
if (!theEntry)
{
resValue = XMLTransService::UnsupportedEncoding;
return 0;
}
// We found it, so return a Win32 transcoder for this encoding
return new Win32Transcoder
(
encodingName
, theEntry->getWinCP()
, theEntry->getIEEncoding()
, blockSize
);
}
// ---------------------------------------------------------------------------
// Win32TransService: Private helper methods
// ---------------------------------------------------------------------------
void Win32TransService::initCPMap()
{
// Open up the registry key that contains the info we want
HKEY charsetKey;
if (::RegOpenKeyExA
(
HKEY_CLASSES_ROOT
, "MIME\\Database\\Charset"
, 0
, KEY_READ
, &charsetKey))
{
XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService);
}
//
// Read in the registry keys that hold the code page ids. Skip for now
// those entries which indicate that they are aliases for some other
// encodings. We'll come back and do a second round for those and look
// up the original name and get the code page id.
//
// Note that we have to use A versions here so that this will run on
// 98, and transcode the strings to Unicode.
//
const unsigned int nameBufSz = 1024;
char nameBuf[nameBufSz + 1];
unsigned int subIndex = 0;
unsigned long theSize;
while (true)
{
// Get the name of the next key
theSize = nameBufSz;
if (::RegEnumKeyExA
(
charsetKey
, subIndex
, nameBuf
, &theSize
, 0, 0, 0, 0) == ERROR_NO_MORE_ITEMS)
{
break;
}
// Open this subkey
HKEY encodingKey;
if (::RegOpenKeyExA
(
charsetKey
, nameBuf
, 0
, KEY_READ
, &encodingKey))
{
XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService);
}
//
// Lts see if its an alias. If so, then ignore it in this first
// loop. Else, we'll add a new entry for this one.
//
if (!isAlias(encodingKey))
{
//
// Lets get the two values out of this key that we are
// interested in. There should be a code page entry and an
// IE entry.
//
unsigned long theType;
unsigned int CPId;
unsigned int IEId;
theSize = sizeof(unsigned int);
if (::RegQueryValueExA
(
encodingKey
, "Codepage"
, 0
, &theType
, (unsigned char*)&CPId
, &theSize) != ERROR_SUCCESS)
{
XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService);
}
//
// If this is not a valid Id, and it might not be because its
// not loaded on this system, then don't take it.
//
if (::IsValidCodePage(CPId))
{
theSize = sizeof(unsigned int);
if (::RegQueryValueExA
(
encodingKey
, "InternetEncoding"
, 0
, &theType
, (unsigned char*)&IEId
, &theSize) != ERROR_SUCCESS)
{
XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService);
}
CPMapEntry* newEntry = new CPMapEntry(nameBuf, CPId, IEId);
gCPMap.put(newEntry);
}
}
// And now close the subkey handle and bump the subkey index
::RegCloseKey(encodingKey);
subIndex++;
}
//
// Now loop one more time and this time we do just the aliases. For
// each one we find, we look up that name in the map we've already
// built and add a new entry with this new name and the same id
// values we stored for the original.
//
subIndex = 0;
char aliasBuf[nameBufSz + 1];
while (true)
{
// Get the name of the next key
theSize = nameBufSz;
if (::RegEnumKeyExA
(
charsetKey
, subIndex
, nameBuf
, &theSize
, 0, 0, 0, 0) == ERROR_NO_MORE_ITEMS)
{
break;
}
// Open this subkey
HKEY encodingKey;
if (::RegOpenKeyExA
(
charsetKey
, nameBuf
, 0
, KEY_READ
, &encodingKey))
{
XMLPlatformUtils::panic(XMLPlatformUtils::Panic_NoTransService);
}
//
// If its an alias, look up the name in the map. If we find it,
// then construct a new one with the new name and the aliased
// ids.
//
if (isAlias(encodingKey, aliasBuf, nameBufSz))
{
const unsigned int srcLen = strlen(aliasBuf);
const unsigned int targetLen = ::mbstowcs(0, aliasBuf, srcLen);
XMLCh* uniAlias = new XMLCh[targetLen + 1];
::mbstowcs(uniAlias, aliasBuf, srcLen);
uniAlias[targetLen] = 0;
::wcsupr(uniAlias);
// Look up the alias name
CPMapEntry* aliasedEntry = gCPMap.get(uniAlias);
if (aliasedEntry)
{
//
// If the name is actually different, then take it.
// Otherwise, don't take it. They map aliases that are
// just different case.
//
if (::wcscmp(uniAlias, aliasedEntry->getEncodingName()))
{
CPMapEntry* newEntry = new CPMapEntry
(
uniAlias
, aliasedEntry->getWinCP()
, aliasedEntry->getIEEncoding()
);
gCPMap.put(newEntry);
}
}
else
{
delete [] uniAlias;
}
}
// And now close the subkey handle and bump the subkey index
::RegCloseKey(encodingKey);
subIndex++;
}
// And close the main key handle
::RegCloseKey(charsetKey);
}