refactor: move std patch into correct position

This commit is contained in:
2025-07-01 11:00:09 +08:00
parent 732a560a65
commit 58ec960e9c
9 changed files with 332 additions and 224 deletions

View File

@ -14,6 +14,7 @@ PRIVATE
yycc/string/reinterpret.cpp yycc/string/reinterpret.cpp
yycc/string/op.cpp yycc/string/op.cpp
yycc/rust/panic.cpp yycc/rust/panic.cpp
yycc/patch/path.cpp
# YYCC/COMHelper.cpp # YYCC/COMHelper.cpp
# YYCC/ArgParser.cpp # YYCC/ArgParser.cpp
# YYCC/ConfigManager.cpp # YYCC/ConfigManager.cpp
@ -57,6 +58,9 @@ FILES
yycc/windows/import_guard_tail.hpp yycc/windows/import_guard_tail.hpp
yycc/constraint.hpp yycc/constraint.hpp
yycc/constraint/builder.hpp yycc/constraint/builder.hpp
yycc/patch/path.hpp
yycc/patch/contains.hpp
yycc/patch/starts_ends_with.hpp
# # Headers # # Headers
# # Common headers # # Common headers

View File

@ -6,36 +6,4 @@
namespace YYCC::StdPatch { namespace YYCC::StdPatch {
std::filesystem::path ToStdPath(const yycc_u8string_view& u8_path) {
#if YYCC_OS == YYCC_OS_WINDOWS
// convert path to wchar
std::wstring wpath;
if (!YYCC::EncodingHelper::UTF8ToWchar(u8_path, wpath))
throw std::invalid_argument("Fail to convert given UTF8 string.");
// return path with wchar_t ctor
return std::filesystem::path(wpath);
#else
std::string cache = YYCC::EncodingHelper::ToOrdinary(u8_path);
return std::filesystem::path(cache.c_str());
#endif
}
yycc_u8string ToUTF8Path(const std::filesystem::path& path) {
#if YYCC_OS == YYCC_OS_WINDOWS
// get and convert to utf8
yycc_u8string u8_path;
if (!YYCC::EncodingHelper::WcharToUTF8(path.c_str(), u8_path))
throw std::invalid_argument("Fail to convert to UTF8 string.");
// return utf8 path
return u8_path;
#else
return EncodingHelper::ToUTF8(path.string());
#endif
}
} }

View File

