// Copyright 2011 Tan Zhi(Tom) #ifndef TR_HPP #define TR_HPP #include #include #include #include namespace adapt { /** * this class is a shim between wide-char and marrow-char string types. * it accepts a std::basic_string type or C-style literal, returns a std::basic_string type * or streamming to std::basic_ostream according to the context(e.g. type on the left side * of '=' operator): * * typical usage: * std::string s = tr("hello"); // s = "hello" * std::basic_stringstream ws = tr("hello"); // ws = L"hello" * see more examples in test cases * N.B. it doe not do any code conversion like: MBCS <--> UNICODE */ using namespace std; struct TR { template TR(const RangeT& r) { auto rng = boost::as_literal(r); m_s.assign(boost::begin(rng), boost::end(rng)); } // implicit convert to string or wstring template operator basic_string() const { return basic_string(m_s.begin(), m_s.end()); } private: basic_string m_s; }; /** * an alternative implementation of TR based on boost.range */ template struct TR2 { TR2(const RangeT& r) : m_r(r) { } // implicit convert to string or wstring template operator basic_string() const { auto rng = boost::as_literal(m_r); return basic_string(boost::begin(rng), boost::end(rng)); } private: RangeT m_r; }; // overload TR for streaming operation with std::basic_ostream<> and derives template basic_ostream& operator << (basic_ostream& os, const TR& s) { os << s.operator basic_string(); return os; } // overload TR for streaming operation with std::basic_ostream<> and derives template basic_ostream& operator << (basic_ostream& os, const TR2& s) { os << s.operator basic_string(); return os; } #ifdef ENABLE_TEST namespace test_cases { BOOST_AUTO_TEST_SUITE(TR_Tests) BOOST_AUTO_TEST_CASE(TR_to_string) { string s; //char* literal to string s = TR("char"); BOOST_CHECK(s == "char"); //wchar_t* literal to string s = TR(L"wchar"); BOOST_CHECK_EQUAL("wchar", s); //char* to string const char* c = "char"; s = TR(c); BOOST_CHECK_EQUAL("char", s); //wchar_t* to string const wchar_t* wc = L"wchar"; s = TR(wc); BOOST_CHECK_EQUAL("wchar", s); // string to string string ts = "string"; s = TR(ts); BOOST_CHECK_EQUAL("string", s); // wstring to string wstring ws = L"wstring"; s = TR(ws); BOOST_CHECK_EQUAL("wstring", s); } BOOST_AUTO_TEST_CASE(TR_to_wstring) { // BOOST_CHECK is used because boost.test // does not support log output in wide chars wstring ws; //char* literal to wstring ws = TR("char"); BOOST_CHECK(L"char" == ws); //wchar_t* literal to wstring ws = TR(L"wchar"); BOOST_CHECK(L"wchar" == ws); //char* to wstring const char* c = "char"; ws = TR(c); BOOST_CHECK(L"char" == ws); //wchar_t* to wstring const wchar_t* wc = L"char"; ws = TR(wc); BOOST_CHECK(L"char" == ws); // string to wstring string s = "string"; ws = TR(s); BOOST_CHECK(L"string" == ws); // wstring to wstring wstring tws = L"wstring"; ws = TR(tws); BOOST_CHECK(L"wstring" == ws); } BOOST_AUTO_TEST_CASE(TR_to_ostream) { // narrow string narrow stream ostringstream os; os << TR("literal string") ; BOOST_CHECK_EQUAL(os.str(), "literal string"); // wide string narrow stream os.str(""); os << TR(L"literal string") ; BOOST_CHECK_EQUAL(os.str(), "literal string"); // narrow string wide stream wostringstream wos; wos << TR("literal string") ; BOOST_CHECK(wos.str() == L"literal string"); // wide string wide stream wos.str(L""); wos << TR(L"literal string") ; BOOST_CHECK(wos.str() == L"literal string"); } BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE(TR2_Tests) BOOST_AUTO_TEST_CASE(TR2_to_wstring) { // BOOST_CHECK is used because boost.test // does not support log output in wide chars wstring ws; //char* literal to wstring ws = TR2("char"); BOOST_CHECK(L"char" == ws); //wchar_t* literal to wstring ws = TR2(L"wchar"); BOOST_CHECK(L"wchar" == ws); //char* to wstring const char* c = "char"; ws = TR2(c); BOOST_CHECK(L"char" == ws); //wchar_t* to wstring const wchar_t* wc = L"char"; ws = TR2(wc); BOOST_CHECK(L"char" == ws); // string to wstring string s = "string"; ws = TR2(s); BOOST_CHECK(L"string" == ws); // wstring to wstring wstring tws = L"wstring"; ws = TR2(tws); BOOST_CHECK(L"wstring" == ws); } BOOST_AUTO_TEST_CASE(TR2_to_string) { string s; //char* literal to string s = TR2("char"); BOOST_CHECK(s == "char"); //wchar_t* literal to string s = TR2(L"wchar"); BOOST_CHECK_EQUAL("wchar", s); //char* to string const char* c = "char"; s = TR2(c); BOOST_CHECK_EQUAL("char", s); //wchar_t* to string const wchar_t* wc = L"wchar"; s = TR2(wc); BOOST_CHECK_EQUAL("wchar", s); // string to string string ts = "string"; s = TR2(ts); BOOST_CHECK_EQUAL("string", s); // wstring to string wstring ws = L"wstring"; s = TR2(ws); BOOST_CHECK_EQUAL("wstring", s); } BOOST_AUTO_TEST_CASE(TR2_to_ostream) { // narrow string narrow stream ostringstream os; os << TR2("literal string") ; BOOST_CHECK_EQUAL(os.str(), "literal string"); // wide string narrow stream os.str(""); os << TR2(L"literal string") ; BOOST_CHECK_EQUAL(os.str(), "literal string"); // narrow string wide stream wostringstream wos; wos << TR2("literal string") ; BOOST_CHECK(wos.str() == L"literal string"); // wide string wide stream wos.str(L""); wos << TR2(L"literal string") ; BOOST_CHECK(wos.str() == L"literal string"); } BOOST_AUTO_TEST_SUITE_END() } //namespace test_cases #endif } #endif