Skip to content

Commit

Permalink
Refactor utf8_to_windows_encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
AntoinePrv committed Oct 26, 2023
1 parent 08cbcb7 commit 2007b5b
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 56 deletions.
1 change: 0 additions & 1 deletion libmamba/include/mamba/core/util_os.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ namespace mamba
std::string to_utf8(const wchar_t* windows_unicode_text, size_t size);
std::string to_utf8(const wchar_t* windows_unicode_text);
std::string to_utf8(const std::wstring& windows_unicode_text);
std::wstring to_windows_unicode(const std::string_view utf8_text);
#endif

/* Test whether a given `std::ostream` object refers to a terminal. */
Expand Down
6 changes: 5 additions & 1 deletion libmamba/include/mamba/util/os_win.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
#ifndef MAMBA_UTIL_OS_WIN_HPP
#define MAMBA_UTIL_OS_WIN_HPP

#include "mamba/fs/filesystem.hpp"
#include <string>
#include <string_view>

#include "mamba/fs/filesystem.hpp"

namespace mamba::util
{
Expand All @@ -23,5 +25,7 @@ namespace mamba::util
};

auto get_windows_known_user_folder(WindowsKnowUserFolder dir) -> fs::u8path;

auto utf8_to_windows_encoding(const std::string_view utf8_text) -> std::wstring;
}
#endif
6 changes: 3 additions & 3 deletions libmamba/src/core/environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace mamba::env
);
};

const std::wstring unicode_key = to_windows_unicode(key);
const std::wstring unicode_key = util::utf8_to_windows_encoding(key);
size_t required_size = 0;
if (auto error_code = _wgetenv_s(&required_size, nullptr, 0, unicode_key.c_str());
error_code == 0)
Expand Down Expand Up @@ -99,8 +99,8 @@ namespace mamba::env
// functions are not thread-safe, this
// is to prevent related issues.

const std::wstring unicode_key = to_windows_unicode(key);
const std::wstring unicode_value = to_windows_unicode(value);
const std::wstring unicode_key = util::utf8_to_windows_encoding(key);
const std::wstring unicode_value = util::utf8_to_windows_encoding(value);
auto res = _wputenv_s(unicode_key.c_str(), unicode_value.c_str());
if (res != 0)
{
Expand Down
37 changes: 0 additions & 37 deletions libmamba/src/core/util_os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -538,43 +538,6 @@ namespace mamba
return to_utf8(s.data(), s.size());
}

std::wstring to_windows_unicode(const std::string_view utf8_text)
{
std::wstring output;
if (!utf8_text.empty())
{
assert(utf8_text.size() <= INT_MAX);
const int size = MultiByteToWideChar(
CP_UTF8,
0,
utf8_text.data(),
utf8_text.size(),
nullptr,
0
);
if (size <= 0)
{
unsigned long last_error = ::GetLastError();
LOG_ERROR << "Failed to convert UTF-8 string to Windows Unicode (UTF-16)"
<< std::system_category().message(static_cast<int>(last_error));
throw std::runtime_error("Failed to convert UTF-8 string to UTF-16");
}

output.resize(size);
int res_size = MultiByteToWideChar(
CP_UTF8,
0,
utf8_text.data(),
utf8_text.size(),
output.data(),
output.size()
);
assert(res_size == size);
}

return output;
}

#endif

