+
+// ----------------------------------------------------------------------------
+// UTF-8 tests
+// ----------------------------------------------------------------------------
+
+#ifdef HAVE_WCHAR_H
+
+// Check that 'charSequence' translates to 'wideSequence' and back.
+// Invalid sequences can be tested by giving NULL for 'wideSequence'. Even
+// invalid sequences should roundtrip when an option is given and this is
+// checked.
+//
+void MBConvTestCase::UTF8(const char *charSequence,
+ const wchar_t *wideSequence)
+{
+ UTF8(charSequence, wideSequence, wxMBConvUTF8::MAP_INVALID_UTF8_NOT);
+ UTF8(charSequence, wideSequence, wxMBConvUTF8::MAP_INVALID_UTF8_TO_PUA);
+ UTF8(charSequence, wideSequence, wxMBConvUTF8::MAP_INVALID_UTF8_TO_OCTAL);
+}
+
+// Use this alternative when 'charSequence' contains a PUA character. Such
+// sequences should still roundtrip ok, and this is checked.
+//
+void MBConvTestCase::UTF8PUA(const char *charSequence,
+ const wchar_t *wideSequence)
+{
+ UTF8(charSequence, wideSequence, wxMBConvUTF8::MAP_INVALID_UTF8_NOT);
+ UTF8(charSequence, NULL, wxMBConvUTF8::MAP_INVALID_UTF8_TO_PUA);
+ UTF8(charSequence, wideSequence, wxMBConvUTF8::MAP_INVALID_UTF8_TO_OCTAL);
+}
+
+// Use this alternative when 'charSequence' contains an octal escape sequence.
+// Such sequences should still roundtrip ok, and this is checked.
+//
+void MBConvTestCase::UTF8Octal(const char *charSequence,
+ const wchar_t *wideSequence)
+{
+ UTF8(charSequence, wideSequence, wxMBConvUTF8::MAP_INVALID_UTF8_NOT);
+ UTF8(charSequence, wideSequence, wxMBConvUTF8::MAP_INVALID_UTF8_TO_PUA);
+ UTF8(charSequence, NULL, wxMBConvUTF8::MAP_INVALID_UTF8_TO_OCTAL);
+}
+
+// include the option in the error messages so it's possible to see which
+// test failed
+#define UTF8ASSERT(expr) CPPUNIT_ASSERT_MESSAGE(#expr + errmsg, expr)
+
+// The test implementation
+//
+void MBConvTestCase::UTF8(const char *charSequence,
+ const wchar_t *wideSequence,
+ int option)
+{
+ const size_t BUFSIZE = 128;
+ wxASSERT(strlen(charSequence) * 3 + 10 < BUFSIZE);
+ char bytes[BUFSIZE];
+
+ // include the option in the error messages so it's possible to see
+ // which test failed
+ sprintf(bytes, " (with option == %d)", option);
+ std::string errmsg(bytes);
+
+ // put the charSequence at the start, middle and end of a string
+ strcpy(bytes, charSequence);
+ strcat(bytes, "ABC");
+ strcat(bytes, charSequence);
+ strcat(bytes, "XYZ");
+ strcat(bytes, charSequence);
+
+ // translate it into wide characters
+ wxMBConvUTF8 utf8(option);
+ wchar_t widechars[BUFSIZE];
+ size_t lenResult = utf8.MB2WC(NULL, bytes, 0);
+ size_t result = utf8.MB2WC(widechars, bytes, BUFSIZE);
+ UTF8ASSERT(result == lenResult);
+
+ // check we got the expected result
+ if (wideSequence) {
+ UTF8ASSERT(result != (size_t)-1);
+ wxASSERT(result < BUFSIZE);
+
+ wchar_t expected[BUFSIZE];
+ wcscpy(expected, wideSequence);
+ wcscat(expected, L"ABC");
+ wcscat(expected, wideSequence);
+ wcscat(expected, L"XYZ");
+ wcscat(expected, wideSequence);
+
+ UTF8ASSERT(wcscmp(widechars, expected) == 0);
+ UTF8ASSERT(wcslen(widechars) == result);
+ }
+ else {
+ // If 'wideSequence' is NULL, then the result is expected to be
+ // invalid. Normally that is as far as we can go, but if there is an
+ // option then the conversion should succeed anyway, and it should be
+ // possible to translate back to the original
+ if (!option) {
+ UTF8ASSERT(result == (size_t)-1);
+ return;
+ }
+ else {
+ UTF8ASSERT(result != (size_t)-1);
+ }
+ }
+
+ // translate it back and check we get the original
+ char bytesAgain[BUFSIZE];
+ size_t lenResultAgain = utf8.WC2MB(NULL, widechars, 0);
+ size_t resultAgain = utf8.WC2MB(bytesAgain, widechars, BUFSIZE);
+ UTF8ASSERT(resultAgain == lenResultAgain);
+ UTF8ASSERT(resultAgain != (size_t)-1);
+ wxASSERT(resultAgain < BUFSIZE);
+
+ UTF8ASSERT(strcmp(bytes, bytesAgain) == 0);
+ UTF8ASSERT(strlen(bytesAgain) == resultAgain);
+}
+
+#endif // HAVE_WCHAR_H