|
12 | 12 |
|
13 | 13 | #include "behaviortree_cpp/basic_types.h" |
14 | 14 |
|
| 15 | +#include <charconv> |
15 | 16 | #include <cstdio> |
16 | 17 | #include <cstring> |
17 | 18 | #include <functional> |
18 | 19 | #include <iostream> |
| 20 | +#include <limits> |
19 | 21 | #include <list> |
20 | 22 | #include <sstream> |
21 | 23 | #include <string> |
@@ -1149,10 +1151,59 @@ void BT::XMLParser::PImpl::recursivelyCreateSubtree( |
1149 | 1151 | } |
1150 | 1152 | else |
1151 | 1153 | { |
1152 | | - // constant string: just set that constant value into the BB |
| 1154 | + // constant value: set it into the BB with appropriate type |
1153 | 1155 | // IMPORTANT: this must not be autoremapped!!! |
1154 | 1156 | new_bb->enableAutoRemapping(false); |
1155 | | - new_bb->set(attr_name, static_cast<std::string>(attr_value)); |
| 1157 | + const std::string str_value(attr_value); |
| 1158 | + |
| 1159 | + // Try to preserve numeric types so that Script expressions |
| 1160 | + // can perform arithmetic without type-mismatch errors. |
| 1161 | + // Use std::from_chars with strict full-string validation to avoid |
| 1162 | + // false positives on compound strings like "1;2;3" or "2.2;2.4". |
| 1163 | + bool stored = false; |
| 1164 | + if(!str_value.empty()) |
| 1165 | + { |
| 1166 | + const char* begin = str_value.data(); |
| 1167 | + const char* end = begin + str_value.size(); |
| 1168 | + // Try integer first (no decimal point, no exponent notation). |
| 1169 | + // Use int when the value fits, to match the most common port |
| 1170 | + // declarations. Fall back to int64_t for larger values. |
| 1171 | + if(str_value.find('.') == std::string::npos && |
| 1172 | + str_value.find('e') == std::string::npos && |
| 1173 | + str_value.find('E') == std::string::npos) |
| 1174 | + { |
| 1175 | + int64_t int_val = 0; |
| 1176 | + auto [ptr, ec] = std::from_chars(begin, end, int_val); |
| 1177 | + if(ec == std::errc() && ptr == end) |
| 1178 | + { |
| 1179 | + if(int_val >= std::numeric_limits<int>::min() && |
| 1180 | + int_val <= std::numeric_limits<int>::max()) |
| 1181 | + { |
| 1182 | + new_bb->set(attr_name, static_cast<int>(int_val)); |
| 1183 | + } |
| 1184 | + else |
| 1185 | + { |
| 1186 | + new_bb->set(attr_name, int_val); |
| 1187 | + } |
| 1188 | + stored = true; |
| 1189 | + } |
| 1190 | + } |
| 1191 | + // Try double |
| 1192 | + if(!stored) |
| 1193 | + { |
| 1194 | + double dbl_val = 0; |
| 1195 | + auto [ptr, ec] = std::from_chars(begin, end, dbl_val); |
| 1196 | + if(ec == std::errc() && ptr == end) |
| 1197 | + { |
| 1198 | + new_bb->set(attr_name, dbl_val); |
| 1199 | + stored = true; |
| 1200 | + } |
| 1201 | + } |
| 1202 | + } |
| 1203 | + if(!stored) |
| 1204 | + { |
| 1205 | + new_bb->set(attr_name, str_value); |
| 1206 | + } |
1156 | 1207 | new_bb->enableAutoRemapping(do_autoremap); |
1157 | 1208 | } |
1158 | 1209 | } |
|
0 commit comments