diff options
author | Dave Blake <oak99sky@yahoo.co.uk> | 2020-07-27 09:51:35 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-27 09:51:35 +0100 |
commit | 45686bddb1f308ec580f97eb4b228b8a6606b320 (patch) | |
tree | f5c282a03e871e4aee62f97b2382ed8211e04493 | |
parent | acbb8160ed0ed4e39bae58db0329f479ce5c4f64 (diff) | |
parent | 1e4e926823a7038d44da7eae3a40faa7f1aba8c8 (diff) |
Merge pull request #18216 from Paxxi/fix_enum_backport18.8-Leia
Fix enum formatting for libfmt 6 [backport]
-rw-r--r-- | xbmc/utils/StringUtils.h | 27 | ||||
-rw-r--r-- | xbmc/utils/test/TestStringUtils.cpp | 55 |
2 files changed, 78 insertions, 4 deletions
diff --git a/xbmc/utils/StringUtils.h b/xbmc/utils/StringUtils.h index e6dca5a04d..1abc071cc5 100644 --- a/xbmc/utils/StringUtils.h +++ b/xbmc/utils/StringUtils.h @@ -51,6 +51,25 @@ DEF_TO_STR_VALUE(foo) // outputs "4" #define DEF_TO_STR_NAME(x) #x #define DEF_TO_STR_VALUE(x) DEF_TO_STR_NAME(x) +template< bool B, class T = void > +using enable_if_t = typename std::enable_if<B,T>::type; + +template< class T > struct remove_rvalue_reference {typedef T type;}; +template< class T > struct remove_rvalue_reference<T&> {typedef T& type;}; +template< class T > struct remove_rvalue_reference<T*> {typedef T* type;}; +template< class T > struct remove_rvalue_reference<T&&> {typedef T type;}; + +template<typename T, enable_if_t<!std::is_enum<T>::value, int> = 0> +constexpr auto EnumToInt(T&& arg) noexcept -> typename remove_rvalue_reference<decltype(arg)>::type +{ + return arg; +} +template<typename T, enable_if_t<std::is_enum<T>::value, int> = 0> +constexpr auto EnumToInt(T&& arg) noexcept -> int +{ + return static_cast<int>(arg); +} + class StringUtils { public: @@ -69,9 +88,9 @@ public: static std::string Format(const std::string& fmt, Args&&... args) { // coverity[fun_call_w_exception : FALSE] - auto result = ::fmt::format(fmt, std::forward<Args>(args)...); + auto result = ::fmt::format(fmt, EnumToInt(std::forward<Args>(args))...); if (result == fmt) - result = ::fmt::sprintf(fmt, std::forward<Args>(args)...); + result = ::fmt::sprintf(fmt, EnumToInt(std::forward<Args>(args))...); return result; } @@ -79,9 +98,9 @@ public: static std::wstring Format(const std::wstring& fmt, Args&&... args) { // coverity[fun_call_w_exception : FALSE] - auto result = ::fmt::format(fmt, std::forward<Args>(args)...); + auto result = ::fmt::format(fmt, EnumToInt(std::forward<Args>(args))...); if (result == fmt) - result = ::fmt::sprintf(fmt, std::forward<Args>(args)...); + result = ::fmt::sprintf(fmt, EnumToInt(std::forward<Args>(args))...); return result; } diff --git a/xbmc/utils/test/TestStringUtils.cpp b/xbmc/utils/test/TestStringUtils.cpp index baf1d42783..a25a45a246 100644 --- a/xbmc/utils/test/TestStringUtils.cpp +++ b/xbmc/utils/test/TestStringUtils.cpp @@ -11,6 +11,32 @@ #include "gtest/gtest.h" +enum class ECG +{ + A, + B +}; + +enum EG +{ + C, + D +}; + +namespace test_enum +{ +enum class ECN +{ + A = 1, + B +}; +enum EN +{ + C = 1, + D +}; +} + TEST(TestStringUtils, Format) { std::string refstr = "test 25 2.7 ff FF"; @@ -22,6 +48,35 @@ TEST(TestStringUtils, Format) EXPECT_STREQ("", varstr.c_str()); } +TEST(TestStringUtils, FormatEnum) +{ + const char* zero = "0"; + const char* one = "1"; + + std::string varstr = StringUtils::Format("{}", ECG::A); + EXPECT_STREQ(zero, varstr.c_str()); + + varstr = StringUtils::Format("{}", EG::C); + EXPECT_STREQ(zero, varstr.c_str()); + + varstr = StringUtils::Format("{}", test_enum::ECN::A); + EXPECT_STREQ(one, varstr.c_str()); + + varstr = StringUtils::Format("{}", test_enum::EN::C); + EXPECT_STREQ(one, varstr.c_str()); +} + +TEST(TestStringUtils, FormatEnumWidth) +{ + const char* one = "01"; + + std::string varstr = StringUtils::Format("{:02d}", ECG::B); + EXPECT_STREQ(one, varstr.c_str()); + + varstr = StringUtils::Format("%02d", EG::D); + EXPECT_STREQ(one, varstr.c_str()); +} + TEST(TestStringUtils, ToUpper) { std::string refstr = "TEST"; |