From 1e4e926823a7038d44da7eae3a40faa7f1aba8c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A4r=20Bj=C3=B6rklund?= Date: Fri, 14 Feb 2020 18:56:17 +0100 Subject: Fix enum formatting This attempt removes the enums from fmt altogether, fmt never sees an enum, only ints. --- xbmc/utils/StringUtils.h | 27 +++++++++++++++--- 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::type; + +template< class T > struct remove_rvalue_reference {typedef T type;}; +template< class T > struct remove_rvalue_reference {typedef T& type;}; +template< class T > struct remove_rvalue_reference {typedef T* type;}; +template< class T > struct remove_rvalue_reference {typedef T type;}; + +template::value, int> = 0> +constexpr auto EnumToInt(T&& arg) noexcept -> typename remove_rvalue_reference::type +{ + return arg; +} +template::value, int> = 0> +constexpr auto EnumToInt(T&& arg) noexcept -> int +{ + return static_cast(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)...); + auto result = ::fmt::format(fmt, EnumToInt(std::forward(args))...); if (result == fmt) - result = ::fmt::sprintf(fmt, std::forward(args)...); + result = ::fmt::sprintf(fmt, EnumToInt(std::forward(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)...); + auto result = ::fmt::format(fmt, EnumToInt(std::forward(args))...); if (result == fmt) - result = ::fmt::sprintf(fmt, std::forward(args)...); + result = ::fmt::sprintf(fmt, EnumToInt(std::forward(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"; -- cgit v1.2.3