| 221 | // generic number & vector parsing |
| 222 | |
| 223 | template <typename T> std::optional<T> parse(std::string_view s) |
| 224 | { |
| 225 | namespace ds = donut::string_utils; |
| 226 | |
| 227 | trim(s); |
| 228 | if (ds::strcasencmp(s, std::string_view("0x"), 2)) |
| 229 | { |
| 230 | // as of C++17, std::from_chars does handle hex, so fall back on strings |
| 231 | return from_string<T>(std::string(s)); |
| 232 | } |
| 233 | else |
| 234 | { |
| 235 | // as of C++17, std::from_chars returns an error when parsing integers |
| 236 | // with a '+' sign prefix |
| 237 | ltrim(s, '+'); |
| 238 | T value; |
| 239 | if (auto [p, ec] = std::from_chars(s.data(), s.data() + s.size(), value); ec == std::errc()) |
| 240 | return value; |
| 241 | } |
| 242 | return std::optional<T>(); |
| 243 | } |
| 244 | |
| 245 | template <typename T> std::optional<T> parse(std::string const& s) |
| 246 | { |
nothing calls this directly
no test coverage detected