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

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  * 
  4.  * Copyright (c) 1999-2001 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: Iconv400TransService.cpp,v 1.7 2001/06/25 16:27:08 tng Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <util/TranscodingException.hpp>
  63. #include "Iconv400TransService.hpp"
  64. #include <string.h>
  65. #include <qlgcase.h>
  66. #include "iconv_cnv.hpp"
  67. #include "iconv_util.hpp"
  68. #include <qusec.h>
  69. #include <util/XMLUniDefs.hpp>
  70. #include <util/XMLString.hpp>
  71. #include <util/Janitor.hpp>
  72. // ---------------------------------------------------------------------------
  73. //  Local functions
  74. // ---------------------------------------------------------------------------
  75. //
  76. //  When XMLCh and ICU's UChar are not the same size, we have to do a temp
  77. //  conversion of all strings. These local helper methods make that easier.
  78. //
  79. static UChar* convertToUChar(   const   XMLCh* const    toConvert
  80.                                 , const unsigned int    srcLen = 0)
  81. {
  82.     const unsigned int actualLen = srcLen
  83.                                    ? srcLen : XMLString::stringLen(toConvert);
  84.     UChar* tmpBuf = new UChar[srcLen + 1];
  85.     const XMLCh* srcPtr = toConvert;
  86.     UChar* outPtr = tmpBuf;
  87.     while (*srcPtr)
  88.         *outPtr++ = UChar(*srcPtr++);
  89.     *outPtr = 0;
  90.     return tmpBuf;
  91. }
  92. // ---------------------------------------------------------------------------
  93. //  Local, const data
  94. // ---------------------------------------------------------------------------
  95. static const XMLCh gMyServiceId[] =
  96. {
  97.     chLatin_I, chLatin_C, chLatin_O, chLatin_V, chDigit_4, chDigit_0, chDigit_0, chNull
  98. };
  99. // ---------------------------------------------------------------------------
  100. //  IconvTransService: Constructors and Destructor
  101. // ---------------------------------------------------------------------------
  102. Iconv400TransService::Iconv400TransService()
  103. {
  104.     memset((char*)&convertCtlblk,'',sizeof(convertCtlblk));
  105.     convertCtlblk.Type_of_Request = 1;
  106.     convertCtlblk.Case_Request = 0;
  107.     convertCtlblk.CCSID_of_Input_Data = 13488;
  108. }
  109. Iconv400TransService::~Iconv400TransService()
  110. {
  111. }
  112. // ---------------------------------------------------------------------------
  113. //  Iconv400TransService: The virtual transcoding service API
  114. // ---------------------------------------------------------------------------
  115. int Iconv400TransService::compareIString(const   XMLCh* const    comp1
  116.                                          , const XMLCh* const    comp2)
  117. {
  118.     const XMLCh* psz1 = comp1;
  119.     const XMLCh* psz2 = comp2;    
  120.     while (true)
  121.     {
  122.                        
  123.         if (toUnicodeUpper(*psz1) != toUnicodeUpper(*psz2))
  124.             return int(*psz1) - int(*psz2);
  125.         // If either has ended, then they both ended, so equal
  126.         if (!*psz1 || !*psz2)
  127.             break;
  128.         // Move upwards for the next round
  129.         psz1++;
  130.         psz2++;
  131.     }
  132.     return 0;
  133. }
  134. int Iconv400TransService::compareNIString(const  XMLCh* const    comp1
  135.                                           , const XMLCh* const    comp2
  136.                                           , const unsigned int    maxChars)
  137. {
  138.     const XMLCh* psz1 = comp1;
  139.     const XMLCh* psz2 = comp2;
  140.   
  141.     unsigned int curCount = 0;
  142.     while (true)
  143.     {
  144.         // If an inequality, then return the difference
  145.   
  146.         // If an inequality, then return difference
  147.         if (toUnicodeUpper(*psz1) != toUnicodeUpper(*psz2))
  148.             return int(*psz1) - int(*psz2);
  149.         // If either ended, then both ended, so equal
  150.         if (!*psz1 || !*psz2)
  151.             break;
  152.         // Move upwards to next chars
  153.         psz1++;
  154.         psz2++;
  155.         //
  156.         //  Bump the count of chars done. If it equals the count then we 
  157.         //  are equal for the requested count, so break out and return
  158.         //  equal.
  159.         //
  160.         curCount++;
  161.         if (maxChars == curCount)
  162.             break;
  163.     }
  164.     return 0;
  165. }
  166. const XMLCh* Iconv400TransService::getId() const
  167. {
  168.     return gMyServiceId;
  169. }
  170. bool Iconv400TransService::isSpace(const XMLCh toCheck) const
  171. {
  172.     //   The following are Unicode Space characters
  173.     //
  174.     if ((toCheck == 0x09)
  175.     ||  (toCheck == 0x0A)
  176.     ||  (toCheck == 0x0D)
  177.     ||  (toCheck == 0x20)
  178.     ||  (toCheck == 0xA0)
  179.     ||  ((toCheck >= 0x2000) && (toCheck <= 0x200B))
  180.     ||  (toCheck == 0x3000)
  181.     ||  (toCheck == 0xFEFF))
  182.     {
  183.         return true;
  184.     }
  185.     else return false;
  186. }
  187. XMLLCPTranscoder* Iconv400TransService::makeNewLCPTranscoder()
  188. {
  189.     //
  190.     //  Try to create a default converter. If it fails, return a null pointer
  191.     //  which will basically cause the system to give up because we really can't
  192.     //  do anything without one.
  193.     //
  194.     UErrorCode uerr = U_ZERO_ERROR;
  195.     UConverter* converter = ucnv_open(NULL, &uerr);
  196.     if (!converter)
  197.         return 0;
  198.     // That went ok, so create an Iconv LCP transcoder wrapper and return it
  199.     return new Iconv400LCPTranscoder(converter);
  200. }
  201. bool Iconv400TransService::supportsSrcOfs() const
  202. {
  203.     // This implementation supports source offset information
  204.     return true;
  205. }
  206. void Iconv400TransService::upperCase(XMLCh* const toUpperCase) const
  207. {
  208.     XMLCh* outPtr = toUpperCase;
  209.     while (*outPtr)
  210.     {
  211.         *outPtr = toUnicodeUpper(*outPtr);
  212.         outPtr++;
  213.     }
  214. }
  215. // ---------------------------------------------------------------------------
  216. //  Iconv400TransService: The virtual transcoding service API
  217. // ---------------------------------------------------------------------------
  218. XMLCh Iconv400TransService::toUnicodeUpper(XMLCh comp1) const
  219. {
  220.     XMLCh chRet;
  221.     struct {
  222.              int bytes_available;
  223.              int bytes_used;
  224.              char exception_id[7];
  225.              char reserved;
  226.              char exception_data[15];
  227.             } error_code;
  228.      error_code.bytes_available = sizeof(error_code);
  229.  
  230.     long charlen =2;
  231.     QlgConvertCase((char*)&convertCtlblk,
  232.                        (char*)&comp1,
  233.                        (char*)&chRet,
  234.                        (long*)&charlen,
  235.                        (char*)&error_code);
  236.     return chRet;
  237. }
  238. // ---------------------------------------------------------------------------
  239. //  Iconv400TransService: The protected virtual transcoding service API
  240. // ---------------------------------------------------------------------------
  241. XMLTranscoder*
  242. Iconv400TransService::makeNewXMLTranscoder(  const   XMLCh* const            encodingName
  243.                                         ,       XMLTransService::Codes& resValue
  244.                                         , const unsigned int            blockSize)
  245. {
  246.     UErrorCode uerr = U_ZERO_ERROR;
  247.     UConverter* converter = ucnv_openU(encodingName, &uerr);
  248.     if (!converter)
  249.     {
  250.         resValue = XMLTransService::UnsupportedEncoding;
  251.         return 0;
  252.     }
  253.     return new Iconv400Transcoder(encodingName, converter, blockSize);
  254. }
  255. // ---------------------------------------------------------------------------
  256. //  IconvTranscoder: Constructors and Destructor
  257. // ---------------------------------------------------------------------------
  258. Iconv400Transcoder::Iconv400Transcoder(const  XMLCh* const        encodingName
  259.                             ,       UConverter* const   toAdopt
  260.                             , const unsigned int        blockSize) :
  261.     XMLTranscoder(encodingName, blockSize)
  262.     , fConverter(toAdopt)
  263.     , fFixed(false)
  264.     , fSrcOffsets(0)
  265. {
  266.     // If there is a block size, then allocate our source offset array
  267.     if (blockSize)
  268.         fSrcOffsets = new long[blockSize];
  269.     // Remember if its a fixed size encoding
  270.     fFixed = (ucnv_getMaxCharSize(fConverter) == ucnv_getMinCharSize(fConverter));
  271. }
  272. Iconv400Transcoder::~Iconv400Transcoder()
  273. {
  274.     delete [] fSrcOffsets;
  275.     // If there is a converter, ask Iconv400 to clean it up
  276.     if (fConverter)
  277.     {
  278.         // <TBD> Does this actually delete the structure???
  279.         ucnv_close(fConverter);
  280.         fConverter = 0;
  281.     }
  282. }
  283. XMLCh Iconv400Transcoder::transcodeOne(  const   XMLByte* const  srcData
  284.                                     , const unsigned int    srcBytes
  285.                                     ,       unsigned int&   bytesEaten)
  286. {
  287.     // Check for stupid stuff
  288.     if (!srcBytes)
  289.         return 0;
  290.     UErrorCode err = U_ZERO_ERROR;
  291.     const XMLByte* startSrc = srcData;
  292.     const XMLCh chRet = ucnv_getNextUChar
  293.     (
  294.         fConverter
  295.         , (const char**)&startSrc
  296.         , (const char*)((srcData + srcBytes) - 1)
  297.         , &err
  298.     );
  299.     // Bail out if an error
  300.     if (U_FAILURE(err))
  301.         return 0;
  302.     // Calculate the bytes eaten and return the char
  303.     bytesEaten = startSrc - srcData;
  304.     return chRet;
  305. }
  306. unsigned int
  307. Iconv400Transcoder::transcodeXML(const   XMLByte* const          srcData
  308.                             , const unsigned int            srcCount
  309.                             ,       XMLCh* const            toFill
  310.                             , const unsigned int            maxChars
  311.                             ,       unsigned int&           bytesEaten
  312.                             ,       unsigned char* const    charSizes)
  313. {
  314.     // If debugging, insure the block size is legal
  315.     #if defined(XML4C_DEBUG)
  316.     checkBlockSize(maxChars);
  317.     #endif
  318.     // Set up pointers to the source and destination buffers.
  319.     UChar*          startTarget = toFill;
  320.     const XMLByte*  startSrc = srcData;
  321.     const XMLByte*  endSrc = srcData + srcCount;
  322.     //
  323.     //  Transoode the buffer.  Buffer overflow errors are normal, occuring
  324.     //  when the raw input buffer holds more characters than will fit in
  325.     //  the Unicode output buffer.
  326.     //
  327.     UErrorCode  err = U_ZERO_ERROR;
  328.     ucnv_toUnicode
  329.     (
  330.         fConverter
  331.         , &startTarget
  332.         , toFill + maxChars
  333.         , (const char**)&startSrc
  334.         , (const char*)endSrc
  335.         , (fFixed ? 0 : fSrcOffsets)
  336.         , false
  337.         , &err
  338.     );
  339.     if ((err != U_ZERO_ERROR) && (err != U_BUFFER_OVERFLOW_ERROR))
  340.         ThrowXML(TranscodingException, XMLExcepts::Trans_Unrepresentable);
  341.     // Calculate the bytes eaten and store in caller's param
  342.     bytesEaten = startSrc - srcData;
  343.     // And the characters decoded
  344.     const unsigned int charsDecoded = startTarget - toFill;
  345.     //
  346.     //  Translate the array of char offsets into an array of character
  347.     //  sizes, which is what the transcoder interface semantics requires.
  348.     //  If its fixed, then we can optimize it.
  349.     //
  350.     if (fFixed)
  351.     {
  352.         const unsigned char fillSize = (unsigned char)ucnv_getMaxCharSize(fConverter);;
  353.         memset(charSizes, fillSize, maxChars);
  354.     }
  355.      else
  356.     {
  357.         //
  358.         //  We have to convert the series of offsets into a series of
  359.         //  sizes. If just one char was decoded, then its the total bytes
  360.         //  eaten. Otherwise, do a loop and subtract out each element from
  361.         //  its previous element.
  362.         //
  363.         if (charsDecoded == 1)
  364.         {
  365.             charSizes[0] = (unsigned char)bytesEaten;
  366.         }
  367.          else
  368.         {
  369.             //  ICU does not return an extra element to allow us to figure
  370.             //  out the last char size, so we have to compute it from the
  371.             //  total bytes used.
  372.             unsigned int index;
  373.             for (index = 0; index < charsDecoded - 1; index++)
  374.             {
  375.                 charSizes[index] = (unsigned char)(fSrcOffsets[index + 1]
  376.                                                     - fSrcOffsets[index]);
  377.             }
  378.             if( charsDecoded > 0 ) {
  379.                 charSizes[charsDecoded - 1] = (unsigned char)(bytesEaten
  380.                                               - fSrcOffsets[charsDecoded - 1]);
  381.             }
  382.         }
  383.     }
  384.     // Return the chars we put into the target buffer
  385.     return charsDecoded;
  386. }
  387. // ---------------------------------------------------------------------------
  388. //  Iconv400Transcoder: The virtual transcoder API
  389. // ---------------------------------------------------------------------------
  390. unsigned int
  391. Iconv400Transcoder::transcodeFrom(const  XMLByte* const          srcData
  392.                             , const unsigned int            srcCount
  393.                             ,       XMLCh* const            toFill
  394.                             , const unsigned int            maxChars
  395.                             ,       unsigned int&           bytesEaten
  396.                             ,       unsigned char* const    charSizes)
  397. {
  398.     // If debugging, insure the block size is legal
  399.     // Set up pointers to the start and end of the source buffer
  400.     const XMLByte*  startSrc = srcData;
  401.     const XMLByte*  endSrc = srcData + srcCount;
  402.     //
  403.     //  And now do the target buffer. This works differently according to
  404.     //  whether XMLCh and UChar are the same size or not.
  405.     //
  406.     UChar* startTarget;
  407.     if (sizeof(XMLCh) == sizeof(UChar))
  408.         startTarget = (UChar*)toFill;
  409.      else
  410.         startTarget = new UChar[maxChars];
  411.     UChar* orgTarget = startTarget;
  412.     //
  413.     //  Transoode the buffer.  Buffer overflow errors are normal, occuring
  414.     //  when the raw input buffer holds more characters than will fit in
  415.     //  the Unicode output buffer.
  416.     //
  417.     UErrorCode  err = U_ZERO_ERROR;
  418.     ucnv_toUnicode
  419.     (
  420.         fConverter
  421.         , &startTarget
  422.         , startTarget + maxChars
  423.         , (const char**)&startSrc
  424.         , (const char*)endSrc
  425.         , (fFixed ? 0 : (int32_t*)fSrcOffsets)
  426.         , false
  427.         , &err
  428.     );
  429.     if ((err != U_ZERO_ERROR) && (err != U_INDEX_OUTOFBOUNDS_ERROR))
  430.     {
  431.         if (orgTarget != (UChar*)toFill)
  432.             delete [] orgTarget;
  433.         if (fFixed)
  434.         {
  435.             XMLCh tmpBuf[16];
  436.             XMLString::binToText((unsigned int)(*startTarget), tmpBuf, 16, 16);
  437.             ThrowXML2
  438.             (
  439.                 TranscodingException
  440.                 , XMLExcepts::Trans_BadSrcCP
  441.                 , tmpBuf
  442.                 , getEncodingName()
  443.             );
  444.         }
  445.          else
  446.         {
  447.             ThrowXML(TranscodingException, XMLExcepts::Trans_BadSrcSeq);
  448.         }
  449.     }
  450.     // Calculate the bytes eaten and store in caller's param
  451.     bytesEaten = startSrc - srcData;
  452.     // And the characters decoded
  453.     const unsigned int charsDecoded = startTarget - orgTarget;
  454.     //
  455.     //  Translate the array of char offsets into an array of character
  456.     //  sizes, which is what the transcoder interface semantics requires.
  457.     //  If its fixed, then we can optimize it.
  458.     //
  459.     if (fFixed)
  460.     {
  461.         const unsigned char fillSize = (unsigned char)ucnv_getMaxCharSize(fConverter);;
  462.         memset(charSizes, fillSize, maxChars);
  463.     }
  464.      else
  465.     {
  466.         //
  467.         //  We have to convert the series of offsets into a series of
  468.         //  sizes. If just one char was decoded, then its the total bytes
  469.         //  eaten. Otherwise, do a loop and subtract out each element from
  470.         //  its previous element.
  471.         //
  472.         if (charsDecoded == 1)
  473.         {
  474.             charSizes[0] = (unsigned char)bytesEaten;
  475.         }
  476.          else
  477.         {
  478.             //  ICU does not return an extra element to allow us to figure
  479.             //  out the last char size, so we have to compute it from the
  480.             //  total bytes used.
  481.             unsigned int index;
  482.             for (index = 0; index < charsDecoded - 1; index++)
  483.             {
  484.                 charSizes[index] = (unsigned char)(fSrcOffsets[index + 1]
  485.                                                     - fSrcOffsets[index]);
  486.             }
  487.             if( charsDecoded > 0 ) {
  488.                 charSizes[charsDecoded - 1] = (unsigned char)(bytesEaten
  489.                                               - fSrcOffsets[charsDecoded - 1]);
  490.             }
  491.         }
  492.     }
  493.     //
  494.     //  If XMLCh and UChar are not the same size, then we need to copy over
  495.     //  the temp buffer to the new one.
  496.     //
  497.     if (sizeof(UChar) != sizeof(XMLCh))
  498.     {
  499.         XMLCh* outPtr = toFill;
  500.         startTarget = orgTarget;
  501.         for (unsigned int index = 0; index < charsDecoded; index++)
  502.             *outPtr++ = XMLCh(*startTarget++);
  503.         // And delete the temp buffer
  504.         delete [] orgTarget;
  505.     }
  506.     // Return the chars we put into the target buffer
  507.     return charsDecoded;
  508. }
  509. unsigned int
  510. Iconv400Transcoder::transcodeTo( const   XMLCh* const    srcData
  511.                             , const unsigned int    srcCount
  512.                             ,       XMLByte* const  toFill
  513.                             , const unsigned int    maxBytes
  514.                             ,       unsigned int&   charsEaten
  515.                             , const UnRepOpts       options)
  516. {
  517.     //
  518.     //  Get a pointer to the buffer to transcode. If UChar and XMLCh are
  519.     //  the same size here, then use the original. Else, create a temp
  520.     //  one and put a janitor on it.
  521.     //
  522.     const UChar* srcPtr;
  523.     UChar* tmpBufPtr = 0;
  524.     if (sizeof(XMLCh) == sizeof(UChar))
  525.     {
  526.         srcPtr = (const UChar*)srcData;
  527.     }
  528.      else
  529.     {
  530.         tmpBufPtr = convertToUChar(srcData, srcCount);
  531.         srcPtr = tmpBufPtr;
  532.     }
  533.     ArrayJanitor<UChar> janTmpBuf(tmpBufPtr);
  534.     //
  535.     //  Set the appropriate callback so that it will either fail or use
  536.     //  the rep char. Remember the old one so we can put it back.
  537.     //
  538.     UErrorCode  err = U_ZERO_ERROR;
  539.     //
  540.     //  Ok, lets transcode as many chars as we we can in one shot. The
  541.     //  ICU API gives enough info not to have to do this one char by char.
  542.     //
  543.     XMLByte*        startTarget = toFill;
  544.     const UChar*    startSrc = srcPtr;
  545.     err = U_ZERO_ERROR;
  546.     ucnv_fromUnicode
  547.     (
  548.         fConverter
  549.         , (char**)&startTarget
  550.         , (char*)(startTarget + maxBytes)
  551.         , &startSrc
  552.         , srcPtr + srcCount
  553.         , 0
  554.         , false
  555.         , &err
  556.     );
  557.     if (!err)
  558.     {
  559.         XMLCh tmpBuf[16];
  560.         XMLString::binToText((unsigned int)*startSrc, tmpBuf, 16, 16);
  561.         ThrowXML2
  562.         (
  563.             TranscodingException
  564.             , XMLExcepts::Trans_Unrepresentable
  565.             , tmpBuf
  566.             , getEncodingName()
  567.         );
  568.     }
  569.     // Fill in the chars we ate from the input
  570.     charsEaten = startSrc - srcPtr;
  571.     // Return the chars we stored
  572.     return startTarget - toFill;
  573. }
  574. bool Iconv400Transcoder::canTranscodeTo(const unsigned int toCheck) const
  575. {
  576.     //
  577.     //  If the passed value is really a surrogate embedded together, then
  578.     //  we need to break it out into its two chars. Else just one. While
  579.     //  we are ate it, convert them to UChar format if required.
  580.     //
  581.     UChar           srcBuf[2];
  582.     unsigned int    srcCount = 1;
  583.     if (toCheck & 0xFFFF0000)
  584.     {
  585.         srcBuf[0] = UChar((toCheck >> 10) + 0xD800);
  586.         srcBuf[1] = UChar(toCheck & 0x3FF) + 0xDC00;
  587.         srcCount++;
  588.     }
  589.      else
  590.     {
  591.         srcBuf[0] = UChar(toCheck);
  592.     }
  593.     // Set upa temp buffer to format into. Make it more than big enough
  594.     char            tmpBuf[64];
  595.     char*           startTarget = tmpBuf;
  596.     const UChar*    startSrc = srcBuf;
  597.     UErrorCode  err = U_ZERO_ERROR;
  598.    
  599.     ucnv_fromUnicode
  600.     (
  601.         fConverter
  602.         , &startTarget
  603.         , startTarget + 64
  604.         , &startSrc
  605.         , srcBuf + srcCount
  606.         , 0
  607.         , false
  608.         , &err
  609.     );
  610.  
  611.     return err;
  612. }
  613. // ---------------------------------------------------------------------------
  614. //  IconvLCPTranscoder: Constructors and Destructor
  615. // ---------------------------------------------------------------------------
  616. Iconv400LCPTranscoder::Iconv400LCPTranscoder(UConverter* const toAdopt) :
  617.     fConverter(toAdopt)
  618. {
  619. }
  620. Iconv400LCPTranscoder::~Iconv400LCPTranscoder()
  621. {
  622.     // If there is a converter, ask Iconv to clean it up
  623.     if (fConverter)
  624.     {
  625.         // <TBD> Does this actually delete the structure???
  626.         ucnv_close(fConverter);
  627.         fConverter = 0;
  628.     }
  629. }
  630. // ---------------------------------------------------------------------------
  631. //  Iconv400LCPTranscoder: Constructors and Destructor
  632. // ---------------------------------------------------------------------------
  633. unsigned int Iconv400LCPTranscoder::calcRequiredSize(const XMLCh* const srcText)
  634. {
  635.     if (!srcText)
  636.         return 0;
  637.     // Lock and attempt the calculation
  638.     UErrorCode err = U_ZERO_ERROR;
  639.     int32_t targetCap;
  640.     {
  641.         XMLMutexLock lockConverter(&fMutex);
  642.         targetCap = ucnv_fromUChars
  643.         (
  644.             fConverter
  645.             , 0
  646.             , 0
  647.             , srcText
  648.             , &err
  649.         );
  650.     }
  651.     if (err != U_BUFFER_OVERFLOW_ERROR)
  652.         return 0;
  653.     return (unsigned int)targetCap;
  654. }
  655. unsigned int Iconv400LCPTranscoder::calcRequiredSize(const char* const srcText)
  656. {
  657.     if (!srcText)
  658.         return 0;
  659.     int32_t targetCap;
  660.     UErrorCode err = U_ZERO_ERROR;
  661.     {
  662.         XMLMutexLock lockConverter(&fMutex);
  663.         targetCap = ucnv_toUChars
  664.         (
  665.             fConverter
  666.             , 0
  667.             , 0
  668.             , srcText
  669.             , strlen(srcText)
  670.             , &err
  671.         );
  672.     }
  673.     if (err != U_BUFFER_OVERFLOW_ERROR)
  674.         return 0;
  675.     // Subtract one since it includes the terminator space
  676.     return (unsigned int)(targetCap - 1);
  677. }
  678. char* Iconv400LCPTranscoder::transcode(const XMLCh* const toTranscode)
  679. {
  680.     char* retBuf = 0;
  681.     // Check for a couple of special cases
  682.     if (!toTranscode)
  683.         return 0;
  684.     if (!*toTranscode)
  685.     {
  686.         retBuf = new char[1];
  687.         retBuf[0] = 0;
  688.         return retBuf;
  689.     }
  690.     // Caculate a return buffer size not too big, but less likely to overflow
  691.     int32_t targetLen = (int32_t)(u_strlen(toTranscode) * 1.25);
  692.     // Allocate the return buffer
  693.     retBuf = new char[targetLen + 1];
  694.     // Lock now while we call the converter.
  695.     UErrorCode err = U_ZERO_ERROR;
  696.     int32_t targetCap;
  697.     {
  698.         XMLMutexLock lockConverter(&fMutex);
  699.         //Convert the Unicode string to char*
  700.         targetCap = ucnv_fromUChars
  701.         (
  702.             fConverter
  703.             , retBuf
  704.             , targetLen + 1
  705.             , toTranscode
  706.             , &err
  707.         );
  708.     }
  709.     // If targetLen is not enough then buffer overflow might occur
  710.     if (err == U_BUFFER_OVERFLOW_ERROR)
  711.     {
  712.         // Reset the error, delete the old buffer, allocate a new one, and try again
  713.         err = U_ZERO_ERROR;
  714.         delete [] retBuf;
  715.         retBuf = new char[targetCap];
  716.         // Lock again before we retry
  717.         XMLMutexLock lockConverter(&fMutex);
  718.         targetCap = ucnv_fromUChars
  719.         (
  720.             fConverter
  721.             , retBuf
  722.             , targetCap
  723.             , toTranscode
  724.             , &err
  725.         );
  726.     }
  727.     if (U_FAILURE(err))
  728.     {
  729.         delete [] retBuf;
  730.         return 0;
  731.     }
  732.     // Cap it off and return
  733.     retBuf[targetCap] = 0;
  734.     return retBuf;
  735. }
  736. XMLCh* Iconv400LCPTranscoder::transcode(const char* const toTranscode)
  737. {
  738.     // Watch for a few pyscho corner cases
  739.     if (!toTranscode)
  740.         return 0;
  741.     XMLCh* retVal = 0;
  742.     if (!*toTranscode)
  743.     {
  744.         retVal = new XMLCh[1];
  745.         retVal[0] = 0;
  746.         return retVal;
  747.     }
  748.     //
  749.     //  Get the length of the string to transcode. The Unicode string will
  750.     //  almost always be no more chars than were in the source, so this is
  751.     //  the best guess as to the storage needed.
  752.     //
  753.     const int32_t srcLen = (int32_t)strlen(toTranscode);
  754.     // Allocate unicode string of equivalent length in unicode bytes
  755.     retVal = new XMLCh[srcLen+1];
  756.     // Now lock while we do these calculations
  757.     UErrorCode err = U_ZERO_ERROR;
  758.     {
  759.         XMLMutexLock lockConverter(&fMutex);
  760.         //
  761.         //  Here we don't know what the target length will be so use 0 and
  762.         //  expect an U_BUFFER_OVERFLOW_ERROR in which case it'd get resolved
  763.         //  by the correct capacity value.
  764.         //
  765.         int32_t targetCap;
  766.         targetCap = ucnv_toUChars
  767.         (
  768.             fConverter
  769.             , retVal
  770.             , srcLen+1
  771.             , toTranscode
  772.             , srcLen
  773.             , &err
  774.         );
  775.         if (err != U_BUFFER_OVERFLOW_ERROR)
  776. {
  777.         err = U_ZERO_ERROR;
  778.         retVal = new XMLCh[targetCap];
  779.         ucnv_toUChars
  780.         (
  781.             fConverter
  782.             , retVal
  783.             , targetCap
  784.             , toTranscode
  785.             , srcLen
  786.             , &err
  787.            );
  788.  }
  789.    }
  790.     if (U_FAILURE(err))
  791.     {
  792.         // Clean up if we got anything allocated
  793.         delete [] retVal;
  794.         return 0;
  795.     }
  796.     return retVal;
  797. }
  798. bool Iconv400LCPTranscoder::transcode(const  char* const     toTranscode
  799.                                 ,       XMLCh* const    toFill
  800.                                 , const unsigned int    maxChars)
  801. {
  802.     // Check for a couple of psycho corner cases
  803.     if (!toTranscode || !maxChars)
  804.     {
  805.         toFill[0] = 0;
  806.         return true;
  807.     }
  808.     if (!*toTranscode)
  809.     {
  810.         toFill[0] = 0;
  811.         return true;
  812.     }
  813.     // Lock and do the transcode operation
  814.     UErrorCode err = U_ZERO_ERROR;
  815.     const int32_t srcLen = (int32_t)strlen(toTranscode);
  816.     {
  817.         XMLMutexLock lockConverter(&fMutex);
  818.         ucnv_toUChars
  819.         (
  820.             fConverter
  821.             , toFill
  822.             , maxChars + 1
  823.             , toTranscode
  824.             , srcLen
  825.             , &err
  826.         );
  827.     }
  828.     if (U_FAILURE(err))
  829.         return false;
  830.     return true;
  831. }
  832. bool Iconv400LCPTranscoder::transcode(   const   XMLCh* const    toTranscode
  833.                                     ,       char* const     toFill
  834.                                     , const unsigned int    maxChars)
  835. {
  836.     // Watch for a few psycho corner cases
  837.     if (!toTranscode || !maxChars)
  838.     {
  839.         toFill[0] = 0;
  840.         return true;
  841.     }
  842.     if (!*toTranscode)
  843.     {
  844.         toFill[0] = 0;
  845.         return true;
  846.     }
  847.     UErrorCode err = U_ZERO_ERROR;
  848.     int32_t targetCap;
  849.     {
  850.         XMLMutexLock lockConverter(&fMutex);
  851.         targetCap = ucnv_fromUChars
  852.         (
  853.             fConverter
  854.             , toFill
  855.             , maxChars + 1
  856.             , toTranscode
  857.             , &err
  858.         );
  859.     }
  860.     if (U_FAILURE(err))
  861.         return false;
  862.     toFill[targetCap] = 0;
  863.     return true;
  864. }