zoukankan      html  css  js  c++  java
  • utf8 ucs4

    这个问题不好回答,首先UTF-8编码只不过是一种Unicode的转换,兼容ASCII。
    所以,UTF-8编码支持的最大字符编码应该是Unicode支持的最大字符编码。

    理论上,UTF-8编码可以支持最大6字节:
    00000000-0000007F 0xxxxxxx
    00000080-000007FF 110yyyxx 10xxxxxx
    00000800-0000FFFF 1110yyyy 10yyyyxx 10xxxxxx
    00010000-001FFFFF 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx
    00020000-03FFFFFF 111110aa 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx
    04000000-7FFFFFFF 1111110a 10aaaaaa 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx

    UCS4最多可以表示2^32个字符,但UTF-8最多只能表示2^31个字符,现实当中,Unicode规范根本就还没有规定这么多字符,目前最多也就规定到Plane 16,最多1114111个字符,所以网上关于UTF-8编码,大多截止到4字节:
    00000000-0000007F 0xxxxxxx
    00000080-000007FF 110yyyxx 10xxxxxx
    00000800-0000FFFF 1110yyyy 10yyyyxx 10xxxxxx
    00010000-0010FFFF 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx

    Unicode规范规定,10FFFE和10FFFF作为内部保留,所以Plane 16支持的最大字符编码是:10FFFD
    转换成UTF-8编码是:F48FBFBD

    但是,到底这个字符能否正常显示出来,还要看你系统里装的字体到底支持多少字符。

    所以,“utf-8里现在已经用到的字符最大编码是多少”这个问题的答案依赖于Unicode规范的版本、具体字体字库的支持。

    0x00-0x7F  同ASCII,也不可能作为任何其他多字节UTF-8字符的一部分
    0xC0-0xDF  多字节UTF-8字符的开始字节,而且据此可以判断出该UTF-8字符的长度(字节数)
    0x80-0xBF  多字节UTF-8字符的跟随字节
    0xFE-0xFF  UTF-8未使用

    > 字节数 位数 表示
    > 1 7 0bbbbbbb
    > 2 11 110bbbbb 10bbbbbb
    > 3 16 1110bbbb 10bbbbbb 10bbbbbb
    > 4 21 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
    > 5 26 111110bb 10bbbbbb 10bbbbbb 10bbbbbb 10bbbbbb
    > 6 31 1111110b 10bbbbbb 10bbbbbb 10bbbbbb 10bbbbbb 10bbbbbb
    > 7 36 11111110 10bbbbbb 10bbbbbb 10bbbbbb 10bbbbbb 10bbbbbb 10bbbbbb
    > 8 42 11111111 10bbbbbb 10bbbbbb 10bbbbbb 10bbbbbb 10bbbbbb 10bbbbbb 10bbbbbb

    typedef uint8 utf8;
    //typedef    uint16    utf16; // removed typedef to prevent usage, as utf16 is not supported (yet)
    typedef    uint32    utf32;
    
    
    
    // return number of code units in a null terminated string
        size_type utf_length(const utf8* utf8_str) const
        {
            size_type cnt = 0;
            while (*utf8_str++)
                cnt++;
    
            return cnt;
        }
    
        // return number of code units in a null terminated string
        size_type utf_length(const utf32* utf32_str) const
        {
            size_type cnt = 0;
            while (*utf32_str++)
                cnt++;
    
            return cnt;
        }

    上面是计算utf8所占的字节数和 utf32 占用的字节数

    // return number of utf32 code units required to re-encode given utf8 data as utf32.  len is number of code units in 'buf'.
        size_type encoded_size(const utf8* buf, size_type len) const
        {
            utf8 tcp;
            size_type count = 0;
    
            while (len--)
            {
                tcp = *buf++;
                ++count;
                size_type size = 0;
    
                if (tcp < 0x80)
                {
                }
                else if (tcp < 0xE0)
                {
                    size = 1;
                    ++buf;
                }
                else if (tcp < 0xF0)
                {
                    size = 2;
                    buf += 2;
                }
                else
                {
                    size = 3;
                    buf += 3;
                }
    
                if (len >= size)
                    len -= size;
                else 
                    break;
            }
    
            return count;
        }

    计算utf8的文字个数

    // return the number of utf8 code units required to encode the given utf32 code point
        size_type encoded_size(utf32 code_point) const
        {
            if (code_point < 0x80)
                return 1;
            else if (code_point < 0x0800)
                return 2;
            else if (code_point < 0x10000)
                return 3;
            else
                return 4;
        }

    计算ucs4的  转到utf8 的字节个数

    size_type encode(const utf8* src, utf32* dest, size_type dest_len, size_type src_len = 0) const
        {
            // count length for null terminated source...
            if (src_len == 0)
            {
                src_len = utf_length(src);
            }
    
            size_type destCapacity = dest_len;
    
            // while there is data in the source buffer, and space in the dest buffer
            for (uint idx = 0; ((idx < src_len) && (destCapacity > 0));)
            {
                utf32    cp;
                utf8    cu = src[idx++];
    
                if (cu < 0x80)
                {
                    cp = (utf32)(cu);
                }
                else if (cu < 0xE0)
                {
                    cp = ((cu & 0x1F) << 6);
                    cp |= (src[idx++] & 0x3F);
                }
                else if (cu < 0xF0)
                {
                    cp = ((cu & 0x0F) << 12);
                    cp |= ((src[idx++] & 0x3F) << 6);
                    cp |= (src[idx++] & 0x3F);
                }
                else
                {
                    cp = ((cu & 0x07) << 18);
                    cp |= ((src[idx++] & 0x3F) << 12);
                    cp |= ((src[idx++] & 0x3F) << 6);
                    cp |= (src[idx++] & 0x3F);
                }
    
                *dest++ = cp;
                --destCapacity;
            }
    
            return dest_len - destCapacity;
        }

    从utf8 转到utf32  即ucs4

    size_type encode(const utf32* src, utf8* dest, size_type dest_len, size_type src_len = 0) const
        {
            // count length for null terminated source...
            if (src_len == 0)
            {
                src_len = utf_length(src);
            }
    
            size_type destCapacity = dest_len;
    
            // while there is data in the source buffer,
            for (uint idx = 0; idx < src_len; ++idx)
            {
                utf32    cp = src[idx];
    
                // check there is enough destination buffer to receive this encoded unit (exit loop & return if not)
                if (destCapacity < encoded_size(cp))
                {
                    break;
                }
    
                if (cp < 0x80)
                {
                    *dest++ = (utf8)cp;
                    --destCapacity;
                }
                else if (cp < 0x0800)
                {
                    *dest++ = (utf8)((cp >> 6) | 0xC0);
                    *dest++ = (utf8)((cp & 0x3F) | 0x80);
                    destCapacity -= 2;
                }
                else if (cp < 0x10000)
                {
                    *dest++ = (utf8)((cp >> 12) | 0xE0);
                    *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
                    *dest++ = (utf8)((cp & 0x3F) | 0x80);
                    destCapacity -= 3;
                }
                else
                {
                    *dest++ = (utf8)((cp >> 18) | 0xF0);
                    *dest++ = (utf8)(((cp >> 12) & 0x3F) | 0x80);
                    *dest++ = (utf8)(((cp >> 6) & 0x3F) | 0x80);
                    *dest++ = (utf8)((cp & 0x3F) | 0x80);
                    destCapacity -= 4;
                }
    
            }
    
            return dest_len - destCapacity;
        }

    从utf32 转utf8

  • 相关阅读:
    innerHTML与innerText区别
    HTML5中的数据集dataset和自定义属性data-*
    HTTP协议
    Javascript 中的 && 和 || 使用小结
    JavaScript 实现回文解码
    sublime中用less实现css预编译
    jQuery事件绑定的四种方法
    前端学习过程中需要看的书籍
    Echarts学习宝典
    Vue插槽
  • 原文地址:https://www.cnblogs.com/dragon2012/p/5002628.html
Copyright © 2011-2022 走看看