/*-----------------------Own_lib函数库系列 utf8chars.cc------------------------ cy_utf8chars() /utf8chars.o /libcyfunc.a 描述: 对于国际通行的UTF-8编码字符串, 函数迭代处理以获得字符串的实际字符数(字符数 通过引用参数num_chars获得). 之所以整数采用unsigned short类型(检测的字符数最多不超过65536个), 是因为函数 采用顺序迭代算法, 若检测太长的字节序列则效率不高. src_str: 接受检测字符数的字符串指针. max_chars: 需要检测的最多字符个数限制, 若置之为0, 则检测直到字符串结束符'\0'. num_chars: 返回实际字串字符个数的指针参数. 返回值: 返回实际检测的字节数. 若检测到非法字符序列, 则返回-1. 注意! 传递的字符串必须是合法的UTF-8编码序列(且没有标志头). 作者: 任逍 |2002.05.26. 版权: GNU General (Library) Public License (GPL/LGPL) * 编辑器: vim-6.0 |操作系统: TurboLinux7.0简体中文版 * ------------------------------------------------------------------------------*/ #include "cyinclude/cyutf.h" #define MAX_CONV_CHARS 65535 // unsigned short int 的最大值 size_t cy_utf8chars(const unsigned char * src_str, size_t max_chars, size_t * num_chars = NULL) { int count_bytes = 0; size_t test_length = 0; size_t test_chars = 0; if (!src_str) return 0; if (max_chars == 0) max_chars = MAX_CONV_CHARS; while ( (src_str[test_length] != '\0') && (test_chars < max_chars) ) { for (;;) // 检测字节序列长度 { if (src_str[test_length] <= 0x7f){ count_bytes = 1; // ASCII字符: 0xxxxxxx( ~ 01111111) break; } if ( (src_str[test_length] >= 0xc0) && (src_str[test_length] <= 0xdf) ){ count_bytes = 2; // 110xxxxx(110 00000 ~ 110 111111) break; } if ( (src_str[test_length] >= 0xe0) && (src_str[test_length] <= 0xef) ){ count_bytes = 3; // 1110xxxx(1110 0000 ~ 1110 1111) break; } if ( (src_str[test_length] >= 0xf0) && (src_str[test_length] <= 0xf7) ){ count_bytes = 4; // 11110xxx(11110 000 ~ 11110 111) break; } if ( (src_str[test_length] >= 0xf8) && (src_str[test_length] <= 0xfb) ){ count_bytes = 5; // 111110xx(111110 00 ~ 111110 11) break; } if ( (src_str[test_length] >= 0xfc) && (src_str[test_length] <= 0xfd) ){ count_bytes = 6; // 1111110x(1111110 0 ~ 1111110 1) break; } return -1; // 以上皆不满足则为非法序列 } test_length += count_bytes; test_chars ++; } if (num_chars) *num_chars = test_chars; return test_length; }