dds-fmu 0.5.1
DDS-FMU communication integration
CustomKeyFilter.hpp
1#pragma once
2
3/*
4 Copyright 2023, SINTEF Ocean
5 This Source Code Form is subject to the terms of the Mozilla Public
6 License, v. 2.0. If a copy of the MPL was not distributed with this
7 file, You can obtain one at http://mozilla.org/MPL/2.0/.
8*/
9
10#include <memory>
11#include <string>
12#include <vector>
13
14#include <fastdds/dds/topic/IContentFilter.hpp>
15#include <fastdds/dds/topic/TopicDataType.hpp>
16#include <fastrtps/types/DynamicData.h>
17#include <fastrtps/types/DynamicDataFactory.h>
18#include <fastrtps/types/DynamicPubSubType.h>
19#include <fastrtps/types/DynamicTypePtr.h>
20#include <xtypes/xtypes.hpp>
21
22#include "Converter.hpp"
23
24namespace ddsfmu {
25namespace detail {
26
37 FilterMemberType() = delete;
39 const eprosima::fastdds::dds::TopicDataType* data_type, const std::string& type_name)
40 : pubsub_type(nullptr)
41 , dyn_data(nullptr)
42 , key_data(ddsfmu::Converter::dynamic_data(type_name))
43 , sample_data(ddsfmu::Converter::dynamic_data(type_name))
45 , key_count(0) {
46 namespace etypes = eprosima::fastrtps::types;
47 const auto* dynpubsub = dynamic_cast<const etypes::DynamicPubSubType*>(data_type);
48 if (dynpubsub == nullptr) {
49 throw std::runtime_error("Custom filter only works with dynamic types, was unable to cast "
50 "TopicDataType* to DynamicPubSubType* ");
51 }
52
53 eprosima::fastrtps::types::DynamicType_ptr dyn_type = dynpubsub->GetDynamicType();
54 pubsub_type = new eprosima::fastrtps::types::DynamicPubSubType(dyn_type);
55 dyn_data = eprosima::fastrtps::types::DynamicDataFactory::get_instance()->create_data(dyn_type);
56 }
57 eprosima::fastrtps::types::DynamicPubSubType* pubsub_type;
58 eprosima::fastrtps::types::DynamicData* dyn_data;
59 eprosima::xtypes::DynamicData key_data, sample_data;
60 //std::vector<std::function<bool()>> comparisons;
61 size_t key_count;
62 std::string type_name;
63
64 bool compare_keys() {
65 bool is_equal = true;
66 size_t key_a = 0;
67 sample_data.for_each([&](const eprosima::xtypes::DynamicData::ReadableNode& a_node) {
68 bool a_is_leaf = (a_node.type().is_primitive_type() || a_node.type().is_enumerated_type());
69 bool a_is_string = a_node.type().kind() == eprosima::xtypes::TypeKind::STRING_TYPE;
70 if ((a_is_leaf || a_is_string) && a_node.from_member() && a_node.from_member()->is_key()) {
71 size_t key_b = 0;
72 key_data.for_each([&](const eprosima::xtypes::DynamicData::ReadableNode& b_node) {
73 bool b_is_leaf =
74 (b_node.type().is_primitive_type() || b_node.type().is_enumerated_type());
75 bool b_is_string = b_node.type().kind() == eprosima::xtypes::TypeKind::STRING_TYPE;
76 if (
77 (b_is_leaf || b_is_string) && b_node.from_member() && b_node.from_member()->is_key()) {
78 if (key_a == key_b) { is_equal &= (a_node.data() == b_node.data()); }
79 key_b++;
80 }
81 });
82 key_a++;
83 }
84 if (key_a == key_count) {
85 throw false; // all keys compared
86 }
87 });
88 return is_equal;
89 }
90
92 if (pubsub_type) delete pubsub_type;
93 }
94};
95
99class CustomKeyFilter : public eprosima::fastdds::dds::IContentFilter {
100private:
101 std::map<std::string, std::unique_ptr<FilterMemberType>> member_types;
102
103public:
112 const eprosima::fastdds::dds::TopicDataType* data_type, const std::string& type_name,
113 const eprosima::fastdds::dds::LoanableTypedCollection<const char*>& parameters) {
114 if (add_type(data_type, type_name, parameters)) {
115 //std::cout << "Created CustomKeyFilter for " << type_name << std::endl;
116 }
117 }
118
124 inline bool has_reader_GUID(const std::string& guid) {
125 return static_cast<bool>(member_types.count(guid));
126 }
127
135 bool add_type(
136 const eprosima::fastdds::dds::TopicDataType* data_type, const std::string& type_name,
137 const eprosima::fastdds::dds::LoanableTypedCollection<const char*>& parameters);
138
139 virtual ~CustomKeyFilter() = default;
140
150 bool evaluate(
151 const SerializedPayload& payload, const FilterSampleInfo& sample_info,
152 const GUID_t& reader_guid) const override;
153};
154
155}
156}
Custom key filter for dynamic data topics.
Definition: CustomKeyFilter.hpp:99
bool has_reader_GUID(const std::string &guid)
Check if the filter has registered reader with given GUID.
Definition: CustomKeyFilter.hpp:124
virtual ~CustomKeyFilter()=default
bool evaluate(const SerializedPayload &payload, const FilterSampleInfo &sample_info, const GUID_t &reader_guid) const override
Evaluate filter discriminating whether the sample is relevant or not, i.e. whether it meets the filte...
Definition: CustomKeyFilter.cpp:107
bool add_type(const eprosima::fastdds::dds::TopicDataType *data_type, const std::string &type_name, const eprosima::fastdds::dds::LoanableTypedCollection< const char * > &parameters)
Registers a new data type with associated dynamic data type pointer.
Definition: CustomKeyFilter.cpp:13
CustomKeyFilter(const eprosima::fastdds::dds::TopicDataType *data_type, const std::string &type_name, const eprosima::fastdds::dds::LoanableTypedCollection< const char * > &parameters)
Construct a new CustomKeyFilter object.
Definition: CustomKeyFilter.hpp:111
Definition: auxiliaries.cpp:26
Class with functions to convert between xtypes::DynamicData and fast-dds DynamicData.
Definition: Converter.hpp:31
A helper to hold dynamic data type information.
Definition: CustomKeyFilter.hpp:36
eprosima::xtypes::DynamicData sample_data
Definition: CustomKeyFilter.hpp:59
~FilterMemberType()
Definition: CustomKeyFilter.hpp:91
FilterMemberType(const eprosima::fastdds::dds::TopicDataType *data_type, const std::string &type_name)
Definition: CustomKeyFilter.hpp:38
std::string type_name
Definition: CustomKeyFilter.hpp:62
eprosima::fastrtps::types::DynamicPubSubType * pubsub_type
Definition: CustomKeyFilter.hpp:57
eprosima::fastrtps::types::DynamicData * dyn_data
Definition: CustomKeyFilter.hpp:58
eprosima::xtypes::DynamicData key_data
Definition: CustomKeyFilter.hpp:59
bool compare_keys()
Definition: CustomKeyFilter.hpp:64
size_t key_count
Definition: CustomKeyFilter.hpp:61