testEncoding.cxx 8.54 KB
Newer Older
Kitware Robot's avatar
Kitware Robot committed
1 2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
Kitware Robot's avatar
Kitware Robot committed
3 4 5
#include "kwsysPrivate.h"

#if defined(_MSC_VER)
Kitware Robot's avatar
Kitware Robot committed
6
#  pragma warning(disable : 4786)
Kitware Robot's avatar
Kitware Robot committed
7 8 9
#endif

#include KWSYS_HEADER(Encoding.hxx)
Kitware Robot's avatar
Kitware Robot committed
10
#include KWSYS_HEADER(Encoding.h)
Kitware Robot's avatar
Kitware Robot committed
11

Kitware Robot's avatar
Kitware Robot committed
12
#include <algorithm>
Kitware Robot's avatar
Kitware Robot committed
13
#include <iostream>
Kitware Robot's avatar
Kitware Robot committed
14
#include <locale.h>
Kitware Robot's avatar
Kitware Robot committed
15
#include <stdlib.h>
Kitware Robot's avatar
Kitware Robot committed
16
#include <string.h>
Kitware Robot's avatar
Kitware Robot committed
17 18 19 20

// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
Kitware Robot's avatar
Kitware Robot committed
21 22
#  include "Encoding.h.in"
#  include "Encoding.hxx.in"
Kitware Robot's avatar
Kitware Robot committed
23 24
#endif

Kitware Robot's avatar
Kitware Robot committed
25
static const unsigned char helloWorldStrings[][32] = {
Kitware Robot's avatar
Kitware Robot committed
26
  // English
Kitware Robot's avatar
Kitware Robot committed
27
  { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', 0 },
Kitware Robot's avatar
Kitware Robot committed
28
  // Japanese
Kitware Robot's avatar
Kitware Robot committed
29 30 31 32 33
  { 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 },
Kitware Robot's avatar
Kitware Robot committed
34
  // Yiddish
Kitware Robot's avatar
Kitware Robot committed
35 36
  { 0xD7, 0x94, 0xD7, 0xA2, 0xD7, 0x9C, 0xD7, 0x90, 0x20, 0xD7,
    0x95, 0xD7, 0x95, 0xD7, 0xA2, 0xD7, 0x9C, 0xD7, 0x98, 0 },
Kitware Robot's avatar
Kitware Robot committed
37
  // Russian
Kitware Robot's avatar
Kitware Robot committed
38 39
  { 0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0, 0xB5,
    0xD1, 0x82, 0x20, 0xD0, 0xBC, 0xD0, 0xB8, 0xD1, 0x80, 0 },
Kitware Robot's avatar
Kitware Robot committed
40
  // Latin
Kitware Robot's avatar
Kitware Robot committed
41 42
  { 0x4D, 0x75, 0x6E, 0x64, 0x75, 0x73, 0x20, 0x73, 0x61, 0x6C, 0x76, 0x65,
    0 },
Kitware Robot's avatar
Kitware Robot committed
43
  // Swahili
Kitware Robot's avatar
Kitware Robot committed
44 45
  { 0x68, 0x75, 0x6A, 0x61, 0x6D, 0x62, 0x6F, 0x20, 0x44, 0x75, 0x6E, 0x69,
    0x61, 0 },
Kitware Robot's avatar
Kitware Robot committed
46
  // Icelandic
Kitware Robot's avatar
Kitware Robot committed
47 48 49
  { 0x48, 0x61, 0x6C, 0x6C, 0xC3, 0xB3, 0x20, 0x68, 0x65, 0x69, 0x6D, 0x75,
    0x72, 0 },
  { 0 }
Kitware Robot's avatar
Kitware Robot committed
50 51 52 53 54
};

static int testHelloWorldEncoding()
{
  int ret = 0;
Kitware Robot's avatar
Kitware Robot committed
55
  for (int i = 0; helloWorldStrings[i][0] != 0; i++) {
Kitware Robot's avatar
Kitware Robot committed
56 57 58 59
    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);
Kitware Robot's avatar
Kitware Robot committed
60 61
    wchar_t* c_wstr = kwsysEncoding_DupToWide(str.c_str());
    char* c_str2 = kwsysEncoding_DupToNarrow(c_wstr);
Kitware Robot's avatar
Kitware Robot committed
62
    if (!wstr.empty() && (str != str2 || strcmp(c_str2, str.c_str()))) {
Kitware Robot's avatar
Kitware Robot committed
63
      std::cout << "converted string was different: " << str2 << std::endl;
Kitware Robot's avatar
Kitware Robot committed
64
      std::cout << "converted string was different: " << c_str2 << std::endl;
Kitware Robot's avatar
Kitware Robot committed
65
      ret++;
Kitware Robot's avatar
Kitware Robot committed
66
    }
Kitware Robot's avatar
Kitware Robot committed
67 68
    free(c_wstr);
    free(c_str2);
Kitware Robot's avatar
Kitware Robot committed
69
  }
Kitware Robot's avatar
Kitware Robot committed
70 71 72 73 74 75 76 77
  return ret;
}