/* From https://github.com/ikalnytskyi/termcolor
Expand Down
55 changes: 47 additions & 8 deletions libmamba/src/util/os_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@

#ifdef _WIN32

#include <cassert>
#include <limits>
#include <stdexcept>

#include <fmt/format.h>
#include <Shlobj.h>

#include "mamba/util/os_win.hpp"
Expand All @@ -22,17 +25,17 @@ namespace mamba::util
switch (dir)
{
case (WindowsKnowUserFolder::Documents):
return FOLDERID_Documents;
return ::FOLDERID_Documents;
case (WindowsKnowUserFolder::Profile):
return FOLDERID_Profile;
return ::FOLDERID_Profile;
case (WindowsKnowUserFolder::Programs):
return FOLDERID_Programs;
return ::FOLDERID_Programs;
case (WindowsKnowUserFolder::ProgramData):
return FOLDERID_ProgramData;
return ::FOLDERID_ProgramData;
case (WindowsKnowUserFolder::LocalAppData):
return FOLDERID_LocalAppData;
return ::FOLDERID_LocalAppData;
case (WindowsKnowUserFolder::RoamingAppData):
return FOLDERID_RoamingAppData;
return ::FOLDERID_RoamingAppData;
}
throw std::invalid_argument("Invalid enum");
}
Expand All @@ -41,7 +44,7 @@ namespace mamba::util
{
~COMwstr()
{
CoTaskMemFree(str);
::CoTaskMemFree(str);
}

wchar_t* str = nullptr;
Expand All @@ -52,7 +55,7 @@ namespace mamba::util
{
auto localAppData = COMwstr{ nullptr };

HRESULT const hres = SHGetKnownFolderPath(
const auto hres = SHGetKnownFolderPath(
get_windows_known_user_folder_raw(dir),
KF_FLAG_DONT_VERIFY,
nullptr,
Expand All @@ -66,6 +69,37 @@ namespace mamba::util

return fs::u8path(localAppData.str);
}

auto utf8_to_windows_encoding(const std::string_view utf8_text) -> std::wstring
{
if (utf8_text.empty())
{
return {};
}

assert(utf8_text.size() <= std::numeric_limits<int>::max());
const int size = ::MultiByteToWideChar(CP_UTF8, 0, utf8_text.data(), utf8_text.size(), nullptr, 0);
if (size <= 0)
{
throw std::runtime_error(fmt::format(
R"(Failed to convert UTF-8 string "{}" to UTF-16: )",
utf8_text,
std::system_category().message(static_cast<int>(::GetLastError()))
));
}

auto output = std::wstring(static_cast<std::size_t>(size), char(0));
[[maybe_unused]] const int res_size = ::MultiByteToWideChar(
CP_UTF8,
0,
utf8_text.data(),
utf8_text.size(),
output.data(),
output.size()
);
assert(res_size == size);
return output;
}
}

#else // #ifdef _WIN32
Expand All @@ -91,6 +125,11 @@ namespace mamba::util
{
throw_not_implemented("get_windows_known_user_folder");
}

auto utf8_to_windows_encoding(const std::string_view) -> std::wstring
{
throw_not_implemented("utf8_to_windows_unicode");
}
}

#endif // #ifdef _WIN32
1 change: 1 addition & 0 deletions libmamba/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ set(LIBMAMBA_TEST_SRCS
src/util/test_flat_bool_expr_tree.cpp
src/util/test_graph.cpp
src/util/test_iterator.cpp
src/util/test_os_win.cpp
src/util/test_path_manip.cpp
src/util/test_tuple_hash.cpp
src/util/test_url_manip.cpp
Expand Down
6 changes: 0 additions & 6 deletions libmamba/tests/src/core/test_util_os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ TEST_SUITE("basic_unicode_conversion")
auto result = mamba::to_utf8(text_utf16);
CHECK_EQ(text_utf8, result);
}

TEST_CASE("to_windows_unicode")
{
auto result = mamba::to_windows_unicode(text_utf8);
CHECK_EQ(text_utf16, result);
}
}

TEST_SUITE("windows_path")
Expand Down
31 changes: 31 additions & 0 deletions libmamba/tests/src/util/test_os_win.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) 2023, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.

#ifdef _WIN32

#include <string>

#include <doctest/doctest.h>

#include "mamba/util/os_win.hpp"

using namespace mamba::util;

TEST_SUITE("uti::os_win")
{
TEST_CASE("")
{
const std::wstring text_utf16 = L"Hello, I am Joël. 私のにほんごわへたです";
const std::string text_utf8 = u8"Hello, I am Joël. 私のにほんごわへたです";

SUBCASE("utf8_to_windows_encoding")
{
CHECK_EQ(to_windows_encoding(text_utf8), text_utf16);
}
}
}

#endif

0 comments on commit 2007b5b

Please sign in to comment.