@ -5,11 +5,6 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
/**
* @brief \c Standard library related patches for UTF8 compatibility and the limitation of C++ standard version.
* @details
* See also \ref std_patch.
*/
namespace YYCC::StdPatch { namespace YYCC::StdPatch {
/** /**
@ -28,191 +23,4 @@ namespace YYCC::StdPatch {
*/ */
yycc_u8string ToUTF8Path(const std::filesystem::path& path); yycc_u8string ToUTF8Path(const std::filesystem::path& path);
#pragma region StartsWith EndsWith
// Reference:
// https://en.cppreference.com/w/cpp/string/basic_string_view/starts_with
// https://en.cppreference.com/w/cpp/string/basic_string_view/ends_with
// https://en.cppreference.com/w/cpp/string/basic_string/starts_with
// https://en.cppreference.com/w/cpp/string/basic_string/ends_with
#pragma region String View
/**
* @brief Checks if the string view begins with the given prefix
* @param[in] that The string view to find.
* @param[in] sv A string view which may be a result of implicit conversion from \c std::basic_string.
* @return True if the string view begins with the provided prefix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool StartsWith(const std::basic_string_view<CharT, Traits>& that, std::basic_string_view<CharT, Traits> sv) noexcept {
return std::basic_string_view<CharT, Traits>(that.data(), std::min(that.size(), sv.size())) == sv;
}
/**
* @brief Checks if the string view begins with the given prefix
* @param[in] that The string view to find.
* @param[in] ch A single character.
* @return True if the string view begins with the provided prefix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool StartsWith(const std::basic_string_view<CharT, Traits>& that, CharT ch) noexcept {
return !that.empty() && Traits::eq(that.front(), ch);
}
/**
* @brief Checks if the string view begins with the given prefix
* @param[in] that The string view to find.
* @param[in] s A null-terminated character string.
* @return True if the string view begins with the provided prefix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool StartsWith(const std::basic_string_view<CharT, Traits>& that, const CharT* s) noexcept {
return StartsWith(that, std::basic_string_view(s));
}
/**
* @brief Checks if the string view ends with the given suffix
* @param[in] that The string view to find.
* @param[in] sv A string view which may be a result of implicit conversion from \c std::basic_string.
* @return True if the string view ends with the provided suffix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool EndsWith(const std::basic_string_view<CharT, Traits>& that, std::basic_string_view<CharT, Traits> sv) noexcept {
return that.size() >= sv.size() && that.compare(that.size() - sv.size(), std::basic_string_view<CharT, Traits>::npos, sv) == 0;
}
/**
* @brief Checks if the string view ends with the given suffix
* @param[in] that The string view to find.
* @param[in] ch A single character.
* @return True if the string view ends with the provided suffix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool EndsWith(const std::basic_string_view<CharT, Traits>& that, CharT ch) noexcept {
return !that.empty() && Traits::eq(that.back(), ch);
}
/**
* @brief Checks if the string view ends with the given suffix
* @param[in] that The string view to find.
* @param[in] s A null-terminated character string.
* @return True if the string view ends with the provided suffix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool EndsWith(const std::basic_string_view<CharT, Traits>& that, const CharT* s) noexcept {
return EndsWith(that, std::basic_string_view(s));
}
#pragma endregion
#pragma region String
/**
* @brief Checks if the string begins with the given prefix
* @param[in] that The string to find.
* @param[in] sv A string view which may be a result of implicit conversion from \c std::basic_string.
* @return True if the string view begins with the provided prefix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool StartsWith(const std::basic_string<CharT, Traits>& that, std::basic_string_view<CharT, Traits> sv) noexcept {
return StartsWith(std::basic_string_view<CharT, Traits>(that.data(), that.size()), sv);
}
/**
* @brief Checks if the string begins with the given prefix
* @param[in] that The string to find.
* @param[in] ch A single character.
* @return True if the string view begins with the provided prefix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool StartsWith(const std::basic_string<CharT, Traits>& that, CharT ch) noexcept {
return StartsWith(std::basic_string_view<CharT, Traits>(that.data(), that.size()), ch);
}
/**
* @brief Checks if the string begins with the given prefix
* @param[in] that The string to find.
* @param[in] s A null-terminated character string.
* @return True if the string view begins with the provided prefix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool StartsWith(const std::basic_string<CharT, Traits>& that, const CharT* s) noexcept {
return StartsWith(std::basic_string_view<CharT, Traits>(that.data(), that.size()), s);
}
/**
* @brief Checks if the string ends with the given suffix
* @param[in] that The string to find.
* @param[in] sv A string view which may be a result of implicit conversion from \c std::basic_string.
* @return True if the string view ends with the provided suffix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool EndsWith(const std::basic_string<CharT, Traits>& that, std::basic_string_view<CharT, Traits> sv) noexcept {
return EndsWith(std::basic_string_view<CharT, Traits>(that.data(), that.size()), sv);
}
/**
* @brief Checks if the string ends with the given suffix
* @param[in] that The string to find.
* @param[in] ch A single character.
* @return True if the string view ends with the provided suffix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool EndsWith(const std::basic_string<CharT, Traits>& that, CharT ch) noexcept {
return EndsWith(std::basic_string_view<CharT, Traits>(that.data(), that.size()), ch);
}
/**
* @brief Checks if the string ends with the given suffix
* @param[in] that The string to find.
* @param[in] s A null-terminated character string.
* @return True if the string view ends with the provided suffix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool EndsWith(const std::basic_string<CharT, Traits>& that, const CharT* s) noexcept {
return EndsWith(std::basic_string_view<CharT, Traits>(that.data(), that.size()), s);
}
#pragma endregion
#pragma endregion
#pragma region Contain
/**
* @brief Checks if there is an element with key equivalent to key in the container.
* @details
* The polyfill to \c Contains function of unordered and ordered associative container.
* Because this function only present after C++ 20.
* This function will use our custom polyfill if the version of C++ standard you are using lower than C++ 20.
* Otherwise it will fallback to vanilla standard library function.
* @tparam _TContainer
* The type of container. This container must have \c find() and \c end() member functions.
* @tparam _TKey
* The type of key of container.
* If the container is a set, this type is the type of item in set.
* If the container is a map, this type is the key type of map.
* @param[in] container The reference to container to find.
* @param[in] key Key value of the element to search for
* @return True if there is such an element, otherwise false.
* @remarks
* This template function do not have constraint check.
* If container type has \c find() and \c end() member functions, this template function will be created without any error.
* However, this function should be used for standard library associative container according to its original purpose.
* It means that the type of container usually and should be one of following types:
* \li \c std::set
* \li \c std::multiset
* \li \c std::map
* \li \c std::multimap
* \li \c std::unordered_set
* \li \c std::unordered_multiset
* \li \c std::unordered_map
* \li \c std::unordered_multimap
*/
template<class _TContainer, class _TKey>
bool Contains(const _TContainer& container, const _TKey& key) {
// __cplusplus macro need special compiler switch enabled when compiling.
// So we use _MSVC_LANG check it instead.
#if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
return container.contains(key);
#else
return container.find(key) != container.end();
#endif
}
#pragma endregion
} }

