00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "adchpp.h"
00020
00021 #include "Text.h"
00022
00023 #include "Util.h"
00024
00025 using namespace std;
00026
00027 namespace adchpp {
00028
00029 int Text::utf8ToWc(const char* str, wchar_t& c) {
00030 uint8_t c0 = (uint8_t)str[0];
00031 if(c0 & 0x80) {
00032 if(c0 & 0x40) {
00033 if(c0 & 0x20) {
00034 if(c0 & 0x10) {
00035 int n = -4;
00036 if(c0 & 0x08) {
00037 n = -5;
00038 if(c0 & 0x04) {
00039 if(c0 & 0x02) {
00040 return -1;
00041 }
00042 n = -6;
00043 }
00044 }
00045 int i = -1;
00046 while(i > n && (str[abs(i)] & 0x80) == 0x80)
00047 --i;
00048 return i;
00049 } else {
00050 uint8_t c1 = (uint8_t)str[1];
00051 if((c1 & (0x80 | 0x40)) != 0x80)
00052 return -1;
00053
00054 uint8_t c2 = (uint8_t)str[2];
00055 if((c2 & (0x80 | 0x40)) != 0x80)
00056 return -2;
00057
00058
00059 if((c0 & 0x0f) == 0x0d && (c1 & 0x3c) >= (0x08 << 2))
00060 return -3;
00061
00062
00063 if(c0 == (0x80 | 0x40 | 0x20) && (c1 & (0x80 | 0x40 | 0x20)) == 0x80)
00064 return -3;
00065
00066 c = (((wchar_t)c0 & 0x0f) << 12) |
00067 (((wchar_t)c1 & 0x3f) << 6) |
00068 ((wchar_t)c2 & 0x3f);
00069
00070 return 3;
00071 }
00072 } else {
00073 uint8_t c1 = (uint8_t)str[1];
00074 if((c1 & (0x80 | 0x40)) != 0x80)
00075 return -1;
00076
00077
00078 if((c0 & ~1) == (0x80 | 0x40))
00079 return -2;
00080
00081 c = (((wchar_t)c0 & 0x1f) << 6) |
00082 ((wchar_t)c1 & 0x3f);
00083 return 2;
00084 }
00085 } else {
00086 return -1;
00087 }
00088 } else {
00089 c = (unsigned char)str[0];
00090 return 1;
00091 }
00092 dcassert(0);
00093 }
00094
00095 void Text::wcToUtf8(wchar_t c, string& str) {
00096 if(c >= 0x0800) {
00097 str += (char)(0x80 | 0x40 | 0x20 | (c >> 12));
00098 str += (char)(0x80 | ((c >> 6) & 0x3f));
00099 str += (char)(0x80 | (c & 0x3f));
00100 } else if(c >= 0x0080) {
00101 str += (char)(0x80 | 0x40 | (c >> 6));
00102 str += (char)(0x80 | (c & 0x3f));
00103 } else {
00104 str += (char)c;
00105 }
00106 }
00107
00108 const string& Text::acpToUtf8(const string& str, string& tmp) throw() {
00109 wstring wtmp;
00110 return wideToUtf8(acpToWide(str, wtmp), tmp);
00111 }
00112
00113 const wstring& Text::acpToWide(const string& str, wstring& tmp) throw() {
00114 if(str.empty())
00115 return Util::emptyStringW;
00116 #ifdef _WIN32
00117 int n = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str.c_str(), (int)str.length(), NULL, 0);
00118 if(n == 0) {
00119 return Util::emptyStringW;
00120 }
00121
00122 tmp.resize(n);
00123 n = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str.c_str(), (int)str.length(), &tmp[0], n);
00124 if(n == 0) {
00125 return Util::emptyStringW;
00126 }
00127 return tmp;
00128 #else
00129 size_t rv;
00130 wchar_t wc;
00131 const char *src = str.c_str();
00132 size_t n = str.length() + 1;
00133
00134 tmp.clear();
00135 tmp.reserve(n);
00136
00137 while(n > 0) {
00138 rv = mbrtowc(&wc, src, n, NULL);
00139 if(rv == 0 || rv == (size_t)-2) {
00140 break;
00141 } else if(rv == (size_t)-1) {
00142 tmp.push_back(L'_');
00143 ++src;
00144 --n;
00145 } else {
00146 tmp.push_back(wc);
00147 src += rv;
00148 n -= rv;
00149 }
00150 }
00151 return tmp;
00152 #endif
00153 }
00154
00155 const string& Text::wideToUtf8(const wstring& str, string& tgt) throw() {
00156 if(str.empty()) {
00157 return Util::emptyString;
00158 }
00159
00160 string::size_type n = str.length();
00161 tgt.clear();
00162 for(string::size_type i = 0; i < n; ++i) {
00163 wcToUtf8(str[i], tgt);
00164 }
00165 return tgt;
00166 }
00167
00168 const string& Text::wideToAcp(const wstring& str, string& tmp) throw() {
00169 if(str.empty())
00170 return Util::emptyString;
00171 #ifdef _WIN32
00172 int n = WideCharToMultiByte(CP_ACP, 0, str.c_str(), (int)str.length(), NULL, 0, NULL, NULL);
00173 if(n == 0) {
00174 return Util::emptyString;
00175 }
00176
00177 tmp.resize(n);
00178 n = WideCharToMultiByte(CP_ACP, 0, str.c_str(), (int)str.length(), &tmp[0], n, NULL, NULL);
00179 if(n == 0) {
00180 return Util::emptyString;
00181 }
00182 return tmp;
00183 #else
00184 const wchar_t* src = str.c_str();
00185 int n = wcsrtombs(NULL, &src, 0, NULL);
00186 if(n < 1) {
00187 return Util::emptyString;
00188 }
00189 src = str.c_str();
00190 tmp.resize(n);
00191 n = wcsrtombs(&tmp[0], &src, n, NULL);
00192 if(n < 1) {
00193 return Util::emptyString;
00194 }
00195 return tmp;
00196 #endif
00197 }
00198
00199 bool Text::validateUtf8(const string& str) throw() {
00200 string::size_type i = 0;
00201 while(i < str.length()) {
00202 wchar_t dummy = 0;
00203 int j = utf8ToWc(&str[i], dummy);
00204 if(j < 0)
00205 return false;
00206 i += j;
00207 }
00208 return true;
00209 }
00210
00211 const string& Text::utf8ToAcp(const string& str, string& tmp) throw() {
00212 wstring wtmp;
00213 return wideToAcp(utf8ToWide(str, wtmp), tmp);
00214 }
00215
00216 const wstring& Text::utf8ToWide(const string& str, wstring& tgt) throw() {
00217 tgt.reserve(str.length());
00218 string::size_type n = str.length();
00219 for(string::size_type i = 0; i < n; ) {
00220 wchar_t c = 0;
00221 int x = utf8ToWc(str.c_str() + i, c);
00222 if(x < 0) {
00223 tgt += '_';
00224 i += abs(x);
00225 } else {
00226 i += x;
00227 tgt += c;
00228 }
00229 }
00230 return tgt;
00231 }
00232
00233 string Text::acpToUtf8(const string& str) throw() {
00234 string tmp;
00235 return acpToUtf8(str, tmp);
00236 }
00237
00238 wstring Text::acpToWide(const string& str) throw() {
00239 wstring tmp;
00240 return acpToWide(str, tmp);
00241 }
00242
00243 string Text::utf8ToAcp(const string& str) throw() {
00244 string tmp;
00245 return utf8ToAcp(str, tmp);
00246 }
00247
00248 wstring Text::utf8ToWide(const string& str) throw() {
00249 wstring tmp;
00250 return utf8ToWide(str, tmp);
00251 }
00252
00253 string Text::wideToAcp(const wstring& str) throw() {
00254 string tmp;
00255 return wideToAcp(str, tmp);
00256 }
00257
00258 string Text::wideToUtf8(const wstring& str) throw() {
00259 string tmp;
00260 return wideToUtf8(str, tmp);
00261 }
00262
00263 }