initial commit
This commit is contained in:
61
support/include/utils/all.hpp
Normal file
61
support/include/utils/all.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_ALL_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_ALL_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
#include "utils/atomic.hpp"
|
||||
#include "utils/base64.hpp"
|
||||
#include "utils/collection.hpp"
|
||||
#if defined(_WIN32)
|
||||
#include "utils/com_init_wrapper.hpp"
|
||||
#endif // defined(_WIN32)
|
||||
#include "utils/common.hpp"
|
||||
#if defined(PROJECT_ENABLE_SQLITE)
|
||||
#include "utils/db/sqlite/db_common.hpp"
|
||||
#include "utils/db/sqlite/db_delete.hpp"
|
||||
#include "utils/db/sqlite/db_insert.hpp"
|
||||
#include "utils/db/sqlite/db_select.hpp"
|
||||
#include "utils/db/sqlite/db_update.hpp"
|
||||
#endif // defined(PROJECT_ENABLE_SQLITE)
|
||||
#if defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
#include "utils/encrypting_reader.hpp"
|
||||
#include "utils/encryption.hpp"
|
||||
#endif // defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
#include "utils/error.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#if defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
#include "utils/hash.hpp"
|
||||
#endif // defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/time.hpp"
|
||||
#include "utils/ttl_cache.hpp"
|
||||
#if !defined(_WIN32)
|
||||
#include "utils/unix.hpp"
|
||||
#endif // !defined(_WIN32)
|
||||
#if defined(_WIN32)
|
||||
#include "utils/windows.hpp"
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_ALL_HPP_
|
||||
118
support/include/utils/atomic.hpp
Normal file
118
support/include/utils/atomic.hpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_ATOMIC_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_ATOMIC_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
namespace fifthgrid::utils {
|
||||
template <typename data_t> class atomic final {
|
||||
public:
|
||||
atomic() : mtx_(std::make_shared<std::mutex>()) {}
|
||||
|
||||
atomic(const atomic &at_data)
|
||||
: data_(at_data.load()), mtx_(std::make_shared<std::mutex>()) {}
|
||||
|
||||
atomic(data_t data)
|
||||
: data_(std::move(data)), mtx_(std::make_shared<std::mutex>()) {}
|
||||
|
||||
atomic(atomic &&) = default;
|
||||
|
||||
~atomic() = default;
|
||||
|
||||
private:
|
||||
data_t data_;
|
||||
std::shared_ptr<std::mutex> mtx_;
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto load() const -> data_t {
|
||||
mutex_lock lock(*mtx_);
|
||||
return data_;
|
||||
}
|
||||
|
||||
auto store(data_t data) -> data_t {
|
||||
mutex_lock lock(*mtx_);
|
||||
data_ = std::move(data);
|
||||
return data_;
|
||||
}
|
||||
|
||||
auto operator=(const atomic &at_data) -> atomic & {
|
||||
if (&at_data == this) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
store(at_data.load());
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto operator=(atomic &&) -> atomic & = default;
|
||||
|
||||
auto operator=(data_t data) -> atomic & {
|
||||
if (&data == &data_) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
store(std::move(data));
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto operator==(const atomic &at_data) const -> bool {
|
||||
if (&at_data == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mutex_lock lock(*mtx_);
|
||||
return at_data.load() == data_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto operator==(const data_t &data) const -> bool {
|
||||
if (&data == &data_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mutex_lock lock(*mtx_);
|
||||
return data == data_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto operator!=(const atomic &at_data) const -> bool {
|
||||
if (&at_data == this) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mutex_lock lock(*mtx_);
|
||||
return at_data.load() != data_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto operator!=(const data_t &data) const -> bool {
|
||||
if (&data == &data_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mutex_lock lock(*mtx_);
|
||||
return data != data_;
|
||||
}
|
||||
|
||||
[[nodiscard]] operator data_t() const { return load(); }
|
||||
};
|
||||
} // namespace fifthgrid::utils
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_ATOMIC_HPP_
|
||||
325
support/include/utils/base64.hpp
Normal file
325
support/include/utils/base64.hpp
Normal file
@@ -0,0 +1,325 @@
|
||||
// NOLINTBEGIN
|
||||
#ifndef MACARON_BASE64_H_
|
||||
#define MACARON_BASE64_H_
|
||||
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2016 tomykaira
|
||||
* Copyright (c) 2025 scott.e.graves@protonmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunknown-warning-option"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Wuseless-cast"
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace macaron::Base64 {
|
||||
|
||||
// --- Alphabets --------------------------------------------------------------
|
||||
|
||||
static constexpr std::array<unsigned char, 64U> kStdAlphabet{
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
|
||||
};
|
||||
|
||||
static constexpr std::array<unsigned char, 64U> kUrlAlphabet{
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_',
|
||||
};
|
||||
|
||||
// Decoding table that accepts BOTH standard and URL-safe alphabets.
|
||||
static constexpr std::array<unsigned char, 256U> kDecodingTable = [] {
|
||||
std::array<unsigned char, 256U> t{};
|
||||
t.fill(64U);
|
||||
// 'A'-'Z'
|
||||
for (unsigned char c = 'A'; c <= 'Z'; ++c)
|
||||
t[c] = static_cast<unsigned char>(c - 'A');
|
||||
// 'a'-'z'
|
||||
for (unsigned char c = 'a'; c <= 'z'; ++c)
|
||||
t[c] = static_cast<unsigned char>(26 + c - 'a');
|
||||
// '0'-'9'
|
||||
for (unsigned char c = '0'; c <= '9'; ++c)
|
||||
t[c] = static_cast<unsigned char>(52 + c - '0');
|
||||
// Standard extras
|
||||
t[static_cast<unsigned char>('+')] = 62U;
|
||||
t[static_cast<unsigned char>('/')] = 63U;
|
||||
// URL-safe extras
|
||||
t[static_cast<unsigned char>('-')] = 62U;
|
||||
t[static_cast<unsigned char>('_')] = 63U;
|
||||
return t;
|
||||
}();
|
||||
|
||||
// --- Encoding ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Encode to Base64.
|
||||
* @param data pointer to bytes
|
||||
* @param len number of bytes
|
||||
* @param url_safe if true, use URL-safe alphabet ("-","_") instead of ("+","/")
|
||||
* @param pad if true, add '=' padding; if false, omit padding (RFC 4648
|
||||
* §5)
|
||||
*/
|
||||
static std::string Encode(const unsigned char *data, std::size_t len,
|
||||
bool url_safe = false, bool pad = true) {
|
||||
const auto &alpha = url_safe ? kUrlAlphabet : kStdAlphabet;
|
||||
|
||||
std::string out;
|
||||
if (len == 0U) {
|
||||
return out;
|
||||
}
|
||||
|
||||
const std::size_t full_blocks = len / 3U;
|
||||
const std::size_t rem = len % 3U;
|
||||
|
||||
std::size_t out_len{};
|
||||
if (pad) {
|
||||
out_len = 4U * ((len + 2U) / 3U);
|
||||
} else {
|
||||
// Unpadded length per RFC 4648 §5
|
||||
out_len = 4U * full_blocks + (rem == 0U ? 0U : (rem == 1U ? 2U : 3U));
|
||||
}
|
||||
out.assign(out_len, '\0');
|
||||
|
||||
auto *p = reinterpret_cast<unsigned char *>(out.data());
|
||||
std::size_t i = 0;
|
||||
|
||||
// Full 3-byte blocks -> 4 chars
|
||||
for (; i + 2U < len; i += 3U) {
|
||||
const unsigned char b0 = data[i + 0U];
|
||||
const unsigned char b1 = data[i + 1U];
|
||||
const unsigned char b2 = data[i + 2U];
|
||||
|
||||
*p++ = alpha[(b0 >> 2U) & 0x3F];
|
||||
*p++ = alpha[((b0 & 0x03U) << 4U) | ((b1 >> 4U) & 0x0FU)];
|
||||
*p++ = alpha[((b1 & 0x0FU) << 2U) | ((b2 >> 6U) & 0x03U)];
|
||||
*p++ = alpha[b2 & 0x3FU];
|
||||
}
|
||||
|
||||
// Remainder
|
||||
if (rem == 1U) {
|
||||
const unsigned char b0 = data[i];
|
||||
*p++ = alpha[(b0 >> 2U) & 0x3F];
|
||||
*p++ = alpha[(b0 & 0x03U) << 4U];
|
||||
if (pad) {
|
||||
*p++ = '=';
|
||||
*p++ = '=';
|
||||
}
|
||||
} else if (rem == 2U) {
|
||||
const unsigned char b0 = data[i + 0U];
|
||||
const unsigned char b1 = data[i + 1U];
|
||||
*p++ = alpha[(b0 >> 2U) & 0x3F];
|
||||
*p++ = alpha[((b0 & 0x03U) << 4U) | ((b1 >> 4U) & 0x0FU)];
|
||||
*p++ = alpha[(b1 & 0x0FU) << 2U];
|
||||
if (pad) {
|
||||
*p++ = '=';
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static std::string
|
||||
Encode(std::string_view data, bool url_safe = false, bool pad = true) {
|
||||
return Encode(reinterpret_cast<const unsigned char *>(data.data()),
|
||||
data.size(), url_safe, pad);
|
||||
}
|
||||
|
||||
[[maybe_unused]] static std::string
|
||||
EncodeUrlSafe(const unsigned char *data, std::size_t len, bool pad = false) {
|
||||
return Encode(data, len, /*url_safe=*/true, /*pad=*/pad);
|
||||
}
|
||||
|
||||
[[maybe_unused]] static std::string EncodeUrlSafe(std::string_view data,
|
||||
bool pad = false) {
|
||||
return Encode(reinterpret_cast<const unsigned char *>(data.data()),
|
||||
data.size(), /*url_safe=*/true, /*pad=*/pad);
|
||||
}
|
||||
|
||||
// --- Decoding ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Decode standard OR URL-safe Base64.
|
||||
* Accepts inputs with or without '=' padding.
|
||||
* Throws std::runtime_error on malformed input.
|
||||
*/
|
||||
[[maybe_unused]] static std::vector<unsigned char>
|
||||
Decode(std::string_view input) {
|
||||
std::vector<unsigned char> out;
|
||||
if (input.empty()) {
|
||||
return out;
|
||||
}
|
||||
|
||||
std::size_t inLen = input.size();
|
||||
std::size_t rem = inLen % 4U;
|
||||
|
||||
// padded if multiple of 4 and last char is '='
|
||||
bool hasPadding = (rem == 0U) && (inLen >= 4U) && (input[inLen - 1U] == '=');
|
||||
|
||||
// compute output length
|
||||
std::size_t outLen{};
|
||||
if (hasPadding) {
|
||||
outLen = (inLen / 4U) * 3U;
|
||||
if (input[inLen - 1U] == '=')
|
||||
outLen--;
|
||||
if (input[inLen - 2U] == '=')
|
||||
outLen--;
|
||||
} else {
|
||||
if (rem == 1U) {
|
||||
throw std::runtime_error("Invalid Base64 length (mod 4 == 1)");
|
||||
}
|
||||
outLen = (inLen / 4U) * 3U + (rem == 0U ? 0U : (rem == 2U ? 1U : 2U));
|
||||
}
|
||||
|
||||
out.resize(outLen);
|
||||
|
||||
auto readVal = [](unsigned char c) -> unsigned char {
|
||||
unsigned char v = kDecodingTable[c];
|
||||
if (v == 64U) {
|
||||
throw std::runtime_error("Invalid Base64 character");
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
std::size_t i = 0U;
|
||||
std::size_t j = 0U;
|
||||
|
||||
// process all full unpadded quartets
|
||||
std::size_t lastFull =
|
||||
hasPadding ? (inLen - 4U) : (rem == 0U ? inLen : (inLen - rem));
|
||||
|
||||
while (i + 4U <= lastFull) {
|
||||
unsigned char a = readVal(static_cast<unsigned char>(input[i + 0U]));
|
||||
unsigned char b = readVal(static_cast<unsigned char>(input[i + 1U]));
|
||||
unsigned char c = readVal(static_cast<unsigned char>(input[i + 2U]));
|
||||
unsigned char d = readVal(static_cast<unsigned char>(input[i + 3U]));
|
||||
i += 4U;
|
||||
|
||||
std::uint32_t triple = (static_cast<std::uint32_t>(a) << 18U) |
|
||||
(static_cast<std::uint32_t>(b) << 12U) |
|
||||
(static_cast<std::uint32_t>(c) << 6U) |
|
||||
(static_cast<std::uint32_t>(d));
|
||||
|
||||
if (j < outLen)
|
||||
out[j++] = static_cast<unsigned char>((triple >> 16U) & 0xFFU);
|
||||
if (j < outLen)
|
||||
out[j++] = static_cast<unsigned char>((triple >> 8U) & 0xFFU);
|
||||
if (j < outLen)
|
||||
out[j++] = static_cast<unsigned char>(triple & 0xFFU);
|
||||
}
|
||||
|
||||
// tail: padded quartet or unpadded remainder
|
||||
if (i < inLen) {
|
||||
std::size_t left = inLen - i;
|
||||
|
||||
if (left == 4U) {
|
||||
bool thirdIsPad = (input[i + 2U] == '=');
|
||||
bool fourthIsPad = (input[i + 3U] == '=');
|
||||
|
||||
// '=' is never allowed in positions 1 or 2 of any quartet
|
||||
if (input[i + 0U] == '=' || input[i + 1U] == '=') {
|
||||
throw std::runtime_error("Invalid Base64 padding placement");
|
||||
}
|
||||
|
||||
unsigned char a = readVal(static_cast<unsigned char>(input[i + 0U]));
|
||||
unsigned char b = readVal(static_cast<unsigned char>(input[i + 1U]));
|
||||
unsigned char c = 0U;
|
||||
unsigned char d = 0U;
|
||||
|
||||
if (!thirdIsPad) {
|
||||
c = readVal(static_cast<unsigned char>(input[i + 2U]));
|
||||
if (!fourthIsPad) {
|
||||
d = readVal(static_cast<unsigned char>(input[i + 3U]));
|
||||
}
|
||||
} else {
|
||||
// if the 3rd is '=', the 4th must also be '='
|
||||
if (!fourthIsPad) {
|
||||
throw std::runtime_error("Invalid Base64 padding placement");
|
||||
}
|
||||
}
|
||||
i += 4U;
|
||||
|
||||
std::uint32_t triple = (static_cast<std::uint32_t>(a) << 18U) |
|
||||
(static_cast<std::uint32_t>(b) << 12U) |
|
||||
(static_cast<std::uint32_t>(c) << 6U) |
|
||||
(static_cast<std::uint32_t>(d));
|
||||
|
||||
if (j < outLen)
|
||||
out[j++] = static_cast<unsigned char>((triple >> 16U) & 0xFFU);
|
||||
if (!thirdIsPad && j < outLen)
|
||||
out[j++] = static_cast<unsigned char>((triple >> 8U) & 0xFFU);
|
||||
if (!fourthIsPad && !thirdIsPad && j < outLen)
|
||||
out[j++] = static_cast<unsigned char>(triple & 0xFFU);
|
||||
|
||||
} else if (left == 2U || left == 3U) {
|
||||
unsigned char a = readVal(static_cast<unsigned char>(input[i + 0U]));
|
||||
unsigned char b = readVal(static_cast<unsigned char>(input[i + 1U]));
|
||||
unsigned char c = (left == 3U)
|
||||
? readVal(static_cast<unsigned char>(input[i + 2U]))
|
||||
: 0U;
|
||||
i += left;
|
||||
|
||||
std::uint32_t triple = (static_cast<std::uint32_t>(a) << 18U) |
|
||||
(static_cast<std::uint32_t>(b) << 12U) |
|
||||
(static_cast<std::uint32_t>(c) << 6U);
|
||||
|
||||
if (j < outLen)
|
||||
out[j++] = static_cast<unsigned char>((triple >> 16U) & 0xFFU);
|
||||
if (left == 3U && j < outLen)
|
||||
out[j++] = static_cast<unsigned char>((triple >> 8U) & 0xFFU);
|
||||
} else {
|
||||
throw std::runtime_error("Invalid Base64 length (mod 4 == 1)");
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
} // namespace macaron::Base64
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif /* MACARON_BASE64_H_ */
|
||||
// NOLINTEND
|
||||
178
support/include/utils/collection.hpp
Normal file
178
support/include/utils/collection.hpp
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_COLLECTION_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_COLLECTION_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
#include "utils/error.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
namespace fifthgrid::utils::collection {
|
||||
template <typename col_t>
|
||||
[[nodiscard]] inline auto excludes(const col_t &collection,
|
||||
const typename col_t::value_type &val)
|
||||
-> bool;
|
||||
|
||||
template <typename col_t>
|
||||
[[nodiscard]] inline auto includes(const col_t &collection,
|
||||
const typename col_t::value_type &val)
|
||||
-> bool;
|
||||
|
||||
template <typename val_t>
|
||||
[[nodiscard]] inline auto from_hex_string(std::string_view str, val_t &val)
|
||||
-> bool;
|
||||
|
||||
template <typename val_t>
|
||||
[[nodiscard]] inline auto from_hex_string(std::wstring_view str, val_t &val)
|
||||
-> bool;
|
||||
template <typename col_t>
|
||||
inline auto remove_element(col_t &collection,
|
||||
const typename col_t::value_type &value) -> col_t &;
|
||||
|
||||
template <typename col_t>
|
||||
[[nodiscard]] inline auto to_hex_string(const col_t &collection) -> std::string;
|
||||
|
||||
template <typename col_t>
|
||||
[[nodiscard]] inline auto to_hex_wstring(const col_t &collection)
|
||||
-> std::wstring;
|
||||
|
||||
template <typename col_t>
|
||||
inline auto excludes(const col_t &collection,
|
||||
const typename col_t::value_type &val) -> bool {
|
||||
return std::find(collection.begin(), collection.end(), val) ==
|
||||
collection.end();
|
||||
}
|
||||
|
||||
template <typename col_t>
|
||||
inline auto includes(const col_t &collection,
|
||||
const typename col_t::value_type &val) -> bool {
|
||||
return std::find(collection.begin(), collection.end(), val) !=
|
||||
collection.end();
|
||||
}
|
||||
|
||||
template <typename val_t>
|
||||
[[nodiscard]] inline auto from_hex_string_t(std::string_view str, val_t &val)
|
||||
-> bool {
|
||||
FIFTHGRID_USES_FUNCTION_NAME();
|
||||
|
||||
static constexpr auto base16{16};
|
||||
|
||||
try {
|
||||
val.clear();
|
||||
|
||||
std::string fmt_val{str};
|
||||
utils::string::trim(fmt_val);
|
||||
if (fmt_val.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
fmt_val = utils::string::to_lower(fmt_val);
|
||||
if (utils::string::begins_with(fmt_val, "0x")) {
|
||||
fmt_val = fmt_val.substr(2U);
|
||||
}
|
||||
|
||||
if (fmt_val.empty()) {
|
||||
throw utils::error::create_exception(function_name,
|
||||
{
|
||||
"hex string is invalid",
|
||||
str,
|
||||
});
|
||||
}
|
||||
|
||||
if (fmt_val.length() % 2U) {
|
||||
fmt_val = '0' + fmt_val;
|
||||
}
|
||||
|
||||
auto iter = std::find_if_not(
|
||||
fmt_val.begin(), fmt_val.end(), [](auto cur_char) -> bool {
|
||||
auto check = static_cast<std::uint32_t>(cur_char);
|
||||
return ((check >= 48U && check <= 57U) ||
|
||||
(check >= 97U && check <= 102U));
|
||||
});
|
||||
if (iter != fmt_val.end()) {
|
||||
auto invalid_idx{std::distance(fmt_val.begin(), iter)};
|
||||
throw std::range_error(utils::error::create_error_message({
|
||||
function_name,
|
||||
"invalid character in hex string",
|
||||
std::to_string(invalid_idx),
|
||||
std::string(1U, str.at(invalid_idx)),
|
||||
str,
|
||||
}));
|
||||
}
|
||||
|
||||
val.resize(fmt_val.length() / 2U);
|
||||
for (std::size_t idx = 0U; idx < fmt_val.length(); idx += 2U) {
|
||||
val.at(idx / 2U) = static_cast<typename val_t::value_type>(
|
||||
std::strtoul(fmt_val.substr(idx, 2U).c_str(), nullptr, base16));
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::handle_exception(function_name, e);
|
||||
} catch (...) {
|
||||
utils::error::handle_exception(function_name);
|
||||
}
|
||||
|
||||
val.clear();
|
||||
return false;
|
||||
}
|
||||
template <typename val_t>
|
||||
inline auto from_hex_string(std::string_view str, val_t &val) -> bool {
|
||||
return from_hex_string_t<val_t>(str, val);
|
||||
}
|
||||
|
||||
template <typename val_t>
|
||||
inline auto from_hex_string(std::wstring_view str, val_t &val) -> bool {
|
||||
return from_hex_string_t<val_t>(utils::string::to_utf8(str), val);
|
||||
}
|
||||
|
||||
template <typename col_t>
|
||||
inline auto remove_element(col_t &collection,
|
||||
const typename col_t::value_type &value) -> col_t & {
|
||||
collection.erase(std::remove(collection.begin(), collection.end(), value),
|
||||
collection.end());
|
||||
return collection;
|
||||
}
|
||||
|
||||
template <typename col_t>
|
||||
inline auto to_hex_string(const col_t &collection) -> std::string {
|
||||
static_assert(sizeof(typename col_t::value_type) == 1U,
|
||||
"value_type must be 1 byte in size");
|
||||
static constexpr auto mask{0xFF};
|
||||
|
||||
std::stringstream stream{};
|
||||
for (auto &&val : collection) {
|
||||
stream << std::setfill('0') << std::setw(2) << std::hex
|
||||
<< (static_cast<std::uint32_t>(val) & mask);
|
||||
}
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
template <typename col_t>
|
||||
inline auto to_hex_wstring(const col_t &collection) -> std::wstring {
|
||||
return utils::string::from_utf8(to_hex_string<col_t>(collection));
|
||||
}
|
||||
} // namespace fifthgrid::utils::collection
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_COLLECTION_HPP_
|
||||
54
support/include/utils/com_init_wrapper.hpp
Normal file
54
support/include/utils/com_init_wrapper.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_COM_INIT_WRAPPER_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_COM_INIT_WRAPPER_HPP_
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
namespace fifthgrid::utils {
|
||||
struct com_init_wrapper final {
|
||||
com_init_wrapper()
|
||||
: initialized_(
|
||||
SUCCEEDED(::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED))) {}
|
||||
|
||||
com_init_wrapper(const com_init_wrapper &) = delete;
|
||||
com_init_wrapper(com_init_wrapper &&) = delete;
|
||||
|
||||
~com_init_wrapper() {
|
||||
if (initialized_) {
|
||||
::CoUninitialize();
|
||||
}
|
||||
}
|
||||
|
||||
auto operator=(const com_init_wrapper &) -> com_init_wrapper & = delete;
|
||||
auto operator=(com_init_wrapper &&) -> com_init_wrapper & = delete;
|
||||
|
||||
[[nodiscard]] auto is_initialized() const -> bool { return initialized_; }
|
||||
|
||||
private:
|
||||
BOOL initialized_{};
|
||||
};
|
||||
} // namespace fifthgrid::utils
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_COM_INIT_WRAPPER_HPP_
|
||||
146
support/include/utils/common.hpp
Normal file
146
support/include/utils/common.hpp
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_COMMON_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_COMMON_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
namespace fifthgrid::utils {
|
||||
struct result final {
|
||||
std::string function_name;
|
||||
bool ok{true};
|
||||
std::string reason{"success"};
|
||||
|
||||
[[nodiscard]] operator bool() const { return ok; }
|
||||
};
|
||||
|
||||
using retryable_action_t = std::function<bool()>;
|
||||
|
||||
[[nodiscard]] constexpr auto calculate_read_size(std::uint64_t total_size,
|
||||
std::size_t read_size,
|
||||
std::uint64_t offset)
|
||||
-> std::size_t {
|
||||
return static_cast<std::size_t>(
|
||||
((offset + read_size) > total_size)
|
||||
? ((offset < total_size) ? total_size - offset : 0U)
|
||||
: read_size);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto compare_version_strings(std::string version1,
|
||||
std::string version2)
|
||||
-> std::int32_t;
|
||||
|
||||
[[nodiscard]] auto compare_version_strings(std::wstring_view version1,
|
||||
std::wstring_view version2)
|
||||
-> std::int32_t;
|
||||
|
||||
#if defined(PROJECT_ENABLE_STDUUID)
|
||||
[[nodiscard]] auto create_uuid_string() -> std::string;
|
||||
|
||||
[[nodiscard]] auto create_uuid_wstring() -> std::wstring;
|
||||
#endif // defined(PROJECT_ENABLE_STDUUID)
|
||||
|
||||
template <typename result_t, typename data_t>
|
||||
[[nodiscard]] inline constexpr auto divide_with_ceiling(result_t numerator,
|
||||
data_t denominator)
|
||||
-> result_t;
|
||||
|
||||
template <typename data_t>
|
||||
[[nodiscard]] inline auto generate_random_between(data_t begin, data_t end)
|
||||
-> data_t;
|
||||
|
||||
[[nodiscard]] auto generate_random_string(std::size_t length) -> std::string;
|
||||
|
||||
[[nodiscard]] auto generate_random_wstring(std::size_t length) -> std::wstring;
|
||||
|
||||
#if defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
template <typename data_t>
|
||||
[[nodiscard]] inline auto generate_secure_random() -> data_t;
|
||||
|
||||
template <typename data_t>
|
||||
[[nodiscard]] inline auto generate_secure_random(std::size_t size) -> data_t;
|
||||
#endif // defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
|
||||
[[nodiscard]] auto get_environment_variable(std::string_view variable)
|
||||
-> std::string;
|
||||
|
||||
[[nodiscard]] auto get_environment_variable(std::wstring_view variable)
|
||||
-> std::wstring;
|
||||
|
||||
#if defined(PROJECT_ENABLE_BOOST)
|
||||
[[nodiscard]] auto get_next_available_port(std::uint16_t first_port,
|
||||
std::uint16_t &available_port)
|
||||
-> bool;
|
||||
#endif // defined(PROJECT_ENABLE_BOOST)
|
||||
|
||||
[[nodiscard]] auto retry_action(
|
||||
retryable_action_t action, std::size_t retry_count = 200U,
|
||||
std::chrono::milliseconds retry_wait = std::chrono::milliseconds(10))
|
||||
-> bool;
|
||||
|
||||
template <typename result_t, typename data_t>
|
||||
inline constexpr auto divide_with_ceiling(result_t numerator,
|
||||
data_t denominator) -> result_t {
|
||||
static_assert(std::is_integral_v<std::remove_cv_t<data_t>>,
|
||||
"denominator must be an integral type");
|
||||
|
||||
return denominator == 0
|
||||
? 0
|
||||
: (numerator / denominator) + (numerator % denominator != 0);
|
||||
}
|
||||
|
||||
template <typename data_t>
|
||||
inline auto generate_random_between(data_t begin, data_t end) -> data_t {
|
||||
static_assert(std::is_integral_v<std::remove_cv_t<data_t>>,
|
||||
"data_t must be an integral type");
|
||||
if (end <= begin) {
|
||||
throw std::range_error("end must be greater than begin");
|
||||
}
|
||||
|
||||
thread_local std::mt19937 gen(
|
||||
static_cast<unsigned long>(std::time(nullptr) ^ std::random_device{}()));
|
||||
std::uniform_int_distribution<data_t> dis(begin, end);
|
||||
return dis(gen);
|
||||
}
|
||||
|
||||
#if defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
template <typename data_t> inline auto generate_secure_random() -> data_t {
|
||||
static_assert(!is_collection<std::decay_t<data_t>>::value,
|
||||
"data_t is a vector or collection");
|
||||
data_t ret{};
|
||||
randombytes_buf(&ret, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename data_t>
|
||||
inline auto generate_secure_random(std::size_t size) -> data_t {
|
||||
static_assert(is_collection<std::decay_t<data_t>>::value,
|
||||
"data_t is not a vector or collection");
|
||||
data_t ret;
|
||||
ret.resize(size);
|
||||
randombytes_buf(ret.data(), ret.size() * sizeof(typename data_t::value_type));
|
||||
return ret;
|
||||
}
|
||||
#endif // defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
} // namespace fifthgrid::utils
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_COMMON_HPP_
|
||||
496
support/include/utils/config.hpp
Normal file
496
support/include/utils/config.hpp
Normal file
@@ -0,0 +1,496 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_CONFIG_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_CONFIG_HPP_
|
||||
|
||||
#define NOMINMAX
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define WINVER 0x0A00
|
||||
#define _WIN32_WINNT WINVER
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#include <windows.h>
|
||||
#if defined(PROJECT_ENABLE_WINFSP)
|
||||
#include <sddl.h>
|
||||
#endif // defined(PROJECT_ENABLE_WINFSP)
|
||||
|
||||
#include <direct.h>
|
||||
#if !defined(__cplusplus)
|
||||
#include <errno.h>
|
||||
#endif // !defined(__cplusplus)
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <objbase.h>
|
||||
#include <psapi.h>
|
||||
#include <rpc.h>
|
||||
#include <share.h>
|
||||
#include <shellapi.h>
|
||||
#include <shlobj.h>
|
||||
#include <shlwapi.h>
|
||||
#if !defined(__cplusplus)
|
||||
#include <stdio.h>
|
||||
#endif // !defined(__cplusplus)
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#if !defined(__cplusplus)
|
||||
#include <time.h>
|
||||
#endif // !defined(__cplusplus)
|
||||
#else // !defined(_WIN32)
|
||||
#include <arpa/inet.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <libgen.h>
|
||||
#include <netinet/in.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#if defined(__LFS64__)
|
||||
#include <sys/stat64.h>
|
||||
#else // !defined(__LFS64__)
|
||||
#include <sys/stat.h>
|
||||
#endif // defined(__LFS64__)
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <sys/statfs.h>
|
||||
#endif // defined(HAS_SETXATTR)
|
||||
|
||||
#if defined(HAS_SETXATTR)
|
||||
#include <sys/types.h>
|
||||
#include <sys/xattr.h>
|
||||
#endif // defined(HAS_SETXATTR)
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <libproc.h>
|
||||
#include <sys/attr.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/vnode.h>
|
||||
#endif // defined(__APPLE__)
|
||||
|
||||
#include <unistd.h>
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
#if defined(HAS_WORDEXP_H)
|
||||
#include <wordexp.h>
|
||||
#endif // defined(HAS_WORDEXP_H)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <bit>
|
||||
#include <cerrno>
|
||||
#include <chrono>
|
||||
#include <climits>
|
||||
#include <condition_variable>
|
||||
#include <csignal>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <deque>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <locale>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <numeric>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <queue>
|
||||
#include <random>
|
||||
#include <ranges>
|
||||
#include <regex>
|
||||
#include <span>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#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"
|
||||
#endif // defined(PROJECT_ENABLE_CURL)
|
||||
|
||||
#if defined(PROJECT_ENABLE_FUSE)
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
#include <fuse.h>
|
||||
#include <fuse_lowlevel.h>
|
||||
#else
|
||||
#include <fuse/fuse.h>
|
||||
#endif
|
||||
#endif // defined(PROJECT_ENABLE_FUSE)
|
||||
|
||||
#if defined(PROJECT_ENABLE_FZF)
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif // defined(__cplusplus)
|
||||
#include "fzf.h"
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif // defined(__cplusplus)
|
||||
#endif // defined(PROJECT_ENABLE_FZF)
|
||||
|
||||
#if defined(PROJECT_ENABLE_OPENSSL)
|
||||
#include "openssl/ssl.h"
|
||||
#endif // defined(PROJECT_ENABLE_OPENSSL)
|
||||
|
||||
#if defined(PROJECT_ENABLE_LIBDSM)
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif // defined(__cplusplus)
|
||||
#include "bdsm/bdsm.h"
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
||||
struct netbios_ns_deleter final {
|
||||
void operator()(netbios_ns *ns) const {
|
||||
if (ns != nullptr) {
|
||||
netbios_ns_destroy(ns);
|
||||
}
|
||||
}
|
||||
};
|
||||
using netbios_ns_t = std::unique_ptr<netbios_ns, netbios_ns_deleter>;
|
||||
|
||||
inline const auto smb_session_deleter = [](smb_session *session) {
|
||||
if (session != nullptr) {
|
||||
smb_session_destroy(session);
|
||||
}
|
||||
};
|
||||
using smb_session_t = std::shared_ptr<smb_session>;
|
||||
|
||||
struct smb_stat_deleter final {
|
||||
void operator()(smb_stat st) const {
|
||||
if (st != nullptr) {
|
||||
smb_stat_destroy(st);
|
||||
}
|
||||
}
|
||||
};
|
||||
using smb_stat_t = std::unique_ptr<smb_file, smb_stat_deleter>;
|
||||
|
||||
struct smb_stat_list_deleter final {
|
||||
void operator()(smb_file *list) const {
|
||||
if (list != nullptr) {
|
||||
smb_stat_list_destroy(list);
|
||||
}
|
||||
}
|
||||
};
|
||||
using smb_stat_list_t = std::unique_ptr<smb_file, smb_stat_list_deleter>;
|
||||
#endif // defined(__cplusplus)
|
||||
#endif // defined(PROJECT_ENABLE_LIBDSM)
|
||||
|
||||
#if defined(PROJECT_ENABLE_LIBEVENT)
|
||||
#include "event2/buffer.h"
|
||||
#include "event2/bufferevent.h"
|
||||
#include "event2/listener.h"
|
||||
#include "event2/thread.h"
|
||||
#include "event2/util.h"
|
||||
#endif // defined(PROJECT_ENABLE_LIBEVENT)
|
||||
|
||||
#if defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
#include "sodium.h"
|
||||
#endif // defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
|
||||
#if defined(PROJECT_ENABLE_SDL)
|
||||
#include "SDL.h"
|
||||
#include "SDL_gamecontroller.h"
|
||||
#include "SDL_joystick.h"
|
||||
#endif // defined(PROJECT_ENABLE_SDL)
|
||||
|
||||
#if defined(PROJECT_ENABLE_SQLITE)
|
||||
#include "sqlite3.h"
|
||||
#endif // defined(PROJECT_ENABLE_SQLITE)
|
||||
|
||||
#if defined(PROJECT_ENABLE_VLC)
|
||||
#include <vlc/vlc.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
[[nodiscard]] inline auto get_libvlc_error_msg() -> std::string {
|
||||
const auto *msg = libvlc_errmsg();
|
||||
return msg == nullptr ? "none" : msg;
|
||||
}
|
||||
|
||||
struct vlc_deleter final {
|
||||
void operator()(libvlc_instance_t *inst) const {
|
||||
if (inst != nullptr) {
|
||||
libvlc_release(inst);
|
||||
}
|
||||
}
|
||||
};
|
||||
using vlc_t = std::unique_ptr<libvlc_instance_t, vlc_deleter>;
|
||||
|
||||
struct vlc_media_deleter final {
|
||||
void operator()(libvlc_media_t *media) const {
|
||||
if (media != nullptr) {
|
||||
libvlc_media_release(media);
|
||||
}
|
||||
}
|
||||
};
|
||||
using vlc_media_t = std::unique_ptr<libvlc_media_t, vlc_media_deleter>;
|
||||
|
||||
struct vlc_media_list_deleter final {
|
||||
void operator()(libvlc_media_list_t *media_list) const {
|
||||
if (media_list != nullptr) {
|
||||
libvlc_media_list_release(media_list);
|
||||
}
|
||||
}
|
||||
};
|
||||
using vlc_media_list_t =
|
||||
std::unique_ptr<libvlc_media_list_t, vlc_media_list_deleter>;
|
||||
|
||||
struct vlc_string_deleter final {
|
||||
void operator()(char *str) const {
|
||||
if (str != nullptr) {
|
||||
libvlc_free(str);
|
||||
}
|
||||
}
|
||||
};
|
||||
using vlc_string_t = std::unique_ptr<char, vlc_string_deleter>;
|
||||
#endif // defined(__cplusplus)
|
||||
#endif // defined(PROJECT_ENABLE_VLC)
|
||||
|
||||
#if !defined(fstat64)
|
||||
#define fstat64 fstat
|
||||
#endif // !defined(fstat64)
|
||||
|
||||
#if !defined(pread64)
|
||||
#define pread64 pread
|
||||
#endif // !defined(pread64)
|
||||
|
||||
#if !defined(pwrite64)
|
||||
#define pwrite64 pwrite
|
||||
#endif // !defined(pwrite64)
|
||||
|
||||
#if !defined(stat64)
|
||||
#define stat64 stat
|
||||
#endif // !defined(stat64)
|
||||
|
||||
#if !defined(statfs64)
|
||||
#define statfs64 statfs
|
||||
#endif // !defined(statfs64)
|
||||
|
||||
#if !defined(off64_t)
|
||||
#define off64_t std::size_t
|
||||
#endif // !defined(off64_t)
|
||||
|
||||
#if !defined(__off64_t)
|
||||
#define __off64_t off64_t
|
||||
#endif // !defined(__off64_t)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#if defined(PROJECT_ENABLE_BOOST)
|
||||
#include "boost/archive/text_iarchive.hpp"
|
||||
#include "boost/archive/text_oarchive.hpp"
|
||||
#include "boost/asio.hpp"
|
||||
#include "boost/asio/io_context.hpp"
|
||||
#include "boost/bind/bind.hpp"
|
||||
#include "boost/dynamic_bitset.hpp"
|
||||
#include "boost/dynamic_bitset/serialization.hpp"
|
||||
#include "boost/endian/conversion.hpp"
|
||||
#include "boost/integer.hpp"
|
||||
#include "boost/interprocess/sync/named_mutex.hpp"
|
||||
#include "boost/interprocess/sync/scoped_lock.hpp"
|
||||
#include "boost/multiprecision/cpp_dec_float.hpp"
|
||||
#include "boost/multiprecision/cpp_int.hpp"
|
||||
#include "boost/serialization/vector.hpp"
|
||||
#endif // defined(PROJECT_ENABLE_BOOST)
|
||||
|
||||
#if defined(PROJECT_ENABLE_CLI11)
|
||||
#if defined(PROJECT_IS_MINGW) && !defined(PROJECT_IS_MINGW_UNIX)
|
||||
#include "CLI/CLI.hpp"
|
||||
#else // !defined(PROJECT_IS_MINGW) || defined(PROJECT_IS_MINGW_UNIX)
|
||||
#include "CLI11.hpp"
|
||||
#endif // defined(PROJECT_IS_MINGW) && !defined(PROJECT_IS_MINGW_UNIX)
|
||||
#endif // defined(PROJECT_ENABLE_CLI11)
|
||||
|
||||
#if defined(PROJECT_ENABLE_CPP_HTTPLIB)
|
||||
#include "httplib.h"
|
||||
#endif // defined(PROJECT_ENABLE_JSON)
|
||||
|
||||
#if defined(PROJECT_ENABLE_DTL)
|
||||
#include "dtl/dtl.hpp"
|
||||
#endif // defined(PROJECT_ENABLE_DTL)
|
||||
|
||||
#if defined(PROJECT_ENABLE_JSON)
|
||||
#include "json.hpp"
|
||||
#endif // defined(PROJECT_ENABLE_JSON)
|
||||
|
||||
#if defined(PROJECT_ENABLE_NANA)
|
||||
#include "nana/gui.hpp"
|
||||
#include "nana/gui/timer.hpp"
|
||||
#include "nana/gui/widgets/button.hpp"
|
||||
#include "nana/gui/widgets/combox.hpp"
|
||||
#include "nana/gui/widgets/group.hpp"
|
||||
#include "nana/gui/widgets/label.hpp"
|
||||
#include "nana/gui/widgets/panel.hpp"
|
||||
#include "nana/gui/widgets/picture.hpp"
|
||||
#include "nana/gui/widgets/tabbar.hpp"
|
||||
#endif // defined(PROJECT_ENABLE_NANA)
|
||||
|
||||
#if defined(PROJECT_ENABLE_PUGIXML)
|
||||
#include "pugixml.hpp"
|
||||
#endif // defined(PROJECT_ENABLE_PUGIXML)
|
||||
|
||||
#if defined(PROJECT_ENABLE_ROCKSDB)
|
||||
#include "rocksdb/db.h"
|
||||
#include "rocksdb/utilities/transaction_db.h"
|
||||
#endif // defined(PROJECT_ENABLE_ROCKSDB)
|
||||
|
||||
#if defined(PROJECT_ENABLE_SFML)
|
||||
#include "RoundedRectangleShape.hpp"
|
||||
#include "SFML/Graphics.hpp"
|
||||
#include "Text2.hpp"
|
||||
#endif // defined(PROJECT_ENABLE_SFML)
|
||||
|
||||
#if defined(PROJECT_ENABLE_SAGO_PLATFORM_FOLDERS)
|
||||
#include "platform_folders.hpp"
|
||||
#endif // defined(PROJECT_ENABLE_SAGO_PLATFORM_FOLDERS)
|
||||
|
||||
#if defined(PROJECT_ENABLE_SPDLOG)
|
||||
#include "spdlog/async.h"
|
||||
#include "spdlog/fmt/bundled/core.h"
|
||||
#include "spdlog/fmt/bundled/format.h"
|
||||
#include "spdlog/fmt/bundled/ranges.h"
|
||||
#include "spdlog/fmt/chrono.h"
|
||||
#include "spdlog/sinks/rotating_file_sink.h"
|
||||
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
#endif // defined(PROJECT_ENABLE_SPDLOG)
|
||||
|
||||
#if defined(PROJECT_ENABLE_FMT)
|
||||
#include "fmt/chrono.h"
|
||||
#include "fmt/core.h"
|
||||
#include "fmt/format.h"
|
||||
#include "fmt/ranges.h"
|
||||
#endif // defined(PROJECT_ENABLE_FMT)
|
||||
|
||||
#if defined(PROJECT_ENABLE_STDUUID)
|
||||
#include "uuid.h"
|
||||
#endif // defined(PROJECT_ENABLE_STDUUID)
|
||||
|
||||
#if defined(PROJECT_ENABLE_TPL)
|
||||
#include "process.hpp"
|
||||
#endif // defined(PROJECT_ENABLE_TPL)
|
||||
|
||||
#if defined(PROJECT_ENABLE_WINFSP)
|
||||
#if defined(_ReadWriteBarrier)
|
||||
#undef _ReadWriteBarrier
|
||||
#endif // defined(_ReadWriteBarrier)
|
||||
#include "winfsp/winfsp.hpp"
|
||||
#endif // defined(PROJECT_ENABLE_WINFSP)
|
||||
|
||||
namespace fifthgrid {
|
||||
using data_buffer = std::vector<unsigned char>;
|
||||
using data_span = std::span<unsigned char>;
|
||||
using data_cspan = std::span<const unsigned char>;
|
||||
using mutex_lock = std::lock_guard<std::mutex>;
|
||||
using recur_mutex_lock = std::lock_guard<std::recursive_mutex>;
|
||||
using stop_type = std::atomic_bool;
|
||||
using stop_type_callback = std::function<std::atomic_bool()>;
|
||||
using unique_mutex_lock = std::unique_lock<std::mutex>;
|
||||
using unique_recur_mutex_lock = std::unique_lock<std::recursive_mutex>;
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES)
|
||||
inline constexpr auto max_path_length = std::size_t{32767U};
|
||||
#else // !defined(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES)
|
||||
inline constexpr auto max_path_length = std::size_t{MAX_PATH};
|
||||
#endif // defined(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES)
|
||||
|
||||
using native_handle = HANDLE;
|
||||
#else // !defined(_WIN32)
|
||||
inline constexpr auto max_path_length = std::size_t{PATH_MAX};
|
||||
using native_handle = int;
|
||||
#if !defined(INVALID_HANDLE_VALUE)
|
||||
#define INVALID_HANDLE_VALUE (-1)
|
||||
#endif // !defined(INVALID_HANDLE_VALUE)
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
template <class... Ts> struct overloaded : Ts... {
|
||||
using Ts::operator()...;
|
||||
};
|
||||
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
|
||||
|
||||
template <typename T> struct is_collection {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <typename T, typename A>
|
||||
struct is_collection<std::vector<T, A>> : std::true_type {};
|
||||
|
||||
template <typename T> struct is_collection<std::deque<T>> : std::true_type {};
|
||||
|
||||
template <> struct is_collection<std::string> : std::true_type {};
|
||||
|
||||
template <> struct is_collection<std::wstring> : std::true_type {};
|
||||
|
||||
struct file_deleter final {
|
||||
void operator()(FILE *file) {
|
||||
if (file != nullptr) {
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
};
|
||||
using file_t = std::unique_ptr<FILE, file_deleter>;
|
||||
|
||||
struct http_range final {
|
||||
std::uint64_t begin{};
|
||||
std::uint64_t end{};
|
||||
};
|
||||
|
||||
using http_headers = std::map<std::string, std::string>;
|
||||
using http_query_parameters = std::map<std::string, std::string>;
|
||||
using http_ranges = std::vector<http_range>;
|
||||
} // namespace fifthgrid
|
||||
#endif // defined(__cplusplus)
|
||||
|
||||
#define FIFTHGRID_USES_FUNCTION_NAME() \
|
||||
static constexpr std::string_view function_name { \
|
||||
static_cast<const char *>(__FUNCTION__), \
|
||||
}
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_CONFIG_HPP_
|
||||
170
support/include/utils/db/sqlite/db_common.hpp
Normal file
170
support/include/utils/db/sqlite/db_common.hpp
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_COMMON_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_COMMON_HPP_
|
||||
#if defined(PROJECT_ENABLE_SQLITE)
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
#include "utils/error.hpp"
|
||||
|
||||
namespace fifthgrid::utils::db::sqlite {
|
||||
using db_types_t = std::variant<std::int64_t, std::string>;
|
||||
|
||||
struct sqlite3_deleter final {
|
||||
void operator()(sqlite3 *db3) const;
|
||||
};
|
||||
|
||||
using db3_t = std::unique_ptr<sqlite3, sqlite3_deleter>;
|
||||
|
||||
struct sqlite3_statement_deleter final {
|
||||
void operator()(sqlite3_stmt *stmt) const {
|
||||
if (stmt != nullptr) {
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using db3_stmt_t = std::unique_ptr<sqlite3_stmt, sqlite3_statement_deleter>;
|
||||
|
||||
[[nodiscard]] auto
|
||||
create_db(std::string db_path,
|
||||
const std::map<std::string, std::string> &sql_create_tables) -> db3_t;
|
||||
|
||||
[[nodiscard]] auto execute_sql(sqlite3 &db3, const std::string &sql,
|
||||
std::string &err) -> bool;
|
||||
|
||||
void set_journal_mode(sqlite3 &db3);
|
||||
|
||||
struct db_comp_data_t final {
|
||||
std::string column_name;
|
||||
std::string op_type;
|
||||
};
|
||||
|
||||
struct db_context_t {
|
||||
db_context_t(sqlite3 *db3_, std::string table_name_)
|
||||
: db3(db3_), table_name(std::move(table_name_)) {}
|
||||
|
||||
sqlite3 *db3{};
|
||||
std::string table_name;
|
||||
};
|
||||
|
||||
struct db_result final {
|
||||
struct context final {
|
||||
db3_stmt_t stmt;
|
||||
};
|
||||
|
||||
class db_column final {
|
||||
public:
|
||||
db_column(std::int32_t index, std::string name, db_types_t value) noexcept;
|
||||
|
||||
db_column() noexcept = default;
|
||||
db_column(const db_column &) = default;
|
||||
db_column(db_column &&column) noexcept = default;
|
||||
|
||||
~db_column() = default;
|
||||
|
||||
auto operator=(const db_column &) -> db_column & = default;
|
||||
auto operator=(db_column &&) -> db_column & = default;
|
||||
|
||||
private:
|
||||
std::int32_t index_{};
|
||||
std::string name_;
|
||||
db_types_t value_;
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto get_index() const -> std::int32_t { return index_; }
|
||||
|
||||
[[nodiscard]] auto get_name() const -> std::string { return name_; }
|
||||
|
||||
template <typename data_type>
|
||||
[[nodiscard]] auto get_value() const -> data_type {
|
||||
FIFTHGRID_USES_FUNCTION_NAME();
|
||||
|
||||
return std::visit(
|
||||
overloaded{
|
||||
[](const data_type &value) -> data_type { return value; },
|
||||
[](auto &&) -> data_type {
|
||||
throw utils::error::create_exception(
|
||||
function_name, {
|
||||
"data type not supported",
|
||||
});
|
||||
},
|
||||
},
|
||||
value_);
|
||||
}
|
||||
|
||||
#if defined(PROJECT_ENABLE_JSON)
|
||||
[[nodiscard]] auto get_value_as_json() const -> nlohmann::json;
|
||||
#endif // defined(PROJECT_ENABLE_JSON)
|
||||
};
|
||||
|
||||
class db_row final {
|
||||
public:
|
||||
db_row(std::shared_ptr<context> ctx);
|
||||
|
||||
private:
|
||||
std::map<std::string, db_column> columns_;
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto get_columns() const -> std::vector<db_column>;
|
||||
|
||||
[[nodiscard]] auto get_column(std::int32_t index) const -> db_column;
|
||||
|
||||
[[nodiscard]] auto get_column(std::string name) const -> db_column;
|
||||
};
|
||||
|
||||
db_result(db3_stmt_t stmt, std::int32_t res);
|
||||
|
||||
db_result() = default;
|
||||
db_result(const db_result &) = default;
|
||||
db_result(db_result &&) noexcept = default;
|
||||
|
||||
auto operator=(const db_result &) -> db_result & = default;
|
||||
auto operator=(db_result &&) -> db_result & = default;
|
||||
|
||||
using row = db_row;
|
||||
|
||||
private:
|
||||
std::shared_ptr<context> ctx_;
|
||||
mutable std::int32_t res_{};
|
||||
|
||||
private:
|
||||
void set_res(std::int32_t res) const { res_ = res; }
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto get_error() const -> std::int32_t { return res_; }
|
||||
|
||||
[[nodiscard]] auto get_error_str() const -> std::string;
|
||||
|
||||
[[nodiscard]] auto get_row(std::optional<row> &opt_row) const -> bool;
|
||||
|
||||
[[nodiscard]] auto has_row() const -> bool;
|
||||
|
||||
void next_row() const;
|
||||
|
||||
[[nodiscard]] auto ok() const -> bool;
|
||||
};
|
||||
} // namespace fifthgrid::utils::db::sqlite
|
||||
|
||||
#endif // defined(PROJECT_ENABLE_SQLITE)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_COMMON_HPP_
|
||||
73
support/include/utils/db/sqlite/db_delete.hpp
Normal file
73
support/include/utils/db/sqlite/db_delete.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_DELETE_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_DELETE_HPP_
|
||||
#if defined(PROJECT_ENABLE_SQLITE)
|
||||
|
||||
#include "utils/db/sqlite/db_common.hpp"
|
||||
|
||||
#include "utils/db/sqlite/db_where_t.hpp"
|
||||
|
||||
namespace fifthgrid::utils::db::sqlite {
|
||||
class db_delete final {
|
||||
public:
|
||||
struct context final : db_context_t {
|
||||
struct db_delete_op_t final {
|
||||
std::shared_ptr<context> ctx;
|
||||
|
||||
[[nodiscard]] auto dump() const -> std::string;
|
||||
|
||||
[[nodiscard]] auto go() const -> db_result;
|
||||
};
|
||||
|
||||
context(sqlite3 *db3_, std::string table_name_)
|
||||
: db_context_t(db3_, table_name_) {}
|
||||
|
||||
using w_t = db_where_t<context, db_delete_op_t>;
|
||||
using wd_t = where_data_t<w_t>;
|
||||
|
||||
std::unique_ptr<wd_t> where_data;
|
||||
};
|
||||
|
||||
public:
|
||||
db_delete(sqlite3 &db3, std::string table_name)
|
||||
: ctx_(std::make_shared<context>(&db3, table_name)) {}
|
||||
|
||||
db_delete(std::shared_ptr<context> ctx) : ctx_(std::move(ctx)) {}
|
||||
|
||||
private:
|
||||
std::shared_ptr<context> ctx_;
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto dump() const -> std::string;
|
||||
|
||||
[[nodiscard]] auto go() const -> db_result;
|
||||
|
||||
[[nodiscard]] auto
|
||||
group(context::w_t::group_func_t func) -> context::w_t::wn_t;
|
||||
|
||||
[[nodiscard]] auto where(std::string column_name) const -> context::w_t::cn_t;
|
||||
};
|
||||
} // namespace fifthgrid::utils::db::sqlite
|
||||
|
||||
#endif // defined(PROJECT_ENABLE_SQLITE)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_DELETE_HPP_
|
||||
64
support/include/utils/db/sqlite/db_insert.hpp
Normal file
64
support/include/utils/db/sqlite/db_insert.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_INSERT_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_INSERT_HPP_
|
||||
#if defined(PROJECT_ENABLE_SQLITE)
|
||||
|
||||
#include "utils/db/sqlite/db_common.hpp"
|
||||
|
||||
namespace fifthgrid::utils::db::sqlite {
|
||||
class db_insert final {
|
||||
public:
|
||||
struct context final : db_context_t {
|
||||
context(sqlite3 *db3_, std::string table_name_)
|
||||
: db_context_t(db3_, table_name_) {}
|
||||
|
||||
bool or_replace{false};
|
||||
std::map<std::string, db_types_t> values;
|
||||
};
|
||||
|
||||
public:
|
||||
db_insert(sqlite3 &db3, std::string table_name)
|
||||
: ctx_(std::make_shared<context>(&db3, table_name)) {}
|
||||
|
||||
db_insert(std::shared_ptr<context> ctx) : ctx_(std::move(ctx)) {}
|
||||
|
||||
private:
|
||||
std::shared_ptr<context> ctx_;
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto or_replace() -> db_insert {
|
||||
ctx_->or_replace = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto column_value(std::string column_name, db_types_t value)
|
||||
-> db_insert;
|
||||
|
||||
[[nodiscard]] auto dump() const -> std::string;
|
||||
|
||||
[[nodiscard]] auto go() const -> db_result;
|
||||
};
|
||||
} // namespace fifthgrid::utils::db::sqlite
|
||||
|
||||
#endif // defined(PROJECT_ENABLE_SQLITE)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_INSERT_HPP_
|
||||
104
support/include/utils/db/sqlite/db_select.hpp
Normal file
104
support/include/utils/db/sqlite/db_select.hpp
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_SELECT_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_SELECT_HPP_
|
||||
#if defined(PROJECT_ENABLE_SQLITE)
|
||||
|
||||
#include "utils/db/sqlite/db_common.hpp"
|
||||
|
||||
#include "utils/db/sqlite/db_where_t.hpp"
|
||||
|
||||
namespace fifthgrid::utils::db::sqlite {
|
||||
class db_select final {
|
||||
public:
|
||||
struct context final : db_context_t {
|
||||
struct db_select_op_t final {
|
||||
std::shared_ptr<context> ctx;
|
||||
|
||||
[[nodiscard]] auto dump() const -> std::string;
|
||||
|
||||
[[nodiscard]] auto go() const -> db_result;
|
||||
|
||||
[[nodiscard]] auto group_by(std::string column_name) -> db_select_op_t;
|
||||
|
||||
[[nodiscard]] auto limit(std::int32_t value) -> db_select_op_t;
|
||||
|
||||
[[nodiscard]] auto offset(std::int32_t value) -> db_select_op_t;
|
||||
|
||||
[[nodiscard]] auto order_by(std::string column_name, bool ascending)
|
||||
-> db_select_op_t;
|
||||
};
|
||||
|
||||
context(sqlite3 *db3_, std::string table_name_)
|
||||
: db_context_t(db3_, table_name_) {}
|
||||
|
||||
using w_t = db_where_t<context, db_select_op_t>;
|
||||
using wd_t = where_data_t<w_t>;
|
||||
|
||||
std::vector<std::string> columns;
|
||||
std::map<std::string, std::string> count_columns;
|
||||
|
||||
std::vector<std::string> group_by;
|
||||
std::optional<std::int32_t> limit;
|
||||
std::optional<std::int32_t> offset;
|
||||
std::optional<std::pair<std::string, bool>> order_by;
|
||||
|
||||
std::unique_ptr<wd_t> where_data;
|
||||
};
|
||||
|
||||
public:
|
||||
db_select(sqlite3 &db3, std::string table_name)
|
||||
: ctx_(std::make_shared<context>(&db3, table_name)) {}
|
||||
|
||||
db_select(std::shared_ptr<context> ctx) : ctx_(std::move(ctx)) {}
|
||||
|
||||
private:
|
||||
std::shared_ptr<context> ctx_;
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto column(std::string column_name) -> db_select;
|
||||
|
||||
[[nodiscard]] auto count(std::string column_name, std::string as_column_name)
|
||||
-> db_select;
|
||||
|
||||
[[nodiscard]] auto dump() const -> std::string;
|
||||
|
||||
[[nodiscard]] auto go() const -> db_result;
|
||||
|
||||
[[nodiscard]] auto group_by(std::string column_name) -> db_select;
|
||||
[[nodiscard]] auto group(context::w_t::group_func_t func)
|
||||
|
||||
-> context::w_t::wn_t;
|
||||
|
||||
[[nodiscard]] auto limit(std::int32_t value) -> db_select;
|
||||
|
||||
[[nodiscard]] auto offset(std::int32_t value) -> db_select;
|
||||
|
||||
[[nodiscard]] auto order_by(std::string column_name, bool ascending)
|
||||
-> db_select;
|
||||
|
||||
[[nodiscard]] auto where(std::string column_name) const -> context::w_t::cn_t;
|
||||
};
|
||||
} // namespace fifthgrid::utils::db::sqlite
|
||||
|
||||
#endif // defined(PROJECT_ENABLE_SQLITE)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_SELECT_HPP_
|
||||
91
support/include/utils/db/sqlite/db_update.hpp
Normal file
91
support/include/utils/db/sqlite/db_update.hpp
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_UPDATE_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_UPDATE_HPP_
|
||||
#if defined(PROJECT_ENABLE_SQLITE)
|
||||
|
||||
#include "utils/db/sqlite/db_common.hpp"
|
||||
|
||||
#include "utils/db/sqlite/db_where_t.hpp"
|
||||
|
||||
namespace fifthgrid::utils::db::sqlite {
|
||||
class db_update final {
|
||||
public:
|
||||
struct context final : db_context_t {
|
||||
context(sqlite3 *db3_, std::string table_name_)
|
||||
: db_context_t(db3_, table_name_) {}
|
||||
|
||||
struct db_update_op_t final {
|
||||
std::shared_ptr<context> ctx;
|
||||
|
||||
[[nodiscard]] auto dump() const -> std::string;
|
||||
|
||||
[[nodiscard]] auto go() const -> db_result;
|
||||
|
||||
[[nodiscard]] auto limit(std::int32_t value) -> db_update_op_t;
|
||||
|
||||
[[nodiscard]] auto order_by(std::string column_name, bool ascending)
|
||||
|
||||
-> db_update_op_t;
|
||||
};
|
||||
|
||||
using w_t = db_where_t<context, db_update_op_t>;
|
||||
using wd_t = where_data_t<w_t>;
|
||||
|
||||
std::map<std::string, db_types_t> column_values;
|
||||
std::optional<std::int32_t> limit;
|
||||
std::optional<std::pair<std::string, bool>> order_by;
|
||||
|
||||
std::unique_ptr<wd_t> where_data;
|
||||
};
|
||||
|
||||
public:
|
||||
db_update(sqlite3 &db3, std::string table_name)
|
||||
: ctx_(std::make_shared<context>(&db3, table_name)) {}
|
||||
|
||||
db_update(std::shared_ptr<context> ctx) : ctx_(std::move(ctx)) {}
|
||||
|
||||
private:
|
||||
std::shared_ptr<context> ctx_;
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto column_value(std::string column_name, db_types_t value)
|
||||
-> db_update;
|
||||
|
||||
[[nodiscard]] auto dump() const -> std::string;
|
||||
|
||||
[[nodiscard]] auto go() const -> db_result;
|
||||
|
||||
[[nodiscard]] auto group(context::w_t::group_func_t func)
|
||||
-> context::w_t::wn_t;
|
||||
|
||||
[[nodiscard]] auto limit(std::int32_t value) -> db_update;
|
||||
|
||||
[[nodiscard]] auto order_by(std::string column_name, bool ascending)
|
||||
-> db_update;
|
||||
|
||||
[[nodiscard]] auto where(std::string column_name) const -> context::w_t::cn_t;
|
||||
};
|
||||
} // namespace fifthgrid::utils::db::sqlite
|
||||
|
||||
#endif // defined(PROJECT_ENABLE_SQLITE)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_UPDATE_HPP_
|
||||
224
support/include/utils/db/sqlite/db_where_t.hpp
Normal file
224
support/include/utils/db/sqlite/db_where_t.hpp
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_WHERE_T_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_WHERE_T_HPP_
|
||||
#if defined(PROJECT_ENABLE_SQLITE)
|
||||
|
||||
#include "utils/db/sqlite/db_common.hpp"
|
||||
|
||||
namespace fifthgrid::utils::db::sqlite {
|
||||
template <typename w_t> struct where_data_t final {
|
||||
w_t base;
|
||||
std::map<std::size_t, std::vector<typename w_t::action_t>> actions;
|
||||
std::vector<db_types_t> values;
|
||||
};
|
||||
|
||||
template <typename cn_t, typename ctx_t, typename op_t, typename w_t,
|
||||
typename wn_t>
|
||||
struct db_next_t final {
|
||||
std::size_t action_idx{};
|
||||
std::shared_ptr<ctx_t> ctx;
|
||||
std::string action;
|
||||
|
||||
using group_func_t = std::function<void(w_t &)>;
|
||||
|
||||
[[nodiscard]] auto where(std::string column_name) -> cn_t {
|
||||
return w_t{action_idx, ctx}.where(column_name);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto dump() const -> std::string { return op_t{ctx}.dump(); }
|
||||
|
||||
[[nodiscard]] auto dump(std::int32_t &idx) const -> std::string {
|
||||
return ctx->where_data->base.dump(idx);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto go() const -> auto { return op_t{ctx}.go(); }
|
||||
|
||||
[[nodiscard]] auto group(group_func_t func) -> wn_t {
|
||||
return w_t{action_idx, ctx}.group(std::move(func));
|
||||
}
|
||||
|
||||
[[nodiscard]] auto op() -> op_t {
|
||||
return op_t{
|
||||
ctx,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename cn_t, typename ctx_t, typename op_t, typename w_t>
|
||||
struct db_where_next_t final {
|
||||
std::size_t action_idx{};
|
||||
std::shared_ptr<ctx_t> ctx;
|
||||
|
||||
using n_t = db_next_t<cn_t, ctx_t, op_t, w_t, db_where_next_t>;
|
||||
|
||||
[[nodiscard]] auto and_() -> n_t {
|
||||
n_t next{
|
||||
action_idx,
|
||||
ctx,
|
||||
"AND",
|
||||
};
|
||||
|
||||
ctx->where_data->actions[action_idx].emplace_back(next);
|
||||
return next;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto dump() const -> std::string { return op_t{ctx}.dump(); }
|
||||
|
||||
[[nodiscard]] auto dump(std::int32_t &idx) const -> std::string {
|
||||
return ctx->where_data->base.dump(idx);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto go() const -> auto { return op_t{ctx}.go(); }
|
||||
|
||||
[[nodiscard]] auto op() -> op_t {
|
||||
return op_t{
|
||||
ctx,
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] auto or_() -> n_t {
|
||||
n_t next{
|
||||
action_idx,
|
||||
ctx,
|
||||
"OR",
|
||||
};
|
||||
|
||||
ctx->where_data->actions[action_idx].emplace_back(next);
|
||||
return next;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ctx_t, typename op_t, typename w_t>
|
||||
struct db_comp_next_t final {
|
||||
std::size_t action_idx{};
|
||||
std::shared_ptr<ctx_t> ctx;
|
||||
std::string column_name;
|
||||
|
||||
using wn_t = db_where_next_t<db_comp_next_t, ctx_t, op_t, w_t>;
|
||||
|
||||
[[nodiscard]] auto create(std::string operation, db_types_t value) {
|
||||
ctx->where_data->actions[action_idx].emplace_back(db_comp_data_t{
|
||||
column_name,
|
||||
operation,
|
||||
});
|
||||
|
||||
ctx->where_data->values.push_back(value);
|
||||
|
||||
return wn_t{
|
||||
action_idx,
|
||||
ctx,
|
||||
};
|
||||
}
|
||||
|
||||
auto equals(db_types_t value) -> wn_t { return create("=", value); };
|
||||
|
||||
auto gt(db_types_t value) -> wn_t { return create(">", value); }
|
||||
|
||||
auto gte(db_types_t value) -> wn_t { return create(">=", value); }
|
||||
|
||||
auto like(db_types_t value) -> wn_t { return create("LIKE", value); }
|
||||
|
||||
auto lt(db_types_t value) -> wn_t { return create("<", value); }
|
||||
|
||||
auto lte(db_types_t value) -> wn_t { return create("<=", value); }
|
||||
|
||||
auto not_equals(db_types_t value) -> wn_t { return create("!=", value); };
|
||||
};
|
||||
|
||||
template <typename ctx_t, typename op_t> struct db_where_t final {
|
||||
std::size_t action_idx{0U};
|
||||
std::shared_ptr<ctx_t> ctx;
|
||||
|
||||
using cn_t = db_comp_next_t<ctx_t, op_t, db_where_t>;
|
||||
using wn_t = db_where_next_t<cn_t, ctx_t, op_t, db_where_t>;
|
||||
using n_t = db_next_t<cn_t, ctx_t, op_t, db_where_t, wn_t>;
|
||||
|
||||
using group_func_t = std::function<void(db_where_t &)>;
|
||||
|
||||
using action_t = std::variant<db_comp_data_t, n_t, db_where_t>;
|
||||
|
||||
[[nodiscard]] static auto dump(std::int32_t &idx,
|
||||
auto &&actions) -> std::string {
|
||||
std::stringstream stream;
|
||||
|
||||
for (auto &&action : actions) {
|
||||
std::visit(overloaded{
|
||||
[&idx, &stream](const db_comp_data_t &comp) {
|
||||
stream << '"' << comp.column_name << '"' << comp.op_type
|
||||
<< '?' + std::to_string(++idx);
|
||||
},
|
||||
[&idx, &stream](const n_t &next) {
|
||||
stream << ' ' << next.action << ' ';
|
||||
},
|
||||
[&idx, &stream](const db_where_t &where) {
|
||||
stream << '(' << dump(idx, where.get_actions()) << ')';
|
||||
},
|
||||
},
|
||||
action);
|
||||
}
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto dump() const -> std::string { return op_t{ctx}.dump(); }
|
||||
|
||||
[[nodiscard]] auto dump(std::int32_t &idx) const -> std::string {
|
||||
return dump(idx, ctx->where_data->actions[action_idx]);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_actions() -> auto & {
|
||||
return ctx->where_data->actions[action_idx];
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_actions() const -> const auto & {
|
||||
return ctx->where_data->actions[action_idx];
|
||||
}
|
||||
|
||||
[[nodiscard]] auto group(group_func_t func) -> wn_t {
|
||||
ctx->where_data->actions[action_idx];
|
||||
|
||||
db_where_t where{ctx->where_data->actions.size(), ctx};
|
||||
func(where);
|
||||
|
||||
ctx->where_data->actions[action_idx].emplace_back(where);
|
||||
|
||||
return wn_t{
|
||||
action_idx,
|
||||
ctx,
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] auto where(std::string column_name) -> cn_t {
|
||||
ctx->where_data->actions[action_idx];
|
||||
|
||||
return cn_t{
|
||||
action_idx,
|
||||
ctx,
|
||||
column_name,
|
||||
};
|
||||
}
|
||||
};
|
||||
} // namespace fifthgrid::utils::db::sqlite
|
||||
|
||||
#endif // defined(PROJECT_ENABLE_SQLITE)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_DB_SQLITE_DB_WHERE_T_HPP_
|
||||
239
support/include/utils/encrypting_reader.hpp
Normal file
239
support/include/utils/encrypting_reader.hpp
Normal file
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_ENCRYPTING_READER_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_ENCRYPTING_READER_HPP_
|
||||
#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
#include "utils/encryption.hpp"
|
||||
#include "utils/hash.hpp"
|
||||
#include "utils/types/file/i_file.hpp"
|
||||
|
||||
namespace fifthgrid::utils::encryption {
|
||||
class encrypting_reader final {
|
||||
public:
|
||||
encrypting_reader(std::string_view file_name, std::string_view source_path,
|
||||
stop_type_callback stop_requested_cb,
|
||||
std::string_view token,
|
||||
std::optional<std::string> relative_parent_path,
|
||||
std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(stop_type_callback stop_requested_cb,
|
||||
std::string_view encrypted_file_path,
|
||||
std::string_view source_path, std::string_view token,
|
||||
std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(
|
||||
stop_type_callback stop_requested_cb,
|
||||
std::string_view encrypted_file_path, std::string_view source_path,
|
||||
std::string_view token,
|
||||
std::vector<std::array<unsigned char,
|
||||
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
|
||||
iv_list,
|
||||
std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(std::string_view file_name, std::string_view source_path,
|
||||
stop_type_callback stop_requested_cb,
|
||||
std::string_view token, kdf_config cfg,
|
||||
std::optional<std::string> relative_parent_path,
|
||||
std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(stop_type_callback stop_requested_cb,
|
||||
std::string_view encrypted_file_path,
|
||||
std::string_view source_path, std::string_view token,
|
||||
kdf_config cfg, std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(
|
||||
stop_type_callback stop_requested_cb,
|
||||
std::string_view encrypted_file_path, std::string_view source_path,
|
||||
std::string_view token, kdf_config cfg,
|
||||
std::vector<std::array<unsigned char,
|
||||
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
|
||||
iv_list,
|
||||
std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(std::string_view file_name, std::string_view source_path,
|
||||
stop_type_callback stop_requested_cb,
|
||||
const utils::hash::hash_256_t &master_key,
|
||||
const kdf_config &cfg,
|
||||
std::optional<std::string> relative_parent_path,
|
||||
std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(std::string_view file_name, std::string_view source_path,
|
||||
stop_type_callback stop_requested_cb,
|
||||
const utils::hash::hash_256_t &master_key,
|
||||
const std::pair<kdf_config, kdf_config> &configs,
|
||||
std::optional<std::string> relative_parent_path,
|
||||
std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(stop_type_callback stop_requested_cb,
|
||||
std::string_view encrypted_file_path,
|
||||
std::string_view source_path,
|
||||
const utils::hash::hash_256_t &master_key,
|
||||
const kdf_config &cfg, std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(
|
||||
stop_type_callback stop_requested_cb,
|
||||
std::string_view encrypted_file_path, std::string_view source_path,
|
||||
const utils::hash::hash_256_t &master_key, const kdf_config &cfg,
|
||||
std::vector<std::array<unsigned char,
|
||||
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
|
||||
iv_list,
|
||||
std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(
|
||||
stop_type_callback stop_requested_cb,
|
||||
std::string_view encrypted_file_path, std::string_view source_path,
|
||||
const utils::hash::hash_256_t &master_key,
|
||||
const std::pair<kdf_config, kdf_config> &configs,
|
||||
std::vector<std::array<unsigned char,
|
||||
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
|
||||
iv_list,
|
||||
std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(const encrypting_reader &reader);
|
||||
encrypting_reader(encrypting_reader &&) = delete;
|
||||
|
||||
auto operator=(const encrypting_reader &) -> encrypting_reader & = delete;
|
||||
auto operator=(encrypting_reader &&) -> encrypting_reader & = delete;
|
||||
|
||||
~encrypting_reader() noexcept = default;
|
||||
|
||||
public:
|
||||
using iostream = std::basic_iostream<char, std::char_traits<char>>;
|
||||
using kdf_pair_t = std::pair<data_buffer, data_buffer>;
|
||||
using key_pair_t =
|
||||
std::pair<utils::hash::hash_256_t, utils::hash::hash_256_t>;
|
||||
using streambuf = std::basic_streambuf<char, std::char_traits<char>>;
|
||||
|
||||
private:
|
||||
key_pair_t keys_;
|
||||
stop_type_callback stop_requested_cb_;
|
||||
size_t error_return_;
|
||||
std::unique_ptr<utils::file::i_file> source_file_;
|
||||
std::string encrypted_file_name_;
|
||||
std::string encrypted_file_path_;
|
||||
std::vector<
|
||||
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
|
||||
iv_list_;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::size_t, data_buffer> chunk_buffers_;
|
||||
std::optional<kdf_pair_t> kdf_headers_;
|
||||
std::size_t last_data_chunk_{};
|
||||
std::size_t last_data_chunk_size_{};
|
||||
std::uint64_t read_offset_{};
|
||||
std::uint64_t total_size_{};
|
||||
|
||||
private:
|
||||
static const std::size_t header_size_;
|
||||
static const std::size_t data_chunk_size_;
|
||||
static const std::size_t encrypted_chunk_size_;
|
||||
|
||||
private:
|
||||
auto reader_function(char *buffer, size_t size, size_t nitems) -> size_t;
|
||||
|
||||
void common_initialize(bool procces_iv_list);
|
||||
|
||||
void common_initialize_kdf_data(const kdf_config &cfg,
|
||||
const utils::hash::hash_256_t &master_key);
|
||||
|
||||
void common_initialize_kdf_keys(std::string_view token, kdf_config &cfg);
|
||||
|
||||
void common_initialize_kdf_path(const utils::hash::hash_256_t &master_key);
|
||||
|
||||
void create_encrypted_paths(std::string_view file_name,
|
||||
std::optional<std::string> relative_parent_path);
|
||||
|
||||
public:
|
||||
[[nodiscard]] static auto calculate_decrypted_size(std::uint64_t total_size,
|
||||
bool uses_kdf)
|
||||
-> std::uint64_t;
|
||||
|
||||
[[nodiscard]] static auto
|
||||
calculate_encrypted_size(std::string_view source_path, bool uses_kdf)
|
||||
-> std::uint64_t;
|
||||
|
||||
[[nodiscard]] static auto calculate_encrypted_size(std::uint64_t size,
|
||||
bool uses_kdf)
|
||||
-> std::uint64_t;
|
||||
|
||||
[[nodiscard]] auto create_iostream() const -> std::shared_ptr<iostream>;
|
||||
|
||||
[[nodiscard]] static constexpr auto get_encrypted_chunk_size()
|
||||
-> std::size_t {
|
||||
return encrypted_chunk_size_;
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr auto get_data_chunk_size() -> std::size_t {
|
||||
return data_chunk_size_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_encrypted_file_name() const -> std::string {
|
||||
return encrypted_file_name_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_encrypted_file_path() const -> std::string {
|
||||
return encrypted_file_path_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_error_return() const -> std::size_t {
|
||||
return error_return_;
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr auto get_header_size() -> std::size_t {
|
||||
return header_size_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_iv_list() -> std::vector<
|
||||
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>> {
|
||||
return iv_list_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_kdf_config_for_data() const
|
||||
-> std::optional<kdf_config>;
|
||||
|
||||
[[nodiscard]] auto get_kdf_config_for_path() const
|
||||
-> std::optional<kdf_config>;
|
||||
|
||||
[[nodiscard]] auto get_stop_requested() const -> bool {
|
||||
return stop_requested_cb_();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_total_size() const -> std::uint64_t {
|
||||
return total_size_;
|
||||
}
|
||||
|
||||
[[nodiscard]] static auto reader_function(char *buffer, size_t size,
|
||||
size_t nitems, void *instream)
|
||||
-> size_t {
|
||||
return reinterpret_cast<encrypting_reader *>(instream)->reader_function(
|
||||
buffer, size, nitems);
|
||||
}
|
||||
|
||||
void set_read_position(std::uint64_t position) { read_offset_ = position; }
|
||||
};
|
||||
} // namespace fifthgrid::utils::encryption
|
||||
|
||||
#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_ENCRYPTING_READER_HPP_
|
||||
722
support/include/utils/encryption.hpp
Normal file
722
support/include/utils/encryption.hpp
Normal file
@@ -0,0 +1,722 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_ENCRYPTION_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_ENCRYPTION_HPP_
|
||||
#if defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
#if defined(PROJECT_ENABLE_BOOST) && defined(PROJECT_ENABLE_JSON)
|
||||
#include "utils/collection.hpp"
|
||||
#endif // defined(PROJECT_ENABLE_BOOST) && defined(PROJECT_ENABLE_JSON)
|
||||
#include "utils/error.hpp"
|
||||
#include "utils/hash.hpp"
|
||||
|
||||
namespace fifthgrid::utils::encryption {
|
||||
inline constexpr std::uint32_t encryption_header_size{
|
||||
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES +
|
||||
crypto_aead_xchacha20poly1305_IETF_ABYTES,
|
||||
};
|
||||
|
||||
#if defined(PROJECT_ENABLE_BOOST)
|
||||
enum class kdf_version : std::uint8_t { v1 };
|
||||
|
||||
enum class kdf_type : std::uint8_t { argon2id };
|
||||
|
||||
enum class memlimit_level : std::uint8_t {
|
||||
level1, // 64MiB
|
||||
level2, // 256MiB
|
||||
level3, // 512MiB
|
||||
level4, // 1GiB
|
||||
};
|
||||
|
||||
enum class opslimit_level : std::uint8_t {
|
||||
level1, // interactive
|
||||
level2, // moderate
|
||||
level3, // sensitive
|
||||
};
|
||||
|
||||
[[nodiscard]] inline auto get_memlimit(memlimit_level memlimit) -> size_t {
|
||||
constexpr auto mib512{512ULL * 1024ULL * 1024ULL};
|
||||
|
||||
switch (memlimit) {
|
||||
case memlimit_level::level1:
|
||||
return crypto_pwhash_MEMLIMIT_INTERACTIVE;
|
||||
|
||||
case memlimit_level::level2:
|
||||
return crypto_pwhash_MEMLIMIT_MODERATE;
|
||||
|
||||
case memlimit_level::level3:
|
||||
return mib512;
|
||||
|
||||
case memlimit_level::level4:
|
||||
return crypto_pwhash_MEMLIMIT_SENSITIVE;
|
||||
}
|
||||
|
||||
return mib512;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline auto get_opslimit(opslimit_level opslimit)
|
||||
-> unsigned long long {
|
||||
switch (opslimit) {
|
||||
case opslimit_level::level1:
|
||||
return crypto_pwhash_OPSLIMIT_INTERACTIVE;
|
||||
|
||||
case opslimit_level::level2:
|
||||
return crypto_pwhash_OPSLIMIT_MODERATE;
|
||||
|
||||
case opslimit_level::level3:
|
||||
return crypto_pwhash_OPSLIMIT_SENSITIVE;
|
||||
}
|
||||
|
||||
return crypto_pwhash_OPSLIMIT_MODERATE;
|
||||
}
|
||||
|
||||
enum class kdf_context : std::uint8_t {
|
||||
data,
|
||||
path,
|
||||
undefined,
|
||||
};
|
||||
using kdf_ctx_t = std::array<char, crypto_kdf_CONTEXTBYTES>;
|
||||
|
||||
namespace kdf {
|
||||
constexpr inline std::array<
|
||||
kdf_ctx_t, static_cast<std::size_t>(kdf_context::undefined) + 1U>
|
||||
KDF_CTXS{
|
||||
{
|
||||
{'D', 'A', 'T', 'A', '_', 'C', 'T', 'X'},
|
||||
{'F', 'I', 'L', 'E', '_', 'C', 'T', 'X'},
|
||||
{'D', 'E', 'F', 'L', '_', 'C', 'T', 'X'},
|
||||
},
|
||||
};
|
||||
} // namespace kdf
|
||||
|
||||
[[nodiscard]] constexpr inline auto get_kdf_context_name(kdf_context ctx)
|
||||
-> kdf_ctx_t {
|
||||
const auto idx = static_cast<std::size_t>(ctx);
|
||||
return idx < kdf::KDF_CTXS.size() ? kdf::KDF_CTXS.at(idx)
|
||||
: kdf::KDF_CTXS.back();
|
||||
}
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct kdf_config final {
|
||||
using salt_t = std::array<std::uint8_t, crypto_pwhash_SALTBYTES>;
|
||||
|
||||
kdf_version version{kdf_version::v1};
|
||||
kdf_type kdf{kdf_type::argon2id};
|
||||
memlimit_level memlimit{memlimit_level::level3};
|
||||
opslimit_level opslimit{opslimit_level::level2};
|
||||
std::uint64_t unique_id{};
|
||||
salt_t salt{};
|
||||
std::uint64_t checksum{};
|
||||
|
||||
template <typename hash_t>
|
||||
[[nodiscard]] auto create_subkey(kdf_context ctx, std::size_t unique_id_,
|
||||
const hash_t &master_key) const
|
||||
-> std::pair<hash_t, kdf_config> {
|
||||
auto sub_key = derive_subkey<hash_t>(ctx, unique_id_, master_key);
|
||||
|
||||
auto cfg = *this;
|
||||
cfg.unique_id = unique_id_;
|
||||
cfg.checksum = cfg.generate_checksum();
|
||||
return {sub_key, cfg};
|
||||
}
|
||||
|
||||
template <typename hash_t>
|
||||
[[nodiscard]] static auto derive_subkey(kdf_context ctx,
|
||||
std::size_t unique_id_,
|
||||
const hash_t &master_key) -> hash_t {
|
||||
FIFTHGRID_USES_FUNCTION_NAME();
|
||||
|
||||
hash_t sub_key{};
|
||||
auto res = crypto_kdf_derive_from_key(
|
||||
sub_key.data(), sub_key.size(), unique_id_,
|
||||
get_kdf_context_name(ctx).data(), master_key.data());
|
||||
if (res != 0) {
|
||||
throw fifthgrid::utils::error::create_exception(
|
||||
function_name, {
|
||||
"failed to derive sub-key",
|
||||
std::to_string(res),
|
||||
});
|
||||
}
|
||||
|
||||
return sub_key;
|
||||
}
|
||||
|
||||
template <typename hash_t>
|
||||
[[nodiscard]] auto recreate_subkey(kdf_context ctx,
|
||||
const hash_t &master_key) const -> hash_t {
|
||||
return derive_subkey<hash_t>(ctx, unique_id, master_key);
|
||||
}
|
||||
|
||||
[[nodiscard]] static auto from_header(data_cspan data, kdf_config &cfg,
|
||||
bool ignore_checksum = false) -> bool;
|
||||
|
||||
[[nodiscard]] auto generate_checksum() const -> std::uint64_t;
|
||||
|
||||
void seal();
|
||||
|
||||
[[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;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
#endif // defined(PROJECT_ENABLE_BOOST)
|
||||
|
||||
template <typename hash_t>
|
||||
[[nodiscard]] inline auto generate_key(
|
||||
std::string_view password,
|
||||
std::function<hash_t(const unsigned char *data, std::size_t size)> hasher =
|
||||
utils::hash::default_create_hash<hash_t>()) -> hash_t;
|
||||
|
||||
template <typename hash_t>
|
||||
[[nodiscard]] inline auto generate_key(
|
||||
std::wstring_view password,
|
||||
std::function<hash_t(const unsigned char *data, std::size_t size)> hasher =
|
||||
utils::hash::default_create_hash<hash_t>()) -> hash_t;
|
||||
|
||||
#if defined(PROJECT_ENABLE_BOOST)
|
||||
template <typename hash_t>
|
||||
[[nodiscard]] inline auto generate_key(std::string_view password,
|
||||
kdf_config &cfg) -> hash_t;
|
||||
|
||||
template <typename hash_t>
|
||||
[[nodiscard]] inline auto generate_key(std::wstring_view password,
|
||||
kdf_config &cfg) -> hash_t;
|
||||
|
||||
template <typename hash_t>
|
||||
[[nodiscard]] inline auto recreate_key(std::string_view password,
|
||||
const kdf_config &cfg) -> hash_t;
|
||||
|
||||
template <typename hash_t>
|
||||
[[nodiscard]] inline auto recreate_key(std::wstring_view password,
|
||||
const kdf_config &cfg) -> hash_t;
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] auto create_key_argon2id(string_t password, kdf_config &cfg,
|
||||
utils::hash::hash_256_t &key) -> bool;
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] auto recreate_key_argon2id(string_t password,
|
||||
const kdf_config &cfg,
|
||||
utils::hash::hash_256_t &key) -> bool;
|
||||
|
||||
template <typename hash_t, typename string_t>
|
||||
[[nodiscard]] inline auto
|
||||
detect_and_recreate_key(string_t password, data_cspan header, hash_t &key,
|
||||
std::optional<kdf_config> &cfg) -> bool;
|
||||
|
||||
template <typename hash_t>
|
||||
[[nodiscard]] inline auto
|
||||
detect_and_recreate_key(std::string_view password, data_cspan header,
|
||||
hash_t &key, std::optional<kdf_config> &cfg) -> bool;
|
||||
|
||||
template <typename hash_t>
|
||||
[[nodiscard]] inline auto
|
||||
detect_and_recreate_key(std::wstring_view password, data_cspan header,
|
||||
hash_t &key, std::optional<kdf_config> &cfg) -> bool;
|
||||
|
||||
[[nodiscard]] auto decrypt_file_name(std::string_view encryption_token,
|
||||
std::string &file_name) -> bool;
|
||||
|
||||
[[nodiscard]] auto decrypt_file_path(std::string_view encryption_token,
|
||||
std::string &file_path) -> bool;
|
||||
|
||||
[[nodiscard]] auto decrypt_file_name(std::string_view encryption_token,
|
||||
const kdf_config &cfg,
|
||||
std::string &file_name) -> bool;
|
||||
|
||||
[[nodiscard]] auto decrypt_file_path(std::string_view encryption_token,
|
||||
const kdf_config &cfg,
|
||||
std::string &file_path) -> bool;
|
||||
|
||||
[[nodiscard]] auto decrypt_file_name(const utils::hash::hash_256_t &master_key,
|
||||
std::string &file_name) -> bool;
|
||||
|
||||
[[nodiscard]] auto decrypt_file_path(const utils::hash::hash_256_t &master_key,
|
||||
std::string &file_path) -> bool;
|
||||
|
||||
template <typename result_t, typename arr_t, std::size_t arr_size>
|
||||
[[nodiscard]] inline auto decrypt_data(const std::array<arr_t, arr_size> &key,
|
||||
const unsigned char *buffer,
|
||||
std::size_t buffer_size, result_t &res)
|
||||
-> bool {
|
||||
if (buffer_size > encryption_header_size) {
|
||||
std::uint32_t size =
|
||||
boost::endian::native_to_big(static_cast<std::uint32_t>(buffer_size));
|
||||
res.resize(buffer_size - encryption_header_size);
|
||||
return crypto_aead_xchacha20poly1305_ietf_decrypt_detached(
|
||||
reinterpret_cast<unsigned char *>(res.data()), nullptr,
|
||||
&buffer[encryption_header_size], res.size(),
|
||||
&buffer[crypto_aead_xchacha20poly1305_IETF_NPUBBYTES],
|
||||
reinterpret_cast<const unsigned char *>(&size), sizeof(size),
|
||||
buffer, key.data()) == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename buffer_t, typename result_t, typename arr_t,
|
||||
std::size_t arr_size>
|
||||
[[nodiscard]] inline auto decrypt_data(const std::array<arr_t, arr_size> &key,
|
||||
const buffer_t &buf, result_t &res)
|
||||
-> bool {
|
||||
return decrypt_data<result_t>(
|
||||
key, reinterpret_cast<const unsigned char *>(buf.data()), buf.size(),
|
||||
res);
|
||||
}
|
||||
|
||||
template <typename buffer_t, typename result_t,
|
||||
typename hash_t = utils::hash::hash_256_t>
|
||||
[[nodiscard]] inline auto decrypt_data(
|
||||
std::string_view password, const buffer_t &buf, result_t &res,
|
||||
std::function<hash_t(const unsigned char *data, std::size_t size)> hasher =
|
||||
utils::hash::default_create_hash<hash_t>()) -> bool {
|
||||
return decrypt_data<buffer_t, result_t>(generate_key(password, hasher), buf,
|
||||
res);
|
||||
}
|
||||
|
||||
template <typename buffer_t, typename result_t,
|
||||
typename hash_t = utils::hash::hash_256_t>
|
||||
[[nodiscard]] inline auto decrypt_data(std::string_view password,
|
||||
const kdf_config &cfg,
|
||||
const buffer_t &buf, result_t &res)
|
||||
-> bool {
|
||||
return decrypt_data<buffer_t, result_t>(recreate_key<hash_t>(password, cfg),
|
||||
buf, res);
|
||||
}
|
||||
|
||||
template <typename result_t, typename hash_t = utils::hash::hash_256_t>
|
||||
[[nodiscard]] inline auto decrypt_data(
|
||||
std::string_view password, const unsigned char *buffer,
|
||||
std::size_t buffer_size, result_t &res,
|
||||
std::function<hash_t(const unsigned char *data, std::size_t size)> hasher =
|
||||
utils::hash::default_create_hash<hash_t>()) -> bool {
|
||||
return decrypt_data<result_t>(generate_key(password, hasher), buffer,
|
||||
buffer_size, res);
|
||||
}
|
||||
|
||||
template <typename result_t, typename hash_t = utils::hash::hash_256_t>
|
||||
[[nodiscard]] inline auto decrypt_data(std::string_view password,
|
||||
const kdf_config &cfg,
|
||||
const unsigned char *buffer,
|
||||
std::size_t buffer_size, result_t &res)
|
||||
-> bool {
|
||||
return decrypt_data<result_t>(recreate_key<hash_t>(password, cfg), buffer,
|
||||
buffer_size, res);
|
||||
}
|
||||
|
||||
template <typename result_t, typename arr_t, std::size_t arr_size>
|
||||
inline void
|
||||
encrypt_data(const std::array<unsigned char,
|
||||
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> &iv,
|
||||
const std::array<arr_t, arr_size> &key,
|
||||
const unsigned char *buffer, std::size_t buffer_size,
|
||||
result_t &res) {
|
||||
FIFTHGRID_USES_FUNCTION_NAME();
|
||||
|
||||
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_ABYTES> mac{};
|
||||
|
||||
const std::uint32_t size = boost::endian::native_to_big(
|
||||
static_cast<std::uint32_t>(buffer_size + encryption_header_size));
|
||||
|
||||
res.resize(buffer_size + encryption_header_size);
|
||||
|
||||
unsigned long long mac_length{};
|
||||
if (crypto_aead_xchacha20poly1305_ietf_encrypt_detached(
|
||||
reinterpret_cast<unsigned char *>(&res[encryption_header_size]),
|
||||
mac.data(), &mac_length, buffer, buffer_size,
|
||||
reinterpret_cast<const unsigned char *>(&size), sizeof(size), nullptr,
|
||||
iv.data(), key.data()) != 0) {
|
||||
throw fifthgrid::utils::error::create_exception(function_name,
|
||||
{
|
||||
"encryption failed",
|
||||
});
|
||||
}
|
||||
|
||||
std::memcpy(res.data(), iv.data(), iv.size());
|
||||
std::memcpy(&res[iv.size()], mac.data(), mac.size());
|
||||
}
|
||||
|
||||
template <typename result_t, typename arr_t, std::size_t arr_size>
|
||||
inline void encrypt_data(const std::array<arr_t, arr_size> &key,
|
||||
const unsigned char *buffer, std::size_t buffer_size,
|
||||
result_t &res) {
|
||||
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> iv{};
|
||||
randombytes_buf(iv.data(), iv.size());
|
||||
|
||||
encrypt_data<result_t>(iv, key, buffer, buffer_size, res);
|
||||
}
|
||||
|
||||
template <typename result_t, typename hash_t = utils::hash::hash_256_t>
|
||||
inline void encrypt_data(
|
||||
std::string_view password, const unsigned char *buffer,
|
||||
std::size_t buffer_size, result_t &res,
|
||||
std::function<hash_t(const unsigned char *data, std::size_t size)> hasher =
|
||||
utils::hash::default_create_hash<hash_t>()) {
|
||||
encrypt_data<result_t>(generate_key(password, hasher), buffer, buffer_size,
|
||||
res);
|
||||
}
|
||||
|
||||
template <typename result_t, typename hash_t = utils::hash::hash_256_t>
|
||||
inline void encrypt_data(std::string_view password, kdf_config &cfg,
|
||||
const unsigned char *buffer, std::size_t buffer_size,
|
||||
result_t &res) {
|
||||
encrypt_data<result_t>(generate_key<hash_t>(password, cfg), buffer,
|
||||
buffer_size, res);
|
||||
}
|
||||
|
||||
template <typename buffer_t, typename result_t,
|
||||
typename hash_t = utils::hash::hash_256_t>
|
||||
inline void encrypt_data(
|
||||
std::string_view password, const buffer_t &buf, result_t &res,
|
||||
std::function<hash_t(const unsigned char *data, std::size_t size)> hasher =
|
||||
utils::hash::default_create_hash<hash_t>()) {
|
||||
encrypt_data<result_t>(generate_key(password, hasher),
|
||||
reinterpret_cast<const unsigned char *>(buf.data()),
|
||||
buf.size(), res);
|
||||
}
|
||||
|
||||
template <typename buffer_t, typename result_t,
|
||||
typename hash_t = utils::hash::hash_256_t>
|
||||
inline void encrypt_data(std::string_view password, kdf_config &cfg,
|
||||
const buffer_t &buf, result_t &res) {
|
||||
encrypt_data<result_t>(generate_key<hash_t>(password, cfg),
|
||||
reinterpret_cast<const unsigned char *>(buf.data()),
|
||||
buf.size(), res);
|
||||
}
|
||||
|
||||
template <typename buffer_t, typename result_t, typename arr_t,
|
||||
std::size_t arr_size>
|
||||
inline void encrypt_data(const std::array<arr_t, arr_size> &key,
|
||||
const buffer_t &buf, result_t &res) {
|
||||
encrypt_data<result_t>(key,
|
||||
reinterpret_cast<const unsigned char *>(buf.data()),
|
||||
buf.size(), res);
|
||||
}
|
||||
|
||||
template <typename buffer_t, typename result_t, typename arr_t,
|
||||
std::size_t arr_size>
|
||||
inline void
|
||||
encrypt_data(const std::array<unsigned char,
|
||||
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> &iv,
|
||||
const std::array<arr_t, arr_size> &key, const buffer_t &buf,
|
||||
result_t &res) {
|
||||
encrypt_data<result_t>(iv, key,
|
||||
reinterpret_cast<const unsigned char *>(buf.data()),
|
||||
buf.size(), res);
|
||||
}
|
||||
|
||||
using reader_func_t =
|
||||
std::function<bool(data_buffer &cypher_text, std::uint64_t start_offset,
|
||||
std::uint64_t end_offset)>;
|
||||
|
||||
[[nodiscard]] auto read_encrypted_range(const http_range &range,
|
||||
const utils::hash::hash_256_t &key,
|
||||
bool uses_kdf,
|
||||
reader_func_t reader_func,
|
||||
std::uint64_t total_size,
|
||||
data_buffer &data) -> bool;
|
||||
|
||||
[[nodiscard]] auto read_encrypted_range(
|
||||
const http_range &range, const utils::hash::hash_256_t &key, bool uses_kdf,
|
||||
reader_func_t reader_func, std::uint64_t total_size, unsigned char *data,
|
||||
std::size_t size, std::size_t &bytes_read) -> bool;
|
||||
|
||||
[[nodiscard]] inline auto
|
||||
read_encrypted_range(const http_range &range,
|
||||
const utils::hash::hash_256_t &key,
|
||||
reader_func_t reader_func, std::uint64_t total_size,
|
||||
data_buffer &data) -> bool {
|
||||
return read_encrypted_range(range, key, false, reader_func, total_size, data);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline auto read_encrypted_range(
|
||||
const http_range &range, const utils::hash::hash_256_t &key,
|
||||
reader_func_t reader_func, std::uint64_t total_size, unsigned char *data,
|
||||
std::size_t size, std::size_t &bytes_read) -> bool {
|
||||
return read_encrypted_range(range, key, false, reader_func, total_size, data,
|
||||
size, bytes_read);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
auto create_key_argon2id(string_t password, kdf_config &cfg,
|
||||
utils::hash::hash_256_t &key) -> bool {
|
||||
cfg.seal();
|
||||
|
||||
return recreate_key_argon2id(password, cfg, key);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
auto recreate_key_argon2id(string_t password, const kdf_config &cfg,
|
||||
utils::hash::hash_256_t &key) -> bool {
|
||||
return crypto_pwhash(
|
||||
reinterpret_cast<unsigned char *>(key.data()), key.size(),
|
||||
reinterpret_cast<const char *>(password.data()),
|
||||
password.size() * sizeof(typename string_t::value_type),
|
||||
cfg.salt.data(), get_opslimit(cfg.opslimit),
|
||||
get_memlimit(cfg.memlimit), crypto_pwhash_ALG_ARGON2ID13) == 0;
|
||||
}
|
||||
#endif // defined(PROJECT_ENABLE_BOOST)
|
||||
|
||||
template <typename hash_t>
|
||||
inline auto generate_key(
|
||||
std::string_view password,
|
||||
std::function<hash_t(const unsigned char *data, std::size_t size)> hasher)
|
||||
-> hash_t {
|
||||
return hasher(reinterpret_cast<const unsigned char *>(password.data()),
|
||||
password.size());
|
||||
}
|
||||
|
||||
template <typename hash_t>
|
||||
inline auto generate_key(
|
||||
std::wstring_view password,
|
||||
std::function<hash_t(const unsigned char *data, std::size_t size)> hasher)
|
||||
-> hash_t {
|
||||
return hasher(reinterpret_cast<const unsigned char *>(password.data()),
|
||||
password.size() * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
#if defined(PROJECT_ENABLE_BOOST)
|
||||
template <typename hash_t, typename string_t>
|
||||
inline auto generate_key_impl(string_t password, kdf_config &cfg) -> hash_t {
|
||||
FIFTHGRID_USES_FUNCTION_NAME();
|
||||
|
||||
switch (cfg.version) {
|
||||
case kdf_version::v1:
|
||||
switch (cfg.kdf) {
|
||||
case kdf_type::argon2id: {
|
||||
hash_t key{};
|
||||
if (not create_key_argon2id(password, cfg, key)) {
|
||||
throw utils::error::create_exception(
|
||||
function_name, {
|
||||
"failed to generate argon2id key",
|
||||
});
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
default:
|
||||
throw utils::error::create_exception(
|
||||
function_name, {
|
||||
"unsupported kdf type",
|
||||
std::to_string(static_cast<std::uint8_t>(cfg.kdf)),
|
||||
});
|
||||
}
|
||||
|
||||
default:
|
||||
throw utils::error::create_exception(
|
||||
function_name,
|
||||
{
|
||||
"unsupported kdf version",
|
||||
std::to_string(static_cast<std::uint8_t>(cfg.version)),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename hash_t, typename string_t>
|
||||
inline auto recreate_key_impl(string_t password, const kdf_config &cfg)
|
||||
-> hash_t {
|
||||
FIFTHGRID_USES_FUNCTION_NAME();
|
||||
|
||||
switch (cfg.version) {
|
||||
case kdf_version::v1:
|
||||
switch (cfg.kdf) {
|
||||
case kdf_type::argon2id: {
|
||||
hash_t key{};
|
||||
if (not recreate_key_argon2id(password, cfg, key)) {
|
||||
throw utils::error::create_exception(
|
||||
function_name, {
|
||||
"failed to generate argon2id key",
|
||||
});
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
default:
|
||||
throw utils::error::create_exception(
|
||||
function_name, {
|
||||
"unsupported kdf type",
|
||||
std::to_string(static_cast<std::uint8_t>(cfg.kdf)),
|
||||
});
|
||||
}
|
||||
|
||||
default:
|
||||
throw utils::error::create_exception(
|
||||
function_name,
|
||||
{
|
||||
"unsupported kdf version",
|
||||
std::to_string(static_cast<std::uint8_t>(cfg.version)),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename hash_t>
|
||||
inline auto generate_key(std::string_view password, kdf_config &cfg) -> hash_t {
|
||||
return generate_key_impl<hash_t, std::string_view>(password, cfg);
|
||||
}
|
||||
|
||||
template <typename hash_t>
|
||||
inline auto generate_key(std::wstring_view password, kdf_config &cfg)
|
||||
-> hash_t {
|
||||
return generate_key_impl<hash_t, std::wstring_view>(password, cfg);
|
||||
}
|
||||
|
||||
template <typename hash_t>
|
||||
inline auto recreate_key(std::string_view password, const kdf_config &cfg)
|
||||
-> hash_t {
|
||||
return recreate_key_impl<hash_t, std::string_view>(password, cfg);
|
||||
}
|
||||
|
||||
template <typename hash_t>
|
||||
inline auto recreate_key(std::wstring_view password, const kdf_config &cfg)
|
||||
-> hash_t {
|
||||
return recreate_key_impl<hash_t, std::wstring_view>(password, cfg);
|
||||
}
|
||||
|
||||
template <typename hash_t, typename string_t>
|
||||
inline auto detect_and_recreate_key(string_t password, data_cspan header,
|
||||
hash_t &key, std::optional<kdf_config> &cfg)
|
||||
-> bool {
|
||||
if (header.size() >= kdf_config::size()) {
|
||||
kdf_config tmp{};
|
||||
if (kdf_config::from_header(header.first(kdf_config::size()), tmp)) {
|
||||
cfg = tmp;
|
||||
key = recreate_key<hash_t>(password, *cfg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
key = generate_key<hash_t>(password);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename hash_t>
|
||||
inline auto detect_and_recreate_key(std::string_view password,
|
||||
data_cspan header, hash_t &key,
|
||||
std::optional<kdf_config> &cfg) -> bool {
|
||||
return detect_and_recreate_key<hash_t, std::string_view>(password, header,
|
||||
key, cfg);
|
||||
}
|
||||
|
||||
template <typename hash_t>
|
||||
inline auto detect_and_recreate_key(std::wstring_view password,
|
||||
data_cspan header, hash_t &key,
|
||||
std::optional<kdf_config> &cfg) -> bool {
|
||||
return detect_and_recreate_key<hash_t, std::wstring_view>(password, header,
|
||||
key, cfg);
|
||||
}
|
||||
|
||||
#endif // defined(PROJECT_ENABLE_BOOST)
|
||||
} // namespace fifthgrid::utils::encryption
|
||||
|
||||
#if defined(PROJECT_ENABLE_BOOST) && defined(PROJECT_ENABLE_JSON)
|
||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
|
||||
namespace kdf {
|
||||
inline constexpr std::string_view JSON_CHECKSUM{"checksum"};
|
||||
inline constexpr std::string_view JSON_KDF{"kdf"};
|
||||
inline constexpr std::string_view JSON_MEMLIMIT{"memlimit"};
|
||||
inline constexpr std::string_view JSON_OPSLIMIT{"opslimit"};
|
||||
inline constexpr std::string_view JSON_SALT{"salt"};
|
||||
inline constexpr std::string_view JSON_UNIQUE_ID{"unique_id"};
|
||||
inline constexpr std::string_view JSON_VERSION{"version"};
|
||||
} // namespace kdf
|
||||
|
||||
template <>
|
||||
struct adl_serializer<fifthgrid::utils::encryption::kdf_config::salt_t> {
|
||||
static void
|
||||
to_json(json &data,
|
||||
const fifthgrid::utils::encryption::kdf_config::salt_t &value) {
|
||||
data = fifthgrid::utils::collection::to_hex_string(value);
|
||||
}
|
||||
|
||||
static void
|
||||
from_json(const json &data,
|
||||
fifthgrid::utils::encryption::kdf_config::salt_t &value) {
|
||||
FIFTHGRID_USES_FUNCTION_NAME();
|
||||
|
||||
fifthgrid::data_buffer buffer{};
|
||||
if (not fifthgrid::utils::collection::from_hex_string(
|
||||
data.get<std::string>(), buffer)) {
|
||||
throw fifthgrid::utils::error::create_exception(
|
||||
function_name, {
|
||||
"failed to convert hex string to salt",
|
||||
data.get<std::string>(),
|
||||
});
|
||||
}
|
||||
|
||||
if (buffer.size() != value.size()) {
|
||||
throw fifthgrid::utils::error::create_exception(
|
||||
function_name, {
|
||||
"unexpected length for salt after hex conversion",
|
||||
"expected",
|
||||
std::to_string(value.size()),
|
||||
"actual",
|
||||
std::to_string(buffer.size()),
|
||||
});
|
||||
}
|
||||
|
||||
std::copy_n(buffer.begin(), value.size(), value.begin());
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct adl_serializer<fifthgrid::utils::encryption::kdf_config> {
|
||||
static void to_json(json &data,
|
||||
const fifthgrid::utils::encryption::kdf_config &value) {
|
||||
data[kdf::JSON_CHECKSUM] = value.checksum;
|
||||
data[kdf::JSON_KDF] = value.kdf;
|
||||
data[kdf::JSON_MEMLIMIT] = value.memlimit;
|
||||
data[kdf::JSON_OPSLIMIT] = value.opslimit;
|
||||
data[kdf::JSON_SALT] = value.salt;
|
||||
data[kdf::JSON_UNIQUE_ID] = value.unique_id;
|
||||
data[kdf::JSON_VERSION] = value.version;
|
||||
}
|
||||
|
||||
static void from_json(const json &data,
|
||||
fifthgrid::utils::encryption::kdf_config &value) {
|
||||
data.at(kdf::JSON_CHECKSUM).get_to<std::uint64_t>(value.checksum);
|
||||
data.at(kdf::JSON_KDF)
|
||||
.get_to<fifthgrid::utils::encryption::kdf_type>(value.kdf);
|
||||
data.at(kdf::JSON_MEMLIMIT)
|
||||
.get_to<fifthgrid::utils::encryption::memlimit_level>(value.memlimit);
|
||||
data.at(kdf::JSON_OPSLIMIT)
|
||||
.get_to<fifthgrid::utils::encryption::opslimit_level>(value.opslimit);
|
||||
data.at(kdf::JSON_SALT)
|
||||
.get_to<fifthgrid::utils::encryption::kdf_config::salt_t>(value.salt);
|
||||
data.at(kdf::JSON_UNIQUE_ID).get_to<std::uint64_t>(value.unique_id);
|
||||
data.at(kdf::JSON_VERSION)
|
||||
.get_to<fifthgrid::utils::encryption::kdf_version>(value.version);
|
||||
}
|
||||
};
|
||||
NLOHMANN_JSON_NAMESPACE_END
|
||||
#endif // defined(PROJECT_ENABLE_BOOST) && defined(PROJECT_ENABLE_JSON)
|
||||
|
||||
#endif // defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_ENCRYPTION_HPP_
|
||||
164
support/include/utils/error.hpp
Normal file
164
support/include/utils/error.hpp
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_ERROR_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_ERROR_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
namespace fifthgrid::utils::error {
|
||||
[[nodiscard]] auto create_error_message(std::vector<std::string_view> items)
|
||||
-> std::string;
|
||||
|
||||
[[nodiscard]] auto create_error_message(std::string_view function_name,
|
||||
std::vector<std::string_view> items)
|
||||
-> std::string;
|
||||
|
||||
[[nodiscard]] auto create_exception(std::string_view function_name,
|
||||
std::vector<std::string_view> items)
|
||||
-> std::runtime_error;
|
||||
|
||||
struct i_exception_handler {
|
||||
virtual ~i_exception_handler() {}
|
||||
|
||||
i_exception_handler(const i_exception_handler &) noexcept = delete;
|
||||
i_exception_handler(i_exception_handler &&) noexcept = delete;
|
||||
auto operator=(const i_exception_handler &) noexcept = delete;
|
||||
auto operator=(i_exception_handler &&) noexcept = delete;
|
||||
|
||||
#if defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
virtual void handle_debug(std::string_view function_name,
|
||||
std::string_view msg) const = 0;
|
||||
#endif // defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
|
||||
virtual void handle_error(std::string_view function_name,
|
||||
std::string_view msg) const = 0;
|
||||
|
||||
virtual void handle_exception(std::string_view function_name) const = 0;
|
||||
|
||||
virtual void handle_exception(std::string_view function_name,
|
||||
const std::exception &ex) const = 0;
|
||||
|
||||
#if defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
virtual void handle_info(std::string_view function_name,
|
||||
std::string_view msg) const = 0;
|
||||
|
||||
virtual void handle_trace(std::string_view function_name,
|
||||
std::string_view msg) const = 0;
|
||||
|
||||
virtual void handle_warn(std::string_view function_name,
|
||||
std::string_view msg) const = 0;
|
||||
#endif // defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
|
||||
protected:
|
||||
i_exception_handler() = default;
|
||||
};
|
||||
|
||||
struct iostream_exception_handler final : public i_exception_handler {
|
||||
#if defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
void handle_debug(std::string_view function_name,
|
||||
std::string_view msg) const override;
|
||||
#endif // defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
|
||||
void handle_error(std::string_view function_name,
|
||||
std::string_view msg) const override;
|
||||
|
||||
void handle_exception(std::string_view function_name) const override;
|
||||
|
||||
void handle_exception(std::string_view function_name,
|
||||
const std::exception &ex) const override;
|
||||
|
||||
#if defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
void handle_info(std::string_view function_name,
|
||||
std::string_view msg) const override;
|
||||
|
||||
void handle_trace(std::string_view function_name,
|
||||
std::string_view msg) const override;
|
||||
|
||||
void handle_warn(std::string_view function_name,
|
||||
std::string_view msg) const override;
|
||||
#endif // defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
};
|
||||
|
||||
#if defined(PROJECT_ENABLE_SPDLOG) && defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
struct spdlog_exception_handler final : public i_exception_handler {
|
||||
void handle_debug(std::string_view function_name,
|
||||
std::string_view msg) const override;
|
||||
|
||||
void handle_error(std::string_view function_name,
|
||||
std::string_view msg) const override;
|
||||
|
||||
void handle_exception(std::string_view function_name) const override;
|
||||
|
||||
void handle_exception(std::string_view function_name,
|
||||
const std::exception &ex) const override;
|
||||
|
||||
void handle_info(std::string_view function_name,
|
||||
std::string_view msg) const override;
|
||||
|
||||
void handle_trace(std::string_view function_name,
|
||||
std::string_view msg) const override;
|
||||
|
||||
void handle_warn(std::string_view function_name,
|
||||
std::string_view msg) const override;
|
||||
|
||||
private:
|
||||
iostream_exception_handler fallback{};
|
||||
};
|
||||
#endif // defined(PROJECT_ENABLE_SPDLOG) && defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
|
||||
#if defined(PROJECT_ENABLE_SPDLOG) && defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
inline const spdlog_exception_handler default_exception_handler{};
|
||||
#else // !defined(PROJECT_ENABLE_SPDLOG) || !defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
inline const iostream_exception_handler default_exception_handler{};
|
||||
#endif // defined(PROJECT_ENABLE_SPDLOG) && defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
|
||||
#if defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
void handle_debug(std::string_view function_name, std::string_view msg);
|
||||
#endif // defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
|
||||
void handle_error(std::string_view function_name, std::string_view msg);
|
||||
|
||||
void handle_exception(std::string_view function_name);
|
||||
|
||||
void handle_exception(std::string_view function_name, const std::exception &ex);
|
||||
|
||||
#if defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
void handle_info(std::string_view function_name, std::string_view msg);
|
||||
|
||||
void handle_trace(std::string_view function_name, std::string_view msg);
|
||||
|
||||
void handle_warn(std::string_view function_name, std::string_view msg);
|
||||
#endif // defined(PROJECT_ENABLE_V2_ERRORS)
|
||||
|
||||
void set_exception_handler(const i_exception_handler *handler);
|
||||
|
||||
#if defined(PROJECT_ENABLE_TESTING)
|
||||
extern std::atomic<const i_exception_handler *> exception_handler;
|
||||
|
||||
[[nodiscard]] inline auto get_exception_handler()
|
||||
-> const i_exception_handler * {
|
||||
return exception_handler;
|
||||
}
|
||||
#endif // defined(PROJECT_ENABLE_TESTING)
|
||||
} // namespace fifthgrid::utils::error
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_ERROR_HPP_
|
||||
190
support/include/utils/file.hpp
Normal file
190
support/include/utils/file.hpp
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_FILE_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_FILE_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/types/file/i_directory.hpp"
|
||||
#include "utils/types/file/i_file.hpp"
|
||||
#include "utils/types/file/i_fs_item.hpp"
|
||||
|
||||
namespace fifthgrid::utils::directory {
|
||||
[[nodiscard]] auto temp() -> std::string;
|
||||
}
|
||||
|
||||
namespace fifthgrid::utils::file {
|
||||
[[nodiscard]] auto change_to_process_directory() -> bool;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto create_temp_name(std::string_view file_part) -> std::string;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto create_temp_name(std::wstring_view file_part)
|
||||
-> std::wstring;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] inline auto
|
||||
directory_exists_in_path(std::string_view path, std::string_view sub_directory)
|
||||
-> bool;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] inline auto
|
||||
directory_exists_in_path(std::wstring_view path,
|
||||
std::wstring_view sub_directory) -> bool;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] inline auto file_exists_in_path(std::string_view path,
|
||||
std::string_view file_name)
|
||||
-> bool;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] inline auto file_exists_in_path(std::wstring_view path,
|
||||
std::wstring_view file_name)
|
||||
-> bool;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto get_free_drive_space(std::string_view path)
|
||||
-> std::optional<std::uint64_t>;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto get_free_drive_space(std::wstring_view path)
|
||||
-> std::optional<std::uint64_t>;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto get_time(std::string_view path, time_type type)
|
||||
-> std::optional<std::uint64_t>;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto get_time(std::wstring_view path, time_type type)
|
||||
-> std::optional<std::uint64_t>;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto get_times(std::string_view path)
|
||||
-> std::optional<file_times>;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto get_times(std::wstring_view path)
|
||||
-> std::optional<file_times>;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto get_total_drive_space(std::string_view path)
|
||||
-> std::optional<std::uint64_t>;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto get_total_drive_space(std::wstring_view path)
|
||||
-> std::optional<std::uint64_t>;
|
||||
|
||||
#if defined(PROJECT_ENABLE_LIBDSM)
|
||||
[[nodiscard]] auto
|
||||
smb_create_and_validate_relative_path(std::string_view smb_path,
|
||||
std::string_view rel_path) -> std::string;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto smb_create_relative_path(std::string_view smb_path)
|
||||
-> std::string;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto smb_create_search_path(std::string_view smb_path)
|
||||
-> std::string;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto smb_create_smb_path(std::string_view smb_path,
|
||||
std::string_view rel_path)
|
||||
-> std::string;
|
||||
|
||||
[[nodiscard]] auto smb_get_parent_path(std::string_view smb_path)
|
||||
-> std::string;
|
||||
|
||||
[[nodiscard]] auto smb_get_root_path(std::string_view smb_path) -> std::string;
|
||||
|
||||
[[nodiscard]] auto smb_get_unc_path(std::string_view smb_path) -> std::string;
|
||||
|
||||
[[nodiscard]] auto smb_get_uri_path(std::string_view smb_path) -> std::string;
|
||||
|
||||
[[nodiscard]] auto smb_get_uri_path(std::string_view smb_path,
|
||||
std::string_view user,
|
||||
std::string_view password) -> std::string;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto smb_parent_is_same(std::string_view smb_path1,
|
||||
std::string_view smb_path2) -> bool;
|
||||
|
||||
#define SMB_MOD_RW2 \
|
||||
(SMB_MOD_READ | SMB_MOD_WRITE | SMB_MOD_READ_EXT | SMB_MOD_WRITE_EXT | \
|
||||
SMB_MOD_READ_ATTR | SMB_MOD_WRITE_ATTR | SMB_MOD_READ_CTL)
|
||||
#endif // defined(PROJECT_ENABLE_LIBDSM)
|
||||
|
||||
#if defined(PROJECT_ENABLE_JSON)
|
||||
#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto
|
||||
read_json_file(std::string_view path, nlohmann::json &data,
|
||||
std::optional<std::string_view> password = std::nullopt) -> bool;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto
|
||||
read_json_file(std::wstring_view path, nlohmann::json &data,
|
||||
std::optional<std::wstring_view> password = std::nullopt)
|
||||
-> bool;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto
|
||||
write_json_file(std::string_view path, const nlohmann::json &data,
|
||||
std::optional<std::string_view> password = std::nullopt)
|
||||
-> bool;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto
|
||||
write_json_file(std::wstring_view path, const nlohmann::json &data,
|
||||
std::optional<std::wstring_view> password = std::nullopt)
|
||||
-> bool;
|
||||
#else // !defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto read_json_file(std::string_view path, nlohmann::json &data)
|
||||
-> bool;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto read_json_file(std::wstring_view path, nlohmann::json &data)
|
||||
-> bool;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto write_json_file(std::string_view path,
|
||||
const nlohmann::json &data) -> bool;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] auto write_json_file(std::wstring_view path,
|
||||
const nlohmann::json &data) -> bool;
|
||||
#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
|
||||
#endif // defined(PROJECT_ENABLE_JSON)
|
||||
} // namespace fifthgrid::utils::file
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_FILE_HPP_
|
||||
|
||||
#include "utils/file_directory.hpp"
|
||||
#include "utils/file_enc_file.hpp"
|
||||
#include "utils/file_file.hpp"
|
||||
#include "utils/file_smb_directory.hpp"
|
||||
#include "utils/file_smb_file.hpp"
|
||||
#include "utils/file_thread_file.hpp"
|
||||
124
support/include/utils/file_directory.hpp
Normal file
124
support/include/utils/file_directory.hpp
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_FILE_DIRECTORY_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_FILE_DIRECTORY_HPP_
|
||||
|
||||
#include "utils/file.hpp"
|
||||
|
||||
namespace fifthgrid::utils::file {
|
||||
class directory final : public i_directory {
|
||||
public:
|
||||
using directory_t = std::unique_ptr<directory>;
|
||||
|
||||
directory() noexcept = default;
|
||||
|
||||
directory(std::string_view path, stop_type *stop_requested = nullptr)
|
||||
: path_(utils::path::absolute(path)), stop_requested_(stop_requested) {}
|
||||
|
||||
directory(std::wstring_view path, stop_type *stop_requested = nullptr)
|
||||
: path_(utils::path::absolute(utils::string::to_utf8(path))),
|
||||
stop_requested_(stop_requested) {}
|
||||
|
||||
directory(const directory &) noexcept = delete;
|
||||
|
||||
directory(directory &&move_dir) noexcept = default;
|
||||
|
||||
~directory() override = default;
|
||||
|
||||
private:
|
||||
std::string path_;
|
||||
stop_type *stop_requested_{nullptr};
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto copy_to(std::string_view new_path, bool overwrite) const
|
||||
-> bool override;
|
||||
|
||||
[[nodiscard]] auto count(bool recursive = false) const
|
||||
-> std::uint64_t override;
|
||||
|
||||
[[nodiscard]] auto create_directory(std::string_view path = "") const
|
||||
-> fs_directory_t override;
|
||||
|
||||
[[nodiscard]] auto create_file(std::string_view file_name,
|
||||
bool read_only) const -> fs_file_t override;
|
||||
|
||||
[[nodiscard]] auto exists() const -> bool override;
|
||||
|
||||
[[nodiscard]] auto get_directory(std::string_view path) const
|
||||
-> fs_directory_t override;
|
||||
|
||||
[[nodiscard]] auto get_directories() const
|
||||
-> std::vector<fs_directory_t> override;
|
||||
|
||||
[[nodiscard]] auto get_file(std::string_view path) const
|
||||
-> fs_file_t override;
|
||||
|
||||
[[nodiscard]] auto get_files() const -> std::vector<fs_file_t> override;
|
||||
|
||||
[[nodiscard]] auto get_items() const -> std::vector<fs_item_t> override;
|
||||
|
||||
[[nodiscard]] auto get_path() const -> std::string override { return path_; }
|
||||
|
||||
[[nodiscard]] auto is_stop_requested() const -> bool override;
|
||||
|
||||
[[nodiscard]] auto is_symlink() const -> bool override;
|
||||
|
||||
[[nodiscard]] auto move_to(std::string_view new_path) -> bool override;
|
||||
|
||||
[[nodiscard]] auto remove() -> bool override;
|
||||
|
||||
[[nodiscard]] auto remove_recursively() -> bool override;
|
||||
|
||||
[[nodiscard]] auto size(bool recursive = false) const
|
||||
-> std::uint64_t override;
|
||||
|
||||
public:
|
||||
auto operator=(const directory &) noexcept -> directory & = delete;
|
||||
|
||||
auto operator=(directory &&move_dir) noexcept -> directory & = default;
|
||||
|
||||
[[nodiscard]] operator bool() const override { return exists(); }
|
||||
};
|
||||
|
||||
// INFO: has test
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto directory_exists_in_path_t(
|
||||
std::basic_string_view<typename string_t::value_type> path,
|
||||
std::basic_string_view<typename string_t::value_type> sub_directory)
|
||||
-> bool {
|
||||
return directory(utils::path::combine(path, {sub_directory})).exists();
|
||||
}
|
||||
|
||||
// INFO: has test
|
||||
inline auto directory_exists_in_path(std::string_view path,
|
||||
std::string_view sub_directory) -> bool {
|
||||
return directory_exists_in_path_t<std::string>(path, sub_directory);
|
||||
}
|
||||
|
||||
// INFO: has test
|
||||
inline auto directory_exists_in_path(std::wstring_view path,
|
||||
std::wstring_view sub_directory) -> bool {
|
||||
return directory_exists_in_path_t<std::wstring>(path, sub_directory);
|
||||
}
|
||||
} // namespace fifthgrid::utils::file
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_FILE_DIRECTORY_HPP_
|
||||
124
support/include/utils/file_enc_file.hpp
Normal file
124
support/include/utils/file_enc_file.hpp
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_FILE_ENC_FILE_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_FILE_ENC_FILE_HPP_
|
||||
#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
|
||||
|
||||
#include "utils/file.hpp"
|
||||
|
||||
namespace fifthgrid::utils::file {
|
||||
class enc_file final : public i_file {
|
||||
public:
|
||||
[[nodiscard]] static auto attach_file(fs_file_t file) -> fs_file_t;
|
||||
|
||||
public:
|
||||
enc_file() noexcept = default;
|
||||
|
||||
protected:
|
||||
enc_file(fs_file_t file);
|
||||
|
||||
public:
|
||||
enc_file(const enc_file &) = delete;
|
||||
|
||||
enc_file(enc_file &&move_file) noexcept : file_(std::move(move_file.file_)) {}
|
||||
|
||||
~enc_file() override { close(); }
|
||||
|
||||
private:
|
||||
fs_file_t file_;
|
||||
std::string encryption_token_;
|
||||
|
||||
public:
|
||||
void close() override;
|
||||
|
||||
[[nodiscard]] auto copy_to(std::string_view new_path, bool overwrite) const
|
||||
-> bool override;
|
||||
|
||||
[[nodiscard]] auto exists() const -> bool override { return file_->exists(); }
|
||||
|
||||
void flush() const override;
|
||||
|
||||
[[nodiscard]] auto get_handle() const -> native_handle override {
|
||||
return file_->get_handle();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_path() const -> std::string override {
|
||||
return file_->get_path();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_read_buffer_size() const -> std::uint32_t override {
|
||||
return file_->get_read_buffer_size();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_time(time_type type) const
|
||||
-> std::optional<std::uint64_t> override {
|
||||
return file_->get_time(type);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_read_only() const -> bool override {
|
||||
return file_->is_read_only();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_symlink() const -> bool override {
|
||||
return file_->is_symlink();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto move_to(std::string_view new_path) -> bool override;
|
||||
|
||||
[[nodiscard]] auto read(unsigned char *data, std::size_t to_read,
|
||||
std::uint64_t offset,
|
||||
std::size_t *total_read = nullptr) -> bool override;
|
||||
|
||||
[[nodiscard]] auto remove() -> bool override;
|
||||
|
||||
auto set_read_buffer_size(std::uint32_t size) -> std::uint32_t override {
|
||||
return file_->set_read_buffer_size(size);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto size() const -> std::optional<std::uint64_t> override;
|
||||
|
||||
[[nodiscard]] auto truncate(std::size_t size) -> bool override;
|
||||
|
||||
[[nodiscard]] auto write(const unsigned char *data, std::size_t to_write,
|
||||
std::size_t offset,
|
||||
std::size_t *total_written = nullptr)
|
||||
-> bool override;
|
||||
|
||||
public:
|
||||
[[nodiscard]] operator bool() const override {
|
||||
return static_cast<bool>(*file_);
|
||||
}
|
||||
|
||||
auto operator=(const enc_file &) noexcept -> enc_file & = delete;
|
||||
|
||||
auto operator=(enc_file &&move_file) noexcept -> enc_file & {
|
||||
if (&move_file != this) {
|
||||
file_ = std::move(move_file.file_);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
} // namespace fifthgrid::utils::file
|
||||
|
||||
#endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_FILE_ENC_FILE_HPP_
|
||||
176
support/include/utils/file_file.hpp
Normal file
176
support/include/utils/file_file.hpp
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_FILE_FILE_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_FILE_FILE_HPP_
|
||||
|
||||
#include "utils/file.hpp"
|
||||
|
||||
namespace fifthgrid::utils::file {
|
||||
class file final : public i_file {
|
||||
public:
|
||||
// [[nodiscard]] static auto
|
||||
// attach_file(native_handle handle,
|
||||
// bool read_only = false) -> fs_file_t;
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] static auto open_file(std::string_view path,
|
||||
bool read_only = false) -> fs_file_t;
|
||||
|
||||
[[nodiscard]] static auto open_file(std::wstring_view path,
|
||||
bool read_only = false) -> fs_file_t {
|
||||
return open_file(utils::string::to_utf8(path), read_only);
|
||||
}
|
||||
|
||||
// INFO: has test
|
||||
[[nodiscard]] static auto
|
||||
open_or_create_file(std::string_view path,
|
||||
bool read_only = false) -> fs_file_t;
|
||||
|
||||
[[nodiscard]] static auto
|
||||
open_or_create_file(std::wstring_view path,
|
||||
bool read_only = false) -> fs_file_t {
|
||||
return open_or_create_file(utils::string::to_utf8(path), read_only);
|
||||
}
|
||||
|
||||
public:
|
||||
file() noexcept = default;
|
||||
|
||||
file(std::string_view path)
|
||||
: file_(nullptr), path_(utils::path::absolute(path)) {}
|
||||
|
||||
file(std::wstring_view path)
|
||||
: file_(nullptr),
|
||||
path_(utils::path::absolute(utils::string::to_utf8(path))) {}
|
||||
|
||||
private:
|
||||
file(file_t file_ptr, std::string_view path, bool read_only)
|
||||
: file_(std::move(file_ptr)), path_(path), read_only_(read_only) {}
|
||||
|
||||
public:
|
||||
file(const file &) = delete;
|
||||
|
||||
file(file &&move_file) noexcept
|
||||
: file_(std::move(move_file.file_)),
|
||||
path_(std::move(move_file.path_)),
|
||||
read_only_(move_file.read_only_) {}
|
||||
|
||||
~file() override { close(); }
|
||||
|
||||
private:
|
||||
file_t file_;
|
||||
std::string path_;
|
||||
bool read_only_{false};
|
||||
|
||||
private:
|
||||
std::atomic_uint32_t read_buffer_size{65536U};
|
||||
|
||||
private:
|
||||
void open();
|
||||
|
||||
public:
|
||||
void close() override;
|
||||
|
||||
[[nodiscard]] auto copy_to(std::string_view new_path,
|
||||
bool overwrite) const -> bool override;
|
||||
|
||||
[[nodiscard]] auto exists() const -> bool override;
|
||||
|
||||
void flush() const override;
|
||||
|
||||
[[nodiscard]] auto get_handle() const -> native_handle override;
|
||||
|
||||
[[nodiscard]] auto get_path() const -> std::string override { return path_; }
|
||||
|
||||
[[nodiscard]] auto get_read_buffer_size() const -> std::uint32_t override {
|
||||
return read_buffer_size;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_read_only() const -> bool override {
|
||||
return read_only_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_symlink() const -> bool override;
|
||||
|
||||
[[nodiscard]] auto move_to(std::string_view new_path) -> bool override;
|
||||
|
||||
[[nodiscard]] auto read(unsigned char *data, std::size_t to_read,
|
||||
std::uint64_t offset,
|
||||
std::size_t *total_read = nullptr) -> bool override;
|
||||
|
||||
[[nodiscard]] auto remove() -> bool override;
|
||||
|
||||
auto set_read_buffer_size(std::uint32_t size) -> std::uint32_t override {
|
||||
read_buffer_size = size;
|
||||
return read_buffer_size;
|
||||
}
|
||||
|
||||
#if defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
[[nodiscard]] auto sha256() -> std::optional<std::string>;
|
||||
|
||||
#endif // defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
|
||||
[[nodiscard]] auto size() const -> std::optional<std::uint64_t> override;
|
||||
|
||||
[[nodiscard]] auto truncate(std::size_t size) -> bool override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
write(const unsigned char *data, std::size_t to_write, std::size_t offset,
|
||||
std::size_t *total_written = nullptr) -> bool override;
|
||||
|
||||
public:
|
||||
auto operator=(const file &) noexcept -> file & = delete;
|
||||
|
||||
auto operator=(file &&move_file) noexcept -> file & {
|
||||
if (&move_file != this) {
|
||||
file_ = std::move(move_file.file_);
|
||||
path_ = std::move(move_file.path_);
|
||||
read_only_ = move_file.read_only_;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] operator bool() const override { return file_ != nullptr; }
|
||||
};
|
||||
|
||||
// INFO: has test
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto file_exists_in_path_t(
|
||||
std::basic_string_view<typename string_t::value_type> path,
|
||||
std::basic_string_view<typename string_t::value_type> file_name) -> bool {
|
||||
return file(utils::path::combine(path, {file_name})).exists();
|
||||
}
|
||||
|
||||
// INFO: has test
|
||||
inline auto file_exists_in_path(std::string_view path,
|
||||
std::string_view file_name) -> bool {
|
||||
return file_exists_in_path_t<std::string>(path, file_name);
|
||||
}
|
||||
|
||||
// INFO: has test
|
||||
inline auto file_exists_in_path(std::wstring_view path,
|
||||
std::wstring_view file_name) -> bool {
|
||||
return file_exists_in_path_t<std::wstring>(path, file_name);
|
||||
}
|
||||
} // namespace fifthgrid::utils::file
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_FILE_FILE_HPP_
|
||||
140
support/include/utils/file_smb_directory.hpp
Normal file
140
support/include/utils/file_smb_directory.hpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_FILE_SMB_DIRECTORY_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_FILE_SMB_DIRECTORY_HPP_
|
||||
#if defined(PROJECT_ENABLE_LIBDSM)
|
||||
|
||||
#include "utils/file.hpp"
|
||||
|
||||
namespace fifthgrid::utils::file {
|
||||
class smb_directory final : public i_directory {
|
||||
public:
|
||||
using smb_directory_t = std::unique_ptr<smb_directory>;
|
||||
|
||||
[[nodiscard]] static auto
|
||||
open(std::string_view host, std::string_view user, std::string_view password,
|
||||
std::string_view path,
|
||||
stop_type *stop_requested = nullptr) -> smb_directory_t;
|
||||
|
||||
[[nodiscard]] static auto
|
||||
open(std::wstring_view host, std::wstring_view user,
|
||||
std::wstring_view password, std::wstring_view path,
|
||||
stop_type *stop_requested = nullptr) -> smb_directory_t;
|
||||
|
||||
public:
|
||||
smb_directory() noexcept = default;
|
||||
|
||||
smb_directory(const smb_directory &) noexcept = delete;
|
||||
|
||||
smb_directory(smb_directory &&) noexcept = default;
|
||||
|
||||
~smb_directory() override = default;
|
||||
|
||||
private:
|
||||
smb_directory(std::string path, smb_session_t session,
|
||||
std::string_view share_name, smb_tid tid,
|
||||
stop_type *stop_requested)
|
||||
: path_(std::move(path)),
|
||||
session_(std::move(session)),
|
||||
share_name_(share_name),
|
||||
tid_(tid),
|
||||
stop_requested_(stop_requested) {}
|
||||
|
||||
private:
|
||||
std::string path_{};
|
||||
smb_session_t session_{};
|
||||
std::string share_name_{};
|
||||
smb_tid tid_{};
|
||||
stop_type *stop_requested_{nullptr};
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto
|
||||
count(bool recursive = false) const -> std::uint64_t override;
|
||||
|
||||
[[nodiscard]] auto copy_to(std::string_view new_path,
|
||||
bool overwrite) const -> bool override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
create_directory(std::string_view path = "") const -> fs_directory_t override;
|
||||
|
||||
[[nodiscard]] auto create_file(std::string_view file_name,
|
||||
bool read_only) const -> fs_file_t override;
|
||||
|
||||
[[nodiscard]] auto exists() const -> bool override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_directory(std::string_view path) const -> fs_directory_t override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_directories() const -> std::vector<fs_directory_t> override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_file(std::string_view path) const -> fs_file_t override;
|
||||
|
||||
[[nodiscard]] auto get_files() const -> std::vector<fs_file_t> override;
|
||||
|
||||
[[nodiscard]] auto get_items() const -> std::vector<fs_item_t> override;
|
||||
|
||||
[[nodiscard]] auto get_path() const -> std::string override { return path_; }
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_time(time_type type) const -> std::optional<std::uint64_t> override;
|
||||
|
||||
[[nodiscard]] auto get_unc_path() const -> std::string {
|
||||
return smb_get_unc_path(path_);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_uri_path() const -> std::string {
|
||||
return smb_get_uri_path(path_);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_uri_path(std::string_view user,
|
||||
std::string_view password) const -> std::string {
|
||||
return smb_get_uri_path(path_, user, password);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_stop_requested() const -> bool override;
|
||||
|
||||
[[nodiscard]] auto is_symlink() const -> bool override;
|
||||
|
||||
[[nodiscard]] auto move_to(std::string_view new_path) -> bool override;
|
||||
|
||||
[[nodiscard]] auto remove() -> bool override;
|
||||
|
||||
[[nodiscard]] auto remove_recursively() -> bool override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
size(bool recursive = false) const -> std::uint64_t override;
|
||||
|
||||
public:
|
||||
auto operator=(const smb_directory &) noexcept -> smb_directory & = delete;
|
||||
|
||||
auto
|
||||
operator=(smb_directory &&move_dir) noexcept -> smb_directory & = default;
|
||||
|
||||
[[nodiscard]] operator bool() const override { return session_ != nullptr; }
|
||||
};
|
||||
} // namespace fifthgrid::utils::file
|
||||
|
||||
#endif // defined(PROJECT_ENABLE_LIBDSM)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_FILE_SMB_DIRECTORY_HPP_
|
||||
157
support/include/utils/file_smb_file.hpp
Normal file
157
support/include/utils/file_smb_file.hpp
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_FILE_SMB_FILE_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_FILE_SMB_FILE_HPP_
|
||||
#if defined(PROJECT_ENABLE_LIBDSM)
|
||||
|
||||
#include "utils/file.hpp"
|
||||
|
||||
namespace fifthgrid::utils::file {
|
||||
class smb_file final : public i_file {
|
||||
public:
|
||||
smb_file() = default;
|
||||
|
||||
smb_file(std::optional<smb_fd> fd, std::string path, smb_session_t session,
|
||||
std::string_view share_name, smb_tid tid)
|
||||
: fd_(std::move(fd)),
|
||||
path_(std::move(path)),
|
||||
session_(std::move(session)),
|
||||
share_name_(share_name),
|
||||
tid_(tid) {}
|
||||
|
||||
smb_file(const smb_file &) = delete;
|
||||
|
||||
smb_file(smb_file &&f) noexcept
|
||||
: fd_(std::move(f.fd_)),
|
||||
path_(std::move(f.path_)),
|
||||
read_buffer_size(f.get_read_buffer_size()),
|
||||
read_only_(f.read_only_),
|
||||
session_(std::move(f.session_)),
|
||||
share_name_(std::move(f.share_name_)),
|
||||
tid_(f.tid_) {}
|
||||
|
||||
~smb_file() override { close(); }
|
||||
|
||||
private:
|
||||
std::optional<smb_fd> fd_;
|
||||
std::string path_;
|
||||
std::atomic_uint32_t read_buffer_size{65536U};
|
||||
bool read_only_;
|
||||
smb_session_t session_;
|
||||
std::string share_name_;
|
||||
smb_tid tid_;
|
||||
|
||||
public:
|
||||
void close() override;
|
||||
|
||||
[[nodiscard]] auto copy_to(std::string_view new_path,
|
||||
bool overwrite) const -> bool override;
|
||||
|
||||
[[nodiscard]] auto exists() const -> bool override;
|
||||
|
||||
void flush() const override;
|
||||
|
||||
[[nodiscard]] auto get_handle() const -> native_handle override {
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_path() const -> std::string override { return path_; }
|
||||
|
||||
[[nodiscard]] auto get_read_buffer_size() const -> std::uint32_t override {
|
||||
return read_buffer_size;
|
||||
}
|
||||
|
||||
[[nodiscard]] static auto
|
||||
get_time(smb_session *session, smb_tid tid, std::string path,
|
||||
time_type type) -> std::optional<std::uint64_t>;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_time(time_type type) const -> std::optional<std::uint64_t> override {
|
||||
return get_time(session_.get(), tid_, path_, type);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_unc_path() const -> std::string {
|
||||
return smb_get_unc_path(path_);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_uri_path() const -> std::string {
|
||||
return smb_get_uri_path(path_);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_uri_path(std::string_view user,
|
||||
std::string_view password) const -> std::string {
|
||||
return smb_get_uri_path(path_, user, password);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_read_only() const -> bool override {
|
||||
return read_only_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_symlink() const -> bool override;
|
||||
|
||||
[[nodiscard]] auto move_to(std::string_view new_path) -> bool override;
|
||||
|
||||
[[nodiscard]] auto open(bool read_only) -> bool;
|
||||
|
||||
[[nodiscard]] auto read(unsigned char *data, std::size_t to_read,
|
||||
std::uint64_t offset,
|
||||
std::size_t *total_read = nullptr) -> bool override;
|
||||
|
||||
[[nodiscard]] auto remove() -> bool override;
|
||||
|
||||
auto set_read_buffer_size(std::uint32_t size) -> std::uint32_t override {
|
||||
read_buffer_size = size;
|
||||
return read_buffer_size;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto size() const -> std::optional<std::uint64_t> override;
|
||||
|
||||
[[nodiscard]] auto truncate(std::size_t size) -> bool override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
write(const unsigned char *data, std::size_t to_write, std::size_t offset,
|
||||
std::size_t *total_written = nullptr) -> bool override;
|
||||
|
||||
public:
|
||||
auto operator=(const smb_file &) noexcept -> smb_file & = delete;
|
||||
|
||||
auto operator=(smb_file &&move_file) noexcept -> smb_file & {
|
||||
if (this != &move_file) {
|
||||
fd_ = std::move(move_file.fd_);
|
||||
path_ = std::move(move_file.path_);
|
||||
read_buffer_size = move_file.get_read_buffer_size();
|
||||
read_only_ = move_file.read_only_;
|
||||
session_ = std::move(move_file.session_);
|
||||
share_name_ = std::move(move_file.share_name_);
|
||||
tid_ = move_file.tid_;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] operator bool() const override { return fd_.has_value(); }
|
||||
};
|
||||
} // namespace fifthgrid::utils::file
|
||||
|
||||
#endif // defined(PROJECT_ENABLE_LIBDSM)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_FILE_SMB_FILE_HPP_
|
||||
180
support/include/utils/file_thread_file.hpp
Normal file
180
support/include/utils/file_thread_file.hpp
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_FILE_THREAD_FILE_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_FILE_THREAD_FILE_HPP_
|
||||
|
||||
#include "utils/file.hpp"
|
||||
|
||||
namespace fifthgrid::utils::file {
|
||||
class thread_file final : public i_file {
|
||||
public:
|
||||
// [[nodiscard]] static auto
|
||||
// attach_file(native_handle handle,
|
||||
// bool read_only = false) -> fs_file_t;
|
||||
|
||||
[[nodiscard]] static auto attach_file(fs_file_t file) -> fs_file_t;
|
||||
|
||||
[[nodiscard]] static auto open_file(std::string_view path,
|
||||
bool read_only = false) -> fs_file_t;
|
||||
|
||||
[[nodiscard]] static auto open_file(std::wstring_view path,
|
||||
bool read_only = false) -> fs_file_t {
|
||||
return open_file(utils::string::to_utf8(path), read_only);
|
||||
}
|
||||
|
||||
[[nodiscard]] static auto
|
||||
open_or_create_file(std::string_view path,
|
||||
bool read_only = false) -> fs_file_t;
|
||||
|
||||
[[nodiscard]] static auto
|
||||
open_or_create_file(std::wstring_view path,
|
||||
bool read_only = false) -> fs_file_t {
|
||||
return open_or_create_file(utils::string::to_utf8(path), read_only);
|
||||
}
|
||||
|
||||
public:
|
||||
thread_file() noexcept = default;
|
||||
|
||||
thread_file(std::string_view path);
|
||||
|
||||
thread_file(std::wstring_view path);
|
||||
|
||||
protected:
|
||||
thread_file(fs_file_t file);
|
||||
|
||||
public:
|
||||
thread_file(const thread_file &) = delete;
|
||||
|
||||
thread_file(thread_file &&move_file) noexcept
|
||||
: file_(std::move(move_file.file_)) {}
|
||||
|
||||
~thread_file() override;
|
||||
|
||||
private:
|
||||
using action_t = std::function<bool()>;
|
||||
|
||||
struct io_item final {
|
||||
action_t action;
|
||||
bool complete{false};
|
||||
std::unique_ptr<std::mutex> mtx{
|
||||
std::make_unique<std::mutex>(),
|
||||
};
|
||||
mutable std::unique_ptr<std::condition_variable> notify{
|
||||
std::make_unique<std::condition_variable>(),
|
||||
};
|
||||
bool success{false};
|
||||
|
||||
void done(bool result);
|
||||
|
||||
void wait() const;
|
||||
};
|
||||
|
||||
private:
|
||||
fs_file_t file_;
|
||||
|
||||
private:
|
||||
mutable std::vector<std::shared_ptr<io_item>> actions_;
|
||||
mutable std::unique_ptr<std::thread> io_thread_;
|
||||
mutable std::unique_ptr<std::mutex> mtx_{std::make_unique<std::mutex>()};
|
||||
mutable std::unique_ptr<std::condition_variable> notify_{
|
||||
std::make_unique<std::condition_variable>(),
|
||||
};
|
||||
stop_type stop_requested_{false};
|
||||
|
||||
private:
|
||||
auto do_io(action_t action) const -> bool;
|
||||
|
||||
void thread_func() const;
|
||||
|
||||
public:
|
||||
void close() override;
|
||||
|
||||
[[nodiscard]] auto copy_to(std::string_view new_path,
|
||||
bool overwrite) const -> bool override;
|
||||
|
||||
[[nodiscard]] auto exists() const -> bool override { return file_->exists(); }
|
||||
|
||||
void flush() const override;
|
||||
|
||||
[[nodiscard]] auto get_handle() const -> native_handle override {
|
||||
return file_->get_handle();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_path() const -> std::string override {
|
||||
return file_->get_path();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_read_buffer_size() const -> std::uint32_t override {
|
||||
return file_->get_read_buffer_size();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_time(time_type type) const -> std::optional<std::uint64_t> override {
|
||||
return file_->get_time(type);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_read_only() const -> bool override {
|
||||
return file_->is_read_only();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_symlink() const -> bool override {
|
||||
return file_->is_symlink();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto move_to(std::string_view new_path) -> bool override;
|
||||
|
||||
[[nodiscard]] auto read(unsigned char *data, std::size_t to_read,
|
||||
std::uint64_t offset,
|
||||
std::size_t *total_read = nullptr) -> bool override;
|
||||
|
||||
[[nodiscard]] auto remove() -> bool override;
|
||||
|
||||
auto set_read_buffer_size(std::uint32_t size) -> std::uint32_t override {
|
||||
return file_->set_read_buffer_size(size);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto size() const -> std::optional<std::uint64_t> override;
|
||||
|
||||
[[nodiscard]] auto truncate(std::size_t size) -> bool override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
write(const unsigned char *data, std::size_t to_write, std::size_t offset,
|
||||
std::size_t *total_written = nullptr) -> bool override;
|
||||
|
||||
public:
|
||||
[[nodiscard]] operator bool() const override {
|
||||
return static_cast<bool>(*file_);
|
||||
}
|
||||
|
||||
auto operator=(const thread_file &) noexcept -> thread_file & = delete;
|
||||
|
||||
auto operator=(thread_file &&move_file) noexcept -> thread_file & {
|
||||
if (&move_file != this) {
|
||||
file_ = std::move(move_file.file_);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
} // namespace fifthgrid::utils::file
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_FILE_THREAD_FILE_HPP_
|
||||
243
support/include/utils/hash.hpp
Normal file
243
support/include/utils/hash.hpp
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_HASH_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_HASH_HPP_
|
||||
#if defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
#include "utils/error.hpp"
|
||||
|
||||
namespace fifthgrid::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)
|
||||
-> hash_256_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_256(const data_buffer &data)
|
||||
-> hash_256_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_384(std::string_view data) -> hash_384_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_384(std::wstring_view data)
|
||||
-> hash_384_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_384(const data_buffer &data)
|
||||
-> hash_384_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_512(std::wstring_view data)
|
||||
-> hash_512_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_512(const data_buffer &data)
|
||||
-> hash_512_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_blake2b_512(std::string_view data) -> hash_512_t;
|
||||
|
||||
template <typename hash_t>
|
||||
[[nodiscard]] auto create_hash_blake2b_t(const unsigned char *data,
|
||||
std::size_t data_size) -> hash_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_sha256(std::string_view data) -> hash_256_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_sha256(std::wstring_view data) -> hash_256_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_sha256(const data_buffer &data) -> hash_256_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_sha256(const unsigned char *data,
|
||||
std::size_t data_size) -> hash_256_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_sha512(std::string_view data) -> hash_512_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_sha512(std::wstring_view data) -> hash_512_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_sha512(const data_buffer &data) -> hash_512_t;
|
||||
|
||||
[[nodiscard]] auto create_hash_sha512(const unsigned char *data,
|
||||
std::size_t data_size) -> hash_512_t;
|
||||
|
||||
template <typename hash_t>
|
||||
[[nodiscard]] inline auto default_create_hash() -> const
|
||||
std::function<hash_t(const unsigned char *data, std::size_t size)> &;
|
||||
|
||||
template <typename hash_t>
|
||||
auto create_hash_blake2b_t(const unsigned char *data, std::size_t data_size)
|
||||
-> hash_t {
|
||||
FIFTHGRID_USES_FUNCTION_NAME();
|
||||
|
||||
hash_t hash{};
|
||||
|
||||
crypto_generichash_blake2b_state state{};
|
||||
auto res = crypto_generichash_blake2b_init(&state, nullptr, 0U, hash.size());
|
||||
if (res != 0) {
|
||||
throw utils::error::create_exception(function_name,
|
||||
{
|
||||
"failed to initialize blake2b",
|
||||
std::to_string(hash.size() * 8U),
|
||||
std::to_string(res),
|
||||
});
|
||||
}
|
||||
|
||||
res = crypto_generichash_blake2b_update(&state, data, data_size);
|
||||
if (res != 0) {
|
||||
throw utils::error::create_exception(function_name,
|
||||
{
|
||||
"failed to update blake2b",
|
||||
std::to_string(hash.size() * 8U),
|
||||
std::to_string(res),
|
||||
});
|
||||
}
|
||||
|
||||
res = crypto_generichash_blake2b_final(&state, hash.data(), hash.size());
|
||||
if (res != 0) {
|
||||
throw utils::error::create_exception(function_name,
|
||||
{
|
||||
"failed to finalize blake2b",
|
||||
std::to_string(hash.size() * 8U),
|
||||
std::to_string(res),
|
||||
});
|
||||
}
|
||||
|
||||
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 =
|
||||
[](const unsigned char *data, std::size_t data_size) -> hash_256_t {
|
||||
return create_hash_blake2b_t<hash_256_t>(data, data_size);
|
||||
};
|
||||
|
||||
inline const std::function<hash_384_t(const unsigned char *data,
|
||||
std::size_t size)>
|
||||
blake2b_384_hasher =
|
||||
[](const unsigned char *data, std::size_t data_size) -> hash_384_t {
|
||||
return create_hash_blake2b_t<hash_384_t>(data, data_size);
|
||||
};
|
||||
|
||||
inline const std::function<hash_512_t(const unsigned char *data,
|
||||
std::size_t size)>
|
||||
blake2b_512_hasher =
|
||||
[](const unsigned char *data, std::size_t data_size) -> hash_512_t {
|
||||
return create_hash_blake2b_t<hash_512_t>(data, data_size);
|
||||
};
|
||||
|
||||
inline const std::function<hash_256_t(const unsigned char *data,
|
||||
std::size_t size)>
|
||||
sha256_hasher =
|
||||
[](const unsigned char *data, std::size_t data_size) -> hash_256_t {
|
||||
return create_hash_sha256(data, data_size);
|
||||
};
|
||||
|
||||
inline const std::function<hash_512_t(const unsigned char *data,
|
||||
std::size_t size)>
|
||||
sha512_hasher =
|
||||
[](const unsigned char *data, std::size_t data_size) -> hash_512_t {
|
||||
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)> & {
|
||||
return blake2b_256_hasher;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline auto default_create_hash<hash_384_t>() -> const
|
||||
std::function<hash_384_t(const unsigned char *data, std::size_t size)> & {
|
||||
return blake2b_384_hasher;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline auto default_create_hash<hash_512_t>() -> const
|
||||
std::function<hash_512_t(const unsigned char *data, std::size_t size)> & {
|
||||
return blake2b_512_hasher;
|
||||
}
|
||||
} // namespace fifthgrid::utils::hash
|
||||
|
||||
#endif // defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_HASH_HPP_
|
||||
526
support/include/utils/path.hpp
Normal file
526
support/include/utils/path.hpp
Normal file
@@ -0,0 +1,526 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_PATH_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_PATH_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
namespace fifthgrid::utils::path {
|
||||
inline constexpr std::string_view backslash{"\\"};
|
||||
inline constexpr std::wstring_view backslash_w{L"\\"};
|
||||
inline constexpr std::string_view dot{"."};
|
||||
inline constexpr std::wstring_view dot_w{L"."};
|
||||
inline constexpr std::string_view dot_backslash{".\\"};
|
||||
inline constexpr std::wstring_view dot_backslash_w{L".\\"};
|
||||
inline constexpr std::string_view dot_slash{"./"};
|
||||
inline constexpr std::wstring_view dot_slash_w{L"./"};
|
||||
inline constexpr std::string_view long_notation{"\\\\?\\"};
|
||||
inline constexpr std::wstring_view long_notation_w{L"\\\\?\\"};
|
||||
inline constexpr std::string_view slash{"/"};
|
||||
inline constexpr std::wstring_view slash_w{L"/"};
|
||||
#if defined(_WIN32)
|
||||
inline constexpr std::string_view directory_seperator{backslash};
|
||||
inline constexpr std::wstring_view directory_seperator_w{backslash_w};
|
||||
inline constexpr std::string_view not_directory_seperator{slash};
|
||||
inline constexpr std::wstring_view not_directory_seperator_w{slash_w};
|
||||
inline constexpr std::string_view unc_notation{"\\\\"};
|
||||
inline constexpr std::wstring_view unc_notation_w{L"\\\\"};
|
||||
#else // !defined(_WIN32)
|
||||
inline constexpr std::string_view directory_seperator{slash};
|
||||
inline constexpr std::wstring_view directory_seperator_w{slash_w};
|
||||
inline constexpr std::string_view not_directory_seperator{backslash};
|
||||
inline constexpr std::wstring_view not_directory_seperator_w{backslash_w};
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
template <typename char_t>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_backslash() -> std::basic_string_view<char_t>;
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_backslash<char>() -> std::basic_string_view<char> {
|
||||
return backslash;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_backslash<wchar_t>() -> std::basic_string_view<wchar_t> {
|
||||
return backslash_w;
|
||||
}
|
||||
|
||||
template <typename char_t>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_directory_seperator() -> std::basic_string_view<char_t>;
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_directory_seperator<char>() -> std::basic_string_view<char> {
|
||||
return directory_seperator;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_directory_seperator<wchar_t>() -> std::basic_string_view<wchar_t> {
|
||||
return directory_seperator_w;
|
||||
}
|
||||
|
||||
template <typename char_t>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_not_directory_seperator() -> std::basic_string_view<char_t>;
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_not_directory_seperator<char>() -> std::basic_string_view<char> {
|
||||
return not_directory_seperator;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_not_directory_seperator<wchar_t>() -> std::basic_string_view<wchar_t> {
|
||||
return not_directory_seperator_w;
|
||||
}
|
||||
|
||||
template <typename char_t>
|
||||
[[nodiscard]] inline constexpr auto get_dot() -> std::basic_string_view<char_t>;
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_dot<char>() -> std::basic_string_view<char> {
|
||||
return dot;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_dot<wchar_t>() -> std::basic_string_view<wchar_t> {
|
||||
return dot_w;
|
||||
}
|
||||
|
||||
template <typename char_t>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_dot_backslash() -> std::basic_string_view<char_t>;
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_dot_backslash<char>() -> std::basic_string_view<char> {
|
||||
return dot_backslash;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_dot_backslash<wchar_t>() -> std::basic_string_view<wchar_t> {
|
||||
return dot_backslash_w;
|
||||
}
|
||||
|
||||
template <typename char_t>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_dot_slash() -> std::basic_string_view<char_t>;
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_dot_slash<char>() -> std::basic_string_view<char> {
|
||||
return dot_slash;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_dot_slash<wchar_t>() -> std::basic_string_view<wchar_t> {
|
||||
return dot_slash_w;
|
||||
}
|
||||
|
||||
template <typename char_t>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_long_notation() -> std::basic_string_view<char_t>;
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_long_notation<char>() -> std::basic_string_view<char> {
|
||||
return long_notation;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_long_notation<wchar_t>() -> std::basic_string_view<wchar_t> {
|
||||
return long_notation_w;
|
||||
}
|
||||
|
||||
template <typename char_t>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_slash() -> std::basic_string_view<char_t>;
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_slash<char>() -> std::basic_string_view<char> {
|
||||
return slash;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_slash<wchar_t>() -> std::basic_string_view<wchar_t> {
|
||||
return slash_w;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
template <typename char_t>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_unc_notation() -> std::basic_string_view<char_t>;
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_unc_notation<char>() -> std::basic_string_view<char> {
|
||||
return unc_notation;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline constexpr auto
|
||||
get_unc_notation<wchar_t>() -> std::basic_string_view<wchar_t> {
|
||||
return unc_notation_w;
|
||||
}
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto get_current_path() -> string_t;
|
||||
|
||||
[[nodiscard]] auto absolute(std::string_view path) -> std::string;
|
||||
|
||||
[[nodiscard]] auto absolute(std::wstring_view path) -> std::wstring;
|
||||
|
||||
[[nodiscard]] inline auto
|
||||
combine(std::string_view path,
|
||||
const std::vector<std::string_view> &paths) -> std::string;
|
||||
|
||||
[[nodiscard]] inline auto
|
||||
combine(std::wstring_view path,
|
||||
const std::vector<std::wstring_view> &paths) -> std::wstring;
|
||||
|
||||
[[nodiscard]] auto contains_trash_directory(std::string_view path) -> bool;
|
||||
|
||||
[[nodiscard]] auto contains_trash_directory(std::wstring_view path) -> bool;
|
||||
|
||||
[[nodiscard]] auto inline create_api_path(std::string_view path) -> std::string;
|
||||
|
||||
[[nodiscard]] auto inline create_api_path(std::wstring_view path)
|
||||
-> std::wstring;
|
||||
|
||||
[[nodiscard]] auto exists(std::string_view path) -> bool;
|
||||
|
||||
[[nodiscard]] auto exists(std::wstring_view path) -> bool;
|
||||
|
||||
[[nodiscard]] inline auto finalize(std::string_view path) -> std::string;
|
||||
|
||||
[[nodiscard]] inline auto finalize(std::wstring_view path) -> std::wstring;
|
||||
|
||||
[[nodiscard]] auto
|
||||
find_program_in_path(const std::string &name_without_extension) -> std::string;
|
||||
|
||||
[[nodiscard]] auto
|
||||
find_program_in_path(std::wstring_view name_without_extension) -> std::wstring;
|
||||
|
||||
template <typename string_t>
|
||||
inline auto
|
||||
format_path(string_t &path,
|
||||
std::basic_string_view<typename string_t::value_type> sep,
|
||||
std::basic_string_view<typename string_t::value_type> not_sep)
|
||||
-> string_t &;
|
||||
|
||||
[[nodiscard]] inline auto
|
||||
get_parent_api_path(std::string_view path) -> std::string;
|
||||
|
||||
[[nodiscard]] inline auto
|
||||
get_parent_api_path(std::wstring_view path) -> std::wstring;
|
||||
|
||||
[[nodiscard]] auto get_parent_path(std::string_view path) -> std::string;
|
||||
|
||||
[[nodiscard]] auto get_parent_path(std::wstring_view path) -> std::wstring;
|
||||
|
||||
[[nodiscard]] inline auto
|
||||
get_parts(std::string_view path) -> std::vector<std::string>;
|
||||
|
||||
[[nodiscard]] inline auto
|
||||
get_parts_w(std::wstring_view path) -> std::vector<std::wstring>;
|
||||
|
||||
[[nodiscard]] auto get_relative_path(std::string_view path,
|
||||
std::string_view root_path) -> std::string;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_relative_path(std::wstring_view path,
|
||||
std::wstring_view root_path) -> std::wstring;
|
||||
|
||||
[[nodiscard]] auto make_file_uri(std::string_view path) -> std::string;
|
||||
|
||||
[[nodiscard]] auto make_file_uri(std::wstring_view path) -> std::wstring;
|
||||
|
||||
[[nodiscard]] auto strip_to_file_name(std::string path) -> std::string;
|
||||
|
||||
[[nodiscard]] auto strip_to_file_name(std::wstring path) -> std::wstring;
|
||||
|
||||
[[nodiscard]] auto unmake_file_uri(std::string_view uri) -> std::string;
|
||||
|
||||
[[nodiscard]] auto unmake_file_uri(std::wstring_view uri) -> std::wstring;
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto combine_t(
|
||||
std::basic_string_view<typename string_t::value_type> path,
|
||||
const std::vector<std::basic_string_view<typename string_t::value_type>>
|
||||
&paths) -> string_t {
|
||||
auto dir_sep_t =
|
||||
string_t{get_directory_seperator<typename string_t::value_type>()};
|
||||
return absolute(
|
||||
std::accumulate(paths.begin(), paths.end(),
|
||||
std::basic_string<typename string_t::value_type>{path},
|
||||
[&dir_sep_t](auto next_path, auto &&path_part) {
|
||||
if (next_path.empty()) {
|
||||
return string_t{path_part};
|
||||
}
|
||||
|
||||
return next_path + dir_sep_t + string_t{path_part};
|
||||
}));
|
||||
}
|
||||
|
||||
inline auto combine(std::string_view path,
|
||||
const std::vector<std::string_view> &paths) -> std::string {
|
||||
return combine_t<std::string>(path, paths);
|
||||
}
|
||||
|
||||
inline auto
|
||||
combine(std::wstring_view path,
|
||||
const std::vector<std::wstring_view> &paths) -> std::wstring {
|
||||
return combine_t<std::wstring>(path, paths);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto create_api_path_t(
|
||||
std::basic_string_view<typename string_t::value_type> path) -> string_t {
|
||||
auto backslash_t = get_backslash<typename string_t::value_type>();
|
||||
auto dot_backslash_t = get_dot_backslash<typename string_t::value_type>();
|
||||
auto dot_slash_t = get_dot_slash<typename string_t::value_type>();
|
||||
auto dot_t = get_dot<typename string_t::value_type>();
|
||||
auto slash_t = get_slash<typename string_t::value_type>();
|
||||
|
||||
#if defined(_WIN32)
|
||||
auto long_notation_t = get_long_notation<typename string_t::value_type>();
|
||||
if (utils::string::begins_with(path, long_notation_t)) {
|
||||
path = path.substr(long_notation_t.size());
|
||||
}
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
if (path.empty() || path == backslash_t || path == dot_t ||
|
||||
path == dot_slash_t || path == slash_t || path == dot_backslash_t) {
|
||||
return string_t{slash_t};
|
||||
}
|
||||
|
||||
string_t api_path{path};
|
||||
#if defined(_WIN32)
|
||||
if ((api_path.size() >= 2U) && (api_path.at(1U) == ':')) {
|
||||
api_path = api_path.substr(2U);
|
||||
}
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
format_path(api_path, slash_t, backslash_t);
|
||||
|
||||
while (utils::string::begins_with(api_path, dot_slash_t)) {
|
||||
api_path = api_path.substr(dot_slash_t.size());
|
||||
}
|
||||
|
||||
if (api_path.at(0U) != slash_t.at(0U)) {
|
||||
return string_t{slash_t} + api_path;
|
||||
}
|
||||
|
||||
return api_path;
|
||||
}
|
||||
|
||||
inline auto create_api_path(std::string_view path) -> std::string {
|
||||
return create_api_path_t<std::string>(path);
|
||||
}
|
||||
|
||||
inline auto create_api_path(std::wstring_view path) -> std::wstring {
|
||||
return create_api_path_t<std::wstring>(path);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto finalize_t(
|
||||
std::basic_string_view<typename string_t::value_type> path) -> string_t {
|
||||
string_t dir_sep_t{get_directory_seperator<typename string_t::value_type>()};
|
||||
string_t fmt_path{path};
|
||||
if (fmt_path.empty()) {
|
||||
return fmt_path;
|
||||
}
|
||||
|
||||
format_path(fmt_path, dir_sep_t,
|
||||
get_not_directory_seperator<typename string_t::value_type>());
|
||||
|
||||
#if defined(_WIN32)
|
||||
auto unc_notation_t = get_unc_notation<typename string_t::value_type>();
|
||||
if (utils::string::begins_with(fmt_path, unc_notation_t)) {
|
||||
return fmt_path;
|
||||
}
|
||||
|
||||
auto dot_t = get_dot<typename string_t::value_type>();
|
||||
auto dot_sep_t = string_t{dot_t} + dir_sep_t;
|
||||
if (fmt_path == dot_t || fmt_path == dot_sep_t) {
|
||||
return get_current_path<string_t>();
|
||||
}
|
||||
|
||||
if (fmt_path == dir_sep_t) {
|
||||
#if defined(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES)
|
||||
return get_current_path<string_t>().substr(0U, long_notation.size() + 2U);
|
||||
#else // !defined(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES)
|
||||
return get_current_path<string_t>().substr(0U, 2U);
|
||||
#endif // defined(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES)
|
||||
}
|
||||
|
||||
if (utils::string::begins_with(fmt_path, dir_sep_t)) {
|
||||
#if defined(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES)
|
||||
return get_current_path<string_t>().substr(0U, long_notation.size() + 2U) +
|
||||
fmt_path;
|
||||
#else // !defined(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES)
|
||||
return get_current_path<string_t>().substr(0U, 2U) + fmt_path;
|
||||
#endif // defined(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES)
|
||||
}
|
||||
|
||||
if (utils::string::begins_with(fmt_path, dot_sep_t)) {
|
||||
return get_current_path<string_t>() + dir_sep_t + fmt_path.substr(2U);
|
||||
}
|
||||
|
||||
#if defined(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES)
|
||||
return string_t{get_long_notation<typename string_t::value_type>()} +
|
||||
fmt_path;
|
||||
#endif // defined(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES)
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
return fmt_path;
|
||||
}
|
||||
|
||||
inline auto finalize(std::string_view path) -> std::string {
|
||||
return finalize_t<std::string>(path);
|
||||
}
|
||||
|
||||
inline auto finalize(std::wstring_view path) -> std::wstring {
|
||||
return finalize_t<std::wstring>(path);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline auto
|
||||
format_path(string_t &path,
|
||||
std::basic_string_view<typename string_t::value_type> sep,
|
||||
std::basic_string_view<typename string_t::value_type> not_sep)
|
||||
-> string_t & {
|
||||
utils::string::replace(path, not_sep, sep);
|
||||
|
||||
#if defined(_WIN32)
|
||||
auto is_unc{false};
|
||||
auto long_notation_t = get_long_notation<typename string_t::value_type>();
|
||||
auto unc_notation_t = get_unc_notation<typename string_t::value_type>();
|
||||
if (utils::string::begins_with(path, long_notation_t)) {
|
||||
path = path.substr(long_notation_t.size());
|
||||
} else if (utils::string::begins_with(path, unc_notation_t)) {
|
||||
path = path.substr(unc_notation_t.size());
|
||||
utils::string::left_trim(path, sep.at(0U));
|
||||
is_unc = true;
|
||||
}
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
string_t double_sep(2U, sep.at(0U));
|
||||
while (utils::string::contains(path, double_sep)) {
|
||||
utils::string::replace(path, double_sep, sep);
|
||||
}
|
||||
|
||||
if (path != sep) {
|
||||
utils::string::right_trim(path, sep.at(0U));
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (is_unc) {
|
||||
path = string_t{unc_notation_t} + path;
|
||||
} else if ((path.size() >= 2U) && (path.at(1U) == ':')) {
|
||||
path[0U] = utils::string::to_lower(string_t(1U, path.at(0U))).at(0U);
|
||||
}
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline auto get_current_path<std::string>() -> std::string {
|
||||
#if defined(_WIN32)
|
||||
std::string path;
|
||||
path.resize(fifthgrid::max_path_length + 1U);
|
||||
::GetCurrentDirectoryA(static_cast<DWORD>(path.size()), path.data());
|
||||
path = path.c_str();
|
||||
return finalize(path);
|
||||
#else // !defined(_WIN32)
|
||||
return finalize(std::filesystem::current_path().string());
|
||||
#endif // defined(_WIN32)
|
||||
}
|
||||
|
||||
template <>
|
||||
[[nodiscard]] inline auto get_current_path<std::wstring>() -> std::wstring {
|
||||
return utils::string::from_utf8(get_current_path<std::string>());
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto get_parent_api_path_t(
|
||||
std::basic_string_view<typename string_t::value_type> path) -> string_t {
|
||||
auto slash_t = get_slash<typename string_t::value_type>();
|
||||
|
||||
string_t ret{path};
|
||||
utils::string::right_trim(ret, slash_t.at(0U));
|
||||
|
||||
if (ret == slash_t || ret.empty()) {
|
||||
return string_t{path};
|
||||
}
|
||||
|
||||
auto sub_path = ret.substr(0, ret.rfind(slash_t) + 1);
|
||||
if (sub_path == slash_t) {
|
||||
return string_t{sub_path};
|
||||
}
|
||||
|
||||
return sub_path;
|
||||
}
|
||||
|
||||
inline auto get_parent_api_path(std::string_view path) -> std::string {
|
||||
return create_api_path(get_parent_api_path_t<std::string>(path));
|
||||
}
|
||||
|
||||
inline auto get_parent_api_path(std::wstring_view path) -> std::wstring {
|
||||
return create_api_path(get_parent_api_path_t<std::wstring>(path));
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto
|
||||
get_parts_t(std::basic_string_view<typename string_t::value_type> path)
|
||||
-> std::vector<string_t> {
|
||||
return utils::string::split(
|
||||
path, get_directory_seperator<typename string_t::value_type>().at(0U),
|
||||
false);
|
||||
}
|
||||
|
||||
inline auto get_parts(std::string_view path) -> std::vector<std::string> {
|
||||
return get_parts_t<std::string>(path);
|
||||
}
|
||||
|
||||
inline auto get_parts_w(std::wstring_view path) -> std::vector<std::wstring> {
|
||||
return get_parts_t<std::wstring>(path);
|
||||
}
|
||||
} // namespace fifthgrid::utils::path
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_PATH_HPP_
|
||||
469
support/include/utils/string.hpp
Normal file
469
support/include/utils/string.hpp
Normal file
@@ -0,0 +1,469 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_STRING_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_STRING_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
namespace fifthgrid::utils::string {
|
||||
template <typename string_t> struct chain_replace_with_hex;
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto
|
||||
char_to_hex(typename string_t::value_type character) -> string_t;
|
||||
|
||||
[[nodiscard]] inline auto begins_with(std::string_view str,
|
||||
std::string_view val) -> bool;
|
||||
|
||||
[[nodiscard]] inline auto begins_with(std::wstring_view str,
|
||||
std::wstring_view val) -> bool;
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto case_insensitive_find_string(string_t in_str,
|
||||
string_t for_str) ->
|
||||
typename string_t::const_iterator;
|
||||
|
||||
[[nodiscard]] inline auto contains(std::string_view str,
|
||||
std::string_view search) -> bool;
|
||||
|
||||
[[nodiscard]] inline auto contains(std::wstring_view str,
|
||||
std::wstring_view search) -> bool;
|
||||
|
||||
[[nodiscard]] inline auto ends_with(std::string_view str,
|
||||
std::string_view val) -> bool;
|
||||
|
||||
[[nodiscard]] inline auto ends_with(std::wstring_view str,
|
||||
std::wstring_view val) -> bool;
|
||||
|
||||
[[nodiscard]] auto from_bool(bool val) -> std::string;
|
||||
|
||||
#if defined(PROJECT_ENABLE_BOOST)
|
||||
[[nodiscard]] auto
|
||||
from_dynamic_bitset(const boost::dynamic_bitset<> &bitset) -> std::string;
|
||||
#endif // defined(PROJECT_ENABLE_BOOST)
|
||||
|
||||
[[nodiscard]] auto from_utf8(std::string_view str) -> std::wstring;
|
||||
|
||||
[[nodiscard]] inline auto is_numeric(std::string_view str) -> bool;
|
||||
|
||||
[[nodiscard]] inline auto is_numeric(std::wstring_view str) -> bool;
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto join(const std::vector<string_t> &arr,
|
||||
typename string_t::value_type delim) -> string_t;
|
||||
|
||||
template <typename string_t>
|
||||
auto left_trim(string_t &str,
|
||||
typename string_t::value_type trim_ch = ' ') -> string_t &;
|
||||
|
||||
template <typename string_t>
|
||||
inline auto replace(string_t &src, typename string_t::value_type character,
|
||||
typename string_t::value_type with,
|
||||
std::size_t start_pos = 0U) -> string_t &;
|
||||
|
||||
template <typename string_t>
|
||||
inline auto replace(string_t &src,
|
||||
std::basic_string_view<typename string_t::value_type> find,
|
||||
std::basic_string_view<typename string_t::value_type> with,
|
||||
std::size_t start_pos = 0U) -> string_t &;
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto replace_copy(string_t src,
|
||||
typename string_t::value_type character,
|
||||
typename string_t::value_type with,
|
||||
std::size_t start_pos = 0U) -> string_t;
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto
|
||||
replace_copy(string_t src,
|
||||
std::basic_string_view<typename string_t::value_type> find,
|
||||
std::basic_string_view<typename string_t::value_type> with,
|
||||
std::size_t start_pos = 0U) -> string_t;
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto
|
||||
replace_with_hex(string_t &str, typename string_t::value_type character)
|
||||
-> chain_replace_with_hex<string_t>;
|
||||
|
||||
template <typename string_t>
|
||||
inline auto
|
||||
right_trim(string_t &str,
|
||||
typename string_t::value_type trim_ch = ' ') -> string_t &;
|
||||
|
||||
[[nodiscard]] inline auto split(std::string_view str, char delim,
|
||||
bool should_trim) -> std::vector<std::string>;
|
||||
|
||||
[[nodiscard]] inline auto split(std::wstring_view str, wchar_t delim,
|
||||
bool should_trim) -> std::vector<std::wstring>;
|
||||
|
||||
[[nodiscard]] inline auto split(std::string_view str, std::string_view delim,
|
||||
bool should_trim) -> std::vector<std::string>;
|
||||
|
||||
[[nodiscard]] inline auto split(std::wstring_view str, std::wstring_view delim,
|
||||
bool should_trim) -> std::vector<std::wstring>;
|
||||
|
||||
#if defined(PROJECT_ENABLE_SFML)
|
||||
auto replace_sf(sf::String &src, const sf::String &find, const sf::String &with,
|
||||
std::size_t start_pos = 0U) -> sf::String &;
|
||||
|
||||
[[nodiscard]] auto split_sf(sf::String str, wchar_t delim,
|
||||
bool should_trim) -> std::vector<sf::String>;
|
||||
#endif // defined(PROJECT_ENABLE_SFML)
|
||||
|
||||
[[nodiscard]] auto to_bool(std::string val) -> bool;
|
||||
|
||||
[[nodiscard]] auto to_double(const std::string &str) -> double;
|
||||
|
||||
#if defined(PROJECT_ENABLE_BOOST)
|
||||
[[nodiscard]] auto
|
||||
to_dynamic_bitset(const std::string &val) -> boost::dynamic_bitset<>;
|
||||
#endif // defined(PROJECT_ENABLE_BOOST)
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto to_lower(string_t str) -> string_t;
|
||||
|
||||
[[nodiscard]] auto to_int32(const std::string &val) -> std::int32_t;
|
||||
|
||||
[[nodiscard]] auto to_int64(const std::string &val) -> std::int64_t;
|
||||
|
||||
[[nodiscard]] auto to_size_t(const std::string &val) -> std::size_t;
|
||||
|
||||
[[nodiscard]] auto to_uint8(const std::string &val) -> std::uint8_t;
|
||||
|
||||
[[nodiscard]] auto to_uint16(const std::string &val) -> std::uint16_t;
|
||||
|
||||
[[nodiscard]] auto to_uint32(const std::string &val) -> std::uint32_t;
|
||||
|
||||
[[nodiscard]] auto to_uint64(const std::string &val) -> std::uint64_t;
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto to_upper(string_t str) -> string_t;
|
||||
|
||||
[[nodiscard]] auto to_utf8(std::string_view str) -> std::string;
|
||||
|
||||
[[nodiscard]] auto to_utf8(std::wstring_view str) -> std::string;
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto zero_pad(string_t str, std::size_t count) -> string_t;
|
||||
|
||||
template <typename string_t> struct chain_replace_with_hex final {
|
||||
explicit chain_replace_with_hex(string_t &value) : str(value) {}
|
||||
|
||||
chain_replace_with_hex(const chain_replace_with_hex &) = delete;
|
||||
|
||||
chain_replace_with_hex(chain_replace_with_hex &&) = delete;
|
||||
|
||||
~chain_replace_with_hex() = default;
|
||||
|
||||
auto operator=(const chain_replace_with_hex &) -> chain_replace_with_hex & =
|
||||
delete;
|
||||
|
||||
auto
|
||||
operator=(chain_replace_with_hex &&) -> chain_replace_with_hex & = delete;
|
||||
|
||||
auto operator()(typename string_t::value_type character)
|
||||
-> chain_replace_with_hex {
|
||||
return replace_with_hex<string_t>(str, character);
|
||||
}
|
||||
|
||||
string_t &str;
|
||||
};
|
||||
|
||||
template <typename string_t>
|
||||
inline auto trim(string_t &str,
|
||||
typename string_t::value_type trim_ch = ' ') -> string_t &;
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto
|
||||
trim_copy(string_t str,
|
||||
typename string_t::value_type trim_ch = ' ') -> string_t;
|
||||
|
||||
template <typename char_t>
|
||||
[[nodiscard]] inline auto
|
||||
begins_with_t(std::basic_string_view<char_t> str,
|
||||
std::basic_string_view<char_t> val) -> bool {
|
||||
return (str.find(val) == 0U);
|
||||
}
|
||||
|
||||
inline auto begins_with(std::string_view str, std::string_view val) -> bool {
|
||||
return begins_with_t<std::string_view::value_type>(str, val);
|
||||
}
|
||||
|
||||
inline auto begins_with(std::wstring_view str, std::wstring_view val) -> bool {
|
||||
return begins_with_t<std::wstring_view::value_type>(str, val);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline auto case_insensitive_find_string(string_t in_str, string_t for_str) ->
|
||||
typename string_t::const_iterator {
|
||||
static const auto compare_chars =
|
||||
[](typename string_t::value_type char_a,
|
||||
typename string_t::value_type char_b) -> bool {
|
||||
return (std::tolower(char_a) == std::tolower(char_b));
|
||||
};
|
||||
|
||||
return (std::search(in_str.begin(), in_str.end(), for_str.begin(),
|
||||
for_str.end(), compare_chars));
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline auto char_to_hex(typename string_t::value_type character) -> string_t {
|
||||
std::basic_stringstream<typename string_t::value_type> stream;
|
||||
stream << '%' << std::setfill<typename string_t::value_type>('0')
|
||||
<< std::setw(sizeof(character)) << std::hex
|
||||
<< static_cast<std::uint32_t>(character);
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
template <typename char_t>
|
||||
[[nodiscard]] inline auto
|
||||
contains_t(std::basic_string_view<char_t> str,
|
||||
std::basic_string_view<char_t> search) -> bool {
|
||||
return (str.find(search) != std::basic_string_view<char_t>::npos);
|
||||
}
|
||||
|
||||
inline auto contains(std::string_view str, std::string_view search) -> bool {
|
||||
return contains_t<std::string_view::value_type>(str, search);
|
||||
}
|
||||
|
||||
inline auto contains(std::wstring_view str, std::wstring_view search) -> bool {
|
||||
return contains_t<std::wstring_view::value_type>(str, search);
|
||||
}
|
||||
|
||||
template <typename char_t>
|
||||
[[nodiscard]] inline auto
|
||||
ends_with_t(std::basic_string_view<char_t> str,
|
||||
std::basic_string_view<char_t> val) -> bool {
|
||||
if (val.size() > str.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::equal(val.rbegin(), val.rend(), str.rbegin());
|
||||
}
|
||||
|
||||
inline auto ends_with(std::string_view str, std::string_view val) -> bool {
|
||||
return ends_with_t<std::string_view::value_type>(str, val);
|
||||
}
|
||||
|
||||
inline auto ends_with(std::wstring_view str, std::wstring_view val) -> bool {
|
||||
return ends_with_t<std::wstring_view::value_type>(str, val);
|
||||
}
|
||||
|
||||
template <typename char_t>
|
||||
[[nodiscard]] inline auto
|
||||
is_numeric_t(std::basic_string_view<char_t> str) -> bool {
|
||||
if ((str.length() > 1U) && (str.at(0U) == '+' || str.at(0U) == '-')) {
|
||||
str = str.substr(1U);
|
||||
}
|
||||
|
||||
if (str.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto has_decimal{false};
|
||||
return std::find_if(str.begin(), str.end(),
|
||||
[&has_decimal](auto &&cur_ch) -> bool {
|
||||
if (has_decimal && cur_ch == '.') {
|
||||
return true;
|
||||
}
|
||||
|
||||
has_decimal = has_decimal || cur_ch == '.';
|
||||
if (has_decimal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::isdigit(cur_ch) == 0;
|
||||
}) == str.end();
|
||||
}
|
||||
|
||||
inline auto is_numeric(std::string_view str) -> bool {
|
||||
return is_numeric_t<std::string_view::value_type>(str);
|
||||
}
|
||||
|
||||
inline auto is_numeric(std::wstring_view str) -> bool {
|
||||
return is_numeric_t<std::wstring_view::value_type>(str);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline auto join(const std::vector<string_t> &arr,
|
||||
typename string_t::value_type delim) -> string_t {
|
||||
if (arr.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return std::accumulate(
|
||||
std::next(arr.begin()), arr.end(), arr[0U],
|
||||
[&delim](auto str, const auto &cur) { return str + delim + cur; });
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
auto left_trim(string_t &str,
|
||||
typename string_t::value_type trim_ch) -> string_t & {
|
||||
str.erase(0, str.find_first_not_of(trim_ch));
|
||||
return str;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline auto replace(string_t &src, typename string_t::value_type character,
|
||||
typename string_t::value_type with,
|
||||
std::size_t start_pos) -> string_t & {
|
||||
if (start_pos < src.size()) {
|
||||
std::replace(std::next(src.begin(), start_pos), src.end(), character, with);
|
||||
}
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline auto replace(string_t &src,
|
||||
std::basic_string_view<typename string_t::value_type> find,
|
||||
std::basic_string_view<typename string_t::value_type> with,
|
||||
std::size_t start_pos) -> string_t & {
|
||||
if (start_pos < src.size()) {
|
||||
while ((start_pos = src.find(find, start_pos)) != string_t::npos) {
|
||||
src.replace(start_pos, find.size(), with);
|
||||
start_pos += with.size();
|
||||
}
|
||||
}
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline auto replace_copy(string_t src, typename string_t::value_type character,
|
||||
typename string_t::value_type with,
|
||||
std::size_t start_pos) -> string_t {
|
||||
return replace(src, character, with, start_pos);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline auto
|
||||
replace_copy(string_t src,
|
||||
std::basic_string_view<typename string_t::value_type> find,
|
||||
std::basic_string_view<typename string_t::value_type> with,
|
||||
std::size_t start_pos) -> string_t {
|
||||
return replace(src, find, with, start_pos);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline auto replace_with_hex(string_t &str,
|
||||
typename string_t::value_type character)
|
||||
-> chain_replace_with_hex<string_t> {
|
||||
return chain_replace_with_hex(
|
||||
replace(str, string_t{1U, character}, char_to_hex<string_t>(character)));
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline auto right_trim(string_t &str,
|
||||
typename string_t::value_type trim_ch) -> string_t & {
|
||||
str.erase(str.find_last_not_of(trim_ch) + 1);
|
||||
return str;
|
||||
}
|
||||
|
||||
template <typename string_t> inline auto to_lower(string_t str) -> string_t {
|
||||
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
||||
return str;
|
||||
}
|
||||
|
||||
template <typename string_t> inline auto to_upper(string_t str) -> string_t {
|
||||
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
|
||||
return str;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline auto trim(string_t &str,
|
||||
typename string_t::value_type trim_ch) -> string_t & {
|
||||
return right_trim(left_trim(str, trim_ch), trim_ch);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline auto trim_copy(string_t str,
|
||||
typename string_t::value_type trim_ch) -> string_t {
|
||||
return trim(str, trim_ch);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto
|
||||
split_t(std::basic_string_view<typename string_t::value_type> str,
|
||||
typename string_t::value_type delim,
|
||||
bool should_trim) -> std::vector<string_t> {
|
||||
std::vector<string_t> ret;
|
||||
std::basic_stringstream<typename string_t::value_type> stream{string_t{str}};
|
||||
|
||||
string_t val;
|
||||
while (std::getline(stream, val, delim)) {
|
||||
if (should_trim) {
|
||||
trim(val);
|
||||
}
|
||||
ret.push_back(std::move(val));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline auto split(std::string_view str, char delim,
|
||||
bool should_trim) -> std::vector<std::string> {
|
||||
return split_t<std::string>(str, delim, should_trim);
|
||||
}
|
||||
|
||||
inline auto split(std::wstring_view str, wchar_t delim,
|
||||
bool should_trim) -> std::vector<std::wstring> {
|
||||
return split_t<std::wstring>(str, delim, should_trim);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
[[nodiscard]] inline auto
|
||||
split_t(std::basic_string_view<typename string_t::value_type> str,
|
||||
std::basic_string_view<typename string_t::value_type> delim,
|
||||
bool should_trim) -> std::vector<string_t> {
|
||||
auto result = std::views::split(str, delim);
|
||||
|
||||
std::vector<string_t> ret{};
|
||||
for (auto &&word : result) {
|
||||
auto val = string_t{word.begin(), word.end()};
|
||||
if (should_trim) {
|
||||
trim(val);
|
||||
}
|
||||
ret.push_back(std::move(val));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline auto split(std::string_view str, std::string_view delim,
|
||||
bool should_trim) -> std::vector<std::string> {
|
||||
return split_t<std::string>(str, delim, should_trim);
|
||||
}
|
||||
|
||||
inline auto split(std::wstring_view str, std::wstring_view delim,
|
||||
bool should_trim) -> std::vector<std::wstring> {
|
||||
return split_t<std::wstring>(str, delim, should_trim);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
inline auto zero_pad(string_t str, std::size_t count) -> string_t {
|
||||
str.insert(str.begin(), count - str.length(), '0');
|
||||
return str;
|
||||
}
|
||||
} // namespace fifthgrid::utils::string
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_STRING_HPP_
|
||||
69
support/include/utils/time.hpp
Normal file
69
support/include/utils/time.hpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_TIME_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_TIME_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
namespace fifthgrid::utils::time {
|
||||
inline constexpr auto NANOS_PER_SECOND{1000000000ULL};
|
||||
inline constexpr auto WIN32_TIME_CONVERSION{116444736000000000ULL};
|
||||
inline constexpr auto WIN32_TIME_NANOS_PER_TICK{100ULL};
|
||||
|
||||
#if defined(PROJECT_ENABLE_SPDLOG) || defined(PROJECT_ENABLE_FMT)
|
||||
[[nodiscard]] inline auto convert_to_utc(time_t time) -> std::time_t {
|
||||
auto calendar_time = fmt::gmtime(time);
|
||||
return std::mktime(&calendar_time);
|
||||
}
|
||||
#endif // defined(PROJECT_ENABLE_SPDLOG) || defined(PROJECT_ENABLE_FMT)
|
||||
|
||||
#if defined(PROJECT_ENABLE_SPDLOG) || defined(PROJECT_ENABLE_FMT)
|
||||
[[nodiscard]] inline auto get_current_time_utc() -> std::time_t {
|
||||
auto calendar_time = fmt::gmtime(std::time(nullptr));
|
||||
return std::mktime(&calendar_time);
|
||||
}
|
||||
#endif // defined(PROJECT_ENABLE_SPDLOG) || defined(PROJECT_ENABLE_FMT)
|
||||
|
||||
void get_local_time_now(struct tm &local_time);
|
||||
|
||||
[[nodiscard]] auto get_time_now() -> std::uint64_t;
|
||||
|
||||
#if defined(_WIN32)
|
||||
auto strptime(const char *s, const char *f, struct tm *tm) -> const char *;
|
||||
|
||||
[[nodiscard]] auto unix_time_to_filetime(std::uint64_t unix_time) -> FILETIME;
|
||||
|
||||
[[nodiscard]] auto
|
||||
windows_file_time_to_unix_time(FILETIME win_time) -> std::uint64_t;
|
||||
|
||||
[[nodiscard]] auto
|
||||
windows_time_t_to_unix_time(__time64_t win_time) -> std::uint64_t;
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
[[nodiscard]] auto
|
||||
unix_time_to_windows_time(std::uint64_t unix_time) -> std::uint64_t;
|
||||
|
||||
[[nodiscard]] auto
|
||||
windows_time_to_unix_time(std::uint64_t win_time) -> std::uint64_t;
|
||||
} // namespace fifthgrid::utils::time
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_TIME_HPP_
|
||||
59
support/include/utils/timeout.hpp
Normal file
59
support/include/utils/timeout.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_TIMEOUT_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_TIMEOUT_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
namespace fifthgrid::utils {
|
||||
class timeout final {
|
||||
public:
|
||||
using callback_t = std::function<void()>;
|
||||
|
||||
public:
|
||||
timeout(const timeout &) noexcept = delete;
|
||||
timeout(timeout &&) noexcept = delete;
|
||||
auto operator=(const timeout &) noexcept -> timeout & = delete;
|
||||
auto operator=(timeout &&) noexcept -> timeout & = delete;
|
||||
|
||||
public:
|
||||
timeout(callback_t timeout_callback,
|
||||
std::chrono::system_clock::duration duration);
|
||||
|
||||
~timeout();
|
||||
|
||||
private:
|
||||
std::chrono::system_clock::duration duration_;
|
||||
callback_t timeout_callback_;
|
||||
std::atomic<bool> timeout_killed_{false};
|
||||
std::unique_ptr<std::thread> timeout_thread_{nullptr};
|
||||
std::mutex timeout_mutex_;
|
||||
std::condition_variable timeout_notify_;
|
||||
|
||||
public:
|
||||
void disable();
|
||||
|
||||
void reset();
|
||||
};
|
||||
} // namespace fifthgrid::utils
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_TIMEOUT_HPP_
|
||||
100
support/include/utils/ttl_cache.hpp
Normal file
100
support/include/utils/ttl_cache.hpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_TTL_CACHE_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_TTL_CACHE_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
namespace fifthgrid::utils {
|
||||
template <typename data_t, template <typename> class atomic_t = std::atomic>
|
||||
class ttl_cache final {
|
||||
public:
|
||||
using clock = std::chrono::steady_clock;
|
||||
using duration = std::chrono::milliseconds;
|
||||
using entry_t = atomic_t<data_t>;
|
||||
using entry_ptr_t = std::shared_ptr<entry_t>;
|
||||
|
||||
static constexpr auto default_expiration{duration(60000U)};
|
||||
|
||||
private:
|
||||
struct entry final {
|
||||
entry_ptr_t data;
|
||||
clock::time_point expires_at;
|
||||
};
|
||||
|
||||
public:
|
||||
ttl_cache(duration ttl = default_expiration) : ttl_{ttl} {}
|
||||
|
||||
private:
|
||||
duration ttl_;
|
||||
|
||||
private:
|
||||
mutable std::mutex mutex_;
|
||||
std::unordered_map<std::string, entry> entries_;
|
||||
|
||||
public:
|
||||
void clear() {
|
||||
mutex_lock lock(mutex_);
|
||||
entries_.clear();
|
||||
}
|
||||
|
||||
void erase(const std::string &api_path) {
|
||||
mutex_lock lock(mutex_);
|
||||
entries_.erase(api_path);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto contains(const std::string &api_path) -> bool {
|
||||
mutex_lock lock(mutex_);
|
||||
return entries_.contains(api_path);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get(const std::string &api_path) -> entry_ptr_t {
|
||||
mutex_lock lock(mutex_);
|
||||
auto iter = entries_.find(api_path);
|
||||
if (iter == entries_.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
iter->second.expires_at = clock::now() + ttl_;
|
||||
return iter->second.data;
|
||||
}
|
||||
|
||||
void purge_expired() {
|
||||
mutex_lock lock(mutex_);
|
||||
auto now = clock::now();
|
||||
for (auto iter = entries_.begin(); iter != entries_.end();) {
|
||||
if (iter->second.expires_at <= now) {
|
||||
iter = entries_.erase(iter);
|
||||
continue;
|
||||
}
|
||||
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_ttl() const -> duration {
|
||||
mutex_lock lock(mutex_);
|
||||
return ttl_;
|
||||
}
|
||||
|
||||
void set(const std::string &api_path, const data_t &data) {
|
||||
mutex_lock lock(mutex_);
|
||||
if (entries_.contains(api_path)) {
|
||||
auto &entry = entries_.at(api_path);
|
||||
entry.data->store(data);
|
||||
entry.expires_at = clock::now() + ttl_;
|
||||
return;
|
||||
}
|
||||
|
||||
entries_.emplace(api_path, entry{
|
||||
.data = std::make_shared<entry_t>(data),
|
||||
.expires_at = clock::now() + ttl_,
|
||||
});
|
||||
}
|
||||
|
||||
void set_ttl(duration ttl) {
|
||||
mutex_lock lock(mutex_);
|
||||
ttl_ = ttl;
|
||||
}
|
||||
};
|
||||
} // namespace fifthgrid::utils
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_TTL_CACHE_HPP_
|
||||
81
support/include/utils/types/file/i_directory.hpp
Normal file
81
support/include/utils/types/file/i_directory.hpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_TYPES_FILE_I_DIRECTORY_HPP_
|
||||
#define FIFTHGRID_INCLUDE_TYPES_FILE_I_DIRECTORY_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
#include "utils/types/file/i_file.hpp"
|
||||
#include "utils/types/file/i_fs_item.hpp"
|
||||
|
||||
namespace fifthgrid::utils::file {
|
||||
struct i_directory : public i_fs_item {
|
||||
using fs_directory_t = std::unique_ptr<i_directory>;
|
||||
using fs_file_t = i_file::fs_file_t;
|
||||
|
||||
virtual ~i_directory() = default;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
count(bool recursive = false) const -> std::uint64_t = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
create_directory(std::string_view path = "") const -> fs_directory_t = 0;
|
||||
|
||||
[[nodiscard]] virtual auto create_file(std::string_view file_name,
|
||||
bool read_only) const -> fs_file_t = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_directory(std::string_view path) const -> fs_directory_t = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_directories() const -> std::vector<fs_directory_t> = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_file(std::string_view path) const -> fs_file_t = 0;
|
||||
|
||||
[[nodiscard]] virtual auto get_files() const -> std::vector<fs_file_t> = 0;
|
||||
|
||||
[[nodiscard]] virtual auto get_items() const -> std::vector<fs_item_t> = 0;
|
||||
|
||||
[[nodiscard]] auto is_directory_item() const -> bool override { return true; }
|
||||
|
||||
[[nodiscard]] virtual auto is_stop_requested() const -> bool = 0;
|
||||
|
||||
[[nodiscard]] virtual auto remove_recursively() -> bool = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
size(bool recursive = false) const -> std::uint64_t = 0;
|
||||
|
||||
protected:
|
||||
i_directory() noexcept = default;
|
||||
|
||||
i_directory(const i_directory &) noexcept = default;
|
||||
|
||||
i_directory(i_directory &&) noexcept = default;
|
||||
|
||||
auto operator=(i_directory &&) noexcept -> i_directory & = default;
|
||||
|
||||
auto operator=(const i_directory &) noexcept -> i_directory & = default;
|
||||
};
|
||||
} // namespace fifthgrid::utils::file
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_TYPES_FILE_I_DIRECTORY_HPP_
|
||||
93
support/include/utils/types/file/i_file.hpp
Normal file
93
support/include/utils/types/file/i_file.hpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_TYPES_FILE_I_FILE_HPP_
|
||||
#define FIFTHGRID_INCLUDE_TYPES_FILE_I_FILE_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
#include "utils/types/file/i_fs_item.hpp"
|
||||
|
||||
namespace fifthgrid::utils::file {
|
||||
struct i_file : public i_fs_item {
|
||||
using fs_file_t = std::unique_ptr<i_file>;
|
||||
|
||||
virtual ~i_file() = default;
|
||||
|
||||
virtual void close() = 0;
|
||||
|
||||
virtual void flush() const = 0;
|
||||
|
||||
[[nodiscard]] virtual auto get_handle() const -> native_handle = 0;
|
||||
|
||||
[[nodiscard]] virtual auto get_read_buffer_size() const -> std::uint32_t = 0;
|
||||
|
||||
[[nodiscard]] auto is_directory_item() const -> bool override {
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual auto is_read_only() const -> bool = 0;
|
||||
|
||||
[[nodiscard]] virtual auto read(data_buffer &data, std::uint64_t offset,
|
||||
std::size_t *total_read = nullptr) -> bool {
|
||||
return read(data.data(), data.size(), offset, total_read);
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
read(unsigned char *data, std::size_t to_read, std::uint64_t offset,
|
||||
std::size_t *total_read = nullptr) -> bool = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
read_all(data_buffer &data, std::uint64_t offset,
|
||||
std::size_t *total_read = nullptr) -> bool;
|
||||
|
||||
virtual auto set_read_buffer_size(std::uint32_t size) -> std::uint32_t = 0;
|
||||
|
||||
[[nodiscard]] virtual auto size() const -> std::optional<std::uint64_t> = 0;
|
||||
|
||||
[[nodiscard]] virtual auto truncate() -> bool { return truncate(0U); }
|
||||
|
||||
[[nodiscard]] virtual auto truncate(std::size_t size) -> bool = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
write(const data_buffer &data, std::uint64_t offset,
|
||||
std::size_t *total_written = nullptr) -> bool {
|
||||
return write(data.data(), data.size(), offset, total_written);
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
write(const unsigned char *data, std::size_t to_write, std::size_t offset,
|
||||
std::size_t *total_written = nullptr) -> bool = 0;
|
||||
|
||||
protected:
|
||||
i_file() noexcept = default;
|
||||
|
||||
i_file(const i_file &) noexcept = default;
|
||||
|
||||
i_file(i_file &&) noexcept = default;
|
||||
|
||||
auto operator=(i_file &&) noexcept -> i_file & = default;
|
||||
|
||||
auto operator=(const i_file &) noexcept -> i_file & = default;
|
||||
};
|
||||
} // namespace fifthgrid::utils::file
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_TYPES_FILE_I_FILE_HPP_
|
||||
121
support/include/utils/types/file/i_fs_item.hpp
Normal file
121
support/include/utils/types/file/i_fs_item.hpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_TYPES_FILE_I_FS_ITEM_HPP_
|
||||
#define FIFTHGRID_INCLUDE_TYPES_FILE_I_FS_ITEM_HPP_
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
#include "utils/error.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
namespace fifthgrid::utils::file {
|
||||
enum class time_type {
|
||||
accessed,
|
||||
changed,
|
||||
created,
|
||||
modified,
|
||||
written,
|
||||
};
|
||||
|
||||
struct file_times final {
|
||||
std::uint64_t accessed{};
|
||||
std::uint64_t changed{};
|
||||
std::uint64_t created{};
|
||||
std::uint64_t modified{};
|
||||
std::uint64_t written{};
|
||||
|
||||
[[nodiscard]] auto get(time_type type) const -> std::uint64_t {
|
||||
FIFTHGRID_USES_FUNCTION_NAME();
|
||||
|
||||
switch (type) {
|
||||
case time_type::accessed:
|
||||
return accessed;
|
||||
case time_type::changed:
|
||||
return changed;
|
||||
case time_type::created:
|
||||
return created;
|
||||
case time_type::modified:
|
||||
return modified;
|
||||
case time_type::written:
|
||||
return written;
|
||||
}
|
||||
|
||||
throw utils::error::create_exception(function_name,
|
||||
{
|
||||
"type_type not supported",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
struct i_fs_item {
|
||||
using fs_item_t = std::unique_ptr<i_fs_item>;
|
||||
|
||||
virtual ~i_fs_item() = default;
|
||||
|
||||
[[nodiscard]] virtual auto copy_to(std::string_view to_path,
|
||||
bool overwrite) const -> bool = 0;
|
||||
|
||||
[[nodiscard]] virtual auto copy_to(std::wstring_view new_path, bool overwrite)
|
||||
-> bool {
|
||||
return copy_to(utils::string::to_utf8(new_path), overwrite);
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual auto exists() const -> bool = 0;
|
||||
|
||||
[[nodiscard]] virtual auto get_path() const -> std::string = 0;
|
||||
|
||||
[[nodiscard]] virtual auto get_time(time_type type) const
|
||||
-> std::optional<std::uint64_t>;
|
||||
|
||||
[[nodiscard]] virtual auto is_directory_item() const -> bool = 0;
|
||||
|
||||
[[nodiscard]] auto is_file_item() const -> bool {
|
||||
return not is_directory_item();
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual auto is_symlink() const -> bool = 0;
|
||||
|
||||
[[nodiscard]] virtual auto move_to(std::string_view new_path) -> bool = 0;
|
||||
|
||||
[[nodiscard]] virtual auto move_to(std::wstring_view new_path) -> bool {
|
||||
return move_to(utils::string::to_utf8(new_path));
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual auto remove() -> bool = 0;
|
||||
|
||||
public:
|
||||
[[nodiscard]] virtual operator bool() const = 0;
|
||||
|
||||
protected:
|
||||
i_fs_item() noexcept = default;
|
||||
|
||||
i_fs_item(const i_fs_item &) noexcept = default;
|
||||
|
||||
i_fs_item(i_fs_item &&) noexcept = default;
|
||||
|
||||
auto operator=(i_fs_item &&) noexcept -> i_fs_item & = default;
|
||||
|
||||
auto operator=(const i_fs_item &) noexcept -> i_fs_item & = default;
|
||||
};
|
||||
} // namespace fifthgrid::utils::file
|
||||
|
||||
#endif // FIFTHGRID_INCLUDE_TYPES_FILE_I_FS_ITEM_HPP_
|
||||
124
support/include/utils/unix.hpp
Normal file
124
support/include/utils/unix.hpp
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_UNIX_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_UNIX_HPP_
|
||||
#if !defined(_WIN32)
|
||||
|
||||
#include "utils/common.hpp"
|
||||
#include "utils/config.hpp"
|
||||
|
||||
namespace fifthgrid::utils {
|
||||
#if defined(__linux__)
|
||||
struct autostart_cfg final {
|
||||
std::string app_name;
|
||||
std::optional<std::string> comment;
|
||||
bool enabled{true};
|
||||
std::vector<std::string> exec_args;
|
||||
std::string exec_path;
|
||||
std::optional<std::string> icon_path;
|
||||
std::vector<std::string> only_show_in;
|
||||
bool terminal{false};
|
||||
};
|
||||
#endif // defined(__linux__)
|
||||
|
||||
#if defined(__APPLE__)
|
||||
enum class launchctl_type : std::uint8_t {
|
||||
bootout,
|
||||
bootstrap,
|
||||
kickstart,
|
||||
};
|
||||
|
||||
#if defined(PROJECT_ENABLE_PUGIXML)
|
||||
struct plist_cfg final {
|
||||
std::vector<std::string> args;
|
||||
bool keep_alive{false};
|
||||
std::string label;
|
||||
std::string plist_path;
|
||||
bool run_at_load{false};
|
||||
std::string stderr_log{"/tmp/stderr.log"};
|
||||
std::string stdout_log{"/tmp/stdout.log"};
|
||||
std::string working_dir{"/tmp"};
|
||||
};
|
||||
#endif // defined(PROJECT_ENABLE_PUGIXML)
|
||||
#endif // defined(__APPLE__)
|
||||
|
||||
using passwd_callback_t = std::function<void(struct passwd *pass)>;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
template <typename thread_t>
|
||||
[[nodiscard]] auto convert_to_uint64(const thread_t *thread_ptr)
|
||||
-> std::uint64_t;
|
||||
#else // !defined(__APPLE__)
|
||||
[[nodiscard]] auto convert_to_uint64(const pthread_t &thread) -> std::uint64_t;
|
||||
#endif // defined(__APPLE__)
|
||||
|
||||
#if defined(__linux__)
|
||||
[[nodiscard]] auto create_autostart_entry(const autostart_cfg &cfg,
|
||||
bool overwrite_existing = true)
|
||||
-> bool;
|
||||
#endif // defined(__linux__)
|
||||
|
||||
[[nodiscard]] auto get_last_error_code() -> int;
|
||||
|
||||
[[nodiscard]] auto get_thread_id() -> std::uint64_t;
|
||||
|
||||
[[nodiscard]] auto is_uid_member_of_group(uid_t uid, gid_t gid) -> bool;
|
||||
|
||||
void set_last_error_code(int error_code);
|
||||
|
||||
[[nodiscard]] auto use_getpwuid(uid_t uid, passwd_callback_t callback)
|
||||
-> utils::result;
|
||||
|
||||
#if defined(__linux__)
|
||||
[[nodiscard]] auto remove_autostart_entry(std::string_view name) -> bool;
|
||||
#endif // defined(__linux__)
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#if defined(PROJECT_ENABLE_PUGIXML)
|
||||
[[nodiscard]] auto generate_launchd_plist(const plist_cfg &cfg,
|
||||
bool overwrite_existing = true)
|
||||
-> bool;
|
||||
#endif // defined(PROJECT_ENABLE_PUGIXML)
|
||||
|
||||
#if defined(PROJECT_ENABLE_SPDLOG) || defined(PROJECT_ENABLE_FMT)
|
||||
[[nodiscard]] auto launchctl_command(std::string_view label,
|
||||
launchctl_type type) -> int;
|
||||
|
||||
[[nodiscard]] auto remove_launchd_plist(std::string_view plist_path,
|
||||
std::string_view label,
|
||||
bool should_bootout) -> bool;
|
||||
#endif // defined(PROJECT_ENABLE_SPDLOG) || defined(PROJECT_ENABLE_FMT)
|
||||
#endif // defined(__APPLE__)
|
||||
|
||||
// template implementations
|
||||
#if defined(__APPLE__)
|
||||
template <typename thread_t>
|
||||
[[nodiscard]] auto convert_to_uint64(const thread_t *thread_ptr)
|
||||
-> std::uint64_t {
|
||||
return static_cast<std::uint64_t>(
|
||||
reinterpret_cast<std::uintptr_t>(thread_ptr));
|
||||
}
|
||||
#endif // defined(__APPLE__)
|
||||
} // namespace fifthgrid::utils
|
||||
|
||||
#endif // !defined(_WIN32)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_UNIX_HPP_
|
||||
72
support/include/utils/windows.hpp
Normal file
72
support/include/utils/windows.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef FIFTHGRID_INCLUDE_UTILS_WINDOWS_HPP_
|
||||
#define FIFTHGRID_INCLUDE_UTILS_WINDOWS_HPP_
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include "utils/config.hpp"
|
||||
|
||||
namespace fifthgrid::utils {
|
||||
void create_console();
|
||||
|
||||
void free_console();
|
||||
|
||||
[[nodiscard]] auto get_available_drive_letter(char first = 'a')
|
||||
-> std::optional<std::string_view>;
|
||||
|
||||
[[nodiscard]] auto get_available_drive_letters(char first = 'a')
|
||||
-> std::vector<std::string_view>;
|
||||
|
||||
[[nodiscard]] auto get_local_app_data_directory() -> const std::string &;
|
||||
|
||||
[[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;
|
||||
|
||||
struct shortcut_cfg final {
|
||||
std::wstring arguments;
|
||||
std::wstring exe_path;
|
||||
std::wstring icon_path;
|
||||
std::wstring location{get_startup_folder()};
|
||||
std::wstring shortcut_name;
|
||||
std::wstring working_directory;
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
auto create_shortcut(const shortcut_cfg &cfg, bool overwrite_existing = true)
|
||||
-> bool;
|
||||
|
||||
[[nodiscard]] auto
|
||||
remove_shortcut(std::wstring shortcut_name,
|
||||
const std::wstring &location = get_startup_folder()) -> bool;
|
||||
|
||||
void set_last_error_code(DWORD error_code);
|
||||
} // namespace fifthgrid::utils
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
#endif // FIFTHGRID_INCLUDE_UTILS_WINDOWS_HPP_
|
||||
Reference in New Issue
Block a user