source: rrlib_rtti_conversion/tCompiledConversionOperation.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.5 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/tCompiledConversionOperation.h
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2016-07-15
27 *
28 * \brief   Contains tCompiledConversionOperation
29 *
30 * \b tCompiledConversionOperation
31 *
32 * Conversion operation compiled from possibly multiple elementary and/or possibly generic ones.
33 * Compiled conversion operations are furthermore optimized for runtime performance.
34 *
35 */
36//----------------------------------------------------------------------
37#ifndef __rrlib__rtti_conversion__tCompiledConversionOperation_h__
38#define __rrlib__rtti_conversion__tCompiledConversionOperation_h__
39
40//----------------------------------------------------------------------
41// External includes (system with <>, local with "")
42//----------------------------------------------------------------------
43
44//----------------------------------------------------------------------
45// Internal includes with ""
46//----------------------------------------------------------------------
47#include "rrlib/rtti_conversion/defined_conversions.h"
48#include "rrlib/rtti_conversion/tConversionOperationSequence.h"
49#include "rrlib/rtti_conversion/tConversionOption.h"
50#include "rrlib/rtti_conversion/tCurrentConversionOperation.h"
51
52//----------------------------------------------------------------------
53// Namespace declaration
54//----------------------------------------------------------------------
55namespace rrlib
56{
57namespace rtti
58{
59namespace conversion
60{
61
62//----------------------------------------------------------------------
63// Forward declarations / typedefs / enums
64//----------------------------------------------------------------------
65
66//----------------------------------------------------------------------
67// Class declaration
68//----------------------------------------------------------------------
69//! Compiled conversion operation
70/*!
71 * Conversion operation compiled from possibly multiple elementary and/or possibly generic ones.
72 * Compiled conversion operations are furthermore optimized for runtime performance.
73 */
74class tCompiledConversionOperation : public tConversionOperationSequence
75{
76
77//----------------------------------------------------------------------
78// Public methods and typedefs
79//----------------------------------------------------------------------
80public:
81
82  /*! Flags for conversion operation */
83  enum tFlag
84  {
85    /*! Info required for execution */
86    cDO_FINAL_DEEPCOPY_AFTER_FIRST_FUNCTION = 1 << 0,  //!< Do final DeepCopy after first conversion function?
87    cDO_FINAL_DEEPCOPY_AFTER_SECOND_FUNCTION = 1 << 1, //!< Do final DeepCopy after second conversion function?
88    cDEEPCOPY_ONLY = 1 << 2,                           //!< True if conversion operation can be performed with a simple memcpy
89    cFIRST_OPERATION_OPTIMIZED_AWAY = 1 << 3,          //!< True if first operation was optimized away (relevant for parameter lookup)
90
91    /*! Result of conversion operation */
92    cRESULT_INDEPENDENT = 1 << 29,                   //!< Conversion can be performed with Convert(source_object, destination_object). Destination does not reference source object.
93    cRESULT_REFERENCES_SOURCE_INTERNALLY = 1 << 30,  //!< Conversion can be performed with Convert(source_object, destination_object). Destination references source object.
94    cRESULT_REFERENCES_SOURCE_DIRECTLY = 1 << 31,    //!< Conversion can be performed with Convert(source_object).
95  };
96
97  tCompiledConversionOperation() : tConversionOperationSequence(), conversion_function_first(nullptr), conversion_function_final(nullptr), fixed_offset_first(0), fixed_offset_final(0), flags(0), destination_pointer_type(&typeid(tTypedPointer))
98  {
99    memset(custom_operation_data_storage, 0, sizeof(custom_operation_data_storage));
100  }
101
102  /*!
103   * Perform actual conversion operation.
104   * Available for any conversion result type. Fills provided destination objects with result.
105   *
106   * \param source_object Typed pointer containing data to convert. Must have source type of this operation.
107   * \param destination_object Typed pointer containing buffer to write converted data to. Its type must be equal to destination_type.
108   *
109   * (note: For performance reasons, in general no type checks are performed.
110   *        The caller is responsible for ensuring that typed pointer point to objects of correct types.)
111   */
112  inline void Convert(const tTypedConstPointer& source_object, const tTypedPointer& destination_object) const
113  {
114    assert(flags & (tFlag::cRESULT_INDEPENDENT | tFlag::cRESULT_REFERENCES_SOURCE_INTERNALLY));
115    tTypedConstPointer intermediate_object(static_cast<const char*>(source_object.GetRawDataPointer()) + fixed_offset_first, type_after_first_fixed_offset); // in case we have a fixed offset and conversion function is a deep copy operation
116    if (flags & tFlag::cDEEPCOPY_ONLY)
117    {
118      destination_object.DeepCopyFrom(intermediate_object);
119    }
120    else
121    {
122      tCurrentConversionOperation current_operation = { *this, 0 };
123      (*conversion_function_first)(intermediate_object, destination_object, current_operation);
124    }
125  }
126
127  /*!
128   * Perform actual conversion operation.
129   * This method is only available if conversion result type is REFERENCES_SOURCE_DIRECTLY.
130   * It returns a direct result to the source object - and therefore does not require any copying.
131   *
132   * \param source_object Source object
133   * \return Destination object (references source object)
134   *
135   * (note: For performance reasons, in general no type checks are performed.
136   *        The caller is responsible for ensuring that typed pointer point to objects of correct types.)
137   */
138  inline tTypedConstPointer Convert(const tTypedConstPointer& source_object) const
139  {
140    assert(flags & tFlag::cRESULT_REFERENCES_SOURCE_DIRECTLY);
141    assert(typeid(tTypedPointer) == *destination_pointer_type && "This convert function required default destination_pointer_type");
142    tTypedConstPointer result(static_cast<const char*>(source_object.GetRawDataPointer()) + fixed_offset_first, type_after_first_fixed_offset);
143    if (get_destination_reference_function_first != nullptr)
144    {
145      tCurrentConversionOperation current_operation = { *this, 0 };
146      result = (*get_destination_reference_function_first)(result, current_operation);
147      if (get_destination_reference_function_final != nullptr)
148      {
149        tCurrentConversionOperation current_operation = { *this, 1 };
150        result = (*get_destination_reference_function_final)(result, current_operation);
151      }
152    }
153    result = tTypedConstPointer(static_cast<const char*>(result.GetRawDataPointer()) + fixed_offset_final, destination_type);
154    return result;
155  }
156
157  /*!
158   * return Type of destination_object used when calling Convert
159   */
160  const std::type_info& DestinationPointerType() const
161  {
162    return *destination_pointer_type;
163  }
164
165  /*!
166   * \return Flags for conversion operation
167   */
168  unsigned int Flags() const
169  {
170    return flags;
171  }
172
173  /*!
174   * \return Data type after first conversion function (possibly == destination_type)
175   */
176  const tType& IntermediateType() const
177  {
178    return intermediate_type;
179  }
180
181//----------------------------------------------------------------------
182// Private fields and methods
183//----------------------------------------------------------------------
184private:
185
186  friend class tConversionOperationSequence;
187  friend struct tCurrentConversionOperation;
188
189  /*! Data type after applying first fixed offset */
190  tType type_after_first_fixed_offset;
191
192  /*! Data type after first conversion function (possibly == destination_type) */
193  tType intermediate_type;
194
195  /*! Final data type */
196  tType destination_type;
197
198  /*!
199   * Function pointers to conversion operations. May be null if conversion is performed in another way.
200   * This is preferred to a std::function object here, as it always has minimal memory and computation overhead.
201   * A std::function might be added as a third option if binding of parameters is required.
202   */
203  union
204  {
205    tConversionOption::tConversionFunction conversion_function_first;
206    tConversionOption::tGetDestinationReferenceFunction get_destination_reference_function_first;
207  };
208  union
209  {
210    tConversionOption::tConversionFunction conversion_function_final;
211    tConversionOption::tGetDestinationReferenceFunction get_destination_reference_function_final;
212  };
213
214  /*!
215   * Fixed offsets. In case a memcpy is possible, the second one is the size.
216   */
217  unsigned int fixed_offset_first, fixed_offset_final;
218
219  /*! Flags for conversion operation */
220  unsigned int flags;
221
222  /*!
223   * Custom operation-specific data (e.g. may be filled during compilation for optimization)
224   * (note: if use cases appear that require more or different data, this should be extended)
225   */
226  char* custom_operation_data_storage[2 * tCustomOperationData::cMAX_SIZE];
227
228  /*! Type of destination_object used calling Convert; may be subclass of tTypedPointer; set when compiling */
229  const std::type_info* destination_pointer_type;
230
231  tCustomOperationData CustomOperationData(size_t index)
232  {
233    return tCustomOperationData(custom_operation_data_storage + index * tCustomOperationData::cMAX_SIZE);
234  }
235  tConstCustomOperationData CustomOperationData(size_t index) const
236  {
237    return tConstCustomOperationData(custom_operation_data_storage + index * tCustomOperationData::cMAX_SIZE);
238  }
239};
240
241
242// defined here to handle cyclic dependency (also very closely coupled to tCompiledConversionOperation)
243inline void tCurrentConversionOperation::Continue(const tTypedConstPointer& intermediate_object, const tTypedPointer& destination_object) const
244{
245  unsigned int next_operation_index = operation_index + 1;
246  if (compiled_operation.flags & next_operation_index)
247  {
248    // Do final DeepCopy
249    tTypedConstPointer intermediate_2(static_cast<const char*>(intermediate_object.GetRawDataPointer()) + compiled_operation.fixed_offset_final, destination_object.GetType());  // in case second operation is a const_offset
250    destination_object.DeepCopyFrom(intermediate_2);
251  }
252  else
253  {
254    // Call second conversion function
255    tCurrentConversionOperation current_operation = { compiled_operation, next_operation_index };
256    (*compiled_operation.conversion_function_final)(intermediate_object, destination_object, current_operation);
257  }
258}
259
260inline tTypedConstPointer tCurrentConversionOperation::GetParameterValue() const
261{
262  return compiled_operation.GetParameterValue((compiled_operation.flags & tCompiledConversionOperation::tFlag::cFIRST_OPERATION_OPTIMIZED_AWAY) ? 1 : operation_index);
263}
264
265inline tConstCustomOperationData tCurrentConversionOperation::GetCustomData() const
266{
267  return compiled_operation.CustomOperationData(operation_index);
268}
269
270
271//----------------------------------------------------------------------
272// End of namespace declaration
273//----------------------------------------------------------------------
274}
275}
276}
277
278
279#endif
Note: See TracBrowser for help on using the repository browser.