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

词法分析

开发平台:

Visual C++

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