Skip to content

Commit b1064db

Browse files
committed
preserve order of ports in PortsList
1 parent c9dea7b commit b1064db

File tree

4 files changed

+32
-21
lines changed

4 files changed

+32
-21
lines changed

include/behaviortree_cpp/basic_types.h

+13-1
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,19 @@ template <typename T = AnyTypeAllowed>
582582

583583
//----------
584584

585-
using PortsList = std::unordered_map<std::string, PortInfo>;
585+
using PortsList = std::vector<std::pair<std::string, PortInfo>>;
586+
587+
inline const PortInfo* findPortInfo(const PortsList& ports, const std::string& key)
588+
{
589+
for(auto& it : ports)
590+
{
591+
if(it.first == key)
592+
{
593+
return &it.second;
594+
}
595+
}
596+
return nullptr;
597+
}
586598

587599
template <typename T, typename = void>
588600
struct has_static_method_providedPorts : std::false_type

include/behaviortree_cpp/controls/switch_node.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@ inline PortsList SwitchNode<NUM_CASES>::providedPorts()
9191
{
9292
static PortsList provided_ports = []() {
9393
PortsList ports;
94-
ports.insert(BT::InputPort<std::string>("variable"));
94+
ports.push_back(BT::InputPort<std::string>("variable"));
9595
for(unsigned i = 1; i <= NUM_CASES; i++)
9696
{
9797
auto key = std::string("case_") + std::to_string(i);
98-
ports.insert(BT::InputPort<std::string>(key));
98+
ports.push_back(BT::InputPort<std::string>(key));
9999
}
100100
return ports;
101101
}();

include/behaviortree_cpp/tree_node.h

+8-8
Original file line numberDiff line numberDiff line change
@@ -455,30 +455,29 @@ inline Expected<Timestamp> TreeNode::getInputStamped(const std::string& key,
455455
else
456456
{
457457
// maybe it is declared with a default value in the manifest
458-
auto port_manifest_it = config().manifest->ports.find(key);
459-
if(port_manifest_it == config().manifest->ports.end())
458+
const auto* port_info = findPortInfo(config().manifest->ports, key);
459+
if(!port_info)
460460
{
461461
return nonstd::make_unexpected(StrCat("getInput() of node '", fullPath(),
462462
"' failed because the manifest doesn't "
463463
"contain the key: [",
464464
key, "]"));
465465
}
466-
const auto& port_info = port_manifest_it->second;
467466
// there is a default value
468-
if(port_info.defaultValue().empty())
467+
if(port_info->defaultValue().empty())
469468
{
470469
return nonstd::make_unexpected(StrCat("getInput() of node '", fullPath(),
471470
"' failed because nor the manifest or the "
472471
"XML contain the key: [",
473472
key, "]"));
474473
}
475-
if(port_info.defaultValue().isString())
474+
if(port_info->defaultValue().isString())
476475
{
477-
port_value_str = port_info.defaultValue().cast<std::string>();
476+
port_value_str = port_info->defaultValue().cast<std::string>();
478477
}
479478
else
480479
{
481-
destination = port_info.defaultValue().cast<T>();
480+
destination = port_info->defaultValue().cast<T>();
482481
return Timestamp{};
483482
}
484483
}
@@ -585,7 +584,8 @@ inline Result TreeNode::setOutput(const std::string& key, const T& value)
585584

586585
if constexpr(std::is_same_v<BT::Any, T>)
587586
{
588-
if(config().manifest->ports.at(key).type() != typeid(BT::Any))
587+
const auto* port_info = findPortInfo(config().manifest->ports, key);
588+
if(port_info && port_info->type() != typeid(BT::Any))
589589
{
590590
throw LogicError("setOutput<Any> is not allowed, unless the port "
591591
"was declared using OutputPort<Any>");

src/xml_parsing.cpp

+9-10
Original file line numberDiff line numberDiff line change
@@ -663,31 +663,30 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,
663663

664664
if(manifest)
665665
{
666-
auto port_model_it = manifest->ports.find(port_name);
667-
if(port_model_it == manifest->ports.end())
666+
const auto* port_model = findPortInfo(manifest->ports, port_name);
667+
if(!port_model)
668668
{
669669
throw RuntimeError(StrCat("a port with name [", port_name,
670670
"] is found in the XML, but not in the "
671671
"providedPorts()"));
672672
}
673673
else
674674
{
675-
const auto& port_model = port_model_it->second;
676675
bool is_blacbkboard = port_value.size() >= 3 && port_value.front() == '{' &&
677676
port_value.back() == '}';
678677
// let's test already if conversion is possible
679-
if(!is_blacbkboard && port_model.converter() && port_model.isStronglyTyped())
678+
if(!is_blacbkboard && port_model->converter() && port_model->isStronglyTyped())
680679
{
681680
// This may throw
682681
try
683682
{
684-
port_model.converter()(port_value);
683+
port_model->converter()(port_value);
685684
}
686685
catch(std::exception& ex)
687686
{
688687
auto msg = StrCat("The port with name \"", port_name, "\" and value \"",
689688
port_value, "\" can not be converted to ",
690-
port_model.typeName());
689+
port_model->typeName());
691690
throw LogicError(msg);
692691
}
693692
}
@@ -750,7 +749,7 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,
750749
//Check that name in remapping can be found in the manifest
751750
for(const auto& [name_in_subtree, _] : port_remap)
752751
{
753-
if(manifest->ports.count(name_in_subtree) == 0)
752+
if(!findPortInfo(manifest->ports, name_in_subtree))
754753
{
755754
throw RuntimeError("Possible typo? In the XML, you tried to remap port \"",
756755
name_in_subtree, "\" in node [", config.path, "(type ",
@@ -809,10 +808,10 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,
809808
for(const auto& remap_it : port_remap)
810809
{
811810
const auto& port_name = remap_it.first;
812-
auto port_it = manifest->ports.find(port_name);
813-
if(port_it != manifest->ports.end())
811+
const auto* port_info = findPortInfo(manifest->ports, port_name);
812+
if(port_info != nullptr)
814813
{
815-
auto direction = port_it->second.direction();
814+
auto direction = port_info->direction();
816815
if(direction != PortDirection::OUTPUT)
817816
{
818817
config.input_ports.insert(remap_it);

0 commit comments

Comments
 (0)