diff --git a/CMakeLists.txt b/CMakeLists.txt index c66e1fbd..660ce6f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,16 @@ include(CheckIncludeFileCXX) include(CheckIncludeFiles) include(ExternalProject) +check_include_files(sys/xattr.h HAS_SETXATTR) +if(HAS_SETXATTR) + add_definitions(-DHAS_SETXATTR) +endif() + +check_include_files("wordexp.h" HAS_WORDEXP_H) +if(HAS_WORDEXP_H) + add_definitions(-DHAS_WORDEXP_H) +endif() + include(cmake/versions.cmake) include(cmake/arch.cmake) include(cmake/os.cmake) diff --git a/cmake/flags.cmake b/cmake/flags.cmake index 0aec7e2c..fbde5686 100644 --- a/cmake/flags.cmake +++ b/cmake/flags.cmake @@ -1,4 +1,7 @@ -list(APPEND PROJECT_COMMON_FLAG_LIST +list(APPEND PROJECT_COMMON_FLAG_LIST + -D_GNU_SOURCE + -D_LARGEFILE_SOURCE + -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_TIME_BITS=64 -march=${PROJECT_MARCH} diff --git a/cmake/functions.cmake b/cmake/functions.cmake index f3ad9b47..a62dac0a 100644 --- a/cmake/functions.cmake +++ b/cmake/functions.cmake @@ -26,21 +26,7 @@ function(set_common_target_options name) endif() endfunction(set_common_target_options) -function(add_project_executable name dependencies libraries) - file(GLOB_RECURSE headers - ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/include/*.h - ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/include/*.hh - ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/include/*.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/include/*.hxx - ) - - file(GLOB_RECURSE sources - ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/src/*.c - ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/src/*.cc - ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/src/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/src/*.cxx - ) - +function(add_project_executable2 name dependencies libraries headers sources) if (PROJECT_WINDOWS_VERSION_RC) list(APPEND sources ${PROJECT_WINDOWS_VERSION_RC}) endif() @@ -62,6 +48,28 @@ function(add_project_executable name dependencies libraries) endif() target_link_libraries(${name} PRIVATE ${libraries}) + + if(PROJECT_ENABLE_SDL AND PROJECT_IS_MINGW) + target_link_libraries(${name} PRIVATE SDL2::SDL2main) + endif () +endfunction(add_project_executable2) + +function(add_project_executable name dependencies libraries) + file(GLOB_RECURSE headers + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/include/*.h + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/include/*.hh + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/include/*.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/include/*.hxx + ) + + file(GLOB_RECURSE sources + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/src/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/src/*.cc + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/src/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/src/*.cxx + ) + + add_project_executable2(${name} "${dependencies}" "${libraries}" "${headers}" "${sources}") endfunction(add_project_executable) function(add_project_library name dependencies libraries additional_sources) @@ -96,7 +104,24 @@ function(add_project_test_executable name dependencies libraries) find_package(GTest ${GTEST_VERSION} REQUIRED) enable_testing() - add_project_executable(${name} "${dependencies}" "${libraries}") + file(GLOB_RECURSE headers + ${PROJECT_3RD_PARTY_DIR}/test/include/*.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/include/*.h + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/include/*.hh + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/include/${name}/include/*.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/include/${name}/include/${name}/include/*.hxx + ) + + file(GLOB_RECURSE sources + ${PROJECT_3RD_PARTY_DIR}/test/src/*.cpp + ${additional_sources} + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/src/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/src/*.cc + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/src/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/src/*.cxx + ) + + add_project_executable2(${name} "${dependencies}" "${libraries}" "${headers}" "${sources}") target_compile_definitions(${name} PRIVATE -DPROJECT_TESTING) @@ -104,6 +129,10 @@ function(add_project_test_executable name dependencies libraries) ${GTEST_INCLUDE_DIRS} ) + target_include_directories(${name} AFTER PRIVATE + ${PROJECT_3RD_PARTY_DIR}/test/include + ) + target_link_libraries(${name} PRIVATE GTest::gtest GTest::gmock diff --git a/cmake/libraries/backward_cpp.cmake b/cmake/libraries/backward_cpp.cmake index 2ab43d57..5e2fe93c 100644 --- a/cmake/libraries/backward_cpp.cmake +++ b/cmake/libraries/backward_cpp.cmake @@ -1,8 +1,8 @@ if(PROJECT_ENABLE_BACKWARD_CPP AND PROJECT_BUILD) - add_definitions(-DPROJECT_ENABLE_BACKWARD_CPP) - if(PROJECT_IS_MINGW) link_libraries(msvcr90) + + add_definitions(-DPROJECT_ENABLE_BACKWARD_CPP) else() link_libraries(bfd) add_definitions(-DBACKWARD_HAS_BFD) diff --git a/cmake/libraries/boost.cmake b/cmake/libraries/boost.cmake index 90d6c8df..cf26ce91 100644 --- a/cmake/libraries/boost.cmake +++ b/cmake/libraries/boost.cmake @@ -1,8 +1,6 @@ set(Boost_USE_STATIC_LIBS ${PROJECT_STATIC_LINK}) if(PROJECT_ENABLE_BOOST) - add_definitions(-DPROJECT_ENABLE_BOOST) - if(PROJECT_ENABLE_LIBBITCOIN_SYSTEM) set(BOOST_MAJOR_VERSION ${BOOST2_MAJOR_VERSION}) set(BOOST_MINOR_VERSION ${BOOST2_MINOR_VERSION}) @@ -40,6 +38,8 @@ if(PROJECT_ENABLE_BOOST) wserialization ) + add_definitions(-DPROJECT_ENABLE_BOOST) + include_directories(BEFORE SYSTEM ${Boost_INCLUDE_DIRS} ) @@ -107,5 +107,7 @@ if(PROJECT_ENABLE_BOOST) ) list(APPEND PROJECT_DEPENDENCIES boost_project) + + add_dependencies(boost_project openssl_project) endif() endif() diff --git a/cmake/libraries/cpp_httplib.cmake b/cmake/libraries/cpp_httplib.cmake index 1082f1e6..bc2f667e 100644 --- a/cmake/libraries/cpp_httplib.cmake +++ b/cmake/libraries/cpp_httplib.cmake @@ -1,15 +1,10 @@ if(PROJECT_ENABLE_CPP_HTTPLIB) if(PROJECT_BUILD) - if(PROJECT_ENABLE_OPENSSL) - add_definitions( - -DCPPHTTPLIB_OPENSSL_SUPPORT - ) - endif() - add_definitions( - -DPROJECT_ENABLE_CPP_HTTPLIB + -DCPPHTTPLIB_OPENSSL_SUPPORT -DCPPHTTPLIB_TCP_NODELAY=true -DCPPHTTPLIB_ZLIB_SUPPORT + -DPROJECT_ENABLE_CPP_HTTPLIB ) elseif(NOT PROJECT_IS_MINGW OR CMAKE_HOST_WIN32) ExternalProject_Add(cpphttplib_project @@ -29,10 +24,9 @@ if(PROJECT_ENABLE_CPP_HTTPLIB) list(APPEND PROJECT_DEPENDENCIES cpphttplib_project) - add_dependencies(cpphttplib_project curl_project) - - if(PROJECT_ENABLE_OPENSSL) - add_dependencies(cpphttplib_project openssl_project) - endif() + add_dependencies(cpphttplib_project + curl_project + openssl_project + ) endif() endif() diff --git a/cmake/libraries/curl.cmake b/cmake/libraries/curl.cmake index 2fccf58f..c2909a83 100644 --- a/cmake/libraries/curl.cmake +++ b/cmake/libraries/curl.cmake @@ -48,8 +48,6 @@ if(PROJECT_ENABLE_CURL) list(APPEND PROJECT_DEPENDENCIES curl_project) - if(PROJECT_ENABLE_OPENSSL) - add_dependencies(curl_project openssl_project) - endif() + add_dependencies(curl_project openssl_project) endif() endif() diff --git a/cmake/libraries/fuse.cmake b/cmake/libraries/fuse.cmake index af91fb2c..bb9883fe 100644 --- a/cmake/libraries/fuse.cmake +++ b/cmake/libraries/fuse.cmake @@ -1,6 +1,7 @@ if(PROJECT_ENABLE_FUSE AND NOT PROJECT_IS_MINGW) if(PROJECT_BUILD) add_definitions(-DPROJECT_ENABLE_FUSE) + include_directories(BEFORE SYSTEM ${PROJECT_FUSE_INCLUDE_DIRS}) if(PROJECT_FUSE STREQUAL "fuse3") @@ -18,11 +19,6 @@ if(PROJECT_ENABLE_FUSE AND NOT PROJECT_IS_MINGW) link_libraries(fuse) endif() endif() - - check_include_files(sys/xattr.h HAS_SETXATTR) - if(HAS_SETXATTR) - add_definitions(-DHAS_SETXATTR) - endif() else() pkg_check_modules(LIBFUSE3 fuse3>=3.0.0) if(LIBFUSE3_FOUND) diff --git a/repertory/librepertory/include/common.hpp b/repertory/librepertory/include/common.hpp index 441f9154..7322839e 100644 --- a/repertory/librepertory/include/common.hpp +++ b/repertory/librepertory/include/common.hpp @@ -48,113 +48,7 @@ #if defined(__cplusplus) REPERTORY_IGNORE_WARNINGS_ENABLE() - -#if defined(_WIN32) -#define WINVER 0x0602 -#define _WIN32_WINNT WINVER -#define WIN32_LEAN_AND_MEAN - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(__linux__) -#include -#endif -#include -#if defined(HAS_SETXATTR) -#include -#include -#endif -#if defined(__APPLE__) -#include -#include -#include -#endif -#if defined(__APPLE__) -#include -#include -#endif -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sodium.h" -template -[[nodiscard]] inline auto repertory_rand() -> data_type { - data_type ret{}; - randombytes_buf(&ret, sizeof(ret)); - return ret; -} - -#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/serialization/vector.hpp" -#include "curl/curl.h" -#include "curl/multi.h" -#include "json.hpp" -#include "sqlite3.h" -#include "uuid.h" - -#if defined(_WIN32) -#include -#include "winfsp/winfsp.hpp" -#else -#if FUSE_USE_VERSION >= 30 -#include -#include -#else -#include -#endif -#endif - -#include "pugixml.hpp" - -#include "httplib.h" - +#include "utils/config.hpp" REPERTORY_IGNORE_WARNINGS_DISABLE() using namespace std::chrono_literals; @@ -279,26 +173,6 @@ inline constexpr const auto NANOS_PER_SECOND = 1000000000L; #endif #endif -#ifndef fstat64 -#define fstat64 fstat -#endif - -#ifndef pread64 -#define pread64 pread -#endif - -#ifndef pwrite64 -#define pwrite64 pwrite -#endif - -#ifndef stat64 -#define stat64 stat -#endif - -#ifndef statfs64 -#define statfs64 statfs -#endif - #define WINFSP_ALLOCATION_UNIT UINT64(4096U) #if defined(_WIN32) @@ -409,13 +283,6 @@ using FileInfo = FSP_FSCTL_FILE_INFO; using namespace Fsp; -namespace { -template struct overloaded : Ts... { - using Ts::operator()...; -}; -template overloaded(Ts...) -> overloaded; -} // namespace - #define INTERFACE_SETUP(name) \ public: \ name(const name &) noexcept = delete; \ diff --git a/repertory/librepertory/include/drives/fuse/fuse_base.hpp b/repertory/librepertory/include/drives/fuse/fuse_base.hpp index 9b683ab9..a3998e6d 100644 --- a/repertory/librepertory/include/drives/fuse/fuse_base.hpp +++ b/repertory/librepertory/include/drives/fuse/fuse_base.hpp @@ -24,7 +24,7 @@ #if !defined(_WIN32) #include "events/event_system.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" namespace repertory { class app_config; diff --git a/repertory/librepertory/include/drives/remote/remote_server_base.hpp b/repertory/librepertory/include/drives/remote/remote_server_base.hpp index b511f970..87ebb885 100644 --- a/repertory/librepertory/include/drives/remote/remote_server_base.hpp +++ b/repertory/librepertory/include/drives/remote/remote_server_base.hpp @@ -32,7 +32,7 @@ #include "types/remote.hpp" #include "types/repertory.hpp" #include "utils/base64.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #define REPERTORY_DIRECTORY_PAGE_SIZE std::size_t(100U) diff --git a/repertory/librepertory/include/events/event_system.hpp b/repertory/librepertory/include/events/event_system.hpp index 4f642774..63764a80 100644 --- a/repertory/librepertory/include/events/event_system.hpp +++ b/repertory/librepertory/include/events/event_system.hpp @@ -24,7 +24,7 @@ #include "events/event.hpp" #include "events/t_event_system.hpp" -#include "utils/string_utils.hpp" +#include "utils/string.hpp" namespace repertory { using event_system = t_event_system; diff --git a/repertory/librepertory/include/events/t_event_system.hpp b/repertory/librepertory/include/events/t_event_system.hpp index d21e0f34..a6ee5c22 100644 --- a/repertory/librepertory/include/events/t_event_system.hpp +++ b/repertory/librepertory/include/events/t_event_system.hpp @@ -23,6 +23,7 @@ #define INCLUDE_EVENTS_T_EVENT_SYSTEM_HPP_ #include "events/event.hpp" +#include "utils/collection.hpp" #include "utils/utils.hpp" namespace repertory { @@ -151,14 +152,14 @@ public: void release(event_consumer *consumer) { recur_mutex_lock lock(consumer_mutex_); - auto iter = - std::find_if(event_consumers_.begin(), event_consumers_.end(), - [&](const auto &item) -> bool { - return utils::collection_includes(item.second, consumer); - }); + auto iter = std::find_if(event_consumers_.begin(), event_consumers_.end(), + [&](const auto &item) -> bool { + return utils::collection::includes(item.second, + consumer); + }); if (iter != event_consumers_.end()) { - utils::remove_element_from((*iter).second, consumer); + utils::collection::remove_element((*iter).second, consumer); } } diff --git a/repertory/librepertory/include/types/repertory.hpp b/repertory/librepertory/include/types/repertory.hpp index 99993ab3..71498417 100644 --- a/repertory/librepertory/include/types/repertory.hpp +++ b/repertory/librepertory/include/types/repertory.hpp @@ -102,6 +102,12 @@ enum class api_error { api_error_to_string(const api_error &error) -> const std::string &; enum class download_type { direct, fallback, ring_buffer }; +[[nodiscard]] auto +download_type_from_string(std::string type, + const download_type &default_type) -> download_type; + +[[nodiscard]] auto +download_type_to_string(const download_type &type) -> std::string; enum class exit_code : std::int32_t { success, diff --git a/repertory/librepertory/include/types/s3.hpp b/repertory/librepertory/include/types/s3.hpp index ef10eab3..03ff98b9 100644 --- a/repertory/librepertory/include/types/s3.hpp +++ b/repertory/librepertory/include/types/s3.hpp @@ -23,7 +23,7 @@ #define INCLUDE_TYPES_S3_HPP_ #include "types/repertory.hpp" -#include "utils/string_utils.hpp" +#include "utils/string.hpp" #include "utils/utils.hpp" namespace repertory { diff --git a/repertory/librepertory/include/utils/encrypt.hpp b/repertory/librepertory/include/utils/encrypt.hpp index f321188a..3bb1848e 100644 --- a/repertory/librepertory/include/utils/encrypt.hpp +++ b/repertory/librepertory/include/utils/encrypt.hpp @@ -23,6 +23,7 @@ #define INCLUDE_UTILS_ENCRYPT_HPP_ #include "types/repertory.hpp" +#include "utils/encryption.hpp" #include "utils/encrypting_reader.hpp" namespace repertory::utils::encryption { @@ -40,122 +41,6 @@ using reader_func = std::function api_error; - -[[nodiscard]] auto generate_key(std::string_view encryption_token) -> key_type; - -// Implementations -template -[[nodiscard]] inline auto -decrypt_data(const key_type &key, const unsigned char *buffer, - std::size_t buffer_size, result &res) -> bool { - const auto header_size = - static_cast(encrypting_reader::get_header_size()); - if (buffer_size > header_size) { - const std::uint32_t size = - boost::endian::native_to_big(static_cast(buffer_size)); - res.resize(buffer_size - header_size); - return crypto_aead_xchacha20poly1305_ietf_decrypt_detached( - reinterpret_cast(res.data()), nullptr, - &buffer[header_size], res.size(), - &buffer[crypto_aead_xchacha20poly1305_IETF_NPUBBYTES], - reinterpret_cast(&size), sizeof(size), - buffer, key.data()) == 0; - } - - return false; -} - -template -[[nodiscard]] inline auto decrypt_data(const key_type &key, const buffer &buf, - result &res) -> bool { - return decrypt_data( - key, reinterpret_cast(buf.data()), buf.size(), - res); -} - -template -[[nodiscard]] inline auto decrypt_data(std::string_view encryption_token, - const buffer &buf, result &res) -> bool { - return decrypt_data(generate_key(encryption_token), buf, res); -} - -template -[[nodiscard]] inline auto -decrypt_data(std::string_view encryption_token, const unsigned char *buffer, - std::size_t buffer_size, result &res) -> bool { - return decrypt_data(generate_key(encryption_token), buffer, - buffer_size, res); -} - -template -inline void -encrypt_data(const std::array &iv, - const key_type &key, const unsigned char *buffer, - std::size_t buffer_size, result &res) { - std::array mac{}; - - const auto header_size = - static_cast(encrypting_reader::get_header_size()); - - const std::uint32_t size = boost::endian::native_to_big( - static_cast(buffer_size + header_size)); - - res.resize(buffer_size + header_size); - - unsigned long long mac_length{}; - if (crypto_aead_xchacha20poly1305_ietf_encrypt_detached( - reinterpret_cast(&res[header_size]), mac.data(), - &mac_length, buffer, buffer_size, - reinterpret_cast(&size), sizeof(size), nullptr, - iv.data(), key.data()) != 0) { - throw std::runtime_error("encryption failed"); - } - - std::memcpy(res.data(), iv.data(), iv.size()); - std::memcpy(&res[iv.size()], mac.data(), mac.size()); -} - -template -inline void encrypt_data(const key_type &key, const unsigned char *buffer, - std::size_t buffer_size, result &res) { - std::array iv{}; - randombytes_buf(iv.data(), iv.size()); - - encrypt_data(iv, key, buffer, buffer_size, res); -} - -template -inline void encrypt_data(std::string_view encryption_token, - const unsigned char *buffer, std::size_t buffer_size, - result &res) { - encrypt_data(generate_key(encryption_token), buffer, buffer_size, - res); -} - -template -inline void encrypt_data(std::string_view encryption_token, const buffer &buf, - result &res) { - encrypt_data(generate_key(encryption_token), - reinterpret_cast(buf.data()), - buf.size(), res); -} - -template -inline void encrypt_data(const key_type &key, const buffer &buf, result &res) { - encrypt_data(key, reinterpret_cast(buf.data()), - buf.size(), res); -} - -template -inline void -encrypt_data(const std::array &iv, - const key_type &key, const buffer &buf, result &res) { - encrypt_data(iv, key, - reinterpret_cast(buf.data()), - buf.size(), res); -} } // namespace repertory::utils::encryption #endif // INCLUDE_UTILS_ENCRYPT_HPP_ diff --git a/repertory/librepertory/include/utils/file_utils.hpp b/repertory/librepertory/include/utils/file_utils.hpp index 7fb8ce89..aa80fefa 100644 --- a/repertory/librepertory/include/utils/file_utils.hpp +++ b/repertory/librepertory/include/utils/file_utils.hpp @@ -23,6 +23,7 @@ #define INCLUDE_UTILS_FILE_UTILS_HPP_ #include "types/repertory.hpp" +#include "utils/file.hpp" #include "utils/native_file.hpp" namespace repertory::utils::file { @@ -62,16 +63,9 @@ get_free_drive_space(const std::string &path) -> std::uint64_t; [[nodiscard]] auto get_total_drive_space(const std::string &path) -> std::uint64_t; -[[nodiscard]] auto get_file_size(std::string_view path, - std::uint64_t &file_size) -> bool; - [[nodiscard]] auto get_modified_time(const std::string &path, std::uint64_t &modified) -> bool; -[[nodiscard]] auto is_directory(const std::string &path) -> bool; - -[[nodiscard]] auto is_file(const std::string &path) -> bool; - [[nodiscard]] auto is_modified_date_older_than(const std::string &path, const std::chrono::hours &hours) -> bool; @@ -81,16 +75,11 @@ is_modified_date_older_than(const std::string &path, [[nodiscard]] auto read_file_lines(const std::string &path) -> std::vector; -[[nodiscard]] auto read_json_file(const std::string &path, json &data) -> bool; - [[nodiscard]] auto reset_modified_time(const std::string &path) -> bool; [[nodiscard]] auto retry_delete_directory(const std::string &dir) -> bool; [[nodiscard]] auto retry_delete_file(const std::string &file) -> bool; - -[[nodiscard]] auto write_json_file(const std::string &path, - const json &j) -> bool; } // namespace repertory::utils::file #endif // INCLUDE_UTILS_FILE_UTILS_HPP_ diff --git a/repertory/librepertory/include/utils/path_utils.hpp b/repertory/librepertory/include/utils/path_utils.hpp deleted file mode 100644 index d5ca6452..00000000 --- a/repertory/librepertory/include/utils/path_utils.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - Copyright <2018-2024> - - 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 INCLUDE_UTILS_PATH_UTILS_HPP_ -#define INCLUDE_UTILS_PATH_UTILS_HPP_ - -namespace repertory::utils::path { -#if defined(_WIN32) -static const std::string directory_seperator = "\\"; -static const std::string not_directory_seperator = "/"; -#else -static const std::string directory_seperator = "/"; -static const std::string not_directory_seperator = "\\"; -#endif - -// Prototypes -[[nodiscard]] auto absolute(std::string path) -> std::string; - -[[nodiscard]] auto -combine(std::string path, const std::vector &paths) -> std::string; - -[[nodiscard]] auto create_api_path(std::string path) -> std::string; - -[[nodiscard]] auto finalize(std::string path) -> std::string; - -auto format_path(std::string &path, const std::string &sep, - const std::string ¬_sep) -> std::string &; - -[[nodiscard]] auto get_parent_api_path(const std::string &path) -> std::string; - -#if !defined(_WIN32) -[[nodiscard]] auto get_parent_directory(std::string path) -> std::string; -#endif - -[[nodiscard]] auto is_ads_file_path(const std::string &path) -> bool; - -[[nodiscard]] auto is_trash_directory(std::string path) -> bool; - -[[nodiscard]] auto remove_file_name(std::string path) -> std::string; - -#if !defined(_WIN32) -[[nodiscard]] auto resolve(std::string path) -> std::string; -#endif - -[[nodiscard]] auto strip_to_file_name(std::string path) -> std::string; -} // namespace repertory::utils::path - -#endif // INCLUDE_UTILS_PATH_UTILS_HPP_ diff --git a/repertory/librepertory/include/utils/string_utils.hpp b/repertory/librepertory/include/utils/string_utils.hpp deleted file mode 100644 index 0c15c472..00000000 --- a/repertory/librepertory/include/utils/string_utils.hpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - Copyright <2018-2024> - - 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 INCLUDE_UTILS_STRING_UTILS_HPP_ -#define INCLUDE_UTILS_STRING_UTILS_HPP_ - -namespace repertory::utils::string { -// Prototypes -constexpr auto begins_with(std::string_view str, std::string_view val) -> bool { - return (str.find(val) == 0U); -} - -constexpr auto contains(std::string_view str, std::string_view search) -> bool { - return (str.find(search) != std::string_view::npos); -} - -[[nodiscard]] /* constexpr c++20 */ auto -ends_with(std::string_view str, std::string_view val) -> bool; - -[[nodiscard]] auto from_bool(bool val) -> std::string; - -[[nodiscard]] auto -from_dynamic_bitset(const boost::dynamic_bitset<> &bitset) -> std::string; - -[[nodiscard]] auto from_utf8(std::string_view str) -> std::wstring; - -[[nodiscard]] /* constexpr c++20 */ auto -is_numeric(std::string_view str) -> bool; - -[[nodiscard]] auto join(const std::vector &arr, - const char &delim) -> std::string; - -auto left_trim(std::string &str) -> std::string &; - -auto left_trim(std::string &str, const char &trim_ch) -> std::string &; - -auto replace(std::string &src, const char &character, - const char &with) -> std::string &; - -auto replace(std::string &src, const std::string &find, const std::string &with, - size_t start_pos = 0) -> std::string &; - -[[nodiscard]] auto replace_copy(std::string src, const char &character, - const char &with) -> std::string; - -[[nodiscard]] auto replace_copy(std::string src, const std::string &find, - const std::string &with, - size_t start_pos = 0) -> std::string; - -auto right_trim(std::string &str) -> std::string &; - -auto right_trim(std::string &str, const char &trim_ch) -> std::string &; - -[[nodiscard]] auto split(const std::string &str, const char &delim, - bool should_trim = true) -> std::vector; - -[[nodiscard]] auto to_bool(std::string val) -> bool; - -[[nodiscard]] auto to_double(const std::string &str) -> double; - -[[nodiscard]] auto -to_dynamic_bitset(const std::string &val) -> boost::dynamic_bitset<>; - -[[nodiscard]] auto to_lower(std::string str) -> std::string; - -[[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; - -[[nodiscard]] auto to_upper(std::string str) -> std::string; - -[[nodiscard]] auto to_utf8(std::string_view str) -> std::string; - -[[nodiscard]] auto to_utf8(std::wstring_view str) -> std::string; - -auto trim(std::string &str) -> std::string &; - -auto trim(std::string &str, const char &trim_ch) -> std::string &; - -[[nodiscard]] auto trim_copy(std::string str) -> std::string; - -[[nodiscard]] auto trim_copy(std::string str, - const char &trim_ch) -> std::string; -} // namespace repertory::utils::string - -#endif // INCLUDE_UTILS_STRING_UTILS_HPP_ diff --git a/repertory/librepertory/include/utils/unix/unix_utils.hpp b/repertory/librepertory/include/utils/unix/unix_utils.hpp index e5391313..df0218b5 100644 --- a/repertory/librepertory/include/utils/unix/unix_utils.hpp +++ b/repertory/librepertory/include/utils/unix/unix_utils.hpp @@ -25,6 +25,7 @@ #include "types/remote.hpp" #include "types/repertory.hpp" +#include "utils/unix.hpp" namespace repertory::utils { #if defined(__linux__) @@ -35,25 +36,8 @@ inline const std::array attribute_namespaces = { "user", }; #endif - -#if defined(__APPLE__) -template -[[nodiscard]] auto convert_to_uint64(const t *ptr) -> std::uint64_t; -#else -[[nodiscard]] auto convert_to_uint64(const pthread_t &thread) -> std::uint64_t; -#endif - [[nodiscard]] auto from_api_error(const api_error &err) -> int; -[[nodiscard]] auto get_last_error_code() -> int; - -[[nodiscard]] auto get_thread_id() -> std::uint64_t; - -[[nodiscard]] auto is_uid_member_of_group(const uid_t &uid, - const gid_t &gid) -> bool; - -void set_last_error_code(int error_code); - [[nodiscard]] auto to_api_error(int err) -> api_error; [[nodiscard]] auto unix_error_to_windows(int err) -> std::int32_t; @@ -61,22 +45,12 @@ void set_last_error_code(int error_code); [[nodiscard]] auto unix_time_to_windows_time(const remote::file_time &file_time) -> UINT64; -void use_getpwuid(uid_t uid, std::function callback); - void windows_create_to_unix(const UINT32 &create_options, const UINT32 &granted_access, std::uint32_t &flags, remote::file_mode &mode); [[nodiscard]] auto windows_time_to_unix_time(std::uint64_t win_time) -> remote::file_time; - -// template implementations -#if defined(__APPLE__) -template -[[nodiscard]] auto convert_to_uint64(const t *v) -> std::uint64_t { - return static_cast(reinterpret_cast(v)); -} -#endif } // namespace repertory::utils #endif // !_WIN32 diff --git a/repertory/librepertory/include/utils/utils.hpp b/repertory/librepertory/include/utils/utils.hpp index c381a5ca..eded0e3b 100644 --- a/repertory/librepertory/include/utils/utils.hpp +++ b/repertory/librepertory/include/utils/utils.hpp @@ -32,73 +32,19 @@ void calculate_allocation_size(bool directory, std::uint64_t file_size, UINT64 allocation_size, std::string &allocation_meta_size); -[[nodiscard]] auto calculate_read_size(const uint64_t &total_size, - std::size_t read_size, - const uint64_t &offset) -> std::size_t; - -template -[[nodiscard]] auto collection_excludes(t collection, - const typename t::value_type &val) - -> bool; - -template -[[nodiscard]] auto collection_includes(t collection, - const typename t::value_type &val) - -> bool; - -[[nodiscard]] auto compare_version_strings(std::string version1, - std::string version2) -> int; - [[nodiscard]] auto convert_api_date(const std::string &date) -> std::uint64_t; [[nodiscard]] auto create_curl() -> CURL *; -[[nodiscard]] auto create_uuid_string() -> std::string; - -[[nodiscard]] auto create_volume_label(const provider_type &prov) - -> std::string; - -template -[[nodiscard]] auto divide_with_ceiling(const t &n, const t &d) -> t; - -[[nodiscard]] auto download_type_from_string(std::string type, - const download_type &default_type) - -> download_type; - -[[nodiscard]] auto download_type_to_string(const download_type &type) - -> std::string; - -template -[[nodiscard]] auto from_hex_string(const std::string &str, t &val) -> bool; - -[[nodiscard]] auto generate_random_string(std::uint16_t length) -> std::string; +[[nodiscard]] auto +create_volume_label(const provider_type &prov) -> std::string; [[nodiscard]] auto get_attributes_from_meta(const api_meta_map &meta) -> DWORD; -[[nodiscard]] auto get_environment_variable(const std::string &variable) - -> std::string; - -[[nodiscard]] auto get_file_time_now() -> std::uint64_t; - -void get_local_time_now(struct tm &local_time); - -[[nodiscard]] auto get_next_available_port(std::uint16_t first_port, - std::uint16_t &available_port) - -> bool; - -[[nodiscard]] auto get_time_now() -> std::uint64_t; - -template -[[nodiscard]] auto random_between(const data_type &begin, const data_type &end) - -> data_type; - -template -void remove_element_from(t &collection, const typename t::value_type &val); - [[nodiscard]] auto reset_curl(CURL *curl_handle) -> CURL *; -[[nodiscard]] auto retryable_action(const std::function &action) - -> bool; +[[nodiscard]] auto +retryable_action(const std::function &action) -> bool; void spin_wait_for_mutex(std::function complete, std::condition_variable &cond, std::mutex &mtx, @@ -107,75 +53,6 @@ void spin_wait_for_mutex(std::function complete, void spin_wait_for_mutex(bool &complete, std::condition_variable &cond, std::mutex &mtx, const std::string &text = ""); -template -[[nodiscard]] auto to_hex_string(const collection_t &collection) -> std::string; - -// template implementations -template -[[nodiscard]] auto collection_excludes(t collection, - const typename t::value_type &val) - -> bool { - return std::find(collection.begin(), collection.end(), val) == - collection.end(); -} - -template -[[nodiscard]] auto collection_includes(t collection, - const typename t::value_type &val) - -> bool { - return std::find(collection.begin(), collection.end(), val) != - collection.end(); -} - -template -[[nodiscard]] auto divide_with_ceiling(const t &n, const t &d) -> t { - return n ? (n / d) + (n % d != 0) : 0; -} - -template -[[nodiscard]] auto from_hex_string(const std::string &str, t &val) -> bool { - static constexpr const auto base16 = 16; - - val.clear(); - if (not(str.length() % 2U)) { - for (std::size_t i = 0U; i < str.length(); i += 2U) { - val.emplace_back(static_cast( - strtol(str.substr(i, 2U).c_str(), nullptr, base16))); - } - return true; - } - - return false; -} - -template -[[nodiscard]] auto random_between(const data_type &begin, const data_type &end) - -> data_type { - return begin + repertory_rand() % ((end + data_type{1}) - begin); -} - -template -void remove_element_from(collection_t &collection, - const typename collection_t::value_type &value) { - collection.erase(std::remove(collection.begin(), collection.end(), value), - collection.end()); -} - -template -[[nodiscard]] auto to_hex_string(const collection_t &collection) - -> std::string { - static_assert(sizeof(typename collection_t::value_type) == 1U, - "value_type must be 1 byte in size"); - static constexpr const auto mask = 0xFF; - - std::stringstream stream; - for (const auto &val : collection) { - stream << std::setfill('0') << std::setw(2) << std::hex - << (static_cast(val) & mask); - } - - return stream.str(); -} } // namespace repertory::utils #endif // INCLUDE_UTILS_UTILS_HPP_ diff --git a/repertory/librepertory/include/utils/windows/windows_utils.hpp b/repertory/librepertory/include/utils/windows/windows_utils.hpp index fb6719b3..52b2c555 100644 --- a/repertory/librepertory/include/utils/windows/windows_utils.hpp +++ b/repertory/librepertory/include/utils/windows/windows_utils.hpp @@ -25,15 +25,9 @@ #include "types/remote.hpp" #include "types/repertory.hpp" +#include "utils/windows.hpp" namespace repertory::utils { -[[nodiscard]] auto -filetime_to_unix_time(const FILETIME &ft) -> remote::file_time; - -[[nodiscard]] auto get_last_error_code() -> DWORD; - -[[nodiscard]] auto get_local_app_data_directory() -> const std::string &; - [[nodiscard]] auto get_accessed_time_from_meta(const api_meta_map &meta) -> std::uint64_t; @@ -46,29 +40,14 @@ get_creation_time_from_meta(const api_meta_map &meta) -> std::uint64_t; [[nodiscard]] auto get_written_time_from_meta(const api_meta_map &meta) -> std::uint64_t; -[[nodiscard]] auto get_thread_id() -> std::uint64_t; - -[[nodiscard]] auto is_process_elevated() -> bool; - -[[nodiscard]] auto run_process_elevated(std::vector args) -> int; - -void set_last_error_code(DWORD errorCode); - [[nodiscard]] auto from_api_error(const api_error &e) -> NTSTATUS; -auto strptime(const char *s, const char *f, struct tm *tm) -> const char *; - [[nodiscard]] auto unix_access_mask_to_windows(std::int32_t mask) -> int; [[nodiscard]] auto unix_open_flags_to_flags_and_perms(const remote::file_mode &mode, const remote::open_flags &flags, std::int32_t &perms) -> int; - -void unix_time_to_filetime(const remote::file_time &ts, FILETIME &ft); - -[[nodiscard]] auto -time64_to_unix_time(const __time64_t &t) -> remote::file_time; } // namespace repertory::utils #endif // _WIN32 diff --git a/repertory/librepertory/src/app_config.cpp b/repertory/librepertory/src/app_config.cpp index 24b25f13..df9e312a 100644 --- a/repertory/librepertory/src/app_config.cpp +++ b/repertory/librepertory/src/app_config.cpp @@ -24,7 +24,7 @@ #include "types/startup_exception.hpp" #include "utils/error_utils.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/unix/unix_utils.hpp" #include "utils/utils.hpp" diff --git a/repertory/librepertory/src/comm/curl/curl_comm.cpp b/repertory/librepertory/src/comm/curl/curl_comm.cpp index ffb4fcf4..c5d256be 100644 --- a/repertory/librepertory/src/comm/curl/curl_comm.cpp +++ b/repertory/librepertory/src/comm/curl/curl_comm.cpp @@ -22,8 +22,8 @@ #include "comm/curl/curl_comm.hpp" #include "types/repertory.hpp" -#include "utils/path_utils.hpp" -#include "utils/string_utils.hpp" +#include "utils/path.hpp" +#include "utils/string.hpp" namespace repertory { const curl_comm::write_callback curl_comm::write_data = @@ -92,8 +92,8 @@ auto curl_comm::construct_url(CURL *curl, const std::string &relative_path, relative_path, url); } -auto curl_comm::create_host_config(const s3_config &cfg, bool use_s3_path_style) - -> host_config { +auto curl_comm::create_host_config(const s3_config &cfg, + bool use_s3_path_style) -> host_config { host_config host_cfg{}; host_cfg.api_password = cfg.secret_key; host_cfg.api_user = cfg.access_key; diff --git a/repertory/librepertory/src/comm/curl/requests/http_put_file.cpp b/repertory/librepertory/src/comm/curl/requests/http_put_file.cpp index f32f81a7..94010077 100644 --- a/repertory/librepertory/src/comm/curl/requests/http_put_file.cpp +++ b/repertory/librepertory/src/comm/curl/requests/http_put_file.cpp @@ -21,7 +21,7 @@ */ #include "comm/curl/requests/http_put_file.hpp" -#include "utils/string_utils.hpp" +#include "utils/string.hpp" namespace repertory::curl::requests { auto http_put_file::set_method(CURL *curl, stop_type &stop_requested) const diff --git a/repertory/librepertory/src/comm/packet/packet_client.cpp b/repertory/librepertory/src/comm/packet/packet_client.cpp index a07e9056..80d1d660 100644 --- a/repertory/librepertory/src/comm/packet/packet_client.cpp +++ b/repertory/librepertory/src/comm/packet/packet_client.cpp @@ -23,6 +23,7 @@ #include "events/events.hpp" #include "types/repertory.hpp" +#include "utils/collection.hpp" #include "utils/error_utils.hpp" #include "utils/timeout.hpp" #include "version.hpp" @@ -102,7 +103,7 @@ auto packet_client::get_client() -> std::shared_ptr { connect(*ret); } else { ret = clients_[0U]; - utils::remove_element_from(clients_, ret); + utils::collection::remove_element(clients_, ret); clients_lock.unlock(); } } diff --git a/repertory/librepertory/src/comm/packet/packet_server.cpp b/repertory/librepertory/src/comm/packet/packet_server.cpp index b38443fb..c0661a8d 100644 --- a/repertory/librepertory/src/comm/packet/packet_server.cpp +++ b/repertory/librepertory/src/comm/packet/packet_server.cpp @@ -26,7 +26,7 @@ #include "events/events.hpp" #include "types/repertory.hpp" #include "utils/error_utils.hpp" -#include "utils/string_utils.hpp" +#include "utils/string.hpp" #include "utils/utils.hpp" namespace repertory { diff --git a/repertory/librepertory/src/drives/directory_cache.cpp b/repertory/librepertory/src/drives/directory_cache.cpp index c475cd70..34ccbc41 100644 --- a/repertory/librepertory/src/drives/directory_cache.cpp +++ b/repertory/librepertory/src/drives/directory_cache.cpp @@ -23,6 +23,7 @@ #include "drives/directory_iterator.hpp" #include "types/repertory.hpp" +#include "utils/collection.hpp" #include "utils/utils.hpp" namespace repertory { @@ -72,7 +73,7 @@ void directory_cache::remove_directory(std::uint64_t handle) { handle) != kv.second.handles.end(); }); if (it != directory_lookup_.end()) { - utils::remove_element_from(it->second.handles, handle); + utils::collection::remove_element(it->second.handles, handle); if (it->second.handles.empty()) { directory_lookup_.erase(it); } diff --git a/repertory/librepertory/src/drives/directory_iterator.cpp b/repertory/librepertory/src/drives/directory_iterator.cpp index b3dc5fb1..d5829aab 100644 --- a/repertory/librepertory/src/drives/directory_iterator.cpp +++ b/repertory/librepertory/src/drives/directory_iterator.cpp @@ -22,7 +22,7 @@ #include "drives/directory_iterator.hpp" #include "utils/error_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" namespace repertory { #if !defined(_WIN32) diff --git a/repertory/librepertory/src/drives/fuse/fuse_base.cpp b/repertory/librepertory/src/drives/fuse/fuse_base.cpp index 07c40d0a..836ba8ff 100644 --- a/repertory/librepertory/src/drives/fuse/fuse_base.cpp +++ b/repertory/librepertory/src/drives/fuse/fuse_base.cpp @@ -29,9 +29,10 @@ #include "events/events.hpp" #include "initialize.hpp" #include "providers/i_provider.hpp" +#include "utils/collection.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" -#include "utils/string_utils.hpp" +#include "utils/path.hpp" +#include "utils/string.hpp" #include "utils/utils.hpp" namespace repertory { @@ -615,7 +616,7 @@ auto fuse_base::parse_args(std::vector &args) -> int { force_no_console = true; } } - utils::remove_element_from(args, "-nc"); + utils::collection::remove_element(args, "-nc"); for (std::size_t i = 1u; i < args.size(); i++) { if (args[i] == "-f") { diff --git a/repertory/librepertory/src/drives/fuse/fuse_drive.cpp b/repertory/librepertory/src/drives/fuse/fuse_drive.cpp index f5c5f7ee..2f09a9d1 100644 --- a/repertory/librepertory/src/drives/fuse/fuse_drive.cpp +++ b/repertory/librepertory/src/drives/fuse/fuse_drive.cpp @@ -39,6 +39,7 @@ #include "types/repertory.hpp" #include "types/startup_exception.hpp" #include "utils/base64.hpp" +#include "utils/collection.hpp" #include "utils/error_utils.hpp" #include "utils/file_utils.hpp" #include "utils/polling.hpp" @@ -905,7 +906,7 @@ auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size, api_meta_map meta; if ((res = provider_.get_item_meta(api_path, meta)) == api_error::success) { for (const auto &meta_item : meta) { - if (utils::collection_excludes(META_USED_NAMES, meta_item.first)) { + if (utils::collection::excludes(META_USED_NAMES, meta_item.first)) { auto attribute_name = meta_item.first; #if defined(__APPLE__) if (attribute_name != G_KAUTH_FILESEC_XATTR) { @@ -948,7 +949,7 @@ auto fuse_drive::removexattr_impl(std::string api_path, return check_and_perform( api_path, X_OK, [&](api_meta_map &meta) -> api_error { if ((meta.find(name) != meta.end()) && - (utils::collection_excludes(META_USED_NAMES, name))) { + (utils::collection::excludes(META_USED_NAMES, name))) { return provider_.remove_item_meta(api_path, attribute_name); } @@ -988,8 +989,8 @@ auto fuse_drive::setxattr_impl(std::string api_path, const char *name, if (utils::string::contains(attribute_name, " .") || utils::string::contains(attribute_name, ". ") #if !defined(__APPLE__) - || utils::collection_excludes(utils::attribute_namespaces, - attribute_namespace) + || utils::collection::excludes(utils::attribute_namespaces, + attribute_namespace) #endif ) { return api_error::not_supported; diff --git a/repertory/librepertory/src/drives/fuse/remotefuse/remote_client.cpp b/repertory/librepertory/src/drives/fuse/remotefuse/remote_client.cpp index e027689d..3a32ecb1 100644 --- a/repertory/librepertory/src/drives/fuse/remotefuse/remote_client.cpp +++ b/repertory/librepertory/src/drives/fuse/remotefuse/remote_client.cpp @@ -23,7 +23,7 @@ #include "app_config.hpp" #include "comm/packet/packet.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" namespace repertory::remote_fuse { remote_client::remote_client(const app_config &config) diff --git a/repertory/librepertory/src/drives/fuse/remotefuse/remote_fuse_drive.cpp b/repertory/librepertory/src/drives/fuse/remotefuse/remote_fuse_drive.cpp index f9684d06..14b180c6 100644 --- a/repertory/librepertory/src/drives/fuse/remotefuse/remote_fuse_drive.cpp +++ b/repertory/librepertory/src/drives/fuse/remotefuse/remote_fuse_drive.cpp @@ -34,7 +34,7 @@ #include "types/remote.hpp" #include "utils/error_utils.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/utils.hpp" namespace repertory::remote_fuse { diff --git a/repertory/librepertory/src/drives/fuse/remotefuse/remote_server.cpp b/repertory/librepertory/src/drives/fuse/remotefuse/remote_server.cpp index fbf5b9d5..71c5ce06 100644 --- a/repertory/librepertory/src/drives/fuse/remotefuse/remote_server.cpp +++ b/repertory/librepertory/src/drives/fuse/remotefuse/remote_server.cpp @@ -38,7 +38,7 @@ #include "utils/base64.hpp" #include "utils/error_utils.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" namespace repertory::remote_fuse { #define RAISE_REMOTE_FUSE_SERVER_EVENT(func, file, ret) \ diff --git a/repertory/librepertory/src/drives/remote/remote_open_file_table.cpp b/repertory/librepertory/src/drives/remote/remote_open_file_table.cpp index 489269cc..1bbf7395 100644 --- a/repertory/librepertory/src/drives/remote/remote_open_file_table.cpp +++ b/repertory/librepertory/src/drives/remote/remote_open_file_table.cpp @@ -23,6 +23,7 @@ #include "events/event_system.hpp" #include "events/events.hpp" +#include "utils/collection.hpp" #include "utils/utils.hpp" namespace repertory { @@ -30,7 +31,7 @@ void remote_open_file_table::add_directory(const std::string &client_id, std::uint64_t handle) { recur_mutex_lock directory_lock(directory_mutex_); auto &list = directory_lookup_[client_id]; - if (utils::collection_excludes(list, handle)) { + if (utils::collection::excludes(list, handle)) { directory_lookup_[client_id].emplace_back(handle); } } @@ -144,7 +145,7 @@ auto remote_open_file_table::has_open_directory(const std::string &client_id, std::uint64_t handle) -> bool { recur_mutex_lock directory_lock(directory_mutex_); auto &list = directory_lookup_[client_id]; - return (utils::collection_includes(list, handle)); + return (utils::collection::includes(list, handle)); } auto remote_open_file_table::has_compat_open_info( @@ -207,8 +208,8 @@ auto remote_open_file_table::remove_directory(const std::string &client_id, std::uint64_t handle) -> bool { recur_mutex_lock directory_lock(directory_mutex_); auto &list = directory_lookup_[client_id]; - if (utils::collection_includes(list, handle)) { - utils::remove_element_from(list, handle); + if (utils::collection::includes(list, handle)) { + utils::collection::remove_element(list, handle); if (directory_lookup_[client_id].empty()) { directory_lookup_.erase(client_id); } diff --git a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp index 07bc79bd..e8299c57 100644 --- a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp +++ b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp @@ -26,7 +26,7 @@ #include "events/event_system.hpp" #include "events/events.hpp" #include "types/repertory.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "version.hpp" namespace repertory::remote_winfsp { diff --git a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_server.cpp b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_server.cpp index 2ede7fab..91859387 100644 --- a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_server.cpp +++ b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_server.cpp @@ -37,7 +37,7 @@ #include "types/remote.hpp" #include "types/repertory.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #if !defined(_SH_DENYNO) #define _SH_DENYRW 0x10 // deny read/write mode diff --git a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_winfsp_drive.cpp b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_winfsp_drive.cpp index 34e0923a..1b3d475c 100644 --- a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_winfsp_drive.cpp +++ b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_winfsp_drive.cpp @@ -29,9 +29,10 @@ #include "events/events.hpp" #include "platform/platform.hpp" #include "rpc/server/server.hpp" +#include "utils/collection.hpp" #include "utils/error_utils.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/utils.hpp" namespace repertory::remote_winfsp { @@ -232,7 +233,7 @@ auto remote_winfsp_drive::mount(const std::vector &drive_args) -> int { std::vector parsed_drive_args; - const auto force_no_console = utils::collection_includes(drive_args, "-nc"); + const auto force_no_console = utils::collection::includes(drive_args, "-nc"); auto enable_console = false; for (const auto &arg : drive_args) { diff --git a/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp b/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp index a1f99649..0c70f7c4 100644 --- a/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp +++ b/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp @@ -32,10 +32,11 @@ #include "providers/i_provider.hpp" #include "types/repertory.hpp" #include "types/startup_exception.hpp" +#include "utils/collection.hpp" #include "utils/error_utils.hpp" #include "utils/file_utils.hpp" #include "utils/polling.hpp" -#include "utils/string_utils.hpp" +#include "utils/string.hpp" #include "utils/utils.hpp" namespace repertory { @@ -560,7 +561,7 @@ auto winfsp_drive::Init(PVOID host) -> NTSTATUS { auto winfsp_drive::mount(const std::vector &drive_args) -> int { std::vector parsed_drive_args; - const auto force_no_console = utils::collection_includes(drive_args, "-nc"); + const auto force_no_console = utils::collection::includes(drive_args, "-nc"); auto enable_console = false; for (const auto &arg : drive_args) { diff --git a/repertory/librepertory/src/events/consumers/logging_consumer.cpp b/repertory/librepertory/src/events/consumers/logging_consumer.cpp index ef15947c..b761183f 100644 --- a/repertory/librepertory/src/events/consumers/logging_consumer.cpp +++ b/repertory/librepertory/src/events/consumers/logging_consumer.cpp @@ -25,7 +25,7 @@ #include "spdlog/async.h" #include "spdlog/sinks/rotating_file_sink.h" #include "spdlog/spdlog.h" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" namespace repertory { logging_consumer::logging_consumer(event_level level, diff --git a/repertory/librepertory/src/events/event.cpp b/repertory/librepertory/src/events/event.cpp index c848627a..c317a5c6 100644 --- a/repertory/librepertory/src/events/event.cpp +++ b/repertory/librepertory/src/events/event.cpp @@ -21,7 +21,7 @@ */ #include "events/event.hpp" -#include "utils/string_utils.hpp" +#include "utils/string.hpp" namespace repertory { auto event_level_from_string(std::string level) -> event_level { diff --git a/repertory/librepertory/src/file_manager/file_manager.cpp b/repertory/librepertory/src/file_manager/file_manager.cpp index 6a138f55..b732872f 100644 --- a/repertory/librepertory/src/file_manager/file_manager.cpp +++ b/repertory/librepertory/src/file_manager/file_manager.cpp @@ -32,13 +32,13 @@ #include "utils/encrypting_reader.hpp" #include "utils/error_utils.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/polling.hpp" #include "utils/utils.hpp" namespace { -[[nodiscard]] auto create_resume_entry(const repertory::i_open_file &file) - -> json { +[[nodiscard]] auto +create_resume_entry(const repertory::i_open_file &file) -> json { return { {"chunk_size", file.get_chunk_size()}, {"path", file.get_api_path()}, @@ -439,11 +439,10 @@ auto file_manager::open(const std::string &api_path, bool directory, return open(api_path, directory, ofd, handle, file, nullptr); } -auto file_manager::open(const std::string &api_path, bool directory, - const open_file_data &ofd, std::uint64_t &handle, - std::shared_ptr &file, - std::shared_ptr closeable_file) - -> api_error { +auto file_manager::open( + const std::string &api_path, bool directory, const open_file_data &ofd, + std::uint64_t &handle, std::shared_ptr &file, + std::shared_ptr closeable_file) -> api_error { const auto create_and_add_handle = [&](std::shared_ptr cur_file) { handle = get_next_handle(); @@ -696,8 +695,8 @@ auto file_manager::rename_directory(const std::string &from_api_path, } auto file_manager::rename_file(const std::string &from_api_path, - const std::string &to_api_path, bool overwrite) - -> api_error { + const std::string &to_api_path, + bool overwrite) -> api_error { constexpr const auto *function_name = static_cast(__FUNCTION__); if (not provider_.is_rename_supported()) { diff --git a/repertory/librepertory/src/file_manager/file_manager_open_file.cpp b/repertory/librepertory/src/file_manager/file_manager_open_file.cpp index 9bc722bc..8a0fccdd 100644 --- a/repertory/librepertory/src/file_manager/file_manager_open_file.cpp +++ b/repertory/librepertory/src/file_manager/file_manager_open_file.cpp @@ -27,7 +27,7 @@ #include "types/startup_exception.hpp" #include "utils/error_utils.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/unix/unix_utils.hpp" #include "utils/utils.hpp" diff --git a/repertory/librepertory/src/file_manager/file_manager_open_file_base.cpp b/repertory/librepertory/src/file_manager/file_manager_open_file_base.cpp index 01c0319f..32e50bce 100644 --- a/repertory/librepertory/src/file_manager/file_manager_open_file_base.cpp +++ b/repertory/librepertory/src/file_manager/file_manager_open_file_base.cpp @@ -21,7 +21,7 @@ */ #include "file_manager/file_manager.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" namespace repertory { file_manager::open_file_base::open_file_base(std::uint64_t chunk_size, diff --git a/repertory/librepertory/src/file_manager/file_manager_ring_buffer_open_file.cpp b/repertory/librepertory/src/file_manager/file_manager_ring_buffer_open_file.cpp index 6dd18525..c87fd0d5 100644 --- a/repertory/librepertory/src/file_manager/file_manager_ring_buffer_open_file.cpp +++ b/repertory/librepertory/src/file_manager/file_manager_ring_buffer_open_file.cpp @@ -27,7 +27,7 @@ #include "types/repertory.hpp" #include "utils/encrypting_reader.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/unix/unix_utils.hpp" #include "utils/utils.hpp" diff --git a/repertory/librepertory/src/platform/unix_platform.cpp b/repertory/librepertory/src/platform/unix_platform.cpp index f44d5bd7..b380e228 100644 --- a/repertory/librepertory/src/platform/unix_platform.cpp +++ b/repertory/librepertory/src/platform/unix_platform.cpp @@ -28,7 +28,7 @@ #include "types/startup_exception.hpp" #include "utils/error_utils.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/unix/unix_utils.hpp" namespace repertory { diff --git a/repertory/librepertory/src/providers/base_provider.cpp b/repertory/librepertory/src/providers/base_provider.cpp index 474ea8ab..2fd22e91 100644 --- a/repertory/librepertory/src/providers/base_provider.cpp +++ b/repertory/librepertory/src/providers/base_provider.cpp @@ -29,7 +29,7 @@ #include "events/events.hpp" #include "file_manager/i_file_manager.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/polling.hpp" namespace repertory { diff --git a/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp b/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp index b5f04786..54898fc9 100644 --- a/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp +++ b/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp @@ -29,7 +29,7 @@ #include "types/repertory.hpp" #include "utils/encrypting_reader.hpp" #include "utils/encrypt.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/polling.hpp" namespace { diff --git a/repertory/librepertory/src/providers/meta_db.cpp b/repertory/librepertory/src/providers/meta_db.cpp index f45b964f..d6872bd1 100644 --- a/repertory/librepertory/src/providers/meta_db.cpp +++ b/repertory/librepertory/src/providers/meta_db.cpp @@ -26,8 +26,8 @@ #include "database/db_insert.hpp" #include "database/db_select.hpp" #include "utils/error_utils.hpp" -#include "utils/path_utils.hpp" -#include "utils/string_utils.hpp" +#include "utils/path.hpp" +#include "utils/string.hpp" namespace repertory { meta_db::meta_db(const app_config &cfg) { @@ -101,8 +101,8 @@ auto meta_db::get_api_path_list() -> std::vector { return ret; } -auto meta_db::get_item_meta(const std::string &api_path, api_meta_map &meta) - -> api_error { +auto meta_db::get_item_meta(const std::string &api_path, + api_meta_map &meta) -> api_error { constexpr const auto *function_name = static_cast(__FUNCTION__); auto result = db::db_select{*db_, table_name} @@ -283,8 +283,8 @@ auto meta_db::set_item_meta(const std::string &api_path, return update_item_meta(api_path, existing_meta); } -auto meta_db::update_item_meta(const std::string &api_path, api_meta_map meta) - -> api_error { +auto meta_db::update_item_meta(const std::string &api_path, + api_meta_map meta) -> api_error { constexpr const auto *function_name = static_cast(__FUNCTION__); auto directory = utils::string::to_bool(meta[META_DIRECTORY]); diff --git a/repertory/librepertory/src/providers/s3/s3_provider.cpp b/repertory/librepertory/src/providers/s3/s3_provider.cpp index b41df7aa..bf6bc903 100644 --- a/repertory/librepertory/src/providers/s3/s3_provider.cpp +++ b/repertory/librepertory/src/providers/s3/s3_provider.cpp @@ -32,9 +32,9 @@ #include "utils/encrypting_reader.hpp" #include "utils/error_utils.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/polling.hpp" -#include "utils/string_utils.hpp" +#include "utils/string.hpp" namespace repertory { s3_provider::s3_provider(app_config &config, i_http_comm &comm) diff --git a/repertory/librepertory/src/providers/sia/sia_provider.cpp b/repertory/librepertory/src/providers/sia/sia_provider.cpp index 30cfca46..1383ace6 100644 --- a/repertory/librepertory/src/providers/sia/sia_provider.cpp +++ b/repertory/librepertory/src/providers/sia/sia_provider.cpp @@ -29,9 +29,9 @@ #include "types/repertory.hpp" #include "utils/error_utils.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/polling.hpp" -#include "utils/string_utils.hpp" +#include "utils/string.hpp" #include "utils/utils.hpp" namespace repertory { diff --git a/repertory/librepertory/src/rpc/server/full_server.cpp b/repertory/librepertory/src/rpc/server/full_server.cpp index 8a3576b2..e8a5a62a 100644 --- a/repertory/librepertory/src/rpc/server/full_server.cpp +++ b/repertory/librepertory/src/rpc/server/full_server.cpp @@ -28,7 +28,7 @@ #include "types/repertory.hpp" #include "types/rpc.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" namespace repertory { full_server::full_server(app_config &config, i_provider &provider, diff --git a/repertory/librepertory/src/types/repertory.cpp b/repertory/librepertory/src/types/repertory.cpp index 400b55ca..b63ddcb3 100644 --- a/repertory/librepertory/src/types/repertory.cpp +++ b/repertory/librepertory/src/types/repertory.cpp @@ -22,8 +22,40 @@ #include "types/repertory.hpp" #include "types/startup_exception.hpp" +#include "utils/string.hpp" namespace repertory { +auto download_type_from_string( + std::string type, const download_type &default_type) -> download_type { + type = utils::string::to_lower(utils::string::trim(type)); + if (type == "direct") { + return download_type::direct; + } + + if (type == "fallback") { + return download_type::fallback; + } + + if (type == "ring_buffer") { + return download_type::ring_buffer; + } + + return default_type; +} + +auto download_type_to_string(const download_type &type) -> std::string { + switch (type) { + case download_type::direct: + return "direct"; + case download_type::fallback: + return "fallback"; + case download_type::ring_buffer: + return "ring_buffer"; + default: + return "fallback"; + } +} + static const std::unordered_map LOOKUP = { {api_error::success, "success"}, {api_error::access_denied, "access_denied"}, diff --git a/repertory/librepertory/src/utils/cli_utils.cpp b/repertory/librepertory/src/utils/cli_utils.cpp index 76b2edd3..c99b9181 100644 --- a/repertory/librepertory/src/utils/cli_utils.cpp +++ b/repertory/librepertory/src/utils/cli_utils.cpp @@ -22,9 +22,10 @@ #include "utils/cli_utils.hpp" #include "app_config.hpp" +#include "utils/collection.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" -#include "utils/string_utils.hpp" +#include "utils/path.hpp" +#include "utils/string.hpp" #include "utils/utils.hpp" namespace repertory::utils::cli { @@ -187,14 +188,16 @@ auto parse_drive_options( if (new_drive_args[i].find("-o") == 0) { if (new_drive_args[i].size() == 2) { if ((i + 1) < drive_args.size()) { - utils::remove_element_from(new_drive_args, new_drive_args[i]); - utils::remove_element_from(new_drive_args, new_drive_args[i]); + utils::collection::remove_element(new_drive_args, + new_drive_args[i]); + utils::collection::remove_element(new_drive_args, + new_drive_args[i]); i--; } continue; } - utils::remove_element_from(new_drive_args, new_drive_args[i]); + utils::collection::remove_element(new_drive_args, new_drive_args[i]); i--; continue; } diff --git a/repertory/librepertory/src/utils/encrypt.cpp b/repertory/librepertory/src/utils/encrypt.cpp index 0bfaf4ec..e9130cc9 100644 --- a/repertory/librepertory/src/utils/encrypt.cpp +++ b/repertory/librepertory/src/utils/encrypt.cpp @@ -65,30 +65,6 @@ auto decrypt_file_name(std::string_view encryption_token, return api_error::success; } -auto generate_key(std::string_view encryption_token) -> key_type { - crypto_hash_sha256_state state{}; - auto res = crypto_hash_sha256_init(&state); - if (res != 0) { - throw std::runtime_error("failed to initialize sha256|" + - std::to_string(res)); - } - res = crypto_hash_sha256_update( - &state, reinterpret_cast(encryption_token.data()), - encryption_token.size()); - if (res != 0) { - throw std::runtime_error("failed to update sha256|" + std::to_string(res)); - } - - key_type ret{}; - res = crypto_hash_sha256_final(&state, ret.data()); - if (res != 0) { - throw std::runtime_error("failed to finalize sha256|" + - std::to_string(res)); - } - - return ret; -} - auto read_encrypted_range(const http_range &range, const key_type &key, reader_func reader, std::uint64_t total_size, data_buffer &data) -> api_error { diff --git a/repertory/librepertory/src/utils/file_utils.cpp b/repertory/librepertory/src/utils/file_utils.cpp index 3dc32627..1bc0fea9 100644 --- a/repertory/librepertory/src/utils/file_utils.cpp +++ b/repertory/librepertory/src/utils/file_utils.cpp @@ -23,8 +23,8 @@ #include "types/repertory.hpp" #include "utils/error_utils.hpp" -#include "utils/path_utils.hpp" -#include "utils/string_utils.hpp" +#include "utils/path.hpp" +#include "utils/string.hpp" #include "utils/utils.hpp" namespace repertory::utils::file { @@ -483,51 +483,6 @@ auto get_modified_time(const std::string &path, return ret; } -auto get_file_size(std::string_view path, std::uint64_t &file_size) -> bool { - file_size = 0U; - auto abs_path = utils::path::absolute(std::string{path}); - -#if defined(_WIN32) - struct _stat64 st {}; - if (_stat64(abs_path.c_str(), &st) != 0) { -#else -#if defined(__APPLE__) - struct stat st {}; - if (stat(abs_path.c_str(), &st) != 0) { -#else - struct stat64 st {}; - if (stat64(abs_path.c_str(), &st) != 0) { -#endif -#endif - return false; - } - - if (st.st_size >= 0) { - file_size = static_cast(st.st_size); - } - - return (st.st_size >= 0); -} - -auto is_directory(const std::string &path) -> bool { -#if defined(_WIN32) - return ::PathIsDirectory(path.c_str()) != 0; -#else - struct stat st {}; - return (not stat(path.c_str(), &st) && S_ISDIR(st.st_mode)); -#endif -} - -auto is_file(const std::string &path) -> bool { -#if defined(_WIN32) - return (::PathFileExists(path.c_str()) && - not ::PathIsDirectory(path.c_str())); -#else - struct stat st {}; - return (not stat(path.c_str(), &st) && not S_ISDIR(st.st_mode)); -#endif -} - auto is_modified_date_older_than(const std::string &path, const std::chrono::hours &hours) -> bool { auto ret = false; @@ -580,40 +535,6 @@ auto read_file_lines(const std::string &path) -> std::vector { return ret; } -auto read_json_file(const std::string &path, json &data) -> bool { - constexpr const auto *function_name = static_cast(__FUNCTION__); - - if (not utils::file::is_file(path)) { - return true; - } - - try { - std::ifstream file_stream(path.c_str()); - if (file_stream.is_open()) { - try { - std::stringstream ss; - ss << file_stream.rdbuf(); - - std::string json_text = ss.str(); - if (not json_text.empty()) { - data = json::parse(json_text.c_str()); - } - - file_stream.close(); - return true; - } catch (const std::exception &e) { - file_stream.close(); - throw e; - } - } - } catch (const std::exception &e) { - utils::error::raise_error(function_name, e, path, - "failed to read json file"); - } - - return false; -} - auto reset_modified_time(const std::string &path) -> bool { auto ret = false; #if defined(_WIN32) @@ -660,24 +581,4 @@ auto retry_delete_file(const std::string &file) -> bool { return deleted; } - -auto write_json_file(const std::string &path, const json &j) -> bool { - std::string data; - { - std::stringstream ss; - ss << std::setw(2) << j; - data = ss.str(); - } - native_file_ptr nf; - auto ret = (native_file::create_or_open(path, nf) == api_error::success); - if (ret) { - std::size_t bytes_written{0U}; - ret = nf->truncate(0) && - nf->write_bytes(reinterpret_cast(data.data()), - data.size(), 0U, bytes_written); - nf->close(); - } - - return ret; -} } // namespace repertory::utils::file diff --git a/repertory/librepertory/src/utils/native_file.cpp b/repertory/librepertory/src/utils/native_file.cpp index 869ea020..bd7871a9 100644 --- a/repertory/librepertory/src/utils/native_file.cpp +++ b/repertory/librepertory/src/utils/native_file.cpp @@ -22,7 +22,7 @@ #include "utils/native_file.hpp" #include "types/repertory.hpp" -#include "utils/string_utils.hpp" +#include "utils/string.hpp" #include "utils/unix/unix_utils.hpp" #include "utils/utils.hpp" diff --git a/repertory/librepertory/src/utils/path_utils.cpp b/repertory/librepertory/src/utils/path_utils.cpp deleted file mode 100644 index 08fa60eb..00000000 --- a/repertory/librepertory/src/utils/path_utils.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - Copyright <2018-2024> - - 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. -*/ -#include "utils/path_utils.hpp" - -#include "types/repertory.hpp" -#include "utils/error_utils.hpp" -#include "utils/string_utils.hpp" -#include "utils/utils.hpp" - -namespace repertory::utils::path { -auto absolute(std::string path) -> std::string { - path = finalize(path); - -#if defined(_WIN32) - if (not path.empty() && ::PathIsRelative(path.c_str())) { - std::string temp; - temp.resize(MAX_PATH + 1); - path = _fullpath(temp.data(), path.c_str(), MAX_PATH); - } -#else - if (not path.empty() && (path[0U] != '/')) { - auto found = false; - auto tmp = path; - do { - auto *res = realpath(&tmp[0U], nullptr); - if (res) { - path = combine(res, {path.substr(tmp.size())}); - free(res); - found = true; - } else if (tmp == ".") { - found = true; - } else { - tmp = dirname(&tmp[0U]); - } - } while (not found); - } -#endif - - return path; -} - -auto combine(std::string path, - const std::vector &paths) -> std::string { - return absolute( - std::accumulate(paths.begin(), paths.end(), path, - [](std::string next_path, const auto &path_part) { - if (next_path.empty()) { - return path_part; - } - return next_path + (directory_seperator + path_part); - })); -} - -auto create_api_path(std::string path) -> std::string { - if (path.empty() || (path == ".") || (path == "/")) { - return "/"; - } - - format_path(path, "/", "\\"); - if (path.find("./") == 0) { - path = path.substr(1); - } - - if (path[0U] != '/') { - path = "/" + path; - } - - if ((path != "/") && utils::string::ends_with(path, "/")) { - utils::string::right_trim(path, '/'); - } - - return path; -} - -auto finalize(std::string path) -> std::string { - format_path(path, not_directory_seperator, directory_seperator); - format_path(path, directory_seperator, not_directory_seperator); - if ((path.size() > 1U) && - (path[path.size() - 1U] == directory_seperator[0U])) { - path = path.substr(0U, path.size() - 1U); - } - -#if defined(_WIN32) - if ((path.size() >= 2u) && (path[1U] == ':')) { - path[0U] = utils::string::to_lower(std::string(1U, path[0U]))[0U]; - } -#endif - - return path; -} - -auto format_path(std::string &path, const std::string &sep, - const std::string ¬_sep) -> std::string & { - std::replace(path.begin(), path.end(), not_sep[0U], sep[0U]); - - while (utils::string::contains(path, sep + sep)) { - utils::string::replace(path, sep + sep, sep); - } - - return path; -} - -auto get_parent_api_path(const std::string &path) -> std::string { - std::string ret; - if (path != "/") { - ret = path.substr(0, path.rfind('/') + 1); - if (ret != "/") { - ret = utils::string::right_trim(ret, '/'); - } - } - - return ret; -} - -#if !defined(_WIN32) -auto get_parent_directory(std::string path) -> std::string { - auto ret = std::string(dirname(&path[0U])); - if (ret == ".") { - ret = "/"; - } - - return ret; -} -#endif - -auto is_ads_file_path([[maybe_unused]] const std::string &path) -> bool { -#if defined(_WIN32) - return utils::string::contains(path, ":"); -#else - return false; -#endif -} - -auto is_trash_directory(std::string path) -> bool { - path = create_api_path(utils::string::to_lower(path)); - if (utils::string::begins_with(path, "/.trash-") || - utils::string::begins_with(path, "/.trashes") || - utils::string::begins_with(path, "/$recycle.bin")) { - return true; - } - return false; -} - -auto remove_file_name(std::string path) -> std::string { - path = absolute(path); - -#if defined(_WIN32) - ::PathRemoveFileSpec(&path[0U]); - path = path.c_str(); -#else - if (path != "/") { - auto i = path.size() - 1; - while ((i != 0) && (path[i] != '/')) { - i--; - } - - path = (i > 0) ? absolute(path.substr(0, i)) : "/"; - } -#endif - - return path; -} - -#if !defined(_WIN32) -auto resolve(std::string path) -> std::string { - std::string home{}; - use_getpwuid(getuid(), [&home](struct passwd *pw) { - home = (pw->pw_dir ? pw->pw_dir : ""); - if (home.empty() || ((home == "/") && (getuid() != 0))) { - home = combine("/home", {pw->pw_name}); - } - }); - - return absolute(utils::string::replace(path, "~", home)); -} -#endif - -auto strip_to_file_name(std::string path) -> std::string { -#if defined(_WIN32) - return ::PathFindFileName(path.c_str()); -#else - return utils::string::contains(path, "/") ? basename(&path[0U]) : path; -#endif -} -} // namespace repertory::utils::path diff --git a/repertory/librepertory/src/utils/string_utils.cpp b/repertory/librepertory/src/utils/string_utils.cpp deleted file mode 100644 index c1a3913a..00000000 --- a/repertory/librepertory/src/utils/string_utils.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - Copyright <2018-2024> - - 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. -*/ -#include "utils/string_utils.hpp" - -namespace repertory::utils::string { -/* constexpr c++20 */ auto ends_with(std::string_view str, - std::string_view val) -> bool { - if (val.size() > str.size()) { - return false; - } - return std::equal(val.rbegin(), val.rend(), str.rbegin()); -} - -auto from_bool(bool val) -> std::string { - return std::to_string(static_cast(val)); -} - -auto from_dynamic_bitset(const boost::dynamic_bitset<> &bitset) -> std::string { - std::stringstream stream; - boost::archive::text_oarchive archive(stream); - archive << bitset; - return stream.str(); -} - -auto from_utf8(std::string_view str) -> std::wstring { - return str.empty() - ? L"" - : std::wstring_convert, wchar_t>() - .from_bytes(std::string{str}); -} - -/* constexpr c++20 */ auto is_numeric(std::string_view str) -> bool { - if ((str.length() > 1U) && (str[0U] == '+' || str[0U] == '-')) { - str = str.substr(1U); - } - - if (str.empty()) { - return false; - } - - auto has_decimal = false; - return std::find_if(str.begin(), str.end(), - [&has_decimal]( - const std::string_view::value_type &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(); -} - -auto join(const std::vector &arr, - const char &delim) -> std::string { - 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; }); -} - -auto left_trim(std::string &str) -> std::string & { - return left_trim(str, ' '); -} - -auto left_trim(std::string &str, const char &trim_ch) -> std::string & { - str.erase(0, str.find_first_not_of(trim_ch)); - return str; -} - -auto replace(std::string &src, const char &character, - const char &with) -> std::string & { - std::replace(src.begin(), src.end(), character, with); - return src; -} - -auto replace(std::string &src, const std::string &find, const std::string &with, - size_t start_pos) -> std::string & { - if (!src.empty() && (start_pos < src.size())) { - while ((start_pos = src.find(find, start_pos)) != std::string::npos) { - src.replace(start_pos, find.size(), with); - start_pos += with.size(); - } - } - return src; -} - -auto replace_copy(std::string src, const char &character, - const char &with) -> std::string { - std::replace(src.begin(), src.end(), character, with); - return src; -} - -auto replace_copy(std::string src, const std::string &find, - const std::string &with, size_t start_pos) -> std::string { - return replace(src, find, with, start_pos); -} - -auto right_trim(std::string &str) -> std::string & { - return right_trim(str, ' '); -} - -auto right_trim(std::string &str, const char &trim_ch) -> std::string & { - str.erase(str.find_last_not_of(trim_ch) + 1); - return str; -} - -auto split(const std::string &str, const char &delim, - bool should_trim) -> std::vector { - std::vector ret; - std::stringstream stream(str); - std::string item; - while (std::getline(stream, item, delim)) { - ret.push_back(should_trim ? trim(item) : item); - } - return ret; -} - -auto to_bool(std::string val) -> bool { - auto ret = false; - - trim(val); - if (is_numeric(val)) { - if (contains(val, ".")) { - ret = (to_double(val) != 0.0); - } else { - std::istringstream(val) >> ret; - } - } else { - std::istringstream(to_lower(val)) >> std::boolalpha >> ret; - } - - return ret; -} - -auto to_double(const std::string &str) -> double { return std::stod(str); } - -auto to_dynamic_bitset(const std::string &val) -> boost::dynamic_bitset<> { - std::stringstream stream(val); - boost::dynamic_bitset<> bitset; - boost::archive::text_iarchive archive(stream); - archive >> bitset; - return bitset; -} - -auto to_int32(const std::string &val) -> std::int32_t { return std::stoi(val); } - -auto to_int64(const std::string &val) -> std::int64_t { - return std::stoll(val); -} - -auto to_lower(std::string str) -> std::string { - std::transform(str.begin(), str.end(), str.begin(), ::tolower); - return str; -} - -auto to_size_t(const std::string &val) -> std::size_t { - return static_cast(std::stoull(val)); -} - -auto to_uint8(const std::string &val) -> std::uint8_t { - return static_cast(std::stoul(val)); -} - -auto to_uint16(const std::string &val) -> std::uint16_t { - return static_cast(std::stoul(val)); -} - -auto to_uint32(const std::string &val) -> std::uint32_t { - return static_cast(std::stoul(val)); -} - -auto to_uint64(const std::string &val) -> std::uint64_t { - return std::stoull(val); -} - -auto to_upper(std::string str) -> std::string { - std::transform(str.begin(), str.end(), str.begin(), ::toupper); - return str; -} - -auto to_utf8(std::string_view str) -> std::string { return std::string{str}; } - -auto to_utf8(std::wstring_view str) -> std::string { - return str.empty() - ? "" - : std::wstring_convert, wchar_t>() - .to_bytes(std::wstring{str}); -} - -auto trim(std::string &str) -> std::string & { - return right_trim(left_trim(str)); -} - -auto trim(std::string &str, const char &trim_ch) -> std::string & { - return right_trim(left_trim(str, trim_ch), trim_ch); -} - -auto trim_copy(std::string str) -> std::string { - return right_trim(left_trim(str)); -} - -auto trim_copy(std::string str, const char &trim_ch) -> std::string { - return right_trim(left_trim(str, trim_ch), trim_ch); -} -} // namespace repertory::utils::string diff --git a/repertory/librepertory/src/utils/unix/unix_utils.cpp b/repertory/librepertory/src/utils/unix/unix_utils.cpp index ea6396ef..3d19389f 100644 --- a/repertory/librepertory/src/utils/unix/unix_utils.cpp +++ b/repertory/librepertory/src/utils/unix/unix_utils.cpp @@ -24,15 +24,8 @@ #include "utils/unix/unix_utils.hpp" #include "utils/error_utils.hpp" -#include "utils/utils.hpp" namespace repertory::utils { -#if !defined(__APPLE__) -auto convert_to_uint64(const pthread_t &thread) -> std::uint64_t { - return static_cast(thread); -} -#endif - auto from_api_error(const api_error &err) -> int { switch (err) { case api_error::access_denied: @@ -100,30 +93,6 @@ auto from_api_error(const api_error &err) -> int { } } -auto get_last_error_code() -> int { return errno; } - -auto get_thread_id() -> std::uint64_t { - return convert_to_uint64(pthread_self()); -} - -auto is_uid_member_of_group(const uid_t &uid, const gid_t &gid) -> bool { - std::vector groups{}; - use_getpwuid(uid, [&groups](struct passwd *pass) { - int group_count{}; - if (getgrouplist(pass->pw_name, pass->pw_gid, nullptr, &group_count) < 0) { - groups.resize(static_cast(group_count)); -#if defined(__APPLE__) - getgrouplist(pass->pw_name, pass->pw_gid, - reinterpret_cast(groups.data()), &group_count); -#else - getgrouplist(pass->pw_name, pass->pw_gid, groups.data(), &group_count); -#endif - } - }); - - return collection_includes(groups, gid); -} - auto to_api_error(int err) -> api_error { switch (abs(err)) { case 0: @@ -192,8 +161,6 @@ auto to_api_error(int err) -> api_error { } } -void set_last_error_code(int error_code) { errno = error_code; } - auto unix_error_to_windows(int err) -> std::int32_t { switch (err) { case 0: @@ -238,21 +205,6 @@ auto unix_time_to_windows_time(const remote::file_time &file_time) -> UINT64 { return (file_time / 100ULL) + 116444736000000000ULL; } -void use_getpwuid(uid_t uid, - std::function callback) { - constexpr const auto *function_name = static_cast(__FUNCTION__); - - static std::mutex mtx{}; - mutex_lock lock{mtx}; - auto *temp_pw = getpwuid(uid); - if (temp_pw == nullptr) { - utils::error::raise_error(function_name, "'getpwuid' returned nullptr"); - return; - } - - callback(temp_pw); -} - void windows_create_to_unix(const UINT32 &create_options, const UINT32 &granted_access, std::uint32_t &flags, remote::file_mode &mode) { diff --git a/repertory/librepertory/src/utils/utils.cpp b/repertory/librepertory/src/utils/utils.cpp index 01a580be..891d42a6 100644 --- a/repertory/librepertory/src/utils/utils.cpp +++ b/repertory/librepertory/src/utils/utils.cpp @@ -27,9 +27,10 @@ #include "providers/i_provider.hpp" #include "types/startup_exception.hpp" #include "utils/com_init_wrapper.hpp" +#include "utils/common.hpp" #include "utils/native_file.hpp" -#include "utils/path_utils.hpp" -#include "utils/string_utils.hpp" +#include "utils/path.hpp" +#include "utils/string.hpp" namespace repertory::utils { void calculate_allocation_size(bool directory, std::uint64_t file_size, @@ -51,47 +52,6 @@ void calculate_allocation_size(bool directory, std::uint64_t file_size, allocation_meta_size = std::to_string(allocation_size); } -auto calculate_read_size(const uint64_t &total_size, std::size_t read_size, - const uint64_t &offset) -> std::size_t { - return static_cast( - ((offset + read_size) > total_size) - ? ((offset < total_size) ? total_size - offset : 0U) - : read_size); -} - -auto compare_version_strings(std::string version1, - std::string version2) -> int { - if (utils::string::contains(version1, "-")) { - version1 = utils::string::split(version1, '-')[0U]; - } - - if (utils::string::contains(version2, "-")) { - version2 = utils::string::split(version2, '-')[0U]; - } - - auto nums1 = utils::string::split(version1, '.'); - auto nums2 = utils::string::split(version2, '.'); - - while (nums1.size() > nums2.size()) { - nums2.emplace_back("0"); - } - - while (nums2.size() > nums1.size()) { - nums1.emplace_back("0"); - } - - for (std::size_t i = 0U; i < nums1.size(); i++) { - const auto int1 = utils::string::to_uint32(nums1[i]); - const auto int2 = utils::string::to_uint32(nums2[i]); - const auto res = std::memcmp(&int1, &int2, sizeof(int1)); - if (res != 0) { - return res; - } - } - - return 0; -} - auto convert_api_date(const std::string &date) -> std::uint64_t { // 2009-10-12T17:50:30.000Z const auto date_parts = utils::string::split(date, '.'); @@ -118,165 +78,14 @@ auto create_curl() -> CURL * { return reset_curl(curl_easy_init()); } -auto create_uuid_string() -> std::string { - std::random_device random_device; - auto seed_data = std::array{}; - std::generate(std::begin(seed_data), std::end(seed_data), - std::ref(random_device)); - std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); - std::mt19937 generator(seq); - uuids::uuid_random_generator gen{generator}; - - return uuids::to_string(gen()); -} - auto create_volume_label(const provider_type &prov) -> std::string { return "repertory_" + app_config::get_provider_name(prov); } -auto download_type_from_string( - std::string type, const download_type &default_type) -> download_type { - type = utils::string::to_lower(utils::string::trim(type)); - if (type == "direct") { - return download_type::direct; - } - - if (type == "fallback") { - return download_type::fallback; - } - - if (type == "ring_buffer") { - return download_type::ring_buffer; - } - - return default_type; -} - -auto download_type_to_string(const download_type &type) -> std::string { - switch (type) { - case download_type::direct: - return "direct"; - case download_type::fallback: - return "fallback"; - case download_type::ring_buffer: - return "ring_buffer"; - default: - return "fallback"; - } -} - -#if defined(_WIN32) -// https://www.frenk.com/2009/12/convert-filetime-to-unix-timestamp/ -auto filetime_to_unix_time(const FILETIME &ft) -> remote::file_time { - LARGE_INTEGER date{}; - date.HighPart = static_cast(ft.dwHighDateTime); - date.LowPart = ft.dwLowDateTime; - date.QuadPart -= 116444736000000000LL; - - return static_cast(date.QuadPart) * 100ULL; -} - -void unix_time_to_filetime(const remote::file_time &ts, FILETIME &ft) { - const auto win_time = (ts / 100ULL) + 116444736000000000ULL; - ft.dwHighDateTime = static_cast(win_time >> 32U); - ft.dwLowDateTime = win_time & 0xFFFFFFFF; -} -#endif - -auto generate_random_string(std::uint16_t length) -> std::string { - std::string ret; - ret.resize(length); - for (std::uint16_t i = 0U; i < length; i++) { - do { - ret[i] = static_cast(repertory_rand() % 74 + 48); - } while (((ret[i] >= 91) && (ret[i] <= 96)) || - ((ret[i] >= 58) && (ret[i] <= 64))); - } - - return ret; -} - auto get_attributes_from_meta(const api_meta_map &meta) -> DWORD { return static_cast(utils::string::to_uint32(meta.at(META_ATTRIBUTES))); } -auto get_environment_variable(const std::string &variable) -> std::string { - static std::mutex mtx{}; - mutex_lock lock{mtx}; - - const auto *val = std::getenv(variable.c_str()); - auto ret = std::string(val == nullptr ? "" : val); - return ret; -} - -auto get_file_time_now() -> std::uint64_t { -#if defined(_WIN32) - SYSTEMTIME st{}; - ::GetSystemTime(&st); - FILETIME ft{}; - ::SystemTimeToFileTime(&st, &ft); - return static_cast( - (reinterpret_cast(&ft))->QuadPart); -#else - return get_time_now(); -#endif -} - -void get_local_time_now(struct tm &local_time) { - memset(&local_time, 0, sizeof(local_time)); - - const auto now = - std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); -#if defined(_WIN32) - localtime_s(&local_time, &now); -#else - localtime_r(&now, &local_time); -#endif -} - -auto get_next_available_port(std::uint16_t first_port, - std::uint16_t &available_port) -> bool { - using namespace boost::asio; - using ip::tcp; - - boost::system::error_code error_code{}; - while (first_port != 0U) { - io_service svc{}; - tcp::acceptor acceptor(svc); - acceptor.open(tcp::v4(), error_code) || - acceptor.bind({tcp::v4(), first_port}, error_code); - if (not error_code) { - break; - } - - ++first_port; - } - - if (not error_code) { - available_port = first_port; - } - - return not error_code; -} - -auto get_time_now() -> std::uint64_t { -#if defined(_WIN32) - return static_cast( - std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())); -#else -#if defined(__APPLE__) - return std::chrono::nanoseconds( - std::chrono::system_clock::now().time_since_epoch()) - .count(); -#else - return static_cast( - std::chrono::nanoseconds( - std::chrono::high_resolution_clock::now().time_since_epoch()) - .count()); -#endif -#endif -} - auto reset_curl(CURL *curl_handle) -> CURL * { curl_easy_reset(curl_handle); #if defined(__APPLE__) diff --git a/repertory/librepertory/src/utils/windows/windows_utils.cpp b/repertory/librepertory/src/utils/windows/windows_utils.cpp index b7a61ed0..57bd7aa9 100644 --- a/repertory/librepertory/src/utils/windows/windows_utils.cpp +++ b/repertory/librepertory/src/utils/windows/windows_utils.cpp @@ -25,7 +25,7 @@ #include "types/startup_exception.hpp" #include "utils/com_init_wrapper.hpp" -#include "utils/string_utils.hpp" +#include "utils/string.hpp" #if !defined(STATUS_DEVICE_INSUFFICIENT_RESOURCES) #define STATUS_DEVICE_INSUFFICIENT_RESOURCES static_cast(0xC0000468L) @@ -232,10 +232,6 @@ auto unix_open_flags_to_flags_and_perms(const remote::file_mode & /*mode*/, return ret; } - -auto time64_to_unix_time(const __time64_t &t) -> remote::file_time { - return static_cast(t * NANOS_PER_SECOND); -} } // namespace repertory::utils #endif // _WIN32 diff --git a/repertory/repertory/include/cli/mount.hpp b/repertory/repertory/include/cli/mount.hpp index 8c188b31..aa177bda 100644 --- a/repertory/repertory/include/cli/mount.hpp +++ b/repertory/repertory/include/cli/mount.hpp @@ -30,7 +30,7 @@ #include "utils/cli_utils.hpp" #include "utils/com_init_wrapper.hpp" #include "utils/file_utils.hpp" -#include "utils/string_utils.hpp" +#include "utils/string.hpp" #if defined(_WIN32) #include "drives/winfsp/remotewinfsp/remote_client.hpp" diff --git a/repertory/repertory_test/include/mocks/mock_fuse_drive.hpp b/repertory/repertory_test/include/mocks/mock_fuse_drive.hpp index 0ea317b5..11b24527 100644 --- a/repertory/repertory_test/include/mocks/mock_fuse_drive.hpp +++ b/repertory/repertory_test/include/mocks/mock_fuse_drive.hpp @@ -29,7 +29,7 @@ #include "types/remote.hpp" #include "types/repertory.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/utils.hpp" namespace repertory { diff --git a/repertory/repertory_test/include/mocks/mock_winfsp_drive.hpp b/repertory/repertory_test/include/mocks/mock_winfsp_drive.hpp index 106fe875..2d52f849 100644 --- a/repertory/repertory_test/include/mocks/mock_winfsp_drive.hpp +++ b/repertory/repertory_test/include/mocks/mock_winfsp_drive.hpp @@ -27,7 +27,7 @@ #include "drives/winfsp/i_winfsp_drive.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/utils.hpp" namespace repertory { diff --git a/repertory/repertory_test/include/utils/event_capture.hpp b/repertory/repertory_test/include/utils/event_capture.hpp index f0cbf7e0..2a25eb46 100644 --- a/repertory/repertory_test/include/utils/event_capture.hpp +++ b/repertory/repertory_test/include/utils/event_capture.hpp @@ -24,6 +24,7 @@ #include "test_common.hpp" +#include "utils/collection.hpp" #include "utils/utils.hpp" namespace repertory { @@ -59,7 +60,7 @@ private: public: void process_event(const event &event) { unique_mutex_lock l(mutex_); - utils::remove_element_from(event_names_, event.get_name()); + utils::collection::remove_element(event_names_, event.get_name()); fired_event_names_.emplace_back(event.get_name()); notify_.notify_all(); l.unlock(); diff --git a/repertory/repertory_test/src/config_test.cpp b/repertory/repertory_test/src/config_test.cpp index 634dcc1e..bcc44c71 100644 --- a/repertory/repertory_test/src/config_test.cpp +++ b/repertory/repertory_test/src/config_test.cpp @@ -23,8 +23,8 @@ #include "app_config.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" -#include "utils/string_utils.hpp" +#include "utils/path.hpp" +#include "utils/string.hpp" namespace repertory { class config_test : public ::testing::Test { diff --git a/repertory/repertory_test/src/database_test.cpp b/repertory/repertory_test/src/database_test.cpp index c2c5e1b7..f00c8dc3 100644 --- a/repertory/repertory_test/src/database_test.cpp +++ b/repertory/repertory_test/src/database_test.cpp @@ -24,7 +24,7 @@ #include "database/db_common.hpp" #include "database/db_insert.hpp" #include "database/db_select.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" namespace repertory { TEST(database, db_insert) { diff --git a/repertory/repertory_test/src/encrypting_reader_test.cpp b/repertory/repertory_test/src/encrypting_reader_test.cpp index 6fc85c5d..fdf6ae8a 100644 --- a/repertory/repertory_test/src/encrypting_reader_test.cpp +++ b/repertory/repertory_test/src/encrypting_reader_test.cpp @@ -24,7 +24,7 @@ #include "types/repertory.hpp" #include "utils/encrypting_reader.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" namespace repertory { static auto get_source_file_name() -> std::string { diff --git a/repertory/repertory_test/src/file_manager_open_file_test.cpp b/repertory/repertory_test/src/file_manager_open_file_test.cpp index d6596e5d..722164f7 100644 --- a/repertory/repertory_test/src/file_manager_open_file_test.cpp +++ b/repertory/repertory_test/src/file_manager_open_file_test.cpp @@ -26,7 +26,7 @@ #include "mocks/mock_upload_manager.hpp" #include "types/repertory.hpp" #include "utils/event_capture.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" namespace repertory { static constexpr const std::size_t test_chunk_size = 1024u; diff --git a/repertory/repertory_test/src/file_manager_ring_buffer_open_file_test.cpp b/repertory/repertory_test/src/file_manager_ring_buffer_open_file_test.cpp index ffc4d0e6..900e28ed 100644 --- a/repertory/repertory_test/src/file_manager_ring_buffer_open_file_test.cpp +++ b/repertory/repertory_test/src/file_manager_ring_buffer_open_file_test.cpp @@ -25,7 +25,7 @@ #include "mocks/mock_provider.hpp" #include "mocks/mock_upload_manager.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/unix/unix_utils.hpp" namespace repertory { diff --git a/repertory/repertory_test/src/file_manager_test.cpp b/repertory/repertory_test/src/file_manager_test.cpp index 86da414a..b12a1190 100644 --- a/repertory/repertory_test/src/file_manager_test.cpp +++ b/repertory/repertory_test/src/file_manager_test.cpp @@ -33,9 +33,9 @@ #include "utils/event_capture.hpp" #include "utils/file_utils.hpp" #include "utils/native_file.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/polling.hpp" -#include "utils/string_utils.hpp" +#include "utils/string.hpp" #include "utils/utils.hpp" namespace repertory { diff --git a/repertory/repertory_test/src/file_manager_upload_test.cpp b/repertory/repertory_test/src/file_manager_upload_test.cpp index 9cdff8f6..fbc1ab99 100644 --- a/repertory/repertory_test/src/file_manager_upload_test.cpp +++ b/repertory/repertory_test/src/file_manager_upload_test.cpp @@ -25,7 +25,7 @@ #include "mocks/mock_provider.hpp" #include "mocks/mock_upload_manager.hpp" #include "utils/event_capture.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" namespace repertory { static constexpr const std::size_t test_chunk_size = 1024u; diff --git a/repertory/repertory_test/src/path_utils_test.cpp b/repertory/repertory_test/src/path_utils_test.cpp index 96f36600..a18d73c4 100644 --- a/repertory/repertory_test/src/path_utils_test.cpp +++ b/repertory/repertory_test/src/path_utils_test.cpp @@ -21,7 +21,7 @@ */ #include "test_common.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" namespace repertory { TEST(path_utils, combine) { diff --git a/repertory/repertory_test/src/providers_test.cpp b/repertory/repertory_test/src/providers_test.cpp index 7253411c..77dedd7b 100644 --- a/repertory/repertory_test/src/providers_test.cpp +++ b/repertory/repertory_test/src/providers_test.cpp @@ -29,9 +29,10 @@ #include "providers/i_provider.hpp" #include "providers/s3/s3_provider.hpp" #include "providers/sia/sia_provider.hpp" +#include "utils/collection.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" -#include "utils/string_utils.hpp" +#include "utils/path.hpp" +#include "utils/string.hpp" #include "utils/utils.hpp" #include "gtest/gtest.h" @@ -562,8 +563,8 @@ static void get_file_list(const app_config &cfg, i_provider &provider) { for (auto &file : list) { decrypt_parts(cfg, file.api_parent); decrypt_parts(cfg, file.api_path); - utils::remove_element_from(expected_parents, file.api_parent); - utils::remove_element_from(expected_paths, file.api_path); + utils::collection::remove_element(expected_parents, file.api_parent); + utils::collection::remove_element(expected_paths, file.api_path); } EXPECT_TRUE(expected_parents.empty()); EXPECT_TRUE(expected_paths.empty()); diff --git a/repertory/repertory_test/src/string_utils_test.cpp b/repertory/repertory_test/src/string_utils_test.cpp index 7e0e92ad..77fb3480 100644 --- a/repertory/repertory_test/src/string_utils_test.cpp +++ b/repertory/repertory_test/src/string_utils_test.cpp @@ -21,7 +21,7 @@ */ #include "test_common.hpp" -#include "utils/string_utils.hpp" +#include "utils/string.hpp" namespace repertory { TEST(string_utils, is_numeric) { diff --git a/repertory/repertory_test/src/test_common.cpp b/repertory/repertory_test/src/test_common.cpp index 160dc417..a3d7bc9b 100644 --- a/repertory/repertory_test/src/test_common.cpp +++ b/repertory/repertory_test/src/test_common.cpp @@ -22,7 +22,7 @@ #include "test_common.hpp" #include "types/repertory.hpp" -#include "utils/path_utils.hpp" +#include "utils/path.hpp" #include "utils/utils.hpp" namespace repertory { diff --git a/repertory/repertory_test/src/utils_test.cpp b/repertory/repertory_test/src/utils_test.cpp index d1d73c57..7927cf4f 100644 --- a/repertory/repertory_test/src/utils_test.cpp +++ b/repertory/repertory_test/src/utils_test.cpp @@ -22,8 +22,8 @@ #include "test_common.hpp" #include "utils/file_utils.hpp" -#include "utils/path_utils.hpp" -#include "utils/string_utils.hpp" +#include "utils/path.hpp" +#include "utils/string.hpp" #include "utils/utils.hpp" namespace repertory { diff --git a/scripts/copy_mingw64_deps.sh b/scripts/copy_mingw64_deps.sh index d609911a..c2772b06 100755 --- a/scripts/copy_mingw64_deps.sh +++ b/scripts/copy_mingw64_deps.sh @@ -23,6 +23,10 @@ if [ "${PROJECT_IS_MINGW}" == "1" ] && [ "${PROJECT_STATIC_LINK}" == "OFF" ]; th PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libboost*.dll) fi + if [ "${PROJECT_ENABLE_BACKWARD_CPP}" == "ON" ]; then + PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/msvcr90.dll) + fi + if [ "${PROJECT_ENABLE_CLI11}" == "ON" ]; then PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libcli11*.dll) fi @@ -31,11 +35,14 @@ if [ "${PROJECT_IS_MINGW}" == "1" ] && [ "${PROJECT_STATIC_LINK}" == "OFF" ]; th PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libFLAC*.dll) fi + if [ "${PROJECT_ENABLE_FMT}" == "ON" ]; then + PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libfmt*.dll) + fi + if [ "${PROJECT_ENABLE_FONTCONFIG}" == "ON" ]; then PROJECT_MINGW64_COPY_DEPENDENCIES+=( /mingw64/bin/libexpat*.dll /mingw64/bin/libfontconfig*.dll - /mingw64/bin/libpng*.dll ) fi @@ -47,6 +54,11 @@ if [ "${PROJECT_IS_MINGW}" == "1" ] && [ "${PROJECT_STATIC_LINK}" == "OFF" ]; th PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libcurl*.dll) fi + if [ "${PROJECT_ENABLE_LIBJPEG_TURBO}" == "ON" ]; then + PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libjpeg*.dll) + PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libturbo*.dll) + fi + if [ "${PROJECT_ENABLE_LIBSODIUM}" == "ON" ]; then PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libsodium*.dll) fi @@ -70,6 +82,14 @@ if [ "${PROJECT_IS_MINGW}" == "1" ] && [ "${PROJECT_STATIC_LINK}" == "OFF" ]; th PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libopenal*.dll) fi + if [ "${PROJECT_ENABLE_LIBPNG}" == "ON" ]; then + PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libpng*.dll) + fi + + if [ "${PROJECT_ENABLE_NANA}" == "ON" ]; then + PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libnana*.dll) + fi + if [ "${PROJECT_ENABLE_PUGIXML}" == "ON" ]; then PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libpugi*.dll) fi @@ -82,11 +102,15 @@ if [ "${PROJECT_IS_MINGW}" == "1" ] && [ "${PROJECT_STATIC_LINK}" == "OFF" ]; th PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libsecp256k1*.dll) fi + if [ "${PROJECT_ENABLE_SDL}" == "ON" ]; then + PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/SDL*.dll) + fi + if [ "${PROJECT_ENABLE_SFML}" == "ON" ]; then PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libsfml*.dll) fi - if [ "${PROJECT_ENABLE_SFML}" == "ON" ]; then + if [ "${PROJECT_ENABLE_SPDLOG}" == "ON" ]; then PROJECT_MINGW64_COPY_DEPENDENCIES+=(/mingw64/bin/libspdlog*.dll) fi diff --git a/scripts/env.sh b/scripts/env.sh index 0f9e7cad..9466c4f4 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -41,11 +41,24 @@ done PROJECT_APP_LIST=() PROJECT_CMAKE_OPTS="" PROJECT_IS_ALPINE=0 +PROJECT_IS_ARM64=0 PROJECT_MINGW64_COPY_DEPENDENCIES=() PROJECT_MSYS2_PACKAGE_LIST=() PROJECT_REQUIRE_ALPINE=OFF PROJECT_STATIC_LINK=OFF +if [ "${PROJECT_BUILD_ARCH}" == "" ]; then + PROJECT_BUILD_ARCH=x86_64 +elif [ "${PROJECT_BUILD_ARCH}" == "aarch64" ]; then + PROJECT_IS_ARM64=1 +fi + +if [ "${PROJECT_BUILD_ARCH}" == "x86_64" ]; then + PROJECT_BUILD_ARCH2="x86-64" +else + PROJECT_BUILD_ARCH2="${PROJECT_BUILD_ARCH}" +fi + if [ -f /etc/alpine-release ]; then PROJECT_IS_ALPINE=1 fi @@ -110,22 +123,13 @@ if [ "${PROJECT_ENABLE_BOOST}" == "ON" ]; then PROJECT_ENABLE_OPENSSL=ON fi -if [ "${PROJECT_ENABLE_WXWIDGETS}" == "ON" ] || [ "${PROJECT_ENABLE_NANA}" == "ON" ]; then +if [ "${PROJECT_ENABLE_FONTCONFIG}" == "ON" ] || [ "${PROJECT_ENABLE_NANA}" == "ON" ] || [ "${PROJECT_ENABLE_WXWIDGETS}" == "ON" ]; then PROJECT_ENABLE_LIBJPEG_TURBO=ON PROJECT_ENABLE_LIBPNG=ON fi -PROJECT_IS_ARM64=0 -if [ "${PROJECT_BUILD_ARCH}" == "" ]; then - PROJECT_BUILD_ARCH=x86_64 -elif [ "${PROJECT_BUILD_ARCH}" == "aarch64" ]; then - PROJECT_IS_ARM64=1 -fi - -if [ "${PROJECT_BUILD_ARCH}" == "x86_64" ]; then - PROJECT_BUILD_ARCH2="x86-64" -else - PROJECT_BUILD_ARCH2="${PROJECT_BUILD_ARCH}" +if [ "${PROJECT_IS_MINGW}" == "1" ]; then + PROJECT_ENABLE_BACKWARD_CPP=OFF fi if [ "${PROJECT_IS_MINGW}" == "1" ] && [ "${PROJECT_IS_MINGW_UNIX}" != "1" ]; then diff --git a/support/3rd_party/include/utils/all.hpp b/support/3rd_party/include/utils/all.hpp new file mode 100644 index 00000000..d0a9455f --- /dev/null +++ b/support/3rd_party/include/utils/all.hpp @@ -0,0 +1,36 @@ +/* + Copyright <2018-2024> + + 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 REPERTORY_INCLUDE_UTILS_ALL_HPP_ +#define REPERTORY_INCLUDE_UTILS_ALL_HPP_ + +#include "utils/config.hpp" + +#include "utils/collection.hpp" +#include "utils/com_init_wrapper.hpp" +#include "utils/common.hpp" +#include "utils/path.hpp" +#include "utils/string.hpp" +#include "utils/time.hpp" +#include "utils/unix.hpp" +#include "utils/windows.hpp" + +#endif // REPERTORY_INCLUDE_UTILS_ALL_HPP_ \ No newline at end of file diff --git a/repertory/librepertory/include/utils/base64.hpp b/support/3rd_party/include/utils/base64.hpp similarity index 87% rename from repertory/librepertory/include/utils/base64.hpp rename to support/3rd_party/include/utils/base64.hpp index 94e713d8..b5099d69 100644 --- a/repertory/librepertory/include/utils/base64.hpp +++ b/support/3rd_party/include/utils/base64.hpp @@ -128,18 +128,22 @@ Decode(std::string_view input) { out.resize(out_len); for (std::size_t i = 0U, j = 0U; i < in_len;) { - std::uint32_t a = input[i] == '=' - ? 0U & i++ - : kDecodingTable[static_cast(input[i++])]; - std::uint32_t b = input[i] == '=' - ? 0U & i++ - : kDecodingTable[static_cast(input[i++])]; - std::uint32_t c = input[i] == '=' - ? 0U & i++ - : kDecodingTable[static_cast(input[i++])]; - std::uint32_t d = input[i] == '=' - ? 0U & i++ - : kDecodingTable[static_cast(input[i++])]; + std::uint32_t a = + input.at(i) == '=' + ? 0U & i++ + : kDecodingTable[static_cast(input.at(i++))]; + std::uint32_t b = + input.at(i) == '=' + ? 0U & i++ + : kDecodingTable[static_cast(input.at(i++))]; + std::uint32_t c = + input.at(i) == '=' + ? 0U & i++ + : kDecodingTable[static_cast(input.at(i++))]; + std::uint32_t d = + input.at(i) == '=' + ? 0U & i++ + : kDecodingTable[static_cast(input.at(i++))]; std::uint32_t triple = (a << 3U * 6U) + (b << 2U * 6U) + (c << 1U * 6U) + (d << 0U * 6U); diff --git a/support/3rd_party/include/utils/collection.hpp b/support/3rd_party/include/utils/collection.hpp new file mode 100644 index 00000000..ad46600c --- /dev/null +++ b/support/3rd_party/include/utils/collection.hpp @@ -0,0 +1,133 @@ +/* + Copyright <2018-2024> + + 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 REPERTORY_INCLUDE_UTILS_COLLECTION_HPP_ +#define REPERTORY_INCLUDE_UTILS_COLLECTION_HPP_ + +#include "utils/config.hpp" + +namespace repertory::utils::collection { +template +[[nodiscard]] inline auto +excludes(const col_t &collection, + const typename col_t::value_type &val) -> bool; + +template +[[nodiscard]] inline auto +includes(const col_t &collection, + const typename col_t::value_type &val) -> bool; + +template +[[nodiscard]] inline auto from_hex_string(std::string_view str, + val_t &val) -> bool; + +template +[[nodiscard]] inline auto from_hex_string(std::wstring_view str, + val_t &val) -> bool; +template +inline auto remove_element(col_t &collection, + const typename col_t::value_type &value) -> col_t &; + +template +[[nodiscard]] inline auto to_hex_string(const col_t &collection) -> std::string; + +template +[[nodiscard]] inline auto +to_hex_wstring(const col_t &collection) -> std::wstring; + +template +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 +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 +[[nodiscard]] inline auto +from_hex_string_t(std::basic_string_view str, + val_t &val) -> bool { + static constexpr const auto base16{16}; + + val.clear(); + if (not(str.length() % 2U)) { + for (std::size_t i = 0U; i < str.length(); i += 2U) { + val.emplace_back(static_cast( + std::strtol(string_t{str.substr(i, 2U)}.c_str(), nullptr, base16))); + } + + return true; + } + + return false; +} + +template +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 +[[nodiscard]] inline auto to_hex_string_t(const col_t &collection) -> string_t { + static_assert(sizeof(typename col_t::value_type) == 1U, + "value_type must be 1 byte in size"); + static constexpr const auto mask = 0xFF; + + std::basic_stringstream stream{}; + for (auto &&val : collection) { + stream << std::setfill('0') << std::setw(2) << std::hex + << (static_cast(val) & mask); + } + + return stream.str(); +} + +template +inline auto from_hex_string(std::string_view str, val_t &val) -> bool { + return from_hex_string_t(str, val); +} + +template +inline auto from_hex_string(std::wstring_view str, val_t &val) -> bool { + return from_hex_string_t(str, val); +} + +template +inline auto to_hex_string(const col_t &collection) -> std::string { + return to_hex_string_t(collection); +} + +template +inline auto to_hex_wstring(const col_t &collection) -> std::wstring { + return to_hex_string_t(collection); +} +} // namespace repertory::utils::collection + +#endif // REPERTORY_INCLUDE_UTILS_COLLECTION_HPP_ diff --git a/repertory/librepertory/include/utils/com_init_wrapper.hpp b/support/3rd_party/include/utils/com_init_wrapper.hpp similarity index 82% rename from repertory/librepertory/include/utils/com_init_wrapper.hpp rename to support/3rd_party/include/utils/com_init_wrapper.hpp index 81484928..777ad247 100644 --- a/repertory/librepertory/include/utils/com_init_wrapper.hpp +++ b/support/3rd_party/include/utils/com_init_wrapper.hpp @@ -1,45 +1,47 @@ -/* - Copyright <2018-2024> - - 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 INCLUDE_UTILS_COM_INIT_WRAPPER_HPP_ -#define INCLUDE_UTILS_COM_INIT_WRAPPER_HPP_ -#if defined(_WIN32) - -namespace repertory { -class com_init_wrapper { -public: - com_init_wrapper() - : uninit_( - SUCCEEDED(::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED))) {} - - ~com_init_wrapper() { - if (uninit_) { - ::CoUninitialize(); - } - } - -private: - const BOOL uninit_; -}; -} // namespace repertory - -#endif // _WIN32 -#endif // INCLUDE_UTILS_COM_INIT_WRAPPER_HPP_ +/* + Copyright <2018-2024> + + 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 REPERTORY_INCLUDE_UTILS_COM_INIT_WRAPPER_HPP_ +#define REPERTORY_INCLUDE_UTILS_COM_INIT_WRAPPER_HPP_ +#if defined(_WIN32) + +#include "utils/config.hpp" + +namespace repertory::utils { +class com_init_wrapper { +public: + com_init_wrapper() + : uninit_( + SUCCEEDED(::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED))) {} + + ~com_init_wrapper() { + if (uninit_) { + ::CoUninitialize(); + } + } + +private: + BOOL uninit_; +}; +} // namespace repertory::utils + +#endif // defined(_WIN32) +#endif // REPERTORY_INCLUDE_UTILS_COM_INIT_WRAPPER_HPP_ diff --git a/support/3rd_party/include/utils/common.hpp b/support/3rd_party/include/utils/common.hpp new file mode 100644 index 00000000..c09513be --- /dev/null +++ b/support/3rd_party/include/utils/common.hpp @@ -0,0 +1,111 @@ +/* + Copyright <2018-2024> + + 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 REPERTORY_INCLUDE_UTILS_COMMON_HPP_ +#define REPERTORY_INCLUDE_UTILS_COMMON_HPP_ + +#include "utils/config.hpp" + +namespace repertory::utils { +struct result final { + std::string_view function_name; + bool ok{false}; + std::string reason{}; + + [[nodiscard]] operator bool() const { return ok; } +}; + +[[nodiscard]] inline auto +calculate_read_size(std::uint64_t total_size, std::size_t read_size, + std::uint64_t offset) -> std::size_t { + return static_cast( + ((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) + +#if defined(PROJECT_ENABLE_LIBSODIUM) +template +[[nodiscard]] inline auto generate_random() -> data_type; + +template +[[nodiscard]] inline auto +generate_random_between(const data_type &begin, + const data_type &end) -> data_type; + +[[nodiscard]] auto generate_random_string(std::uint16_t length) -> std::string; +#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 resolve_variables(std::string str) -> std::string; + +[[nodiscard]] auto resolve_variables(std::wstring_view str) -> std::wstring; + +// template implementations +template +[[nodiscard]] inline auto divide_with_ceiling(const val_t &n, + const val_t &d) -> val_t { + return n ? (n / d) + (n % d != 0) : 0; +} + +#if defined(PROJECT_ENABLE_LIBSODIUM) +template +[[nodiscard]] inline auto generate_random() -> data_type { + data_type ret{}; + randombytes_buf(&ret, sizeof(ret)); + return ret; +} + +template +[[nodiscard]] inline auto +generate_random_between(const data_type &begin, + const data_type &end) -> data_type { + return begin + generate_random() % ((end + data_type{1}) - begin); +} +#endif // defined(PROJECT_ENABLE_LIBSODIUM) +} // namespace repertory::utils + +#endif // REPERTORY_INCLUDE_UTILS_COMMON_HPP_ diff --git a/support/3rd_party/include/utils/config.hpp b/support/3rd_party/include/utils/config.hpp new file mode 100644 index 00000000..32e549aa --- /dev/null +++ b/support/3rd_party/include/utils/config.hpp @@ -0,0 +1,313 @@ +/* + Copyright <2018-2024> + + 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 REPERTORY_INCLUDE_UTILS_CONFIG_HPP_ +#define REPERTORY_INCLUDE_UTILS_CONFIG_HPP_ + +#if defined(_WIN32) +#define WINVER 0x0602 +#define _WIN32_WINNT WINVER +#define WIN32_LEAN_AND_MEAN + +#include +#include + +#include +#if defined(PROJECT_ENABLE_WINFSP) +#include +#endif // defined(PROJECT_ENABLE_WINFSP) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else // !defined(_WIN32) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(__LFS64__) +#include +#else +#include +#endif + +#if defined(__linux__) +#include +#endif // defined(HAS_SETXATTR) + +#if defined(HAS_SETXATTR) +#include +#include +#endif // defined(HAS_SETXATTR) + +#if defined(__APPLE__) +#include +#include +#include +#include +#include +#endif // defined(__APPLE__) + +#include +#endif // defined(_WIN32) + +#if defined(HAS_WORDEXP_H) +#include +#endif // defined(HAS_WORDEXP_H) + +#if defined(__cplusplus) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // defined(__cplusplus) + +#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 +#include +#else +#include +#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_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_SDL) +#include "SDL.h" +#include "SDL_gamecontroller.h" +#include "SDL_joystick.h" +#endif // defined(PROJECT_ENABLE_SDL) + +#if defined(PROJECT_ENABLE_LIBSODIUM) +#include "sodium.h" +#endif // defined(PROJECT_ENABLE_LIBSODIUM) + +#if defined(PROJECT_ENABLE_SQLITE) +#include "sqlite3.h" +#endif // defined(PROJECT_ENABLE_SQLITE) + +#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_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/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_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) +#include "winfsp/winfsp.hpp" +#endif // defined(PROJECT_ENABLE_WINFSP) + +#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) + +namespace repertory { +using data_buffer = std::vector; +using mutex_lock = std::lock_guard; +using recur_mutex_lock = std::lock_guard; +using unique_mutex_lock = std::unique_lock; +using unique_recur_mutex_lock = std::unique_lock; + +template struct overloaded : Ts... { + using Ts::operator()...; +}; +template overloaded(Ts...) -> overloaded; + +struct file_deleter final { + void operator()(FILE *file) { + if (file != nullptr) { + fclose(file); + } + } +}; +using file_t = std::unique_ptr; +} // namespace repertory +#endif // defined(__cplusplus) + +#endif // REPERTORY_INCLUDE_UTILS_CONFIG_HPP_ diff --git a/support/3rd_party/include/utils/encryption.hpp b/support/3rd_party/include/utils/encryption.hpp new file mode 100644 index 00000000..91650ca9 --- /dev/null +++ b/support/3rd_party/include/utils/encryption.hpp @@ -0,0 +1,160 @@ +/* + Copyright <2018-2024> + + 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 REPERTORY_INCLUDE_UTILS_ENCRYPTION_HPP_ +#define REPERTORY_INCLUDE_UTILS_ENCRYPTION_HPP_ +#if defined(PROJECT_ENABLE_LIBSODIUM) + +#include "utils/config.hpp" + +namespace repertory::utils::encryption { +using hash_256_t = std::array; +using hash_256_func_t = std::function; +using key_type = std::array; + +inline constexpr const std::uint32_t encryption_header_size{ + crypto_aead_xchacha20poly1305_IETF_NPUBBYTES + + crypto_aead_xchacha20poly1305_IETF_ABYTES, +}; + +[[nodiscard]] auto decrypt_data( + std::string_view data, std::string_view password, + std::optional hasher = std::nullopt) -> data_buffer; + +[[nodiscard]] auto encrypt_data( + std::string_view data, std::string_view password, + std::optional hasher = std::nullopt) -> data_buffer; + +[[nodiscard]] auto generate_key(std::string_view encryption_token) -> key_type; + +#if defined(PROJECT_ENABLE_BOOST) +template +[[nodiscard]] inline auto +decrypt_data(const key_type &key, const unsigned char *buffer, + std::size_t buffer_size, result &res) -> bool { + if (buffer_size > encryption_header_size) { + const std::uint32_t size = + boost::endian::native_to_big(static_cast(buffer_size)); + res.resize(buffer_size - encryption_header_size); + return crypto_aead_xchacha20poly1305_ietf_decrypt_detached( + reinterpret_cast(res.data()), nullptr, + &buffer[header_size], res.size(), + &buffer[crypto_aead_xchacha20poly1305_IETF_NPUBBYTES], + reinterpret_cast(&size), sizeof(size), + buffer, key.data()) == 0; + } + + return false; +} + +template +[[nodiscard]] inline auto decrypt_data(const key_type &key, const buffer &buf, + result &res) -> bool { + return decrypt_data( + key, reinterpret_cast(buf.data()), buf.size(), + res); +} + +template +[[nodiscard]] inline auto decrypt_data(std::string_view encryption_token, + const buffer &buf, result &res) -> bool { + return decrypt_data(generate_key(encryption_token), buf, res); +} + +template +[[nodiscard]] inline auto +decrypt_data(std::string_view encryption_token, const unsigned char *buffer, + std::size_t buffer_size, result &res) -> bool { + return decrypt_data(generate_key(encryption_token), buffer, + buffer_size, res); +} + +template +inline void +encrypt_data(const std::array &iv, + const key_type &key, const unsigned char *buffer, + std::size_t buffer_size, result &res) { + std::array mac{}; + + const std::uint32_t size = boost::endian::native_to_big( + static_cast(buffer_size + encryption_header_size)); + + res.resize(buffer_size + header_size); + + unsigned long long mac_length{}; + if (crypto_aead_xchacha20poly1305_ietf_encrypt_detached( + reinterpret_cast(&res[encryption_header_size]), + mac.data(), &mac_length, buffer, buffer_size, + reinterpret_cast(&size), sizeof(size), nullptr, + iv.data(), key.data()) != 0) { + throw std::runtime_error("encryption failed"); + } + + std::memcpy(res.data(), iv.data(), iv.size()); + std::memcpy(&res[iv.size()], mac.data(), mac.size()); +} + +template +inline void encrypt_data(const key_type &key, const unsigned char *buffer, + std::size_t buffer_size, result &res) { + std::array iv{}; + randombytes_buf(iv.data(), iv.size()); + + encrypt_data(iv, key, buffer, buffer_size, res); +} + +template +inline void encrypt_data(std::string_view encryption_token, + const unsigned char *buffer, std::size_t buffer_size, + result &res) { + encrypt_data(generate_key(encryption_token), buffer, buffer_size, + res); +} + +template +inline void encrypt_data(std::string_view encryption_token, const buffer &buf, + result &res) { + encrypt_data(generate_key(encryption_token), + reinterpret_cast(buf.data()), + buf.size(), res); +} + +template +inline void encrypt_data(const key_type &key, const buffer &buf, result &res) { + encrypt_data(key, reinterpret_cast(buf.data()), + buf.size(), res); +} + +template +inline void +encrypt_data(const std::array &iv, + const key_type &key, const buffer &buf, result &res) { + encrypt_data(iv, key, + reinterpret_cast(buf.data()), + buf.size(), res); +} +#endif // defined(PROJECT_ENABLE_BOOST) +} // namespace repertory::utils::encryption + +#endif // defined(PROJECT_ENABLE_LIBSODIUM) +#endif // REPERTORY_INCLUDE_UTILS_ENCRYPTION_HPP_ diff --git a/support/3rd_party/include/utils/error.hpp b/support/3rd_party/include/utils/error.hpp new file mode 100644 index 00000000..11671fdf --- /dev/null +++ b/support/3rd_party/include/utils/error.hpp @@ -0,0 +1,52 @@ +/* + Copyright <2018-2024> + + 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 REPERTORY_INCLUDE_UTILS_ERROR_HPP_ +#define REPERTORY_INCLUDE_UTILS_ERROR_HPP_ + +#include "utils/config.hpp" + +namespace repertory::utils::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; + + 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; + +protected: + i_exception_handler() = default; +}; + +void handle_exception(std::string_view function_name); + +void handle_exception(std::string_view function_name, const std::exception &ex); + +void set_exception_handler(i_exception_handler *handler); +} // namespace repertory::utils::error + +#endif // REPERTORY_INCLUDE_UTILS_ERROR_HPP_ diff --git a/support/3rd_party/include/utils/file.hpp b/support/3rd_party/include/utils/file.hpp new file mode 100644 index 00000000..d0fb63a4 --- /dev/null +++ b/support/3rd_party/include/utils/file.hpp @@ -0,0 +1,147 @@ +/* + Copyright <2018-2024> + + 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 REPERTORY_INCLUDE_UTILS_FILE_HPP_ +#define REPERTORY_INCLUDE_UTILS_FILE_HPP_ + +#include "utils/config.hpp" + +namespace repertory::utils::file { +class file final { +public: + [[nodiscard]] static auto open_file(std::filesystem::path path) -> file; + + [[nodiscard]] static auto + open_or_create_file(std::filesystem::path path) -> file; + +protected: + file(std::fstream stream, std::filesystem::path path) + : path_(std::move(path)), stream_(std::move(stream)) {} + file() = default; + +public: + file(const file &) = delete; + file(file &&file_) noexcept = default; + + ~file() { close(); } + + auto operator=(const file &) noexcept -> file & = delete; + auto operator=(file &&file_) noexcept -> file & = default; + +private: + std::error_code error_{}; + std::filesystem::path path_; + std::fstream stream_; + +public: + void close(); + + [[nodiscard]] auto get_error_code() const -> std::error_code { + return error_; + } + + [[nodiscard]] auto get_path() const -> std::filesystem::path { return path_; } + + [[nodiscard]] auto move_to(std::filesystem::path new_path) -> bool; + + [[nodiscard]] 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]] auto remove() -> bool; + + [[nodiscard]] auto truncate() -> bool { return truncate(0U); } + + [[nodiscard]] auto truncate(std::size_t size) -> bool; + +#if defined(PROJECT_ENABLE_JSON) + [[nodiscard]] auto write(const nlohmann::json &data, std::uint64_t offset, + std::size_t *total_written = nullptr) -> bool { + return write(data.dump().c_str(), offset, total_written); + } +#endif // defined(PROJECT_ENABLE_JSON) + + [[nodiscard]] 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]] operator bool() const { return stream_.is_open(); } + +private: + [[nodiscard]] auto read(unsigned char *data, std::size_t to_read, + std::uint64_t offset, + std::size_t *total_read) -> bool; + + [[nodiscard]] auto write(const typename data_buffer::value_type *data, + std::size_t to_write, std::size_t offset, + std::size_t *total_written) -> bool; +}; + +[[nodiscard]] auto get_file_size(std::string_view path, + std::uint64_t &file_size) -> bool; + +[[nodiscard]] auto get_file_size(std::wstring_view path, + std::uint64_t &file_size) -> bool; + +[[nodiscard]] auto is_directory(std::string_view path) -> bool; + +[[nodiscard]] auto is_directory(std::wstring_view path) -> bool; + +[[nodiscard]] auto is_file(std::string_view path) -> bool; + +[[nodiscard]] auto is_file(std::wstring_view path) -> bool; + +#if defined(PROJECT_ENABLE_JSON) +#if defined(PROJECT_ENABLE_LIBSODIUM) +[[nodiscard]] auto +read_json_file(std::string_view path, nlohmann::json &data, + std::optional password = std::nullopt) -> bool; + +[[nodiscard]] auto read_json_file( + std::wstring_view path, nlohmann::json &data, + std::optional password = std::nullopt) -> bool; + +[[nodiscard]] auto write_json_file( + std::string_view path, const nlohmann::json &data, + std::optional password = std::nullopt) -> bool; + +[[nodiscard]] auto write_json_file( + std::wstring_view path, const nlohmann::json &data, + std::optional password = std::nullopt) -> bool; +#else // !defined(PROJECT_ENABLE_LIBSODIUM) +[[nodiscard]] auto read_json_file(std::string_view path, + nlohmann::json &data) -> bool; + +[[nodiscard]] auto read_json_file(std::wstring_view path, + nlohmann::json &data) -> bool; + +[[nodiscard]] auto write_json_file(std::string_view path, + const nlohmann::json &data) -> bool; + +[[nodiscard]] auto write_json_file(std::wstring_view path, + const nlohmann::json &data) -> bool; +#endif // defined(PROJECT_ENABLE_LIBSODIUM) +#endif // defined(PROJECT_ENABLE_JSON) +} // namespace repertory::utils::file + +#endif // REPERTORY_INCLUDE_UTILS_FILE_HPP_ diff --git a/support/3rd_party/include/utils/path.hpp b/support/3rd_party/include/utils/path.hpp new file mode 100644 index 00000000..747a618a --- /dev/null +++ b/support/3rd_party/include/utils/path.hpp @@ -0,0 +1,403 @@ +/* + Copyright <2018-2024> + + 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 REPERTORY_INCLUDE_UTILS_PATH_HPP_ +#define REPERTORY_INCLUDE_UTILS_PATH_HPP_ + +#include "utils/config.hpp" +#include "utils/string.hpp" + +namespace repertory::utils::path { +inline constexpr const std::string_view backslash{"\\"}; +inline constexpr const std::wstring_view backslash_w{L"\\"}; +inline constexpr const std::string_view dot{"."}; +inline constexpr const std::wstring_view dot_w{L"."}; +inline constexpr const std::string_view dot_slash{"./"}; +inline constexpr const std::wstring_view dot_slash_w{L"./"}; +inline constexpr const std::string_view slash{"/"}; +inline constexpr const std::wstring_view slash_w{L"/"}; +#if defined(_WIN32) +inline constexpr const std::string_view directory_seperator{backslash}; +inline constexpr const std::wstring_view directory_seperator_w{backslash_w}; +inline constexpr const std::string_view not_directory_seperator{slash}; +inline constexpr const std::wstring_view not_directory_seperator_w{slash_w}; +#else // !defined(_WIN32) +inline constexpr const std::string_view directory_seperator{slash}; +inline constexpr const std::wstring_view directory_seperator_w{slash_w}; +inline constexpr const std::string_view not_directory_seperator{backslash}; +inline constexpr const std::wstring_view not_directory_seperator_w{backslash_w}; +#endif // defined(_WIN32) + +template +[[nodiscard]] inline constexpr auto +get_backslash() -> std::basic_string_view; + +template <> +[[nodiscard]] inline constexpr auto +get_backslash() -> std::basic_string_view { + return backslash; +} + +template <> +[[nodiscard]] inline constexpr auto +get_backslash() -> std::basic_string_view { + return backslash_w; +} + +template +[[nodiscard]] inline constexpr auto get_dot() -> std::basic_string_view; + +template <> +[[nodiscard]] inline constexpr auto +get_dot() -> std::basic_string_view { + return dot; +} + +template <> +[[nodiscard]] inline constexpr auto +get_dot() -> std::basic_string_view { + return dot_w; +} + +template +[[nodiscard]] inline constexpr auto +get_dot_slash() -> std::basic_string_view; + +template <> +[[nodiscard]] inline constexpr auto +get_dot_slash() -> std::basic_string_view { + return dot_slash; +} + +template <> +[[nodiscard]] inline constexpr auto +get_dot_slash() -> std::basic_string_view { + return dot_slash_w; +} + +template +[[nodiscard]] inline constexpr auto +get_slash() -> std::basic_string_view; + +template <> +[[nodiscard]] inline constexpr auto +get_slash() -> std::basic_string_view { + return slash; +} + +template <> +[[nodiscard]] inline constexpr auto +get_slash() -> std::basic_string_view { + return slash_w; +} + +template +[[nodiscard]] inline constexpr auto +get_directory_seperator() -> std::basic_string_view; + +template <> +[[nodiscard]] inline constexpr auto +get_directory_seperator() -> std::basic_string_view { + return directory_seperator; +} + +template <> +[[nodiscard]] inline constexpr auto +get_directory_seperator() -> std::basic_string_view { + return directory_seperator_w; +} + +template +[[nodiscard]] inline constexpr auto +get_not_directory_seperator() -> std::basic_string_view; + +template <> +[[nodiscard]] inline constexpr auto +get_not_directory_seperator() -> std::basic_string_view { + return not_directory_seperator; +} + +template <> +[[nodiscard]] inline constexpr auto +get_not_directory_seperator() -> std::basic_string_view { + return not_directory_seperator_w; +} + +[[nodiscard]] inline auto absolute(std::string_view path) -> std::string; + +[[nodiscard]] inline auto absolute(std::wstring_view path) -> std::wstring; + +[[nodiscard]] inline auto +combine(std::string path, + const std::vector &paths) -> std::string; + +[[nodiscard]] inline auto +combine(std::wstring path, + const std::vector &paths) -> std::wstring; + +[[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]] inline auto +directory_exists_in_path(std::string_view path, + std::string_view sub_directory) -> bool; + +[[nodiscard]] inline auto +directory_exists_in_path(std::wstring_view path, + std::wstring_view sub_directory) -> bool; + +[[nodiscard]] inline auto +file_exists_in_path(std::string_view path, std::string_view file_name) -> bool; + +[[nodiscard]] inline auto +file_exists_in_path(std::wstring_view path, + std::wstring_view file_name) -> 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 +inline auto +format_path(string_t &path, + std::basic_string_view sep, + std::basic_string_view 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_directory(std::string_view path) -> std::string; + +[[nodiscard]] auto get_parent_directory(std::wstring_view path) -> std::wstring; + +[[nodiscard]] auto is_trash_directory(std::string_view path) -> bool; + +[[nodiscard]] auto is_trash_directory(std::wstring_view path) -> bool; + +[[nodiscard]] auto make_file_uri(std::string_view path) -> std::string; + +[[nodiscard]] auto make_file_uri(std::wstring_view path) -> std::wstring; + +[[nodiscard]] auto remove_file_name(std::string_view path) -> std::string; + +[[nodiscard]] auto remove_file_name(std::wstring_view path) -> std::wstring; + +#if !defined(_WIN32) +[[nodiscard]] auto resolve(std::string path) -> std::string; + +[[nodiscard]] auto resolve(std::wstring_view path) -> std::wstring; +#endif // !defined(_WIN32) + +[[nodiscard]] auto strip_to_file_name(std::string_view path) -> std::string; + +[[nodiscard]] auto unmake_file_uri(std::string_view uri) -> std::string; + +[[nodiscard]] auto unmake_file_uri(std::wstring_view uri) -> std::wstring; + +inline auto absolute(std::string_view path) -> std::string { + return finalize(std::filesystem::absolute(path).lexically_normal().string()); +} + +inline auto absolute(std::wstring_view path) -> std::wstring { + return finalize(std::filesystem::absolute(path).lexically_normal().wstring()); +} + +template +[[nodiscard]] inline auto combine_t( + string_t path, + const std::vector> + &paths) -> string_t { + return absolute(std::accumulate( + paths.begin(), paths.end(), path, [](auto next_path, auto &&path_part) { + if (next_path.empty()) { + return string_t{path_part}; + } + + return next_path + + string_t{ + get_directory_seperator()} + + string_t{path_part}; + })); +} + +inline auto combine(std::string path, + const std::vector &paths) -> std::string { + return combine_t(path, paths); +} + +inline auto +combine(std::wstring path, + const std::vector &paths) -> std::wstring { + return combine_t(path, paths); +} + +template +[[nodiscard]] inline auto create_api_path_t( + std::basic_string_view path) -> string_t { + static auto backslash_t = get_backslash(); + static auto dot_slash_t = get_dot_slash(); + static auto dot_t = get_dot(); + static auto slash_t = get_slash(); + + if (path.empty() || (path == dot_t) || (path == slash_t)) { + return string_t{slash_t}; + } + + string_t api_path{path}; + format_path(api_path, slash_t, backslash_t); + if (api_path.find(dot_slash_t) == 0) { + api_path = api_path.substr(1U); + } + + if (api_path.at(0U) != '/') { + api_path = string_t{slash_t} + api_path; + } + + if ((api_path != slash_t) && utils::string::ends_with(api_path, slash_t)) { + utils::string::right_trim(api_path, '/'); + } + + return api_path; +} + +inline auto create_api_path(std::string_view path) -> std::string { + return create_api_path_t(path); +} + +inline auto create_api_path(std::wstring_view path) -> std::wstring { + return create_api_path_t(path); +} + +template +[[nodiscard]] inline auto directory_exists_in_path_t( + std::basic_string_view path, + std::basic_string_view sub_directory) + -> bool { + return std::filesystem::is_directory( + std::filesystem::path(path).append(sub_directory)); +} + +inline auto directory_exists_in_path(std::string_view path, + std::string_view sub_directory) -> bool { + return directory_exists_in_path_t(path, sub_directory); +} + +inline auto directory_exists_in_path(std::wstring_view path, + std::wstring_view sub_directory) -> bool { + return directory_exists_in_path_t(path, sub_directory); +} + +template +[[nodiscard]] inline auto file_exists_in_path_t( + std::basic_string_view path, + std::basic_string_view file_name) -> bool { + return std::filesystem::is_regular_file( + std::filesystem::path(path).append(file_name)); +} + +inline auto file_exists_in_path(std::string_view path, + std::string_view file_name) -> bool { + return file_exists_in_path_t(path, file_name); +} + +inline auto file_exists_in_path(std::wstring_view path, + std::wstring_view file_name) -> bool { + return file_exists_in_path_t(path, file_name); +} + +template +[[nodiscard]] inline auto finalize_t( + std::basic_string_view path) -> string_t { + string_t fmt_path{path}; + +#if defined(_WIN32) + if ((fmt_path.size() >= 2U) && (fmt_path.at(1U) == ':')) { + fmt_path[0U] = + utils::string::to_lower(string_t{1U, fmt_path.at(0U)}).at(0U); + } +#endif // defined(_WIN32) + + return fmt_path; +} + +inline auto finalize(std::string_view path) -> std::string { + return finalize_t(path); +} + +inline auto finalize(std::wstring_view path) -> std::wstring { + return finalize_t(path); +} + +template +inline auto +format_path(string_t &path, + std::basic_string_view sep, + std::basic_string_view not_sep) + -> string_t & { + utils::string::replace(path, not_sep, sep); + + string_t double_sep{2, sep.at(0U)}; + while (utils::string::contains(path, double_sep)) { + utils::string::replace(path, double_sep, sep); + } + + return path; +} + +template +[[nodiscard]] inline auto get_parent_api_path_t( + std::basic_string_view path) -> string_t { + static auto slash_t = get_slash(); + + string_t ret; + if (path == slash_t) { + return ret; + } + + ret = path.substr(0, path.rfind('/') + 1); + if (ret == slash_t) { + return ret; + } + return utils::string::right_trim(ret, '/'); +} + +inline auto get_parent_api_path(std::string_view path) -> std::string { + return get_parent_api_path_t(path); +} + +inline auto get_parent_api_path(std::wstring_view path) -> std::wstring { + return get_parent_api_path_t(path); +} +} // namespace repertory::utils::path + +#endif // REPERTORY_INCLUDE_UTILS_PATH_HPP_ diff --git a/support/3rd_party/include/utils/string.hpp b/support/3rd_party/include/utils/string.hpp new file mode 100644 index 00000000..83b023b7 --- /dev/null +++ b/support/3rd_party/include/utils/string.hpp @@ -0,0 +1,496 @@ +/* + Copyright <2018-2024> + + 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 REPERTORY_INCLUDE_UTILS_STRING_HPP_ +#define REPERTORY_INCLUDE_UTILS_STRING_HPP_ + +#include "utils/config.hpp" + +namespace repertory::utils::string { +template struct chain_replace_with_hex; + +template +[[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 +[[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 +[[nodiscard]] inline auto join(const std::vector &arr, + typename string_t::value_type delim) -> string_t; + +template +auto left_trim(string_t &str, + typename string_t::value_type trim_ch = ' ') -> string_t &; + +template +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 +inline auto replace(string_t &src, + std::basic_string_view find, + std::basic_string_view with, + std::size_t start_pos = 0U) -> string_t &; + +template +[[nodiscard]] auto from_hex_string(const std::string &str, t &val) -> bool; + +template +[[nodiscard]] auto to_hex_string(const collection_t &collection) -> std::string; + +template +[[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 +[[nodiscard]] inline auto +replace_copy(string_t src, + std::basic_string_view find, + std::basic_string_view with, + std::size_t start_pos = 0U) -> string_t; + +template +[[nodiscard]] inline auto +replace_with_hex(string_t &str, typename string_t::value_type character) + -> chain_replace_with_hex; + +template +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; + +[[nodiscard]] inline auto split(std::wstring_view str, wchar_t delim, + bool should_trim) -> std::vector; + +[[nodiscard]] inline auto split(std::string_view str, std::string_view delim, + bool should_trim) -> std::vector; + +[[nodiscard]] inline auto split(std::wstring_view str, std::wstring_view delim, + bool should_trim) -> std::vector; + +#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; +#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 +[[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 +[[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 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(str, character); + } + + string_t &str; +}; + +template +inline auto trim(string_t &str, + typename string_t::value_type trim_ch = ' ') -> string_t &; + +template +[[nodiscard]] inline auto +trim_copy(string_t str, + typename string_t::value_type trim_ch = ' ') -> string_t; + +template +[[nodiscard]] inline auto +begins_with_t(std::basic_string_view str, + std::basic_string_view val) -> bool { + return (str.find(val) == 0U); +} + +inline auto begins_with(std::string_view str, std::string_view val) -> bool { + return begins_with_t(str, val); +} + +inline auto begins_with(std::wstring_view str, std::wstring_view val) -> bool { + return begins_with_t(str, val); +} + +template +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 +inline auto char_to_hex(typename string_t::value_type character) -> string_t { + std::basic_stringstream stream; + stream << '%' << std::setfill('0') + << std::setw(sizeof(character)) << std::hex + << static_cast(character); + return stream.str(); +} + +template +[[nodiscard]] inline auto +contains_t(std::basic_string_view str, + std::basic_string_view search) -> bool { + return (str.find(search) != std::basic_string_view::npos); +} + +inline auto contains(std::string_view str, std::string_view search) -> bool { + return contains_t(str, search); +} + +inline auto contains(std::wstring_view str, std::wstring_view search) -> bool { + return contains_t(str, search); +} + +template +[[nodiscard]] inline auto +ends_with_t(std::basic_string_view str, + std::basic_string_view 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(str, val); +} + +inline auto ends_with(std::wstring_view str, std::wstring_view val) -> bool { + return ends_with_t(str, val); +} + +template +[[nodiscard]] inline auto +is_numeric_t(std::basic_string_view 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(str); +} + +inline auto is_numeric(std::wstring_view str) -> bool { + return is_numeric_t(str); +} + +template +inline auto join(const std::vector &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 +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 +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 (not src.empty() && (start_pos < src.size())) { + std::replace(std::next(src.begin(), start_pos), src.end(), character, with); + } + + return src; +} + +template +inline auto replace(string_t &src, + std::basic_string_view find, + std::basic_string_view with, + std::size_t start_pos) -> string_t & { + if (not src.empty() && (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 +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 +inline auto +replace_copy(string_t src, + std::basic_string_view find, + std::basic_string_view with, + std::size_t start_pos) -> string_t { + return replace(src, find, with, start_pos); +} + +template +inline auto replace_with_hex(string_t &str, + typename string_t::value_type character) + -> chain_replace_with_hex { + return chain_replace_with_hex( + replace(str, string_t{1U, character}, char_to_hex(character))); +} + +template +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 inline auto to_lower(string_t str) -> string_t { + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + return str; +} + +template inline auto to_upper(string_t str) -> string_t { + std::transform(str.begin(), str.end(), str.begin(), ::toupper); + return str; +} + +template +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 +inline auto trim_copy(string_t str, + typename string_t::value_type trim_ch) -> string_t { + return trim(str, trim_ch); +} + +template +[[nodiscard]] inline auto +split_t(std::basic_string_view str, + typename string_t::value_type delim, + bool should_trim) -> std::vector { + std::vector ret; + std::basic_stringstream 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 { + return split_t(str, delim, should_trim); +} + +inline auto split(std::wstring_view str, wchar_t delim, + bool should_trim) -> std::vector { + return split_t(str, delim, should_trim); +} + +template +[[nodiscard]] inline auto +split_t(std::basic_string_view str, + std::basic_string_view delim, + bool should_trim) -> std::vector { + auto result = std::views::split(str, delim); + + std::vector 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 { + return split_t(str, delim, should_trim); +} + +inline auto split(std::wstring_view str, std::wstring_view delim, + bool should_trim) -> std::vector { + return split_t(str, delim, should_trim); +} + +template +auto from_hex_string(const std::string &str, t &val) -> bool { + static constexpr const auto base16 = 16; + + val.clear(); + if (not(str.length() % 2U)) { + for (std::size_t i = 0U; i < str.length(); i += 2U) { + val.emplace_back(static_cast( + strtol(str.substr(i, 2U).c_str(), nullptr, base16))); + } + return true; + } + + return false; +} + +template +auto to_hex_string(const collection_t &collection) -> std::string { + static_assert(sizeof(typename collection_t::value_type) == 1U, + "value_type must be 1 byte in size"); + static constexpr const auto mask = 0xFF; + + std::stringstream stream; + for (auto &&val : collection) { + stream << std::setfill('0') << std::setw(2) << std::hex + << (static_cast(val) & mask); + } + + return stream.str(); +} +} // namespace repertory::utils::string + +#endif // REPERTORY_INCLUDE_UTILS_STRING_HPP_ diff --git a/support/3rd_party/include/utils/time.hpp b/support/3rd_party/include/utils/time.hpp new file mode 100644 index 00000000..2db765ef --- /dev/null +++ b/support/3rd_party/include/utils/time.hpp @@ -0,0 +1,64 @@ +/* + Copyright <2018-2024> + + 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 REPERTORY_INCLUDE_UTILS_TIME_HPP_ +#define REPERTORY_INCLUDE_UTILS_TIME_HPP_ + +#include "utils/config.hpp" + +namespace repertory::utils::time { +inline constexpr const auto NANOS_PER_SECOND = 1000000000L; + +#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(_WIN32) +[[nodiscard]] auto +filetime_to_unix_time(const FILETIME &file_time) -> std::uint64_t; +#endif // defined(_WIN32) + +#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) + +[[nodiscard]] auto get_file_time_now() -> std::uint64_t; + +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 time64_to_unix_time(const __time64_t &time) -> std::uint64_t; + +[[nodiscard]] auto unix_time_to_filetime(std::uint64_t unix_time) -> FILETIME; +#endif // defined(_WIN32) +} // namespace repertory::utils::time + +#endif // REPERTORY_INCLUDE_UTILS_TIME_HPP_ diff --git a/support/3rd_party/include/utils/unix.hpp b/support/3rd_party/include/utils/unix.hpp new file mode 100644 index 00000000..5ea7e84e --- /dev/null +++ b/support/3rd_party/include/utils/unix.hpp @@ -0,0 +1,64 @@ +/* + Copyright <2018-2024> + + 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 REPERTORY_INCLUDE_UTILS_UNIX_HPP_ +#define REPERTORY_INCLUDE_UTILS_UNIX_HPP_ +#if !defined(_WIN32) + +#include "utils/common.hpp" +#include "utils/config.hpp" + +namespace repertory::utils { +using passwd_callback_t = std::function; + +#if defined(__APPLE__) +template +[[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__) + +[[nodiscard]] auto get_last_error_code() -> int; + +[[nodiscard]] auto get_thread_id() -> std::uint64_t; + +[[nodiscard]] auto is_uid_member_of_group(const uid_t &uid, + const 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; + +// template implementations +#if defined(__APPLE__) +template +[[nodiscard]] auto +convert_to_uint64(const thread_t *thread_ptr) -> std::uint64_t { + return static_cast( + reinterpret_cast(thread_ptr)); +} +#endif // defined(__APPLE__) +} // namespace repertory::utils + +#endif // !defined(_WIN32) +#endif // REPERTORY_INCLUDE_UTILS_UNIX_HPP_ diff --git a/support/3rd_party/include/utils/windows.hpp b/support/3rd_party/include/utils/windows.hpp new file mode 100644 index 00000000..a46cf45d --- /dev/null +++ b/support/3rd_party/include/utils/windows.hpp @@ -0,0 +1,43 @@ +/* + Copyright <2018-2024> + + 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 REPERTORY_INCLUDE_UTILS_WINDOWS_HPP_ +#define REPERTORY_INCLUDE_UTILS_WINDOWS_HPP_ +#if defined(_WIN32) + +#include "utils/config.hpp" + +namespace repertory::utils { +[[nodiscard]] auto get_local_app_data_directory() -> const std::string &; + +[[nodiscard]] auto get_last_error_code() -> DWORD; + +[[nodiscard]] auto get_thread_id() -> std::uint64_t; + +[[nodiscard]] auto is_process_elevated() -> bool; + +[[nodiscard]] auto run_process_elevated(std::vector args) -> int; + +void set_last_error_code(DWORD errorCode); +} // namespace repertory::utils + +#endif // defined(_WIN32) +#endif // REPERTORY_INCLUDE_UTILS_WINDOWS_HPP_ diff --git a/support/3rd_party/src/backward.cpp b/support/3rd_party/src/backward.cpp index ccfb49cc..c0330166 100644 --- a/support/3rd_party/src/backward.cpp +++ b/support/3rd_party/src/backward.cpp @@ -1,4 +1,3 @@ -#if defined(PROJECT_ENABLE_BACKWARD_CPP) // Pick your poison. // // On GNU/Linux, you have few choices to get the most out of your stack trace. @@ -33,12 +32,14 @@ // - apt-get install libunwind-dev // - g++/clang++ -lunwind // #define BACKWARD_HAS_LIBUNWIND 1 - #include "backward.hpp" +#if defined(PROJECT_ENABLE_BACKWARD_CPP) + namespace backward { backward::SignalHandling sh; } // namespace backward + #endif // defined(PROJECT_ENABLE_BACKWARD_CPP) diff --git a/support/3rd_party/src/utils/common.cpp b/support/3rd_party/src/utils/common.cpp new file mode 100644 index 00000000..9b1e10d3 --- /dev/null +++ b/support/3rd_party/src/utils/common.cpp @@ -0,0 +1,169 @@ +/* + Copyright <2018-2024> + + 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. +*/ +#include "utils/common.hpp" + +#include "utils/string.hpp" + +namespace repertory::utils { +auto compare_version_strings(std::string version1, + std::string version2) -> std::int32_t { + + if (utils::string::contains(version1, "-")) { + version1 = utils::string::split(version1, '-', true)[0U]; + } + + if (utils::string::contains(version2, "-")) { + version2 = utils::string::split(version2, '-', true)[0U]; + } + + auto nums1 = utils::string::split(version1, '.', true); + auto nums2 = utils::string::split(version2, '.', true); + + while (nums1.size() > nums2.size()) { + nums2.emplace_back("0"); + } + + while (nums2.size() > nums1.size()) { + nums1.emplace_back("0"); + } + + for (std::size_t idx = 0U; idx < nums1.size(); idx++) { + auto int1 = utils::string::to_uint32(nums1[idx]); + auto int2 = utils::string::to_uint32(nums2[idx]); + auto res = std::memcmp(&int1, &int2, sizeof(int1)); + if (res != 0) { + return res; + } + } + + return 0; +} + +auto compare_version_strings(std::wstring_view version1, + std::wstring_view version2) -> std::int32_t { + return compare_version_strings(utils::string::to_utf8(version1), + utils::string::to_utf8(version2)); +} + +#if defined(PROJECT_ENABLE_STDUUID) +auto create_uuid_string() -> std::string { + std::random_device random_device; + auto seed_data = std::array{}; + std::generate(std::begin(seed_data), std::end(seed_data), + std::ref(random_device)); + std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); + std::mt19937 generator(seq); + uuids::uuid_random_generator gen{generator}; + + return uuids::to_string(gen()); +} + +auto create_uuid_wstring() -> std::wstring { + return utils::string::from_utf8(create_uuid_string()); +} +#endif // defined(PROJECT_ENABLE_STDUUID) + +#if defined(PROJECT_ENABLE_LIBSODIUM) +auto generate_random_string(std::uint16_t length) -> std::string { + std::string ret; + ret.resize(length); + for (std::uint16_t i = 0U; i < length; i++) { + do { + ret[i] = static_cast(generate_random() % 74 + 48); + } while (((ret[i] >= 91) && (ret[i] <= 96)) || + ((ret[i] >= 58) && (ret[i] <= 64))); + } + + return ret; +} +#endif // defined(PROJECT_ENABLE_LIBSODIUM) + +auto get_environment_variable(std::string_view variable) -> std::string { + static std::mutex mtx{}; + mutex_lock lock{mtx}; + + const auto *val = std::getenv(std::string{variable}.c_str()); + return std::string{val == nullptr ? "" : val}; +} + +auto get_environment_variable(std::wstring_view variable) -> std::wstring { + return utils::string::from_utf8( + get_environment_variable(utils::string::to_utf8(variable))); +} + +#if defined(PROJECT_ENABLE_BOOST) +auto get_next_available_port(std::uint16_t first_port, + std::uint16_t &available_port) -> bool { + using namespace boost::asio; + using ip::tcp; + + boost::system::error_code error_code{}; + while (first_port != 0U) { + io_service svc{}; + tcp::acceptor acceptor(svc); + acceptor.open(tcp::v4(), error_code) || + acceptor.bind({tcp::v4(), first_port}, error_code); + if (not error_code) { + break; + } + + ++first_port; + } + + if (not error_code) { + available_port = first_port; + } + + return not error_code; +} +#endif // defined(PROJECT_ENABLE_BOOST) + +auto resolve_variables(std::string str) -> std::string { +#if defined(HAS_WORDEXP_H) + wordexp_t wt{}; + int ret{}; + if ((ret = wordexp(std::string{str}.c_str(), &wt, 0)) != 0) { + throw std::runtime_error("'wordexp()' failed|" + std::to_string(ret)); + } + str = wt.we_wordv[0U]; + wordfree(&wt); +#else // !defined(HAS_WORDEXP_H) + std::string dest; + dest.resize(::ExpandEnvironmentStringsA(str.c_str(), nullptr, 0)); + ::ExpandEnvironmentStringsA(str.c_str(), dest.data(), + static_cast(dest.size())); + str = std::string(dest.c_str(), strlen(dest.c_str())); + + dest.resize(::GetFullPathNameA(str.c_str(), 0, nullptr, nullptr)); + ::GetFullPathNameA(str.c_str(), static_cast(dest.size()), dest.data(), + nullptr); + str = std::string(dest.c_str(), strlen(dest.c_str())); +#endif // defined(HAS_WORDEXP_H) + + return str; +} + +auto resolve_variables(std::wstring_view str) -> std::wstring { + return utils::string::from_utf8( + resolve_variables(utils::string::to_utf8(str))); +} +} // namespace repertory::utils diff --git a/support/3rd_party/src/utils/encryption.cpp b/support/3rd_party/src/utils/encryption.cpp new file mode 100644 index 00000000..0a0d547c --- /dev/null +++ b/support/3rd_party/src/utils/encryption.cpp @@ -0,0 +1,103 @@ +/* + Copyright <2018-2024> + + 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. +*/ +#include "utils/encryption.hpp" + +#if defined(PROJECT_ENABLE_LIBSODIUM) + +namespace { +using nonce_t = + std::array; + +static constexpr const auto nonce_size{sizeof(nonce_t)}; + +[[nodiscard]] static auto create_hash_256(std::string_view data) + -> repertory::utils::encryption::hash_256_t { + repertory::utils::encryption::hash_256_t hash{}; + + crypto_generichash_blake2b_state state{}; + crypto_generichash_blake2b_init(&state, nullptr, 0U, hash.size()); + crypto_generichash_blake2b_update( + &state, reinterpret_cast(data.data()), + data.size()); + crypto_generichash_blake2b_final(&state, hash.data(), hash.size()); + + return hash; +} +} // namespace + +namespace repertory::utils::encryption { +auto decrypt_data(std::string_view data, std::string_view password, + std::optional hasher) -> data_buffer { + auto key = + hasher.has_value() ? (*hasher)(password) : create_hash_256(password); + + data_buffer buf{}; + if (not decrypt_data(key, + reinterpret_cast(data.data()), + data.size(), buf)) { + throw std::runtime_error("decryption failed"); + } + + return buf; +} + +auto encrypt_data(std::string_view data, std::string_view password, + std::optional hasher) -> data_buffer { + auto key = + hasher.has_value() ? (*hasher)(password) : create_hash_256(password); + + data_buffer buf{}; + if (not encrypt_data(key, + reinterpret_cast(data.data()), + data.size(), buf)) { + throw std::runtime_error("encryption failed"); + } + + return buf; +} + +auto generate_key(std::string_view encryption_token) -> key_type { + crypto_hash_sha256_state state{}; + auto res = crypto_hash_sha256_init(&state); + if (res != 0) { + throw std::runtime_error("failed to initialize sha256|" + + std::to_string(res)); + } + res = crypto_hash_sha256_update( + &state, reinterpret_cast(encryption_token.data()), + encryption_token.size()); + if (res != 0) { + throw std::runtime_error("failed to update sha256|" + std::to_string(res)); + } + + key_type ret{}; + res = crypto_hash_sha256_final(&state, ret.data()); + if (res != 0) { + throw std::runtime_error("failed to finalize sha256|" + + std::to_string(res)); + } + + return ret; +} +} // namespace repertory::utils::encryption + +#endif // defined(PROJECT_ENABLE_LIBSODIUM) diff --git a/support/3rd_party/src/utils/error.cpp b/support/3rd_party/src/utils/error.cpp new file mode 100644 index 00000000..6b42fa79 --- /dev/null +++ b/support/3rd_party/src/utils/error.cpp @@ -0,0 +1,71 @@ +/* + Copyright <2018-2024> + + 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. +*/ +#include "utils/error.hpp" + +namespace { +struct default_exception_handler final + : repertory::utils::error::i_exception_handler { + void handle_exception(std::string_view function_name) const override { + std::cerr << function_name << "|exception|unknown" << std::endl; + } + + void handle_exception(std::string_view function_name, + const std::exception &ex) const override { + std::cerr << function_name << "|exception|" + << (ex.what() == nullptr ? "unknown" : ex.what()) << std::endl; + } +}; + +static default_exception_handler default_handler{}; + +static std::atomic + exception_handler{ + &default_handler, + }; +} // namespace + +namespace repertory::utils::error { +void handle_exception(std::string_view function_name) { + i_exception_handler *handler{exception_handler}; + if (handler != nullptr) { + handler->handle_exception(function_name); + return; + } + + default_handler.handle_exception(function_name); +} + +void handle_exception(std::string_view function_name, + const std::exception &ex) { + i_exception_handler *handler{exception_handler}; + if (handler != nullptr) { + handler->handle_exception(function_name, ex); + return; + } + + default_handler.handle_exception(function_name, ex); +} + +void set_exception_handler(i_exception_handler *handler) { + exception_handler = handler; +} +} // namespace repertory::utils::error diff --git a/support/3rd_party/src/utils/file.cpp b/support/3rd_party/src/utils/file.cpp new file mode 100644 index 00000000..5207fe6d --- /dev/null +++ b/support/3rd_party/src/utils/file.cpp @@ -0,0 +1,366 @@ +/* + Copyright <2018-2024> + + 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. +*/ +#include "utils/file.hpp" + +#include "utils/encryption.hpp" +#include "utils/error.hpp" +#include "utils/path.hpp" +#include "utils/string.hpp" + +namespace repertory::utils::file { +auto file::open_file(std::filesystem::path path) -> file { + path = utils::path::absolute(path.string()); + if (not is_file(path.string())) { + throw std::runtime_error("file not found: " + path.string()); + } + + auto stream = std::fstream{ + path, + std::ios_base::binary | std::ios_base::in | std::ios_base::out, + }; + return { + std::move(stream), + path, + }; +} + +auto file::open_or_create_file(std::filesystem::path path) -> file { + path = utils::path::absolute(path.string()); + auto stream = std::fstream{ + path.string().c_str(), + std::ios_base::binary | std::ios_base::trunc | std::ios_base::in | + std::ios_base::out, + }; + + return { + std::move(stream), + path, + }; +} + +void file::close() { + if (stream_.is_open()) { + stream_.close(); + } +} + +auto file::move_to(std::filesystem::path new_path) -> bool { + new_path = utils::path::absolute(new_path.string()); + + auto reopen{false}; + if (stream_.is_open()) { + reopen = true; + close(); + } + + std::filesystem::rename(path_, new_path, error_); + if (not error_) { + path_ = new_path; + if (reopen) { + *this = std::move(open_file(path_)); + } + return true; + } + + if (reopen) { + *this = std::move(open_file(path_)); + } + return false; +} + +auto file::read(unsigned char *data, std::size_t to_read, std::uint64_t offset, + std::size_t *total_read) -> bool { + static constexpr const std::string_view function_name{ + static_cast(__FUNCTION__), + }; + + if (total_read != nullptr) { + (*total_read) = 0U; + } + + try { + stream_.seekg(static_cast(offset)); + + auto before = stream_.tellg(); + if (before == -1) { + throw std::runtime_error("failed to tellg() before read"); + } + + stream_.read(reinterpret_cast(data), + static_cast(to_read)); + if (total_read != nullptr) { + auto after = stream_.tellg(); + if (after == -1) { + throw std::runtime_error("failed to tellg() after read"); + } + (*total_read) = static_cast(after - before); + } + + return true; + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); + } + + return false; +} + +auto file::remove() -> bool { + close(); + return std::filesystem::remove(path_, error_); +} + +auto file::truncate(std::size_t size) -> bool { + auto reopen{false}; + if (stream_.is_open()) { + reopen = true; + close(); + } + + std::filesystem::resize_file(path_, size, error_); + if (reopen) { + *this = std::move(open_file(path_)); + } + + return not error_; +} + +auto file::write(const typename data_buffer::value_type *data, + std::size_t to_write, std::size_t offset, + std::size_t *total_written) -> bool { + static constexpr const std::string_view function_name{ + static_cast(__FUNCTION__), + }; + + if (total_written != nullptr) { + (*total_written) = 0U; + } + + try { + stream_.seekp(static_cast(offset)); + auto before = stream_.tellp(); + if (before == -1) { + throw std::runtime_error("failed to tellp() before write"); + } + + stream_.write(reinterpret_cast(data), + static_cast(to_write)); + + auto after = stream_.tellp(); + if (after == -1) { + throw std::runtime_error("failed to tellp() after write"); + } + + if (total_written != nullptr) { + (*total_written) = static_cast(after - before); + } + + return true; + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); + } + + return false; +} + +auto get_file_size(std::string_view path, std::uint64_t &file_size) -> bool { + auto abs_path = utils::path::absolute(path); + + file_size = 0U; + +#if defined(_WIN32) + struct _stat64 st {}; + if (_stat64(abs_path.c_str(), &st) != 0) { +#else // !defined(_WIN32) + struct stat st {}; + if (stat(abs_path.c_str(), &st) != 0) { +#endif // defined(_WIN32) + return false; + } + + if (st.st_size >= 0) { + file_size = static_cast(st.st_size); + } + + return (st.st_size >= 0); +} + +auto get_file_size(std::wstring_view path, std::uint64_t &file_size) -> bool { + return get_file_size(utils::string::to_utf8(path), file_size); +} + +auto is_directory(std::string_view path) -> bool { + auto abs_path = utils::path::absolute(path); + +#if defined(_WIN32) + return ::PathIsDirectory(abs_path.c_str()) != 0; +#else // !defined(_WIN32) + struct stat st {}; + return (stat(abs_path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)); +#endif // defined(_WIN32) +} + +auto is_directory(std::wstring_view path) -> bool { + return is_directory(utils::string::to_utf8(path)); +} + +auto is_file(std::string_view path) -> bool { + auto abs_path = utils::path::absolute(path); + +#if defined(_WIN32) + return (::PathFileExists(abs_path.c_str()) && + not ::PathIsDirectory(abs_path.c_str())); +#else // !defined(_WIN32) + struct stat st {}; + return (stat(abs_path.c_str(), &st) == 0 && not S_ISDIR(st.st_mode)); +#endif // defined(_WIN32) +} + +auto is_file(std::wstring_view path) -> bool { + return is_file(utils::string::to_utf8(path)); +} + +#if defined(PROJECT_ENABLE_JSON) +#if defined(PROJECT_ENABLE_LIBSODIUM) +auto read_json_file(std::string_view path, nlohmann::json &data, + std::optional password) -> bool { +#else // !defined(PROJECT_ENABLE_LIBSODIUM) +auto read_json_file(std::string_view path, nlohmann::json &data) -> bool { +#endif // defined(PROJECT_ENABLE_LIBSODIUM) + static constexpr const std::string_view function_name{ + static_cast(__FUNCTION__), + }; + + try { + auto abs_path = utils::path::absolute(path); + std::ifstream file_stream{ + abs_path.c_str(), + std::ios_base::binary | std::ios::in, + }; + if (not file_stream.is_open()) { + throw std::runtime_error("failed to open file: " + abs_path); + } + + auto ret{true}; + try { + std::stringstream stream; + stream << file_stream.rdbuf(); + + auto json_text = stream.str(); +#if defined(PROJECT_ENABLE_LIBSODIUM) + if (password.has_value()) { + auto data = utils::encryption::decrypt_data(json_text, *password); + json_text = {data.begin(), data.end()}; + } +#endif // defined(PROJECT_ENABLE_LIBSODIUM) + if (not json_text.empty()) { + data = nlohmann::json::parse(json_text.c_str()); + } + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + ret = false; + } catch (...) { + utils::error::handle_exception(function_name); + ret = false; + } + + file_stream.close(); + return ret; + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); + } + + return false; +} + +#if defined(PROJECT_ENABLE_LIBSODIUM) +auto write_json_file(std::string_view path, const nlohmann::json &data, + std::optional password) -> bool { +#else // !defined(PROJECT_ENABLE_LIBSODIUM) +auto write_json_file(std::string_view path, + const nlohmann::json &data) -> bool { +#endif // defined(PROJECT_ENABLE_LIBSODIUM) + static constexpr const std::string_view function_name{ + static_cast(__FUNCTION__), + }; + + try { + auto file = file::open_or_create_file(path); + if (not file.truncate()) { + throw std::runtime_error("failed to truncate file: " + + file.get_error_code().message()); + } + +#if defined(PROJECT_ENABLE_LIBSODIUM) + if (password.has_value()) { + return file.write(utils::encryption::encrypt_data(data.dump(), *password), + 0U); + } +#endif // defined(PROJECT_ENABLE_LIBSODIUM) + + return file.write(data, 0U); + } catch (const std::exception &e) { + utils::error::handle_exception(function_name, e); + } catch (...) { + utils::error::handle_exception(function_name); + } + + return false; +} + +#if defined(PROJECT_ENABLE_LIBSODIUM) +auto read_json_file(std::wstring_view path, nlohmann::json &data, + std::optional password) -> bool { + if (password.has_value()) { + auto password_a = utils::string::to_utf8(*password); + return read_json_file(utils::string::to_utf8(path), data, password_a); + } + + return read_json_file(utils::string::to_utf8(path), data, std::nullopt); +} + +auto write_json_file(std::wstring_view path, const nlohmann::json &data, + std::optional password) -> bool { + if (password.has_value()) { + auto password_a = utils::string::to_utf8(*password); + return write_json_file(utils::string::to_utf8(path), data, password_a); + } + + return write_json_file(utils::string::to_utf8(path), data, std::nullopt); +} +#else // !defined(PROJECT_ENABLE_LIBSODIUM) +auto read_json_file(std::wstring_view path, nlohmann::json &data) -> bool { + return read_json_file(utils::string::to_utf8(path), data); +} + +auto write_json_file(std::wstring_view path, + const nlohmann::json &data) -> bool { + return write_json_file(utils::string::to_utf8(path), data); +} +#endif // defined(PROJECT_ENABLE_LIBSODIUM) +#endif // defined(PROJECT_ENABLE_JSON) +} // namespace repertory::utils::file diff --git a/support/3rd_party/src/utils/path.cpp b/support/3rd_party/src/utils/path.cpp new file mode 100644 index 00000000..f394611f --- /dev/null +++ b/support/3rd_party/src/utils/path.cpp @@ -0,0 +1,225 @@ +/* + Copyright <2018-2024> + + 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. +*/ +#include "utils/path.hpp" + +#include "utils/common.hpp" +#include "utils/string.hpp" +#include "utils/unix.hpp" + +namespace { +static const std::string directory_seperator_str{ + repertory::utils::path::directory_seperator, +}; + +static const std::wstring directory_seperator_str_w{ + repertory::utils::path::directory_seperator_w, +}; +} // namespace + +namespace repertory::utils::path { +auto find_program_in_path(const std::string &name_without_extension) + -> std::string { + static std::mutex mtx{}; + static std::unordered_map found_items{}; + + mutex_lock lock(mtx); + if (found_items.contains(name_without_extension)) { + return found_items.at(name_without_extension); + } + + auto path = utils::get_environment_variable("PATH"); + if (path.empty()) { + return path; + } + +#if defined(_WIN32) + static constexpr const std::array extension_list{ + ".bat", + ".cmd", + ".exe", + ".ps1", + }; + static constexpr const auto split_char = ';'; +#else // !defined(_WIN32) + static constexpr const std::array extension_list{ + "", + ".sh", + }; + static constexpr const auto split_char = ':'; +#endif // defined(_WIN32) + + const auto search_path_list = utils::string::split(path, split_char, false); + for (auto &&search_path : search_path_list) { + for (auto &&extension : extension_list) { + auto exec_path = combine( + search_path, {name_without_extension + std::string{extension}}); + if (std::filesystem::exists(exec_path)) { + found_items[name_without_extension] = exec_path; + return exec_path; + } + } + } + + return ""; +} + +[[nodiscard]] auto +find_program_in_path(std::wstring_view name_without_extension) -> std::wstring { + return utils::string::from_utf8( + find_program_in_path(utils::string::to_utf8(name_without_extension))); +} + +auto get_parent_directory(std::string_view path) -> std::string { + auto ret = std::filesystem::path{path}.parent_path().string(); +#if !defined(_WIN32) + if (ret == ".") { + ret = "/"; + } +#endif // !defined(_WIN32) + + return absolute(ret); +} + +auto get_parent_directory(std::wstring_view path) -> std::wstring { + return utils::string::from_utf8( + get_parent_directory(utils::string::to_utf8(path))); +} + +auto is_trash_directory(std::string_view path) -> bool { + auto trash_path = utils::string::to_lower(absolute(path)); + return utils::string::begins_with(trash_path, + directory_seperator_str + ".trash-") || + utils::string::begins_with(trash_path, + directory_seperator_str + ".trashes") || + utils::string::begins_with(trash_path, + directory_seperator_str + "$recycle.bin"); +} + +auto is_trash_directory(std::wstring_view path) -> bool { + auto trash_path = utils::string::to_lower(absolute(path)); + return utils::string::begins_with(trash_path, + directory_seperator_str_w + L".trash-") || + utils::string::begins_with(trash_path, + directory_seperator_str_w + L".trashes") || + utils::string::begins_with(trash_path, directory_seperator_str_w + + L"$recycle.bin"); +} + +auto make_file_uri(std::string_view path) -> std::string { + auto abs_path = absolute(path); +#if defined(_WIN32) + utils::string::replace(abs_path, '\\', '/'); + abs_path = '/' + abs_path; +#endif // defined(_WIN32) + return "file://" + abs_path; +} + +auto make_file_uri(std::wstring_view path) -> std::wstring { + return utils::string::from_utf8(make_file_uri(utils::string::to_utf8(path))); +} + +auto remove_file_name(std::string_view path) -> std::string { + auto abs_path = absolute(path); + +#if defined(_WIN32) + ::PathRemoveFileSpec(abs_path.data()); + abs_path = abs_path.c_str(); +#else // !defined(_WIN32) + if (abs_path != "/") { + auto idx{abs_path.size() - 1U}; + while ((idx != 0U) && (abs_path.at(idx) != '/')) { + idx--; + } + + abs_path = (idx > 0U) ? absolute(abs_path.substr(0U, idx)) : "/"; + } +#endif // defined(_WIN32) + + return abs_path; +} + +#if !defined(_WIN32) +auto resolve(std::string path) -> std::string { + std::string home{}; + use_getpwuid(getuid(), [&home](struct passwd *pw) { + home = (pw->pw_dir ? pw->pw_dir : ""); + if (home.empty() || ((home == "/") && (getuid() != 0))) { + home = combine("/home", {pw->pw_name}); + } + }); + + return absolute(utils::string::replace(path, "~", home)); +} + +auto resolve(std::wstring_view path) -> std::wstring { + return utils::string::from_utf8(resolve(utils::string::to_utf8(path))); +} +#endif // !defined(_WIN32) + +auto strip_to_file_name(std::string path) -> std::string { +#if defined(_WIN32) + return ::PathFindFileName(path.c_str()); +#else + return utils::string::contains(path, "/") ? basename(path.data()) : path; +#endif +} + +auto unmake_file_uri(std::string_view uri) -> std::string { + static constexpr const std::array escape_characters = { + { + " ", "<", ">", "#", "%", "+", "{", "}", "|", "\\", "^", "~", + "[", "]", "`", ";", "/", "?", ":", "@", "=", "&", "$", + }}; + static constexpr const std::array + escape_sequences_lower = {{ + "%20", "%3c", "%3e", "%23", "%25", "%2b", "%7b", "%7d", + "%7c", "%5c", "%5e", "%7e", "%5b", "%5d", "%60", "%3b", + "%2f", "%3f", "%3a", "%40", "%3d", "%26", "%24", + }}; + static constexpr const std::array + escape_sequences_upper = {{ + "%20", "%3C", "%3E", "%23", "%25", "%2B", "%7B", "%7D", + "%7C", "%5C", "%5E", "%7E", "%5B", "%5D", "%60", "%3B", + "%2F", "%3F", "%3A", "%40", "%3D", "%26", "%24", + }}; + + std::string ret_uri{uri}; +#if defined(_WIN32) + ret_uri = ret_uri.substr(8U); +#else + ret_uri = ret_uri.substr(7U); +#endif + + for (std::size_t idx = 0U; idx < escape_characters.size(); idx++) { + utils::string::replace(ret_uri, escape_sequences_lower.at(idx), + escape_characters.at(idx)); + utils::string::replace(ret_uri, escape_sequences_upper.at(idx), + escape_characters.at(idx)); + } + + return absolute(uri); +} + +auto unmake_file_uri(std::wstring_view uri) -> std::wstring { + return utils::string::from_utf8(unmake_file_uri(utils::string::to_utf8(uri))); +} +} // namespace repertory::utils::path diff --git a/support/3rd_party/src/utils/string.cpp b/support/3rd_party/src/utils/string.cpp new file mode 100644 index 00000000..cfaa6968 --- /dev/null +++ b/support/3rd_party/src/utils/string.cpp @@ -0,0 +1,138 @@ +/* + Copyright <2018-2024> + + 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. +*/ +#include "utils/string.hpp" + +namespace repertory::utils::string { +auto from_bool(bool val) -> std::string { + return std::to_string(static_cast(val)); +} + +#if defined(PROJECT_ENABLE_BOOST) +auto from_dynamic_bitset(const boost::dynamic_bitset<> &bitset) -> std::string { + std::stringstream stream; + boost::archive::text_oarchive archive(stream); + archive << bitset; + return stream.str(); +} +#endif // defined(PROJECT_ENABLE_BOOST) + +auto from_utf8(std::string_view str) -> std::wstring { + return str.empty() + ? L"" + : std::wstring_convert, wchar_t>() + .from_bytes(std::string{str}); +} + +#if defined(PROJECT_ENABLE_SFML) +auto replace_sf(sf::String &src, const sf::String &find, const sf::String &with, + std::size_t start_pos) -> sf::String & { + if (not src.isEmpty() && (start_pos < src.getSize())) { + while ((start_pos = src.find(find, start_pos)) != std::string::npos) { + src.replace(start_pos, find.getSize(), with); + start_pos += with.getSize(); + } + } + + return src; +} + +auto split_sf(sf::String str, wchar_t delim, + bool should_trim) -> std::vector { + auto result = std::views::split(str.toWideString(), delim); + + std::vector ret{}; + for (auto &&word : result) { + auto val = std::wstring{word.begin(), word.end()}; + if (should_trim) { + trim(val); + } + ret.emplace_back(val); + } + + return ret; +} +#endif // defined(PROJECT_ENABLE_SFML) + +auto to_bool(std::string val) -> bool { + auto ret = false; + + trim(val); + if (is_numeric(val)) { + if (contains(val, ".")) { + ret = (to_double(val) != 0.0); + } else { + std::istringstream(val) >> ret; + } + } else { + std::istringstream(to_lower(val)) >> std::boolalpha >> ret; + } + + return ret; +} + +auto to_double(const std::string &str) -> double { return std::stod(str); } + +#if defined(PROJECT_ENABLE_BOOST) +auto to_dynamic_bitset(const std::string &val) -> boost::dynamic_bitset<> { + std::stringstream stream(val); + boost::dynamic_bitset<> bitset; + boost::archive::text_iarchive archive(stream); + archive >> bitset; + return bitset; +} +#endif // defined(PROJECT_ENABLE_BOOST) + +auto to_int32(const std::string &val) -> std::int32_t { return std::stoi(val); } + +auto to_int64(const std::string &val) -> std::int64_t { + return std::stoll(val); +} + +auto to_size_t(const std::string &val) -> std::size_t { + return static_cast(std::stoull(val)); +} + +auto to_uint8(const std::string &val) -> std::uint8_t { + return static_cast(std::stoul(val)); +} + +auto to_uint16(const std::string &val) -> std::uint16_t { + return static_cast(std::stoul(val)); +} + +auto to_uint32(const std::string &val) -> std::uint32_t { + return static_cast(std::stoul(val)); +} + +auto to_uint64(const std::string &val) -> std::uint64_t { + return std::stoull(val); +} + +auto to_utf8(std::string_view str) -> std::string { return std::string{str}; } + +auto to_utf8(std::wstring_view str) -> std::string { + return str.empty() + ? "" + : std::wstring_convert, wchar_t>() + .to_bytes(std::wstring{str}); +} +} // namespace repertory::utils::string diff --git a/support/3rd_party/src/utils/time.cpp b/support/3rd_party/src/utils/time.cpp new file mode 100644 index 00000000..0c30977e --- /dev/null +++ b/support/3rd_party/src/utils/time.cpp @@ -0,0 +1,107 @@ +/* + Copyright <2018-2024> + + 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. +*/ +#include "utils/time.hpp" + +namespace repertory::utils::time { +#if defined(_WIN32) +// https://www.frenk.com/2009/12/convert-filetime-to-unix-timestamp/ +auto filetime_to_unix_time(const FILETIME &file_time) -> std::uint64_t { + LARGE_INTEGER date{}; + date.HighPart = static_cast(file_time.dwHighDateTime); + date.LowPart = file_time.dwLowDateTime; + date.QuadPart -= 116444736000000000LL; + + return static_cast(date.QuadPart) * 100ULL; +} +#endif // defined(_WIN32) + +auto get_file_time_now() -> std::uint64_t { +#if defined(_WIN32) + SYSTEMTIME sys_time{}; + ::GetSystemTime(&sys_time); + + FILETIME file_time{}; + ::SystemTimeToFileTime(&sys_time, &file_time); + return static_cast( + (reinterpret_cast(&file_time))->QuadPart); +#else // !defined(_WIN32) + return get_time_now(); +#endif // defined(_WIN32) +} + +void get_local_time_now(struct tm &local_time) { + std::memset(&local_time, 0, sizeof(local_time)); + + const auto now = + std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); +#if defined(_WIN32) + localtime_s(&local_time, &now); +#else // !defined(_WIN32) + localtime_r(&now, &local_time); +#endif // defined(_WIN32) +} + +auto get_time_now() -> std::uint64_t { +#if defined(_WIN32) + return static_cast( + std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())); +#endif // defined(_WIN32) + +#if defined(__APPLE__) + return std::chrono::nanoseconds( + std::chrono::system_clock::now().time_since_epoch()) + .count(); +#else // !defined(__APPLE__) + return static_cast( + std::chrono::nanoseconds( + std::chrono::high_resolution_clock::now().time_since_epoch()) + .count()); +#endif // defined(__APPLE__) +} + +#if defined(_WIN32) +// https://stackoverflow.com/questions/321849/strptime-equivalent-on-windows +auto strptime(const char *s, const char *f, struct tm *tm) -> const char * { + std::istringstream input{s}; + input.imbue(std::locale(setlocale(LC_ALL, nullptr))); + input >> std::get_time(tm, f); + if (input.fail()) { + return nullptr; + } + + return reinterpret_cast(s + input.tellg()); +} + +auto time64_to_unix_time(const __time64_t &time) -> std::uint64_t { + return static_cast(time * NANOS_PER_SECOND); +} + +// https://www.frenk.com/2009/12/convert-filetime-to-unix-timestamp/ +auto unix_time_to_filetime(std::uint64_t unix_time) -> FILETIME { + const auto win_time = (unix_time / 100ULL) + 116444736000000000ULL; + FILETIME file_time{}; + file_time.dwHighDateTime = static_cast(win_time >> 32U); + file_time.dwLowDateTime = win_time & 0xFFFFFFFF; + return file_time; +} +#endif // defined(_WIN32) +} // namespace repertory::utils::time diff --git a/support/3rd_party/src/utils/unix.cpp b/support/3rd_party/src/utils/unix.cpp new file mode 100644 index 00000000..cc98f146 --- /dev/null +++ b/support/3rd_party/src/utils/unix.cpp @@ -0,0 +1,76 @@ +/* + Copyright <2018-2024> + + 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. +*/ +#if !defined(_WIN32) + +#include "utils/unix.hpp" +#include "utils/collection.hpp" + +namespace repertory::utils { +#if !defined(__APPLE__) +auto convert_to_uint64(const pthread_t &thread) -> std::uint64_t { + return static_cast(thread); +} +#endif // !defined(__APPLE__) + +auto get_last_error_code() -> int { return errno; } + +auto get_thread_id() -> std::uint64_t { + return convert_to_uint64(pthread_self()); +} + +auto is_uid_member_of_group(const uid_t &uid, const gid_t &gid) -> bool { + std::vector groups{}; + use_getpwuid(uid, [&groups](struct passwd *pass) { + int group_count{}; + if (getgrouplist(pass->pw_name, pass->pw_gid, nullptr, &group_count) < 0) { + groups.resize(static_cast(group_count)); +#if defined(__APPLE__) + getgrouplist(pass->pw_name, pass->pw_gid, + reinterpret_cast(groups.data()), &group_count); +#else // !defined(__APPLE__) + getgrouplist(pass->pw_name, pass->pw_gid, groups.data(), &group_count); +#endif // defined(__APPLE__) + } + }); + + return collection::includes(groups, gid); +} + +auto use_getpwuid(uid_t uid, passwd_callback_t callback) -> result { + static constexpr const std::string_view function_name{ + static_cast(__FUNCTION__), + }; + + static std::mutex mtx{}; + mutex_lock lock{mtx}; + + auto *temp_pw = getpwuid(uid); + if (temp_pw == nullptr) { + return {function_name, false, "'getpwuid' returned nullptr"}; + } + + callback(temp_pw); + return {function_name}; +} +} // namespace repertory::utils + +#endif // !defined(_WIN32) diff --git a/support/3rd_party/src/utils/windows.cpp b/support/3rd_party/src/utils/windows.cpp new file mode 100644 index 00000000..5e745499 --- /dev/null +++ b/support/3rd_party/src/utils/windows.cpp @@ -0,0 +1,105 @@ +/* + Copyright <2018-2024> + + 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. +*/ +#if defined(_WIN32) +#include "utils/windows.hpp" + +#include "utils/com_init_wrapper.hpp" +#include "utils/string.hpp" + +namespace repertory::utils { +auto get_last_error_code() -> DWORD { return ::GetLastError(); } + +auto get_local_app_data_directory() -> const std::string & { + static std::string app_data = ([]() -> std::string { + com_init_wrapper cw; + PWSTR local_app_data{}; + if (SUCCEEDED(::SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, + &local_app_data))) { + auto ret = utils::string::to_utf8(local_app_data); + ::CoTaskMemFree(local_app_data); + return ret; + } + + throw std::runtime_error("unable to detect local application data folder"); + })(); + + return app_data; +} + +auto get_thread_id() -> std::uint64_t { + return static_cast(::GetCurrentThreadId()); +} + +auto is_process_elevated() -> bool { + auto ret{false}; + HANDLE token{INVALID_HANDLE_VALUE}; + if (::OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { + TOKEN_ELEVATION te{}; + DWORD sz = sizeof(te); + if (::GetTokenInformation(token, TokenElevation, &te, sizeof(te), &sz)) { + ret = (te.TokenIsElevated != 0); + } + } + + if (token != INVALID_HANDLE_VALUE) { + ::CloseHandle(token); + } + + return ret; +} + +auto run_process_elevated(std::vector args) -> int { + std::cout << "Elevating Process" << std::endl; + std::string parameters{"-hidden"}; + for (std::size_t idx = 1U; idx < args.size(); idx++) { + parameters += + (parameters.empty() ? args.at(idx) : " " + std::string(args.at(idx))); + } + + std::string full_path; + full_path.resize(MAX_PATH + 1); + + if (::GetModuleFileName(nullptr, full_path.data(), MAX_PATH)) { + SHELLEXECUTEINFO sei{}; + sei.fMask = SEE_MASK_NOCLOSEPROCESS; + sei.cbSize = sizeof(sei); + sei.lpVerb = "runas"; + sei.lpFile = full_path.c_str(); + sei.lpParameters = parameters.c_str(); + sei.hwnd = nullptr; + sei.nShow = SW_NORMAL; + if (::ShellExecuteEx(&sei)) { + ::WaitForSingleObject(sei.hProcess, INFINITE); + DWORD exit_code{}; + ::GetExitCodeProcess(sei.hProcess, &exit_code); + ::CloseHandle(sei.hProcess); + return static_cast(exit_code); + } + } + + return static_cast(::GetLastError()); +} + +void set_last_error_code(DWORD error_code) { ::SetLastError(error_code); } +} // namespace repertory::utils + +#endif // defined(_WIN32)