win32transservice.cpp

来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 1,004 行 · 第 1/2 页

CPP
1,004
字号
/* * Copyright 1999-2004 The Apache Software Foundation. *  * Licensed 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: Win32TransService.cpp,v 1.23 2004/09/14 20:33:39 amassari Exp $ */// ---------------------------------------------------------------------------//  Includes// ---------------------------------------------------------------------------#include <xercesc/util/PlatformUtils.hpp>#include <xercesc/util/TranscodingException.hpp>#include <xercesc/util/XMLException.hpp>#include <xercesc/util/XMLString.hpp>#include <xercesc/util/XMLUniDefs.hpp>#include <xercesc/util/XMLUni.hpp>#include <xercesc/util/RefHashTableOf.hpp>#include "Win32TransService.hpp"#include <windows.h>XERCES_CPP_NAMESPACE_BEGIN// ---------------------------------------------------------------------------//  Local, const data// ---------------------------------------------------------------------------static const XMLCh gMyServiceId[] ={    chLatin_W, chLatin_i, chLatin_n, chDigit_3, chDigit_2, chNull};// ---------------------------------------------------------------------------//  This is the simple CPMapEntry class. It just contains an encoding name//  and a code page for that encoding.// ---------------------------------------------------------------------------class CPMapEntry : public XMemory{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&);    CPMapEntry& 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;};// ---------------------------------------------------------------------------//  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 charLen = ::mblen(encodingName, MB_CUR_MAX);    if (charLen != -1) {        const unsigned int targetLen = srcLen/charLen;        fEncodingName = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate        (            (targetLen + 1) * sizeof(XMLCh)        );//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, XMLPlatformUtils::fgMemoryManager);    //    //  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(){    XMLPlatformUtils::fgMemoryManager->deallocate(fEncodingName);//delete [] fEncodingName;}// ---------------------------------------------------------------------------//  CPMapEntry: Getter methods// ---------------------------------------------------------------------------const XMLCh* CPMapEntry::getEncodingName() const{    return fEncodingName;}unsigned int CPMapEntry::getWinCP() const{    return fCPId;}unsigned int CPMapEntry::getIEEncoding() const{    return fIEId;}//---------------------------------------------------------------------------////  class Win32TransService Implementation ...////---------------------------------------------------------------------------// ---------------------------------------------------------------------------//  Win32TransService: Constructors and Destructor// ---------------------------------------------------------------------------Win32TransService::Win32TransService(){    fCPMap = new RefHashTableOf<CPMapEntry>(109);    //    //  Open up the registry key that contains the info we want. Note that,    //  if this key does not exist, then we just return. It will just mean    //  that we don't have any support except for intrinsic encodings supported    //  by the parser itself (and the LCP support of course.    //    HKEY charsetKey;    if (::RegOpenKeyExA    (        HKEY_CLASSES_ROOT        , "MIME\\Database\\Charset"        , 0        , KEY_READ        , &charsetKey))    {        return;    }    //    //  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;    unsigned long theSize;    for (subIndex = 0;;++subIndex)    {        // 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))        {            continue;        }        //        //  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)            {                ::RegCloseKey(encodingKey);                continue;            }            //            //  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)                {                    ::RegCloseKey(encodingKey);                    continue;                }                CPMapEntry* newEntry = new CPMapEntry(nameBuf, CPId, IEId);                fCPMap->put((void*)newEntry->getEncodingName(), newEntry);            }        }        // And close the subkey handle        ::RegCloseKey(encodingKey);    }    //    //  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.    //    char aliasBuf[nameBufSz + 1];    for (subIndex = 0;;++subIndex)    {        // 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))        {            continue;        }        //        //  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 charLen = ::mblen(aliasBuf, MB_CUR_MAX);            if (charLen != -1) {                const unsigned int targetLen = srcLen/charLen;                XMLCh* uniAlias = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate                (                    (targetLen + 1) * sizeof(XMLCh)                );//new XMLCh[targetLen + 1];                ::mbstowcs(uniAlias, aliasBuf, srcLen);                uniAlias[targetLen] = 0;                _wcsupr(uniAlias);                // Look up the alias name                CPMapEntry* aliasedEntry = fCPMap->get(uniAlias);                if (aliasedEntry)                {                    const unsigned int srcLen = strlen(nameBuf);                    const unsigned charLen = ::mblen(nameBuf, MB_CUR_MAX);                    const unsigned int targetLen = srcLen/charLen;                                        XMLCh* uniName = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate                    (                        (targetLen + 1) * sizeof(XMLCh)                    );//new XMLCh[targetLen + 1];                    ::mbstowcs(uniName, nameBuf, srcLen);                    uniName[targetLen] = 0;                    _wcsupr(uniName);                    //                    //  If the name is actually different, then take it.                    //  Otherwise, don't take it. They map aliases that are                    //  just different case.                    //                    if (::wcscmp(uniName, aliasedEntry->getEncodingName()))                    {                        CPMapEntry* newEntry = new CPMapEntry(uniName, aliasedEntry->getWinCP(), aliasedEntry->getIEEncoding());                        fCPMap->put((void*)newEntry->getEncodingName(), newEntry);                    }                    XMLPlatformUtils::fgMemoryManager->deallocate(uniName);//delete [] uniName;                }                XMLPlatformUtils::fgMemoryManager->deallocate(uniAlias);//delete [] uniAlias;            }        }        // And close the subkey handle        ::RegCloseKey(encodingKey);    }    // And close the main key handle    ::RegCloseKey(charsetKey);}Win32TransService::~Win32TransService(){    delete fCPMap;}// ---------------------------------------------------------------------------//  Win32TransService: The virtual transcoding service API// ---------------------------------------------------------------------------int Win32TransService::compareIString(  const   XMLCh* const    comp1                                        , const XMLCh* const    comp2){    return _wcsicmp(comp1, comp2);}int Win32TransService::compareNIString( const   XMLCh* const    comp1                                        , const XMLCh* const    comp2                                        , const unsigned int    maxChars){    return _wcsnicmp(comp1, comp2, maxChars);}const XMLCh* Win32TransService::getId() const{    return gMyServiceId;}bool Win32TransService::isSpace(const XMLCh toCheck) const{    return (iswspace(toCheck) != 0);}XMLLCPTranscoder* Win32TransService::makeNewLCPTranscoder(){    // Just allocate a new LCP transcoder of our type    return new Win32LCPTranscoder;}bool Win32TransService::supportsSrcOfs() const{    //    //  Since the only mechanism we have to translate XML text in this    //  transcoder basically require us to do work that allows us to support    //  source offsets, we might as well do it.    //    return true;}void Win32TransService::upperCase(XMLCh* const toUpperCase) const{    _wcsupr(toUpperCase);}void Win32TransService::lowerCase(XMLCh* const toLowerCase) const{    _wcslwr(toLowerCase);}bool Win32TransService::isAlias(const   HKEY            encodingKey                    ,       char* const     aliasBuf                    , const unsigned int    nameBufSz ){    unsigned long theType;    unsigned long theSize = nameBufSz;    return (::RegQueryValueExA    (        encodingKey        , "AliasForCharset"        , 0        , &theType        , (unsigned char*)aliasBuf        , &theSize    ) == ERROR_SUCCESS);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?