source: rrlib_rtti_conversion/tConversionOperationSequence.h @ 8:b9554b04aa0f

17.03
Last change on this file since 8:b9554b04aa0f was 3:c3f0aa1ccd48, checked in by Max Reichardt <mreichardt@…>, 2 years ago

Fixes bug in construction of tConversionOptions and serialization of tConversionOperationSequence

File size: 11.4 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   * \throw Throws exception if conversion operation sequence erroneous, ambiguous, or cannot be used to convert specified types
142   */
143  tCompiledConversionOperation Compile(bool allow_reference_to_source, const tType& source_type = tType(), const tType& destination_type = tType()) const;
144
145  /*!
146   * Get conversion parameter value
147   *
148   * \param operation_index Index of conversion operation in sequence. 0 or 1 are valid indices.
149   * \return Pointer to buffer with parameter if it has been specified (otherwise nullptr -> the conversion operation should use a default value)
150   */
151  const tTypedConstPointer& GetParameterValue(size_t operation_index) const
152  {
153    return operations[operation_index].parameter ? static_cast<const tTypedConstPointer&>(*operations[operation_index].parameter) : cNO_PARAMETER_VALUE;
154  }
155
156  /*!
157   * \return If sequence contains two operations: type after first operation
158   */
159  tType IntermediateType() const
160  {
161    return intermediate_type;
162  }
163
164  /*!
165   * Set conversion parameter value
166   *
167   * \param operation_index Index of conversion operation in sequence. 0 or 1 are valid indices.
168   * \param new_value Pointer to buffer with new parameter value. An empty pointer is also valid in order to reset value to default.
169   * \throw Throws std::exception on invalid arguments
170   */
171  void SetParameterValue(size_t operation_index, const tTypedConstPointer& new_value);
172
173  /*!
174   * Set conversion parameter value
175   *
176   * \param operation_index Index of conversion operation in sequence. 0 or 1 are valid indices.
177   * \param new_value Parameter as string. Will be deserialized when operation is compiled.
178   * \throw Throws std::exception on invalid arguments
179   */
180  void SetParameterValue(size_t operation_index, const std::string& new_value)
181  {
182    SetParameterValue(operation_index, tTypedConstPointer(&new_value));
183  }
184
185  /*!
186   * \return Number of conversion operations in chain
187   */
188  unsigned int Size() const
189  {
190    return operations[0].operation == nullptr ? 0 : (operations[1].operation == nullptr ? 1 : 2);
191  }
192
193  /*!
194   * \param Index of conversion operation in sequence. 0 or 1 are valid indices.
195   * \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.
196   */
197  const std::pair<const char*, const tRegisteredConversionOperation*> operator[](size_t index) const
198  {
199    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);
200  }
201
202  friend bool operator==(const tConversionOperationSequence& lhs, const tConversionOperationSequence& rhs)
203  {
204    if (lhs.Size() != rhs.Size())
205    {
206      return false;
207    }
208    for (size_t i = 0; i < lhs.Size(); i++)
209    {
210      if (lhs.ambiguous_operation_lookup[i] != rhs.ambiguous_operation_lookup[i] || (!(lhs.operations[i] == rhs.operations[i])))
211      {
212        return false;
213      }
214    }
215    return lhs.Size() < 2 || lhs.intermediate_type == rhs.intermediate_type;
216  }
217
218//----------------------------------------------------------------------
219// Private fields and methods
220//----------------------------------------------------------------------
221private:
222
223  friend serialization::tInputStream& operator >> (serialization::tInputStream& stream, tConversionOperationSequence& sequence);
224
225  /*! Data on Single operation in sequence */
226  struct tSingleOperation
227  {
228    /*! Stores operations */
229    const tRegisteredConversionOperation* operation;
230
231    /*! Any parameter of operation */
232    std::unique_ptr<tGenericObject> parameter;
233
234    tSingleOperation(const tRegisteredConversionOperation* operation) : operation(operation), parameter() {}
235
236    bool operator==(const tSingleOperation& other) const
237    {
238      return operation == other.operation && (((!parameter) && (!other.parameter)) || (parameter && other.parameter && parameter->Equals(*other.parameter)));
239    }
240  };
241
242  /*! Operations in sequence */
243  tSingleOperation operations[2];
244
245  /*! Whether name lookup of operation was ambiguous (=> only name of operation is valid; => when compiling, this ambiguity needs to be resolved) */
246  bool ambiguous_operation_lookup[2];  // extra array to reduce memory overhead
247
248  /*! If sequence contains two operations: type after first operation (may be ambiguous otherwise) */
249  tType intermediate_type;
250
251  /*! Empty pointer - returned for parameter values that have not been set */
252  static const tTypedConstPointer cNO_PARAMETER_VALUE;
253
254  /*!
255   * Copies parameter
256   *
257   * \param source Source parameter (may be nullptr, then destination will be reset)
258   * \param destination Destination parameter
259   */
260  static void CopyParameter(const tTypedConstPointer& source, std::unique_ptr<tGenericObject>& destination);
261};
262
263
264serialization::tOutputStream& operator << (serialization::tOutputStream& stream, const tConversionOperationSequence& sequence);
265serialization::tInputStream& operator >> (serialization::tInputStream& stream, tConversionOperationSequence& sequence);
266
267//----------------------------------------------------------------------
268// End of namespace declaration
269//----------------------------------------------------------------------
270}
271}
272}
273
274
275#endif
Note: See TracBrowser for help on using the repository browser.