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

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: XMLUTF8Transcoder.cpp,v 1.11 2000/07/25 22:28:16 aruna1 Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <util/TranscodingException.hpp>
  63. #include <util/XMLString.hpp>
  64. #include <util/XMLUniDefs.hpp>
  65. #include <util/XMLUTF8Transcoder.hpp>
  66. #include <util/UTFDataFormatException.hpp>
  67. // ---------------------------------------------------------------------------
  68. //  Local static data
  69. //
  70. //  gUTFBytes
  71. //      A list of counts of trailing bytes for each initial byte in the input.
  72. //
  73. //  gUTFOffsets
  74. //      A list of values to offset each result char type, according to how
  75. //      many source bytes when into making it.
  76. //
  77. //  gFirstByteMark
  78. //      A list of values to mask onto the first byte of an encoded sequence,
  79. //      indexed by the number of bytes used to create the sequence.
  80. // ---------------------------------------------------------------------------
  81. static const XMLByte gUTFBytes[256] =
  82. {
  83.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  84.     ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  85.     ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  86.     ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  87.     ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  88.     ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  89.     ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  90.     ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  91.     ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  92.     ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  93.     ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  94.     ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  95.     ,   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  96.     ,   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  97.     ,   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  98.     ,   3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
  99. };
  100. static const XMLUInt32 gUTFOffsets[6] =
  101. {
  102.     0, 0x3080, 0xE2080, 0x3C82080, 0xFA082080, 0x82082080
  103. };
  104. static const XMLByte gFirstByteMark[7] =
  105. {
  106.     0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
  107. };
  108. // ---------------------------------------------------------------------------
  109. //  XMLUTF8Transcoder: Constructors and Destructor
  110. // ---------------------------------------------------------------------------
  111. XMLUTF8Transcoder::XMLUTF8Transcoder(const  XMLCh* const    encodingName
  112.                                     , const unsigned int    blockSize) :
  113.     XMLTranscoder(encodingName, blockSize)
  114. {
  115. }
  116. XMLUTF8Transcoder::~XMLUTF8Transcoder()
  117. {
  118. }
  119. // ---------------------------------------------------------------------------
  120. //  XMLUTF8Transcoder: Implementation of the transcoder API
  121. // ---------------------------------------------------------------------------
  122. unsigned int
  123. XMLUTF8Transcoder::transcodeFrom(const  XMLByte* const          srcData
  124.                                 , const unsigned int            srcCount
  125.                                 ,       XMLCh* const            toFill
  126.                                 , const unsigned int            maxChars
  127.                                 ,       unsigned int&           bytesEaten
  128.                                 ,       unsigned char* const    charSizes)
  129. {
  130.     // Watch for pathological scenario. Shouldn't happen, but...
  131.     if (!srcCount || !maxChars)
  132.         return 0;
  133.     // If debugging, make sure that the block size is legal
  134.     #if defined(XERCES_DEBUG)
  135.     checkBlockSize(maxChars);
  136.     #endif
  137.     //
  138.     //  Get pointers to our start and end points of the input and output
  139.     //  buffers.
  140.     //
  141.     const XMLByte*  srcPtr = srcData;
  142.     const XMLByte*  srcEnd = srcPtr + srcCount;
  143.     XMLCh*          outPtr = toFill;
  144.     XMLCh*          outEnd = outPtr + maxChars;
  145.     unsigned char*  sizePtr = charSizes;
  146.  
  147.     
  148.     //
  149.     //  We now loop until we either run out of input data, or room to store
  150.     //  output chars.
  151.     //
  152.     while ((srcPtr < srcEnd) && (outPtr < outEnd))
  153.     {
  154.         // Get the next leading byte out
  155.         const XMLByte firstByte = *srcPtr;
  156.         // Special-case ASCII, which is a leading byte value of <= 127
  157.         if (firstByte <= 127)
  158.         {
  159.             *outPtr++ = XMLCh(firstByte);
  160.             srcPtr++;
  161.             *sizePtr++ = 1;
  162.             continue;
  163.         }
  164.         // See how many trailing src bytes this sequence is going to require
  165.         const unsigned int trailingBytes = gUTFBytes[firstByte];
  166.         //
  167.         //  If there are not enough source bytes to do this one, then we
  168.         //  are done. Note that we done >= here because we are implicitly
  169.         //  counting the 1 byte we get no matter what.
  170.         //
  171.         //  If we break out here, then there is nothing to undo since we
  172.         //  haven't updated any pointers yet.
  173.         //
  174.         if (srcPtr + trailingBytes >= srcEnd)
  175.             break;
  176.         // Looks ok, so lets build up the value
  177.         XMLUInt32 tmpVal = 0;
  178.         switch(trailingBytes)
  179.         {
  180.             case 5 : tmpVal += *srcPtr++; tmpVal <<= 6;
  181.             case 4 : tmpVal += *srcPtr++; tmpVal <<= 6;
  182.             case 3 : tmpVal += *srcPtr++; tmpVal <<= 6;
  183.             case 2 : tmpVal += *srcPtr++; tmpVal <<= 6;
  184.             case 1 : tmpVal += *srcPtr++; tmpVal <<= 6;
  185.             case 0 : tmpVal += *srcPtr++;
  186.                      break;
  187.             default :
  188.                 ThrowXML(TranscodingException, XMLExcepts::Trans_BadSrcSeq);
  189.         }
  190.         tmpVal -= gUTFOffsets[trailingBytes];
  191.         //
  192.         //  If it will fit into a single char, then put it in. Otherwise
  193.         //  encode it as a surrogate pair. If its not valid, use the
  194.         //  replacement char.
  195.         //
  196.         if (!(tmpVal & 0xFFFF0000))
  197.         {
  198.             *sizePtr++ = trailingBytes + 1;
  199.             *outPtr++ = XMLCh(tmpVal);
  200.         }
  201.          else if (tmpVal > 0x10FFFF)
  202.         {
  203.             //
  204.             //  If we've gotten more than 32 chars so far, then just break
  205.             //  out for now and lets process those. When we come back in
  206.             //  here again, we'll get no chars and throw an exception. This
  207.             //  way, the error will have a line and col number closer to
  208.             //  the real problem area.
  209.             //
  210.             if ((outPtr - toFill) > 32)
  211.                 break;
  212.             ThrowXML(TranscodingException, XMLExcepts::Trans_BadSrcSeq);
  213.         }
  214.          else
  215.         {
  216.             //
  217.             //  If we have enough room to store the leading and trailing
  218.             //  chars, then lets do it. Else, pretend this one never
  219.             //  happened, and leave it for the next time. Since we don't
  220.             //  update the bytes read until the bottom of the loop, by
  221.             //  breaking out here its like it never happened.
  222.             //
  223.             if (outPtr + 1 >= outEnd)
  224.                 break;
  225.             // Store the leading surrogate char
  226.             tmpVal -= 0x10000;
  227.             *sizePtr++ = trailingBytes + 1;
  228.             *outPtr++ = XMLCh((tmpVal >> 10) + 0xD800);
  229.             //
  230.             //  And then the treailing char. This one accounts for no
  231.             //  bytes eaten from the source, so set the char size for this
  232.             //  one to be zero.
  233.             //
  234.             *sizePtr++ = 0;
  235.             *outPtr++ = XMLCh(tmpVal & 0x3FF) + 0xDC00;
  236.         }
  237.     }
  238.     // Update the bytes eaten
  239.     bytesEaten = srcPtr - srcData;
  240.     // Return the characters read
  241.     return outPtr - toFill;
  242. }
  243. unsigned int
  244. XMLUTF8Transcoder::transcodeTo( const   XMLCh* const    srcData
  245.                                 , const unsigned int    srcCount
  246.                                 ,       XMLByte* const  toFill
  247.                                 , const unsigned int    maxBytes
  248.                                 ,       unsigned int&   charsEaten
  249.                                 , const UnRepOpts       options)
  250. {
  251.     // Watch for pathological scenario. Shouldn't happen, but...
  252.     if (!srcCount || !maxBytes)
  253.         return 0;
  254.     //
  255.     //  Get pointers to our start and end points of the input and output
  256.     //  buffers.
  257.     //
  258.     const XMLCh*    srcPtr = srcData;
  259.     const XMLCh*    srcEnd = srcPtr + srcCount;
  260.     XMLByte*        outPtr = toFill;
  261.     XMLByte*        outEnd = toFill + maxBytes;
  262.     while (srcPtr < srcEnd)
  263.     {
  264.         //
  265.         //  Tentatively get the next char out. We have to get it into a
  266.         //  32 bit value, because it could be a surrogate pair.
  267.         //
  268.         XMLUInt32 curVal = *srcPtr;
  269.         //
  270.         //  If its a leading surrogate, then lets see if we have the trailing
  271.         //  available. If not, then give up now and leave it for next time.
  272.         //
  273.         unsigned int srcUsed = 1;
  274.         if ((curVal >= 0xD800) && (curVal <= 0xDBFF))
  275.         {
  276.             if (srcPtr + 1 >= srcEnd)
  277.                 break;
  278.             // Create the composite surrogate pair
  279.             curVal = ((curVal - 0xD800) << 10)
  280.                     + ((*(srcPtr + 1) - 0xDC00) + 0x10000);
  281.             // And indicate that we ate another one
  282.             srcUsed++;
  283.         }
  284.         // Figure out how many bytes we need
  285.         unsigned int encodedBytes;
  286.         if (curVal < 0x80)
  287.             encodedBytes = 1;
  288.         else if (curVal < 0x800)
  289.             encodedBytes = 2;
  290.         else if (curVal < 0x10000)
  291.             encodedBytes = 3;
  292.         else if (curVal < 0x200000)
  293.             encodedBytes = 4;
  294.         else if (curVal < 0x4000000)
  295.             encodedBytes = 5;
  296.         else if (curVal <= 0x7FFFFFFF)
  297.             encodedBytes = 6;
  298.         else
  299.         {
  300.             // If the options say to throw, then throw
  301.             if (options == UnRep_Throw)
  302.             {
  303.                 XMLCh tmpBuf[16];
  304.                 XMLString::binToText(curVal, tmpBuf, 16, 16);
  305.                 ThrowXML2
  306.                 (
  307.                     TranscodingException
  308.                     , XMLExcepts::Trans_Unrepresentable
  309.                     , tmpBuf
  310.                     , getEncodingName()
  311.                 );
  312.             }
  313.             // Else, use the replacement character
  314.             *outPtr++ = chSpace;
  315.             srcPtr += srcUsed;
  316.             continue;
  317.         }
  318.         //
  319.         //  If we cannot fully get this char into the output buffer,
  320.         //  then leave it for the next time.
  321.         //
  322.         if (outPtr + encodedBytes > outEnd)
  323.             break;
  324.         // We can do it, so update the source index
  325.         srcPtr += srcUsed;
  326.         //
  327.         //  And spit out the bytes. We spit them out in reverse order
  328.         //  here, so bump up the output pointer and work down as we go.
  329.         //
  330.         outPtr += encodedBytes;
  331.         switch(encodedBytes)
  332.         {
  333.             case 6 : *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
  334.                      curVal >>= 6;
  335.             case 5 : *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
  336.                      curVal >>= 6;
  337.             case 4 : *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
  338.                      curVal >>= 6;
  339.             case 3 : *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
  340.                      curVal >>= 6;
  341.             case 2 : *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
  342.                      curVal >>= 6;
  343.             case 1 : *--outPtr = XMLByte
  344.                      (
  345.                         curVal | gFirstByteMark[encodedBytes]
  346.                      );
  347.         }
  348.         // Add the encoded bytes back in again to indicate we've eaten them
  349.         outPtr += encodedBytes;
  350.     }
  351.     // Fill in the chars we ate
  352.     charsEaten = (srcPtr - srcData);
  353.     // And return the bytes we filled in
  354.     return (outPtr - toFill);
  355. }
  356. bool XMLUTF8Transcoder::canTranscodeTo(const unsigned int toCheck) const
  357. {
  358.     // We can represent anything in the Unicode (with surrogates) range
  359.     return (toCheck <= 0x10FFFF);
  360. }