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

#if defined(_MSC_VER)
6
#pragma warning(disable : 4786)
7 8 9
#endif

#include KWSYS_HEADER(Encoding.hxx)
10
#include KWSYS_HEADER(Encoding.h)
11

12
#include <algorithm>
13
#include <iostream>
14
#include <locale.h>
15
#include <stdlib.h>
16
#include <string.h>
17 18 19 20

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

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

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

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

  int ret = 0;
79
  char cstr[] = { (char)-1, 0 };
80 81 82 83
  // this conversion could fail
  std::wstring wstr = kwsys::Encoding::ToWide(cstr);

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

104
#ifdef _WIN32
105
  // 16 bit wchar_t - we make an invalid surrogate pair
106
  wchar_t cwstr[] = { 0xD801, 0xDA00, 0 };
107 108 109 110 111
  // this conversion could fail
  std::string win_str = kwsys::Encoding::ToNarrow(cwstr);
#endif

  std::string str = kwsys::Encoding::ToNarrow(NULL);
112
  if (str != "") {
113 114
    std::cout << "ToNarrow(NULL) returned " << str << std::endl;
    ret++;
115
  }
116 117

  str = kwsys::Encoding::ToNarrow(L"");
118
  if (wstr != L"") {
119 120
    std::cout << "ToNarrow(\"\") returned " << str << std::endl;
    ret++;
121
  }
122 123 124 125

  return ret;
}

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
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;
}

155 156 157 158
static int testCommandLineArguments()
{
  int status = 0;

159
  char const* argv[2] = { "./app.exe", (char const*)helloWorldStrings[1] };
160 161 162 163 164 165

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

  char const* const* u8_argv = args.argv();
166
  for (int i = 0; i < args.argc(); i++) {
167
    char const* u8_arg = u8_argv[i];
168 169 170
    if (strcmp(argv[i], u8_arg) != 0) {
      std::cout << "argv[" << i << "] " << argv[i] << " != " << u8_arg
                << std::endl;
171 172 173 174 175 176 177 178 179
      status++;
    }
  }

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

  return status;
}
180

181 182 183 184 185 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
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
}

263
int testEncoding(int, char* [])
264 265
{
  const char* loc = setlocale(LC_ALL, "");
266
  if (loc) {
267
    std::cout << "Locale: " << loc << std::endl;
268
  } else {
269
    std::cout << "Locale: None" << std::endl;
270
  }
271 272 273 274 275

  int ret = 0;

  ret |= testHelloWorldEncoding();
  ret |= testRobustEncoding();
276
  ret |= testCommandLineArguments();
277
  ret |= testWithNulls();
278
  ret |= testToWindowsExtendedPath();
279 280 281

  return ret;
}