一个在UTF32、UTF-16、UTF-8中相互转换的C++程序

来源:互联网 发布:学风水看什么书 知乎 编辑:程序博客网 时间:2024/06/15 17:43

首先是最重要的版权信息。

/*
 * Copyright 2001-2004 Unicode, Inc.
 * 
 * Disclaimer
 * 
 * This source code is provided as is by Unicode, Inc. No claims are
 * made as to fitness for any particular purpose. No warranties of any
 * kind are expressed or implied. The recipient agrees to determine
 * applicability of information provided. If this file has been
 * purchased on magnetic or optical media from Unicode, Inc., the
 * sole remedy for any claim will be exchange of defective media
 * within 90 days of receipt.
 * 
 * Limitations on Rights to Redistribute This Code
 * 
 * Unicode, Inc. hereby grants the right to freely use the information
 * supplied in this file in the creation of products supporting the
 * Unicode Standard, and to make copies of this file in any form
 * for internal or external distribution as long as this notice
 * remains attached.
 */

 

头文件:

 

[cpp] view plain copy
  1. typedef unsigned int    UTF32;  /* at least 32 bits */  
  2. typedef unsigned short  UTF16;  /* at least 16 bits */  
  3. typedef unsigned char   UTF8;   /* typically 8 bits */  
  4. typedef unsigned char   Boolean; /* 0 or 1 */  
  5.   
  6. /* Some fundamental constants */  
  7. #define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD  
  8. #define UNI_MAX_BMP (UTF32)0x0000FFFF  
  9. #define UNI_MAX_UTF16 (UTF32)0x0010FFFF  
  10. #define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF  
  11. #define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF  
  12.   
  13. typedef enum {  
  14.     conversionOK,       /* conversion successful */  
  15.     sourceExhausted,    /* partial character in source, but hit end */  
  16.     targetExhausted,    /* insuff. room in target for conversion */  
  17.     sourceIllegal       /* source sequence is illegal/malformed */  
  18. } ConversionResult;  
  19.   
  20. typedef enum {  
  21.     strictConversion = 0,  
  22.     lenientConversion  
  23. } ConversionFlags;  
  24.   
  25. /* This is for C++ and does no harm in C */  
  26. #ifdef __cplusplus  
  27. extern "C" {  
  28. #endif  
  29.   
  30. ConversionResult ConvertUTF8toUTF16 (  
  31.         const UTF8** sourceStart, const UTF8* sourceEnd,   
  32.         UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);  
  33.   
  34. ConversionResult ConvertUTF16toUTF8 (  
  35.         const UTF16** sourceStart, const UTF16* sourceEnd,   
  36.         UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);  
  37.           
  38. ConversionResult ConvertUTF8toUTF32 (  
  39.         const UTF8** sourceStart, const UTF8* sourceEnd,   
  40.         UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);  
  41.   
  42. ConversionResult ConvertUTF32toUTF8 (  
  43.         const UTF32** sourceStart, const UTF32* sourceEnd,   
  44.         UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);  
  45.           
  46. ConversionResult ConvertUTF16toUTF32 (  
  47.         const UTF16** sourceStart, const UTF16* sourceEnd,   
  48.         UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);  
  49.   
  50. ConversionResult ConvertUTF32toUTF16 (  
  51.         const UTF32** sourceStart, const UTF32* sourceEnd,   
  52.         UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);  
  53.   
  54. Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);  
  55.   
  56. #ifdef __cplusplus  
  57. }  
  58. #endif  

 

实现:

 

