Files
qt6-migration-pipeline/external/rti_connext_dds-7.7.0/include/rti/flat/SequenceBuilders.hpp
T
torstenandCopilot 342ffd3e5c Update submodule to latest BUILD_RTI fixes
- 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
2026-08-21 19:30:20 +02:00

953 lines
27 KiB
C++

/*
(c) Copyright, Real-Time Innovations, 2018-2024.
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_SEQUENCEBUILDERS_HPP_
#define RTI_DDS_FLAT_SEQUENCEBUILDERS_HPP_
#include "rti/flat/Builder.hpp"
//
// Builders for sequences, strings, and arrays.
//
// Type hierarchy (- indicates an abstract builder; * a concrete, usable builder)
//
// - AbstractListBuilder
// * MutableArrayBuilder
// - AbstractSequenceBuilder
// * MutableSequenceBuilder
// * FinalSequenceBuilder
// * PrimitiveSequenceBuilder
// * StringBuilder
//
// Notes:
// - there's no "FinalArrayBuilder" because that's a fixed-size type and
// doesn't need a builder (it's constructed via an "add" operation, not a "build"
// operation).
// - MutableSequenceBuilder "builds" its elements
// - FinalSequenceBuilder "adds" its elements
//
namespace rti { namespace flat {
namespace detail {
template <bool IsForEnum>
struct DHeaderGeneratorImpl {
static bool reserve_dheader(rti::xcdr::Stream& stream)
{
if (collection_dheader_traits<IsForEnum>::dheader_required()) {
return stream.serialize_dheader() != NULL;
} else {
return true;
}
}
static bool finish_dheader(
rti::xcdr::Stream& stream,
unsigned char *dheader_position)
{
if (collection_dheader_traits<IsForEnum>::dheader_required()) {
return stream.finish_dheader((char *) dheader_position);
} else {
return true;
}
}
static bool move_after_dheader(
rti::xcdr::Stream& stream,
unsigned char *begin_position)
{
stream.current_position(begin_position);
if (collection_dheader_traits<IsForEnum>::dheader_required()) {
return stream.skip(RTI_XCDR_DHEADER_SIZE);
} else {
return true;
}
}
};
struct NoDHeaderGenerator {
static bool reserve_dheader(rti::xcdr::Stream&)
{
return true;
}
static bool finish_dheader(rti::xcdr::Stream&, unsigned char *)
{
return true;
}
static bool move_after_dheader(
rti::xcdr::Stream& stream,
unsigned char *begin_position)
{
stream.current_position(begin_position);
return true;
}
};
typedef DHeaderGeneratorImpl<false> DHeaderGenerator;
typedef DHeaderGeneratorImpl<true> DHeaderGeneratorForEnum;
// Maybe specialized for enums to select DHeaderGenerator
template <typename T, typename Enable = void>
struct primitive_sequence_dheader_gen {
typedef NoDHeaderGenerator type;
};
} // namespace detail
/*i
* Extends and specializes AbstractBuilder to add or override the
* functionality required to build a collection of consecutive elements
* (sequence or array):
*
* - Add or build elements
* - Keep track of the element count
* - Handle element alignment
*
*/
/**
* @ingroup RTIFlatBuildersModule
* @brief Base class of all array and sequence builders
*/
template <typename DHeaderGen>
class AbstractListBuilder : public AbstractBuilder {
protected:
AbstractListBuilder() : element_count_(0)
{ }
AbstractListBuilder(
nested_tag_t,
AbstractBuilder& parent,
unsigned int alignment)
: AbstractBuilder(nested_tag_t(), parent, alignment),
element_count_(0)
{
DHeaderGen::reserve_dheader(stream());
}
template <typename ElementBuilder>
ElementBuilder build_next()
{
rti::xcdr::Stream::Memento stream_memento(stream());
return build_element<ElementBuilder>(stream_memento);
}
template <typename ElementOffset>
ElementOffset add_next()
{
RTI_FLAT_BUILDER_CHECK_VALID(return ElementOffset());
// save state in case of error
rti::xcdr::Stream::Memento stream_memento(stream());
if (!stream().align(ElementOffset::required_alignment)) {
RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return ElementOffset());
}
ElementOffset element = add_element<ElementOffset>();
if (element.is_null()) {
return ElementOffset();
}
// Success: clear memento, increment element count
stream_memento.discard();
element_count_++;
return element;
}
template <typename ElementOffset>
void add_n(unsigned int count)
{
RTI_FLAT_BUILDER_CHECK_VALID(return);
if (count == 0) {
return;
}
if (!stream().align(ElementOffset::required_alignment)) {
RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return);
}
offset_t elements_size = ElementOffset::serialized_size(0)
+ ElementOffset::serialized_size_w_padding() * (count - 1);
if (!stream().skip(elements_size)) {
RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return);
}
element_count_ += count;
}
/**
* @brief Returns the current number of elements that have been added
*/
unsigned int element_count() const
{
return element_count_;
}
#if defined(RTI_FLAT_DATA_CXX11_RVALUE_REFERENCES)
AbstractListBuilder(AbstractListBuilder&& other) = default;
AbstractListBuilder& operator=(AbstractListBuilder&& other)
{
if (this == &other) {
return *this;
}
finish_untyped_impl();
AbstractBuilder::operator=(static_cast<AbstractBuilder&&>(other));
element_count_ = other.element_count_;
other.element_count_ = 0;
return *this;
}
#else
public:
// Enables the safe-move-constructor idiom without C++11 move constructors
struct AbstractListBuilderMoveProxy : AbstractBuilderMoveProxy {
unsigned int element_count_;
};
operator AbstractListBuilderMoveProxy () throw() // move-constructor idiom
{
AbstractListBuilderMoveProxy other;
move_to(other);
return other;
}
protected:
void move_from(AbstractListBuilderMoveProxy& other)
{
AbstractBuilder::move_from(other);
element_count_ = other.element_count_;
}
void move_to(AbstractListBuilderMoveProxy& other)
{
AbstractBuilder::move_to(other);
other.element_count_ = element_count_;
}
#endif
private:
friend class AbstractBuilder;
virtual void finish_member() // override
{
RTI_FLAT_BUILDER_CHECK_VALID(return);
// Increment element count after the nested element builder finishes,
// instead of on build_next(). This makes it easier to roll back the
// state if the element building doesn't complete.
element_count_++;
AbstractBuilder::finish_member();
}
protected:
bool finish_dheader()
{
return DHeaderGen::finish_dheader(stream(), begin_position());
}
unsigned int element_count_;
};
// --- Array: -----------------------------------------------------------------
//
// (Note: there is no FinalArrayBuilder, because a final array's size is fixed,
// and is handled directly returning its offset with add_*; on the other hand,
// sequences are never fixed-size.)
/**
* @ingroup RTIFlatBuildersModule
* @brief Builds an array member of variable-size elements
*
* @tparam ElementBuilder The Builder type for the elements of the array
* @tparam N The array bound; the exact number of elements this array builder
* must build. For multidimensional arrays, \p N is the product
* of each dimension bound.
*
* Each element of this array needs to be built using the ElementBuilder returned
* by build_next(). N elements exactly must be built. Unlike a sequence Builder,
* it is not possible to finish an array with less than N elements.
*
* This example shows how to use a MutableArrayBuilder to build an array member
* of MyFlatMutableBuilder:
*
* \code
* MyFlatMutableBuilder builder = rti::flat::build_data(writer);
* auto array_builder = builder.build_my_mutable_array();
* for (int i = 0; i < 10; i++) {
* FlatMutableBarBuilder element_builder = array_builder.build_next();
* // ... build element
* element_builder.finish();
* }
* array_builder.finish();
* \endcode
*
* Note that Builder types are not necessary for arrays of fixed-size elements,
* since they are added at once (see MyFlatMutableBuilder::add_my_final_array()).
*/
template <typename ElementBuilder, unsigned int N>
class MutableArrayBuilder : public AbstractListBuilder<detail::DHeaderGenerator> {
public:
/**
* @brief The related Offset type
*/
typedef MutableArrayOffset<typename ElementBuilder::Offset, N> Offset;
typedef AbstractListBuilder<detail::DHeaderGenerator> Base;
MutableArrayBuilder()
{ }
// The destructor does the same as finish_impl() but doesn't need to return
// an Offset
~MutableArrayBuilder()
{
finish_untyped_impl();
}
#if defined(RTI_FLAT_DATA_CXX11_RVALUE_REFERENCES)
MutableArrayBuilder(MutableArrayBuilder&& other) = default;
MutableArrayBuilder& operator=(MutableArrayBuilder&& other)
{
finish_untyped_impl();
Base::operator=(static_cast<Base&&>(other));
return *this;
}
#endif
void finish_untyped_impl()
{
if (!Base::is_valid() || !Base::is_nested()) {
return;
}
Base::finish_dheader();
Base::finish_untyped_impl();
}
private:
friend class AbstractBuilder; // to allow access to the constructor
MutableArrayBuilder(
nested_tag_t,
AbstractBuilder& parent,
unsigned int alignment = 0)
: AbstractListBuilder(nested_tag_t(), parent, alignment)
{
}
public:
/**
* @brief Begins building the next element
*
* Before calling build_next() to create a new element, the element Builder
* returned by a previous call to build_next must have been finished.
*/
ElementBuilder build_next()
{
if (element_count() == N) {
RTI_FLAT_BUILDER_PRECONDITION_ERROR(
"Array builder build_next: too many elements",
return ElementBuilder());
}
return AbstractListBuilder::build_next<ElementBuilder>();
}
/**
* @brief Finishes building the array
*
* @pre build_next() must have been succesfully called \p N times exactly.
* @return The Offset to the member that has been built.
* @see discard()
*/
Offset finish()
{
RTI_FLAT_BUILDER_CHECK_CAN_FINISH(return Offset());
if (element_count() != N) {
RTI_FLAT_BUILDER_PRECONDITION_ERROR(
"Cannot finish array builder: too few elements",
return Offset());
}
if (!finish_dheader()) {
RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return Offset());
}
return finish_impl<Offset>();
}
RTI_FLAT_BUILDER_DEFINE_MOVE_OPERATIONS_IMPL(\
MutableArrayBuilder, AbstractListBuilder, AbstractListBuilderMoveProxy)
};
// --- Sequences: -------------------------------------------------------------
// Specializes AbstractListBuilder to handle the length header serialization
// common to all sequences (which arrays don't have)
/**
* @ingroup RTIFlatBuildersModule
* @brief Base class of Builders for sequence members.
*
* This class contains only implementation details and doesn't add any public
* function to AbstractListBuilder.
*/
template <typename DHeaderGen>
class AbstractSequenceBuilder : public AbstractListBuilder<DHeaderGen> {
public:
typedef AbstractListBuilder<DHeaderGen> Base;
using Base::element_count;
using Base::is_nested;
using Base::is_valid;
using Base::stream;
using typename Base::nested_tag_t;
#if !defined(RTI_FLAT_DATA_CXX11_RVALUE_REFERENCES)
using typename Base::AbstractListBuilderMoveProxy;
#endif
protected:
AbstractSequenceBuilder()
{
}
AbstractSequenceBuilder(
nested_tag_t,
AbstractBuilder& parent,
unsigned int alignment)
: Base(nested_tag_t(), parent, alignment)
{
// leave space for sequence length
if (!stream().check_size(sizeof(rti::xcdr::length_t))) {
RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(this->invalidate());
} else {
// No need to align; the base constructor already aligned to 4 the
// begin_position
stream().template serialize_fast<rti::xcdr::length_t>(0);
}
}
// The destructor does the same as finish_impl() but doesn't need to return
// an Offset
~AbstractSequenceBuilder()
{
finish_untyped_impl();
}
#if defined(RTI_FLAT_DATA_CXX11_RVALUE_REFERENCES)
AbstractSequenceBuilder(AbstractSequenceBuilder&& other) = default;
AbstractSequenceBuilder& operator=(AbstractSequenceBuilder&& other)
{
finish_untyped_impl();
Base::operator=(static_cast<Base&&>(other));
return *this;
}
#endif
void finish_untyped_impl()
{
if (!Base::is_valid() || !Base::is_nested()) {
return;
}
Base::finish_dheader();
finish_length();
Base::finish_untyped_impl();
}
// Concrete sequences must call this method in their own finish() function
template <typename Offset>
Offset finish_impl()
{
RTI_FLAT_BUILDER_CHECK_VALID(return Offset());
RTI_FLAT_BUILDER_CHECK_CAN_FINISH(return Offset());
Base::finish_dheader();
finish_length(); // serialize the length header
return Base::template finish_impl<Offset>();
}
private:
// Serializes the sequence length when finishing the builder.
void finish_length()
{
rti::xcdr::Stream::Memento stream_memento(stream());
DHeaderGen::move_after_dheader(stream(), Base::begin_position());
// Coverity found examples where element_count() is checked, but
// that's only done in Array builders, which are unrelated to this
// class, AbstractSequenceBuilder.
// coverity[CHECKED_RETURN : FALSE]
stream().template serialize_fast<rti::xcdr::length_t>(element_count());
}
};
/**
* @ingroup RTIFlatBuildersModule
* @brief Builds a sequence member of variable-size elements
*
* @tparam ElementBuilder The Builder type for the elements of the sequence
*
* To build the elements use the ElementBuilder returned
* by build_next(). An empty sequence can be built by calling finish() without
* any call to build_next().
*
* This class doesn't enforce the sequence bound set in IDL.
*
* The following example uses a MutableSequenceBuilder to initialize a sequence
* member of MyFlatMutableBuilder with two elements:
*
* \code
* MyFlatMutableBuilder builder = rti::flat::build_data(writer);
* auto seq_builder = builder.build_my_mutable_seq();
* auto element_builder = seq_builder.build_next();
* // ... build the first element
* element_builder.finish();
* element_builder = seq_builder.build_next();
* // ... build the second element
* element_builder.finish();
*
* seq_builder.finish();
* \endcode
*/
template <typename ElementBuilder>
class MutableSequenceBuilder
: public AbstractSequenceBuilder<detail::DHeaderGenerator> {
public:
/**
* @brief The related Offset type
*/
typedef SequenceOffset<typename ElementBuilder::Offset> Offset;
MutableSequenceBuilder()
{
}
private:
typedef AbstractSequenceBuilder<detail::DHeaderGenerator> Base;
friend class AbstractBuilder; // to allow access to the constructor
MutableSequenceBuilder(
nested_tag_t,
AbstractBuilder& parent,
unsigned int alignment = RTI_XCDR_DHEADER_ALIGNMENT)
: Base(nested_tag_t(), parent, alignment)
{
}
public:
/**
* @brief Begins building the next element
*
* Before calling build_next() to create a new element, the application must
* have called finish() on the previous element Builder.
*/
ElementBuilder build_next()
{
return AbstractListBuilder::build_next<ElementBuilder>();
}
/**
* @brief Finishes building the sequence
*
* @return An Offset to the member that has been built.
*
* @see discard()
*/
Offset finish()
{
return finish_impl<Offset>();
}
RTI_FLAT_BUILDER_DEFINE_MOVE_OPERATIONS_IMPL(
MutableSequenceBuilder,
Base,
AbstractListBuilderMoveProxy)
};
/**
* @ingroup RTIFlatBuildersModule
* @brief Builds a sequence member of fixed-size elements
*
* @tparam ElementOffset The Offset type for the elements of the sequence
*
* To add an element, call add_next() and use the ElementOffset it returns to
* initialize the element's values. An empty sequence can be built by
* calling finish() without any call to add_next().
*
* This class doesn't enforce the sequence bound set in IDL.
*
* The following example uses a FinalSequenceBuilder to initialize a sequence
* member of MyFlatMutableBuilder with two elements:
*
* \code
* MyFlatMutableBuilder builder = rti::flat::build_data(writer);
* auto seq_builder = builder.build_my_final_seq();
* MyFlatFinalOffset element = seq_builder.add_next();
* element.my_primitive(1);
* // ... continue initializing the first element
*
* element = seq_builder.add_next();
* element.my_primitive(2);
* // ... continue initializing the second element
*
* seq_builder.finish();
* \endcode
*
* If the element type meets certain requirements, rti::flat::plain_cast()
* provides a more efficient way to initialize a sequence of final elements.
*/
template <typename ElementOffset>
class FinalSequenceBuilder
: public AbstractSequenceBuilder<detail::DHeaderGenerator> {
public:
typedef SequenceOffset<ElementOffset> Offset;
FinalSequenceBuilder()
{
}
private:
friend class AbstractBuilder; // to allow access to the constructor
FinalSequenceBuilder(
nested_tag_t,
AbstractBuilder& parent,
unsigned int alignment = RTI_XCDR_SEQ_LENGTH_ALIGNMENT)
: AbstractSequenceBuilder(nested_tag_t(), parent, alignment)
{
}
public:
/**
* @brief Adds the next element
*
* @return The Offset that can be used to set the element values
*/
ElementOffset add_next()
{
return AbstractListBuilder::add_next<ElementOffset>();
}
/**
* @brief Adds a number of elements at once
*
* This is an alternative to add_next().
*
* To initialize the elements, call finish() and use the Offset it returns
* to access the elements.
*/
FinalSequenceBuilder& add_n(unsigned int count)
{
AbstractListBuilder::add_n<ElementOffset>(count);
return *this;
}
/**
* @brief Finishes building the sequence
*
* @return An Offset to the member that has been built.
* @see discard()
*/
Offset finish()
{
return finish_impl<Offset>();
}
RTI_FLAT_BUILDER_DEFINE_MOVE_OPERATIONS_IMPL(\
FinalSequenceBuilder, AbstractSequenceBuilder, AbstractListBuilderMoveProxy)
};
/**
* @ingroup RTIFlatBuildersModule
* @brief Builds a sequence of primitive members
*
* The elements can be added one by one with add_next() or all at once with
* add_n().
*/
template <typename T>
class PrimitiveSequenceBuilder
: public AbstractSequenceBuilder<
typename detail::primitive_sequence_dheader_gen<T>::type> {
public:
typedef PrimitiveSequenceOffset<T> Offset;
typedef AbstractSequenceBuilder<
typename detail::primitive_sequence_dheader_gen<T>::type>
Base;
using Base::is_valid;
using Base::stream;
using typename Base::nested_tag_t;
#if !defined(RTI_FLAT_DATA_CXX11_RVALUE_REFERENCES)
using typename Base::AbstractListBuilderMoveProxy;
#endif
PrimitiveSequenceBuilder()
{
}
protected:
friend class AbstractBuilder; // to allow access to the constructor
PrimitiveSequenceBuilder(
nested_tag_t,
AbstractBuilder& parent,
unsigned int alignment = RTI_XCDR_SEQ_LENGTH_ALIGNMENT)
: Base(nested_tag_t(), parent, alignment)
{
}
public:
/**
* @brief Adds the next element
*
* @param value The primitive element to add
*/
PrimitiveSequenceBuilder& add_next(T value)
{
RTI_FLAT_BUILDER_CHECK_VALID(return *this);
if (!stream().template serialize<T>(value)) {
RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return *this);
}
Base::element_count_++;
return *this;
}
/**
* @brief Adds all the elements in an array
*
* @param array The array containing the values to add
* @param count The size of the array
*
* @pre array must not be NULL
*/
PrimitiveSequenceBuilder& add_n(const T *array, unsigned int count)
{
RTI_FLAT_BUILDER_CHECK_VALID(return *this);
RTI_FLAT_ASSERT(array != NULL, return *this);
if (RTIXCdrUnsignedLong_MAX / static_cast<unsigned int>(sizeof(T))
< count) {
RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return *this);
}
if (!stream().check_size(static_cast<unsigned int>(sizeof(T)) * count)) {
RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return *this);
}
if (stream().needs_byte_swap() && sizeof(T) > 1) {
for (unsigned int i = 0; i < count; i++) {
stream().template serialize_fast<T>(array[i]);
}
} else {
stream().serialize_fast((void *) array, count * static_cast<unsigned int>(sizeof(T)));
}
Base::element_count_ += count;
return *this;
}
/**
* @brief Adds a number of elements with the same value
*
* This overload initializes all the elements to a value.
*
* @note This operation is O(\p count). The other overloads,
* add_n(unsigned int) and add_n(const T*, unsigned int), are more
* efficient
*
*
* @param count The number of elements to add
* @param value The value to set for each element
*/
PrimitiveSequenceBuilder& add_n(unsigned int count, T value)
{
RTI_FLAT_BUILDER_CHECK_VALID(return *this);
if (RTIXCdrUnsignedLong_MAX / static_cast<unsigned int>(sizeof(T))
< count) {
RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return *this);
}
if (!stream().check_size(static_cast<unsigned int>(sizeof(T)) * count)) {
RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return *this);
}
for (unsigned int i = 0; i < count; i++) {
stream().template serialize_fast<T>(value);
}
Base::element_count_ += count;
return *this;
}
/**
* @brief Adds a number of uninitialized elements
*
* This operation is O(1), since it leaves the elements uninitialized.
* They can be initialized using the Offset returned by finish() and
* rti::flat::plain_cast(). For example:
*
* \code
* MyFlatMutableBuilder builder = ...;
* auto seq_builder = builder.build_my_primitive_seq();
* seq_builder.add_n(1000);
* auto seq_offset = seq_builder.finish();
* int32_t *elements = rti::flat::plain_cast(seq_offset);
* for (int i = 0; i < 1000; i++) {
* elements[i] = ...;
* }
* \endcode
*
* @param count The number of elements to add
*/
PrimitiveSequenceBuilder& add_n(unsigned int count)
{
RTI_FLAT_BUILDER_CHECK_VALID(return *this);
if (RTIXCdrUnsignedLong_MAX / static_cast<unsigned int>(sizeof(T))
< count) {
RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return *this);
}
if (!stream().skip(static_cast<unsigned int>(sizeof(T)) * count)) {
RTI_FLAT_BUILDER_OUT_OF_RESOURCES_ERROR(return *this);
}
Base::element_count_ += count;
return *this;
}
/**
* @brief Finishes building the sequence
*
* @return An Offset to the member that has been built.
* @see discard()
*/
Offset finish()
{
this->finish_dheader();
return Base::template finish_impl<Offset>();
}
private:
RTI_FLAT_BUILDER_DEFINE_MOVE_OPERATIONS_IMPL(\
PrimitiveSequenceBuilder, Base, AbstractListBuilderMoveProxy)
};
/**
* @ingroup RTIFlatBuildersModule
* @brief Builds a string
*
* A StringBuilder only provides one method, set_string(), so it can be
* typically used as follows:
*
* \code
* MyFlatMutableBuilder my_builder = ...;
* my_builder.build_my_string().set_string("Hello!");
* \endcode
*
* Note that by relying on the builder destructor, there is no need to call
* finish() on the object returned by build_my_string().
*/
class StringBuilder : public PrimitiveSequenceBuilder<char> {
public:
typedef StringOffset Offset;
typedef PrimitiveSequenceBuilder<char> Base;
using Base::is_valid;
using Base::stream;
using typename Base::nested_tag_t;
StringBuilder()
{
}
private:
friend class AbstractBuilder; // to allow access to the constructor
StringBuilder(
nested_tag_t,
AbstractBuilder& parent,
unsigned int alignment = RTI_XCDR_SEQ_LENGTH_ALIGNMENT)
: Base(nested_tag_t(), parent, alignment)
{
}
public:
/**
* @brief Sets the string value
*
* @param value The string value to set.
*
* @pre value must not be NULL.
*/
StringBuilder& set_string(const char *value)
{
RTI_FLAT_BUILDER_CHECK_VALID(return *this);
RTI_FLAT_ASSERT(value != NULL, return *this);
// if set_string is called more than once we override the string
// that was set before
if (Base::element_count_ != 0) {
stream().current_position(begin_position());
stream().serialize_fast<rti::xcdr::length_t>(0);
Base::element_count_ = 0;
}
unsigned int length =
static_cast<unsigned int>(RTIXCdrString_getLength(value)) + 1;
add_n(value, length); // if this fail, error has been reported
return *this;
}
/**
* @brief Finishes building the string
*
* @return An Offset to the member that has been built.
* @see discard()
*/
Offset finish()
{
RTI_FLAT_BUILDER_CHECK_VALID(return Offset());
if (element_count_ == 0) {
add_next('\0'); // build empty string if no string was built
}
Base::finish_dheader();
return finish_impl<Offset>();
}
RTI_FLAT_BUILDER_DEFINE_MOVE_OPERATIONS_IMPL(\
StringBuilder, Base, AbstractListBuilderMoveProxy)
};
// Wide strings are treated as a sequence of octets
typedef PrimitiveSequenceBuilder<unsigned char> WStringBuilder;
} }
#endif // RTI_DDS_FLAT_SEQUENCEBUILDERS_HPP_