Win32TransService.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:27k
源码类别:

xml/soap/webservice

开发平台:

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