cmake/Source/kwsys/testEncoding.cxx

286 lines
8.5 KiB
C++
Raw Normal View History

2017-04-14 19:02:05 +02:00
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
2014-08-03 19:52:23 +02:00
#include "kwsysPrivate.h"
#if defined(_MSC_VER)
2018-08-09 18:06:22 +02:00
# pragma warning(disable : 4786)
2014-08-03 19:52:23 +02:00
#endif
#include KWSYS_HEADER(Encoding.hxx)
#include KWSYS_HEADER(Encoding.h)
2017-04-14 19:02:05 +02:00
#include <algorithm>
2020-08-30 11:54:41 +02:00
#include <clocale>
#include <cstdlib>
#include <cstring>
2015-11-17 17:22:37 +01:00
#include <iostream>
2014-08-03 19:52:23 +02:00
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
2018-08-09 18:06:22 +02:00
# include "Encoding.h.in"
# include "Encoding.hxx.in"
2014-08-03 19:52:23 +02:00
#endif
2017-04-14 19:02:05 +02:00
static const unsigned char helloWorldStrings[][32] = {
2014-08-03 19:52:23 +02:00
// English
2017-04-14 19:02:05 +02:00
{ 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', 0 },
2014-08-03 19:52:23 +02:00
// Japanese
2017-04-14 19:02:05 +02:00
{ 0xE3, 0x81, 0x93, 0xE3, 0x82, 0x93, 0xE3, 0x81, 0xAB, 0xE3, 0x81,
0xA1, 0xE3, 0x81, 0xAF, 0xE4, 0xB8, 0x96, 0xE7, 0x95, 0x8C, 0 },
// Arabic
{ 0xD9, 0x85, 0xD8, 0xB1, 0xD8, 0xAD, 0xD8, 0xA8, 0xD8, 0xA7, 0x20, 0xD8,
0xA7, 0xD9, 0x84, 0xD8, 0xB9, 0xD8, 0xA7, 0xD9, 0x84, 0xD9, 0x85, 0 },
2014-08-03 19:52:23 +02:00
// Yiddish
2017-04-14 19:02:05 +02:00
{ 0xD7, 0x94, 0xD7, 0xA2, 0xD7, 0x9C, 0xD7, 0x90, 0x20, 0xD7,
0x95, 0xD7, 0x95, 0xD7, 0xA2, 0xD7, 0x9C, 0xD7, 0x98, 0 },
2014-08-03 19:52:23 +02:00
// Russian
2017-04-14 19:02:05 +02:00
{ 0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0, 0xB5,
0xD1, 0x82, 0x20, 0xD0, 0xBC, 0xD0, 0xB8, 0xD1, 0x80, 0 },
2014-08-03 19:52:23 +02:00
// Latin
2017-04-14 19:02:05 +02:00
{ 0x4D, 0x75, 0x6E, 0x64, 0x75, 0x73, 0x20, 0x73, 0x61, 0x6C, 0x76, 0x65,
0 },
2014-08-03 19:52:23 +02:00
// Swahili
2017-04-14 19:02:05 +02:00
{ 0x68, 0x75, 0x6A, 0x61, 0x6D, 0x62, 0x6F, 0x20, 0x44, 0x75, 0x6E, 0x69,
0x61, 0 },
2014-08-03 19:52:23 +02:00
// Icelandic
2017-04-14 19:02:05 +02:00
{ 0x48, 0x61, 0x6C, 0x6C, 0xC3, 0xB3, 0x20, 0x68, 0x65, 0x69, 0x6D, 0x75,
0x72, 0 },
{ 0 }
2014-08-03 19:52:23 +02:00
};
static int testHelloWorldEncoding()
{
int ret = 0;
2017-04-14 19:02:05 +02:00
for (int i = 0; helloWorldStrings[i][0] != 0; i++) {
2014-08-03 19:52:23 +02:00
std::string str = reinterpret_cast<const char*>(helloWorldStrings[i]);
std::cout << str << std::endl;
std::wstring wstr = kwsys::Encoding::ToWide(str);
std::string str2 = kwsys::Encoding::ToNarrow(wstr);
wchar_t* c_wstr = kwsysEncoding_DupToWide(str.c_str());
char* c_str2 = kwsysEncoding_DupToNarrow(c_wstr);
2020-08-30 11:54:41 +02:00
if (!wstr.empty() && (str != str2 || strcmp(c_str2, str.c_str()) != 0)) {
2014-08-03 19:52:23 +02:00
std::cout << "converted string was different: " << str2 << std::endl;
std::cout << "converted string was different: " << c_str2 << std::endl;
ret++;
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
free(c_wstr);
free(c_str2);
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
return ret;
}
static int testRobustEncoding()
{
// test that the conversion functions handle invalid
// unicode correctly/gracefully
2018-04-23 21:13:27 +02:00
// we manipulate the format flags of stdout, remember
// the original state here to restore before return
std::ios::fmtflags const& flags = std::cout.flags();
2014-08-03 19:52:23 +02:00
int ret = 0;
2017-04-14 19:02:05 +02:00
char cstr[] = { (char)-1, 0 };
2014-08-03 19:52:23 +02:00
// this conversion could fail
std::wstring wstr = kwsys::Encoding::ToWide(cstr);
2020-02-01 23:06:01 +01:00
wstr = kwsys::Encoding::ToWide(nullptr);
2020-08-30 11:54:41 +02:00
if (!wstr.empty()) {
2014-08-03 19:52:23 +02:00
const wchar_t* wcstr = wstr.c_str();
std::cout << "ToWide(NULL) returned";
2017-04-14 19:02:05 +02:00
for (size_t i = 0; i < wstr.size(); i++) {
2014-08-03 19:52:23 +02:00
std::cout << " " << std::hex << (int)wcstr[i];
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
std::cout << std::endl;
ret++;
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
wstr = kwsys::Encoding::ToWide("");
2020-08-30 11:54:41 +02:00
if (!wstr.empty()) {
2014-08-03 19:52:23 +02:00
const wchar_t* wcstr = wstr.c_str();
std::cout << "ToWide(\"\") returned";
2017-04-14 19:02:05 +02:00
for (size_t i = 0; i < wstr.size(); i++) {
2014-08-03 19:52:23 +02:00
std::cout << " " << std::hex << (int)wcstr[i];
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
std::cout << std::endl;
ret++;
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
2016-07-09 11:21:54 +02:00
#ifdef _WIN32
2014-08-03 19:52:23 +02:00
// 16 bit wchar_t - we make an invalid surrogate pair
2017-04-14 19:02:05 +02:00
wchar_t cwstr[] = { 0xD801, 0xDA00, 0 };
2014-08-03 19:52:23 +02:00
// this conversion could fail
std::string win_str = kwsys::Encoding::ToNarrow(cwstr);
#endif
2020-02-01 23:06:01 +01:00
std::string str = kwsys::Encoding::ToNarrow(nullptr);
2020-08-30 11:54:41 +02:00
if (!str.empty()) {
2014-08-03 19:52:23 +02:00
std::cout << "ToNarrow(NULL) returned " << str << std::endl;
ret++;
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
str = kwsys::Encoding::ToNarrow(L"");
2020-08-30 11:54:41 +02:00
if (!wstr.empty()) {
2014-08-03 19:52:23 +02:00
std::cout << "ToNarrow(\"\") returned " << str << std::endl;
ret++;
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
2018-04-23 21:13:27 +02:00
std::cout.flags(flags);
2014-08-03 19:52:23 +02:00
return ret;
}
2017-04-14 19:02:05 +02:00
static int testWithNulls()
{
int ret = 0;
std::vector<std::string> strings;
strings.push_back(std::string("ab") + '\0' + 'c');
strings.push_back(std::string("d") + '\0' + '\0' + 'e');
strings.push_back(std::string() + '\0' + 'f');
strings.push_back(std::string() + '\0' + '\0' + "gh");
strings.push_back(std::string("ij") + '\0');
strings.push_back(std::string("k") + '\0' + '\0');
strings.push_back(std::string("\0\0\0\0", 4) + "lmn" +
std::string("\0\0\0\0", 4));
2020-08-30 11:54:41 +02:00
for (auto& string : strings) {
std::wstring wstr = kwsys::Encoding::ToWide(string);
2017-04-14 19:02:05 +02:00
std::string str = kwsys::Encoding::ToNarrow(wstr);
2020-08-30 11:54:41 +02:00
std::string s(string);
2017-04-14 19:02:05 +02:00
std::replace(s.begin(), s.end(), '\0', ' ');
2020-08-30 11:54:41 +02:00
std::cout << "'" << s << "' (" << string.size() << ")" << std::endl;
if (str != string) {
2017-04-14 19:02:05 +02:00
std::replace(str.begin(), str.end(), '\0', ' ');
std::cout << "string with null was different: '" << str << "' ("
<< str.size() << ")" << std::endl;
ret++;
}
}
return ret;
}
2014-08-03 19:52:23 +02:00
static int testCommandLineArguments()
{
int status = 0;
2017-04-14 19:02:05 +02:00
char const* argv[2] = { "./app.exe", (char const*)helloWorldStrings[1] };
2014-08-03 19:52:23 +02:00
kwsys::Encoding::CommandLineArguments args(2, argv);
kwsys::Encoding::CommandLineArguments arg2 =
kwsys::Encoding::CommandLineArguments(args);
char const* const* u8_argv = args.argv();
2017-04-14 19:02:05 +02:00
for (int i = 0; i < args.argc(); i++) {
2014-08-03 19:52:23 +02:00
char const* u8_arg = u8_argv[i];
2017-04-14 19:02:05 +02:00
if (strcmp(argv[i], u8_arg) != 0) {
std::cout << "argv[" << i << "] " << argv[i] << " != " << u8_arg
<< std::endl;
2014-08-03 19:52:23 +02:00
status++;
}
}
kwsys::Encoding::CommandLineArguments args3 =
kwsys::Encoding::CommandLineArguments::Main(2, argv);
return status;
}
2017-07-20 19:35:53 +02:00
static int testToWindowsExtendedPath()
{
#ifdef _WIN32
int ret = 0;
if (kwsys::Encoding::ToWindowsExtendedPath(
"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") !=
L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\""
<< std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath(
"L:/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"L:/Local Mojo/Hex Power Pack/Iffy Voodoo\"" << std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath(
"\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") !=
L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\""
<< std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath(
"//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo\""
<< std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath("//") != L"//") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"//\"" << std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\") != L"\\\\.\\") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"\\\\.\\\"" << std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X") != L"\\\\.\\X") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"\\\\.\\X\"" << std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X:") != L"\\\\?\\X:") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"\\\\.\\X:\"" << std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X:\\") !=
L"\\\\?\\X:\\") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"\\\\.\\X:\\\"" << std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath("NUL") != L"\\\\.\\NUL") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"NUL\"" << std::endl;
++ret;
}
return ret;
#else
return 0;
#endif
}
2017-04-14 19:02:05 +02:00
int testEncoding(int, char* [])
2014-08-03 19:52:23 +02:00
{
const char* loc = setlocale(LC_ALL, "");
2017-04-14 19:02:05 +02:00
if (loc) {
2014-08-03 19:52:23 +02:00
std::cout << "Locale: " << loc << std::endl;
2017-04-14 19:02:05 +02:00
} else {
2014-08-03 19:52:23 +02:00
std::cout << "Locale: None" << std::endl;
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
int ret = 0;
ret |= testHelloWorldEncoding();
ret |= testRobustEncoding();
ret |= testCommandLineArguments();
2017-04-14 19:02:05 +02:00
ret |= testWithNulls();
2017-07-20 19:35:53 +02:00
ret |= testToWindowsExtendedPath();
2014-08-03 19:52:23 +02:00
return ret;
}