updated build system
Some checks failed
BlockStorage/repertory/pipeline/head There was a failure building this commit
Some checks failed
BlockStorage/repertory/pipeline/head There was a failure building this commit
This commit is contained in:
16
support/3rd_party/icu_configure.sh
vendored
Normal file
16
support/3rd_party/icu_configure.sh
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [ "$(uname -m)" == "arm64" ] &&
|
||||
[ "${PROJECT_IS_ARM64}" == "0" ]; then
|
||||
HOST_CFG="--host=x86_64-apple-darwin"
|
||||
export CC="clang -arch x86_64"
|
||||
export CXX="clang++ -arch x86_64"
|
||||
fi
|
||||
|
||||
CXXFLAGS="-std=gnu++17 -march=$1 -mtune=generic" ./configure \
|
||||
--disable-samples \
|
||||
--disable-tests \
|
||||
--enable-shared=$3 \
|
||||
--enable-static=yes \
|
||||
--prefix="$2" \
|
||||
${HOST_CFG}
|
@@ -46,7 +46,7 @@ struct com_init_wrapper final {
|
||||
[[nodiscard]] auto is_initialized() const -> bool { return initialized_; }
|
||||
|
||||
private:
|
||||
BOOL initialized_;
|
||||
BOOL initialized_{};
|
||||
};
|
||||
} // namespace repertory::utils
|
||||
|
||||
|
@@ -107,7 +107,6 @@
|
||||
#include <cerrno>
|
||||
#include <chrono>
|
||||
#include <climits>
|
||||
#include <codecvt>
|
||||
#include <condition_variable>
|
||||
#include <csignal>
|
||||
#include <cstdint>
|
||||
@@ -149,6 +148,9 @@
|
||||
#include <version>
|
||||
#endif // defined(__cplusplus)
|
||||
|
||||
#include <unicode/uchar.h>
|
||||
#include <unicode/utf.h>
|
||||
|
||||
#if defined(PROJECT_ENABLE_CURL)
|
||||
#include "curl/curl.h"
|
||||
#include "curl/multi.h"
|
||||
|
@@ -97,7 +97,7 @@ private:
|
||||
|
||||
private:
|
||||
std::unordered_map<std::size_t, data_buffer> chunk_buffers_;
|
||||
std::optional<std::array<std::uint8_t, kdf_config::size()>> kdf_header_;
|
||||
std::optional<data_buffer> kdf_header_;
|
||||
std::size_t last_data_chunk_{};
|
||||
std::size_t last_data_chunk_size_{};
|
||||
std::uint64_t read_offset_{};
|
||||
|
@@ -101,27 +101,19 @@ struct kdf_config final {
|
||||
salt_t salt{};
|
||||
std::uint64_t checksum{};
|
||||
|
||||
[[nodiscard]] static constexpr auto size() -> std::size_t {
|
||||
return sizeof(kdf_config);
|
||||
}
|
||||
[[nodiscard]] static auto from_header(std::span<const unsigned char> data,
|
||||
kdf_config &cfg) -> bool;
|
||||
|
||||
[[nodiscard]] auto generate_checksum() const -> std::uint64_t;
|
||||
|
||||
void generate_salt();
|
||||
|
||||
[[nodiscard]] static auto from_header(std::span<const unsigned char> data,
|
||||
kdf_config &cfg) -> bool;
|
||||
|
||||
[[nodiscard]] auto to_header() -> auto {
|
||||
kdf_config tmp{*this};
|
||||
tmp.checksum = boost::endian::native_to_big(tmp.checksum);
|
||||
tmp.magic = boost::endian::native_to_big(tmp.magic);
|
||||
|
||||
std::array<std::uint8_t, size()> ret{};
|
||||
std::memcpy(ret.data(), &tmp, size());
|
||||
return ret;
|
||||
[[nodiscard]] static constexpr auto size() -> std::size_t {
|
||||
return sizeof(kdf_config);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto to_header() const -> data_buffer;
|
||||
|
||||
[[nodiscard]] auto operator==(const kdf_config &) const -> bool = default;
|
||||
[[nodiscard]] auto operator!=(const kdf_config &) const -> bool = default;
|
||||
};
|
||||
|
@@ -28,10 +28,33 @@
|
||||
#include "utils/error.hpp"
|
||||
|
||||
namespace repertory::utils::hash {
|
||||
using hash_32_t = std::array<unsigned char, 4U>;
|
||||
using hash_64_t = std::array<unsigned char, 8U>;
|
||||
using hash_128_t = std::array<unsigned char, 16U>;
|
||||
using hash_256_t = std::array<unsigned char, 32U>;
|
||||
using hash_384_t = std::array<unsigned char, 48U>;
|
||||
using hash_512_t = std::array<unsigned char, 64U>;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_32(std::string_view data) -> hash_32_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_32(std::wstring_view data) -> hash_32_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_32(const data_buffer &data) -> hash_32_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_64(std::string_view data) -> hash_64_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_64(std::wstring_view data) -> hash_64_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_64(const data_buffer &data) -> hash_64_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_128(std::string_view data) -> hash_128_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_128(std::wstring_view data)
|
||||
-> hash_128_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_128(const data_buffer &data)
|
||||
-> hash_128_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_256(std::string_view data) -> hash_256_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_256(std::wstring_view data)
|
||||
@@ -123,6 +146,27 @@ auto create_hash_blake2b_t(const unsigned char *data, std::size_t data_size)
|
||||
return hash;
|
||||
}
|
||||
|
||||
inline const std::function<hash_32_t(const unsigned char *data,
|
||||
std::size_t size)>
|
||||
blake2b_32_hasher =
|
||||
[](const unsigned char *data, std::size_t data_size) -> hash_32_t {
|
||||
return create_hash_blake2b_t<hash_32_t>(data, data_size);
|
||||
};
|
||||
|
||||
inline const std::function<hash_64_t(const unsigned char *data,
|
||||
std::size_t size)>
|
||||
blake2b_64_hasher =
|
||||
[](const unsigned char *data, std::size_t data_size) -> hash_64_t {
|
||||
return create_hash_blake2b_t<hash_64_t>(data, data_size);
|
||||
};
|
||||
|
||||
inline const std::function<hash_128_t(const unsigned char *data,
|
||||
std::size_t size)>
|
||||
blake2b_128_hasher =
|
||||
[](const unsigned char *data, std::size_t data_size) -> hash_128_t {
|
||||
return create_hash_blake2b_t<hash_128_t>(data, data_size);
|
||||
};
|
||||
|
||||
inline const std::function<hash_256_t(const unsigned char *data,
|
||||
std::size_t size)>
|
||||
blake2b_256_hasher =
|
||||
@@ -158,6 +202,24 @@ inline const std::function<hash_512_t(const unsigned char *data,
|
||||
return create_hash_sha512(data, data_size);
|
||||
};
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline auto default_create_hash<hash_32_t>() -> const
|
||||
std::function<hash_32_t(const unsigned char *data, std::size_t size)> & {
|
||||
return blake2b_32_hasher;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline auto default_create_hash<hash_64_t>() -> const
|
||||
std::function<hash_64_t(const unsigned char *data, std::size_t size)> & {
|
||||
return blake2b_64_hasher;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline auto default_create_hash<hash_128_t>() -> const
|
||||
std::function<hash_128_t(const unsigned char *data, std::size_t size)> & {
|
||||
return blake2b_128_hasher;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline auto default_create_hash<hash_256_t>() -> const
|
||||
std::function<hash_256_t(const unsigned char *data, std::size_t size)> & {
|
||||
|
@@ -34,13 +34,23 @@ void free_console();
|
||||
|
||||
[[nodiscard]] auto get_last_error_code() -> DWORD;
|
||||
|
||||
[[nodiscard]] auto get_startup_folder() -> std::wstring;
|
||||
|
||||
[[nodiscard]] auto get_thread_id() -> std::uint64_t;
|
||||
|
||||
[[nodiscard]] auto is_process_elevated() -> bool;
|
||||
|
||||
[[nodiscard]] auto run_process_elevated(std::vector<const char *> args) -> int;
|
||||
|
||||
void set_last_error_code(DWORD errorCode);
|
||||
[[nodiscard]]
|
||||
auto create_shortcut(const std::wstring &exe_path,
|
||||
const std::wstring &arguments,
|
||||
const std::wstring &working_directory,
|
||||
const std::wstring &shortcut_name = L"",
|
||||
const std::wstring &location = get_startup_folder())
|
||||
-> bool;
|
||||
|
||||
void set_last_error_code(DWORD error_code);
|
||||
} // namespace repertory::utils
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
|
@@ -25,9 +25,19 @@
|
||||
|
||||
#include "utils/collection.hpp"
|
||||
#include "utils/encrypting_reader.hpp"
|
||||
#include "utils/hash.hpp"
|
||||
#include "utils/path.hpp"
|
||||
|
||||
namespace repertory::utils::encryption {
|
||||
auto kdf_config::to_header() const -> data_buffer {
|
||||
kdf_config tmp{*this};
|
||||
tmp.checksum = boost::endian::native_to_big(tmp.checksum);
|
||||
tmp.magic = boost::endian::native_to_big(tmp.magic);
|
||||
|
||||
data_buffer ret(size());
|
||||
std::memcpy(ret.data(), &tmp, ret.size());
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto kdf_config::generate_checksum() const -> std::uint64_t {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
@@ -35,18 +45,8 @@ auto kdf_config::generate_checksum() const -> std::uint64_t {
|
||||
kdf_config tmp = *this;
|
||||
tmp.checksum = 0;
|
||||
|
||||
auto hdr = tmp.to_header();
|
||||
|
||||
std::uint64_t ret{0};
|
||||
if (crypto_generichash(reinterpret_cast<unsigned char *>(&ret), sizeof(ret),
|
||||
hdr.data(), hdr.size(), nullptr, 0) != 0) {
|
||||
throw utils::error::create_exception(function_name,
|
||||
{
|
||||
"failed to calculate checksum",
|
||||
});
|
||||
}
|
||||
|
||||
return ret;
|
||||
auto hash = utils::hash::create_hash_blake2b_64(tmp.to_header());
|
||||
return *reinterpret_cast<std::uint64_t *>(hash.data());
|
||||
}
|
||||
|
||||
void kdf_config::generate_salt() {
|
||||
|
@@ -26,6 +26,57 @@
|
||||
#include "utils/error.hpp"
|
||||
|
||||
namespace repertory::utils::hash {
|
||||
auto create_hash_blake2b_32(std::string_view data) -> hash_32_t {
|
||||
return create_hash_blake2b_t<hash_32_t>(
|
||||
reinterpret_cast<const unsigned char *>(data.data()), data.size());
|
||||
}
|
||||
|
||||
auto create_hash_blake2b_32(std::wstring_view data) -> hash_32_t {
|
||||
return create_hash_blake2b_t<hash_32_t>(
|
||||
reinterpret_cast<const unsigned char *>(data.data()),
|
||||
data.size() * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
auto create_hash_blake2b_32(const data_buffer &data) -> hash_32_t {
|
||||
return create_hash_blake2b_t<hash_32_t>(
|
||||
reinterpret_cast<const unsigned char *>(data.data()),
|
||||
data.size() * sizeof(data_buffer::value_type));
|
||||
}
|
||||
|
||||
auto create_hash_blake2b_64(std::string_view data) -> hash_64_t {
|
||||
return create_hash_blake2b_t<hash_64_t>(
|
||||
reinterpret_cast<const unsigned char *>(data.data()), data.size());
|
||||
}
|
||||
|
||||
auto create_hash_blake2b_64(std::wstring_view data) -> hash_64_t {
|
||||
return create_hash_blake2b_t<hash_64_t>(
|
||||
reinterpret_cast<const unsigned char *>(data.data()),
|
||||
data.size() * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
auto create_hash_blake2b_64(const data_buffer &data) -> hash_64_t {
|
||||
return create_hash_blake2b_t<hash_64_t>(
|
||||
reinterpret_cast<const unsigned char *>(data.data()),
|
||||
data.size() * sizeof(data_buffer::value_type));
|
||||
}
|
||||
|
||||
auto create_hash_blake2b_128(std::string_view data) -> hash_128_t {
|
||||
return create_hash_blake2b_t<hash_128_t>(
|
||||
reinterpret_cast<const unsigned char *>(data.data()), data.size());
|
||||
}
|
||||
|
||||
auto create_hash_blake2b_128(std::wstring_view data) -> hash_128_t {
|
||||
return create_hash_blake2b_t<hash_128_t>(
|
||||
reinterpret_cast<const unsigned char *>(data.data()),
|
||||
data.size() * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
auto create_hash_blake2b_128(const data_buffer &data) -> hash_128_t {
|
||||
return create_hash_blake2b_t<hash_128_t>(
|
||||
reinterpret_cast<const unsigned char *>(data.data()),
|
||||
data.size() * sizeof(data_buffer::value_type));
|
||||
}
|
||||
|
||||
auto create_hash_blake2b_256(std::string_view data) -> hash_256_t {
|
||||
return create_hash_blake2b_t<hash_256_t>(
|
||||
reinterpret_cast<const unsigned char *>(data.data()), data.size());
|
||||
|
@@ -36,10 +36,49 @@ auto from_dynamic_bitset(const boost::dynamic_bitset<> &bitset) -> std::string {
|
||||
#endif // defined(PROJECT_ENABLE_BOOST)
|
||||
|
||||
auto from_utf8(std::string_view str) -> std::wstring {
|
||||
return str.empty()
|
||||
? L""
|
||||
: std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>()
|
||||
.from_bytes(std::string{str});
|
||||
if (str.empty()) {
|
||||
return L"";
|
||||
}
|
||||
|
||||
std::wstring out;
|
||||
|
||||
const auto *str_ptr = reinterpret_cast<const std::uint8_t *>(str.data());
|
||||
std::int32_t idx{};
|
||||
auto len{static_cast<std::int32_t>(str.size())};
|
||||
|
||||
#if WCHAR_MAX <= 0xFFFF
|
||||
out.reserve((str.size() + 1U) / 2U);
|
||||
while (idx < len) {
|
||||
UChar32 uni_ch{};
|
||||
U8_NEXT(str_ptr, idx, len, uni_ch);
|
||||
if (uni_ch < 0 || !U_IS_UNICODE_CHAR(uni_ch)) {
|
||||
throw std::runtime_error("from_utf8: invalid UTF-8 sequence");
|
||||
}
|
||||
std::array<UChar, 2U> units{};
|
||||
std::int32_t off{};
|
||||
auto err{false};
|
||||
U16_APPEND(units.data(), off, 2, uni_ch, err);
|
||||
if (err || off <= 0) {
|
||||
throw std::runtime_error("from_utf8: U16_APPEND failed");
|
||||
}
|
||||
out.push_back(static_cast<wchar_t>(units[0U]));
|
||||
if (off == 2) {
|
||||
out.push_back(static_cast<wchar_t>(units[1U]));
|
||||
}
|
||||
}
|
||||
#else // WCHAR_MAX > 0xFFFF
|
||||
out.reserve(str.size());
|
||||
while (idx < len) {
|
||||
UChar32 uni_ch{};
|
||||
U8_NEXT(str_ptr, idx, len, uni_ch);
|
||||
if (uni_ch < 0 || !U_IS_UNICODE_CHAR(uni_ch)) {
|
||||
throw std::runtime_error("from_utf8: invalid UTF-8 sequence");
|
||||
}
|
||||
out.push_back(static_cast<wchar_t>(uni_ch));
|
||||
}
|
||||
#endif // WCHAR_MAX <= 0xFFFF
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#if defined(PROJECT_ENABLE_SFML)
|
||||
@@ -55,8 +94,8 @@ auto replace_sf(sf::String &src, const sf::String &find, const sf::String &with,
|
||||
return src;
|
||||
}
|
||||
|
||||
auto split_sf(sf::String str, wchar_t delim,
|
||||
bool should_trim) -> std::vector<sf::String> {
|
||||
auto split_sf(sf::String str, wchar_t delim, bool should_trim)
|
||||
-> std::vector<sf::String> {
|
||||
auto result = std::views::split(str.toWideString(), delim);
|
||||
|
||||
std::vector<sf::String> ret{};
|
||||
@@ -130,9 +169,51 @@ auto to_uint64(const std::string &val) -> std::uint64_t {
|
||||
auto to_utf8(std::string_view str) -> std::string { return std::string{str}; }
|
||||
|
||||
auto to_utf8(std::wstring_view str) -> std::string {
|
||||
return str.empty()
|
||||
? ""
|
||||
: std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>()
|
||||
.to_bytes(std::wstring{str});
|
||||
if (str.empty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string out;
|
||||
out.reserve(static_cast<size_t>(str.size()) * 4);
|
||||
|
||||
#if WCHAR_MAX <= 0xFFFF
|
||||
const auto *u16 = reinterpret_cast<const UChar *>(str.data());
|
||||
std::int32_t idx{};
|
||||
auto len{static_cast<int32_t>(str.size())};
|
||||
while (idx < len) {
|
||||
UChar32 uni_ch{};
|
||||
U16_NEXT(u16, idx, len, uni_ch);
|
||||
if (uni_ch < 0 || !U_IS_UNICODE_CHAR(uni_ch)) {
|
||||
throw std::runtime_error("to_utf8: invalid UTF-16 sequence");
|
||||
}
|
||||
std::array<std::uint8_t, U8_MAX_LENGTH> buf{};
|
||||
std::int32_t off{0};
|
||||
auto err{false};
|
||||
U8_APPEND(buf.data(), off, U8_MAX_LENGTH, uni_ch, err);
|
||||
if (err || off <= 0) {
|
||||
throw std::runtime_error("to_utf8: U8_APPEND failed");
|
||||
}
|
||||
out.append(reinterpret_cast<const char *>(buf.data()),
|
||||
static_cast<std::size_t>(off));
|
||||
}
|
||||
#else // WCHAR_MAX > 0xFFFF
|
||||
for (auto cur_ch : str) {
|
||||
auto uni_char{static_cast<UChar32>(cur_ch)};
|
||||
if (!U_IS_UNICODE_CHAR(uni_char)) {
|
||||
throw std::runtime_error("to_utf8: invalid Unicode scalar value");
|
||||
}
|
||||
std::array<std::uint8_t, U8_MAX_LENGTH> buf{};
|
||||
std::int32_t off{0};
|
||||
auto err{false};
|
||||
U8_APPEND(buf.data(), off, U8_MAX_LENGTH, uni_char, err);
|
||||
if (err || off <= 0) {
|
||||
throw std::runtime_error("to_utf8: U8_APPEND failed");
|
||||
}
|
||||
out.append(reinterpret_cast<const char *>(buf.data()),
|
||||
static_cast<std::size_t>(off));
|
||||
}
|
||||
#endif // WCHAR_MAX <= 0xFFFF
|
||||
|
||||
return out;
|
||||
}
|
||||
} // namespace repertory::utils::string
|
||||
|
@@ -23,7 +23,6 @@
|
||||
|
||||
#include "utils/windows.hpp"
|
||||
|
||||
#include "utils/com_init_wrapper.hpp"
|
||||
#include "utils/error.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
@@ -65,7 +64,6 @@ auto get_local_app_data_directory() -> const std::string & {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
static std::string app_data = ([]() -> std::string {
|
||||
com_init_wrapper cw;
|
||||
PWSTR local_app_data{};
|
||||
if (SUCCEEDED(::SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr,
|
||||
&local_app_data))) {
|
||||
@@ -139,6 +137,142 @@ auto run_process_elevated(std::vector<const char *> args) -> int {
|
||||
}
|
||||
|
||||
void set_last_error_code(DWORD error_code) { ::SetLastError(error_code); }
|
||||
|
||||
auto get_startup_folder() -> std::wstring {
|
||||
PWSTR raw{nullptr};
|
||||
auto result = ::SHGetKnownFolderPath(FOLDERID_Startup, 0, nullptr, &raw);
|
||||
if (FAILED(result)) {
|
||||
if (raw != nullptr) {
|
||||
::CoTaskMemFree(raw);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::wstring str{raw};
|
||||
::CoTaskMemFree(raw);
|
||||
return str;
|
||||
}
|
||||
|
||||
auto create_shortcut(const std::wstring &exe_path,
|
||||
const std::wstring &arguments,
|
||||
const std::wstring &working_directory,
|
||||
const std::wstring &shortcut_name, std::wstring location)
|
||||
-> bool {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
const auto hr_hex = [](HRESULT hr) -> std::string {
|
||||
std::ostringstream oss;
|
||||
oss << "0x" << std::uppercase << std::hex << std::setw(8)
|
||||
<< std::setfill('0') << static_cast<std::uint32_t>(hr);
|
||||
return oss.str();
|
||||
};
|
||||
|
||||
if (location.empty()) {
|
||||
utils::error::handle_error(function_name, "Shortcut location was empty.");
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
std::error_code ec_mk;
|
||||
std::filesystem::create_directories(std::filesystem::path{location}, ec_mk);
|
||||
}
|
||||
|
||||
std::filesystem::path exe_p{exe_path};
|
||||
std::wstring final_name = shortcut_name.empty()
|
||||
? (exe_p.stem().wstring() + L".lnk")
|
||||
: shortcut_name;
|
||||
if (not final_name.ends_with(L".lnk")) {
|
||||
final_name += L".lnk";
|
||||
}
|
||||
|
||||
const std::filesystem::path lnk_path =
|
||||
std::filesystem::path{location} / final_name;
|
||||
|
||||
IShellLinkW *psl{nullptr};
|
||||
HRESULT result = ::CoCreateInstance(CLSID_ShellLink, nullptr,
|
||||
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&psl));
|
||||
if (FAILED(result)) {
|
||||
utils::error::handle_error(
|
||||
function_name,
|
||||
std::string("CoCreateInstance(CLSID_ShellLink) failed: ") +
|
||||
hr_hex(result));
|
||||
return false;
|
||||
}
|
||||
|
||||
result = psl->SetPath(exe_path.c_str());
|
||||
if (FAILED(result)) {
|
||||
utils::error::handle_error(function_name,
|
||||
std::string("IShellLink::SetPath failed: ") +
|
||||
hr_hex(result));
|
||||
psl->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not arguments.empty()) {
|
||||
result = psl->SetArguments(arguments.c_str());
|
||||
if (FAILED(result)) {
|
||||
utils::error::handle_error(
|
||||
function_name,
|
||||
std::string("IShellLink::SetArguments failed: ") + hr_hex(result));
|
||||
psl->Release();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (not working_directory.empty()) {
|
||||
result = psl->SetWorkingDirectory(working_directory.c_str());
|
||||
if (FAILED(result)) {
|
||||
utils::error::handle_error(
|
||||
function_name,
|
||||
std::string("IShellLink::SetWorkingDirectory failed: ") +
|
||||
hr_hex(result));
|
||||
psl->Release();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
result = psl->SetShowCmd(SW_SHOWNORMAL);
|
||||
if (FAILED(result)) {
|
||||
utils::error::handle_error(function_name,
|
||||
std::string("IShellLink::SetShowCmd failed: ") +
|
||||
hr_hex(result));
|
||||
psl->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Best-effort overwrite
|
||||
{
|
||||
std::error_code ec;
|
||||
std::filesystem::remove(lnk_path, ec);
|
||||
}
|
||||
|
||||
IPersistFile *ppf{nullptr};
|
||||
result = psl->QueryInterface(IID_PPV_ARGS(&ppf));
|
||||
if (FAILED(result)) {
|
||||
utils::error::handle_error(
|
||||
function_name,
|
||||
std::string("QueryInterface(IPersistFile) failed: ") + hr_hex(result));
|
||||
psl->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
result = ppf->Save(lnk_path.c_str(), TRUE);
|
||||
ppf->SaveCompleted(lnk_path.c_str());
|
||||
|
||||
ppf->Release();
|
||||
psl->Release();
|
||||
|
||||
if (FAILED(result)) {
|
||||
utils::error::handle_error(function_name,
|
||||
std::string("IPersistFile::Save failed: ") +
|
||||
hr_hex(result));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace repertory::utils
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
|
@@ -25,12 +25,24 @@
|
||||
|
||||
namespace repertory {
|
||||
TEST(utils_hash, hash_type_sizes) {
|
||||
EXPECT_EQ(4U, utils::hash::hash_32_t{}.size());
|
||||
EXPECT_EQ(8U, utils::hash::hash_64_t{}.size());
|
||||
EXPECT_EQ(16U, utils::hash::hash_128_t{}.size());
|
||||
EXPECT_EQ(32U, utils::hash::hash_256_t{}.size());
|
||||
EXPECT_EQ(48U, utils::hash::hash_384_t{}.size());
|
||||
EXPECT_EQ(64U, utils::hash::hash_512_t{}.size());
|
||||
}
|
||||
|
||||
TEST(utils_hash, default_hasher_is_blake2b) {
|
||||
EXPECT_EQ(&utils::hash::blake2b_32_hasher,
|
||||
&utils::hash::default_create_hash<utils::hash::hash_32_t>());
|
||||
|
||||
EXPECT_EQ(&utils::hash::blake2b_64_hasher,
|
||||
&utils::hash::default_create_hash<utils::hash::hash_64_t>());
|
||||
|
||||
EXPECT_EQ(&utils::hash::blake2b_128_hasher,
|
||||
&utils::hash::default_create_hash<utils::hash::hash_128_t>());
|
||||
|
||||
EXPECT_EQ(&utils::hash::blake2b_256_hasher,
|
||||
&utils::hash::default_create_hash<utils::hash::hash_256_t>());
|
||||
|
||||
@@ -41,6 +53,60 @@ TEST(utils_hash, default_hasher_is_blake2b) {
|
||||
&utils::hash::default_create_hash<utils::hash::hash_512_t>());
|
||||
}
|
||||
|
||||
TEST(utils_hash, blake2b_32) {
|
||||
auto hash = utils::collection::to_hex_string(
|
||||
utils::hash::create_hash_blake2b_32("a"));
|
||||
EXPECT_STREQ("ca234c55", hash.c_str());
|
||||
|
||||
hash = utils::collection::to_hex_string(
|
||||
utils::hash::create_hash_blake2b_32(L"a"));
|
||||
#if defined(_WIN32)
|
||||
EXPECT_STREQ("4c368117", hash.c_str());
|
||||
#else // !defined(_WIN32)
|
||||
EXPECT_STREQ("02a631b8", hash.c_str());
|
||||
#endif
|
||||
|
||||
hash = utils::collection::to_hex_string(
|
||||
utils::hash::create_hash_blake2b_32({1U}));
|
||||
EXPECT_STREQ("593bda73", hash.c_str());
|
||||
}
|
||||
|
||||
TEST(utils_hash, blake2b_64) {
|
||||
auto hash = utils::collection::to_hex_string(
|
||||
utils::hash::create_hash_blake2b_64("a"));
|
||||
EXPECT_STREQ("40f89e395b66422f", hash.c_str());
|
||||
|
||||
hash = utils::collection::to_hex_string(
|
||||
utils::hash::create_hash_blake2b_64(L"a"));
|
||||
#if defined(_WIN32)
|
||||
EXPECT_STREQ("4dd0bb1c45b748c1", hash.c_str());
|
||||
#else // !defined(_WIN32)
|
||||
EXPECT_STREQ("85ff8cc55b79d38a", hash.c_str());
|
||||
#endif
|
||||
|
||||
hash = utils::collection::to_hex_string(
|
||||
utils::hash::create_hash_blake2b_64({1U}));
|
||||
EXPECT_STREQ("00e83d0a3f7519ad", hash.c_str());
|
||||
}
|
||||
|
||||
TEST(utils_hash, blake2b_128) {
|
||||
auto hash = utils::collection::to_hex_string(
|
||||
utils::hash::create_hash_blake2b_128("a"));
|
||||
EXPECT_STREQ("27c35e6e9373877f29e562464e46497e", hash.c_str());
|
||||
|
||||
hash = utils::collection::to_hex_string(
|
||||
utils::hash::create_hash_blake2b_128(L"a"));
|
||||
#if defined(_WIN32)
|
||||
EXPECT_STREQ("396660e76c84bb7786f979f10b58fa79", hash.c_str());
|
||||
#else // !defined(_WIN32)
|
||||
EXPECT_STREQ("dae64afb310a3426ad84f0739fde5cef", hash.c_str());
|
||||
#endif
|
||||
|
||||
hash = utils::collection::to_hex_string(
|
||||
utils::hash::create_hash_blake2b_128({1U}));
|
||||
EXPECT_STREQ("4a9e6f9b8d43f6ad008f8c291929dee2", hash.c_str());
|
||||
}
|
||||
|
||||
TEST(utils_hash, blake2b_256) {
|
||||
auto hash = utils::collection::to_hex_string(
|
||||
utils::hash::create_hash_blake2b_256("a"));
|
||||
|
@@ -134,4 +134,10 @@ TEST(utils_string, to_bool) {
|
||||
EXPECT_FALSE(utils::string::to_bool("0"));
|
||||
EXPECT_FALSE(utils::string::to_bool("00000.00000"));
|
||||
}
|
||||
|
||||
TEST(utils_string, utf8_string_conversion) {
|
||||
std::wstring ws = L"Hello 🌍 — 𝄞 漢字";
|
||||
std::wstring ws2 = utils::string::from_utf8(utils::string::to_utf8(ws));
|
||||
EXPECT_STREQ(ws.c_str(), ws2.c_str());
|
||||
}
|
||||
} // namespace repertory
|
||||
|
@@ -150,7 +150,7 @@ TEST(utils_ttl_cache, can_handle_concurrent_access) {
|
||||
for (std::uint8_t ttl = 0U; ttl < 100U; ++ttl) {
|
||||
auto data = cache.get("/key");
|
||||
if (data) {
|
||||
(void)data->load();
|
||||
[[maybe_unused]] auto res = data->load();
|
||||
}
|
||||
std::this_thread::yield();
|
||||
}
|
||||
@@ -162,7 +162,7 @@ TEST(utils_ttl_cache, can_handle_concurrent_access) {
|
||||
|
||||
auto data = cache.get("/key");
|
||||
ASSERT_NE(data, nullptr);
|
||||
(void)data->load();
|
||||
[[maybe_unused]] auto res = data->load();
|
||||
}
|
||||
|
||||
TEST(utils_ttl_cache, can_handle_custom_atomic) {
|
||||
|
Reference in New Issue
Block a user