ros2_control - rolling
Loading...
Searching...
No Matches
lexical_casts.hpp
1// Copyright 2023 ros2_control Development Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef HARDWARE_INTERFACE__LEXICAL_CASTS_HPP_
16#define HARDWARE_INTERFACE__LEXICAL_CASTS_HPP_
17
18#include <regex>
19#include <sstream>
20#include <stdexcept>
21#include <string>
22#include <type_traits>
23#include <vector>
24
25namespace hardware_interface
26{
27
33double stod(const std::string & s);
34
40std::string to_lower_case(const std::string & string);
41
48bool parse_bool(const std::string & bool_string);
49
50template <typename T>
51std::vector<T> parse_array(const std::string & array_string)
52{
53 // Use regex to check for a flat array: starts with [, ends with ], no nested brackets
54 const std::regex array_regex(R"(^\[\s*([^\[\]]*\s*(,\s*[^\[\]]+\s*)*)?\]$)");
55 if (!std::regex_match(array_string, array_regex))
56 {
57 throw std::invalid_argument(
58 "String must be a flat array: starts with '[' and ends with ']', no nested arrays");
59 }
60
61 // Use regex for the expression that either empty or contains only spaces
62 const std::regex empty_or_spaces_regex(R"(^\[\s*\]$)");
63 if (std::regex_match(array_string, empty_or_spaces_regex))
64 {
65 return {}; // Return empty array if input is "[]"
66 }
67
68 // Use regex to find cases of comma-separated but only whitespaces or no spaces between them like
69 // "[,]" "[a,b,,c]"
70 const std::regex comma_separated_regex(R"(^\[\s*([^,\s]+(\s*,\s*[^,\s]+)*)?\s*\]$)");
71 if (!std::regex_match(array_string, comma_separated_regex))
72 {
73 throw std::invalid_argument(
74 "String must be a flat array with comma-separated values and no spaces between them");
75 }
76
77 std::vector<T> result = {};
78 if (array_string == "[]")
79 {
80 return result; // Return empty array if input is "[]"
81 }
82
83 // regex for comma separated values and no spaces between them or just content like "[a,b,c]" or
84 // "[a]" or "[a, b, c]"
85 const std::regex value_regex(R"([^\s,\[\]]+)");
86 auto begin = std::sregex_iterator(array_string.begin(), array_string.end(), value_regex);
87 auto end = std::sregex_iterator();
88
89 for (auto it = begin; it != end; ++it)
90 {
91 const std::string value_str = it->str(); // Get the first capturing group
92 if constexpr (std::is_same_v<T, std::string>)
93 {
94 result.push_back(value_str);
95 }
96 else if constexpr (std::is_same_v<T, bool>)
97 {
98 result.push_back(parse_bool(value_str));
99 }
100 else if constexpr (std::is_floating_point_v<T> || std::is_integral_v<T>)
101 {
102 try
103 {
104 const T value = static_cast<T>(hardware_interface::stod(value_str));
105 result.push_back(value);
106 }
107 catch (const std::exception &)
108 {
109 throw std::invalid_argument(
110 "Failed converting string to floating point or integer: " + value_str);
111 }
112 }
113 else
114 {
115 throw std::invalid_argument("Unsupported type for parsing: " + std::string(typeid(T).name()));
116 }
117 }
118 return result;
119}
120
121std::vector<std::string> parse_string_array(const std::string & string_array_string);
122
123} // namespace hardware_interface
124
125#endif // HARDWARE_INTERFACE__LEXICAL_CASTS_HPP_
Definition actuator.hpp:22
std::string to_lower_case(const std::string &string)
Convert a string to lower case.
Definition lexical_casts.cpp:65
double stod(const std::string &s)
Helper function to convert a std::string to double in a locale-independent way.
Definition lexical_casts.cpp:56
bool parse_bool(const std::string &bool_string)
Parse a boolean value from a string.
Definition lexical_casts.cpp:74