Skip to content

Commit 2ee883c

Browse files
committed
fix issue #605: strip whitespaces and better error message
1 parent 25b25c7 commit 2ee883c

File tree

6 files changed

+77
-32
lines changed

6 files changed

+77
-32
lines changed

include/behaviortree_cpp/basic_types.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,17 +263,21 @@ class PortInfo
263263
};
264264

265265
PortInfo(PortDirection direction = PortDirection::INOUT) :
266-
type_(direction), type_info_(typeid(AnyTypeAllowed))
266+
type_(direction), type_info_(typeid(AnyTypeAllowed)),
267+
type_str_("AnyTypeAllowed")
267268
{}
268269

269270
PortInfo(PortDirection direction, std::type_index type_info, StringConverter conv) :
270-
type_(direction), type_info_(type_info), converter_(conv)
271+
type_(direction), type_info_(type_info), converter_(conv),
272+
type_str_(BT::demangle(type_info))
271273
{}
272274

273275
[[nodiscard]] PortDirection direction() const;
274276

275277
[[nodiscard]] const std::type_index& type() const;
276278

279+
[[nodiscard]] const std::string& typeName() const;
280+
277281
[[nodiscard]] Any parseString(const char* str) const;
278282

279283
[[nodiscard]] Any parseString(const std::string& str) const;
@@ -319,6 +323,7 @@ class PortInfo
319323
std::string description_;
320324
Any default_value_;
321325
std::string default_value_str_;
326+
std::string type_str_;
322327
};
323328

324329
template <typename T = PortInfo::AnyTypeAllowed> [[nodiscard]]

include/behaviortree_cpp/scripting/operators.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,8 @@ struct ExprAssignment : ExprBase
479479
// fail otherwise
480480
auto msg = StrCat("The blackboard entry [", key,
481481
"] doesn't exist, yet.\n"
482-
"If you want to create a new one, use the operator "
482+
"If you want to create a new one, "
483+
"use the operator "
483484
"[:=] instead of [=]");
484485
throw RuntimeError(msg);
485486
}
@@ -531,11 +532,12 @@ struct ExprAssignment : ExprBase
531532
{
532533
value.copyInto(*dst_ptr);
533534
}
534-
catch (RuntimeError&)
535+
catch (std::exception&)
535536
{
536537
auto msg = StrCat(errorPrefix(), "\nThe right operand has type [",
537538
BT::demangle(value.type()),
538-
"] and can't be converted");
539+
"] and can't be converted to [",
540+
BT::demangle(dst_ptr->type()), "]");
539541
throw RuntimeError(msg);
540542
}
541543
}

include/behaviortree_cpp/tree_node.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,9 @@ class TreeNode
284284
// in the port (no remapping and no conversion to a type)
285285
[[nodiscard]] StringView getRawPortValue(const std::string& key) const;
286286

287-
/// Check a string and return true if it matches either one of these
288-
/// two patterns: {...} or ${...}
287+
/// Check a string and return true if it matches the pattern: {...}
289288
[[nodiscard]]
290-
static bool isBlackboardPointer(StringView str);
289+
static bool isBlackboardPointer(StringView str, StringView* stripped_pointer = nullptr);
291290

292291
[[nodiscard]]
293292
static StringView stripBlackboardPointer(StringView str);

src/basic_types.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,11 @@ const std::type_index& PortInfo::type() const
335335
return type_info_;
336336
}
337337

338+
const std::string &PortInfo::typeName() const
339+
{
340+
return type_str_;
341+
}
342+
338343
Any PortInfo::parseString(const char* str) const
339344
{
340345
if (converter_)

src/tree_node.cpp

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -346,36 +346,38 @@ StringView TreeNode::getRawPortValue(const std::string& key) const
346346
return remap_it->second;
347347
}
348348

349-
bool TreeNode::isBlackboardPointer(StringView str)
349+
bool TreeNode::isBlackboardPointer(StringView str, StringView* stripped_pointer)
350350
{
351-
const auto size = str.size();
352-
if (size >= 3 && str.back() == '}')
351+
if (str.size() < 3)
353352
{
354-
if (str[0] == '{')
355-
{
356-
return true;
357-
}
358-
if (size >= 4 && str[0] == '$' && str[1] == '{')
359-
{
360-
return true;
361-
}
353+
return false;
354+
}
355+
// strip leading and following spaces
356+
size_t front_index = 0;
357+
size_t last_index = str.size()-1;
358+
while(str[front_index] == ' ' && front_index <= last_index)
359+
{
360+
front_index++;
361+
}
362+
while(str[last_index] == ' ' && front_index <= last_index)
363+
{
364+
last_index--;
365+
}
366+
const auto size = (last_index-front_index) + 1;
367+
auto valid = size >= 3 && str[front_index] == '{' && str[last_index] == '}';
368+
if(valid && stripped_pointer)
369+
{
370+
*stripped_pointer = StringView( &str[front_index+1], size-2);
362371
}
363-
return false;
372+
return valid;
364373
}
365374

366375
StringView TreeNode::stripBlackboardPointer(StringView str)
367376
{
368-
const auto size = str.size();
369-
if (size >= 3 && str.back() == '}')
377+
StringView out;
378+
if(isBlackboardPointer(str, &out))
370379
{
371-
if (str[0] == '{')
372-
{
373-
return str.substr(1, size - 2);
374-
}
375-
if (str[0] == '$' && str[1] == '{')
376-
{
377-
return str.substr(2, size - 3);
378-
}
380+
return out;
379381
}
380382
return {};
381383
}
@@ -387,9 +389,10 @@ Expected<StringView> TreeNode::getRemappedKey(StringView port_name,
387389
{
388390
return {port_name};
389391
}
390-
if (isBlackboardPointer(remapped_port))
392+
StringView stripped;
393+
if (isBlackboardPointer(remapped_port, &stripped))
391394
{
392-
return {stripBlackboardPointer(remapped_port)};
395+
return {stripped};
393396
}
394397
return nonstd::make_unexpected("Not a blackboard pointer");
395398
}

tests/gtest_blackboard.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,3 +360,34 @@ TEST(BlackboardTest, SetStringView)
360360

361361
ASSERT_NO_THROW(bb->set("string_view", string_view_const));
362362
}
363+
364+
TEST(ParserTest, Issue605_whitespaces)
365+
{
366+
BT::BehaviorTreeFactory factory;
367+
368+
const std::string xml_text = R"(
369+
<root BTCPP_format="4" >
370+
<BehaviorTree ID="MySubtree">
371+
<Script code=" sub_value:=false " />
372+
</BehaviorTree>
373+
374+
<BehaviorTree ID="MyMainTree">
375+
<Sequence>
376+
<Script code=" my_value:=true " />
377+
<SubTree ID="MySubtree" sub_value="{my_value} "/>
378+
</Sequence>
379+
</BehaviorTree>
380+
</root> )";
381+
382+
factory.registerBehaviorTreeFromText(xml_text);
383+
auto tree = factory.createTree("MyMainTree");
384+
const auto status = tree.tickWhileRunning();
385+
386+
for(auto const& subtree: tree.subtrees)
387+
{
388+
subtree->blackboard->debugMessage();
389+
}
390+
391+
ASSERT_EQ(status, BT::NodeStatus::SUCCESS);
392+
ASSERT_EQ(false, tree.rootBlackboard()->get<bool>("my_value"));
393+
}

0 commit comments

Comments
 (0)