| 55 | namespace EE { |
| 56 | |
| 57 | template <typename T> static bool _fromString( T& t, const std::string& s, int base = 10 ) { |
| 58 | const char* begin = s.data(); |
| 59 | const char* end = s.data() + s.size(); |
| 60 | |
| 61 | if constexpr ( std::is_integral_v<T> && std::is_signed_v<T> ) { |
| 62 | long long value = 0; |
| 63 | auto result = std::from_chars( begin, end, value, base ); |
| 64 | if ( result.ec == std::errc{} && result.ptr == end && |
| 65 | value >= std::numeric_limits<T>::min() && value <= std::numeric_limits<T>::max() ) { |
| 66 | t = static_cast<T>( value ); |
| 67 | return true; |
| 68 | } |
| 69 | return false; |
| 70 | } else if constexpr ( std::is_integral_v<T> && std::is_unsigned_v<T> ) { |
| 71 | unsigned long long value = 0; |
| 72 | auto result = std::from_chars( begin, end, value, base ); |
| 73 | if ( result.ec == std::errc{} && result.ptr == end && |
| 74 | value <= std::numeric_limits<T>::max() ) { |
| 75 | t = static_cast<T>( value ); |
| 76 | return true; |
| 77 | } |
| 78 | return false; |
| 79 | } else if constexpr ( (std::is_same_v<T, float> || std::is_same_v<T, double>)) { |
| 80 | auto result = fast_float::from_chars( begin, end, t ); |
| 81 | bool res = result.ec == std::errc{} && result.ptr == end; |
| 82 | return res; |
| 83 | } else { |
| 84 | T value; |
| 85 | auto result = std::from_chars( begin, end, value, base ); |
| 86 | if ( result.ec == std::errc{} && result.ptr == end ) { |
| 87 | t = static_cast<T>( value ); |
| 88 | return true; |
| 89 | } |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | template <class T> static std::string _toString( const T& value, size_t digitsAfterComma = 2 ) { |
| 94 | char buffer[32]; |