utf8.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:14k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: utf8.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:40:43  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.6
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: utf8.cpp,v 1000.2 2004/06/01 19:40:43 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author: Aleksey Vinokurov, Vladimir Ivanov
  35.  *
  36.  * File Description:  UTF8 converter functions
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <util/utf8.hpp>
  41. BEGIN_NCBI_SCOPE
  42. BEGIN_SCOPE(utf8)
  43. // Translation tables.
  44. // I've put codes from ASCII-7 table here. So in this table should be only 
  45. // 7-bit characters and two special characters - 0x00 (unable to translate) 
  46. // and 0xFF (character should be skipped).
  47. static unsigned char tblTrans[] =
  48. {
  49.     // Latin Base
  50.  // 0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
  51.     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 , // 08
  52.     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 , // 09
  53.     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  'a',  0,  '"',  0,   0,  '-', // 0A
  54.    0xFF, 0,  '2', '3',''',  0,   0,  '.',  0,  '1', 'o',  0,  '"',  0,   0,   0 , // 0B
  55.    'A', 'A', 'A', 'A', 'A', 'A', 'A', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', // 0C
  56.    'D', 'N', 'O', 'O', 'O', 'O', 'O', 'x', 'O', 'U', 'U', 'U', 'U', 'Y',  0,  'B', // 0D 
  57.    'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', // 0E 
  58.    'o', 'n', 'o', 'o', 'o', 'o', 'o', '-', 'o', 'u', 'u', 'u', 'u', 'y',  0,  'y', // 0F 
  59.     // Latin A
  60.  // 0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
  61.    'A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', // 10 
  62.    'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', // 11 
  63.    'G', 'g', 'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', // 12 
  64.    'I', 'i', 'J', 'j', 'J', 'j', 'K', 'k', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', // 13 
  65.    'l', 'L', 'l', 'N', 'n', 'N', 'n', 'N', 'n', 'n', 'N', 'n', 'O', 'o', 'O', 'o', // 14 
  66.    'O', 'o', 'O', 'o', 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', // 15 
  67.    'S', 's', 'T', 't', 'T', 't', 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', // 16 
  68.    'U', 'u', 'U', 'u', 'W', 'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z',  0 , // 17 
  69.     // Latin B
  70.  // 0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
  71.    'b', 'B',  0 ,  0 ,  0 ,  0 ,  0 , 'C', 'c', 'D', 'D',  0 ,  0 ,  0 ,  0 ,  0 , // 18 
  72.    'E', 'F', 'f', 'G',  0 ,  0 ,  0 , 'I', 'K', 'k',  0 ,  0 ,  0 , 'N', 'n',  0 , // 19 
  73.    'O', 'o',  0 ,  0 , 'P', 'p', 'R',  0 ,  0 ,  0 ,  0 , 't', 'T', 't', 'T', 'U', // 1A 
  74.    'u',  0 ,  0 , 'Y', 'y', 'Z', 'z', 'Z',  0 ,  0 , 'z',  0 ,  0 ,  0 ,  0 ,  0 , // 1B 
  75.     0 ,  0 ,  0 , '!', 'D', 'd', 'd', 'L', 'L', 'l', 'N', 'N', 'n', 'A', 'a', 'I', // 1C 
  76.    'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u',  0 , 'A', 'a', // 1D 
  77.    'A', 'a', 'A', 'a', 'G', 'g', 'G', 'g', 'K', 'k', 'O', 'o', 'O', 'o', 'Z', 'z', // 1E
  78.    'j', 'D', 'D', 'd', 'G', 'g',  0 ,  0 , 'N', 'n', 'A', 'a',  0,   0 , 'O', 'o', // 1F 
  79.    'A', 'a', 'A', 'a', 'E', 'e', 'E', 'e', 'I', 'i', 'I', 'i', 'O', 'o', 'O', 'o', // 20 
  80.    'R', 'r', 'R', 'r', 'U', 'u', 'U', 'u', 'S', 's', 'T', 't',  0 ,  0 , 'H', 'h', // 21 
  81.     0 ,  0 ,  0 ,  0 , 'Z', 'z', 'A', 'a', 'E', 'e', 'O', 'o', 'O', 'o', 'O', 'o', // 22 
  82.    'O', 'o', 'Y', 'y',  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , // 23
  83.     0 ,  0,   0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , // 24
  84.     // IPA Extensions
  85.  // 0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
  86.     0 , 'a',  0 ,  0 ,  0 ,  0 , 'd', 'd',  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , // 25
  87.    'g', 'g', 'G',  0 ,  0 ,  0 , 'h' ,'h', 'i', 'i', 'I',  0 ,  0 ,  0 ,  0 ,  0 , // 26
  88.     0,  'm',  0,  'n', 'N',  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 , // 27
  89.    'R',  0,  's',  0,   0,   0,   0,   0,  't', 'u',  0,   0,   0,   0,   0,  'Y', // 28
  90.    'Z', 'Z', 'z',  'z', 0,   0,   0,   0,  'O', 'B',  0,  'G', 'H', 'j',  0,  'L', // 29
  91.    'q',  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 , // 2A
  92.     // Spacing Modifiers
  93.  // 0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
  94.    'h', 'h', 'j', 'r',  0 ,  0 ,  0 , 'w', 'y',''', '"',''',''',''',''',''', // 2B
  95.    '?', '?', '<', '>', '^', 'v', '^', 'v',''', '-',''', '`',''', '_',''', '`', // 2C
  96.     0,   0, ''',''',  0 ,  0 , '+', '-', '~', '.', '.',  0,  '~', '"' , 0 , 'x', // 2D
  97.     0 ,  0,   0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , // 2E
  98.     0 , 'l', 's', 'x',  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , 'v' ,'=', '"',  0   // 2F
  99. };
  100. static unsigned char tblTransA[] =
  101. {
  102.     // Spacing Modifiers
  103.  // 0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
  104.    'A', 'a', 'B', 'b', 'B', 'b', 'B', 'b', 'C', 'c', 'D', 'd', 'D', 'd', 'D', 'd', // 1E0
  105.    'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'F', 'f', // 1E1
  106.    'G', 'g', 'H', 'h', 'H', 'h', 'H', 'h', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', // 1E2
  107.    'K', 'k', 'K', 'k', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'M', 'm', // 1E3
  108.    'M', 'm', 'M', 'm', 'N', 'n', 'N', 'n', 'N', 'n', 'N', 'n', 'O', 'o', 'O', 'o', // 1E4
  109.    'O', 'o', 'O', 'o', 'P', 'p', 'P', 'p', 'R', 'r', 'R', 'r', 'R', 'r', 'R', 'r', // 1E5
  110.    'S', 's', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't', 'T', 't', // 1E6
  111.    'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'V', 'v', 'V', 'v', // 1E7
  112.    'W', 'w', 'W', 'w', 'W', 'w', 'W', 'w', 'W', 'w', 'X', 'x', 'X', 'x', 'Y', 'y', // 1E8
  113.    'Z', 'z', 'Z', 'z', 'Z', 'z', 'h', 't', 'w', 'y', 'a', 'f',  0 ,  0 ,  0 ,  0 , // 1E9
  114.    'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', // 1EA
  115.    'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', // 1EB
  116.    'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'I', 'i', 'I', 'i', 'O', 'o', 'O', 'o', // 1EC
  117.    'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', 'O', 'o', // 1ED
  118.    'O', 'o', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', // 1EE
  119.    'U', 'u', 'Y', 'y', 'Y', 'y', 'Y', 'y', 'Y', 'y',  0 ,  0 ,  0 ,  0,   0,   0   // 1EF
  120. };
  121. // Macro for return character together with status
  122. // Using in functions returning status their work
  123. //
  124. #define RETURN_S(ch,res)
  125. {
  126.     if (status) *status = res;
  127.     return ch;
  128. }
  129. // Macro for return character together with status and length 
  130. // Using in functions returning status and length their work
  131. //
  132. #define RETURN_LS(ch,len,res)
  133. {
  134.     if (seq_len) *seq_len = len;
  135.     if (status) *status = res;
  136.     return ch;
  137. }
  138. // Convert first UTF-8 symbol of "src" into ASCII-7 character.
  139. // "ascii_table" specifies whether to use ASCII-7 translation tables.
  140. // Length of the retrieved UTF-8 symbol is returned in "*seq_len"
  141. // (if "seq_len" is not NULL).
  142. // Return resulting ASCII-7 character.
  143. // NOTE:  If the UTF-8 symbol has no ASCII-7 equivalent, then return
  144. //        kOutrangeChar or hSkipChar.
  145. //
  146. char StringToChar(const string&      src,
  147.                   size_t*            seq_len,
  148.                   bool               ascii_table,
  149.                   EConversionStatus* status)
  150. {
  151.     long              dst_code;  // UTF-code symbol code
  152.     unsigned char     dst_char;  // Result character
  153.     EConversionStatus stat;      // Temporary status     
  154.     // Process one UTF character
  155.     dst_code = StringToCode(src, seq_len, &stat);
  156.     if (status) *status = stat;
  157.     // If it was happily
  158.     if (stat == eSuccess) {
  159.         // Conversion
  160.         if (ascii_table) {
  161.             // Convert into appropriate 7-bit character via conversion table 
  162.             dst_char = CodeToChar(dst_code, status);
  163.             return dst_char;
  164.         }    
  165.         else
  166.         {
  167.             // if character greater than 127 (0x7F) than substitute it 
  168.             // with kOutrangeChar, else leave it as is.
  169.             if (dst_code > 0x7F) {
  170.                 RETURN_S (kOutrangeChar, eOutrange);
  171.             }
  172.         }
  173.     }
  174.     // Was error translate char
  175.     return (char)dst_code;
  176. }
  177. // Convert UTF-8 string "src" into the ASCII-7 string with
  178. // graphically similar characters -- using StringToChar().
  179. // Return resulting ASCII-7 string.
  180. //
  181. string StringToAscii(const string& src, bool ascii_table)
  182. {
  183.     string  dst;      // String to result 
  184.     char    ch;       // Temporary UTF symbol code
  185.     size_t  utf_len;  // Length of UTF symbol
  186.     size_t  src_len;  // Length source string
  187.     src_len = src.size();
  188.     for (size_t i = 0; i < src_len; )
  189.     {
  190.         // Process one UTF character
  191.         ch = StringToChar(src.data() + i, &utf_len, ascii_table);
  192.         // Add character to the result vector
  193.         if ( ch != kSkipChar ) dst += ch;
  194.         i += utf_len;
  195.     }
  196.     return dst;
  197. }
  198. // Convert first UTF-8 symbol of "src" into a Unicode symbol code.
  199. // Length of the retrieved UTF-8 symbol is returned in "*seq_len"
  200. // (if "seq_len" is not NULL).
  201. // Return resulting Unicode symbol code.
  202. // NOTE:  If the UTF-8 symbol has no Unicode equivalent, then return
  203. //        kOutrangeChar or hSkipChar.
  204. //
  205. long StringToCode(const string&      src,
  206.                   size_t*            seq_len,
  207.                   EConversionStatus* status)
  208. {
  209.     unsigned char ch = src.data()[0];
  210.     size_t utf_len = 0;
  211.     long dst_code = 0;
  212.         
  213.     // If character less then 0x80 we put it as is
  214.     if (ch < 0x80)
  215.     {
  216.         RETURN_LS (ch, 1, eSuccess)
  217.     } 
  218.     else
  219.     {
  220.         // Determine the length of the UTF-8 symbol in bytes
  221.         if      ((ch & 0xFC) == 0xFC) utf_len = 6; // 6 bytes length
  222.         else if ((ch & 0xF8) == 0xF8) utf_len = 5; // 5 bytes length
  223.         else if ((ch & 0xF0) == 0xF0) utf_len = 4; // 4 bytes length
  224.         else if ((ch & 0xE0) == 0xE0) utf_len = 3; // 3 bytes length
  225.         else if ((ch & 0xC0) == 0xC0) utf_len = 2; // 2 bytes length
  226.         else
  227.         {
  228.             // Bad character. Save it as kOutrangeChar
  229.             RETURN_LS (kOutrangeChar, 1, eOutrange)
  230.         }
  231.     }
  232.     // Broken unicode sequence
  233.     if (utf_len > src.size()) {
  234.         RETURN_LS ((long)kSkipChar, 1, eSkip);
  235.     }
  236.         
  237.     unsigned char mask = 0xFF;
  238.     mask = mask >> utf_len; 
  239.     dst_code = ch & mask;
  240.     for (size_t j = 1; j < utf_len; j++)
  241.     {
  242.         dst_code = dst_code << 6;
  243.         ch = src.data()[j];
  244.         ch &= 0x3F;
  245.         dst_code = dst_code | ch;
  246.     }
  247.     // Return result
  248.     RETURN_LS (dst_code, utf_len, eSuccess)
  249. }
  250. // Convert UTF-8 string "src" into the vector of Unicode symbol codes
  251. // using StringToCode().
  252. // Return resulting vector.
  253. //
  254. vector<long> StringToVector (const string& src)
  255. {
  256.     vector<long> dst;      // String to result 
  257.     long         ch;       // Unicode symbol code
  258.     size_t       utf_len;  // Length of Unicode symbol
  259.     size_t       src_len;  // Length of source string
  260.     src_len = src.size();
  261.     for (size_t i = 0; i < src_len; )
  262.     {
  263.         // Process one UTF character
  264.         ch = StringToCode(src.data()+i, &utf_len);
  265.         // Add character to the result vector
  266.         dst.push_back(ch);
  267.         i += utf_len;
  268.     }
  269.     return dst;
  270. }
  271. // Translate Unicode symbol code "src" into graphically similar ASCII-7
  272. // character.
  273. // Return resulting ASCII-7 character.
  274. // NOTE:  If the Unicode symbol has no ASCII-7 equivalent, then return
  275. //        kOutrangeChar or hSkipChar.
  276. //
  277. char CodeToChar(const long src, EConversionStatus* status)
  278. {
  279.     unsigned char ch;
  280.     if (src < 0x80) RETURN_S ((char)src, eSuccess);
  281.     if ((src >= 0x0300) && (src <= 0x036F)) RETURN_S (kSkipChar, eSkip);
  282.     if ((src >= 0x1E00) && (src <= 0x1EFF))
  283.     {
  284.       ch = tblTransA[src-0x1E00];
  285.       if (!ch) RETURN_S (kOutrangeChar, eOutrange)
  286.       else     RETURN_S ((char)ch, eSuccess);
  287.     }
  288.     if ((src >= 0xFE20) && (src <= 0xFE2F)) RETURN_S (kSkipChar, eSkip);
  289.     if (src > 0x2FF) RETURN_S (kOutrangeChar, eOutrange);
  290.     ch = tblTrans[src-0x80];
  291.     if (!ch) RETURN_S (kOutrangeChar, eOutrange);
  292.     RETURN_S ((char)ch, eSuccess);
  293. }
  294. END_SCOPE(utf8)
  295. END_NCBI_SCOPE
  296. /*
  297.  * ===========================================================================
  298.  * $Log: utf8.cpp,v $
  299.  * Revision 1000.2  2004/06/01 19:40:43  gouriano
  300.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.6
  301.  *
  302.  * Revision 1.6  2004/05/17 21:06:02  gorelenk
  303.  * Added include of PCH ncbi_pch.hpp
  304.  *
  305.  * Revision 1.5  2002/01/24 20:10:21  vinokuro
  306.  * Skip characters processing has been fixed in StringToAscii function.
  307.  *
  308.  * Revision 1.4  2002/01/18 19:24:13  ivanov
  309.  * Changed result char's upper limit from 0xFF to 0x7F in StringToChar()
  310.  *
  311.  * Revision 1.3  2001/05/17 15:07:15  lavr
  312.  * Typos corrected
  313.  *
  314.  * Revision 1.2  2001/04/18 16:31:59  ivanov
  315.  * Change types TUnicodeChar, TUnicodeString to simple types.
  316.  * TUnicode char to long, TUnicodeString to vector<long>.
  317.  *
  318.  * Revision 1.1  2001/04/06 19:14:37  ivanov
  319.  * Initial revision
  320.  * ===========================================================================
  321.  */