diff -r e20de85af2ee -r ce057bb09d0b genericopenlibs/cppstdlib/stl/test/unit/codecvt_test.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/genericopenlibs/cppstdlib/stl/test/unit/codecvt_test.cpp Fri Jun 04 16:20:51 2010 +0100 @@ -0,0 +1,633 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include +#if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS) +# include +# include + +# include "cppunit/cppunit_proxy.h" + +# if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES) +using namespace std; +# endif + +// +// TestCase class +// +class CodecvtTest : public CPPUNIT_NS::TestCase +{ + CPPUNIT_TEST_SUITE(CodecvtTest); +#if defined (STLPORT) && defined (_STLP_NO_MEMBER_TEMPLATES) + CPPUNIT_IGNORE; +#endif + CPPUNIT_TEST(variable_encoding); + CPPUNIT_TEST(locale_cov1); + CPPUNIT_TEST(locale_cov2); + CPPUNIT_TEST(locale_cov3); + CPPUNIT_TEST(locale_cov4); + CPPUNIT_TEST(locale_cov5); + CPPUNIT_TEST(locale_cov6); + CPPUNIT_TEST(locale_cov7); + CPPUNIT_TEST_SUITE_END(); + +protected: + void variable_encoding(); + void locale_cov1(); + void locale_cov2(); + void locale_cov3(); + void locale_cov4(); + void locale_cov5(); + void locale_cov6(); + void locale_cov7(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(CodecvtTest); + +#if defined (STLPORT) +# define __NO_THROW _STLP_NOTHROW +#else +# define __NO_THROW throw() +#endif + + +/* Codecvt facet eating some characters from the external buffer. + * Transform '01' in 'a' + */ +struct eater_codecvt : public codecvt { + typedef codecvt base; + + explicit eater_codecvt(size_t refs = 0) : base(refs) {} + + // primitive conversion + virtual base::result + do_in(mbstate_t& mb, + const char* ebegin, const char* eend, const char*& ecur, + char* ibegin, char* iend, char*& icur) const __NO_THROW { + char *state = (char*)&mb; + ecur = ebegin; + icur = ibegin; + + while (ecur != eend) { + if (icur == iend) + return partial; + if (*ecur == '0' || *state == 1) { + if (*state != 1) { + ++ecur; + } + if (ecur == eend) { + *state = 1; + return ok; + } + + if (*ecur == '1') { + *icur = 'a'; + } + else { + *(icur++) = '0'; + if (icur == iend) { + if (*state != 1) { + --ecur; + } + return partial; + } + *icur = *ecur; + } + } + else { + *icur = *ecur; + } + + *state = 0; + ++icur; + ++ecur; + } + + return ok; + } + + // claim it's not a null-conversion + virtual bool do_always_noconv() const __NO_THROW + { return false; } + + // claim it doesn't have a fixed-length encoding + virtual int do_encoding() const __NO_THROW + { return 0; } + + // implemented for consistency with do_in overload + virtual int do_length(const mbstate_t &state, + const char *efrom, const char *eend, size_t m) const { + char *ibegin = new char[m]; + const char *ecur = efrom; + char *icur = ibegin; + mbstate_t tmp = state; + do_in(tmp, efrom, eend, ecur, ibegin, ibegin + m, icur); + delete[] ibegin; + return ecur - efrom; + } + + virtual int do_max_length() const __NO_THROW + { return 2; } +}; + +/* Codecvt facet generating more characters than the ones read from the + * external buffer, transform '01' in 'abc' + * This kind of facet do not allow systematical positionning in the external + * buffer (tellg -> -1), when you just read a 'a' you are at an undefined + * external buffer position. + */ +struct generator_codecvt : public codecvt { + typedef codecvt base; + + explicit generator_codecvt(size_t refs = 0) : base(refs) {} + + // primitive conversion + virtual base::result + do_in(mbstate_t& mb, + const char* ebegin, const char* eend, const char*& ecur, + char* ibegin, char* iend, char*& icur) const __NO_THROW { + //Access the mbstate information in a portable way: + char *state = (char*)&mb; + ecur = ebegin; + icur = ibegin; + + if (icur == iend) return ok; + + if (*state == 2) { + *(icur++) = 'b'; + if (icur == iend) { + *state = 3; + return ok; + } + *(icur++) = 'c'; + *state = 0; + } + else if (*state == 3) { + *(icur++) = 'c'; + *state = 0; + } + + while (ecur != eend) { + if (icur == iend) + return ok; + if (*ecur == '0' || *state == 1) { + if (*state != 1) { + ++ecur; + } + if (ecur == eend) { + *state = 1; + return partial; + } + + if (*ecur == '1') { + *(icur++) = 'a'; + if (icur == iend) { + *state = 2; + return ok; + } + *(icur++) = 'b'; + if (icur == iend) { + *state = 3; + return ok; + } + *icur = 'c'; + } + else { + *(icur++) = '0'; + if (icur == iend) { + if (*state != 1) { + --ecur; + } + return ok; + } + *icur = *ecur; + } + } + else { + *icur = *ecur; + } + + *state = 0; + ++icur; + ++ecur; + } + + return ok; + } + + // claim it's not a null-conversion + virtual bool do_always_noconv() const __NO_THROW + { return false; } + + // claim it doesn't have a fixed-length encoding + virtual int do_encoding() const __NO_THROW + { return 0; } + + // implemented for consistency with do_in overload + virtual int do_length(const mbstate_t &mb, + const char *efrom, const char *eend, size_t m) const { + const char *state = (const char*)&mb; + int offset = 0; + if (*state == 2) + offset = 2; + else if (*state == 3) + offset = 1; + + char *ibegin = new char[m + offset]; + const char *ecur = efrom; + char *icur = ibegin; + mbstate_t tmpState = mb; + do_in(tmpState, efrom, eend, ecur, ibegin, ibegin + m + offset, icur); + /* + char *state = (char*)&tmpState; + if (*state != 0) { + if (*state == 1) + --ecur; + else if (*state == 2 || *state == 3) { + //Undefined position, we return -1: + ecur = efrom - 1; + } + } + else { + if (*((char*)&mb) != 0) { + //We take into account the character that hasn't been counted yet in + //the previous decoding step: + ecur++; + } + } + */ + delete[] ibegin; + return (int)min((size_t)(ecur - efrom), m); + } + + virtual int do_max_length() const __NO_THROW + { return 0; } +}; + +// +// tests implementation +// +void CodecvtTest::variable_encoding() +{ +#if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES) + //We first generate the file used for test: + const char* fileName = "c:\\test_file.txt"; + { + ofstream ostr(fileName); + //Maybe we simply do not have write access to repository + CPPUNIT_ASSERT( ostr.good() ); + for (int i = 0; i < 2048; ++i) { + ostr << "0123456789"; + } + CPPUNIT_ASSERT( ostr.good() ); + } + + { + ifstream istr(fileName); + CPPUNIT_ASSERT( istr.good() ); + CPPUNIT_ASSERT( !istr.eof() ); + + eater_codecvt codec(1); + locale loc(locale::classic(), &codec); + + istr.imbue(loc); + CPPUNIT_ASSERT( istr.good() ); + CPPUNIT_ASSERT( (int)istr.tellg() == 0 ); + + int theoricalPos = 0; + do { + signed char c = (signed char)istr.get(); + if (c == char_traits::eof()) { + break; + } + ++theoricalPos; + if (c == 'a') { + ++theoricalPos; + } + CPPUNIT_ASSERT( (int)istr.tellg() == theoricalPos ); + } + while (!istr.eof()); + + CPPUNIT_ASSERT( istr.eof() ); + } + +# if 0 + /* This test is broken, not sure if it is really possible to get a position in + * a locale having a codecvt such as generator_codecvt. Maybe generator_codecvt + * is not a valid theorical example of codecvt implementation. */ + { + ifstream istr(fileName); + CPPUNIT_ASSERT( istr.good() ); + CPPUNIT_ASSERT( !istr.eof() ); + + generator_codecvt codec(1); + locale loc(locale::classic(), &codec); + + istr.imbue(loc); + CPPUNIT_ASSERT( istr.good() ); + CPPUNIT_ASSERT( (int)istr.tellg() == 0 ); + + int theoricalPos = 0; + int theoricalTellg; + do { + char c = istr.get(); + if (c == char_traits::eof()) { + break; + } + switch (c) { + case 'a': + case 'b': + theoricalTellg = -1; + break; + case 'c': + ++theoricalPos; + default: + ++theoricalPos; + theoricalTellg = theoricalPos; + break; + } + + if ((int)istr.tellg() != theoricalTellg) { + CPPUNIT_ASSERT( (int)istr.tellg() == theoricalTellg ); + } + } + while (!istr.eof()); + + CPPUNIT_ASSERT( istr.eof() ); + } +# endif +#endif +} + +void CodecvtTest::locale_cov1() + { + locale loc ( "fr_FR.ISO-8859-1" ); + locale loc1 ( "en_US.ISO-8859-1" ); + bool result1,result2; + { + result1 = isalnum ( 'L', loc); + result2 = isalnum ( '@', loc); + CPPUNIT_ASSERT( result1 == true ); + CPPUNIT_ASSERT( result2 == false); + + result1 = isalnum ( 'L', loc1); + result2 = isalnum ( '@', loc1); + CPPUNIT_ASSERT( result1 == true ); + CPPUNIT_ASSERT( result2 == false); + } + { + result1 = isalpha ( 'L', loc); + result2 = isalpha ( '@', loc); + CPPUNIT_ASSERT( result1 == true ); + CPPUNIT_ASSERT( result2 == false); + + result1 = isalpha ( 'L', loc1); + result2 = isalpha ( '@', loc1); + CPPUNIT_ASSERT( result1 == true ); + CPPUNIT_ASSERT( result2 == false); + } + { + result1 = iscntrl ( 'L', loc); + result2 = iscntrl ( '\n', loc); + CPPUNIT_ASSERT( result1 == false); + CPPUNIT_ASSERT( result2 == true ); + + result1 = iscntrl ( 'L', loc1); + result2 = iscntrl ( '\n', loc1); + CPPUNIT_ASSERT( result1 == false); + CPPUNIT_ASSERT( result2 == true ); + } + { + result1 = isdigit ( 'L', loc); + result2 = isdigit ( '3', loc); + CPPUNIT_ASSERT( result1 == false); + CPPUNIT_ASSERT( result2 == true ); + + result1 = isdigit ( 'L', loc1); + result2 = isdigit ( '3', loc1); + CPPUNIT_ASSERT( result1 == false); + CPPUNIT_ASSERT( result2 == true ); + } + } +void CodecvtTest::locale_cov2() + { + locale loc ( "fr_FR.ISO-8859-1" ); + locale loc1 ( "en_US.ISO-8859-1" ); + bool result1,result2; + { + result1 = isgraph ( ' ', loc); + result2 = isgraph ( '.', loc); + CPPUNIT_ASSERT( result1 == false); + CPPUNIT_ASSERT( result2 == true ); + + result1 = isgraph ( ' ', loc1); + result2 = isgraph ( '.', loc1); + CPPUNIT_ASSERT( result1 == false); + CPPUNIT_ASSERT( result2 == true ); + } + { + result1 = islower ( 'L', loc); + result2 = islower ( 'v', loc); + CPPUNIT_ASSERT( result1 == false); + CPPUNIT_ASSERT( result2 == true ); + + result1 = islower ( 'L', loc1); + result2 = islower ( 'v', loc1); + CPPUNIT_ASSERT( result1 == false); + CPPUNIT_ASSERT( result2 == true ); + } + { + result1 = isprint ( '\n', loc); + result2 = isprint ( 't', loc); + CPPUNIT_ASSERT( result1 == false); + CPPUNIT_ASSERT( result2 == true ); + + result1 = isprint ( '\n', loc1); + result2 = isprint ( 't', loc1); + CPPUNIT_ASSERT( result1 == false); + CPPUNIT_ASSERT( result2 == true ); + } + { + result1 = ispunct ( 'L', loc); + result2 = ispunct ( ';', loc); + CPPUNIT_ASSERT( result1 == false); + CPPUNIT_ASSERT( result2 == true ); + + result1 = ispunct ( 'L', loc1); + result2 = ispunct ( ';', loc1); + CPPUNIT_ASSERT( result1 == false); + CPPUNIT_ASSERT( result2 == true ); + } + } +void CodecvtTest::locale_cov3() + { + locale loc ( "fr_FR.ISO-8859-1" ); + locale loc1 ( "en_US.ISO-8859-1" ); + bool result1,result2,result3; + { + result2 = isspace ( '\n', loc); + result3 = isspace ( 'x', loc); + CPPUNIT_ASSERT( result2 == true ); + CPPUNIT_ASSERT( result3 == false ); + + result2 = isspace ( '\n', loc1); + result3 = isspace ( 'x', loc1); + CPPUNIT_ASSERT( result2 == true ); + CPPUNIT_ASSERT( result3 == false ); + } + { + result1 = isupper ( 'L', loc); + result2 = isupper ( ';', loc); + CPPUNIT_ASSERT( result1 == true ); + CPPUNIT_ASSERT( result2 == false ); + + result1 = isupper ( 'L', loc1); + result2 = isupper ( ';', loc1); + CPPUNIT_ASSERT( result1 == true ); + CPPUNIT_ASSERT( result2 == false ); + } + { + result1 = isxdigit ( 'f', loc); + result2 = isxdigit ( 'd', loc); + result3 = isxdigit ( 'q', loc); + CPPUNIT_ASSERT( result1 == true ); + CPPUNIT_ASSERT( result2 == true ); + CPPUNIT_ASSERT( result3 == false ); + + result1 = isxdigit ( 'f', loc1); + result2 = isxdigit ( 'd', loc1); + result3 = isxdigit ( 'q', loc1); + CPPUNIT_ASSERT( result1 == true ); + CPPUNIT_ASSERT( result2 == true ); + CPPUNIT_ASSERT( result3 == false ); + } + } +void CodecvtTest::locale_cov4() + { + locale loc ( "fr_FR.ISO-8859-1" ); + locale loc1 ( "en_US.ISO-8859-1" ); + char cresult1; + { + cresult1 = tolower ( 'H', loc ); + CPPUNIT_ASSERT( cresult1 == 'h' ); + cresult1 = tolower ( 'h', loc ); + CPPUNIT_ASSERT( cresult1 == 'h' ); + cresult1 = tolower ( '$', loc ); + CPPUNIT_ASSERT( cresult1 == '$' ); + + cresult1 = tolower ( 'H', loc1 ); + CPPUNIT_ASSERT( cresult1 == 'h' ); + cresult1 = tolower ( 'h', loc1 ); + CPPUNIT_ASSERT( cresult1 == 'h' ); + cresult1 = tolower ( '$', loc1 ); + CPPUNIT_ASSERT( cresult1 == '$' ); + } + { + cresult1 = toupper ( 'H', loc ); + CPPUNIT_ASSERT( cresult1 == 'H' ); + cresult1 = toupper ( 'h', loc ); + CPPUNIT_ASSERT( cresult1 == 'H' ); + cresult1 = toupper ( '$', loc ); + CPPUNIT_ASSERT( cresult1 == '$' ); + + cresult1 = toupper ( 'H', loc1 ); + CPPUNIT_ASSERT( cresult1 == 'H' ); + cresult1 = toupper ( 'h', loc1 ); + CPPUNIT_ASSERT( cresult1 == 'H' ); + cresult1 = toupper ( '$', loc1 ); + CPPUNIT_ASSERT( cresult1 == '$' ); + } + } +void CodecvtTest::locale_cov5() + { + { + char* str = "stdcpp with pips"; + mbstate_t state = {0}; + locale loc("C"); + int res = use_facet > ( loc ).length( state,str, &str[strlen(str)], 50 ); + CPPUNIT_ASSERT( res == 16 ); + res = use_facet >( loc ).max_length( ); + } + { + char* str = "stdcpp with pips"; + wchar_t wstr [50]; + memset(&wstr[0], 0, (sizeof(wchar_t))*(50)); + const char* pszNext; + wchar_t* pwszNext; + mbstate_t state = {0}; + locale loc("C"); + int res = use_facet >( loc ).in( state,str, &str[strlen(str)], pszNext,wstr, &wstr[strlen(str)], pwszNext ); + wstr[strlen(str)] = 0; + CPPUNIT_ASSERT(res!=codecvt_base::error); + } + { + locale loc ( "fr_FR.ISO-8859-1" ); + int result1 = use_facet > ( loc ).encoding ( ); + CPPUNIT_ASSERT(result1 == 1); + bool result2 = use_facet >( loc ).always_noconv( ); + CPPUNIT_ASSERT(result2 == true); + result2 = use_facet >( loc ).always_noconv( ); + CPPUNIT_ASSERT(result2 == false); + } + } +void CodecvtTest::locale_cov6() + { + { + locale loc( "en_US.ISO-8859-1" ); + const numpunct < char> &npunct = use_facet >( loc ); + string str = npunct.truename(); + CPPUNIT_ASSERT(str == "true"); + str = npunct.falsename(); + CPPUNIT_ASSERT(str == "false"); + CPPUNIT_ASSERT(npunct.thousands_sep( ) == ','); + + const numpunct < wchar_t> &npunct1 = use_facet >( loc ); + wstring str1 = npunct1.truename(); + CPPUNIT_ASSERT(str1 == L"true"); + str1 = npunct1.falsename(); + CPPUNIT_ASSERT(str1 == L"false"); + CPPUNIT_ASSERT(npunct1.thousands_sep( ) == L','); + CPPUNIT_ASSERT(npunct1.decimal_point( ) == L'.'); + } + } +void CodecvtTest::locale_cov7() + { + { + locale loc( "en_US.ISO-8859-1" ); + const moneypunct &mpunct = use_facet >(loc); + CPPUNIT_ASSERT(mpunct.thousands_sep( ) == ','); + string str = mpunct.positive_sign( ); + str = mpunct.negative_sign( ); + char x = mpunct.neg_format().field[0]; + x = mpunct.neg_format().field[1]; + x = mpunct.neg_format().field[2]; + x = mpunct.neg_format().field[3]; + CPPUNIT_ASSERT(mpunct.decimal_point( ) == '.'); + str = mpunct.curr_symbol( ); + + const moneypunct &mpunct2 = use_facet >(loc); + CPPUNIT_ASSERT(mpunct2.thousands_sep( ) == ','); + str = mpunct2.positive_sign( ); + str = mpunct2.negative_sign( ); + x = mpunct2.neg_format().field[0]; + x = mpunct2.neg_format().field[1]; + x = mpunct2.neg_format().field[2]; + x = mpunct2.neg_format().field[3]; + CPPUNIT_ASSERT(mpunct2.decimal_point( ) == '.'); + str = mpunct2.curr_symbol( ); + } + } +#endif