You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
3.7 KiB

  1. #pragma once
  2. #include "enum.h"
  3. namespace cppcore
  4. {
  5. namespace __impl
  6. {
  7. /* enum_value_traits */
  8. template<typename T_enum, typename T_enable>
  9. decltype(auto) enum_value_traits<T_enum, T_enable>::get_enum_values()
  10. {
  11. static const auto value = enum_value_vector_type();
  12. return value;
  13. }
  14. /* enum_conversion_traits */
  15. template<typename T_enum, typename T_traits>
  16. decltype(auto) enum_conversion_traits<T_enum, T_traits>
  17. ::get_enum_to_string_map()
  18. {
  19. static const auto value = create_enum_to_string_map();
  20. return value;
  21. }
  22. template<typename T_enum, typename T_traits>
  23. decltype(auto) enum_conversion_traits<T_enum, T_traits>
  24. ::get_string_to_enum_map()
  25. {
  26. static const auto value = create_string_to_enum_map();
  27. return value;
  28. }
  29. template<typename T_enum, typename T_traits>
  30. decltype(auto) enum_conversion_traits<T_enum, T_traits>
  31. ::create_enum_to_string_map()
  32. {
  33. auto& values = traits_type::get_enum_values();
  34. enum_to_string_map_type ret;
  35. for (auto& p : values)
  36. {
  37. ret.emplace(p.first, p.second);
  38. }
  39. return ret;
  40. }
  41. template<typename T_enum, typename T_traits>
  42. decltype(auto) enum_conversion_traits<T_enum, T_traits>
  43. ::create_string_to_enum_map()
  44. {
  45. auto& values = traits_type::get_enum_values();
  46. string_to_enum_map_type ret;
  47. for (auto& p : values)
  48. {
  49. ret.emplace(p.second, p.first);
  50. }
  51. return ret;
  52. }
  53. }
  54. /* enum_conversion */
  55. template<typename T_enum, typename T_traits>
  56. std::string enum_conversion<T_enum, T_traits>
  57. ::to_string(enum_type value, bool add_numeric_value)
  58. {
  59. std::string ret;
  60. auto& map = traits_type::get_enum_to_string_map();
  61. auto it = map.find(value);
  62. if (it != map.end())
  63. {
  64. ret = it->second;
  65. if (add_numeric_value)
  66. ret += '(' + std::to_string(static_cast<base_type>(value)) + ')'; // TODO
  67. }
  68. else
  69. ret = std::to_string(static_cast<base_type>(value)); // TODO
  70. return ret;
  71. }
  72. template<typename T_enum, typename T_traits>
  73. bool enum_conversion<T_enum, T_traits>
  74. ::try_to_enum(const std::string& str, enum_type& value, bool accept_numeric_value)
  75. {
  76. static const auto& map = traits_type::get_string_to_enum_map();
  77. auto it = map.find(str);
  78. if (it != map.end())
  79. {
  80. value = it->second;
  81. return true;
  82. }
  83. if (!accept_numeric_value)
  84. return false;
  85. char *e = nullptr;
  86. const char *c = str.c_str();
  87. value = static_cast<enum_type>(std::strtoull(c, &e, 0));
  88. return (c != e);
  89. }
  90. template<typename T_enum, typename T_traits>
  91. T_enum enum_conversion<T_enum, T_traits>
  92. ::to_enum(const std::string& str, bool accept_numeric_value)
  93. {
  94. using namespace ::std;
  95. enum_type value;
  96. if (!try_to_enum(str, value, accept_numeric_value))
  97. throw convert_exception("unable to convert '"s + str + "' to '"s + type_helper<enum_type>::name() + "'"s);
  98. return value;
  99. }
  100. template<typename T_enum, typename T_traits>
  101. T_enum enum_conversion<T_enum, T_traits>
  102. ::to_enum_default(const std::string& str, enum_type default_value, bool accept_numeric_value)
  103. {
  104. enum_type value;
  105. return try_to_enum(str, value, accept_numeric_value)
  106. ? value
  107. : default_value;
  108. }
  109. }