First public contribution.
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
18 #if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
22 # include "cppunit/cppunit_proxy.h"
24 # if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
31 class CodecvtTest : public CPPUNIT_NS::TestCase
33 CPPUNIT_TEST_SUITE(CodecvtTest);
34 #if defined (STLPORT) && defined (_STLP_NO_MEMBER_TEMPLATES)
37 CPPUNIT_TEST(variable_encoding);
38 CPPUNIT_TEST(locale_cov1);
39 CPPUNIT_TEST(locale_cov2);
40 CPPUNIT_TEST(locale_cov3);
41 CPPUNIT_TEST(locale_cov4);
42 CPPUNIT_TEST(locale_cov5);
43 CPPUNIT_TEST(locale_cov6);
44 CPPUNIT_TEST(locale_cov7);
45 CPPUNIT_TEST_SUITE_END();
48 void variable_encoding();
58 CPPUNIT_TEST_SUITE_REGISTRATION(CodecvtTest);
61 # define __NO_THROW _STLP_NOTHROW
63 # define __NO_THROW throw()
67 /* Codecvt facet eating some characters from the external buffer.
68 * Transform '01' in 'a'
70 struct eater_codecvt : public codecvt<char, char, mbstate_t> {
71 typedef codecvt<char,char,mbstate_t> base;
73 explicit eater_codecvt(size_t refs = 0) : base(refs) {}
75 // primitive conversion
78 const char* ebegin, const char* eend, const char*& ecur,
79 char* ibegin, char* iend, char*& icur) const __NO_THROW {
80 char *state = (char*)&mb;
84 while (ecur != eend) {
87 if (*ecur == '0' || *state == 1) {
122 // claim it's not a null-conversion
123 virtual bool do_always_noconv() const __NO_THROW
126 // claim it doesn't have a fixed-length encoding
127 virtual int do_encoding() const __NO_THROW
130 // implemented for consistency with do_in overload
131 virtual int do_length(const mbstate_t &state,
132 const char *efrom, const char *eend, size_t m) const {
133 char *ibegin = new char[m];
134 const char *ecur = efrom;
136 mbstate_t tmp = state;
137 do_in(tmp, efrom, eend, ecur, ibegin, ibegin + m, icur);
142 virtual int do_max_length() const __NO_THROW
146 /* Codecvt facet generating more characters than the ones read from the
147 * external buffer, transform '01' in 'abc'
148 * This kind of facet do not allow systematical positionning in the external
149 * buffer (tellg -> -1), when you just read a 'a' you are at an undefined
150 * external buffer position.
152 struct generator_codecvt : public codecvt<char, char, mbstate_t> {
153 typedef codecvt<char,char,mbstate_t> base;
155 explicit generator_codecvt(size_t refs = 0) : base(refs) {}
157 // primitive conversion
160 const char* ebegin, const char* eend, const char*& ecur,
161 char* ibegin, char* iend, char*& icur) const __NO_THROW {
162 //Access the mbstate information in a portable way:
163 char *state = (char*)&mb;
167 if (icur == iend) return ok;
178 else if (*state == 3) {
183 while (ecur != eend) {
186 if (*ecur == '0' || *state == 1) {
231 // claim it's not a null-conversion
232 virtual bool do_always_noconv() const __NO_THROW
235 // claim it doesn't have a fixed-length encoding
236 virtual int do_encoding() const __NO_THROW
239 // implemented for consistency with do_in overload
240 virtual int do_length(const mbstate_t &mb,
241 const char *efrom, const char *eend, size_t m) const {
242 const char *state = (const char*)&mb;
246 else if (*state == 3)
249 char *ibegin = new char[m + offset];
250 const char *ecur = efrom;
252 mbstate_t tmpState = mb;
253 do_in(tmpState, efrom, eend, ecur, ibegin, ibegin + m + offset, icur);
255 char *state = (char*)&tmpState;
259 else if (*state == 2 || *state == 3) {
260 //Undefined position, we return -1:
265 if (*((char*)&mb) != 0) {
266 //We take into account the character that hasn't been counted yet in
267 //the previous decoding step:
273 return (int)min((size_t)(ecur - efrom), m);
276 virtual int do_max_length() const __NO_THROW
281 // tests implementation
283 void CodecvtTest::variable_encoding()
285 #if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES)
286 //We first generate the file used for test:
287 const char* fileName = "c:\\test_file.txt";
289 ofstream ostr(fileName);
290 //Maybe we simply do not have write access to repository
291 CPPUNIT_ASSERT( ostr.good() );
292 for (int i = 0; i < 2048; ++i) {
293 ostr << "0123456789";
295 CPPUNIT_ASSERT( ostr.good() );
299 ifstream istr(fileName);
300 CPPUNIT_ASSERT( istr.good() );
301 CPPUNIT_ASSERT( !istr.eof() );
303 eater_codecvt codec(1);
304 locale loc(locale::classic(), &codec);
307 CPPUNIT_ASSERT( istr.good() );
308 CPPUNIT_ASSERT( (int)istr.tellg() == 0 );
310 int theoricalPos = 0;
312 signed char c = (signed char)istr.get();
313 if (c == char_traits<char>::eof()) {
320 CPPUNIT_ASSERT( (int)istr.tellg() == theoricalPos );
324 CPPUNIT_ASSERT( istr.eof() );
328 /* This test is broken, not sure if it is really possible to get a position in
329 * a locale having a codecvt such as generator_codecvt. Maybe generator_codecvt
330 * is not a valid theorical example of codecvt implementation. */
332 ifstream istr(fileName);
333 CPPUNIT_ASSERT( istr.good() );
334 CPPUNIT_ASSERT( !istr.eof() );
336 generator_codecvt codec(1);
337 locale loc(locale::classic(), &codec);
340 CPPUNIT_ASSERT( istr.good() );
341 CPPUNIT_ASSERT( (int)istr.tellg() == 0 );
343 int theoricalPos = 0;
347 if (c == char_traits<char>::eof()) {
359 theoricalTellg = theoricalPos;
363 if ((int)istr.tellg() != theoricalTellg) {
364 CPPUNIT_ASSERT( (int)istr.tellg() == theoricalTellg );
369 CPPUNIT_ASSERT( istr.eof() );
375 void CodecvtTest::locale_cov1()
377 locale loc ( "fr_FR.ISO-8859-1" );
378 locale loc1 ( "en_US.ISO-8859-1" );
379 bool result1,result2;
381 result1 = isalnum ( 'L', loc);
382 result2 = isalnum ( '@', loc);
383 CPPUNIT_ASSERT( result1 == true );
384 CPPUNIT_ASSERT( result2 == false);
386 result1 = isalnum ( 'L', loc1);
387 result2 = isalnum ( '@', loc1);
388 CPPUNIT_ASSERT( result1 == true );
389 CPPUNIT_ASSERT( result2 == false);
392 result1 = isalpha ( 'L', loc);
393 result2 = isalpha ( '@', loc);
394 CPPUNIT_ASSERT( result1 == true );
395 CPPUNIT_ASSERT( result2 == false);
397 result1 = isalpha ( 'L', loc1);
398 result2 = isalpha ( '@', loc1);
399 CPPUNIT_ASSERT( result1 == true );
400 CPPUNIT_ASSERT( result2 == false);
403 result1 = iscntrl ( 'L', loc);
404 result2 = iscntrl ( '\n', loc);
405 CPPUNIT_ASSERT( result1 == false);
406 CPPUNIT_ASSERT( result2 == true );
408 result1 = iscntrl ( 'L', loc1);
409 result2 = iscntrl ( '\n', loc1);
410 CPPUNIT_ASSERT( result1 == false);
411 CPPUNIT_ASSERT( result2 == true );
414 result1 = isdigit ( 'L', loc);
415 result2 = isdigit ( '3', loc);
416 CPPUNIT_ASSERT( result1 == false);
417 CPPUNIT_ASSERT( result2 == true );
419 result1 = isdigit ( 'L', loc1);
420 result2 = isdigit ( '3', loc1);
421 CPPUNIT_ASSERT( result1 == false);
422 CPPUNIT_ASSERT( result2 == true );
425 void CodecvtTest::locale_cov2()
427 locale loc ( "fr_FR.ISO-8859-1" );
428 locale loc1 ( "en_US.ISO-8859-1" );
429 bool result1,result2;
431 result1 = isgraph ( ' ', loc);
432 result2 = isgraph ( '.', loc);
433 CPPUNIT_ASSERT( result1 == false);
434 CPPUNIT_ASSERT( result2 == true );
436 result1 = isgraph ( ' ', loc1);
437 result2 = isgraph ( '.', loc1);
438 CPPUNIT_ASSERT( result1 == false);
439 CPPUNIT_ASSERT( result2 == true );
442 result1 = islower ( 'L', loc);
443 result2 = islower ( 'v', loc);
444 CPPUNIT_ASSERT( result1 == false);
445 CPPUNIT_ASSERT( result2 == true );
447 result1 = islower ( 'L', loc1);
448 result2 = islower ( 'v', loc1);
449 CPPUNIT_ASSERT( result1 == false);
450 CPPUNIT_ASSERT( result2 == true );
453 result1 = isprint ( '\n', loc);
454 result2 = isprint ( 't', loc);
455 CPPUNIT_ASSERT( result1 == false);
456 CPPUNIT_ASSERT( result2 == true );
458 result1 = isprint ( '\n', loc1);
459 result2 = isprint ( 't', loc1);
460 CPPUNIT_ASSERT( result1 == false);
461 CPPUNIT_ASSERT( result2 == true );
464 result1 = ispunct ( 'L', loc);
465 result2 = ispunct ( ';', loc);
466 CPPUNIT_ASSERT( result1 == false);
467 CPPUNIT_ASSERT( result2 == true );
469 result1 = ispunct ( 'L', loc1);
470 result2 = ispunct ( ';', loc1);
471 CPPUNIT_ASSERT( result1 == false);
472 CPPUNIT_ASSERT( result2 == true );
475 void CodecvtTest::locale_cov3()
477 locale loc ( "fr_FR.ISO-8859-1" );
478 locale loc1 ( "en_US.ISO-8859-1" );
479 bool result1,result2,result3;
481 result2 = isspace ( '\n', loc);
482 result3 = isspace ( 'x', loc);
483 CPPUNIT_ASSERT( result2 == true );
484 CPPUNIT_ASSERT( result3 == false );
486 result2 = isspace ( '\n', loc1);
487 result3 = isspace ( 'x', loc1);
488 CPPUNIT_ASSERT( result2 == true );
489 CPPUNIT_ASSERT( result3 == false );
492 result1 = isupper ( 'L', loc);
493 result2 = isupper ( ';', loc);
494 CPPUNIT_ASSERT( result1 == true );
495 CPPUNIT_ASSERT( result2 == false );
497 result1 = isupper ( 'L', loc1);
498 result2 = isupper ( ';', loc1);
499 CPPUNIT_ASSERT( result1 == true );
500 CPPUNIT_ASSERT( result2 == false );
503 result1 = isxdigit ( 'f', loc);
504 result2 = isxdigit ( 'd', loc);
505 result3 = isxdigit ( 'q', loc);
506 CPPUNIT_ASSERT( result1 == true );
507 CPPUNIT_ASSERT( result2 == true );
508 CPPUNIT_ASSERT( result3 == false );
510 result1 = isxdigit ( 'f', loc1);
511 result2 = isxdigit ( 'd', loc1);
512 result3 = isxdigit ( 'q', loc1);
513 CPPUNIT_ASSERT( result1 == true );
514 CPPUNIT_ASSERT( result2 == true );
515 CPPUNIT_ASSERT( result3 == false );
518 void CodecvtTest::locale_cov4()
520 locale loc ( "fr_FR.ISO-8859-1" );
521 locale loc1 ( "en_US.ISO-8859-1" );
524 cresult1 = tolower ( 'H', loc );
525 CPPUNIT_ASSERT( cresult1 == 'h' );
526 cresult1 = tolower ( 'h', loc );
527 CPPUNIT_ASSERT( cresult1 == 'h' );
528 cresult1 = tolower ( '$', loc );
529 CPPUNIT_ASSERT( cresult1 == '$' );
531 cresult1 = tolower ( 'H', loc1 );
532 CPPUNIT_ASSERT( cresult1 == 'h' );
533 cresult1 = tolower ( 'h', loc1 );
534 CPPUNIT_ASSERT( cresult1 == 'h' );
535 cresult1 = tolower ( '$', loc1 );
536 CPPUNIT_ASSERT( cresult1 == '$' );
539 cresult1 = toupper ( 'H', loc );
540 CPPUNIT_ASSERT( cresult1 == 'H' );
541 cresult1 = toupper ( 'h', loc );
542 CPPUNIT_ASSERT( cresult1 == 'H' );
543 cresult1 = toupper ( '$', loc );
544 CPPUNIT_ASSERT( cresult1 == '$' );
546 cresult1 = toupper ( 'H', loc1 );
547 CPPUNIT_ASSERT( cresult1 == 'H' );
548 cresult1 = toupper ( 'h', loc1 );
549 CPPUNIT_ASSERT( cresult1 == 'H' );
550 cresult1 = toupper ( '$', loc1 );
551 CPPUNIT_ASSERT( cresult1 == '$' );
554 void CodecvtTest::locale_cov5()
557 char* str = "stdcpp with pips";
558 mbstate_t state = {0};
560 int res = use_facet<codecvt<wchar_t, char, mbstate_t> > ( loc ).length( state,str, &str[strlen(str)], 50 );
561 CPPUNIT_ASSERT( res == 16 );
562 res = use_facet<codecvt<char, char, mbstate_t> >( loc ).max_length( );
565 char* str = "stdcpp with pips";
567 memset(&wstr[0], 0, (sizeof(wchar_t))*(50));
570 mbstate_t state = {0};
572 int res = use_facet<codecvt<wchar_t, char, mbstate_t> >( loc ).in( state,str, &str[strlen(str)], pszNext,wstr, &wstr[strlen(str)], pwszNext );
573 wstr[strlen(str)] = 0;
574 CPPUNIT_ASSERT(res!=codecvt_base::error);
577 locale loc ( "fr_FR.ISO-8859-1" );
578 int result1 = use_facet<codecvt<char, char, mbstate_t> > ( loc ).encoding ( );
579 CPPUNIT_ASSERT(result1 == 1);
580 bool result2 = use_facet<codecvt<char, char, mbstate_t> >( loc ).always_noconv( );
581 CPPUNIT_ASSERT(result2 == true);
582 result2 = use_facet<codecvt<wchar_t, char, mbstate_t> >( loc ).always_noconv( );
583 CPPUNIT_ASSERT(result2 == false);
586 void CodecvtTest::locale_cov6()
589 locale loc( "en_US.ISO-8859-1" );
590 const numpunct < char> &npunct = use_facet <numpunct <char> >( loc );
591 string str = npunct.truename();
592 CPPUNIT_ASSERT(str == "true");
593 str = npunct.falsename();
594 CPPUNIT_ASSERT(str == "false");
595 CPPUNIT_ASSERT(npunct.thousands_sep( ) == ',');
597 const numpunct < wchar_t> &npunct1 = use_facet <numpunct <wchar_t> >( loc );
598 wstring str1 = npunct1.truename();
599 CPPUNIT_ASSERT(str1 == L"true");
600 str1 = npunct1.falsename();
601 CPPUNIT_ASSERT(str1 == L"false");
602 CPPUNIT_ASSERT(npunct1.thousands_sep( ) == L',');
603 CPPUNIT_ASSERT(npunct1.decimal_point( ) == L'.');
606 void CodecvtTest::locale_cov7()
609 locale loc( "en_US.ISO-8859-1" );
610 const moneypunct <char, true> &mpunct = use_facet <moneypunct <char, true > >(loc);
611 CPPUNIT_ASSERT(mpunct.thousands_sep( ) == ',');
612 string str = mpunct.positive_sign( );
613 str = mpunct.negative_sign( );
614 char x = mpunct.neg_format().field[0];
615 x = mpunct.neg_format().field[1];
616 x = mpunct.neg_format().field[2];
617 x = mpunct.neg_format().field[3];
618 CPPUNIT_ASSERT(mpunct.decimal_point( ) == '.');
619 str = mpunct.curr_symbol( );
621 const moneypunct <char, false> &mpunct2 = use_facet <moneypunct <char, false> >(loc);
622 CPPUNIT_ASSERT(mpunct2.thousands_sep( ) == ',');
623 str = mpunct2.positive_sign( );
624 str = mpunct2.negative_sign( );
625 x = mpunct2.neg_format().field[0];
626 x = mpunct2.neg_format().field[1];
627 x = mpunct2.neg_format().field[2];
628 x = mpunct2.neg_format().field[3];
629 CPPUNIT_ASSERT(mpunct2.decimal_point( ) == '.');
630 str = mpunct2.curr_symbol( );