static int testRobustEncoding()
{
  // test that the conversion functions handle invalid
  // unicode correctly/gracefully

Kitware Robot's avatar
Kitware Robot committed
78 79 80 81
  // we manipulate the format flags of stdout, remember
  // the original state here to restore before return
  std::ios::fmtflags const& flags = std::cout.flags();

Kitware Robot's avatar
Kitware Robot committed
82
  int ret = 0;
Kitware Robot's avatar
Kitware Robot committed
83
  char cstr[] = { (char)-1, 0 };
Kitware Robot's avatar
Kitware Robot committed
84 85 86
  // this conversion could fail
  std::wstring wstr = kwsys::Encoding::ToWide(cstr);

Kitware Robot's avatar
Kitware Robot committed
87
  wstr = kwsys::Encoding::ToWide(KWSYS_NULLPTR);
Kitware Robot's avatar
Kitware Robot committed
88
  if (wstr != L"") {
Kitware Robot's avatar
Kitware Robot committed
89 90
    const wchar_t* wcstr = wstr.c_str();
    std::cout << "ToWide(NULL) returned";
Kitware Robot's avatar
Kitware Robot committed
91
    for (size_t i = 0; i < wstr.size(); i++) {
Kitware Robot's avatar
Kitware Robot committed
92
      std::cout << " " << std::hex << (int)wcstr[i];
Kitware Robot's avatar
Kitware Robot committed
93
    }
Kitware Robot's avatar
Kitware Robot committed
94 95
    std::cout << std::endl;
    ret++;
Kitware Robot's avatar
Kitware Robot committed
96
  }
Kitware Robot's avatar
Kitware Robot committed
97
  wstr = kwsys::Encoding::ToWide("");
Kitware Robot's avatar
Kitware Robot committed
98
  if (wstr != L"") {
Kitware Robot's avatar
Kitware Robot committed
99 100
    const wchar_t* wcstr = wstr.c_str();
    std::cout << "ToWide(\"\") returned";
Kitware Robot's avatar
Kitware Robot committed
101
    for (size_t i = 0; i < wstr.size(); i++) {
Kitware Robot's avatar
Kitware Robot committed
102
      std::cout << " " << std::hex << (int)wcstr[i];
Kitware Robot's avatar
Kitware Robot committed
103
    }
Kitware Robot's avatar
Kitware Robot committed
104 105
    std::cout << std::endl;
    ret++;
Kitware Robot's avatar
Kitware Robot committed
106
  }
Kitware Robot's avatar
Kitware Robot committed
107

Kitware Robot's avatar
Kitware Robot committed
108
#ifdef _WIN32
Kitware Robot's avatar
Kitware Robot committed
109
  // 16 bit wchar_t - we make an invalid surrogate pair
Kitware Robot's avatar
Kitware Robot committed
110
  wchar_t cwstr[] = { 0xD801, 0xDA00, 0 };
Kitware Robot's avatar
Kitware Robot committed
111 112 113 114
  // this conversion could fail
  std::string win_str = kwsys::Encoding::ToNarrow(cwstr);
#endif

Kitware Robot's avatar
Kitware Robot committed
115
  std::string str = kwsys::Encoding::ToNarrow(KWSYS_NULLPTR);
Kitware Robot's avatar
Kitware Robot committed
116
  if (str != "") {
Kitware Robot's avatar
Kitware Robot committed
117 118
    std::cout << "ToNarrow(NULL) returned " << str << std::endl;
    ret++;
Kitware Robot's avatar
Kitware Robot committed
119
  }
Kitware Robot's avatar
Kitware Robot committed
120 121

  str = kwsys::Encoding::ToNarrow(L"");
Kitware Robot's avatar
Kitware Robot committed
122
  if (wstr != L"") {
Kitware Robot's avatar
Kitware Robot committed
123 124
    std::cout << "ToNarrow(\"\") returned " << str << std::endl;
    ret++;
Kitware Robot's avatar
Kitware Robot committed
125
  }
Kitware Robot's avatar
Kitware Robot committed
126

Kitware Robot's avatar
Kitware Robot committed
127
  std::cout.flags(flags);
Kitware Robot's avatar
Kitware Robot committed
128 129 130
  return ret;
}

