coding_conv.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #ifndef _coding_conv_ns_h__
  2. #define _coding_conv_ns_h__
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string>
  6. #include <string.h>
  7. #if defined(_MSC_VER) || defined(WIN64) || defined(WIN32)
  8. #include <windows.h>
  9. #else
  10. #include <boost/locale.hpp>
  11. #endif
  12. namespace coding_conv_ns
  13. {
  14. static int preNUm(unsigned char byted) {
  15. unsigned char mask = 0x80;
  16. int num = 0;
  17. for (int i = 0; i < 8; i++) {
  18. if ((byted & mask) == mask) {
  19. mask = mask >> 1;
  20. num++;
  21. } else {
  22. break;
  23. }
  24. }
  25. return num;
  26. }
  27. static bool isUtf8(unsigned char* data, int len) {
  28. int num = 0;
  29. int i = 0;
  30. while (i < len) {
  31. if ((data[i] & 0x80) == 0x00) {
  32. // 0XXX_XXXX
  33. i++;
  34. continue;
  35. }
  36. else if ((num = preNUm(data[i])) > 2) {
  37. // 110X_XXXX 10XX_XXXX
  38. // 1110_XXXX 10XX_XXXX 10XX_XXXX
  39. // 1111_0XXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
  40. // 1111_10XX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
  41. // 1111_110X 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
  42. // preNUm() 返回首个字节8个bits中首??0bit前面1bit的个数,该数量也是该字符所使用的字节数
  43. i++;
  44. for(int j = 0; j < num - 1; j++) {
  45. //判断后面num - 1 个字节是不是都是10开
  46. if ((data[i] & 0xc0) != 0x80) {
  47. return false;
  48. }
  49. i++;
  50. }
  51. } else {
  52. //其他情况说明不是utf-8
  53. return false;
  54. }
  55. }
  56. return true;
  57. }
  58. static bool isGBK(unsigned char* data, int len) {
  59. int i = 0;
  60. while (i < len) {
  61. if (data[i] <= 0x7f) {
  62. //编码小于等于127,只有一个字节的编码,兼容ASCII
  63. i++;
  64. continue;
  65. } else {
  66. //大于127的使用双字节编码
  67. if (data[i] >= 0x81 &&
  68. data[i] <= 0xfe &&
  69. data[i + 1] >= 0x40 &&
  70. data[i + 1] <= 0xfe &&
  71. data[i + 1] != 0xf7) {
  72. i += 2;
  73. continue;
  74. } else {
  75. return false;
  76. }
  77. }
  78. }
  79. return true;
  80. }
  81. typedef enum {
  82. GBK,
  83. UTF8,
  84. UNKOWN
  85. } CODING;
  86. //需要说明的是,isGBK()是通过双字节是否落在gbk的编码范围内实现的,
  87. //而utf-8编码格式的每个字节都是落在gbk的编码范围内??
  88. //所以只有先调用isUtf8()先判断不是utf-8编码,再调用isGBK()才有意义
  89. static CODING GetCoding(const char* data, int len) {
  90. CODING coding;
  91. if (isUtf8((unsigned char*)(data), len) == true) {
  92. coding = UTF8;
  93. } else if (isGBK((unsigned char*)(data), len) == true) {
  94. coding = GBK;
  95. } else {
  96. coding = UNKOWN;
  97. }
  98. return coding;
  99. }
  100. #if defined(_MSC_VER) || defined(WIN64) || defined(WIN32)
  101. static std::string utf8_to_gbk_str(const char* src)
  102. {
  103. auto code = GetCoding(src, strlen(src));
  104. if (code != UTF8)
  105. {
  106. return src;
  107. }
  108. std::string gbkstr;
  109. wchar_t* pUnicodeBuff = NULL;
  110. int rlen = 0;
  111. rlen = MultiByteToWideChar(CP_UTF8, 0, src, -1, NULL, NULL);
  112. pUnicodeBuff = new wchar_t[rlen + 1]; //为Unicode字符串空间
  113. rlen = MultiByteToWideChar(CP_UTF8, 0, src, -1, pUnicodeBuff, rlen);
  114. rlen = WideCharToMultiByte(936, 0, pUnicodeBuff, -1, NULL, NULL, NULL, NULL); //936 为windows gb2312代码页码
  115. char* dstgbk = new char[rlen + 1];
  116. WideCharToMultiByte(936, 0, pUnicodeBuff, -1, dstgbk, rlen, NULL, NULL);
  117. delete[] pUnicodeBuff;
  118. gbkstr = dstgbk;
  119. delete[]dstgbk;
  120. return gbkstr;
  121. }
  122. static std::string gbk_to_utf8_str(const char* src)
  123. {
  124. auto code = GetCoding(src, strlen(src));
  125. if (code == UTF8)
  126. {
  127. return src;
  128. }
  129. int rlen = MultiByteToWideChar(936, 0, src, -1, NULL, NULL);
  130. wchar_t* pUnicodeBuff = new wchar_t[rlen + 1]; //为Unicode字符串空间
  131. rlen = MultiByteToWideChar(936, 0, src, -1, pUnicodeBuff, rlen);
  132. rlen = WideCharToMultiByte(CP_UTF8, 0, pUnicodeBuff, -1, NULL, NULL, NULL, NULL);
  133. char* dstutf8 = new char[rlen + 1];
  134. WideCharToMultiByte(CP_UTF8, 0, pUnicodeBuff, -1, dstutf8, rlen, NULL, NULL);
  135. delete[] pUnicodeBuff;
  136. std::string str = dstutf8;
  137. delete[]dstutf8;
  138. return str;
  139. }
  140. #else
  141. static std::string utf8_to_gbk_str(const char* src)
  142. {
  143. auto code = GetCoding(src, strlen(src));
  144. if (code == UTF8)
  145. {
  146. std::string strGBK = boost::locale::conv::from_utf(src, "GBK");
  147. return strGBK;
  148. }
  149. return src;
  150. }
  151. static std::string gbk_to_utf8_str(const char* src)
  152. {
  153. auto code =GetCoding(src, strlen(src));
  154. if (code == UTF8)
  155. {
  156. return src;
  157. }
  158. std::string strUTF8 = boost::locale::conv::to_utf<char>(src, "GBK");
  159. return strUTF8;
  160. }
  161. #endif // WIN32 || WIN64
  162. //在linux 下如果是 gbk则转换为utf8
  163. //在windows 下如果是 utf8则转换为gbk
  164. static std::string check_str_to_default(const char* str)
  165. {
  166. #if defined(_MSC_VER) || defined(WIN64) || defined(WIN32)
  167. if (GetCoding(str, strlen(str) == UTF8))
  168. {
  169. return utf8_to_gbk_str(str);
  170. }
  171. #else
  172. auto code = GetCoding(str, strlen(str));
  173. if (code != UTF8)
  174. {
  175. return gbk_to_utf8_str(str);
  176. }
  177. #endif
  178. return str;
  179. }
  180. }
  181. #endif // _coding_conv_ns_h__