source: icXML/icXML-devel/src/icxercesc/util/XMLUTF8Transcoder.cpp @ 2720

Last change on this file since 2720 was 2720, checked in by cameron, 6 years ago

Initial check-in of icXML 0.8 source files

File size: 26.9 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/**
19 * $Id: XMLUTF8Transcoder.cpp 932887 2010-04-11 13:04:59Z borisk $
20 */
21
22// ---------------------------------------------------------------------------
23//  Includes
24// ---------------------------------------------------------------------------
25
26#include <xercesc/util/TranscodingException.hpp>
27#include <xercesc/util/XMLUTF8Transcoder.hpp>
28#include <xercesc/util/XMLUniDefs.hpp>
29#include <xercesc/internal/XMLReader.hpp>
30#include <xercesc/internal/XMLScanner.hpp>
31#include <xercesc/util/XMLString.hpp>
32
33
34XERCES_CPP_NAMESPACE_BEGIN
35
36// ---------------------------------------------------------------------------
37//  Local static data
38//
39//  gUTFBytes
40//      A list of counts of trailing bytes for each initial byte in the input.
41//
42//  gUTFByteIndicator
43//      For a UTF8 sequence of n bytes, n>=2, the first byte of the
44//      sequence must contain n 1's followed by precisely 1 0 with the
45//      rest of the byte containing arbitrary bits.  This array stores
46//      the required bit pattern for validity checking.
47//  gUTFByteIndicatorTest
48//      When bitwise and'd with the observed value, if the observed
49//      value is correct then a result matching gUTFByteIndicator will
50//      be produced.
51//
52//  gUTFOffsets
53//      A list of values to offset each result char type, according to how
54//      many source bytes when into making it.
55//
56//  gFirstByteMark
57//      A list of values to mask onto the first byte of an encoded sequence,
58//      indexed by the number of bytes used to create the sequence.
59// ---------------------------------------------------------------------------
60static const XMLByte gUTFBytes[256] =
61{
62                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
63        ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
64        ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
65        ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
66        ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
67        ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
68        ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
69        ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
70        ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
71        ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
72        ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
73        ,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
74        ,   0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
75        ,   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
76        ,   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
77        ,   3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
78};
79
80static const XMLByte gUTFByteIndicator[6] =
81{
82        0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
83};
84static const XMLByte gUTFByteIndicatorTest[6] =
85{
86        0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE
87};
88
89static const XMLUInt32 gUTFOffsets[6] =
90{
91        0, 0x3080, 0xE2080, 0x3C82080, 0xFA082080, 0x82082080
92};
93
94static const XMLByte gFirstByteMark[7] =
95{
96        0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
97};
98
99
100
101// ---------------------------------------------------------------------------
102//  XMLUTF8Transcoder: Constructors and Destructor
103// ---------------------------------------------------------------------------
104XMLUTF8Transcoder::XMLUTF8Transcoder(const  XMLCh* const    encodingName
105                                                                        , const XMLSize_t       blockSize
106                                                                        , MemoryManager* const  manager)
107:XMLTranscoder(encodingName, blockSize, manager)
108{
109}
110
111XMLUTF8Transcoder::~XMLUTF8Transcoder()
112{
113}
114
115
116// ---------------------------------------------------------------------------
117//  XMLUTF8Transcoder: Implementation of the transcoder API
118// ---------------------------------------------------------------------------
119XMLSize_t
120XMLUTF8Transcoder::transcodeFrom( const  XMLByte* const         srcData
121                                                                , const XMLSize_t               srcCount
122                                                                ,       XMLCh* const            toFill
123                                                                , const XMLSize_t               maxChars
124                                                                ,       XMLSize_t&              bytesEaten
125                                                                ,       unsigned char* const    charSizes)
126{
127#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
128        // Watch for pathological scenario. Shouldn't happen, but...
129        if (!srcCount || !maxChars)
130                return 0;
131
132        //
133        //  Get pointers to our start and end points of the input and output
134        //  buffers.
135        //
136        const XMLByte*  srcPtr = srcData;
137        const XMLByte*  srcEnd = srcPtr + srcCount;
138        XMLCh*          outPtr = toFill;
139        XMLCh*          outEnd = outPtr + maxChars;
140        unsigned char*  sizePtr = charSizes;
141
142        //
143        //  We now loop until we either run out of input data, or room to store
144        //  output chars.
145        //
146        while ((srcPtr < srcEnd) && (outPtr < outEnd))
147        {
148                // Special-case ASCII, which is a leading byte value of <= 127
149                if (*srcPtr <= 127)
150                {
151                        // Handle ASCII in groups instead of single character at a time.
152                        const XMLByte* srcPtr_save = srcPtr;
153                        const XMLSize_t chunkSize = (srcEnd-srcPtr)<(outEnd-outPtr)?(srcEnd-srcPtr):(outEnd-outPtr);
154                        for(XMLSize_t i=0;i<chunkSize && *srcPtr <= 127;++i)
155                                *outPtr++ = XMLCh(*srcPtr++);
156                        memset(sizePtr,1,srcPtr - srcPtr_save);
157                        sizePtr += srcPtr - srcPtr_save;
158                        if (srcPtr == srcEnd || outPtr == outEnd)
159                                break;
160                }
161
162                // See how many trailing src bytes this sequence is going to require
163                const unsigned int trailingBytes = gUTFBytes[*srcPtr];
164
165                //
166                //  If there are not enough source bytes to do this one, then we
167                //  are done. Note that we done >= here because we are implicitly
168                //  counting the 1 byte we get no matter what.
169                //
170                //  If we break out here, then there is nothing to undo since we
171                //  haven't updated any pointers yet.
172                //
173                if (srcPtr + trailingBytes >= srcEnd)
174                        break;
175
176                // Looks ok, so lets build up the value
177                // or at least let's try to do so--remembering that
178                // we cannot assume the encoding to be valid:
179
180                // first, test first byte
181                if((gUTFByteIndicatorTest[trailingBytes] & *srcPtr) != gUTFByteIndicator[trailingBytes]) {
182                        char pos[2] = {(char)0x31, 0};
183                        char len[2] = {(char)(trailingBytes+0x31), 0};
184                        char byte[2] = {*srcPtr, 0};
185                        ThrowXMLwithMemMgr3(UTFDataFormatException, XMLExcepts::UTF8_FormatError, pos, byte, len, getMemoryManager());
186                }
187
188                /***
189                 * http://www.unicode.org/reports/tr27/
190                 *
191                 * Table 3.1B. lists all of the byte sequences that are legal in UTF-8.
192                 * A range of byte values such as A0..BF indicates that any byte from A0 to BF (inclusive)
193                 * is legal in that position.
194                 * Any byte value outside of the ranges listed is illegal.
195                 * For example,
196                 * the byte sequence <C0 AF> is illegal  since C0 is not legal in the 1st Byte column.
197                 * The byte sequence <E0 9F 80> is illegal since in the row
198                 *    where E0 is legal as a first byte,
199                 *    9F is not legal as a second byte.
200                 * The byte sequence <F4 80 83 92> is legal, since every byte in that sequence matches
201                 * a byte range in a row of the table (the last row).
202                 *
203                 *
204                 * Table 3.1B. Legal UTF-8 Byte Sequences
205                 * Code Points              1st Byte    2nd Byte    3rd Byte    4th Byte
206                 * =========================================================================
207                 * U+0000..U+007F            00..7F
208                 * -------------------------------------------------------------------------
209                 * U+0080..U+07FF            C2..DF      80..BF
210                 *
211                 * -------------------------------------------------------------------------
212                 * U+0800..U+0FFF            E0          A0..BF     80..BF
213                 *                                       --
214                 *
215                 * U+1000..U+FFFF            E1..EF      80..BF     80..BF
216                 *
217                 * --------------------------------------------------------------------------
218                 * U+10000..U+3FFFF          F0          90..BF     80..BF       80..BF
219                 *                                       --
220                 * U+40000..U+FFFFF          F1..F3      80..BF     80..BF       80..BF
221                 * U+100000..U+10FFFF        F4          80..8F     80..BF       80..BF
222                 *                                           --
223                 * ==========================================================================
224                 *
225                 *  Cases where a trailing byte range is not 80..BF are underlined in the table to
226                 *  draw attention to them. These occur only in the second byte of a sequence.
227                 *
228                 ***/
229
230                XMLUInt32 tmpVal = 0;
231
232                switch(trailingBytes)
233                {
234                        case 1 :
235                                // UTF-8:   [110y yyyy] [10xx xxxx]
236                                // Unicode: [0000 0yyy] [yyxx xxxx]
237                                //
238                                // 0xC0, 0xC1 has been filtered out
239                                checkTrailingBytes(*(srcPtr+1), 1, 1);
240
241                                tmpVal = *srcPtr++;
242                                tmpVal <<= 6;
243                                tmpVal += *srcPtr++;
244
245                                break;
246                        case 2 :
247                                // UTF-8:   [1110 zzzz] [10yy yyyy] [10xx xxxx]
248                                // Unicode: [zzzz yyyy] [yyxx xxxx]
249                                //
250                                if (( *srcPtr == 0xE0) && ( *(srcPtr+1) < 0xA0))
251                                {
252                                        char byte0[2] = {*srcPtr    ,0};
253                                        char byte1[2] = {*(srcPtr+1),0};
254
255                                        ThrowXMLwithMemMgr2(UTFDataFormatException
256                                                                          , XMLExcepts::UTF8_Invalid_3BytesSeq
257                                                                          , byte0
258                                                                          , byte1
259                                                                          , getMemoryManager());
260                                }
261
262                                checkTrailingBytes(*(srcPtr+1), 2, 1);
263                                checkTrailingBytes(*(srcPtr+2), 2, 2);
264
265                                //
266                                // D36 (a) UTF-8 is the Unicode Transformation Format that serializes
267                                //         a Unicode code point as a sequence of one to four bytes,
268                                //         as specified in Table 3.1, UTF-8 Bit Distribution.
269                                //     (b) An illegal UTF-8 code unit sequence is any byte sequence that
270                                //         does not match the patterns listed in Table 3.1B, Legal UTF-8
271                                //         Byte Sequences.
272                                //     (c) An irregular UTF-8 code unit sequence is a six-byte sequence
273                                //         where the first three bytes correspond to a high surrogate,
274                                //         and the next three bytes correspond to a low surrogate.
275                                //         As a consequence of C12, these irregular UTF-8 sequences shall
276                                //         not be generated by a conformant process.
277                                //
278                                //irregular three bytes sequence
279                                // that is zzzzyy matches leading surrogate tag 110110 or
280                                //                       trailing surrogate tag 110111
281                                // *srcPtr=1110 1101
282                                // *(srcPtr+1)=1010 yyyy or
283                                // *(srcPtr+1)=1011 yyyy
284                                //
285                                // 0xED 1110 1101
286                                // 0xA0 1010 0000
287
288                                if ((*srcPtr == 0xED) && (*(srcPtr+1) >= 0xA0))
289                                {
290                                        char byte0[2] = {*srcPtr,    0};
291                                        char byte1[2] = {*(srcPtr+1),0};
292
293                                         ThrowXMLwithMemMgr2(UTFDataFormatException
294                                                          , XMLExcepts::UTF8_Irregular_3BytesSeq
295                                                          , byte0
296                                                          , byte1
297                                                          , getMemoryManager());
298                                }
299
300                                tmpVal = *srcPtr++;
301                                tmpVal <<= 6;
302                                tmpVal += *srcPtr++;
303                                tmpVal <<= 6;
304                                tmpVal += *srcPtr++;
305
306                                break;
307                        case 3 :
308                                // UTF-8:   [1111 0uuu] [10uu zzzz] [10yy yyyy] [10xx xxxx]*
309                                // Unicode: [1101 10ww] [wwzz zzyy] (high surrogate)
310                                //          [1101 11yy] [yyxx xxxx] (low surrogate)
311                                //          * uuuuu = wwww + 1
312                                //
313                                if (((*srcPtr == 0xF0) && (*(srcPtr+1) < 0x90)) ||
314                                        ((*srcPtr == 0xF4) && (*(srcPtr+1) > 0x8F))  )
315                                {
316                                        char byte0[2] = {*srcPtr    ,0};
317                                        char byte1[2] = {*(srcPtr+1),0};
318
319                                        ThrowXMLwithMemMgr2(UTFDataFormatException
320                                                                          , XMLExcepts::UTF8_Invalid_4BytesSeq
321                                                                          , byte0
322                                                                          , byte1
323                                                                          , getMemoryManager());
324                                }
325
326                                checkTrailingBytes(*(srcPtr+1), 3, 1);
327                                checkTrailingBytes(*(srcPtr+2), 3, 2);
328                                checkTrailingBytes(*(srcPtr+3), 3, 3);
329
330                                tmpVal = *srcPtr++;
331                                tmpVal <<= 6;
332                                tmpVal += *srcPtr++;
333                                tmpVal <<= 6;
334                                tmpVal += *srcPtr++;
335                                tmpVal <<= 6;
336                                tmpVal += *srcPtr++;
337
338                                break;
339                        default: // trailingBytes > 3
340
341                                /***
342                                 * The definition of UTF-8 in Annex D of ISO/IEC 10646-1:2000 also allows
343                                 * for the use of five- and six-byte sequences to encode characters that
344                                 * are outside the range of the Unicode character set; those five- and
345                                 * six-byte sequences are illegal for the use of UTF-8 as a transformation
346                                 * of Unicode characters. ISO/IEC 10646 does not allow mapping of unpaired
347                                 * surrogates, nor U+FFFE and U+FFFF (but it does allow other noncharacters).
348                                 ***/
349                                char len[2]  = {(char)(trailingBytes+0x31), 0};
350                                char byte[2] = {*srcPtr,0};
351
352                                ThrowXMLwithMemMgr2(UTFDataFormatException
353                                                                  , XMLExcepts::UTF8_Exceeds_BytesLimit
354                                                                  , byte
355                                                                  , len
356                                                                  , getMemoryManager());
357
358                                break;
359                }
360
361
362                // since trailingBytes comes from an array, this logic is redundant
363                //  default :
364                //      ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq);
365                //}
366                tmpVal -= gUTFOffsets[trailingBytes];
367
368                //
369                //  If it will fit into a single char, then put it in. Otherwise
370                //  encode it as a surrogate pair. If its not valid, use the
371                //  replacement char.
372                //
373                if (!(tmpVal & 0xFFFF0000))
374                {
375                        *sizePtr++ = trailingBytes + 1;
376                        *outPtr++ = XMLCh(tmpVal);
377                }
378                 else if (tmpVal > 0x10FFFF)
379                {
380                        //
381                        //  If we've gotten more than 32 chars so far, then just break
382                        //  out for now and lets process those. When we come back in
383                        //  here again, we'll get no chars and throw an exception. This
384                        //  way, the error will have a line and col number closer to
385                        //  the real problem area.
386                        //
387                        if ((outPtr - toFill) > 32)
388                                break;
389
390                        ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, getMemoryManager());
391                }
392                 else
393                {
394                        //
395                        //  If we have enough room to store the leading and trailing
396                        //  chars, then lets do it. Else, pretend this one never
397                        //  happened, and leave it for the next time. Since we don't
398                        //  update the bytes read until the bottom of the loop, by
399                        //  breaking out here its like it never happened.
400                        //
401                        if (outPtr + 1 >= outEnd)
402                                break;
403
404                        // Store the leading surrogate char
405                        tmpVal -= 0x10000;
406                        *sizePtr++ = trailingBytes + 1;
407                        *outPtr++ = XMLCh((tmpVal >> 10) + 0xD800);
408
409                        //
410                        //  And then the trailing char. This one accounts for no
411                        //  bytes eaten from the source, so set the char size for this
412                        //  one to be zero.
413                        //
414                        *sizePtr++ = 0;
415                        *outPtr++ = XMLCh((tmpVal & 0x3FF) + 0xDC00);
416                }
417        }
418
419        // Update the bytes eaten
420        bytesEaten = srcPtr - srcData;
421
422        // Return the characters read
423        return outPtr - toFill;
424#else
425        return 0;
426#endif
427}
428
429XMLSize_t
430XMLUTF8Transcoder::transcodeFrom( const XMLByte* const          srcData
431                                                                , const XMLSize_t               srcCount
432                                                                ,       XMLBuffer &             toFill )
433{
434        // Watch for pathological scenario. Shouldn't happen, but...
435        if (!srcCount)
436                return 0;
437
438    toFill.ensureCapacity(srcCount);
439
440        //
441        //  Get pointers to our start and end points of the input and output
442        //  buffers.
443        //
444        const XMLByte * srcPtr = srcData;
445        const XMLByte * const srcEnd = srcPtr + srcCount;
446
447        //
448        //  We now loop until we either run out of input data, or room to store
449        //  output chars.
450        //
451        while (srcPtr < srcEnd)
452        {
453                // Special-case ASCII, which is a leading byte value of <= 127
454                if (unlikely(*srcPtr <= 127))
455                {
456                        toFill.append(XMLCh(*srcPtr++));
457                        XMLSize_t count = (srcEnd - srcPtr);
458                        // Handle ASCII in groups instead of single character at a time.
459                        for(; count && *srcPtr <= 127; --count)
460                                toFill.append(XMLCh(*srcPtr++));
461
462                        if (!count) break;
463                }
464
465                // See how many trailing src bytes this sequence is going to require
466                const unsigned int trailingBytes = gUTFBytes[*srcPtr];
467
468                //
469                //  If there are not enough source bytes to do this one, then we
470                //  are done. Note that we done >= here because we are implicitly
471                //  counting the 1 byte we get no matter what.
472                //
473                //  If we break out here, then there is nothing to undo since we
474                //  haven't updated any pointers yet.
475                //
476                if (srcPtr + trailingBytes >= srcEnd)
477                        break;
478
479                // Looks ok, so lets build up the value
480                // or at least let's try to do so--remembering that
481                // we cannot assume the encoding to be valid:
482
483                // first, test first byte
484                if((gUTFByteIndicatorTest[trailingBytes] & *srcPtr) != gUTFByteIndicator[trailingBytes]) {
485                        char pos[2] = {(char)0x31, 0};
486                        char len[2] = {(char)(trailingBytes+0x31), 0};
487                        char byte[2] = {*srcPtr,0};
488                        ThrowXMLwithMemMgr3(UTFDataFormatException, XMLExcepts::UTF8_FormatError, pos, byte, len, getMemoryManager());
489                }
490
491                /***
492                 * http://www.unicode.org/reports/tr27/
493                 *
494                 * Table 3.1B. lists all of the byte sequences that are legal in UTF-8.
495                 * A range of byte values such as A0..BF indicates that any byte from A0 to BF (inclusive)
496                 * is legal in that position.
497                 * Any byte value outside of the ranges listed is illegal.
498                 * For example,
499                 * the byte sequence <C0 AF> is illegal  since C0 is not legal in the 1st Byte column.
500                 * The byte sequence <E0 9F 80> is illegal since in the row
501                 *    where E0 is legal as a first byte,
502                 *    9F is not legal as a second byte.
503                 * The byte sequence <F4 80 83 92> is legal, since every byte in that sequence matches
504                 * a byte range in a row of the table (the last row).
505                 *
506                 *
507                 * Table 3.1B. Legal UTF-8 Byte Sequences
508                 * Code Points              1st Byte    2nd Byte    3rd Byte    4th Byte
509                 * =========================================================================
510                 * U+0000..U+007F            00..7F
511                 * -------------------------------------------------------------------------
512                 * U+0080..U+07FF            C2..DF      80..BF
513                 *
514                 * -------------------------------------------------------------------------
515                 * U+0800..U+0FFF            E0          A0..BF     80..BF
516                 *                                       --
517                 *
518                 * U+1000..U+FFFF            E1..EF      80..BF     80..BF
519                 *
520                 * --------------------------------------------------------------------------
521                 * U+10000..U+3FFFF          F0          90..BF     80..BF       80..BF
522                 *                                       --
523                 * U+40000..U+FFFFF          F1..F3      80..BF     80..BF       80..BF
524                 * U+100000..U+10FFFF        F4          80..8F     80..BF       80..BF
525                 *                                           --
526                 * ==========================================================================
527                 *
528                 *  Cases where a trailing byte range is not 80..BF are underlined in the table to
529                 *  draw attention to them. These occur only in the second byte of a sequence.
530                 *
531                 ***/
532
533                XMLUInt32 tmpVal = 0;
534
535                switch (trailingBytes)
536                {
537                        case 1 :
538                                // UTF-8:   [110y yyyy] [10xx xxxx]
539                                // Unicode: [0000 0yyy] [yyxx xxxx]
540                                //
541                                // 0xC0, 0xC1 has been filtered out
542                                checkTrailingBytes(*(srcPtr+1), 1, 1);
543
544                                tmpVal = *srcPtr++;
545                                tmpVal <<= 6;
546                                tmpVal += *srcPtr++;
547
548                                break;
549                        case 2 :
550                                // UTF-8:   [1110 zzzz] [10yy yyyy] [10xx xxxx]
551                                // Unicode: [zzzz yyyy] [yyxx xxxx]
552                                //
553                                if (( *srcPtr == 0xE0) && ( *(srcPtr+1) < 0xA0))
554                                {
555                                        char byte0[2] = {*srcPtr    ,0};
556                                        char byte1[2] = {*(srcPtr+1),0};
557
558                                        ThrowXMLwithMemMgr2(UTFDataFormatException
559                                                                          , XMLExcepts::UTF8_Invalid_3BytesSeq
560                                                                          , byte0
561                                                                          , byte1
562                                                                          , getMemoryManager());
563                                }
564
565                                checkTrailingBytes(*(srcPtr+1), 2, 1);
566                                checkTrailingBytes(*(srcPtr+2), 2, 2);
567
568                                //
569                                // D36 (a) UTF-8 is the Unicode Transformation Format that serializes
570                                //         a Unicode code point as a sequence of one to four bytes,
571                                //         as specified in Table 3.1, UTF-8 Bit Distribution.
572                                //     (b) An illegal UTF-8 code unit sequence is any byte sequence that
573                                //         does not match the patterns listed in Table 3.1B, Legal UTF-8
574                                //         Byte Sequences.
575                                //     (c) An irregular UTF-8 code unit sequence is a six-byte sequence
576                                //         where the first three bytes correspond to a high surrogate,
577                                //         and the next three bytes correspond to a low surrogate.
578                                //         As a consequence of C12, these irregular UTF-8 sequences shall
579                                //         not be generated by a conformant process.
580                                //
581                                //irregular three bytes sequence
582                                // that is zzzzyy matches leading surrogate tag 110110 or
583                                //                       trailing surrogate tag 110111
584                                // *srcPtr=1110 1101
585                                // *(srcPtr+1)=1010 yyyy or
586                                // *(srcPtr+1)=1011 yyyy
587                                //
588                                // 0xED 1110 1101
589                                // 0xA0 1010 0000
590
591                                if ((*srcPtr == 0xED) && (*(srcPtr+1) >= 0xA0))
592                                {
593                                        char byte0[2] = {*srcPtr,    0};
594                                        char byte1[2] = {*(srcPtr+1),0};
595
596                                         ThrowXMLwithMemMgr2(UTFDataFormatException
597                                                          , XMLExcepts::UTF8_Irregular_3BytesSeq
598                                                          , byte0
599                                                          , byte1
600                                                          , getMemoryManager());
601                                }
602
603                                tmpVal = *srcPtr++;
604                                tmpVal <<= 6;
605                                tmpVal += *srcPtr++;
606                                tmpVal <<= 6;
607                                tmpVal += *srcPtr++;
608
609                                break;
610                        case 3 :
611                                // UTF-8:   [1111 0uuu] [10uu zzzz] [10yy yyyy] [10xx xxxx]*
612                                // Unicode: [1101 10ww] [wwzz zzyy] (high surrogate)
613                                //          [1101 11yy] [yyxx xxxx] (low surrogate)
614                                //          * uuuuu = wwww + 1
615                                //
616                                if (((*srcPtr == 0xF0) && (*(srcPtr+1) < 0x90)) ||
617                                        ((*srcPtr == 0xF4) && (*(srcPtr+1) > 0x8F))  )
618                                {
619                                        char byte0[2] = {*srcPtr    ,0};
620                                        char byte1[2] = {*(srcPtr+1),0};
621
622                                        ThrowXMLwithMemMgr2(UTFDataFormatException
623                                                                          , XMLExcepts::UTF8_Invalid_4BytesSeq
624                                                                          , byte0
625                                                                          , byte1
626                                                                          , getMemoryManager());
627                                }
628
629                                checkTrailingBytes(*(srcPtr+1), 3, 1);
630                                checkTrailingBytes(*(srcPtr+2), 3, 2);
631                                checkTrailingBytes(*(srcPtr+3), 3, 3);
632
633                                tmpVal = *srcPtr++;
634                                tmpVal <<= 6;
635                                tmpVal += *srcPtr++;
636                                tmpVal <<= 6;
637                                tmpVal += *srcPtr++;
638                                tmpVal <<= 6;
639                                tmpVal += *srcPtr++;
640
641                                break;
642                        default: // trailingBytes > 3
643
644                                /***
645                                 * The definition of UTF-8 in Annex D of ISO/IEC 10646-1:2000 also allows
646                                 * for the use of five- and six-byte sequences to encode characters that
647                                 * are outside the range of the Unicode character set; those five- and
648                                 * six-byte sequences are illegal for the use of UTF-8 as a transformation
649                                 * of Unicode characters. ISO/IEC 10646 does not allow mapping of unpaired
650                                 * surrogates, nor U+FFFE and U+FFFF (but it does allow other noncharacters).
651                                 ***/
652                                char len[2]  = {(char)(trailingBytes+0x31), 0};
653                                char byte[2] = {*srcPtr,0};
654
655                                ThrowXMLwithMemMgr2(UTFDataFormatException
656                                                                  , XMLExcepts::UTF8_Exceeds_BytesLimit
657                                                                  , byte
658                                                                  , len
659                                                                  , getMemoryManager());
660
661                                break;
662                }
663
664
665                // since trailingBytes comes from an array, this logic is redundant
666                //  default :
667                //      ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq);
668                //}
669                tmpVal -= gUTFOffsets[trailingBytes];
670
671                //
672                //  If it will fit into a single char, then put it in. Otherwise
673                //  encode it as a surrogate pair. If its not valid, use the
674                //  replacement char.
675                //
676                if (!(tmpVal & 0xFFFF0000))
677                {
678                        toFill.append(XMLCh(tmpVal));
679                }
680                else if (tmpVal > 0x10FFFF)
681                {
682                        //
683                        //  If we've gotten more than 32 chars so far, then just break
684                        //  out for now and lets process those. When we come back in
685                        //  here again, we'll get no chars and throw an exception. This
686                        //  way, the error will have a line and col number closer to
687                        //  the real problem area.
688                        //
689
690                        ThrowXMLwithMemMgr(TranscodingException, XMLExcepts::Trans_BadSrcSeq, getMemoryManager());
691                }
692                 else
693                {
694                        //
695                        //  If we have enough room to store the leading and trailing
696                        //  chars, then lets do it. Else, pretend this one never
697                        //  happened, and leave it for the next time. Since we don't
698                        //  update the bytes read until the bottom of the loop, by
699                        //  breaking out here its like it never happened.
700                        //
701
702                        // Store the leading surrogate char
703                        tmpVal -= 0x10000;
704                        toFill.append(XMLCh((tmpVal >> 10) + 0xD800));
705
706                        //
707                        //  And then the trailing char. This one accounts for no
708                        //  bytes eaten from the source, so set the char size for this
709                        //  one to be zero.
710                        //
711                        toFill.append(XMLCh((tmpVal & 0x3FF) + 0xDC00));
712                }
713        }
714
715        // Return the bytes eaten
716        return srcPtr - srcData;
717
718
719}
720
721
722XMLSize_t
723XMLUTF8Transcoder::transcodeTo( const   XMLCh*  const srcData
724                                                          , const XMLSize_t       srcCount
725                                                          ,       XMLByte*  const toFill
726                                                          , const XMLSize_t       maxBytes
727                                                          ,       XMLSize_t&      charsEaten
728                                                          , const UnRepOpts       options)
729{
730        // Watch for pathological scenario. Shouldn't happen, but...
731        if (!srcCount || !maxBytes)
732                return 0;
733
734        //
735        //  Get pointers to our start and end points of the input and output
736        //  buffers.
737        //
738        const XMLCh*    srcPtr = srcData;
739        const XMLCh*    srcEnd = srcPtr + srcCount;
740        XMLByte*        outPtr = toFill;
741        XMLByte*        outEnd = toFill + maxBytes;
742
743        while (srcPtr < srcEnd)
744        {
745                //
746                //  Tentatively get the next char out. We have to get it into a
747                //  32 bit value, because it could be a surrogate pair.
748                //
749                XMLUInt32 curVal = *srcPtr;
750
751                //
752                //  If its a leading surrogate, then lets see if we have the trailing
753                //  available. If not, then give up now and leave it for next time.
754                //
755                unsigned int srcUsed = 1;
756                if ((curVal >= 0xD800) && (curVal <= 0xDBFF))
757                {
758                        if (srcPtr + 1 >= srcEnd)
759                                break;
760
761                        // Create the composite surrogate pair
762                        curVal = ((curVal - 0xD800) << 10)
763                                        + ((*(srcPtr + 1) - 0xDC00) + 0x10000);
764
765                        // And indicate that we ate another one
766                        srcUsed++;
767                }
768
769                // Figure out how many bytes we need
770                unsigned int encodedBytes;
771                if (curVal < 0x80)
772                        encodedBytes = 1;
773                else if (curVal < 0x800)
774                        encodedBytes = 2;
775                else if (curVal < 0x10000)
776                        encodedBytes = 3;
777                else if (curVal < 0x110000)
778                        encodedBytes = 4;
779                else
780                {
781                        // If the options say to throw, then throw
782                        if (options == UnRep_Throw)
783                        {
784                                XMLCh tmpBuf[17];
785                                XMLString::binToText(curVal, tmpBuf, 16, 16, getMemoryManager());
786                                ThrowXMLwithMemMgr2
787                                (
788                                        TranscodingException
789                                        , XMLExcepts::Trans_Unrepresentable
790                                        , tmpBuf
791                                        , getEncodingName()
792                                        , getMemoryManager()
793                                );
794                        }
795
796                        // Else, use the replacement character
797                        *outPtr++ = chSpace;
798                        srcPtr += srcUsed;
799                        continue;
800                }
801
802                //
803                //  If we cannot fully get this char into the output buffer,
804                //  then leave it for the next time.
805                //
806                if (outPtr + encodedBytes > outEnd)
807                        break;
808
809                // We can do it, so update the source index
810                srcPtr += srcUsed;
811
812                //
813                //  And spit out the bytes. We spit them out in reverse order
814                //  here, so bump up the output pointer and work down as we go.
815                //
816                outPtr += encodedBytes;
817                switch(encodedBytes)
818                {
819                        case 6 : *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
820                                         curVal >>= 6;
821                        case 5 : *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
822                                         curVal >>= 6;
823                        case 4 : *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
824                                         curVal >>= 6;
825                        case 3 : *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
826                                         curVal >>= 6;
827                        case 2 : *--outPtr = XMLByte((curVal | 0x80UL) & 0xBFUL);
828                                         curVal >>= 6;
829                        case 1 : *--outPtr = XMLByte
830                                         (
831                                                curVal | gFirstByteMark[encodedBytes]
832                                         );
833                }
834
835                // Add the encoded bytes back in again to indicate we've eaten them
836                outPtr += encodedBytes;
837        }
838
839        // Fill in the chars we ate
840        charsEaten = (srcPtr - srcData);
841
842        // And return the bytes we filled in
843        return (outPtr - toFill);
844}
845
846
847bool XMLUTF8Transcoder::canTranscodeTo(const unsigned int toCheck)
848{
849        // We can represent anything in the Unicode (with surrogates) range
850        return (toCheck <= 0x10FFFF);
851}
852
853
854XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.