Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

142 linhas
4.0 KiB

  1. #pragma once
  2. #include <sstream>
  3. #include <cpputils/misc/exception.h>
  4. namespace utl
  5. {
  6. namespace __impl
  7. {
  8. template<class T, class Enable = void>
  9. struct op_to_string
  10. {
  11. inline void operator()(std::ostream& os, const T& s) const
  12. { os << s; }
  13. };
  14. template<class T>
  15. struct op_to_string<T, decltype(std::declval<T>().to_string(std::declval<std::ostream&>()), void())>
  16. {
  17. inline void operator()(std::ostream& os, const T& s) const
  18. { s.to_string(os); }
  19. };
  20. template<class T>
  21. struct op_to_string<T, decltype(std::declval<T>().to_string(), void())>
  22. {
  23. inline void operator()(std::ostream& os, const T& s) const
  24. { os << s.to_string(); }
  25. };
  26. template<class T, class Enable = void>
  27. struct op_from_string
  28. {
  29. inline bool operator()(const std::string& s, T& value) const
  30. {
  31. std::istringstream ss(s);
  32. ss >> value;
  33. return static_cast<bool>(ss);
  34. }
  35. };
  36. template<>
  37. struct op_from_string<std::string, void>
  38. {
  39. inline bool operator()(const std::string& s, std::string& value) const
  40. {
  41. value = s;
  42. return true;
  43. }
  44. };
  45. template<>
  46. struct op_from_string<const char*, void>
  47. {
  48. inline bool operator()(const std::string& s, const char*& value) const
  49. {
  50. value = s.c_str();
  51. return true;
  52. }
  53. };
  54. template<class T>
  55. struct op_from_string<T, decltype(std::declval<T&>().from_string(std::declval<const std::string&>()), void())>
  56. {
  57. inline bool operator()(const std::string& s, T& value) const
  58. { return value.from_string(s); }
  59. };
  60. template<class T>
  61. struct op_from_string<T, decltype(T::from_string(std::declval<const std::string&>(), std::declval<T&>()), void())>
  62. {
  63. inline bool operator()(const std::string& s, T& value) const
  64. { return T::from_string(s, value); }
  65. };
  66. template<class T>
  67. struct op_from_string<T, typename std::enable_if<std::is_integral<T>::value>::type>
  68. {
  69. inline bool operator()(const std::string& s, T& value) const
  70. {
  71. char *e = nullptr;
  72. const char *c = s.c_str();
  73. value = static_cast<T>(std::strtoull(c, &e, 0));
  74. return (c != e);
  75. }
  76. };
  77. template<class T>
  78. struct op_from_string<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
  79. {
  80. inline bool operator()(const std::string& s, T& value) const
  81. {
  82. char *e = nullptr;
  83. const char *c = s.c_str();
  84. value = static_cast<T>(std::strtold(c, &e));
  85. return (c != e);
  86. }
  87. };
  88. }
  89. template<class T>
  90. inline void to_string(std::ostream& os, const T& t)
  91. { __impl::op_to_string<T>()(os, t); }
  92. template<class T>
  93. inline std::string to_string(const T& t)
  94. {
  95. std::ostringstream ss;
  96. to_string(ss, t);
  97. return ss.str();
  98. }
  99. template<>
  100. inline std::string to_string<std::string>(const std::string& s)
  101. { return s; }
  102. template<class T>
  103. inline bool try_from_string(const std::string& s, T& value)
  104. { return __impl::op_from_string<T>()(s, value); }
  105. template<class T>
  106. inline T from_string(const std::string& s, T defaultValue)
  107. {
  108. T tmp;
  109. return try_from_string<T>(s, tmp)
  110. ? tmp
  111. : defaultValue;
  112. }
  113. template<class T>
  114. inline T from_string(const std::string& s)
  115. {
  116. T tmp;
  117. if (!try_from_string<T>(s, tmp))
  118. throw exception(std::string("unable to convert string to specific value: ") + s);
  119. return tmp;
  120. }
  121. }