View File

@ -0,0 +1,45 @@
#pragma once
#include "../macro/feature_probe.hpp"
namespace yycc::patch::contains {
/**
* @brief Checks if there is an element with key equivalent to key in the container.
* @details
* The polyfill to \c contains() function of unordered and ordered associative container.
* Because this function only present after C++ 20.
* This function will use our custom polyfill if the version of C++ standard you are using lower than C++ 20.
* Otherwise it will fallback to vanilla standard library function.
* @tparam TContainer
* The type of container. This container must have \c find() and \c end() member functions.
* @tparam TKey
* The type of key of container.
* If the container is a set, this type is the type of item in set.
* If the container is a map, this type is the key type of map.
* @param[in] container The reference to container to find.
* @param[in] key Key value of the element to search for
* @return True if there is such an element, otherwise false.
* @remarks
* This template function do not have constraint check.
* If container type has \c find() and \c end() member functions, this template function will be created without any error.
* However, this function should be used for standard library associative container according to its original purpose.
* It means that the type of container usually and should be one of following types:
* \li \c std::set
* \li \c std::multiset
* \li \c std::map
* \li \c std::multimap
* \li \c std::unordered_set
* \li \c std::unordered_multiset
* \li \c std::unordered_map
* \li \c std::unordered_multimap
*/
template<class TContainer, class TKey>
bool contains(const TContainer& container, const TKey& key) {
#if defined(YYCC_CPPFEAT_CONTAINS)
return container.contains(key);
#else
return container.find(key) != container.end();
#endif
}
} // namespace yycc::patch::container

48
src/yycc/patch/path.cpp Normal file
View File

@ -0,0 +1,48 @@
#include "path.hpp"
#include "../macro/os_detector.hpp"
#include <stdexcept>
#define NS_YYCC_STRING ::yycc::string
namespace yycc::patch::path {
// TODO: Fix this after finish encoding parts.
// TODO: Add native implementation if C++ support it.
// So we need add feature test macro at the same time.
std::filesystem::path to_std_path(const NS_YYCC_STRING::u8string_view& u8_path) {
// #if YYCC_OS == YYCC_OS_WINDOWS
// // convert path to wchar
// std::wstring wpath;
// if (!YYCC::EncodingHelper::UTF8ToWchar(u8_path, wpath))
// throw std::invalid_argument("Fail to convert given UTF8 string.");
// // return path with wchar_t ctor
// return std::filesystem::path(wpath);
// #else
// std::string cache = YYCC::EncodingHelper::ToOrdinary(u8_path);
// return std::filesystem::path(cache.c_str());
// #endif
return std::filesystem::path();
}
NS_YYCC_STRING::u8string to_u8string(const std::filesystem::path& path) {
// #if YYCC_OS == YYCC_OS_WINDOWS
// // get and convert to utf8
// NS_YYCC_STRING::u8string u8_path;
// if (!YYCC::EncodingHelper::WcharToUTF8(path.c_str(), u8_path))
// throw std::invalid_argument("Fail to convert to UTF8 string.");
// // return utf8 path
// return u8_path;
// #else
// return EncodingHelper::ToUTF8(path.string());
// #endif
return NS_YYCC_STRING::u8string();
}
}

