Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencodecvt_test.cpp
Go to the documentation of this file.
00001 #include <string> 00002 00003 #if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS) 00004 # include <fstream> 00005 # include <locale> 00006 # include <stdexcept> 00007 # include <cstdio> // for WEOF 00008 00009 # include "cppunit/cppunit_proxy.h" 00010 00011 # if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES) 00012 using namespace std; 00013 # endif 00014 00015 // 00016 // TestCase class 00017 // 00018 class CodecvtTest : public CPPUNIT_NS::TestCase 00019 { 00020 CPPUNIT_TEST_SUITE(CodecvtTest); 00021 #if defined (STLPORT) && defined (_STLP_NO_MEMBER_TEMPLATES) 00022 CPPUNIT_IGNORE; 00023 #endif 00024 CPPUNIT_TEST(variable_encoding); 00025 CPPUNIT_STOP_IGNORE; 00026 #if defined (STLPORT) && (defined (_STLP_NO_WCHAR_T) || !defined (_STLP_USE_EXCEPTIONS)) 00027 CPPUNIT_IGNORE; 00028 #endif 00029 CPPUNIT_TEST(in_out_test); 00030 CPPUNIT_TEST(length_test); 00031 CPPUNIT_TEST(imbue_while_reading); 00032 CPPUNIT_TEST(special_encodings); 00033 CPPUNIT_TEST_SUITE_END(); 00034 00035 protected: 00036 void variable_encoding(); 00037 void in_out_test(); 00038 void length_test(); 00039 void imbue_while_reading(); 00040 void special_encodings(); 00041 }; 00042 00043 CPPUNIT_TEST_SUITE_REGISTRATION(CodecvtTest); 00044 00045 #if defined (STLPORT) 00046 # define __NO_THROW _STLP_NOTHROW 00047 #else 00048 # define __NO_THROW throw() 00049 #endif 00050 00051 00052 /* Codecvt facet eating some characters from the external buffer. 00053 * Transform '01' in 'a' 00054 */ 00055 struct eater_codecvt : public codecvt<char, char, mbstate_t> { 00056 typedef codecvt<char,char,mbstate_t> base; 00057 00058 explicit eater_codecvt(size_t refs = 0) : base(refs) {} 00059 00060 // primitive conversion 00061 virtual base::result 00062 do_in(mbstate_t& mb, 00063 const char* ebegin, const char* eend, const char*& ecur, 00064 char* ibegin, char* iend, char*& icur) const __NO_THROW { 00065 char *state = (char*)&mb; 00066 ecur = ebegin; 00067 icur = ibegin; 00068 00069 while (ecur != eend) { 00070 if (icur == iend) 00071 return partial; 00072 if (*ecur == '0' || *state == 1) { 00073 if (*state != 1) { 00074 ++ecur; 00075 } 00076 if (ecur == eend) { 00077 *state = 1; 00078 return ok; 00079 } 00080 00081 if (*ecur == '1') { 00082 *icur = 'a'; 00083 } 00084 else { 00085 *(icur++) = '0'; 00086 if (icur == iend) { 00087 if (*state != 1) { 00088 --ecur; 00089 } 00090 return partial; 00091 } 00092 *icur = *ecur; 00093 } 00094 } 00095 else { 00096 *icur = *ecur; 00097 } 00098 00099 *state = 0; 00100 ++icur; 00101 ++ecur; 00102 } 00103 00104 return ok; 00105 } 00106 00107 // claim it's not a null-conversion 00108 virtual bool do_always_noconv() const __NO_THROW 00109 { return false; } 00110 00111 // claim it doesn't have a fixed-length encoding 00112 virtual int do_encoding() const __NO_THROW 00113 { return 0; } 00114 00115 // implemented for consistency with do_in overload 00116 virtual int do_length(mbstate_t &state, 00117 const char *efrom, const char *eend, size_t m) const { 00118 char *ibegin = new char[m]; 00119 const char *ecur = efrom; 00120 char *icur = ibegin; 00121 mbstate_t tmp = state; 00122 do_in(tmp, efrom, eend, ecur, ibegin, ibegin + m, icur); 00123 delete[] ibegin; 00124 return ecur - efrom; 00125 } 00126 00127 virtual int do_max_length() const __NO_THROW 00128 { return 2; } 00129 00130 #ifdef __DMC__ 00131 static locale::id id; 00132 #endif 00133 }; 00134 00135 #ifdef __DMC__ 00136 locale::id eater_codecvt::id; 00137 00138 locale::id& _GetFacetId(const eater_codecvt*) 00139 { return eater_codecvt::id; } 00140 #endif 00141 00142 /* Codecvt facet generating more characters than the ones read from the 00143 * external buffer, transform '01' in 'abc' 00144 * This kind of facet do not allow systematical positionning in the external 00145 * buffer (tellg -> -1), when you just read a 'a' you are at an undefined 00146 * external buffer position. 00147 */ 00148 struct generator_codecvt : public codecvt<char, char, mbstate_t> { 00149 typedef codecvt<char,char,mbstate_t> base; 00150 00151 explicit generator_codecvt(size_t refs = 0) : base(refs) {} 00152 00153 // primitive conversion 00154 virtual base::result 00155 do_in(mbstate_t& mb, 00156 const char* ebegin, const char* eend, const char*& ecur, 00157 char* ibegin, char* iend, char*& icur) const __NO_THROW { 00158 //Access the mbstate information in a portable way: 00159 char *state = (char*)&mb; 00160 ecur = ebegin; 00161 icur = ibegin; 00162 00163 if (icur == iend) return ok; 00164 00165 if (*state == 2) { 00166 *(icur++) = 'b'; 00167 if (icur == iend) { 00168 *state = 3; 00169 return ok; 00170 } 00171 *(icur++) = 'c'; 00172 *state = 0; 00173 } 00174 else if (*state == 3) { 00175 *(icur++) = 'c'; 00176 *state = 0; 00177 } 00178 00179 while (ecur != eend) { 00180 if (icur == iend) 00181 return ok; 00182 if (*ecur == '0' || *state == 1) { 00183 if (*state != 1) { 00184 ++ecur; 00185 } 00186 if (ecur == eend) { 00187 *state = 1; 00188 return partial; 00189 } 00190 00191 if (*ecur == '1') { 00192 *(icur++) = 'a'; 00193 if (icur == iend) { 00194 *state = 2; 00195 return ok; 00196 } 00197 *(icur++) = 'b'; 00198 if (icur == iend) { 00199 *state = 3; 00200 return ok; 00201 } 00202 *icur = 'c'; 00203 } 00204 else { 00205 *(icur++) = '0'; 00206 if (icur == iend) { 00207 if (*state != 1) { 00208 --ecur; 00209 } 00210 return ok; 00211 } 00212 *icur = *ecur; 00213 } 00214 } 00215 else { 00216 *icur = *ecur; 00217 } 00218 00219 *state = 0; 00220 ++icur; 00221 ++ecur; 00222 } 00223 00224 return ok; 00225 } 00226 00227 // claim it's not a null-conversion 00228 virtual bool do_always_noconv() const __NO_THROW 00229 { return false; } 00230 00231 // claim it doesn't have a fixed-length encoding 00232 virtual int do_encoding() const __NO_THROW 00233 { return 0; } 00234 00235 // implemented for consistency with do_in overload 00236 virtual int do_length(mbstate_t &mb, 00237 const char *efrom, const char *eend, size_t m) const { 00238 const char *state = (const char*)&mb; 00239 int offset = 0; 00240 if (*state == 2) 00241 offset = 2; 00242 else if (*state == 3) 00243 offset = 1; 00244 00245 char *ibegin = new char[m + offset]; 00246 const char *ecur = efrom; 00247 char *icur = ibegin; 00248 mbstate_t tmpState = mb; 00249 do_in(tmpState, efrom, eend, ecur, ibegin, ibegin + m + offset, icur); 00250 /* 00251 char *state = (char*)&tmpState; 00252 if (*state != 0) { 00253 if (*state == 1) 00254 --ecur; 00255 else if (*state == 2 || *state == 3) { 00256 //Undefined position, we return -1: 00257 ecur = efrom - 1; 00258 } 00259 } 00260 else { 00261 if (*((char*)&mb) != 0) { 00262 //We take into account the character that hasn't been counted yet in 00263 //the previous decoding step: 00264 ecur++; 00265 } 00266 } 00267 */ 00268 delete[] ibegin; 00269 return (int)min((size_t)(ecur - efrom), m); 00270 } 00271 00272 virtual int do_max_length() const __NO_THROW 00273 { return 0; } 00274 #ifdef __DMC__ 00275 static locale::id id; 00276 #endif 00277 }; 00278 00279 #ifdef __DMC__ 00280 locale::id generator_codecvt::id; 00281 00282 locale::id& _GetFacetId(const generator_codecvt*) 00283 { return generator_codecvt::id; } 00284 #endif 00285 00286 // 00287 // tests implementation 00288 // 00289 void CodecvtTest::variable_encoding() 00290 { 00291 #if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES) 00292 //We first generate the file used for test: 00293 const char* fileName = "test_file.txt"; 00294 { 00295 ofstream ostr(fileName); 00296 //Maybe we simply do not have write access to repository 00297 CPPUNIT_ASSERT( ostr.good() ); 00298 for (int i = 0; i < 2048; ++i) { 00299 ostr << "0123456789"; 00300 } 00301 CPPUNIT_ASSERT( ostr.good() ); 00302 } 00303 00304 { 00305 ifstream istr(fileName); 00306 CPPUNIT_ASSERT( istr.good() ); 00307 CPPUNIT_ASSERT( !istr.eof() ); 00308 00309 eater_codecvt codec(1); 00310 locale loc(locale::classic(), &codec); 00311 00312 istr.imbue(loc); 00313 CPPUNIT_ASSERT( istr.good() ); 00314 CPPUNIT_ASSERT( (int)istr.tellg() == 0 ); 00315 00316 int theoricalPos = 0; 00317 do { 00318 int c = istr.get(); 00319 if (char_traits<char>::eq_int_type(c, char_traits<char>::eof())) { 00320 break; 00321 } 00322 ++theoricalPos; 00323 if (c == 'a') { 00324 ++theoricalPos; 00325 } 00326 00327 CPPUNIT_ASSERT( (int)istr.tellg() == theoricalPos ); 00328 } 00329 while (!istr.eof()); 00330 00331 CPPUNIT_ASSERT( istr.eof() ); 00332 } 00333 00334 # if 0 00335 /* This test is broken, not sure if it is really possible to get a position in 00336 * a locale having a codecvt such as generator_codecvt. Maybe generator_codecvt 00337 * is not a valid theorical example of codecvt implementation. */ 00338 { 00339 ifstream istr(fileName); 00340 CPPUNIT_ASSERT( istr.good() ); 00341 CPPUNIT_ASSERT( !istr.eof() ); 00342 00343 generator_codecvt codec(1); 00344 locale loc(locale::classic(), &codec); 00345 00346 istr.imbue(loc); 00347 CPPUNIT_ASSERT( istr.good() ); 00348 CPPUNIT_ASSERT( (int)istr.tellg() == 0 ); 00349 00350 int theoricalPos = 0; 00351 int theoricalTellg; 00352 do { 00353 char c = istr.get(); 00354 if (c == char_traits<char>::eof()) { 00355 break; 00356 } 00357 switch (c) { 00358 case 'a': 00359 case 'b': 00360 theoricalTellg = -1; 00361 break; 00362 case 'c': 00363 ++theoricalPos; 00364 default: 00365 ++theoricalPos; 00366 theoricalTellg = theoricalPos; 00367 break; 00368 } 00369 00370 if ((int)istr.tellg() != theoricalTellg) { 00371 CPPUNIT_ASSERT( (int)istr.tellg() == theoricalTellg ); 00372 } 00373 } 00374 while (!istr.eof()); 00375 00376 CPPUNIT_ASSERT( istr.eof() ); 00377 } 00378 # endif 00379 #endif 00380 } 00381 00382 void CodecvtTest::in_out_test() 00383 { 00384 #if !defined (STLPORT) || !(defined (_STLP_NO_WCHAR_T) || !defined (_STLP_USE_EXCEPTIONS)) 00385 try { 00386 locale loc(""); 00387 00388 typedef codecvt<wchar_t, char, mbstate_t> cdecvt_type; 00389 if (has_facet<cdecvt_type>(loc)) { 00390 cdecvt_type const& cdect = use_facet<cdecvt_type>(loc); 00391 { 00392 cdecvt_type::state_type state; 00393 memset(&state, 0, sizeof(cdecvt_type::state_type)); 00394 string from("abcdef"); 00395 const char* next_from; 00396 wchar_t to[1]; 00397 wchar_t *next_to; 00398 cdecvt_type::result res = cdect.in(state, from.data(), from.data() + from.size(), next_from, 00399 to, to + sizeof(to) / sizeof(wchar_t), next_to); 00400 CPPUNIT_ASSERT( res == cdecvt_type::ok ); 00401 CPPUNIT_ASSERT( next_from == from.data() + 1 ); 00402 CPPUNIT_ASSERT( next_to == &to[0] + 1 ); 00403 CPPUNIT_ASSERT( to[0] == L'a'); 00404 } 00405 { 00406 cdecvt_type::state_type state; 00407 memset(&state, 0, sizeof(cdecvt_type::state_type)); 00408 wstring from(L"abcdef"); 00409 const wchar_t* next_from; 00410 char to[1]; 00411 char *next_to; 00412 cdecvt_type::result res = cdect.out(state, from.data(), from.data() + from.size(), next_from, 00413 to, to + sizeof(to) / sizeof(char), next_to); 00414 CPPUNIT_ASSERT( res == cdecvt_type::ok ); 00415 CPPUNIT_ASSERT( next_from == from.data() + 1 ); 00416 CPPUNIT_ASSERT( next_to == &to[0] + 1 ); 00417 CPPUNIT_ASSERT( to[0] == 'a'); 00418 } 00419 } 00420 } 00421 catch (runtime_error const&) { 00422 } 00423 catch (...) { 00424 CPPUNIT_FAIL; 00425 } 00426 #endif 00427 } 00428 00429 void CodecvtTest::length_test() 00430 { 00431 #if !defined (STLPORT) || !(defined (_STLP_NO_WCHAR_T) || !defined (_STLP_USE_EXCEPTIONS)) 00432 try { 00433 locale loc(""); 00434 00435 typedef codecvt<wchar_t, char, mbstate_t> cdecvt_type; 00436 if (has_facet<cdecvt_type>(loc)) { 00437 cdecvt_type const& cdect = use_facet<cdecvt_type>(loc); 00438 { 00439 cdecvt_type::state_type state; 00440 memset(&state, 0, sizeof(cdecvt_type::state_type)); 00441 string from("abcdef"); 00442 int res = cdect.length(state, from.data(), from.data() + from.size(), from.size()); 00443 CPPUNIT_ASSERT( (size_t)res == from.size() ); 00444 } 00445 } 00446 } 00447 catch (runtime_error const&) { 00448 } 00449 catch (...) { 00450 CPPUNIT_FAIL; 00451 } 00452 #endif 00453 } 00454 00455 #if !defined (STLPORT) || !(defined (_STLP_NO_WCHAR_T) || !defined (_STLP_USE_EXCEPTIONS)) 00456 typedef std::codecvt<wchar_t, char, mbstate_t> my_codecvt_base; 00457 00458 class my_codecvt : public my_codecvt_base { 00459 public: 00460 explicit my_codecvt(size_t r = 0) 00461 : my_codecvt_base(r) {} 00462 00463 protected: 00464 virtual result do_in(state_type& /*state*/, const extern_type* first1, 00465 const extern_type* last1, const extern_type*& next1, 00466 intern_type* first2, intern_type* last2, 00467 intern_type*& next2) const { 00468 for ( next1 = first1, next2 = first2; next1 < last1; next1 += 2 ) { 00469 if ( (last1 - next1) < 2 || (last2 - next2) < 1 ) 00470 return partial; 00471 *next2++ = (intern_type)((*(next1 + 1) << 8) | (*next1 & 255)); 00472 } 00473 return ok; 00474 } 00475 virtual bool do_always_noconv() const __NO_THROW 00476 { return false; } 00477 virtual int do_max_length() const __NO_THROW 00478 { return 2; } 00479 virtual int do_encoding() const __NO_THROW 00480 { return 2; } 00481 }; 00482 #endif 00483 00484 void CodecvtTest::imbue_while_reading() 00485 { 00486 #if !defined (STLPORT) || !(defined (_STLP_NO_WCHAR_T) || !defined (_STLP_USE_EXCEPTIONS)) 00487 { 00488 wofstream ofs( "test.txt" ); 00489 const wchar_t buf[] = L" "; 00490 for ( int i = 0; i < 4098; ++i ) { 00491 ofs << buf[0]; 00492 } 00493 } 00494 00495 wifstream ifs("test.txt"); // a file containing 4098 wchars 00496 00497 ifs.imbue( locale(locale(), new my_codecvt) ); 00498 ifs.get(); 00499 ifs.seekg(0); 00500 ifs.imbue( locale() ); 00501 ifs.ignore(4096); 00502 int ch = ifs.get(); 00503 CPPUNIT_CHECK( ch != (int)WEOF ); 00504 #endif 00505 } 00506 00507 void CodecvtTest::special_encodings() 00508 { 00509 #if !defined (STLPORT) || (!defined (_STLP_NO_WCHAR_T) && defined (_STLP_USE_EXCEPTIONS)) 00510 { 00511 locale loc(locale::classic(), new codecvt_byname<wchar_t, char, mbstate_t>("C")); 00512 codecvt<wchar_t, char, mbstate_t> const& cvt = use_facet<codecvt<wchar_t, char, mbstate_t> >(loc); 00513 mbstate_t state; 00514 memset(&state, 0, sizeof(mbstate_t)); 00515 char c = '0'; 00516 const char *from_next; 00517 wchar_t wc; 00518 wchar_t *to_next; 00519 CPPUNIT_ASSERT( cvt.in(state, &c, &c + 1, from_next, &wc, &wc, to_next) == codecvt_base::ok ); 00520 CPPUNIT_ASSERT( to_next == &wc ); 00521 CPPUNIT_ASSERT( cvt.in(state, &c, &c + 1, from_next, &wc, &wc + 1, to_next) == codecvt_base::ok ); 00522 CPPUNIT_ASSERT( wc == L'0' ); 00523 CPPUNIT_ASSERT( to_next == &wc + 1 ); 00524 } 00525 try 00526 { 00527 wstring cp936_wstr; 00528 const string cp936_str = "\xd6\xd0\xb9\xfa\xc9\xe7\xbb\xe1\xbf\xc6\xd1\xa7\xd4\xba\xb7\xa2\xb2\xbc\x32\x30\x30\x38\xc4\xea\xa1\xb6\xbe\xad\xbc\xc3\xc0\xb6\xc6\xa4\xca\xe9\xa1\xb7\xd6\xb8\xb3\xf6\xa3\xac\x32\x30\x30\x37\xc4\xea\xd6\xd0\xb9\xfa\xbe\xad\xbc\xc3\xd4\xf6\xb3\xa4\xd3\xc9\xc6\xab\xbf\xec\xd7\xaa\xcf\xf2\xb9\xfd\xc8\xc8\xb5\xc4\xc7\xf7\xca\xc6\xc3\xf7\xcf\xd4\xd4\xa4\xbc\xc6\xc8\xab\xc4\xea\x47\x44\x50\xd4\xf6\xcb\xd9\xbd\xab\xb4\xef\x31\x31\x2e\x36\x25\xa1\xa3"; 00529 locale loc(locale::classic(), ".936", locale::ctype); 00530 codecvt<wchar_t, char, mbstate_t> const& cvt = use_facet<codecvt<wchar_t, char, mbstate_t> >(loc); 00531 mbstate_t state; 00532 memset(&state, 0, sizeof(mbstate_t)); 00533 00534 codecvt_base::result res; 00535 00536 { 00537 wchar_t wbuf[4096]; 00538 // Check we will have enough room for the generated wide string generated from the whole char buffer: 00539 int len = cvt.length(state, cp936_str.data(), cp936_str.data() + cp936_str.size(), sizeof(wbuf) / sizeof(wchar_t)); 00540 CPPUNIT_ASSERT( cp936_str.size() == (size_t)len ); 00541 00542 const char *from_next; 00543 wchar_t *to_next; 00544 res = cvt.in(state, cp936_str.data(), cp936_str.data() + cp936_str.size(), from_next, 00545 wbuf, wbuf + sizeof(wbuf) / sizeof(wchar_t), to_next); 00546 CPPUNIT_ASSERT( res == codecvt_base::ok ); 00547 CPPUNIT_ASSERT( from_next == cp936_str.data() + cp936_str.size() ); 00548 cp936_wstr.assign(wbuf, to_next); 00549 } 00550 00551 { 00552 const wchar_t *from_next; 00553 char buf[4096]; 00554 char *to_next; 00555 res = cvt.out(state, cp936_wstr.data(), cp936_wstr.data() + cp936_wstr.size(), from_next, 00556 buf, buf + sizeof(buf), to_next); 00557 CPPUNIT_ASSERT( res == codecvt_base::ok ); 00558 CPPUNIT_CHECK( string(buf, to_next) == cp936_str ); 00559 } 00560 } 00561 catch (const runtime_error&) 00562 { 00563 CPPUNIT_MESSAGE("Not enough platform localization support to check 936 code page encoding."); 00564 } 00565 try 00566 { 00567 const string utf8_str = "\xe4\xb8\xad\xe5\x9b\xbd\xe7\xa4\xbe\xe4\xbc\x9a\xe7\xa7\x91\xe5\xad\xa6\xe9\x99\xa2\xe5\x8f\x91\xe5\xb8\x83\x32\x30\x30\x38\xe5\xb9\xb4\xe3\x80\x8a\xe7\xbb\x8f\xe6\xb5\x8e\xe8\x93\x9d\xe7\x9a\xae\xe4\xb9\xa6\xe3\x80\x8b\xe6\x8c\x87\xe5\x87\xba\xef\xbc\x8c\x32\x30\x30\x37\xe5\xb9\xb4\xe4\xb8\xad\xe5\x9b\xbd\xe7\xbb\x8f\xe6\xb5\x8e\xe5\xa2\x9e\xe9\x95\xbf\xe7\x94\xb1\xe5\x81\x8f\xe5\xbf\xab\xe8\xbd\xac\xe5\x90\x91\xe8\xbf\x87\xe7\x83\xad\xe7\x9a\x84\xe8\xb6\x8b\xe5\x8a\xbf\xe6\x98\x8e\xe6\x98\xbe\xe9\xa2\x84\xe8\xae\xa1\xe5\x85\xa8\xe5\xb9\xb4\x47\x44\x50\xe5\xa2\x9e\xe9\x80\x9f\xe5\xb0\x86\xe8\xbe\xbe\x31\x31\x2e\x36\x25\xe3\x80\x82"; 00568 wstring utf8_wstr; 00569 locale loc(locale::classic(), new codecvt_byname<wchar_t, char, mbstate_t>(".utf8")); 00570 codecvt<wchar_t, char, mbstate_t> const& cvt = use_facet<codecvt<wchar_t, char, mbstate_t> >(loc); 00571 mbstate_t state; 00572 memset(&state, 0, sizeof(mbstate_t)); 00573 00574 codecvt_base::result res; 00575 00576 { 00577 wchar_t wbuf[4096]; 00578 // Check we will have enough room for the wide string generated from the whole char buffer: 00579 int len = cvt.length(state, utf8_str.data(), utf8_str.data() + utf8_str.size(), sizeof(wbuf) / sizeof(wchar_t)); 00580 CPPUNIT_ASSERT( utf8_str.size() == (size_t)len ); 00581 00582 const char *from_next; 00583 wchar_t *to_next; 00584 res = cvt.in(state, utf8_str.data(), utf8_str.data() + utf8_str.size(), from_next, 00585 wbuf, wbuf + sizeof(wbuf) / sizeof(wchar_t), to_next); 00586 CPPUNIT_ASSERT( res == codecvt_base::ok ); 00587 CPPUNIT_ASSERT( from_next == utf8_str.data() + utf8_str.size() ); 00588 utf8_wstr.assign(wbuf, to_next); 00589 00590 // Try to read one char after the other: 00591 wchar_t wc; 00592 const char* from = utf8_str.data(); 00593 const char* from_end = from + utf8_str.size(); 00594 from_next = utf8_str.data(); 00595 size_t length = 1; 00596 size_t windex = 0; 00597 while (from + length <= from_end) { 00598 res = cvt.in(state, from, from + length, from_next, 00599 &wc, &wc + 1, to_next); 00600 switch (res) { 00601 case codecvt_base::ok: 00602 // reset length: 00603 from = from_next; 00604 length = 1; 00605 CPPUNIT_ASSERT( wc == utf8_wstr[windex++] ); 00606 wc = 0; 00607 break; 00608 case codecvt_base::partial: 00609 if (from_next == from) 00610 // from_next hasn't move so we have to pass more chars 00611 ++length; 00612 else 00613 // char between from and from_next has been eaten, we simply restart 00614 // conversion from from_next: 00615 from = from_next; 00616 continue; 00617 case codecvt_base::error: 00618 case codecvt_base::noconv: 00619 CPPUNIT_FAIL; 00620 //break; 00621 } 00622 } 00623 CPPUNIT_ASSERT( windex == utf8_wstr.size() ); 00624 } 00625 00626 { 00627 const wchar_t *from_next; 00628 char buf[4096]; 00629 char *to_next; 00630 res = cvt.out(state, utf8_wstr.data(), utf8_wstr.data() + utf8_wstr.size(), from_next, 00631 buf, buf + sizeof(buf), to_next); 00632 CPPUNIT_ASSERT( res == codecvt_base::ok ); 00633 CPPUNIT_CHECK( string(buf, to_next) == utf8_str ); 00634 } 00635 00636 { 00637 // Check that an obviously wrong UTF8 encoded string is correctly detected: 00638 const string bad_utf8_str("\xdf\xdf\xdf\xdf\xdf"); 00639 wchar_t wc; 00640 const char *from_next; 00641 wchar_t *to_next; 00642 res = cvt.in(state, bad_utf8_str.data(), bad_utf8_str.data() + bad_utf8_str.size(), from_next, 00643 &wc, &wc + 1, to_next); 00644 CPPUNIT_ASSERT( res == codecvt_base::error ); 00645 } 00646 } 00647 catch (const runtime_error&) 00648 { 00649 CPPUNIT_MESSAGE("Not enough platform localization support to check UTF8 encoding."); 00650 } 00651 #endif 00652 } 00653 00654 #endif Generated on Sun May 27 2012 04:35:20 for ReactOS by
1.7.6.1
|