source: rrlib_rtti_conversion/tConversionOperationSequence.h @ 49:cdd4cf3eda0c

17.03 tip
Last change on this file since 49:cdd4cf3eda0c was 49:cdd4cf3eda0c, checked in by Max Reichardt <mreichardt@…>, 12 months ago

Allows to specify destination object pointer type passed to Convert function. Custom types may allow conversion operations to provide additional information (timestamps are an example).

File size: 11.7 KB
Line 
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//----------------------------------------------------------------------
51namespace rrlib
52{
53namespace rtti
54{
55namespace conversion
56{
57
58//----------------------------------------------------------------------
59// Forward declarations / typedefs / enums
60//----------------------------------------------------------------------
61class 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 */
74class tConversionOperationSequence
75{
76
77//----------------------------------------------------------------------
78// Public methods and typedefs
79//----------------------------------------------------------------------
80public:
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//----------------------------------------------------------------------
222private:
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
265serialization::tOutputStream& operator << (serialization::tOutputStream& stream, const tConversionOperationSequence& sequence);
266serialization::tInputStream& operator >> (serialization::tInputStream& stream, tConversionOperationSequence& sequence);
267
268//----------------------------------------------------------------------
269// End of namespace declaration
270//----------------------------------------------------------------------
271}
272}
273}
274
275
276#endif
Note: See TracBrowser for help on using the repository browser.