ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

codecvt_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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.