diff options
author | 杨宇千 <crupest@outlook.com> | 2019-03-28 20:39:36 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-28 20:39:36 +0800 |
commit | c45a6e62298e972f5945f5f3461ed723aea80317 (patch) | |
tree | f46ef303ee87a8e3814ea8743bd7062d432bfee3 /src/util | |
parent | b028e74a48de181ca078ad3bf4ababf4fa146cd3 (diff) | |
parent | 37216f211b0e22205a3a0d3373d985fc68aea59b (diff) | |
download | cru-c45a6e62298e972f5945f5f3461ed723aea80317.tar.gz cru-c45a6e62298e972f5945f5f3461ed723aea80317.tar.bz2 cru-c45a6e62298e972f5945f5f3461ed723aea80317.zip |
Merge pull request #37 from crupest/render
Refactor.
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/com_util.hpp | 22 | ||||
-rw-r--r-- | src/util/format.hpp | 100 | ||||
-rw-r--r-- | src/util/math_util.hpp | 51 | ||||
-rw-r--r-- | src/util/string_util.cpp | 22 | ||||
-rw-r--r-- | src/util/string_util.hpp | 8 |
5 files changed, 203 insertions, 0 deletions
diff --git a/src/util/com_util.hpp b/src/util/com_util.hpp new file mode 100644 index 00000000..bbaf1c27 --- /dev/null +++ b/src/util/com_util.hpp @@ -0,0 +1,22 @@ +#pragma once +#include "pre.hpp" + +#include <memory> + +namespace cru::util { + +template <typename TInterface> +std::shared_ptr<TInterface> CreateComSharedPtr(TInterface* p) { + return std::shared_ptr<TInterface>(p, [](TInterface* ptr) { + if (ptr != nullptr) ptr->Release(); + }); +} + +template <class TInterface> +void SafeRelease(TInterface*& p) { + if (p != nullptr) { + p->Release(); + p = nullptr; + } +} +} // namespace cru::util diff --git a/src/util/format.hpp b/src/util/format.hpp new file mode 100644 index 00000000..7c1cee05 --- /dev/null +++ b/src/util/format.hpp @@ -0,0 +1,100 @@ +#pragma once +#include "pre.hpp" + +#include "base.hpp" + +namespace cru::util { +namespace details { +template <typename T> +struct TypeTag {}; + +constexpr StringView PlaceHolder(TypeTag<String>) { return StringView(L"{}"); } + +constexpr MultiByteStringView PlaceHolder(TypeTag<MultiByteString>) { + return MultiByteStringView("{}"); +} + +template <typename TString> +void FormatInternal(TString& string) { + const auto find_result = string.find(PlaceHolder(TypeTag<TString>{})); + if (find_result != TString::npos) + throw std::invalid_argument("There is more placeholders than args."); +} + +template <typename TString, typename T, typename... TRest> +void FormatInternal(TString& string, const T& arg, const TRest&... args) { + const auto find_result = string.find(PlaceHolder(TypeTag<TString>{})); + if (find_result == TString::npos) + throw std::invalid_argument("There is less placeholders than args."); + + string.replace(find_result, 2, FormatToString(arg, TypeTag<TString>{})); + FormatInternal<TString>(string, args...); +} +} // namespace details + +template <typename... T> +String Format(const StringView& format, const T&... args) { + String result(format); + details::FormatInternal<String>(result, args...); + return result; +} + +template <typename... T> +MultiByteString Format(const MultiByteStringView& format, const T&... args) { + MultiByteString result(format); + details::FormatInternal<MultiByteString>(result, args...); + return result; +} + +#define CRU_FORMAT_NUMBER(type) \ + inline String FormatToString(const type number, details::TypeTag<String>) { \ + return std::to_wstring(number); \ + } \ + inline MultiByteString FormatToString(const type number, \ + details::TypeTag<MultiByteString>) { \ + return std::to_string(number); \ + } + +CRU_FORMAT_NUMBER(int) +CRU_FORMAT_NUMBER(short) +CRU_FORMAT_NUMBER(long) +CRU_FORMAT_NUMBER(long long) +CRU_FORMAT_NUMBER(unsigned int) +CRU_FORMAT_NUMBER(unsigned short) +CRU_FORMAT_NUMBER(unsigned long) +CRU_FORMAT_NUMBER(unsigned long long) +CRU_FORMAT_NUMBER(float) +CRU_FORMAT_NUMBER(double) + +#undef CRU_FORMAT_NUMBER + +inline StringView FormatToString(const String& string, + details::TypeTag<String>) { + return string; +} + +inline MultiByteString FormatToString(const MultiByteString& string, + details::TypeTag<MultiByteString>) { + return string; +} + +inline StringView FormatToString(const StringView& string, + details::TypeTag<String>) { + return string; +} + +inline MultiByteStringView FormatToString(const MultiByteStringView& string, + details::TypeTag<MultiByteString>) { + return string; +} + +inline StringView FormatToString(const wchar_t* string, + details::TypeTag<String>) { + return StringView(string); +} + +inline MultiByteStringView FormatToString(const char* string, + details::TypeTag<MultiByteString>) { + return MultiByteString(string); +} +} // namespace cru::util diff --git a/src/util/math_util.hpp b/src/util/math_util.hpp new file mode 100644 index 00000000..01348641 --- /dev/null +++ b/src/util/math_util.hpp @@ -0,0 +1,51 @@ +#pragma once +#include "pre.hpp" + +#include <optional> +#include <type_traits> + +namespace cru::util { +template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> +float Coerce(const T n, const std::optional<T> min, + const std::optional<T> max) { + if (min.has_value() && n < min.value()) return min.value(); + if (max.has_value() && n > max.value()) return max.value(); + return n; +} + +template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> +float Coerce(const T n, const T min, const T max) { + if (n < min) return min; + if (n > max) return max; + return n; +} + +template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> +float Coerce(const T n, const std::nullopt_t, const std::optional<T> max) { + if (max.has_value() && n > max.value()) return max.value(); + return n; +} + +template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> +float Coerce(const T n, const std::optional<T> min, const std::nullopt_t) { + if (min.has_value() && n < min.value()) return min.value(); + return n; +} + +template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> +float Coerce(const T n, const std::nullopt_t, const T max) { + if (n > max) return max; + return n; +} + +template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> +float Coerce(const T n, const T min, const std::nullopt_t) { + if (n < min) return min; + return n; +} + +template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> +T AtLeast0(const T value) { + return value < static_cast<T>(0) ? static_cast<T>(0) : value; +} +} // namespace cru::util diff --git a/src/util/string_util.cpp b/src/util/string_util.cpp new file mode 100644 index 00000000..c9391fc6 --- /dev/null +++ b/src/util/string_util.cpp @@ -0,0 +1,22 @@ +#include "string_util.hpp" + +#include <Windows.h> + +#include "exception.hpp" + +namespace cru::util { +MultiByteString ToUtf8String(const StringView& string) { + if (string.empty()) return MultiByteString(); + + const auto length = ::WideCharToMultiByte(CP_UTF8, 0, string.data(), -1, + nullptr, 0, nullptr, nullptr); + MultiByteString result; + result.reserve(length); + if (::WideCharToMultiByte(CP_UTF8, 0, string.data(), -1, result.data(), + static_cast<int>(result.capacity()), nullptr, + nullptr) == 0) + throw Win32Error(::GetLastError(), + "Failed to convert wide string to UTF-8."); + return result; +} +} // namespace cru::util diff --git a/src/util/string_util.hpp b/src/util/string_util.hpp new file mode 100644 index 00000000..6d060089 --- /dev/null +++ b/src/util/string_util.hpp @@ -0,0 +1,8 @@ +#pragma once +#include "pre.hpp" + +#include "base.hpp" + +namespace cru::util { +MultiByteString ToUtf8String(const StringView& string); +} |