View File

@ -0,0 +1,32 @@
#pragma once
#include "../string.hpp"
#include <filesystem>
#define NS_YYCC_STRING ::yycc::string
/**
* @brief \c Standard library related patches for UTF8 compatibility and the limitation of C++ standard version.
* @details
* See also \ref std_patch.
*/
namespace yycc::patch::path {
/**
* @brief Constructs \c std::filesystem::path from UTF8 path.
* @param[in] u8_path UTF8 path string for building.
* @return \c std::filesystem::path instance.
* @exception std::invalid_argument Fail to parse given UTF8 string (maybe invalid?).
*/
std::filesystem::path to_std_path(const NS_YYCC_STRING::u8string_view& u8_path);
/**
* @brief Returns the UTF8 representation of given \c std::filesystem::path.
* @param[in] path The \c std::filesystem::path instance converting to UTF8 path.
* @return The UTF8 representation of given \c std::filesystem::path.
* @exception std::invalid_argument Fail to convert to UTF8 string.
*/
NS_YYCC_STRING::u8string to_u8string(const std::filesystem::path& path);
} // namespace yycc::patch::path
#undef NS_YYCC_STRING

View File

@ -0,0 +1,203 @@
#pragma once
#include "../macro/feature_probe.hpp"
#include <string>
#include <string_view>
namespace yycc::patch::starts_ends_with {
// Reference:
// https://en.cppreference.com/w/cpp/string/basic_string_view/starts_with
// https://en.cppreference.com/w/cpp/string/basic_string_view/ends_with
// https://en.cppreference.com/w/cpp/string/basic_string/starts_with
// https://en.cppreference.com/w/cpp/string/basic_string/ends_with
#pragma region For String View
/**
* @brief Checks if the string view begins with the given prefix
* @param[in] that The string view to find.
* @param[in] sv A string view which may be a result of implicit conversion from \c std::basic_string.
* @return True if the string view begins with the provided prefix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool starts_with(const std::basic_string_view<CharT, Traits>& that,
std::basic_string_view<CharT, Traits> sv) noexcept {
#if defined(YYCC_CPPFEAT_STARTS_ENDS_WITH)
return that.starts_with(sv);
#else
return std::basic_string_view<CharT, Traits>(that.data(), std::min(that.size(), sv.size()))
== sv;
#endif
}
/**
* @brief Checks if the string view begins with the given prefix
* @param[in] that The string view to find.
* @param[in] ch A single character.
* @return True if the string view begins with the provided prefix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool starts_with(const std::basic_string_view<CharT, Traits>& that, CharT ch) noexcept {
#if defined(YYCC_CPPFEAT_STARTS_ENDS_WITH)
return that.starts_with(ch);
#else
return !that.empty() && Traits::eq(that.front(), ch);
#endif
}
/**
* @brief Checks if the string view begins with the given prefix
* @param[in] that The string view to find.
* @param[in] s A null-terminated character string.
* @return True if the string view begins with the provided prefix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool starts_with(const std::basic_string_view<CharT, Traits>& that, const CharT* s) noexcept {
#if defined(YYCC_CPPFEAT_STARTS_ENDS_WITH)
return that.starts_with(s);
#else
return starts_with(that, std::basic_string_view(s));
#endif
}
/**
* @brief Checks if the string view ends with the given suffix
* @param[in] that The string view to find.
* @param[in] sv A string view which may be a result of implicit conversion from \c std::basic_string.
* @return True if the string view ends with the provided suffix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool ends_with(const std::basic_string_view<CharT, Traits>& that,
std::basic_string_view<CharT, Traits> sv) noexcept {
#if defined(YYCC_CPPFEAT_STARTS_ENDS_WITH)
return that.ends_with(sv);
#else
return that.size() >= sv.size()
&& that.compare(that.size() - sv.size(),
std::basic_string_view<CharT, Traits>::npos,
sv)
== 0;
#endif
}
/**
* @brief Checks if the string view ends with the given suffix
* @param[in] that The string view to find.
* @param[in] ch A single character.
* @return True if the string view ends with the provided suffix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool ends_with(const std::basic_string_view<CharT, Traits>& that, CharT ch) noexcept {
#if defined(YYCC_CPPFEAT_STARTS_ENDS_WITH)
return that.ends_with(ch);
#else
return !that.empty() && Traits::eq(that.back(), ch);
#endif
}
/**
* @brief Checks if the string view ends with the given suffix
* @param[in] that The string view to find.
* @param[in] s A null-terminated character string.
* @return True if the string view ends with the provided suffix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool ends_with(const std::basic_string_view<CharT, Traits>& that, const CharT* s) noexcept {
#if defined(YYCC_CPPFEAT_STARTS_ENDS_WITH)
return that.ends_with(s);
#else
return ends_with(that, std::basic_string_view(s));
#endif
}
#pragma endregion
#pragma region For String
/**
* @brief Checks if the string begins with the given prefix
* @param[in] that The string to find.
* @param[in] sv A string view which may be a result of implicit conversion from \c std::basic_string.
* @return True if the string view begins with the provided prefix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool starts_with(const std::basic_string<CharT, Traits>& that,
std::basic_string_view<CharT, Traits> sv) noexcept {
#if defined(YYCC_CPPFEAT_STARTS_ENDS_WITH)
return that.starts_with(sv);
#else
return starts_with(std::basic_string_view<CharT, Traits>(that.data(), that.size()), sv);
#endif
}
/**
* @brief Checks if the string begins with the given prefix
* @param[in] that The string to find.
* @param[in] ch A single character.
* @return True if the string view begins with the provided prefix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool starts_with(const std::basic_string<CharT, Traits>& that, CharT ch) noexcept {
#if defined(YYCC_CPPFEAT_STARTS_ENDS_WITH)
return that.starts_with(ch);
#else
return starts_with(std::basic_string_view<CharT, Traits>(that.data(), that.size()), ch);
#endif
}
/**
* @brief Checks if the string begins with the given prefix
* @param[in] that The string to find.
* @param[in] s A null-terminated character string.
* @return True if the string view begins with the provided prefix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool starts_with(const std::basic_string<CharT, Traits>& that, const CharT* s) noexcept {
#if defined(YYCC_CPPFEAT_STARTS_ENDS_WITH)
return that.starts_with(s);
#else
return starts_with(std::basic_string_view<CharT, Traits>(that.data(), that.size()), s);
#endif
}
/**
* @brief Checks if the string ends with the given suffix
* @param[in] that The string to find.
* @param[in] sv A string view which may be a result of implicit conversion from \c std::basic_string.
* @return True if the string view ends with the provided suffix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool ends_with(const std::basic_string<CharT, Traits>& that,
std::basic_string_view<CharT, Traits> sv) noexcept {
#if defined(YYCC_CPPFEAT_STARTS_ENDS_WITH)
return that.ends_with(sv);
#else
return ends_with(std::basic_string_view<CharT, Traits>(that.data(), that.size()), sv);
#endif
}
/**
* @brief Checks if the string ends with the given suffix
* @param[in] that The string to find.
* @param[in] ch A single character.
* @return True if the string view ends with the provided suffix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool ends_with(const std::basic_string<CharT, Traits>& that, CharT ch) noexcept {
#if defined(YYCC_CPPFEAT_STARTS_ENDS_WITH)
return that.ends_with(ch);
#else
return ends_with(std::basic_string_view<CharT, Traits>(that.data(), that.size()), ch);
#endif
}
/**
* @brief Checks if the string ends with the given suffix
* @param[in] that The string to find.
* @param[in] s A null-terminated character string.
* @return True if the string view ends with the provided suffix, false otherwise.
*/
template<class CharT, class Traits = std::char_traits<CharT>>
bool ends_with(const std::basic_string<CharT, Traits>& that, const CharT* s) noexcept {
#if defined(YYCC_CPPFEAT_STARTS_ENDS_WITH)
return that.ends_with(s);
#else
return ends_with(std::basic_string_view<CharT, Traits>(that.data(), that.size()), s);
#endif
}
#pragma endregion
} // namespace yycc::patch::starts_ends_with