15#ifndef HARDWARE_INTERFACE__LEXICAL_CASTS_HPP_
16#define HARDWARE_INTERFACE__LEXICAL_CASTS_HPP_
35double stod(
const std::string & s);
40float stof(
const std::string & s);
49 static_assert(std::is_integral_v<T> && std::is_signed_v<T>,
"T must be a signed integral type");
52 const auto v = std::stol(s, &pos);
53 if (pos != s.length())
55 throw std::invalid_argument(
"Invalid characters in string");
57 if (v < std::numeric_limits<T>::min() || v > std::numeric_limits<T>::max())
59 throw std::out_of_range(
"value not in range of target type");
62 return static_cast<T
>(v);
66inline int8_t stoi8(
const std::string & s) {
return stoi_generic<int8_t>(s); }
67inline int16_t stoi16(
const std::string & s) {
return stoi_generic<int16_t>(s); }
68inline int32_t stoi32(
const std::string & s) {
return stoi_generic<int32_t>(s); }
78 std::is_integral_v<T> && std::is_unsigned_v<T>,
"T must be an unsigned integral type");
81 const auto v = std::stoul(s, &pos);
82 if (pos != s.length())
84 throw std::invalid_argument(
"Invalid characters in string");
86 if (v > std::numeric_limits<T>::max())
88 throw std::out_of_range(
"value not in range of target type");
91 return static_cast<T
>(v);
95inline uint8_t stoui8(
const std::string & s) {
return stoui_generic<uint8_t>(s); }
96inline uint16_t stoui16(
const std::string & s) {
return stoui_generic<uint16_t>(s); }
97inline uint32_t stoui32(
const std::string & s) {
return stoui_generic<uint32_t>(s); }
112bool parse_bool(
const std::string & bool_string);
115std::vector<T> parse_array(
const std::string & array_string)
118 const std::regex array_regex(R
"(^\[\s*([^\[\]]*\s*(,\s*[^\[\]]+\s*)*)?\]$)");
119 if (!std::regex_match(array_string, array_regex))
121 throw std::invalid_argument(
122 "String must be a flat array: starts with '[' and ends with ']', no nested arrays");
126 const std::regex empty_or_spaces_regex(R
"(^\[\s*\]$)");
127 if (std::regex_match(array_string, empty_or_spaces_regex))
134 const std::regex comma_separated_regex(R
"(^\[\s*([^,\s]+(\s*,\s*[^,\s]+)*)?\s*\]$)");
135 if (!std::regex_match(array_string, comma_separated_regex))
137 throw std::invalid_argument(
138 "String must be a flat array with comma-separated values and no spaces between them");
141 std::vector<T> result = {};
142 if (array_string ==
"[]")
149 const std::regex value_regex(R
"([^\s,\[\]]+)");
150 auto begin = std::sregex_iterator(array_string.begin(), array_string.end(), value_regex);
151 auto end = std::sregex_iterator();
153 for (
auto it = begin; it != end; ++it)
155 const std::string value_str = it->str();
156 if constexpr (std::is_same_v<T, std::string>)
158 result.push_back(value_str);
160 else if constexpr (std::is_same_v<T, bool>)
164 else if constexpr (std::is_floating_point_v<T> || std::is_integral_v<T>)
169 result.push_back(value);
171 catch (
const std::exception &)
173 throw std::invalid_argument(
174 "Failed converting string to floating point or integer: " + value_str);
179 throw std::invalid_argument(
"Unsupported type for parsing: " + std::string(
typeid(T).name()));
185std::vector<std::string> parse_string_array(
const std::string & string_array_string);
Definition mujoco_system_interface.hpp:69
T stoui_generic(const std::string &s)
Overflow-safe conversion from string to uint32_t.
Definition lexical_casts.hpp:75
std::string to_lower_case(const std::string &string)
Convert a string to lower case.
Definition lexical_casts.cpp:103
T stoi_generic(const std::string &s)
Overflow-safe conversion from string to int32_t.
Definition lexical_casts.hpp:47
float stof(const std::string &s)
Helper function to convert a std::string to float in a locale-independent way.
Definition lexical_casts.cpp:94
double stod(const std::string &s)
Helper function to convert a std::string to double in a locale-independent way.
Definition lexical_casts.cpp:85
bool parse_bool(const std::string &bool_string)
Parse a boolean value from a string.
Definition lexical_casts.cpp:112