[cpp] view plain copy
  1. #include "ConvertUTF.h"  
  2. #ifdef CVTUTF_DEBUG  
  3. #include <stdio.h>  
  4. #endif  
  5.   
  6. static const int halfShift  = 10; /* used for shifting by 10 bits */  
  7.   
  8. static const UTF32 halfBase = 0x0010000UL;  
  9. static const UTF32 halfMask = 0x3FFUL;  
  10.   
  11. #define UNI_SUR_HIGH_START  (UTF32)0xD800  
  12. #define UNI_SUR_HIGH_END    (UTF32)0xDBFF  
  13. #define UNI_SUR_LOW_START   (UTF32)0xDC00  
  14. #define UNI_SUR_LOW_END     (UTF32)0xDFFF  
  15. #define false      0  
  16. #define true        1  
  17.   
  18. /* --------------------------------------------------------------------- */  
  19.   
  20. ConversionResult ConvertUTF32toUTF16 (  
  21.     const UTF32** sourceStart, const UTF32* sourceEnd,   
  22.     UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {  
  23.     ConversionResult result = conversionOK;  
  24.     const UTF32* source = *sourceStart;  
  25.     UTF16* target = *targetStart;  
  26.     while (source < sourceEnd) {  
  27.     UTF32 ch;  
  28.     if (target >= targetEnd) {  
  29.         result = targetExhausted; break;  
  30.     }  
  31.     ch = *source++;  
  32.     if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */  
  33.         /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */  
  34.         if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {  
  35.         if (flags == strictConversion) {  
  36.             --source; /* return to the illegal value itself */  
  37.             result = sourceIllegal;  
  38.             break;  
  39.         } else {  
  40.             *target++ = UNI_REPLACEMENT_CHAR;  
  41.         }  
  42.         } else {  
  43.         *target++ = (UTF16)ch; /* normal case */  
  44.         }  
  45.     } else if (ch > UNI_MAX_LEGAL_UTF32) {  
  46.         if (flags == strictConversion) {  
  47.         result = sourceIllegal;  
  48.         } else {  
  49.         *target++ = UNI_REPLACEMENT_CHAR;  
  50.         }  
  51.     } else {  
  52.         /* target is a character in range 0xFFFF - 0x10FFFF. */  
  53.         if (target + 1 >= targetEnd) {  
  54.         --source; /* Back up source pointer! */  
  55.         result = targetExhausted; break;  
  56.         }  
  57.         ch -= halfBase;  
  58.         *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);  
  59.         *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);  
  60.     }  
  61.     }  
  62.     *sourceStart = source;  
  63.     *targetStart = target;  
  64.     return result;  
  65. }  
  66.   
  67. /* --------------------------------------------------------------------- */  
  68.   
  69. ConversionResult ConvertUTF16toUTF32 (  
  70.     const UTF16** sourceStart, const UTF16* sourceEnd,   
  71.     UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {  
  72.     ConversionResult result = conversionOK;  
  73.     const UTF16* source = *sourceStart;  
  74.     UTF32* target = *targetStart;  
  75.     UTF32 ch, ch2;  
  76.     while (source < sourceEnd) {  
  77.     const UTF16* oldSource = source; /*  In case we have to back up because of target overflow. */  
  78.     ch = *source++;  
  79.     /* If we have a surrogate pair, convert to UTF32 first. */  
  80.     if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {  
  81.         /* If the 16 bits following the high surrogate are in the source buffer... */  
  82.         if (source < sourceEnd) {  
  83.         ch2 = *source;  
  84.         /* If it's a low surrogate, convert to UTF32. */  
  85.         if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {  
  86.             ch = ((ch - UNI_SUR_HIGH_START) << halfShift)  
  87.             + (ch2 - UNI_SUR_LOW_START) + halfBase;  
  88.             ++source;  
  89.         } else if (flags == strictConversion) { /* it's an unpaired high surrogate */  
  90.             --source; /* return to the illegal value itself */  
  91.             result = sourceIllegal;  
  92.             break;  
  93.         }  
  94.         } else { /* We don't have the 16 bits following the high surrogate. */  
  95.         --source; /* return to the high surrogate */  
  96.         result = sourceExhausted;  
  97.         break;  
  98.         }  
  99.     } else if (flags == strictConversion) {  
  100.         /* UTF-16 surrogate values are illegal in UTF-32 */  
  101.         if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {  
  102.         --source; /* return to the illegal value itself */  
  103.         result = sourceIllegal;  
  104.         break;  
  105.         }  
  106.     }  
  107.     if (target >= targetEnd) {  
  108.         source = oldSource; /* Back up source pointer! */  
  109.         result = targetExhausted; break;  
  110.     }  
  111.     *target++ = ch;  
  112.     }  
  113.     *sourceStart = source;  
  114.     *targetStart = target;  
  115. #ifdef CVTUTF_DEBUG  
  116. if (result == sourceIllegal) {  
  117.     fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x/n", ch, ch2);  
  118.     fflush(stderr);  
  119. }  
  120. #endif  
  121.     return result;  
  122. }  
  123.   
  124. /* --------------------------------------------------------------------- */  
  125.   
  126. /* 
  127.  * Index into the table below with the first byte of a UTF-8 sequence to 
  128.  * get the number of trailing bytes that are supposed to follow it. 
  129.  * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is 
  130.  * left as-is for anyone who may want to do such conversion, which was 
  131.  * allowed in earlier algorithms. 
  132.  */  
  133. static const char trailingBytesForUTF8[256] = {  
  134.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
  135.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
  136.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
  137.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
  138.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
  139.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
  140.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  
  141.     2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5  
  142. };  
  143.   
  144. /* 
  145.  * Magic values subtracted from a buffer value during UTF8 conversion. 
  146.  * This table contains as many values as there might be trailing bytes 
  147.  * in a UTF-8 sequence. 
  148.  */  
  149. static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,   
  150.              0x03C82080UL, 0xFA082080UL, 0x82082080UL };  
  151.   
  152. /* 
  153.  * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed 
  154.  * into the first byte, depending on how many bytes follow.  There are 
  155.  * as many entries in this table as there are UTF-8 sequence types. 
  156.  * (I.e., one byte sequence, two byte... etc.). Remember that sequencs 
  157.  * for *legal* UTF-8 will be 4 or fewer bytes total. 
  158.  */  
  159. static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };  
  160.   
  161. /* --------------------------------------------------------------------- */  
  162.   
  163. /* The interface converts a whole buffer to avoid function-call overhead. 
  164.  * Constants have been gathered. Loops & conditionals have been removed as 
  165.  * much as possible for efficiency, in favor of drop-through switches. 
  166.  * (See "Note A" at the bottom of the file for equivalent code.) 
  167.  * If your compiler supports it, the "isLegalUTF8" call can be turned 
  168.  * into an inline function. 
  169.  */  
  170.   
  171. /* --------------------------------------------------------------------- */  
  172.   
  173. ConversionResult ConvertUTF16toUTF8 (  
  174.     const UTF16** sourceStart, const UTF16* sourceEnd,   
  175.     UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {  
  176.     ConversionResult result = conversionOK;  
  177.     const UTF16* source = *sourceStart;  
  178.     UTF8* target = *targetStart;  
  179.     while (source < sourceEnd) {  
  180.     UTF32 ch;  
  181.     unsigned short bytesToWrite = 0;  
  182.     const UTF32 byteMask = 0xBF;  
  183.     const UTF32 byteMark = 0x80;   
  184.     const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */  
  185.     ch = *source++;  
  186.     /* If we have a surrogate pair, convert to UTF32 first. */  
  187.     if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {  
  188.         /* If the 16 bits following the high surrogate are in the source buffer... */  
  189.         if (source < sourceEnd) {  
  190.         UTF32 ch2 = *source;  
  191.         /* If it's a low surrogate, convert to UTF32. */  
  192.         if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {  
  193.             ch = ((ch - UNI_SUR_HIGH_START) << halfShift)  
  194.             + (ch2 - UNI_SUR_LOW_START) + halfBase;  
  195.             ++source;  
  196.         } else if (flags == strictConversion) { /* it's an unpaired high surrogate */  
  197.             --source; /* return to the illegal value itself */  
  198.             result = sourceIllegal;  
  199.             break;  
  200.         }  
  201.         } else { /* We don't have the 16 bits following the high surrogate. */  
  202.         --source; /* return to the high surrogate */  
  203.         result = sourceExhausted;  
  204.         break;  
  205.         }  
  206.     } else if (flags == strictConversion) {  
  207.         /* UTF-16 surrogate values are illegal in UTF-32 */  
  208.         if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {  
  209.         --source; /* return to the illegal value itself */  
  210.         result = sourceIllegal;  
  211.         break;  
  212.         }  
  213.     }  
  214.     /* Figure out how many bytes the result will require */  
  215.     if (ch < (UTF32)0x80) {       bytesToWrite = 1;  
  216.     } else if (ch < (UTF32)0x800) {     bytesToWrite = 2;  
  217.     } else if (ch < (UTF32)0x10000) {   bytesToWrite = 3;  
  218.     } else if (ch < (UTF32)0x110000) {  bytesToWrite = 4;  
  219.     } else {                bytesToWrite = 3;  
  220.                         ch = UNI_REPLACEMENT_CHAR;  
  221.     }  
  222.   
  223.     target += bytesToWrite;  
  224.     if (target > targetEnd) {  
  225.         source = oldSource; /* Back up source pointer! */  
  226.         target -= bytesToWrite; result = targetExhausted; break;  
  227.     }  
  228.     switch (bytesToWrite) { /* note: everything falls through. */  
  229.         case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;  
  230.         case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;  
  231.         case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;  
  232.         case 1: *--target =  (UTF8)(ch | firstByteMark[bytesToWrite]);  
  233.     }  
  234.     target += bytesToWrite;  
  235.     }  
  236.     *sourceStart = source;  
  237.     *targetStart = target;  
  238.     return result;  
  239. }  
  240.   
  241. /* --------------------------------------------------------------------- */  
  242.   
  243. /* 
  244.  * Utility routine to tell whether a sequence of bytes is legal UTF-8. 
  245.  * This must be called with the length pre-determined by the first byte. 
  246.  * If not calling this from ConvertUTF8to*, then the length can be set by: 
  247.  *  length = trailingBytesForUTF8[*source]+1; 
  248.  * and the sequence is illegal right away if there aren't that many bytes 
  249.  * available. 
  250.  * If presented with a length > 4, this returns false.  The Unicode 
  251.  * definition of UTF-8 goes up to 4-byte sequences. 
  252.  */  
  253.   
  254. static Boolean isLegalUTF8(const UTF8 *source, int length) {  
  255.     UTF8 a;  
  256.     const UTF8 *srcptr = source+length;  
  257.     switch (length) {  
  258.     defaultreturn false;  
  259.     /* Everything else falls through when "true"... */  
  260.     case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;  
  261.     case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;  
  262.     case 2: if ((a = (*--srcptr)) > 0xBF) return false;  
  263.   
  264.     switch (*source) {  
  265.         /* no fall-through in this inner switch */  
  266.         case 0xE0: if (a < 0xA0) return falsebreak;  
  267.         case 0xED: if (a > 0x9F) return falsebreak;  
  268.         case 0xF0: if (a < 0x90) return falsebreak;  
  269.         case 0xF4: if (a > 0x8F) return falsebreak;  
  270.         default:   if (a < 0x80) return false;  
  271.     }  
  272.   
  273.     case 1: if (*source >= 0x80 && *source < 0xC2) return false;  
  274.     }  
  275.     if (*source > 0xF4) return false;  
  276.     return true;  
  277. }  
  278.   
  279. /* --------------------------------------------------------------------- */  
  280.   
  281. /* 
  282.  * Exported function to return whether a UTF-8 sequence is legal or not. 
  283.  * This is not used here; it's just exported. 
  284.  */  
  285. Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {  
  286.     int length = trailingBytesForUTF8[*source]+1;  
  287.     if (source+length > sourceEnd) {  
  288.     return false;  
  289.     }  
  290.     return isLegalUTF8(source, length);  
  291. }  
  292.   
  293. /* --------------------------------------------------------------------- */  
  294.   
  295. ConversionResult ConvertUTF8toUTF16 (  
  296.     const UTF8** sourceStart, const UTF8* sourceEnd,   
  297.     UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {  
  298.     ConversionResult result = conversionOK;  
  299.     const UTF8* source = *sourceStart;  
  300.     UTF16* target = *targetStart;  
  301.     while (source < sourceEnd) {  
  302.     UTF32 ch = 0;  
  303.     unsigned short extraBytesToRead = trailingBytesForUTF8[*source];  
  304.     if (source + extraBytesToRead >= sourceEnd) {  
  305.         result = sourceExhausted; break;  
  306.     }  
  307.     /* Do this check whether lenient or strict */  
  308.     if (! isLegalUTF8(source, extraBytesToRead+1)) {  
  309.         result = sourceIllegal;  
  310.         break;  
  311.     }  
  312.     /* 
  313.      * The cases all fall through. See "Note A" below. 
  314.      */  
  315.     switch (extraBytesToRead) {  
  316.         case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */  
  317.         case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */  
  318.         case 3: ch += *source++; ch <<= 6;  
  319.         case 2: ch += *source++; ch <<= 6;  
  320.         case 1: ch += *source++; ch <<= 6;  
  321.         case 0: ch += *source++;  
  322.     }  
  323.     ch -= offsetsFromUTF8[extraBytesToRead];  
  324.   
  325.     if (target >= targetEnd) {  
  326.         source -= (extraBytesToRead+1); /* Back up source pointer! */  
  327.         result = targetExhausted; break;  
  328.     }  
  329.     if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */  
  330.         /* UTF-16 surrogate values are illegal in UTF-32 */  
  331.         if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {  
  332.         if (flags == strictConversion) {  
  333.             source -= (extraBytesToRead+1); /* return to the illegal value itself */  
  334.             result = sourceIllegal;  
  335.             break;  
  336.         } else {  
  337.             *target++ = UNI_REPLACEMENT_CHAR;  
  338.         }  
  339.         } else {  
  340.         *target++ = (UTF16)ch; /* normal case */  
  341.         }  
  342.     } else if (ch > UNI_MAX_UTF16) {  
  343.         if (flags == strictConversion) {  
  344.         result = sourceIllegal;  
  345.         source -= (extraBytesToRead+1); /* return to the start */  
  346.         break/* Bail out; shouldn't continue */  
  347.         } else {  
  348.         *target++ = UNI_REPLACEMENT_CHAR;  
  349.         }  
  350.     } else {  
  351.         /* target is a character in range 0xFFFF - 0x10FFFF. */  
  352.         if (target + 1 >= targetEnd) {  
  353.         source -= (extraBytesToRead+1); /* Back up source pointer! */  
  354.         result = targetExhausted; break;  
  355.         }  
  356.         ch -= halfBase;  
  357.         *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);  
  358.         *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);  
  359.     }  
  360.     }  
  361.     *sourceStart = source;  
  362.     *targetStart = target;  
  363.     return result;  
  364. }  
  365.   
  366. /* --------------------------------------------------------------------- */  
  367.   
  368. ConversionResult ConvertUTF32toUTF8 (  
  369.     const UTF32** sourceStart, const UTF32* sourceEnd,   
  370.     UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {  
  371.     ConversionResult result = conversionOK;  
  372.     const UTF32* source = *sourceStart;  
  373.     UTF8* target = *targetStart;  
  374.     while (source < sourceEnd) {  
  375.     UTF32 ch;  
  376.     unsigned short bytesToWrite = 0;  
  377.     const UTF32 byteMask = 0xBF;  
  378.     const UTF32 byteMark = 0x80;   
  379.     ch = *source++;  
  380.     if (flags == strictConversion ) {  
  381.         /* UTF-16 surrogate values are illegal in UTF-32 */  
  382.         if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {  
  383.         --source; /* return to the illegal value itself */  
  384.         result = sourceIllegal;  
  385.         break;  
  386.         }  
  387.     }  
  388.     /* 
  389.      * Figure out how many bytes the result will require. Turn any 
  390.      * illegally large UTF32 things (> Plane 17) into replacement chars. 
  391.      */  
  392.     if (ch < (UTF32)0x80) {       bytesToWrite = 1;  
  393.     } else if (ch < (UTF32)0x800) {     bytesToWrite = 2;  
  394.     } else if (ch < (UTF32)0x10000) {   bytesToWrite = 3;  
  395.     } else if (ch <= UNI_MAX_LEGAL_UTF32) {  bytesToWrite = 4;  
  396.     } else {                bytesToWrite = 3;  
  397.                         ch = UNI_REPLACEMENT_CHAR;  
  398.                         result = sourceIllegal;  
  399.     }  
  400.       
  401.     target += bytesToWrite;  
  402.     if (target > targetEnd) {  
  403.         --source; /* Back up source pointer! */  
  404.         target -= bytesToWrite; result = targetExhausted; break;  
  405.     }  
  406.     switch (bytesToWrite) { /* note: everything falls through. */  
  407.         case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;  
  408.         case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;  
  409.         case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;  
  410.         case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);  
  411.     }  
  412.     target += bytesToWrite;  
  413.     }  
  414.     *sourceStart = source;  
  415.     *targetStart = target;  
  416.     return result;  
  417. }  
  418.   
  419. /* --------------------------------------------------------------------- */  
  420.   
  421. ConversionResult ConvertUTF8toUTF32 (  
  422.     const UTF8** sourceStart, const UTF8* sourceEnd,   
  423.     UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {  
  424.     ConversionResult result = conversionOK;  
  425.     const UTF8* source = *sourceStart;  
  426.     UTF32* target = *targetStart;  
  427.     while (source < sourceEnd) {  
  428.     UTF32 ch = 0;  
  429.     unsigned short extraBytesToRead = trailingBytesForUTF8[*source];  
  430.     if (source + extraBytesToRead >= sourceEnd) {  
  431.         result = sourceExhausted; break;  
  432.     }  
  433.     /* Do this check whether lenient or strict */  
  434.     if (! isLegalUTF8(source, extraBytesToRead+1)) {  
  435.         result = sourceIllegal;  
  436.         break;  
  437.     }  
  438.     /* 
  439.      * The cases all fall through. See "Note A" below. 
  440.      */  
  441.     switch (extraBytesToRead) {  
  442.         case 5: ch += *source++; ch <<= 6;  
  443.         case 4: ch += *source++; ch <<= 6;  
  444.         case 3: ch += *source++; ch <<= 6;  
  445.         case 2: ch += *source++; ch <<= 6;  
  446.         case 1: ch += *source++; ch <<= 6;  
  447.         case 0: ch += *source++;  
  448.     }  
  449.     ch -= offsetsFromUTF8[extraBytesToRead];  
  450.   
  451.     if (target >= targetEnd) {  
  452.         source -= (extraBytesToRead+1); /* Back up the source pointer! */  
  453.         result = targetExhausted; break;  
  454.     }  
  455.     if (ch <= UNI_MAX_LEGAL_UTF32) {  
  456.         /* 
  457.          * UTF-16 surrogate values are illegal in UTF-32, and anything 
  458.          * over Plane 17 (> 0x10FFFF) is illegal. 
  459.          */  
  460.         if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {  
  461.         if (flags == strictConversion) {  
  462.             source -= (extraBytesToRead+1); /* return to the illegal value itself */  
  463.             result = sourceIllegal;  
  464.             break;  
  465.         } else {  
  466.             *target++ = UNI_REPLACEMENT_CHAR;  
  467.         }  
  468.         } else {  
  469.         *target++ = ch;  
  470.         }  
  471.     } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */  
  472.         result = sourceIllegal;  
  473.         *target++ = UNI_REPLACEMENT_CHAR;  
  474.     }  
  475.     }  
  476.     *sourceStart = source;  
  477.     *targetStart = target;  
  478.     return result;  
  479. }  
  480.   

0 0
原创粉丝点击