- HandlerMinelayerData: BUILD_RTI Guards für RTI-Abhängigkeiten - svcTabCommon: Export-Header-Fix via Fallback-Target - TrainingAreaBase: Stub-Header für BUILD_RTI=OFF - ddsfts: Include-Pfad und Dependency-Fixes - BUILD_RTI=OFF Compilation vollständig unterstützt Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Entire-Checkpoint: 01M0JNZA586SACX1PRZ2DJAE5S
1204 lines
36 KiB
C++
1204 lines
36 KiB
C++
/*
|
|
(c) Copyright, Real-Time Innovations, 2018.
|
|
All rights reserved.
|
|
|
|
No duplications, whole or partial, manual or electronic, may be made
|
|
without express written permission. Any such copies, or
|
|
revisions thereof, must display this notice unaltered.
|
|
This code contains trade secrets of Real-Time Innovations, Inc.
|
|
*/
|
|
|
|
#ifndef RTI_DDS_FLAT_FLATOFFSETS_HPP_
|
|
#define RTI_DDS_FLAT_FLATOFFSETS_HPP_
|
|
|
|
#include "xcdr/xcdr_stream.h"
|
|
#include "xcdr/xcdr_stream_impl.h"
|
|
#include "xcdr/xcdr_interpreter.h"
|
|
|
|
#include "rti/xcdr/Stream.hpp"
|
|
|
|
/**
|
|
* @defgroup RTIFlatOffsetsModule FlatData Offsets
|
|
* @ingroup RTIFlatDataModule
|
|
* @brief Offsets provide access to the members of a FlatData Sample
|
|
*
|
|
* An Offset represents a position within a
|
|
* \ref RTIFlatSampleModule "FlatData Sample" that allows accessing a member
|
|
* of that Sample, or the Sample's \ref rti::flat::Sample::root "root".
|
|
*
|
|
* Offsets can be described as <b>iterators</b>. They represent a position in a
|
|
* buffer, not the value itself. As such, they're lightweight objects that can
|
|
* be copied to point to the same data.
|
|
*
|
|
* There are the following Offset types to access the different IDL types:
|
|
*
|
|
* <table>
|
|
* <tr>
|
|
* <th>Category</th>
|
|
* <th>Offset type</th>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>User types</td>
|
|
* <td> For example: <ul>
|
|
* <li> MyFlatFinalOffset, an Offset to a final struct </li>
|
|
* <li> MyFlatMutableOffset, an Offset to a mutable struct </li>
|
|
* <li> MyFlatUnionOffset, an Offset to a union </li>
|
|
* </ul> </td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>Arrays</td>
|
|
* <td><ul>
|
|
* <li>rti::flat::PrimitiveArrayOffset</li>
|
|
* <li>rti::flat::FinalArrayOffset (array of final elements in a final type) </li>
|
|
* <li>rti::flat::FinalAlignedArrayOffset (array of final elements in a mutable type) </li>
|
|
* <li>rti::flat::MutableArrayOffset</li>
|
|
* </ul></td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>Sequences</td>
|
|
* <td><ul>
|
|
* <li>rti::flat::PrimitiveSequenceOffset</li>
|
|
* <li>rti::flat::SequenceOffset</li>
|
|
* </ul></td>
|
|
* </tr>
|
|
* <tr>
|
|
* <td>Primitive types</td>
|
|
* <td><ul>
|
|
* <li>The type itself, such as \p double</li>
|
|
* <li>rti::flat::PrimitiveOffset (when the member is optional)</li>
|
|
* </ul></td>
|
|
* </tr>
|
|
* </table>
|
|
*
|
|
* Offsets for user types are generated by \nddsgen and provide methods to
|
|
* access the type's members by their names. Offsets for arrays and sequences
|
|
* provide methods to access each element.
|
|
*
|
|
* Some offsets allow accessing the data through a pointer to the equivalent plain
|
|
* C++ type, which generally provides better performance. See rti::flat::plain_cast().
|
|
*
|
|
* @section OffsetErrorManagement Offset Error Management
|
|
* Functions that return an Offset may return a "null" Offset (one such that
|
|
* \ref rti::flat::OffsetBase::is_null "is_null()" returns \p true).
|
|
*
|
|
* An Offset may be null if a member doesn't exist in the \ref
|
|
* RTIFlatSampleModule "Sample". For example, if the member 'my_final' in
|
|
* \ref MyFlatMutable doesn't exist (because it wasn't added while building the
|
|
* Sample, or because it wasn't received in the subscribing application),
|
|
* MyFlatMutableOffset::my_final() returns an null Offset. Note that a
|
|
* <b>member in a final type</b> (for example, MyFlatFinalOffset::my_complex())
|
|
* always exists, except in the case of an error.
|
|
*
|
|
* \if CPP_LANGUAGE_ONLY
|
|
* In addition to that, a function may return a null Offset for any error
|
|
* condition.
|
|
* \endif
|
|
*
|
|
* \if CPP2_LANGUAGE_ONLY
|
|
* Other than that, any error condition will cause one of the following
|
|
* exceptions, not a null Offset:
|
|
* - dds::core::NullReferenceError, when accessing a null Offset
|
|
* - dds::core::PreconditionNotMetError, for any precondition failure.
|
|
* - dds::core::OutOfResourcesError, when a \ref RTIFlatBuildersModule "Builder"
|
|
* runs out of space while adding a member.
|
|
* \endif
|
|
*
|
|
*/
|
|
|
|
#ifdef DOXYGEN_DOCUMENTATION_ONLY
|
|
|
|
/**
|
|
* @ingroup RTIFlatOffsetsModule
|
|
* @brief Represents the Offset to an arbitrary user-defined FlatData final
|
|
* IDL struct
|
|
*
|
|
* This example type represents the Offset type that \nddsgen would generate
|
|
* for \ref MyFlatFinal.
|
|
*
|
|
* It provides accessors for each of its members. Accessors can return other
|
|
* Offsets or primitive values.
|
|
*
|
|
* An Offset to a final type may meet the requirements to be cast to its
|
|
* equivalent plain C++ type (see rti::flat::plain_cast()).
|
|
*
|
|
*/
|
|
class MyFlatFinalOffset : public rti::flat::FinalOffset<MyFlatFinalOffset> {
|
|
public:
|
|
/**
|
|
* @brief The equivalent read-only Offset type
|
|
*
|
|
* Each Offset for a user type has an equivalent const Offset that doesn't
|
|
* provide the methods to modify the Sample. \if CPP2_LANGUAGE_ONLY
|
|
* For example, when reading data from a \idref_DataReader, a const Sample's
|
|
* Sample::root() function returns a const Offset.\endif
|
|
*/
|
|
typedef MyFlatFinalConstOffset ConstOffset;
|
|
|
|
/**
|
|
* @brief Creates a null Offset
|
|
*
|
|
* @post is_null()
|
|
*/
|
|
MyFlatFinalOffset()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @brief Retrieves the value for a primitive member
|
|
*/
|
|
int32_t my_primitive() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a complex member
|
|
*
|
|
* FlatFinalBar is another arbitrary user-defined final FlatData type.
|
|
*/
|
|
FlatFinalBar::ConstOffset my_complex() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a primitive array
|
|
*/
|
|
const rti::flat::PrimitiveArrayOffset<int32_t, 10> my_primitive_array() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a complex array
|
|
*/
|
|
rti::flat::FinalArrayOffset<FlatFinalBar::ConstOffset, 10> my_complex_array() const;
|
|
|
|
/**
|
|
* @brief Sets the value for a primitive member
|
|
*/
|
|
bool my_primitive(int32_t value);
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a complex member
|
|
*
|
|
* FlatFinalBar is another arbitrary user-defined final FlatData type.
|
|
*/
|
|
FlatFinalBar::Offset my_complex();
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a primitive array
|
|
*/
|
|
rti::flat::PrimitiveArrayOffset<int32_t, 10> my_primitive_array();
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a complex array
|
|
*/
|
|
rti::flat::FinalArrayOffset<FlatFinalBar::Offset, 10> my_complex_array();
|
|
};
|
|
|
|
/**
|
|
* @ingroup RTIFlatOffsetsModule
|
|
* @brief Represents the Offset to an arbitrary user-defined FlatData
|
|
* mutable IDL struct
|
|
*
|
|
* This example type represents the Offset type that \nddsgen would generate
|
|
* for \ref MyFlatMutable.
|
|
*
|
|
* It provides accessors for each of its members. Accessors can return other
|
|
* Offsets or primitive values.
|
|
*
|
|
*/
|
|
class NDDSUSERDllExport MyFlatMutableOffset : public rti::flat::MutableOffset {
|
|
public:
|
|
/**
|
|
* @brief The equivalent read-only Offset type
|
|
*
|
|
* Each Offset for a user type has an equivalent const Offset that doesn't
|
|
* allow modifying the underlying Sample. \if CPP2_LANGUAGE_ONLY
|
|
* For example, when reading data from a \idref_DataReader, a const Sample's
|
|
* Sample::root() function returns a const Offset.\endif
|
|
*/
|
|
typedef MyFlatMutableConstOffset ConstOffset;
|
|
|
|
/**
|
|
* @brief Creates a null Offset
|
|
*
|
|
* @post is_null()
|
|
*/
|
|
MyFlatMutableOffset()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @brief Retrieves the value for a primitive member
|
|
*
|
|
* @return The value of the member or its default value if this member
|
|
* doesn't exist in this Sample.
|
|
*/
|
|
int32_t my_primitive() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to an optional primitive
|
|
*
|
|
* Unlike the non-optional my_primitive(), which accesses the integer
|
|
* directly, for an optional primitive it is possible to check whether it
|
|
* exists or not. If it doesn't exist, the Offset this function returns
|
|
* will be null (\p is_null()).
|
|
*/
|
|
rti::flat::PrimitiveConstOffset<int32_t> my_optional_primitive() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a primitive array
|
|
*/
|
|
const rti::flat::PrimitiveArrayOffset<int32_t, 10> my_primitive_array() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a primitive sequence
|
|
*/
|
|
const rti::flat::PrimitiveSequenceOffset<int32_t> my_primitive_seq() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a complex member
|
|
*/
|
|
MyFlatFinal::ConstOffset my_final() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a complex array
|
|
*/
|
|
rti::flat::FinalAlignedArrayOffset<MyFlatFinal::ConstOffset, 10> my_final_array() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a complex sequence
|
|
*/
|
|
rti::flat::SequenceOffset<MyFlatFinal::ConstOffset> my_final_seq() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a complex member
|
|
*
|
|
* FlatMutableBar is another arbitrary user-defined mutable FlatData type.
|
|
*/
|
|
FlatMutableBar::ConstOffset my_mutable() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a complex array
|
|
*/
|
|
rti::flat::MutableArrayOffset<FlatMutableBar::ConstOffset, 10> my_mutable_array() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a complex sequence
|
|
*/
|
|
rti::flat::SequenceOffset<FlatMutableBar::ConstOffset> my_mutable_seq() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a string
|
|
*/
|
|
const rti::flat::StringOffset my_string() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a sequence of strings
|
|
*/
|
|
rti::flat::SequenceOffset<const rti::flat::StringOffset> my_string_seq() const;
|
|
|
|
/**
|
|
* @brief Sets the value of a primitive member
|
|
*/
|
|
bool my_primitive(int32_t value);
|
|
|
|
/* @brief Retrieves a non-const Offset to an optional primitive
|
|
*
|
|
* Unlike the non-optional my_primitive(), which allows accessing the integer
|
|
* directly, an optional primitive may not exist. If it doesn't, the Offset
|
|
* this function returns will be null (\p is_null()).
|
|
*/
|
|
rti::flat::PrimitiveOffset<int32_t> my_optional_primitive();
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a primitive array
|
|
*/
|
|
rti::flat::PrimitiveArrayOffset<int32_t, 10> my_primitive_array();
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a primitive sequence
|
|
*/
|
|
rti::flat::PrimitiveSequenceOffset<int32_t> my_primitive_seq();
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a complex member
|
|
*/
|
|
MyFlatFinal::Offset my_final();
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a complex array
|
|
*/
|
|
rti::flat::FinalAlignedArrayOffset<MyFlatFinal::Offset, 10> my_final_array();
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a complex sequence
|
|
*/
|
|
rti::flat::SequenceOffset<MyFlatFinal::Offset> my_final_seq();
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a complex member
|
|
*
|
|
* FlatMutableBar is another arbitrary user-defined mutable FlatData type.
|
|
*/
|
|
FlatMutableBar::Offset my_mutable();
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a complex array
|
|
*/
|
|
rti::flat::MutableArrayOffset<FlatMutableBar::Offset, 10> my_mutable_array();
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a complex sequence
|
|
*/
|
|
rti::flat::SequenceOffset<FlatMutableBar::Offset> my_mutable_seq();
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a string
|
|
*/
|
|
rti::flat::StringOffset my_string();
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a sequence of strings
|
|
*/
|
|
rti::flat::SequenceOffset<rti::flat::StringOffset> my_string_seq();
|
|
};
|
|
|
|
/**
|
|
* @ingroup RTIFlatOffsetsModule
|
|
* @brief Represents the Offset to an arbitrary user-defined FlatData
|
|
* mutable IDL union
|
|
*
|
|
* This example type represents the Offset type that \nddsgen would generate
|
|
* for \ref MyFlatUnion.
|
|
*
|
|
* It provides accessors for each of its members, plus the discriminator _d().
|
|
* Accessors can return other Offsets or primitive values.
|
|
*
|
|
* Given a union, only one member, the one identified by _d(), can exist at a
|
|
* time. The discriminator cannot be modified.
|
|
*
|
|
*/
|
|
class NDDSUSERDllExport MyFlatUnionOffset
|
|
: public rti::flat::MutableOffset {
|
|
public:
|
|
/**
|
|
* @brief The equivalent read-only Offset type
|
|
*/
|
|
typedef MyFlatUnionConstOffset ConstOffset;
|
|
|
|
/**
|
|
* @brief Creates a null Offset
|
|
*
|
|
* @post is_null()
|
|
*/
|
|
MyFlatUnionOffset()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @brief Retrieves the union discriminator
|
|
*
|
|
* @return The union discriminator, which identifies which field this union
|
|
* contains.
|
|
*
|
|
* In this example:
|
|
* - 0 selects my_primitive()
|
|
* - 1 and 2 select my_mutable()
|
|
* - 3 selects my_final
|
|
*
|
|
* Any other discriminator value indicates that no member or an unknown
|
|
* member follows.
|
|
*
|
|
* Note that the discriminator cannot be modified, since that would
|
|
* potentially change the size of this Sample by selecting a different
|
|
* member. The discriminator is selected during the building of a Sample
|
|
* (see MyUnionBuilder).
|
|
*/
|
|
int32_t _d() const;
|
|
|
|
/**
|
|
* @brief Retrieves the value for a primitive member
|
|
*
|
|
* @return The value of my_primitive if this member is selected by _d()
|
|
* or its default value otherwise.
|
|
*/
|
|
int32_t my_primitive() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a complex member
|
|
*
|
|
* @return The Offset to the 'my_mutable' member if selected by _d(),
|
|
* or a \ref OffsetErrorManagement "null Offset" otherwise
|
|
*/
|
|
MyFlatMutable::ConstOffset my_mutable() const;
|
|
|
|
/**
|
|
* @brief Retrieves a const Offset to a complex member
|
|
*
|
|
* @return The Offset to the 'my_final' member if selected by _d(),
|
|
* or a \ref OffsetErrorManagement "null Offset" otherwise
|
|
*/
|
|
MyFlatFinal::ConstOffset my_final() const;
|
|
|
|
/**
|
|
* @brief Sets the value for a primitive member
|
|
*
|
|
* @pre _d() must select 'my_primitive', otherwise this function
|
|
* returns false.
|
|
*
|
|
* @return true if my_primitive was set or false if the operation failed.
|
|
*/
|
|
bool my_primitive(int32_t value);
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a complex member
|
|
*
|
|
* @return The Offset to the 'my_mutable' member if selected by _d(),
|
|
* or a \ref OffsetErrorManagement "null Offset" otherwise
|
|
*/
|
|
MyFlatMutable::Offset my_mutable();
|
|
|
|
/**
|
|
* @brief Retrieves a non-const Offset to a complex member
|
|
*
|
|
* @return The Offset to the 'my_final' member if selected by _d(),
|
|
* or a \ref OffsetErrorManagement "null Offset" otherwise
|
|
*/
|
|
MyFlatFinal::Offset my_final();
|
|
};
|
|
|
|
#endif
|
|
|
|
namespace rti { namespace flat {
|
|
|
|
namespace detail {
|
|
|
|
inline rti::flat::offset_t ptrdiff(unsigned char *a, unsigned char *b)
|
|
{
|
|
RTI_FLAT_ASSERT(a - b < RTI_XCDR_MAX_SERIALIZED_SIZE, return 0);
|
|
|
|
return static_cast<rti::flat::offset_t>(a - b);
|
|
}
|
|
|
|
// Used to determine which fixed-size types need a DHeader when adding a
|
|
// fixed-size member or element. OffsetType classes may specialize this template
|
|
// to indicate if they need a DHeader.
|
|
template <typename OffsetType, typename Enable = void>
|
|
struct is_fixed_type_w_dheader {
|
|
static bool value()
|
|
{
|
|
return false;
|
|
}
|
|
};
|
|
|
|
inline bool is_dheader_required_in_non_primitive_collections()
|
|
{
|
|
// Allow setting the behavior at compilation time to gain compiler
|
|
// optimizations
|
|
#if defined(RTI_FLATDATA_NO_DHEADER_COLLECTIONS)
|
|
return false;
|
|
#elif defined(RTI_FLATDATA_DHEADER_COLLECTIONS)
|
|
return true;
|
|
#else
|
|
// Without any compilation flag, the behavior is configurable at runtime
|
|
RTIXCdrXTypesComplianceMask xTypesComplianceMask;
|
|
xTypesComplianceMask = RTIXCdrInterpreter_getGlobalXtypeComplianceMask();
|
|
return RTIXCdrXTypesComplianceMask_isBitSet(
|
|
xTypesComplianceMask,
|
|
RTI_XCDR_XTYPES_DHEADER_IN_NON_PRIMITIVE_COLLECTIONS_BIT);
|
|
#endif
|
|
}
|
|
|
|
inline bool is_dheader_required_in_enum_collections()
|
|
{
|
|
#if defined(RTI_FLATDATA_NO_DHEADER_COLLECTIONS)
|
|
return false;
|
|
#elif defined(RTI_FLATDATA_DHEADER_COLLECTIONS)
|
|
return true;
|
|
#else
|
|
RTIXCdrXTypesComplianceMask xTypesComplianceMask;
|
|
xTypesComplianceMask = RTIXCdrInterpreter_getGlobalXtypeComplianceMask();
|
|
return RTIXCdrXTypesComplianceMask_isBitSet(
|
|
xTypesComplianceMask,
|
|
RTI_XCDR_XTYPES_DHEADER_IN_NON_PRIMITIVE_COLLECTIONS_BIT)
|
|
&& !RTIXCdrXTypesComplianceMask_isBitSet(
|
|
xTypesComplianceMask,
|
|
RTI_XCDR_XTYPES_ENUM_AS_PRIMITIVE_IN_COLLECTIONS_BIT);
|
|
#endif
|
|
}
|
|
|
|
template <bool IsForEnum>
|
|
struct collection_dheader_traits {
|
|
static bool dheader_required()
|
|
{
|
|
return is_dheader_required_in_non_primitive_collections();
|
|
}
|
|
|
|
static unsigned int dheader_size()
|
|
{
|
|
return dheader_required() ? RTI_XCDR_DHEADER_SIZE : 0;
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct collection_dheader_traits<true> {
|
|
static bool dheader_required()
|
|
{
|
|
return is_dheader_required_in_enum_collections();
|
|
}
|
|
|
|
static unsigned int dheader_size()
|
|
{
|
|
return dheader_required() ? RTI_XCDR_DHEADER_SIZE : 0;
|
|
}
|
|
};
|
|
|
|
} // namespace detail
|
|
|
|
// Forward declaration
|
|
template <typename T, unsigned int N>
|
|
class FinalArrayOffset;
|
|
|
|
/**
|
|
* @ingroup RTIFlatOffsetsModule
|
|
* @brief Base class of all Offset types
|
|
*
|
|
* @see \ref RTIFlatOffsetsModule
|
|
*/
|
|
class OffsetBase {
|
|
public:
|
|
|
|
/**
|
|
* @brief Indicates whether this Offset doesn't point to a valid element
|
|
*
|
|
* \if CPP2_LANGUAGE_ONLY
|
|
* Comparing this object with \p nullptr is equivalent to calling is_null().
|
|
* For example:
|
|
* \code
|
|
* MyFlatMutableOffset my_mutable = ...;
|
|
* auto my_final_member = my_mutable.my_final();
|
|
* if (my_final_member.is_null()) { ...member doesn't exist... }
|
|
* // alternative syntax:
|
|
* if (my_final_member == nullptr) {...}
|
|
* \endcode
|
|
* \endif
|
|
*
|
|
* @see \ref OffsetErrorManagement
|
|
*/
|
|
bool is_null() const
|
|
{
|
|
return sample_ == NULL;
|
|
}
|
|
|
|
/**
|
|
* @brief Indicates whether rti::flat::plain_cast() is possible
|
|
*
|
|
* @return True only if the data pointed to by this Offset can be
|
|
* rti::flat::plain_cast()
|
|
*
|
|
* @see rti::flat::plain_cast() for the requirements that a type needs to meet
|
|
*/
|
|
bool is_cpp_compatible() const
|
|
{
|
|
// Derived classes may indicate whether
|
|
// a type is cpp-compatible
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*
|
|
* For internal use only. See the const overload.
|
|
*/
|
|
unsigned char * get_buffer()
|
|
{
|
|
if (is_null()) {
|
|
return NULL;
|
|
}
|
|
return stream_.current_position();
|
|
}
|
|
|
|
/**
|
|
* @brief Gets this member's position in the buffer
|
|
*
|
|
* @note This function should be used for debugging purposes only.
|
|
* To access the data in this Offset use the Offset accessor methods or, if
|
|
* this type allows it, rti::flat::plain_cast().
|
|
*
|
|
* Returns the position within the Sample's buffer that this
|
|
* Offset points to.
|
|
*
|
|
* @see get_buffer_size()
|
|
*/
|
|
const unsigned char * get_buffer() const
|
|
{
|
|
if (is_null()) {
|
|
return NULL;
|
|
}
|
|
return stream_.current_position();
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the size, in bytes, of this member in the buffer
|
|
*
|
|
* Returns the number of bytes that this member comprises
|
|
* after the position returned by get_buffer().
|
|
*/
|
|
offset_t get_buffer_size() const
|
|
{
|
|
RTI_FLAT_OFFSET_CHECK_NOT_NULL(return 0);
|
|
return stream_.total_size();
|
|
}
|
|
|
|
/**
|
|
* @brief Compares two Offsets
|
|
*
|
|
* @return True if s1 points to a position smaller than s2's.
|
|
*/
|
|
friend bool operator<(
|
|
const OffsetBase & s1,
|
|
const OffsetBase & s2) {
|
|
return s1.get_buffer() < s2.get_buffer();
|
|
}
|
|
|
|
/**
|
|
* @brief Compares two Offsets
|
|
*
|
|
* @return True if s1 points to a position greater than s2's.
|
|
*/
|
|
friend bool operator > (
|
|
const OffsetBase & s1,
|
|
const OffsetBase & s2) {
|
|
return s1.get_buffer() > s2.get_buffer();
|
|
}
|
|
|
|
/**
|
|
* @brief Compares two Offsets
|
|
*
|
|
* @return True if s1 points to a position equal to or smaller than s2's.
|
|
*/
|
|
friend bool operator <= (
|
|
const OffsetBase & s1,
|
|
const OffsetBase & s2) {
|
|
return s1.get_buffer() <= s2.get_buffer();
|
|
}
|
|
|
|
/**
|
|
* @brief Compares two Offsets
|
|
*
|
|
* @return True if s1 points to a position equal to or greater than s2's.
|
|
*/
|
|
friend bool operator >= (
|
|
const OffsetBase & s1,
|
|
const OffsetBase & s2) {
|
|
return s1.get_buffer() >= s2.get_buffer();
|
|
}
|
|
|
|
/**
|
|
* @brief Determines if two offets point to the same position
|
|
*
|
|
* @return True if s1 points to the same position as s2.
|
|
*/
|
|
friend bool operator == (
|
|
const OffsetBase & s1,
|
|
const OffsetBase & s2) {
|
|
return s1.get_buffer() == s2.get_buffer();
|
|
}
|
|
|
|
/**
|
|
* @brief Determines if two offets point to different positions
|
|
*
|
|
* @return True if s1 points to a different position than s2.
|
|
*/
|
|
friend bool operator != (
|
|
const OffsetBase & s1,
|
|
const OffsetBase & s2) {
|
|
return !(s1 == s2);
|
|
}
|
|
|
|
protected:
|
|
|
|
OffsetBase() :
|
|
sample_(NULL),
|
|
absolute_offset_(0)
|
|
{
|
|
}
|
|
|
|
OffsetBase(
|
|
SampleBase *sample,
|
|
offset_t absolute_offset,
|
|
offset_t serialized_size)
|
|
: sample_(sample),
|
|
absolute_offset_(absolute_offset)
|
|
{
|
|
// In modern C++ this throws PreconditionNotMetError; in traditional
|
|
// C++, this ends the constructor leaving the object in a state such
|
|
// that is_null() is true.
|
|
RTI_FLAT_CHECK_PRECONDITION(sample != NULL, return);
|
|
|
|
sample_->initialize_stream(
|
|
stream_.c_stream(),
|
|
absolute_offset_,
|
|
serialized_size);
|
|
}
|
|
|
|
// Gets the value of a primitive member at the specified relative Offset
|
|
template <typename U>
|
|
U deserialize(offset_t member_offset) const
|
|
{
|
|
RTI_FLAT_OFFSET_CHECK_NOT_NULL(return U());
|
|
RTI_FLAT_ASSERT(stream_.check_size(member_offset + static_cast<offset_t>(sizeof(U))), return U());
|
|
|
|
rti::xcdr::Stream::Memento stream_memento(stream_);
|
|
stream_.skip_fast(member_offset);
|
|
return stream_.deserialize_fast<U>();
|
|
}
|
|
|
|
// Sets the value of a primitive member at the specified relative Offset
|
|
template <typename U>
|
|
bool serialize(offset_t member_offset, U value)
|
|
{
|
|
RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
|
|
RTI_FLAT_ASSERT(stream_.check_size(member_offset + static_cast<offset_t>(sizeof(U))), return false);
|
|
|
|
rti::xcdr::Stream::Memento stream_memento(stream_);
|
|
|
|
stream_.skip_fast(member_offset);
|
|
stream_.serialize_fast<U>(value);
|
|
return true;
|
|
}
|
|
|
|
// Obtains a member at the specified relative offset
|
|
//
|
|
// U is the type of the member. U must be a subclass of Offset<U>.
|
|
template <typename U>
|
|
U get_member(offset_t relative_member_offset)
|
|
{
|
|
RTI_FLAT_OFFSET_CHECK_NOT_NULL(return U());
|
|
|
|
return U(
|
|
sample_,
|
|
// the absolute location of the member:
|
|
absolute_offset_ + relative_member_offset);
|
|
}
|
|
|
|
template <typename U>
|
|
U get_member(offset_t relative_member_offset) const
|
|
{
|
|
RTI_FLAT_OFFSET_CHECK_NOT_NULL(return U());
|
|
|
|
return U(
|
|
sample_,
|
|
// the absolute location of the member:
|
|
absolute_offset_ + relative_member_offset);
|
|
}
|
|
|
|
protected:
|
|
SampleBase *sample_; // the actual CDR buffer is in the sample
|
|
|
|
offset_t absolute_offset_; // the position of this Offset in the buffer
|
|
mutable rti::xcdr::Stream stream_; // a substream that shares the same buffer
|
|
};
|
|
|
|
/**
|
|
* @ingroup RTIFlatOffsetsModule
|
|
* @brief The base class of all Offsets to a final struct type
|
|
*
|
|
* This class contains only implementation details; all the public accessors
|
|
* are defined in the generated type (MyFlatFinalOffset).
|
|
*/
|
|
template <typename T>
|
|
class FinalOffset : public OffsetBase {
|
|
public:
|
|
typedef fixed_size_type_tag_t offset_kind;
|
|
|
|
static offset_t serialized_size_w_padding()
|
|
{
|
|
RTI_FLAT_ASSERT(T::serialized_size(0) > 0, return 0);
|
|
RTI_FLAT_ASSERT(T::required_alignment > 0, return 0);
|
|
|
|
const offset_t element_size = T::serialized_size(0);
|
|
if (element_size % T::required_alignment != 0) {
|
|
return element_size + T::required_alignment
|
|
- element_size % T::required_alignment;
|
|
} else {
|
|
return element_size;
|
|
}
|
|
}
|
|
|
|
bool is_cpp_compatible() const // override
|
|
{
|
|
RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
|
|
return !stream_.needs_byte_swap()
|
|
&& rti::xcdr::has_cpp_friendly_cdr_layout<
|
|
typename rti::flat::flat_type_traits<T>::flat_type>();
|
|
}
|
|
|
|
protected:
|
|
FinalOffset()
|
|
{
|
|
}
|
|
|
|
// Creates an Offset within the sample's CDR buffer at the specified
|
|
// absolute offset
|
|
//
|
|
// This overload requires T::serialized_size(offset_t)
|
|
//
|
|
FinalOffset(SampleBase *sample, offset_t absolute_offset)
|
|
: OffsetBase(
|
|
sample,
|
|
absolute_offset,
|
|
T::serialized_size(absolute_offset))
|
|
{
|
|
}
|
|
|
|
// Gets the value of a primitive member at the specified relative offset
|
|
// relative_member_offsets - the 4 possible offsets depending on the this
|
|
// type's initial alignment
|
|
template <typename U>
|
|
U deserialize(const offset_t *relative_member_offsets) const
|
|
{
|
|
RTI_FLAT_ASSERT(relative_member_offsets != NULL, return U());
|
|
|
|
// In a FinalOffset the stream is guaranteed to have enough space to
|
|
// contain all its members. There are two possible cases:
|
|
//
|
|
// - If the FinalOffset is a member of a mutable type, the member getter
|
|
// will ensure that the stream has enough space for the whole final
|
|
// type.
|
|
//
|
|
// - If the final offset is a top-level type, the type plugin ensures
|
|
// that the serialized buffer is large enough to contain the type.
|
|
|
|
return OffsetBase::deserialize<U>(
|
|
// pick the right offset based on the initial alignment
|
|
get_value_for_alignment(relative_member_offsets));
|
|
}
|
|
|
|
// Sets the value of a primitive member at the specified relative offset
|
|
template <typename U>
|
|
bool serialize(const offset_t *relative_member_offsets, U value)
|
|
{
|
|
RTI_FLAT_ASSERT(relative_member_offsets != NULL, return false);
|
|
|
|
return OffsetBase::serialize<U>(
|
|
// pick the right offset based on the initial alignment
|
|
get_value_for_alignment(relative_member_offsets), value);
|
|
}
|
|
|
|
|
|
// Obtains a member at the specified relative offset
|
|
//
|
|
// U is the type of the member. U must be a subclass of Offset<U>.
|
|
template <typename U>
|
|
U get_member(const offset_t *relative_member_offsets)
|
|
{
|
|
RTI_FLAT_ASSERT(relative_member_offsets != NULL, return U());
|
|
|
|
return OffsetBase::get_member<U>(
|
|
get_value_for_alignment(relative_member_offsets));
|
|
}
|
|
|
|
template <typename U>
|
|
U get_member(const offset_t *relative_member_offsets) const
|
|
{
|
|
RTI_FLAT_ASSERT(relative_member_offsets != NULL, return U());
|
|
|
|
return OffsetBase::get_member<U>(
|
|
get_value_for_alignment(relative_member_offsets));
|
|
}
|
|
|
|
// Returns an FinalArrayOffset located within this Offset
|
|
template <typename U, unsigned int N>
|
|
FinalArrayOffset<U, N> get_array_member(
|
|
const offset_t *relative_member_offsets,
|
|
const offset_t *first_element_sizes,
|
|
offset_t element_size)
|
|
{
|
|
typedef FinalArrayOffset<U, N> ArrayType;
|
|
|
|
RTI_FLAT_ASSERT(relative_member_offsets != NULL, return ArrayType());
|
|
RTI_FLAT_ASSERT(first_element_sizes != NULL, return ArrayType());
|
|
|
|
RTI_FLAT_OFFSET_CHECK_NOT_NULL(return ArrayType());
|
|
|
|
return ArrayType(
|
|
sample_,
|
|
// the absolute location of the member:
|
|
absolute_offset_ + get_value_for_alignment(relative_member_offsets),
|
|
// the size of the first element, which can differ from the rest
|
|
get_value_for_alignment(first_element_sizes),
|
|
// the size of every other element
|
|
element_size);
|
|
}
|
|
|
|
template <typename U, unsigned int N>
|
|
FinalArrayOffset<U, N> get_array_member(
|
|
const offset_t *relative_member_offsets,
|
|
const offset_t *first_element_sizes,
|
|
offset_t element_size) const
|
|
{
|
|
typedef FinalArrayOffset<U, N> ArrayType;
|
|
|
|
RTI_FLAT_ASSERT(relative_member_offsets != NULL, return ArrayType());
|
|
RTI_FLAT_ASSERT(first_element_sizes != NULL, return ArrayType());
|
|
|
|
RTI_FLAT_OFFSET_CHECK_NOT_NULL(return ArrayType());
|
|
return ArrayType(
|
|
sample_,
|
|
// the absolute location of the member:
|
|
absolute_offset_ + get_value_for_alignment(relative_member_offsets),
|
|
// the size of the first element, which can differ from the rest
|
|
get_value_for_alignment(first_element_sizes),
|
|
// the size of every other element
|
|
element_size);
|
|
}
|
|
|
|
private:
|
|
// A member's relative offset or an array's first element size
|
|
// may be different depending on the alignment of the position in the CDR
|
|
// buffer of the type that contains them (this). These values are passed
|
|
// to get_member or get_array_member as an array of 4 possible values. This
|
|
// function picks the right one based on the alingmenet of absolute_offset_
|
|
offset_t get_value_for_alignment(const offset_t *values_per_alignment) const
|
|
{
|
|
return values_per_alignment
|
|
[absolute_offset_ % RTI_XCDR_MAX_XCDR2_ALIGNMENT];
|
|
}
|
|
};
|
|
|
|
struct MutableOffsetHelper {
|
|
// Obtains the size of a mutable struct located at the absolute_offset of
|
|
// a FlatData sample
|
|
static offset_t calculate_serialized_size(
|
|
rti::flat::SampleBase *sample,
|
|
offset_t absolute_offset,
|
|
offset_t)
|
|
{
|
|
RTI_FLAT_ASSERT(sample != NULL, return 0);
|
|
|
|
return RTIXCdrFlatSample_getMutableSampleSize(
|
|
sample->get_buffer(),
|
|
absolute_offset);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @ingroup RTIFlatOffsetsModule
|
|
* @brief The base class of all Offsets to a final struct type
|
|
*
|
|
* This class contains only implementation details; all the public accessors
|
|
* are defined in the generated type (MyFlatMutableOffset).
|
|
*/
|
|
class MutableOffset : public OffsetBase {
|
|
public:
|
|
typedef variable_size_type_tag_t offset_kind;
|
|
typedef MutableOffsetHelper Helper;
|
|
|
|
protected:
|
|
MutableOffset()
|
|
{
|
|
}
|
|
|
|
MutableOffset(
|
|
SampleBase *sample,
|
|
offset_t absolute_offset,
|
|
offset_t serialized_size)
|
|
: OffsetBase(
|
|
sample,
|
|
absolute_offset,
|
|
serialized_size)
|
|
{
|
|
}
|
|
|
|
template <typename U>
|
|
U deserialize(member_id_t member_id, U default_val = U()) const
|
|
{
|
|
RTI_FLAT_OFFSET_CHECK_NOT_NULL(return U());
|
|
|
|
rti::xcdr::Stream::Memento stream_memento(stream_);
|
|
|
|
offset_t member_size = 0;
|
|
if (!RTIXCdrStream_findV2MutableSampleMember(
|
|
&stream_.c_stream(),
|
|
member_id,
|
|
&member_size)) {
|
|
return default_val;
|
|
}
|
|
|
|
return stream_.deserialize_fast<U>();
|
|
}
|
|
|
|
// Sets the value of a primitive member at the specified relative offset
|
|
template <typename U>
|
|
bool serialize(member_id_t member_id, U value)
|
|
{
|
|
RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
|
|
|
|
rti::xcdr::Stream::Memento stream_memento(stream_);
|
|
|
|
offset_t member_size = 0;
|
|
if (!RTIXCdrStream_findV2MutableSampleMember(
|
|
&stream_.c_stream(),
|
|
member_id,
|
|
&member_size)) {
|
|
return false;
|
|
}
|
|
|
|
stream_.serialize_fast<U>(value);
|
|
return true;
|
|
}
|
|
|
|
template <typename U>
|
|
U get_member(member_id_t member_id) const
|
|
{
|
|
RTI_FLAT_OFFSET_CHECK_NOT_NULL(return U());
|
|
|
|
rti::xcdr::Stream::Memento stream_memento(stream_);
|
|
|
|
offset_t member_size = 0;
|
|
if (!RTIXCdrStream_findV2MutableSampleMember(
|
|
&stream_.c_stream(),
|
|
member_id,
|
|
&member_size)) {
|
|
return U();
|
|
}
|
|
|
|
return get_member_impl<U>(
|
|
// absolute offset to the found member
|
|
detail::ptrdiff(stream_.current_position(), sample_->get_buffer()),
|
|
member_size,
|
|
typename U::offset_kind());
|
|
}
|
|
|
|
private:
|
|
template <typename U>
|
|
U get_member_impl(
|
|
offset_t absolute_member_offset,
|
|
offset_t member_size,
|
|
variable_size_type_tag_t) const
|
|
{
|
|
RTI_FLAT_ASSERT(absolute_member_offset > 0, return U());
|
|
|
|
// VariableOffsets receive a member_size
|
|
return U(sample_, absolute_member_offset, member_size);
|
|
}
|
|
|
|
template <typename U>
|
|
U get_member_impl(
|
|
offset_t absolute_member_offset,
|
|
offset_t member_size,
|
|
fixed_size_type_tag_t) const
|
|
{
|
|
(void) member_size; // suppress unused-param warning in release mode
|
|
RTI_FLAT_ASSERT(absolute_member_offset > 0, return U());
|
|
|
|
// FixedOffsets do not receive a member_size (it's already known)
|
|
return U(sample_, absolute_member_offset);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @ingroup RTIFlatOffsetsModule
|
|
* @brief A const Offset to an optional primitive member
|
|
*
|
|
* Read-only version of PrimitiveOffset.
|
|
*
|
|
* If !is_null(), the value can be retrieved with get().
|
|
*/
|
|
template <typename T>
|
|
struct PrimitiveConstOffset : public OffsetBase {
|
|
public:
|
|
typedef fixed_size_type_tag_t offset_kind;
|
|
|
|
PrimitiveConstOffset()
|
|
{
|
|
}
|
|
|
|
PrimitiveConstOffset(
|
|
SampleBase *sample,
|
|
offset_t absolute_offset)
|
|
: OffsetBase(
|
|
sample,
|
|
absolute_offset,
|
|
serialized_size(0))
|
|
{
|
|
}
|
|
|
|
bool is_cpp_compatible() const
|
|
{
|
|
RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
|
|
return sizeof(T) == 1 || !stream_.needs_byte_swap();
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the value of this primitive member
|
|
*
|
|
* @pre !is_null()
|
|
*/
|
|
T get() const
|
|
{
|
|
RTI_FLAT_OFFSET_CHECK_NOT_NULL(return T());
|
|
RTI_FLAT_ASSERT(stream_.check_size(sizeof(T)), return T());
|
|
|
|
return stream_.deserialize_fast<T>();
|
|
}
|
|
|
|
static offset_t serialized_size(offset_t)
|
|
{
|
|
return sizeof(T);
|
|
}
|
|
|
|
static offset_t serialized_size_w_padding()
|
|
{
|
|
return serialized_size(0);
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* @ingroup RTIFlatOffsetsModule
|
|
* @brief An Offset to an optional primitive member
|
|
*
|
|
* @tparam T The primitive type
|
|
*
|
|
* Non-optional primitive members are accessed directly using its container
|
|
* type's methods; however, since an optional member may not exist, this Offset
|
|
* is returned instead. The only purpose of the type PrimitiveOffset is to
|
|
* provide a way to check for the member's existence.
|
|
*
|
|
* If !is_null(), the value can be retrieved with get() or set with set().
|
|
*
|
|
* @see MyFlatMutableOffset::my_optional_primitive vs.
|
|
* MyFlatMutableOffset::my_primitive
|
|
*/
|
|
template <typename T>
|
|
struct PrimitiveOffset : public PrimitiveConstOffset<T> {
|
|
public:
|
|
PrimitiveOffset()
|
|
{
|
|
}
|
|
|
|
PrimitiveOffset(
|
|
SampleBase *sample,
|
|
offset_t absolute_offset)
|
|
: PrimitiveConstOffset<T>(
|
|
sample,
|
|
absolute_offset)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @brief Sets a value for this primitive member
|
|
*
|
|
* @pre !is_null()
|
|
*/
|
|
bool set(T value)
|
|
{
|
|
RTI_FLAT_OFFSET_CHECK_NOT_NULL(return false);
|
|
RTI_FLAT_ASSERT(this->stream_.check_size(sizeof(T)), return false);
|
|
|
|
this->stream_.template serialize_fast<T>(value);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} }
|
|
|
|
#endif // RTI_DDS_FLAT_FLATOFFSETS_HPP_
|
|
|