OpenDDS  Snapshot(2023/04/28-20:55)
DynamicDataXcdrReadImpl.h
Go to the documentation of this file.
1 /*
2  * Distributed under the OpenDDS License.
3  * See: http://www.opendds.org/license.html
4  */
5 
6 #ifndef OPENDDS_DCPS_XTYPES_DYNAMIC_DATA_XCDR_READ_IMPL_H
7 #define OPENDDS_DCPS_XTYPES_DYNAMIC_DATA_XCDR_READ_IMPL_H
8 
9 #ifndef OPENDDS_SAFETY_PROFILE
10 # include "DynamicDataBase.h"
11 # include "TypeObject.h"
12 
13 # include <dds/DCPS/PoolAllocator.h>
14 # include <dds/DCPS/Sample.h>
15 # include <dds/DCPS/Serializer.h>
16 
18 
19 namespace OpenDDS {
20 namespace XTypes {
21 
23 public:
25 
26  /// This creates a duplicated ACE_Message_Block chain from the provided chain.
27  /// The duplicated chain is released when the object is destroyed. Caller is
28  /// responsible for the release of the input message block chain.
30  const DCPS::Encoding& encoding,
31  DDS::DynamicType_ptr type,
33 
34  /// Use this when you want to pass the alignment state of a given Serializer object over.
35  /// A typical use case would be when a part of the data has already been consumed from
36  /// @a ser and you want to give the remaining to DynamicData.
37  DynamicDataXcdrReadImpl(DCPS::Serializer& ser, DDS::DynamicType_ptr type,
39 
41  DynamicDataXcdrReadImpl& operator=(const DynamicDataXcdrReadImpl& other);
42 
44 
46  DDS::MemberId get_member_id_at_index(ACE_CDR::ULong index);
47  ACE_CDR::ULong get_item_count();
48 
49  DDS::ReturnCode_t clear_all_values();
50  DDS::ReturnCode_t clear_nonkey_values();
51  DDS::ReturnCode_t clear_value(DDS::MemberId id);
52  DDS::DynamicData_ptr loan_value(DDS::MemberId id);
53  DDS::ReturnCode_t return_loaned_value(DDS::DynamicData_ptr value);
54 
55  DDS::DynamicData_ptr clone();
56 
57  DDS::ReturnCode_t get_int32_value(CORBA::Long& value,
58  DDS::MemberId id);
61  {
63  }
64 
65  DDS::ReturnCode_t get_uint32_value(CORBA::ULong& value,
66  DDS::MemberId id);
69  {
71  }
72 
73  DDS::ReturnCode_t get_int8_value(CORBA::Int8& value,
74  DDS::MemberId id);
76  CORBA::Int8)
77  {
79  }
80 
81  DDS::ReturnCode_t get_uint8_value(CORBA::UInt8& value,
82  DDS::MemberId id);
84  CORBA::UInt8)
85  {
87  }
88 
89  DDS::ReturnCode_t get_int16_value(CORBA::Short& value,
90  DDS::MemberId id);
93  {
95  }
96 
97  DDS::ReturnCode_t get_uint16_value(CORBA::UShort& value,
98  DDS::MemberId id);
101  {
103  }
104 
105  DDS::ReturnCode_t get_int64_value_impl(CORBA::LongLong& value, DDS::MemberId id);
108  {
110  }
111 
112  DDS::ReturnCode_t get_uint64_value_impl(CORBA::ULongLong& value, DDS::MemberId id);
115  {
117  }
118 
119  DDS::ReturnCode_t get_float32_value(CORBA::Float& value,
120  DDS::MemberId id);
122  CORBA::Float)
123  {
125  }
126 
127  DDS::ReturnCode_t get_float64_value(CORBA::Double& value,
128  DDS::MemberId id);
131  {
133  }
134 
135  DDS::ReturnCode_t get_float128_value(CORBA::LongDouble& value,
136  DDS::MemberId id);
139  {
141  }
142 
143  DDS::ReturnCode_t get_char8_value(CORBA::Char& value,
144  DDS::MemberId id);
146  CORBA::Char)
147  {
149  }
150 
151  DDS::ReturnCode_t get_char16_value(CORBA::WChar& value,
152  DDS::MemberId id);
154  CORBA::WChar)
155  {
157  }
158 
159  DDS::ReturnCode_t get_byte_value(CORBA::Octet& value,
160  DDS::MemberId id);
162  CORBA::Octet)
163  {
165  }
166 
167  DDS::ReturnCode_t get_boolean_value(CORBA::Boolean& value,
168  DDS::MemberId id);
171  {
173  }
174 
175  DDS::ReturnCode_t get_string_value(char*& value,
176  DDS::MemberId id);
178  const char*)
179  {
181  }
182 
183  DDS::ReturnCode_t get_wstring_value(CORBA::WChar*& value,
184  DDS::MemberId id);
186  const CORBA::WChar*)
187  {
189  }
190 
191  DDS::ReturnCode_t get_complex_value(DDS::DynamicData_ptr& value,
192  DDS::MemberId id);
194  DDS::DynamicData_ptr)
195  {
197  }
198 
199  DDS::ReturnCode_t get_int32_values(DDS::Int32Seq& value,
200  DDS::MemberId id);
202  const DDS::Int32Seq&)
203  {
205  }
206 
207  DDS::ReturnCode_t get_uint32_values(DDS::UInt32Seq& value,
208  DDS::MemberId id);
210  const DDS::UInt32Seq&)
211  {
213  }
214 
215  DDS::ReturnCode_t get_int8_values(DDS::Int8Seq& value,
216  DDS::MemberId id);
218  const DDS::Int8Seq&)
219  {
221  }
222 
223  DDS::ReturnCode_t get_uint8_values(DDS::UInt8Seq& value,
224  DDS::MemberId id);
226  const DDS::UInt8Seq&)
227  {
229  }
230 
231  DDS::ReturnCode_t get_int16_values(DDS::Int16Seq& value,
232  DDS::MemberId id);
234  const DDS::Int16Seq&)
235  {
237  }
238 
239  DDS::ReturnCode_t get_uint16_values(DDS::UInt16Seq& value,
240  DDS::MemberId id);
242  const DDS::UInt16Seq&)
243  {
245  }
246 
247  DDS::ReturnCode_t get_int64_values(DDS::Int64Seq& value,
248  DDS::MemberId id);
250  const DDS::Int64Seq&)
251  {
253  }
254 
255  DDS::ReturnCode_t get_uint64_values(DDS::UInt64Seq& value,
256  DDS::MemberId id);
258  const DDS::UInt64Seq&)
259  {
261  }
262 
263  DDS::ReturnCode_t get_float32_values(DDS::Float32Seq& value,
264  DDS::MemberId id);
266  const DDS::Float32Seq&)
267  {
269  }
270 
271  DDS::ReturnCode_t get_float64_values(DDS::Float64Seq& value,
272  DDS::MemberId id);
274  const DDS::Float64Seq&)
275  {
277  }
278 
279  DDS::ReturnCode_t get_float128_values(DDS::Float128Seq& value,
280  DDS::MemberId id);
282  const DDS::Float128Seq&)
283  {
285  }
286 
287  DDS::ReturnCode_t get_char8_values(DDS::CharSeq& value,
288  DDS::MemberId id);
290  const DDS::CharSeq&)
291  {
293  }
294 
295  DDS::ReturnCode_t get_char16_values(DDS::WcharSeq& value,
296  DDS::MemberId id);
298  const DDS::WcharSeq&)
299  {
301  }
302 
303  DDS::ReturnCode_t get_byte_values(DDS::ByteSeq& value,
304  DDS::MemberId id);
306  const DDS::ByteSeq&)
307  {
309  }
310 
311  DDS::ReturnCode_t get_boolean_values(DDS::BooleanSeq& value,
312  DDS::MemberId id);
314  const DDS::BooleanSeq&)
315  {
317  }
318 
319  DDS::ReturnCode_t get_string_values(DDS::StringSeq& value,
320  DDS::MemberId id);
322  const DDS::StringSeq&)
323  {
325  }
326 
327  DDS::ReturnCode_t get_wstring_values(DDS::WstringSeq& value,
328  DDS::MemberId id);
330  const DDS::WstringSeq&)
331  {
333  }
334 
335  DDS::DynamicType_ptr type();
336 
337  bool check_xcdr1_mutable(DDS::DynamicType_ptr dt);
338 
339  CORBA::Boolean equals(DDS::DynamicData_ptr other);
340 
341 #ifndef OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE
342  DDS::ReturnCode_t get_simple_value(DCPS::Value& value, DDS::MemberId id);
343 #endif
344 
345 private:
346 
348  public:
350  : dd_(dd)
351  , dup_(dd_.chain_->duplicate())
352  {
353  dd_.setup_stream(dup_.get());
354  }
355 
357  {
358  dd_.release_chains();
359  }
360 
361  private:
364  };
365 
366  void copy(const DynamicDataXcdrReadImpl& other);
367 
368  /// Skip the whole data corresponding to this type if it is a struct or union.
369  /// This is called by a containing type when it wants to skip a member which
370  /// is an object of this type.
371  bool skip_all();
372 
373  /// Setup the strm_ object so that it has the correct alignment state.
374  ///
375  void setup_stream(ACE_Message_Block* chain);
376 
377  /// Reading a single value as a given type. For instance, an enum with bit bound
378  /// of 32 is read as an 32-bit integer and thus TK_INT32 should be passed to @a tk.
379  template<typename ValueType>
380  bool read_value(ValueType& value, TypeKind tk);
381 
382  /// Check if a member with a given id is excluded from struct sample.
383  bool exclude_struct_member(MemberId id, DDS::MemberDescriptor_var& md) const;
384 
385  /// Check if a member with a given Id is excluded from a union sample.
386  bool exclude_union_member(MemberId id) const;
387 
388  ///@{
389  /** Reading a value of type primitive, string, or wstring as a member of a struct, union,
390  * or a collection (sequence, array, map). TK_ENUM should be passed to @a enum_or_bitmask
391  * if @value is a 8-bit, 16-bit, or 32-bit signed integer type. In that case, @lower and
392  * @upper should be set to form the bit_bound range of the enum type that matches
393  * the number of bits of @a value. For instance, if we are reading a 8-bit integer, then
394  * @enum_or_bitmask is TK_ENUM, @a lower is 1 and @a upper is 8. This allows reading
395  * an enum with a particular bit bound as an integer with the matching size.
396  * Similarly, if we are reading an unsigned integer, set @a enum_or_bitmask to TK_BITMASK,
397  * and @a lower and @a upper to form a corresponding range for the bitmask's bit bound.
398  */
399  template<TypeKind MemberTypeKind, typename MemberType>
400  DDS::ReturnCode_t get_value_from_struct(
401  MemberType& value, MemberId id, TypeKind enum_or_bitmask = TK_NONE,
402  LBound lower = 0, LBound upper = 0);
403 
404  template<TypeKind MemberTypeKind, typename MemberType>
405  DDS::ReturnCode_t get_value_from_union(
406  MemberType& value, MemberId id, TypeKind enum_or_bitmask = TK_NONE,
407  LBound lower = 0, LBound upper = 0);
408 
409  template<TypeKind ElementTypeKind, typename ElementType>
410  bool get_value_from_collection(ElementType& value, MemberId id, TypeKind collection_tk,
411  TypeKind enum_or_bitmask = TK_NONE,
412  LBound lower = 0,
413  LBound upper = 0);
414  ///@}
415 
416  /// Read a single value of type primitive (except char8, char16, and boolean), string,
417  /// or wstring.
418  template<TypeKind ValueTypeKind, typename ValueType>
419  DDS::ReturnCode_t get_single_value(ValueType& value, MemberId id,
420  TypeKind enum_or_bitmask = TK_NONE,
421  LBound lower = 0,
422  LBound upper = 0);
423 
424  /// Common method to read a single char8 or char16 value.
425  template<TypeKind CharKind, TypeKind StringKind, typename ToCharT, typename CharT>
426  DDS::ReturnCode_t get_char_common(CharT& value, MemberId id);
427 
428  template<typename UIntType, TypeKind UIntTypeKind>
429  bool get_boolean_from_bitmask(ACE_CDR::ULong index, ACE_CDR::Boolean& value);
430 
431  /// Skip to a member with a given ID in a struct.
432  ///
433  DDS::ReturnCode_t skip_to_struct_member(DDS::MemberDescriptor* member_desc, MemberId id);
434 
435  bool get_from_struct_common_checks(const DDS::MemberDescriptor_var& md, MemberId id,
436  TypeKind kind, bool is_sequence = false);
437 
438  /// Return the member descriptor for the selected member from a union data or null.
439  DDS::MemberDescriptor* get_union_selected_member();
440 
441  DDS::MemberDescriptor* get_from_union_common_checks(MemberId id, const char* func_name);
442 
443  ///@{
444  /** Skip to an element with a given ID in a sequence or array, or skip the entire collection. */
445  bool skip_to_sequence_element(MemberId id, DDS::DynamicType_ptr coll_type = 0);
446  bool skip_to_array_element(MemberId id, DDS::DynamicType_ptr coll_type = 0);
447  ///@}
448 
449  /// Skip to an element with a given ID in a map. The key associated with that
450  /// element is also skipped.
451  bool skip_to_map_element(MemberId id);
452 
453  /// Read a sequence with element type @a elem_tk and store the result in @a value,
454  /// which is a sequence of primitives or strings or wstrings. Sequence of enums or
455  /// bitmasks are read as a sequence of signed and unsigned integers, respectively.
456  /// In that case, @a elem_tk is set to TK_ENUM or TK_BITMASK.
457  template<typename SequenceType>
458  bool read_values(SequenceType& value, TypeKind elem_tk);
459 
460  ///@{
461  /** Templates for reading a sequence of primitives, strings or wstrings
462  * as a member (or an element) of a given containing type. See get_value_from_struct
463  * and the similar methods for the use of @a enum_or_bitmask, @a lower, @a upper.
464  */
465  template<TypeKind ElementTypeKind, typename SequenceType>
466  DDS::ReturnCode_t get_values_from_struct(
467  SequenceType& value, MemberId id, TypeKind enum_or_bitmask, LBound lower, LBound upper);
468 
469  template<TypeKind ElementTypeKind, typename SequenceType>
470  bool get_values_from_union(SequenceType& value, MemberId id,
471  TypeKind enum_or_bitmask, LBound lower, LBound upper);
472 
473  template<TypeKind ElementTypeKind, typename SequenceType>
474  bool get_values_from_sequence(SequenceType& value, MemberId id,
475  TypeKind enum_or_bitmask, LBound lower, LBound upper);
476 
477  template<TypeKind ElementTypeKind, typename SequenceType>
478  bool get_values_from_array(SequenceType& value, MemberId id,
479  TypeKind enum_or_bitmask, LBound lower, LBound upper);
480 
481  template<TypeKind ElementTypeKind, typename SequenceType>
482  bool get_values_from_map(SequenceType& value, MemberId id,
483  TypeKind enum_or_bitmask, LBound lower, LBound upper);
484  ///@}
485 
486  /// Common method to read a value sequence of any type (primitive, string, wstring).
487  template<TypeKind ElementTypeKind, typename SequenceType>
488  DDS::ReturnCode_t get_sequence_values(SequenceType& value, MemberId id,
489  TypeKind enum_or_bitmask = TK_NONE,
490  LBound lower = 0,
491  LBound upper = 0);
492 
493  bool skip(const char* func_name, const char* description, size_t n, int size = 1);
494 
495  bool read_discriminator(const DDS::DynamicType_ptr disc_type, DDS::ExtensibilityKind union_ek, ACE_CDR::Long& label);
496 
497  /// Skip a member of a final or appendable struct at the given index.
498  ///
499  bool skip_struct_member_at_index(ACE_CDR::ULong index, ACE_CDR::ULong& num_skipped);
500 
501  /// Skip a member with the given type. The member can be a part of any containing type,
502  /// such as a member in a struct or union, an element in a sequence or array, etc.
503  /// Note that this assumes any header preceding this type, e.g. EMHEADER if this is
504  /// a member of a mutable struct, is already consumed, and the read pointer is pointing
505  /// to the actual data of the member.
506  bool skip_member(DDS::DynamicType_ptr member_type);
507 
508  ///@{
509  /** Skip a member which is a sequence, array, or map. */
510  bool skip_sequence_member(DDS::DynamicType_ptr type);
511  bool skip_array_member(DDS::DynamicType_ptr type);
512  bool skip_map_member(DDS::DynamicType_ptr type);
513  ///@}
514 
515  /// Skip a non-primitive collection member. That is, a sequence or an array of non-primitive
516  /// elements, or a map with at least either key type or value type is non-primitive.
517  bool skip_collection_member(DDS::DynamicType_ptr coll_type);
518 
519  /// Skip a member which is a structure or a union.
520  bool skip_aggregated_member(DDS::DynamicType_ptr type);
521 
522  void release_chains();
523 
524  bool get_primitive_size(DDS::DynamicType_ptr dt, ACE_CDR::ULong& size) const;
525 
526  bool has_optional_member(bool& has_optional) const;
527 
528  /// A set of strings used to prevent infinite recursion when checking for XCDR1 Mutable
529  typedef OPENDDS_SET(DCPS::String) DynamicTypeNameSet;
530  bool check_xcdr1_mutable_i(DDS::DynamicType_ptr dt, DynamicTypeNameSet& dtns);
531 
532  typedef OPENDDS_VECTOR(ACE_Message_Block*) IntermediateChains;
533  const IntermediateChains& get_intermediate_chains() const { return chains_to_release; }
534 
535  /// A duplicate of the original message block chain passed from the constructor.
536  /// This is released in the destructor.
538 
541 
542  /// Indicate whether the alignment state of a Serializer object associated
543  /// with this DynamicData needs to be reset.
545 
546  /// The alignment state that a Serializer object associated with this DynamicData
547  /// object will be set to.
549 
550  /// Each public interface creates a new Serializer object with a message block
551  /// chain that is a duplicate from chain_.
553 
554  /// Message block chains created during each get_*_value or get_*_values method's
555  /// execution that need to be released when the method ends. Those chains are created
556  /// when the method skips a nested aggregated type (i.e., struct and union) by
557  /// calling skip_aggregated_member().
558  IntermediateChains chains_to_release;
559 
560  static const ACE_CDR::ULong ITEM_COUNT_INVALID = ACE_UINT32_MAX;
561 
562  /// Cache the number of items (i.e., members or elements) in the data it holds.
564 };
565 
566 OpenDDS_Dcps_Export bool print_dynamic_data(DDS::DynamicData_ptr dd,
567  DCPS::String& type_string,
568  DCPS::String& indent);
569 
570 } // namespace XTypes
571 } // namespace OpenDDS
572 
574 
575 #endif // OPENDDS_SAFETY_PROFILE
576 
577 #endif // OPENDDS_DCPS_XTYPES_DYNAMIC_DATA_XCDR_READ_IMPL_H
ACE_CDR::Long Long
sequence< unsigned short > UInt16Seq
sequence< long > Int32Seq
ACE_CDR::ULong MemberId
Definition: TypeObject.h:910
DDS::ReturnCode_t set_wstring_values(DDS::MemberId, const DDS::WstringSeq &)
sequence< wchar > WcharSeq
const LogLevel::Value value
Definition: debug.cpp:61
DDS::ReturnCode_t set_float128_value(DDS::MemberId, CORBA::LongDouble)
std::string String
DDS::ReturnCode_t set_uint64_value(DDS::MemberId, CORBA::ULongLong)
DDS::ReturnCode_t set_float64_values(DDS::MemberId, const DDS::Float64Seq &)
sequence< char > CharSeq
sequence< long long > Int64Seq
DDS::ReturnCode_t set_int32_values(DDS::MemberId, const DDS::Int32Seq &)
ACE_CDR::LongLong LongLong
DDS::ReturnCode_t set_uint32_values(DDS::MemberId, const DDS::UInt32Seq &)
#define OpenDDS_Dcps_Export
Definition: dcps_export.h:24
DDS::ReturnCode_t set_boolean_value(DDS::MemberId, CORBA::Boolean)
ACE_CDR::Short Short
DDS::ReturnCode_t set_uint16_value(DDS::MemberId, CORBA::UShort)
DDS::ReturnCode_t set_float128_values(DDS::MemberId, const DDS::Float128Seq &)
DDS::ReturnCode_t set_byte_values(DDS::MemberId, const DDS::ByteSeq &)
DDS::ReturnCode_t set_float64_value(DDS::MemberId, CORBA::Double)
DDS::ReturnCode_t set_byte_value(DDS::MemberId, CORBA::Octet)
DDS::ReturnCode_t set_char16_values(DDS::MemberId, const DDS::WcharSeq &)
DDS::ReturnCode_t set_int64_value(DDS::MemberId, CORBA::LongLong)
DDS::ReturnCode_t set_int32_value(DDS::MemberId, CORBA::Long)
DDS::ReturnCode_t set_int8_values(DDS::MemberId, const DDS::Int8Seq &)
DDS::ReturnCode_t set_char8_values(DDS::MemberId, const DDS::CharSeq &)
ACE_CDR::ULongLong ULongLong
sequence< short > Int16Seq
DDS::ReturnCode_t set_int16_values(DDS::MemberId, const DDS::Int16Seq &)
DDS::ReturnCode_t set_wstring_value(DDS::MemberId, const CORBA::WChar *)
DDS::ReturnCode_t set_int64_values(DDS::MemberId, const DDS::Int64Seq &)
ACE_CDR::Octet TypeKind
Definition: TypeObject.h:210
DDS::ReturnCode_t set_uint8_values(DDS::MemberId, const DDS::UInt8Seq &)
sequence< unsigned long long > UInt64Seq
sequence< boolean > BooleanSeq
ACE_CDR::ULong ULong
typedef OPENDDS_VECTOR(MemberPair) MatchedSet
Class to serialize and deserialize data for DDS.
Definition: Serializer.h:369
DDS::ReturnCode_t set_char8_value(DDS::MemberId, CORBA::Char)
DDS::ReturnCode_t set_boolean_values(DDS::MemberId, const DDS::BooleanSeq &)
sequence< uint8 > UInt8Seq
DDS::ReturnCode_t set_float32_value(DDS::MemberId, CORBA::Float)
ACE_CDR::Boolean Boolean
sequence< octet > ByteSeq
sequence< unsigned long > UInt32Seq
DDS::ReturnCode_t set_float32_values(DDS::MemberId, const DDS::Float32Seq &)
ACE_CDR::UShort UShort
sequence< long double > Float128Seq
DDS::ReturnCode_t set_uint16_values(DDS::MemberId, const DDS::UInt16Seq &)
sequence< float > Float32Seq
ACE_UINT32 ULong
DDS::ReturnCode_t set_int16_value(DDS::MemberId, CORBA::Short)
DDS::ReturnCode_t set_complex_value(DDS::MemberId, DDS::DynamicData_ptr)
typedef OPENDDS_SET(DynamicTypePtrPair) DynamicTypePtrPairSeen
const IntermediateChains & get_intermediate_chains() const
DDS::ReturnCode_t set_uint32_value(DDS::MemberId, CORBA::ULong)
DDS::ReturnCode_t set_uint64_values(DDS::MemberId, const DDS::UInt64Seq &)
ACE_INT32 Long
ExtensibilityKind
DDS::ReturnCode_t set_uint8_value(DDS::MemberId, CORBA::UInt8)
sequence< wstring > WstringSeq
ACE_CDR::Char Char
DDS::ReturnCode_t copy(DDS::DynamicData_ptr dest, DDS::DynamicData_ptr src)
ACE_CDR::Octet Octet
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
DDS::ReturnCode_t set_char16_value(DDS::MemberId, CORBA::WChar)
const ReturnCode_t RETCODE_UNSUPPORTED
ACE_CDR::WChar WChar
DDS::ReturnCode_t set_string_value(DDS::MemberId, const char *)
sequence< int8 > Int8Seq
ACE_CDR::ULong LBound
Definition: TypeObject.h:312
DDS::ReturnCode_t set_int8_value(DDS::MemberId, CORBA::Int8)
const DCPS::Encoding encoding(DCPS::Encoding::KIND_UNALIGNED_CDR, DCPS::ENDIAN_BIG)
const TypeKind TK_NONE
Definition: TypeObject.h:213
bool Boolean
sequence< double > Float64Seq
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28
ACE_CDR::ULong item_count_
Cache the number of items (i.e., members or elements) in the data it holds.
#define ACE_UINT32_MAX
sequence< string > StringSeq
Definition: DdsDcpsCore.idl:50
DDS::ReturnCode_t set_string_values(DDS::MemberId, const DDS::StringSeq &)
bool print_dynamic_data(DDS::DynamicData_ptr dd, DCPS::String &type_string, DCPS::String &indent)