Kitware Robot's avatar
Kitware Robot committed
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
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));
  for (std::vector<std::string>::iterator it = strings.begin();
       it != strings.end(); ++it) {
    std::wstring wstr = kwsys::Encoding::ToWide(*it);
    std::string str = kwsys::Encoding::ToNarrow(wstr);
    std::string s(*it);
    std::replace(s.begin(), s.end(), '\0', ' ');
    std::cout << "'" << s << "' (" << it->size() << ")" << std::endl;
    if (str != *it) {
      std::replace(str.begin(), str.end(), '\0', ' ');
      std::cout << "string with null was different: '" << str << "' ("
                << str.size() << ")" << std::endl;
      ret++;
    }
  }
  return ret;
}

Kitware Robot's avatar
Kitware Robot committed
160 161 162 163
static int testCommandLineArguments()
{
  int status = 0;

Kitware Robot's avatar
Kitware Robot committed
164
  char const* argv[2] = { "./app.exe", (char const*)helloWorldStrings[1] };
Kitware Robot's avatar
Kitware Robot committed
165 166 167 168 169 170

  kwsys::Encoding::CommandLineArguments args(2, argv);
  kwsys::Encoding::CommandLineArguments arg2 =
    kwsys::Encoding::CommandLineArguments(args);

  char const* const* u8_argv = args.argv();
Kitware Robot's avatar
Kitware Robot committed
171
  for (int i = 0; i < args.argc(); i++) {
Kitware Robot's avatar
Kitware Robot committed
172
    char const* u8_arg = u8_argv[i];
Kitware Robot's avatar
Kitware Robot committed
173 174 175
    if (strcmp(argv[i], u8_arg) != 0) {
      std::cout << "argv[" << i << "] " << argv[i] << " != " << u8_arg
                << std::endl;
Kitware Robot's avatar
Kitware Robot committed
176 177 178 179 180 181 182 183 184
      status++;
    }
  }

  kwsys::Encoding::CommandLineArguments args3 =
    kwsys::Encoding::CommandLineArguments::Main(2, argv);

  return status;
}
Kitware Robot's avatar
Kitware Robot committed
185

Kitware Robot's avatar
Kitware Robot committed
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
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
}

Kitware Robot's avatar
Kitware Robot committed
268
int testEncoding(int, char* [])
Kitware Robot's avatar
Kitware Robot committed
269 270
{
  const char* loc = setlocale(LC_ALL, "");
Kitware Robot's avatar
Kitware Robot committed
271
  if (loc) {
Kitware Robot's avatar
Kitware Robot committed
272
    std::cout << "Locale: " << loc << std::endl;
Kitware Robot's avatar
Kitware Robot committed
273
  } else {
Kitware Robot's avatar
Kitware Robot committed
274
    std::cout << "Locale: None" << std::endl;
Kitware Robot's avatar
Kitware Robot committed
275
  }
Kitware Robot's avatar
Kitware Robot committed
276 277 278 279 280

  int ret = 0;

  ret |= testHelloWorldEncoding();
  ret |= testRobustEncoding();
Kitware Robot's avatar
Kitware Robot committed
281
  ret |= testCommandLineArguments();
Kitware Robot's avatar
Kitware Robot committed
282
  ret |= testWithNulls();
Kitware Robot's avatar
Kitware Robot committed
283
  ret |= testToWindowsExtendedPath();
Kitware Robot's avatar
Kitware Robot committed
284 285 286

  return ret;
}