cmake/Source/kwsys/EncodingCXX.cxx

289 lines
7.8 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
#ifdef __osf__
2018-08-09 18:06:22 +02:00
# define _OSF_SOURCE
# define _POSIX_C_SOURCE 199506L
# define _XOPEN_SOURCE_EXTENDED
2014-08-03 19:52:23 +02:00
#endif
#include "kwsysPrivate.h"
#include KWSYS_HEADER(Encoding.hxx)
#include KWSYS_HEADER(Encoding.h)
// 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
2020-08-30 11:54:41 +02:00
#include <cstdlib>
#include <cstring>
2017-04-14 19:02:05 +02:00
#include <vector>
2014-08-03 19:52:23 +02:00
#ifdef _MSC_VER
2018-08-09 18:06:22 +02:00
# pragma warning(disable : 4786)
2014-08-03 19:52:23 +02:00
#endif
// Windows API.
#if defined(_WIN32)
2018-08-09 18:06:22 +02:00
# include <windows.h>
2017-04-14 19:02:05 +02:00
2018-08-09 18:06:22 +02:00
# include <ctype.h>
# include <shellapi.h>
2014-08-03 19:52:23 +02:00
#endif
2017-04-14 19:02:05 +02:00
namespace KWSYS_NAMESPACE {
2014-08-03 19:52:23 +02:00
2017-04-14 19:02:05 +02:00
Encoding::CommandLineArguments Encoding::CommandLineArguments::Main(
int argc, char const* const* argv)
2014-08-03 19:52:23 +02:00
{
#ifdef _WIN32
2017-04-14 19:02:05 +02:00
(void)argc;
(void)argv;
2014-08-03 19:52:23 +02:00
int ac;
LPWSTR* w_av = CommandLineToArgvW(GetCommandLineW(), &ac);
std::vector<std::string> av1(ac);
std::vector<char const*> av2(ac);
2017-04-14 19:02:05 +02:00
for (int i = 0; i < ac; i++) {
2014-08-03 19:52:23 +02:00
av1[i] = ToNarrow(w_av[i]);
av2[i] = av1[i].c_str();
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
LocalFree(w_av);
return CommandLineArguments(ac, &av2[0]);
#else
return CommandLineArguments(argc, argv);
#endif
}
Encoding::CommandLineArguments::CommandLineArguments(int ac,
char const* const* av)
{
2017-04-14 19:02:05 +02:00
this->argv_.resize(ac + 1);
for (int i = 0; i < ac; i++) {
2014-08-03 19:52:23 +02:00
this->argv_[i] = strdup(av[i]);
2017-04-14 19:02:05 +02:00
}
2020-02-01 23:06:01 +01:00
this->argv_[ac] = nullptr;
2014-08-03 19:52:23 +02:00
}
Encoding::CommandLineArguments::CommandLineArguments(int ac,
wchar_t const* const* av)
{
2017-04-14 19:02:05 +02:00
this->argv_.resize(ac + 1);
for (int i = 0; i < ac; i++) {
2014-08-03 19:52:23 +02:00
this->argv_[i] = kwsysEncoding_DupToNarrow(av[i]);
2017-04-14 19:02:05 +02:00
}
2020-02-01 23:06:01 +01:00
this->argv_[ac] = nullptr;
2014-08-03 19:52:23 +02:00
}
Encoding::CommandLineArguments::~CommandLineArguments()
{
2017-04-14 19:02:05 +02:00
for (size_t i = 0; i < this->argv_.size(); i++) {
2014-08-03 19:52:23 +02:00
free(argv_[i]);
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
}
2017-04-14 19:02:05 +02:00
Encoding::CommandLineArguments::CommandLineArguments(
const CommandLineArguments& other)
2014-08-03 19:52:23 +02:00
{
this->argv_.resize(other.argv_.size());
2017-04-14 19:02:05 +02:00
for (size_t i = 0; i < this->argv_.size(); i++) {
2020-02-01 23:06:01 +01:00
this->argv_[i] = other.argv_[i] ? strdup(other.argv_[i]) : nullptr;
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
}
2017-04-14 19:02:05 +02:00
Encoding::CommandLineArguments& Encoding::CommandLineArguments::operator=(
const CommandLineArguments& other)
2014-08-03 19:52:23 +02:00
{
2017-04-14 19:02:05 +02:00
if (this != &other) {
2015-04-27 22:25:09 +02:00
size_t i;
2017-04-14 19:02:05 +02:00
for (i = 0; i < this->argv_.size(); i++) {
2015-04-27 22:25:09 +02:00
free(this->argv_[i]);
2017-04-14 19:02:05 +02:00
}
2015-04-27 22:25:09 +02:00
this->argv_.resize(other.argv_.size());
2017-04-14 19:02:05 +02:00
for (i = 0; i < this->argv_.size(); i++) {
2020-02-01 23:06:01 +01:00
this->argv_[i] = other.argv_[i] ? strdup(other.argv_[i]) : nullptr;
2014-08-03 19:52:23 +02:00
}
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
return *this;
}
int Encoding::CommandLineArguments::argc() const
{
return static_cast<int>(this->argv_.size() - 1);
}
char const* const* Encoding::CommandLineArguments::argv() const
{
return &this->argv_[0];
}
#if KWSYS_STL_HAS_WSTRING
2015-11-17 17:22:37 +01:00
std::wstring Encoding::ToWide(const std::string& str)
2014-08-03 19:52:23 +02:00
{
2017-04-14 19:02:05 +02:00
std::wstring wstr;
2018-08-09 18:06:22 +02:00
# if defined(_WIN32)
2020-02-01 23:06:01 +01:00
const int wlength =
MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(),
int(str.size()), nullptr, 0);
2017-04-14 19:02:05 +02:00
if (wlength > 0) {
wchar_t* wdata = new wchar_t[wlength];
int r = MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.data(),
int(str.size()), wdata, wlength);
if (r > 0) {
wstr = std::wstring(wdata, wlength);
}
delete[] wdata;
}
2018-08-09 18:06:22 +02:00
# else
2017-04-14 19:02:05 +02:00
size_t pos = 0;
size_t nullPos = 0;
do {
if (pos < str.size() && str.at(pos) != '\0') {
wstr += ToWide(str.c_str() + pos);
}
nullPos = str.find('\0', pos);
2017-07-20 19:35:53 +02:00
if (nullPos != std::string::npos) {
2017-04-14 19:02:05 +02:00
pos = nullPos + 1;
wstr += wchar_t('\0');
}
2017-07-20 19:35:53 +02:00
} while (nullPos != std::string::npos);
2018-08-09 18:06:22 +02:00
# endif
2017-04-14 19:02:05 +02:00
return wstr;
2014-08-03 19:52:23 +02:00
}
2015-11-17 17:22:37 +01:00
std::string Encoding::ToNarrow(const std::wstring& str)
2014-08-03 19:52:23 +02:00
{
2017-04-14 19:02:05 +02:00
std::string nstr;
2018-08-09 18:06:22 +02:00
# if defined(_WIN32)
2017-04-14 19:02:05 +02:00
int length =
WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.c_str(),
2020-02-01 23:06:01 +01:00
int(str.size()), nullptr, 0, nullptr, nullptr);
2017-04-14 19:02:05 +02:00
if (length > 0) {
char* data = new char[length];
int r =
WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str.c_str(),
2020-02-01 23:06:01 +01:00
int(str.size()), data, length, nullptr, nullptr);
2017-04-14 19:02:05 +02:00
if (r > 0) {
nstr = std::string(data, length);
}
delete[] data;
}
2018-08-09 18:06:22 +02:00
# else
2017-04-14 19:02:05 +02:00
size_t pos = 0;
size_t nullPos = 0;
do {
if (pos < str.size() && str.at(pos) != '\0') {
nstr += ToNarrow(str.c_str() + pos);
}
nullPos = str.find(wchar_t('\0'), pos);
2017-07-20 19:35:53 +02:00
if (nullPos != std::string::npos) {
2017-04-14 19:02:05 +02:00
pos = nullPos + 1;
nstr += '\0';
}
2017-07-20 19:35:53 +02:00
} while (nullPos != std::string::npos);
2018-08-09 18:06:22 +02:00
# endif
2017-04-14 19:02:05 +02:00
return nstr;
2014-08-03 19:52:23 +02:00
}
2015-11-17 17:22:37 +01:00
std::wstring Encoding::ToWide(const char* cstr)
2014-08-03 19:52:23 +02:00
{
2015-11-17 17:22:37 +01:00
std::wstring wstr;
2020-02-01 23:06:01 +01:00
size_t length = kwsysEncoding_mbstowcs(nullptr, cstr, 0) + 1;
2017-04-14 19:02:05 +02:00
if (length > 0) {
2015-11-17 17:22:37 +01:00
std::vector<wchar_t> wchars(length);
2017-04-14 19:02:05 +02:00
if (kwsysEncoding_mbstowcs(&wchars[0], cstr, length) > 0) {
2014-08-03 19:52:23 +02:00
wstr = &wchars[0];
}
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
return wstr;
}
2015-11-17 17:22:37 +01:00
std::string Encoding::ToNarrow(const wchar_t* wcstr)
2014-08-03 19:52:23 +02:00
{
2015-11-17 17:22:37 +01:00
std::string str;
2020-02-01 23:06:01 +01:00
size_t length = kwsysEncoding_wcstombs(nullptr, wcstr, 0) + 1;
2017-04-14 19:02:05 +02:00
if (length > 0) {
2014-08-03 19:52:23 +02:00
std::vector<char> chars(length);
2017-04-14 19:02:05 +02:00
if (kwsysEncoding_wcstombs(&chars[0], wcstr, length) > 0) {
2014-08-03 19:52:23 +02:00
str = &chars[0];
}
2017-04-14 19:02:05 +02:00
}
2014-08-03 19:52:23 +02:00
return str;
}
2017-07-20 19:35:53 +02:00
2018-08-09 18:06:22 +02:00
# if defined(_WIN32)
2017-07-20 19:35:53 +02:00
// Convert local paths to UNC style paths
std::wstring Encoding::ToWindowsExtendedPath(std::string const& source)
{
2020-08-30 11:54:41 +02:00
return ToWindowsExtendedPath(ToWide(source));
}
2017-07-20 19:35:53 +02:00
2020-08-30 11:54:41 +02:00
// Convert local paths to UNC style paths
std::wstring Encoding::ToWindowsExtendedPath(const char* source)
{
return ToWindowsExtendedPath(ToWide(source));
}
// Convert local paths to UNC style paths
std::wstring Encoding::ToWindowsExtendedPath(std::wstring const& wsource)
{
2017-07-20 19:35:53 +02:00
// Resolve any relative paths
DWORD wfull_len;
/* The +3 is a workaround for a bug in some versions of GetFullPathNameW that
* won't return a large enough buffer size if the input is too small */
2020-02-01 23:06:01 +01:00
wfull_len = GetFullPathNameW(wsource.c_str(), 0, nullptr, nullptr) + 3;
2017-07-20 19:35:53 +02:00
std::vector<wchar_t> wfull(wfull_len);
2020-02-01 23:06:01 +01:00
GetFullPathNameW(wsource.c_str(), wfull_len, &wfull[0], nullptr);
2017-07-20 19:35:53 +02:00
/* This should get the correct size without any extra padding from the
* previous size workaround. */
wfull_len = static_cast<DWORD>(wcslen(&wfull[0]));
if (wfull_len >= 2 && isalpha(wfull[0]) &&
wfull[1] == L':') { /* C:\Foo\bar\FooBar.txt */
return L"\\\\?\\" + std::wstring(&wfull[0]);
} else if (wfull_len >= 2 && wfull[0] == L'\\' &&
wfull[1] == L'\\') { /* Starts with \\ */
if (wfull_len >= 4 && wfull[2] == L'?' &&
wfull[3] == L'\\') { /* Starts with \\?\ */
if (wfull_len >= 8 && wfull[4] == L'U' && wfull[5] == L'N' &&
wfull[6] == L'C' &&
wfull[7] == L'\\') { /* \\?\UNC\Foo\bar\FooBar.txt */
return std::wstring(&wfull[0]);
} else if (wfull_len >= 6 && isalpha(wfull[4]) &&
wfull[5] == L':') { /* \\?\C:\Foo\bar\FooBar.txt */
return std::wstring(&wfull[0]);
} else if (wfull_len >= 5) { /* \\?\Foo\bar\FooBar.txt */
return L"\\\\?\\UNC\\" + std::wstring(&wfull[4]);
}
} else if (wfull_len >= 4 && wfull[2] == L'.' &&
wfull[3] == L'\\') { /* Starts with \\.\ a device name */
if (wfull_len >= 6 && isalpha(wfull[4]) &&
wfull[5] == L':') { /* \\.\C:\Foo\bar\FooBar.txt */
return L"\\\\?\\" + std::wstring(&wfull[4]);
} else if (wfull_len >=
5) { /* \\.\Foo\bar\ Device name is left unchanged */
return std::wstring(&wfull[0]);
}
} else if (wfull_len >= 3) { /* \\Foo\bar\FooBar.txt */
return L"\\\\?\\UNC\\" + std::wstring(&wfull[2]);
}
}
// If this case has been reached, then the path is invalid. Leave it
// unchanged
2020-08-30 11:54:41 +02:00
return wsource;
2017-07-20 19:35:53 +02:00
}
2018-08-09 18:06:22 +02:00
# endif
2017-07-20 19:35:53 +02:00
2014-08-03 19:52:23 +02:00
#endif // KWSYS_STL_HAS_WSTRING
} // namespace KWSYS_NAMESPACE