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

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2000 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: Win32TransService.cpp,v 1.14 2003/05/25 21:39:57 knoaman Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <xercesc/util/PlatformUtils.hpp>
  63. #include <xercesc/util/TranscodingException.hpp>
  64. #include <xercesc/util/XMLException.hpp>
  65. #include <xercesc/util/XMLString.hpp>
  66. #include <xercesc/util/XMLUniDefs.hpp>
  67. #include <xercesc/util/XMLUni.hpp>
  68. #include <xercesc/util/RefHashTableOf.hpp>
  69. #include "Win32TransService.hpp"
  70. #include <windows.h>
  71. XERCES_CPP_NAMESPACE_BEGIN
  72. // ---------------------------------------------------------------------------
  73. //  Local, const data
  74. // ---------------------------------------------------------------------------
  75. static const XMLCh gMyServiceId[] =
  76. {
  77.     chLatin_W, chLatin_i, chLatin_n, chDigit_3, chDigit_2, chNull
  78. };
  79. // ---------------------------------------------------------------------------
  80. //  This is the simple CPMapEntry class. It just contains an encoding name
  81. //  and a code page for that encoding.
  82. // ---------------------------------------------------------------------------
  83. class CPMapEntry : public XMemory
  84. {
  85. public :
  86.     // -----------------------------------------------------------------------
  87.     //  Constructors and Destructor
  88.     // -----------------------------------------------------------------------
  89.     CPMapEntry
  90.     (
  91.         const   XMLCh* const    encodingName
  92.         , const unsigned int    cpId
  93.         , const unsigned int    ieId
  94.     );
  95.     CPMapEntry
  96.     (
  97.         const   char* const     encodingName
  98.         , const unsigned int    cpId
  99.         , const unsigned int    ieId
  100.     );
  101.     ~CPMapEntry();
  102.     // -----------------------------------------------------------------------
  103.     //  Getter methods
  104.     // -----------------------------------------------------------------------
  105.     const XMLCh* getEncodingName() const;
  106.     const XMLCh* getKey() const;
  107.     unsigned int getWinCP() const;
  108.     unsigned int getIEEncoding() const;
  109. private :
  110.     // -----------------------------------------------------------------------
  111.     //  Unimplemented constructors and operators
  112.     // -----------------------------------------------------------------------
  113.     CPMapEntry();
  114.     CPMapEntry(const CPMapEntry&);
  115.     CPMapEntry& operator=(const CPMapEntry&);
  116.     // -----------------------------------------------------------------------
  117.     //  Private data members
  118.     //
  119.     //  fEncodingName
  120.     //      This is the encoding name for the code page that this instance
  121.     //      represents.
  122.     //
  123.     //  fCPId
  124.     //      This is the Windows specific code page for the encoding that this
  125.     //      instance represents.
  126.     //
  127.     //  fIEId
  128.     //      This is the IE encoding id. Its not used at this time, but we
  129.     //      go ahead and get it and store it just in case for later.
  130.     // -----------------------------------------------------------------------
  131.     XMLCh*          fEncodingName;
  132.     unsigned int    fCPId;
  133.     unsigned int    fIEId;
  134. };
  135. // ---------------------------------------------------------------------------
  136. //  CPMapEntry: Constructors and Destructor
  137. // ---------------------------------------------------------------------------
  138. CPMapEntry::CPMapEntry( const   char* const     encodingName
  139.                         , const unsigned int    cpId
  140.                         , const unsigned int    ieId) :
  141.     fEncodingName(0)
  142.     , fCPId(cpId)
  143.     , fIEId(ieId)
  144. {
  145.     // Transcode the name to Unicode and store that copy
  146.     const unsigned int srcLen = strlen(encodingName);
  147.     const unsigned charLen = ::mblen(encodingName, MB_CUR_MAX);
  148.     if (charLen != -1) {
  149.         const unsigned int targetLen = srcLen/charLen;
  150.         fEncodingName = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate
  151.         (
  152.             (targetLen + 1) * sizeof(XMLCh)
  153.         );//new XMLCh[targetLen + 1];
  154.         ::mbstowcs(fEncodingName, encodingName, srcLen);
  155.         fEncodingName[targetLen] = 0;
  156.         //
  157.         //  Upper case it because we are using a hash table and need to be
  158.         //  sure that we find all case combinations.
  159.         //
  160.         _wcsupr(fEncodingName);
  161.   }
  162. }
  163. CPMapEntry::CPMapEntry( const   XMLCh* const    encodingName
  164.                         , const unsigned int    cpId
  165.                         , const unsigned int    ieId) :
  166.     fEncodingName(0)
  167.     , fCPId(cpId)
  168.     , fIEId(ieId)
  169. {
  170.     fEncodingName = XMLString::replicate(encodingName, XMLPlatformUtils::fgMemoryManager);
  171.     //
  172.     //  Upper case it because we are using a hash table and need to be
  173.     //  sure that we find all case combinations.
  174.     //
  175.     _wcsupr(fEncodingName);
  176. }
  177. CPMapEntry::~CPMapEntry()
  178. {
  179.     XMLPlatformUtils::fgMemoryManager->deallocate(fEncodingName);//delete [] fEncodingName;
  180. }
  181. // ---------------------------------------------------------------------------
  182. //  CPMapEntry: Getter methods
  183. // ---------------------------------------------------------------------------
  184. const XMLCh* CPMapEntry::getEncodingName() const
  185. {
  186.     return fEncodingName;
  187. }
  188. unsigned int CPMapEntry::getWinCP() const
  189. {
  190.     return fCPId;
  191. }
  192. unsigned int CPMapEntry::getIEEncoding() const
  193. {
  194.     return fIEId;
  195. }
  196. //---------------------------------------------------------------------------
  197. //
  198. //  class Win32TransService Implementation ...
  199. //
  200. //---------------------------------------------------------------------------
  201. // ---------------------------------------------------------------------------
  202. //  Win32TransService: Constructors and Destructor
  203. // ---------------------------------------------------------------------------
  204. Win32TransService::Win32TransService()
  205. {
  206.     fCPMap = new RefHashTableOf<CPMapEntry>(109);
  207.     //
  208.     //  Open up the registry key that contains the info we want. Note that,
  209.     //  if this key does not exist, then we just return. It will just mean
  210.     //  that we don't have any support except for intrinsic encodings supported
  211.     //  by the parser itself (and the LCP support of course.
  212.     //
  213.     HKEY charsetKey;
  214.     if (::RegOpenKeyExA
  215.     (
  216.         HKEY_CLASSES_ROOT
  217.         , "MIME\Database\Charset"
  218.         , 0
  219.         , KEY_READ
  220.         , &charsetKey))
  221.     {
  222.         return;
  223.     }
  224.     //
  225.     //  Read in the registry keys that hold the code page ids. Skip for now
  226.     //  those entries which indicate that they are aliases for some other
  227.     //  encodings. We'll come back and do a second round for those and look
  228.     //  up the original name and get the code page id.
  229.     //
  230.     //  Note that we have to use A versions here so that this will run on
  231.     //  98, and transcode the strings to Unicode.
  232.     //
  233.     const unsigned int nameBufSz = 1024;
  234.     char nameBuf[nameBufSz + 1];
  235.     unsigned int subIndex = 0;
  236.     unsigned long theSize;
  237.     while (true)
  238.     {
  239.         // Get the name of the next key
  240.         theSize = nameBufSz;
  241.         if (::RegEnumKeyExA
  242.         (
  243.             charsetKey
  244.             , subIndex
  245.             , nameBuf
  246.             , &theSize
  247.             , 0, 0, 0, 0) == ERROR_NO_MORE_ITEMS)
  248.         {
  249.             break;
  250.         }
  251.         // Open this subkey
  252.         HKEY encodingKey;
  253.         if (::RegOpenKeyExA
  254.         (
  255.             charsetKey
  256.             , nameBuf
  257.             , 0
  258.             , KEY_READ
  259.             , &encodingKey))
  260.         {
  261.             XMLPlatformUtils::panic(PanicHandler::Panic_NoTransService);
  262.         }
  263.         //
  264.         //  Lts see if its an alias. If so, then ignore it in this first
  265.         //  loop. Else, we'll add a new entry for this one.
  266.         //
  267.         if (!isAlias(encodingKey))
  268.         {
  269.             //
  270.             //  Lets get the two values out of this key that we are
  271.             //  interested in. There should be a code page entry and an
  272.             //  IE entry.
  273.             //
  274.             unsigned long theType;
  275.             unsigned int CPId;
  276.             unsigned int IEId;
  277.             theSize = sizeof(unsigned int);
  278.             if (::RegQueryValueExA
  279.             (
  280.                 encodingKey
  281.                 , "Codepage"
  282.                 , 0
  283.                 , &theType
  284.                 , (unsigned char*)&CPId
  285.                 , &theSize) != ERROR_SUCCESS)
  286.             {
  287.                 XMLPlatformUtils::panic(PanicHandler::Panic_NoTransService);
  288.             }
  289.             //
  290.             //  If this is not a valid Id, and it might not be because its
  291.             //  not loaded on this system, then don't take it.
  292.             //
  293.             if (::IsValidCodePage(CPId))
  294.             {
  295.                 theSize = sizeof(unsigned int);
  296.                 if (::RegQueryValueExA
  297.                 (
  298.                     encodingKey
  299.                     , "InternetEncoding"
  300.                     , 0
  301.                     , &theType
  302.                     , (unsigned char*)&IEId
  303.                     , &theSize) != ERROR_SUCCESS)
  304.                 {
  305.                     XMLPlatformUtils::panic(PanicHandler::Panic_NoTransService);
  306.                 }
  307.                 CPMapEntry* newEntry = new CPMapEntry(nameBuf, CPId, IEId);
  308.                 fCPMap->put((void*)newEntry->getEncodingName(), newEntry);
  309.             }
  310.         }
  311.         // And now close the subkey handle and bump the subkey index
  312.         ::RegCloseKey(encodingKey);
  313.         subIndex++;
  314.     }
  315.     //
  316.     //  Now loop one more time and this time we do just the aliases. For
  317.     //  each one we find, we look up that name in the map we've already
  318.     //  built and add a new entry with this new name and the same id
  319.     //  values we stored for the original.
  320.     //
  321.     subIndex = 0;
  322.     char aliasBuf[nameBufSz + 1];
  323.     while (true)
  324.     {
  325.         // Get the name of the next key
  326.         theSize = nameBufSz;
  327.         if (::RegEnumKeyExA
  328.         (
  329.             charsetKey
  330.             , subIndex
  331.             , nameBuf
  332.             , &theSize
  333.             , 0, 0, 0, 0) == ERROR_NO_MORE_ITEMS)
  334.         {
  335.             break;
  336.         }
  337.         // Open this subkey
  338.         HKEY encodingKey;
  339.         if (::RegOpenKeyExA
  340.         (
  341.             charsetKey
  342.             , nameBuf
  343.             , 0
  344.             , KEY_READ
  345.             , &encodingKey))
  346.         {
  347.             XMLPlatformUtils::panic(PanicHandler::Panic_NoTransService);
  348.         }
  349.         //
  350.         //  If its an alias, look up the name in the map. If we find it,
  351.         //  then construct a new one with the new name and the aliased
  352.         //  ids.
  353.         //
  354.         if (isAlias(encodingKey, aliasBuf, nameBufSz))
  355.         {
  356.             const unsigned int srcLen = strlen(aliasBuf);
  357.             const unsigned charLen = ::mblen(aliasBuf, MB_CUR_MAX);
  358.             if (charLen != -1) {
  359.                 const unsigned int targetLen = srcLen/charLen;
  360.                 XMLCh* uniAlias = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate
  361.                 (
  362.                     (targetLen + 1) * sizeof(XMLCh)
  363.                 );//new XMLCh[targetLen + 1];
  364.                 ::mbstowcs(uniAlias, aliasBuf, srcLen);
  365.                 uniAlias[targetLen] = 0;
  366.                 _wcsupr(uniAlias);
  367.                 // Look up the alias name
  368.                 CPMapEntry* aliasedEntry = fCPMap->get(uniAlias);
  369.                 if (aliasedEntry)
  370.                 {
  371.                     const unsigned int srcLen = strlen(nameBuf);
  372.                     const unsigned charLen = ::mblen(nameBuf, MB_CUR_MAX);
  373.                     const unsigned int targetLen = srcLen/charLen;
  374.                     
  375.                     XMLCh* uniName = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate
  376.                     (
  377.                         (targetLen + 1) * sizeof(XMLCh)
  378.                     );//new XMLCh[targetLen + 1];
  379.                     ::mbstowcs(uniName, nameBuf, srcLen);
  380.                     uniName[targetLen] = 0;
  381.                     _wcsupr(uniName);
  382.                     //
  383.                     //  If the name is actually different, then take it.
  384.                     //  Otherwise, don't take it. They map aliases that are
  385.                     //  just different case.
  386.                     //
  387.                     if (::wcscmp(uniName, aliasedEntry->getEncodingName()))
  388.                     {
  389.                         CPMapEntry* newEntry = new CPMapEntry(uniName, aliasedEntry->getWinCP(), aliasedEntry->getIEEncoding());
  390.                         fCPMap->put((void*)newEntry->getEncodingName(), newEntry);
  391.                     }
  392.                     XMLPlatformUtils::fgMemoryManager->deallocate(uniName);//delete [] uniName;
  393.                 }
  394.                 XMLPlatformUtils::fgMemoryManager->deallocate(uniAlias);//delete [] uniAlias;
  395.             }
  396.         }
  397.         // And now close the subkey handle and bump the subkey index
  398.         ::RegCloseKey(encodingKey);
  399.         subIndex++;
  400.     }
  401.     // And close the main key handle
  402.     ::RegCloseKey(charsetKey);
  403. }
  404. Win32TransService::~Win32TransService()
  405. {
  406.     delete fCPMap;
  407. }
  408. // ---------------------------------------------------------------------------
  409. //  Win32TransService: The virtual transcoding service API
  410. // ---------------------------------------------------------------------------
  411. int Win32TransService::compareIString(  const   XMLCh* const    comp1
  412.                                         , const XMLCh* const    comp2)
  413. {
  414.     return _wcsicmp(comp1, comp2);
  415. }
  416. int Win32TransService::compareNIString( const   XMLCh* const    comp1
  417.                                         , const XMLCh* const    comp2
  418.                                         , const unsigned int    maxChars)
  419. {
  420.     return _wcsnicmp(comp1, comp2, maxChars);
  421. }
  422. const XMLCh* Win32TransService::getId() const
  423. {
  424.     return gMyServiceId;
  425. }
  426. bool Win32TransService::isSpace(const XMLCh toCheck) const
  427. {
  428.     return (iswspace(toCheck) != 0);
  429. }
  430. XMLLCPTranscoder* Win32TransService::makeNewLCPTranscoder()
  431. {
  432.     // Just allocate a new LCP transcoder of our type
  433.     return new Win32LCPTranscoder;
  434. }
  435. bool Win32TransService::supportsSrcOfs() const
  436. {
  437.     //
  438.     //  Since the only mechanism we have to translate XML text in this
  439.     //  transcoder basically require us to do work that allows us to support
  440.     //  source offsets, we might as well do it.
  441.     //
  442.     return true;
  443. }
  444. void Win32TransService::upperCase(XMLCh* const toUpperCase) const
  445. {
  446.     _wcsupr(toUpperCase);
  447. }
  448. void Win32TransService::lowerCase(XMLCh* const toLowerCase) const
  449. {
  450.     _wcslwr(toLowerCase);
  451. }
  452. bool Win32TransService::isAlias(const   HKEY            encodingKey
  453.                     ,       char* const     aliasBuf
  454.                     , const unsigned int    nameBufSz )
  455. {
  456.     unsigned long theType;
  457.     unsigned long theSize = nameBufSz;
  458.     return (::RegQueryValueExA
  459.     (
  460.         encodingKey
  461.         , "AliasForCharset"
  462.         , 0
  463.         , &theType
  464.         , (unsigned char*)aliasBuf
  465.         , &theSize
  466.     ) == ERROR_SUCCESS);
  467. }
  468. XMLTranscoder*
  469. Win32TransService::makeNewXMLTranscoder(const   XMLCh* const            encodingName
  470.                                         ,       XMLTransService::Codes& resValue
  471.                                         , const unsigned int            blockSize
  472.                                         ,       MemoryManager* const    manager)
  473. {
  474.     const unsigned int upLen = 1024;
  475.     XMLCh upEncoding[upLen + 1];
  476.     //
  477.     //  Get an upper cased copy of the encoding name, since we use a hash
  478.     //  table and we store them all in upper case.
  479.     //
  480.     ::wcsncpy(upEncoding, encodingName, upLen);
  481.     upEncoding[upLen] = 0;
  482.     _wcsupr(upEncoding);
  483.     // Now to try to find this guy in the CP map
  484.     CPMapEntry* theEntry = fCPMap->get(upEncoding);
  485.     // If not found, then return a null pointer
  486.     if (!theEntry)
  487.     {
  488.         resValue = XMLTransService::UnsupportedEncoding;
  489.         return 0;
  490.     }
  491.     // We found it, so return a Win32 transcoder for this encoding
  492.     return new (manager) Win32Transcoder
  493.     (
  494.         encodingName
  495.         , theEntry->getWinCP()
  496.         , theEntry->getIEEncoding()
  497.         , blockSize
  498.         , manager
  499.     );
  500. }
  501. //---------------------------------------------------------------------------
  502. //
  503. //  class Win32Transcoder Implementation ...
  504. //
  505. //---------------------------------------------------------------------------
  506. // ---------------------------------------------------------------------------
  507. //  Win32Transcoder: Constructors and Destructor
  508. // ---------------------------------------------------------------------------
  509. Win32Transcoder::Win32Transcoder(const  XMLCh* const    encodingName
  510.                                 , const unsigned int    winCP
  511.                                 , const unsigned int    ieCP
  512.                                 , const unsigned int    blockSize
  513.                                 , MemoryManager* const manager) :
  514.     XMLTranscoder(encodingName, blockSize, manager)
  515.     , fIECP(ieCP)
  516.     , fWinCP(winCP)
  517. {
  518. }
  519. Win32Transcoder::~Win32Transcoder()
  520. {
  521. }
  522. // ---------------------------------------------------------------------------
  523. //  Win32Transcoder: The virtual transcoder API
  524. // ---------------------------------------------------------------------------
  525. unsigned int
  526. Win32Transcoder::transcodeFrom( const   XMLByte* const      srcData
  527.                                 , const unsigned int        srcCount
  528.                                 ,       XMLCh* const        toFill
  529.                                 , const unsigned int        maxChars
  530.                                 ,       unsigned int&       bytesEaten
  531.                                 ,       unsigned char* const charSizes)
  532. {
  533.     // Get temp pointers to the in and out buffers, and the chars sizes one
  534.     XMLCh*          outPtr = toFill;
  535.     const XMLByte*  inPtr  = srcData;
  536.     unsigned char*  sizesPtr = charSizes;
  537.     // Calc end pointers for each of them
  538.     XMLCh*          outEnd = toFill + maxChars;
  539.     const XMLByte*  inEnd  = srcData + srcCount;
  540.     //
  541.     //  Now loop until we either get our max chars, or cannot get a whole
  542.     //  character from the input buffer.
  543.     //
  544.     bytesEaten = 0;
  545.     while ((outPtr < outEnd) && (inPtr < inEnd))
  546.     {
  547.         //
  548.         //  If we are looking at a leading byte of a multibyte sequence,
  549.         //  then we are going to eat 2 bytes, else 1.
  550.         //
  551.         const unsigned int toEat = ::IsDBCSLeadByteEx(fWinCP, *inPtr) ?
  552.                                     2 : 1;
  553.         // Make sure a whol char is in the source
  554.         if (inPtr + toEat > inEnd)
  555.             break;
  556.         // Try to translate this next char and check for an error
  557.         const unsigned int converted = ::MultiByteToWideChar
  558.         (
  559.             fWinCP
  560.             , MB_PRECOMPOSED | MB_ERR_INVALID_CHARS
  561.             , (const char*)inPtr
  562.             , toEat
  563.             , outPtr
  564.             , 1
  565.         );
  566.         if (converted != 1)
  567.         {
  568.             if (toEat == 1)
  569.             {
  570.                 XMLCh tmpBuf[16];
  571.                 XMLString::binToText((unsigned int)(*inPtr), tmpBuf, 16, 16);
  572.                 ThrowXML2
  573.                 (
  574.                     TranscodingException
  575.                     , XMLExcepts::Trans_BadSrcCP
  576.                     , tmpBuf
  577.                     , getEncodingName()
  578.                 );
  579.             }
  580.              else
  581.             {
  582.                 ThrowXML(TranscodingException, XMLExcepts::Trans_BadSrcSeq);
  583.             }
  584.         }
  585.         // Update the char sizes array for this round
  586.         *sizesPtr++ = toEat;
  587.         // And update the bytes eaten count
  588.         bytesEaten += toEat;
  589.         // And update our in/out ptrs
  590.         inPtr += toEat;
  591.         outPtr++;
  592.     }
  593.     // Return the chars we output
  594.     return (outPtr - toFill);
  595. }
  596. unsigned int
  597. Win32Transcoder::transcodeTo(const  XMLCh* const    srcData
  598.                             , const unsigned int    srcCount
  599.                             ,       XMLByte* const  toFill
  600.                             , const unsigned int    maxBytes
  601.                             ,       unsigned int&   charsEaten
  602.                             , const UnRepOpts       options)
  603. {
  604.     // Get pointers to the start and end of each buffer
  605.     const XMLCh*    srcPtr = srcData;
  606.     const XMLCh*    srcEnd = srcData + srcCount;
  607.     XMLByte*        outPtr = toFill;
  608.     XMLByte*        outEnd = toFill + maxBytes;
  609.     //
  610.     //  Now loop until we either get our max chars, or cannot get a whole
  611.     //  character from the input buffer.
  612.     //
  613.     //  NOTE: We have to use a loop for this unfortunately because the
  614.     //  conversion API is too dumb to tell us how many chars it converted if
  615.     //  it couldn't do the whole source.
  616.     //
  617.     BOOL usedDef;
  618.     while ((outPtr < outEnd) && (srcPtr < srcEnd))
  619.     {
  620.         //
  621.         //  Do one char and see if it made it.
  622.         const unsigned int bytesStored = ::WideCharToMultiByte
  623.         (
  624.             fWinCP
  625.             , WC_COMPOSITECHECK | WC_SEPCHARS
  626.             , srcPtr
  627.             , 1
  628.             , (char*)outPtr
  629.             , outEnd - outPtr
  630.             , 0
  631.             , &usedDef
  632.         );
  633.         // If we didn't transcode anything, then we are done
  634.         if (!bytesStored)
  635.             break;
  636.         //
  637.         //  If the defaault char was used and the options indicate that
  638.         //  this isn't allowed, then throw.
  639.         //
  640.         if (usedDef && (options == UnRep_Throw))
  641.         {
  642.             XMLCh tmpBuf[16];
  643.             XMLString::binToText((unsigned int)*srcPtr, tmpBuf, 16, 16);
  644.             ThrowXML2
  645.             (
  646.                 TranscodingException
  647.                 , XMLExcepts::Trans_Unrepresentable
  648.                 , tmpBuf
  649.                 , getEncodingName()
  650.             );
  651.         }
  652.         // Update our pointers
  653.         outPtr += bytesStored;
  654.         srcPtr++;
  655.     }
  656.     // Update the chars eaten
  657.     charsEaten = srcPtr - srcData;
  658.     // And return the bytes we stored
  659.     return outPtr - toFill;
  660. }
  661. bool Win32Transcoder::canTranscodeTo(const unsigned int toCheck) const
  662. {
  663.     //
  664.     //  If the passed value is really a surrogate embedded together, then
  665.     //  we need to break it out into its two chars. Else just one.
  666.     //
  667.     XMLCh           srcBuf[2];
  668.     unsigned int    srcCount = 1;
  669.     if (toCheck & 0xFFFF0000)
  670.     {
  671.         srcBuf[0] = XMLCh((toCheck >> 10) + 0xD800);
  672.         srcBuf[1] = XMLCh(toCheck & 0x3FF) + 0xDC00;
  673.         srcCount++;
  674.     }
  675.      else
  676.     {
  677.         srcBuf[0] = XMLCh(toCheck);
  678.     }
  679.     //
  680.     //  Use a local temp buffer that would hold any sane multi-byte char
  681.     //  sequence and try to transcode this guy into it.
  682.     //
  683.     char tmpBuf[64];
  684.     BOOL usedDef;
  685.     const unsigned int bytesStored = ::WideCharToMultiByte
  686.     (
  687.         fWinCP
  688.         , WC_COMPOSITECHECK | WC_SEPCHARS
  689.         , srcBuf
  690.         , srcCount
  691.         , tmpBuf
  692.         , 64
  693.         , 0
  694.         , &usedDef
  695.     );
  696.     if (!bytesStored || usedDef)
  697.         return false;
  698.     return true;
  699. }
  700. //---------------------------------------------------------------------------
  701. //
  702. //  class Win32Transcoder Implementation ...
  703. //
  704. //---------------------------------------------------------------------------
  705. // ---------------------------------------------------------------------------
  706. //  Win32LCPTranscoder: Constructors and Destructor
  707. // ---------------------------------------------------------------------------
  708. Win32LCPTranscoder::Win32LCPTranscoder()
  709. {
  710. }
  711. Win32LCPTranscoder::~Win32LCPTranscoder()
  712. {
  713. }
  714. // ---------------------------------------------------------------------------
  715. //  Win32LCPTranscoder: Implementation of the virtual transcoder interface
  716. // ---------------------------------------------------------------------------
  717. unsigned int Win32LCPTranscoder::calcRequiredSize(const char* const srcText)
  718. {
  719.     if (!srcText)
  720.         return 0;
  721.     unsigned charLen = ::mblen(srcText, MB_CUR_MAX);
  722.     if (charLen == -1)
  723.         return 0;
  724.     else if (charLen != 0)
  725.         charLen = strlen(srcText)/charLen;
  726.     if (charLen == -1)
  727.         return 0;
  728.     return charLen;
  729. }
  730. unsigned int Win32LCPTranscoder::calcRequiredSize(const XMLCh* const srcText)
  731. {
  732.     if (!srcText)
  733.         return 0;
  734.     unsigned int retVal = -1;
  735.     
  736.     #if defined(XML_METROWERKS)
  737.      const unsigned int srcLen = ::wcslen(srcText);
  738.      retVal = ::wcsmbslen(srcText, srcLen);
  739.     #else
  740.       retVal = ::wcstombs(0, srcText, 0);
  741.     #endif
  742.     
  743.     if (retVal == (unsigned int)-1)
  744.         return 0;
  745.     return retVal;
  746. }
  747. // Return value using global operator new
  748. // Revisit: deprecate ?
  749. char* Win32LCPTranscoder::transcode(const XMLCh* const toTranscode)
  750. {
  751.     if (!toTranscode)
  752.         return 0;
  753.     char* retVal = 0;
  754.     if (*toTranscode)
  755.     {
  756.         // Calc the needed size
  757.         unsigned int neededLen;
  758.         
  759.        #if defined(XML_METROWERKS)
  760.      const unsigned int srcLen = ::wcslen(toTranscode);
  761.      neededLen = ::wcsmbslen(toTranscode, srcLen);
  762.     #else
  763.       neededLen = ::wcstombs(0, toTranscode, 0);
  764.     #endif
  765.         if (neededLen == (unsigned int)-1)
  766.             return 0;
  767.         // Allocate a buffer of that size plus one for the null and transcode
  768.         retVal = new char[neededLen + 1];
  769.         ::wcstombs(retVal, toTranscode, neededLen + 1);
  770.         // And cap it off anyway just to make sure
  771.         retVal[neededLen] = 0;
  772.     }
  773.      else
  774.     {
  775.         retVal = new char[1];
  776.         retVal[0] = 0;
  777.     }
  778.     return retVal;
  779. }
  780. char* Win32LCPTranscoder::transcode(const XMLCh* const toTranscode,
  781.                                     MemoryManager* const manager)
  782. {
  783.     if (!toTranscode)
  784.         return 0;
  785.     char* retVal = 0;
  786.     if (*toTranscode)
  787.     {
  788.         // Calc the needed size
  789.         const unsigned int neededLen = ::wcstombs(0, toTranscode, 0);
  790.         if (neededLen == (unsigned int)-1)
  791.             return 0;
  792.         // Allocate a buffer of that size plus one for the null and transcode
  793.         retVal = (char*) manager->allocate((neededLen + 1) * sizeof(char)); //new char[neededLen + 1];
  794.         ::wcstombs(retVal, toTranscode, neededLen + 1);
  795.         // And cap it off anyway just to make sure
  796.         retVal[neededLen] = 0;
  797.     }
  798.      else
  799.     {
  800.         retVal = (char*) manager->allocate(sizeof(char)); //new char[1];
  801.         retVal[0] = 0;
  802.     }
  803.     return retVal;
  804. }
  805. // Return value using global operator new
  806. // Revisit: deprecate ?
  807. XMLCh* Win32LCPTranscoder::transcode(const char* const toTranscode)
  808. {
  809.     if (!toTranscode)
  810.         return 0;
  811.     XMLCh* retVal = 0;
  812.     if (*toTranscode)
  813.     {
  814.         // Calculate the buffer size required
  815.         const unsigned int neededLen = calcRequiredSize(toTranscode);
  816.         if (neededLen == 0)
  817.         {
  818.             retVal = new XMLCh[1];
  819.             retVal[0] = 0;
  820.             return retVal;
  821.         }
  822.         // Allocate a buffer of that size plus one for the null and transcode
  823.         retVal = new XMLCh[neededLen + 1];
  824.         ::mbstowcs(retVal, toTranscode, neededLen + 1);
  825.         // Cap it off just to make sure. We are so paranoid!
  826.         retVal[neededLen] = 0;
  827.     }
  828.      else
  829.     {
  830.         retVal = new XMLCh[1];
  831.         retVal[0] = 0;
  832.     }
  833.     return retVal;
  834. }
  835. XMLCh* Win32LCPTranscoder::transcode(const char* const toTranscode,
  836.                                      MemoryManager* const manager)
  837. {
  838.     if (!toTranscode)
  839.         return 0;
  840.     XMLCh* retVal = 0;
  841.     if (*toTranscode)
  842.     {
  843.         // Calculate the buffer size required
  844.         const unsigned int neededLen = calcRequiredSize(toTranscode);
  845.         if (neededLen == 0)
  846.         {
  847.             retVal = (XMLCh*) manager->allocate(sizeof(XMLCh)); //new XMLCh[1];
  848.             retVal[0] = 0;
  849.             return retVal;
  850.         }
  851.         // Allocate a buffer of that size plus one for the null and transcode
  852.         retVal = (XMLCh*) manager->allocate((neededLen + 1) * sizeof(XMLCh)); //new XMLCh[neededLen + 1];
  853.         ::mbstowcs(retVal, toTranscode, neededLen + 1);
  854.         // Cap it off just to make sure. We are so paranoid!
  855.         retVal[neededLen] = 0;
  856.     }
  857.      else
  858.     {
  859.         retVal = (XMLCh*) manager->allocate(sizeof(XMLCh*)); //new XMLCh[1];
  860.         retVal[0] = 0;
  861.     }
  862.     return retVal;
  863. }
  864. bool Win32LCPTranscoder::transcode( const   char* const     toTranscode
  865.                                     ,       XMLCh* const    toFill
  866.                                     , const unsigned int    maxChars)
  867. {
  868.     // Check for a couple of psycho corner cases
  869.     if (!toTranscode || !maxChars)
  870.     {
  871.         toFill[0] = 0;
  872.         return true;
  873.     }
  874.     if (!*toTranscode)
  875.     {
  876.         toFill[0] = 0;
  877.         return true;
  878.     }
  879.     // This one has a fixed size output, so try it and if it fails it fails
  880.     if (::mbstowcs(toFill, toTranscode, maxChars + 1) == size_t(-1))
  881.         return false;
  882.     return true;
  883. }
  884. bool Win32LCPTranscoder::transcode( const   XMLCh* const    toTranscode
  885.                                     ,       char* const     toFill
  886.                                     , const unsigned int    maxBytes)
  887. {
  888.     // Watch for a couple of pyscho corner cases
  889.     if (!toTranscode || !maxBytes)
  890.     {
  891.         toFill[0] = 0;
  892.         return true;
  893.     }
  894.     if (!*toTranscode)
  895.     {
  896.         toFill[0] = 0;
  897.         return true;
  898.     }
  899.     // This one has a fixed size output, so try it and if it fails it fails
  900.     if (::wcstombs(toFill, toTranscode, maxBytes + 1) == size_t(-1))
  901.         return false;
  902.     // Cap it off just in case
  903.     toFill[maxBytes] = 0;
  904.     return true;
  905. }
  906. XERCES_CPP_NAMESPACE_END