1 | // |
---|
2 | // You received this file as part of RRLib |
---|
3 | // Robotics Research Library |
---|
4 | // |
---|
5 | // Copyright (C) Finroc GbR (finroc.org) |
---|
6 | // |
---|
7 | // This program is free software; you can redistribute it and/or modify |
---|
8 | // it under the terms of the GNU General Public License as published by |
---|
9 | // the Free Software Foundation; either version 2 of the License, or |
---|
10 | // (at your option) any later version. |
---|
11 | // |
---|
12 | // This program is distributed in the hope that it will be useful, |
---|
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | // GNU General Public License for more details. |
---|
16 | // |
---|
17 | // You should have received a copy of the GNU General Public License along |
---|
18 | // with this program; if not, write to the Free Software Foundation, Inc., |
---|
19 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
---|
20 | // |
---|
21 | //---------------------------------------------------------------------- |
---|
22 | /*!\file rrlib/rtti_conversion/tConversionOperationSequence.h |
---|
23 | * |
---|
24 | * \author Max Reichardt |
---|
25 | * |
---|
26 | * \date 2015-12-17 |
---|
27 | * |
---|
28 | * \brief Contains tConversionOperationSequence |
---|
29 | * |
---|
30 | * \b tConversionOperationSequence |
---|
31 | * |
---|
32 | * Sequence of conversion operations with a maximum of 2 elements. May be empty. |
---|
33 | * |
---|
34 | */ |
---|
35 | //---------------------------------------------------------------------- |
---|
36 | #ifndef __rrlib__rtti_conversion__tConversionOperationSequence_h__ |
---|
37 | #define __rrlib__rtti_conversion__tConversionOperationSequence_h__ |
---|
38 | |
---|
39 | //---------------------------------------------------------------------- |
---|
40 | // External includes (system with <>, local with "") |
---|
41 | //---------------------------------------------------------------------- |
---|
42 | |
---|
43 | //---------------------------------------------------------------------- |
---|
44 | // Internal includes with "" |
---|
45 | //---------------------------------------------------------------------- |
---|
46 | #include "rrlib/rtti_conversion/tRegisteredConversionOperation.h" |
---|
47 | |
---|
48 | //---------------------------------------------------------------------- |
---|
49 | // Namespace declaration |
---|
50 | //---------------------------------------------------------------------- |
---|
51 | namespace rrlib |
---|
52 | { |
---|
53 | namespace rtti |
---|
54 | { |
---|
55 | namespace conversion |
---|
56 | { |
---|
57 | |
---|
58 | //---------------------------------------------------------------------- |
---|
59 | // Forward declarations / typedefs / enums |
---|
60 | //---------------------------------------------------------------------- |
---|
61 | class tCompiledConversionOperation; |
---|
62 | |
---|
63 | //---------------------------------------------------------------------- |
---|
64 | // Class declaration |
---|
65 | //---------------------------------------------------------------------- |
---|
66 | //! Sequence of conversion operations |
---|
67 | /*! |
---|
68 | * Sequence of conversion operations with a maximum of 2 elements. May be empty. |
---|
69 | * |
---|
70 | * Ratio / implementation note: |
---|
71 | * Advantages compared to using a std::vector: More memory and computationally efficient. |
---|
72 | * Advantages compared to using a std::array: Custom constructors and size() operator. |
---|
73 | */ |
---|
74 | class tConversionOperationSequence |
---|
75 | { |
---|
76 | |
---|
77 | //---------------------------------------------------------------------- |
---|
78 | // Public methods and typedefs |
---|
79 | //---------------------------------------------------------------------- |
---|
80 | public: |
---|
81 | |
---|
82 | /*! Constant for sequence with no conversion operations (may be handy if methods return sequences as const reference) */ |
---|
83 | static const tConversionOperationSequence cNONE; |
---|
84 | |
---|
85 | /*! |
---|
86 | * \param first First conversion operation in chain |
---|
87 | * \param second Second conversion operation in chain (must be nullptr if first is nullptr) |
---|
88 | * \param intermediate_type Needs to be specified if there are two operations (including implicit casts) and first operation has multiple destination types and second has multiple source types |
---|
89 | */ |
---|
90 | tConversionOperationSequence(const tRegisteredConversionOperation& first, const tRegisteredConversionOperation& second, const tType& intermediate_type = tType()) : |
---|
91 | operations {&first, &second}, |
---|
92 | ambiguous_operation_lookup {false, false}, |
---|
93 | intermediate_type(intermediate_type) |
---|
94 | { |
---|
95 | assert(first.SupportedDestinationTypes().single_type || second.SupportedSourceTypes().single_type || intermediate_type); |
---|
96 | } |
---|
97 | tConversionOperationSequence(const tRegisteredConversionOperation& first, const tType& intermediate_type = tType()) : |
---|
98 | operations {&first, nullptr}, |
---|
99 | ambiguous_operation_lookup {false, false}, |
---|
100 | intermediate_type(intermediate_type) |
---|
101 | {} |
---|
102 | tConversionOperationSequence() : |
---|
103 | operations {nullptr, nullptr}, |
---|
104 | ambiguous_operation_lookup {false, false}, |
---|
105 | intermediate_type() |
---|
106 | {} |
---|
107 | |
---|
108 | /*! |
---|
109 | * \param Name of first conversion operation |
---|
110 | * \param Name of second conversion operation (optional) |
---|
111 | * \param intermediate_type Needs to be specified if there are two operations (including implicit casts) |
---|
112 | * \throws Throws std::runtime_error if conversion operations with specified names could not be found |
---|
113 | */ |
---|
114 | tConversionOperationSequence(const std::string& first, const std::string& second = "", const tType& intermediate_type = tType()); |
---|
115 | |
---|
116 | tConversionOperationSequence(const tConversionOperationSequence& other) : |
---|
117 | operations {other.operations[0].operation, other.operations[1].operation}, |
---|
118 | ambiguous_operation_lookup {other.ambiguous_operation_lookup[0], other.ambiguous_operation_lookup[1]}, |
---|
119 | intermediate_type(other.intermediate_type) |
---|
120 | { |
---|
121 | if (other.operations[0].parameter) |
---|
122 | { |
---|
123 | CopyParameter(*other.operations[0].parameter, operations[0].parameter); |
---|
124 | } |
---|
125 | if (other.operations[1].parameter) |
---|
126 | { |
---|
127 | CopyParameter(*other.operations[1].parameter, operations[1].parameter); |
---|
128 | } |
---|
129 | } |
---|
130 | tConversionOperationSequence& operator=(const tConversionOperationSequence & other); |
---|
131 | |
---|
132 | tConversionOperationSequence(tConversionOperationSequence && other) = default; |
---|
133 | tConversionOperationSequence& operator=(tConversionOperationSequence && other) = default; |
---|
134 | |
---|
135 | /*! |
---|
136 | * Compiles conversion operation chain to a single optimized operation. |
---|
137 | * |
---|
138 | * \param allow_reference_to_source May the destination object reference the source? (if not, tConversionResultType is always INDEPENDENT; an additional deep copy operation is possibly inserted) |
---|
139 | * \param source_type Source Type (can be omitted if first operation has fixed source type) |
---|
140 | * \param destination_type Destination Type (can be omitted if last operation has fixed destination type) |
---|
141 | * \param destination_pointer_type Type of destination_object pointer caller provides to Convert function. Custom types allow conversion operations to provide additional information (timestamps are an example). |
---|
142 | * \throw Throws exception if conversion operation sequence erroneous, ambiguous, or cannot be used to convert specified types |
---|
143 | */ |
---|
144 | tCompiledConversionOperation Compile(bool allow_reference_to_source, const tType& source_type = tType(), const tType& destination_type = tType(), const std::type_info& destination_pointer_type = typeid(tTypedPointer)) const; |
---|
145 | |
---|
146 | /*! |
---|
147 | * Get conversion parameter value |
---|
148 | * |
---|
149 | * \param operation_index Index of conversion operation in sequence. 0 or 1 are valid indices. |
---|
150 | * \return Pointer to buffer with parameter if it has been specified (otherwise nullptr -> the conversion operation should use a default value) |
---|
151 | */ |
---|
152 | const tTypedConstPointer& GetParameterValue(size_t operation_index) const |
---|
153 | { |
---|
154 | return operations[operation_index].parameter ? static_cast<const tTypedConstPointer&>(*operations[operation_index].parameter) : cNO_PARAMETER_VALUE; |
---|
155 | } |
---|
156 | |
---|
157 | /*! |
---|
158 | * \return If sequence contains two operations: type after first operation |
---|
159 | */ |
---|
160 | tType IntermediateType() const |
---|
161 | { |
---|
162 | return intermediate_type; |
---|
163 | } |
---|
164 | |
---|
165 | /*! |
---|
166 | * Set conversion parameter value |
---|
167 | * |
---|
168 | * \param operation_index Index of conversion operation in sequence. 0 or 1 are valid indices. |
---|
169 | * \param new_value Pointer to buffer with new parameter value. An empty pointer is also valid in order to reset value to default. |
---|
170 | * \throw Throws std::exception on invalid arguments |
---|
171 | */ |
---|
172 | void SetParameterValue(size_t operation_index, const tTypedConstPointer& new_value); |
---|
173 | |
---|
174 | /*! |
---|
175 | * Set conversion parameter value |
---|
176 | * |
---|
177 | * \param operation_index Index of conversion operation in sequence. 0 or 1 are valid indices. |
---|
178 | * \param new_value Parameter as string. Will be deserialized when operation is compiled. |
---|
179 | * \throw Throws std::exception on invalid arguments |
---|
180 | */ |
---|
181 | void SetParameterValue(size_t operation_index, const std::string& new_value) |
---|
182 | { |
---|
183 | SetParameterValue(operation_index, tTypedConstPointer(&new_value)); |
---|
184 | } |
---|
185 | |
---|
186 | /*! |
---|
187 | * \return Number of conversion operations in chain |
---|
188 | */ |
---|
189 | unsigned int Size() const |
---|
190 | { |
---|
191 | return operations[0].operation == nullptr ? 0 : (operations[1].operation == nullptr ? 1 : 2); |
---|
192 | } |
---|
193 | |
---|
194 | /*! |
---|
195 | * \param Index of conversion operation in sequence. 0 or 1 are valid indices. |
---|
196 | * \return Conversion operation at index. First is name of conversion operation (nullptr if there is no conversion operations at specified index). Second is pointer to conversion operation. May be null, if lookup by name was ambiguous. |
---|
197 | */ |
---|
198 | const std::pair<const char*, const tRegisteredConversionOperation*> operator[](size_t index) const |
---|
199 | { |
---|
200 | return std::pair<const char*, const tRegisteredConversionOperation*>(operations[index].operation ? operations[index].operation->Name() : nullptr, operations[index].operation && (!ambiguous_operation_lookup[index]) ? operations[index].operation : nullptr); |
---|
201 | } |
---|
202 | |
---|
203 | friend bool operator==(const tConversionOperationSequence& lhs, const tConversionOperationSequence& rhs) |
---|
204 | { |
---|
205 | if (lhs.Size() != rhs.Size()) |
---|
206 | { |
---|
207 | return false; |
---|
208 | } |
---|
209 | for (size_t i = 0; i < lhs.Size(); i++) |
---|
210 | { |
---|
211 | if (lhs.ambiguous_operation_lookup[i] != rhs.ambiguous_operation_lookup[i] || (!(lhs.operations[i] == rhs.operations[i]))) |
---|
212 | { |
---|
213 | return false; |
---|
214 | } |
---|
215 | } |
---|
216 | return lhs.Size() < 2 || lhs.intermediate_type == rhs.intermediate_type; |
---|
217 | } |
---|
218 | |
---|
219 | //---------------------------------------------------------------------- |
---|
220 | // Private fields and methods |
---|
221 | //---------------------------------------------------------------------- |
---|
222 | private: |
---|
223 | |
---|
224 | friend serialization::tInputStream& operator >> (serialization::tInputStream& stream, tConversionOperationSequence& sequence); |
---|
225 | |
---|
226 | /*! Data on Single operation in sequence */ |
---|
227 | struct tSingleOperation |
---|
228 | { |
---|
229 | /*! Stores operations */ |
---|
230 | const tRegisteredConversionOperation* operation; |
---|
231 | |
---|
232 | /*! Any parameter of operation */ |
---|
233 | std::unique_ptr<tGenericObject> parameter; |
---|
234 | |
---|
235 | tSingleOperation(const tRegisteredConversionOperation* operation) : operation(operation), parameter() {} |
---|
236 | |
---|
237 | bool operator==(const tSingleOperation& other) const |
---|
238 | { |
---|
239 | return operation == other.operation && (((!parameter) && (!other.parameter)) || (parameter && other.parameter && parameter->Equals(*other.parameter))); |
---|
240 | } |
---|
241 | }; |
---|
242 | |
---|
243 | /*! Operations in sequence */ |
---|
244 | tSingleOperation operations[2]; |
---|
245 | |
---|
246 | /*! Whether name lookup of operation was ambiguous (=> only name of operation is valid; => when compiling, this ambiguity needs to be resolved) */ |
---|
247 | bool ambiguous_operation_lookup[2]; // extra array to reduce memory overhead |
---|
248 | |
---|
249 | /*! If sequence contains two operations: type after first operation (may be ambiguous otherwise) */ |
---|
250 | tType intermediate_type; |
---|
251 | |
---|
252 | /*! Empty pointer - returned for parameter values that have not been set */ |
---|
253 | static const tTypedConstPointer cNO_PARAMETER_VALUE; |
---|
254 | |
---|
255 | /*! |
---|
256 | * Copies parameter |
---|
257 | * |
---|
258 | * \param source Source parameter (may be nullptr, then destination will be reset) |
---|
259 | * \param destination Destination parameter |
---|
260 | */ |
---|
261 | static void CopyParameter(const tTypedConstPointer& source, std::unique_ptr<tGenericObject>& destination); |
---|
262 | }; |
---|
263 | |
---|
264 | |
---|
265 | serialization::tOutputStream& operator << (serialization::tOutputStream& stream, const tConversionOperationSequence& sequence); |
---|
266 | serialization::tInputStream& operator >> (serialization::tInputStream& stream, tConversionOperationSequence& sequence); |
---|
267 | |
---|
268 | //---------------------------------------------------------------------- |
---|
269 | // End of namespace declaration |
---|
270 | //---------------------------------------------------------------------- |
---|
271 | } |
---|
272 | } |
---|
273 | } |
---|
274 | |
---|
275 | |
---|
276 | #endif |
---|