/* * (c) Copyright, Real-Time Innovations, 2017. * 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_ROUTING_PROCESSOR_OUTPUT_HPP_ #define RTI_ROUTING_PROCESSOR_OUTPUT_HPP_ #include #include #include #include #include #include "routingservice/routingservice_processor.h" #include "routingservice/routingservice_adapter_new.h" #include namespace rti { namespace routing { namespace processor { class Route; template class TypedOutput; template class TypedOutput; /** @ingroup RTI_RoutingServiceProcessorModule * * @class rti::routing::processor::Output * * @brief Generic Representation of a Route's output. * * This class provides a base representation of the outputs contained in a Route. * Since it is generic, this object does not allow performing any operation * that requires dealing with the data passed to the underlying * rti::routing::adapter::StreamWriter. */ class Output { public: /*i */ Output( RTI_RoutingServiceOutput *native, int32_t index, RTI_RoutingServiceRoute *native_route) : native_(native), index_(index), native_route_(native_route), stream_info_(*RTI_RoutingServiceOutput_get_stream_info(native)), name_(RTI_RoutingServiceOutput_get_name(native)) { } /*i */ const rti::routing::StreamInfo& stream_info() const { return stream_info_; } /*i * */ const std::string& name() const { return name_; } /*i * */ int32_t index() { return index_; } /** * @brief Returns a typed version of this Output. * * Note: This operation is not type-safe and it is the caller's * responsibility to use the appropriate type. * * @see TypedOutput * @see TypedOutput Route::output(int32_t index) */ template TypedOutput get() { return this; } /** * @brief Returns a typed version of this Output. * * Note: This operation is not type-safe and it is the caller's * responsibility to use the appropriate type. * * @see TypedOutput * @see TypedOutput Route::output(int32_t index) */ template TypedOutput get() { return this; } private: template friend class TypedOutput; friend class Route; RTI_RoutingServiceOutput *native_; int32_t index_; RTI_RoutingServiceRoute *native_route_; rti::routing::StreamInfo stream_info_; std::string name_; }; /** @ingroup RTI_RoutingServiceProcessorModule * * @class rti::routing::processor::TypedOutput * * @brief Representation of an Output whose data representation is \p DataRep, * whose info representation is \p InfoRep. * */ template class TypedOutput{ public: TypedOutput(Output *output) ; TypedOutput* operator->(); /** * @brief Returns the StreamInfo associated with this object. * * The associated StreamInfo represents an equivalent object to the one * used to create the underlying rti::routing::adapter::StreamWriter. */ const rti::routing::StreamInfo& stream_info() const; /** * @brief Returns the name of this output. * * The name is given by the name of the corresponding XML configuration tag. */ const std::string& name() const; /** * @brief Writes the specified data and info sample in this output. * * This operation will call rti::routing::adapter::StreamWriter::write on * the underlying rti::routing::adapter::StreamWriter. * * The provided sample is interpreted to contain data represented * as \c Data and the info as \c Info. * * @see rti::routing::adapter::StreamWriter::write */ void write(const Data& sample, const Info& info); /* * @brief Writes a sample given its data only. * * This operation will call rti::routing::adapter::StreamWriter::write * on the underlying rti::routing::adapter::StreamWriter, providing a null * value for the info sample. The underlying adapter will compute any * associated metadata from the data sample. */ void write(const Data& sample); /** * @brief Creates a new data sample that can be used to write in this * output. * * The data constructor called in this operation depends on the data * representation kind of the TypeInfo associated with this output. * If the type representation is a dynamic type, then it will assume * the following constructor: * \code Data(const dds::core::xtypes::DynamicType&) \endcode * * and will use the type code object downcasted from the value * returned by TypeInfo::type_representation. * * Otherwise: * \code Data() \endcode * * @return A new data sample */ Data create_data(); /** * @brief Returns the underlying DDS DataWriter that is part of this * StreamWriter implementation, assuming this input holds a DDS StreamWriter. * * This operation will throw an exception if this output does not hold a * DDS StreamWriter. * * @note The access to the underlying DataWriter is allowed only as long as * this Output remains enabled. The object representing the DataWriter * must be invalidated before the output is disabled, otherwise the behavior * is undefined. * * @throw std::exception * * @return dds::pub::DataWriter */ dds::pub::DataWriter dds_data_writer() { DDS_DataWriter *native_writer = RTI_RoutingServiceOutput_get_dds_writer(output_->native_); if (native_writer == NULL) { throw dds::core::InvalidArgumentError( "invalid argument: input does not hold a DDS StreamWriter"); } typedef dds::pub::DataWriter data_writer_type; return rti::core::detail::create_from_native_entity( native_writer); } private: friend class rti::routing::processor::Route; Output *output_; }; template struct create_data_from_output { static Data get(TypedOutput& ) { return Data(); } }; template struct create_data_from_output { static dds::core::xtypes::DynamicData get(TypedOutput& output) { if (output->stream_info().type_info().type_representation_kind() != TypeRepresentationKind::DYNAMIC_TYPE) { throw dds::core::PreconditionNotMetError( "inconsistent data representation kind"); } dds::core::xtypes::DynamicType *type_code = static_cast ( output->stream_info().type_info().type_representation()); return dds::core::xtypes::DynamicData(*type_code); } }; template TypedOutput::TypedOutput(Output* output) : output_(output) { } template const rti::routing::StreamInfo& TypedOutput::stream_info() const { return output_->stream_info_; } template const std::string& TypedOutput::name() const { return output_->name_; } template TypedOutput* TypedOutput::operator->() { return this; } template void TypedOutput::write(const Data& sample, const Info& info) { if (!RTI_RoutingServiceOutput_write_sample( output_->native_, const_cast (reinterpret_cast (&sample)), const_cast (reinterpret_cast (&info)))) { throw dds::core::Error("error writing sample to native output"); } } template void TypedOutput::write(const Data& sample) { if (!RTI_RoutingServiceOutput_write_sample( output_->native_, const_cast (reinterpret_cast (&sample)), NULL)) { throw dds::core::Error("error writing sample to native output"); } } template Data TypedOutput::create_data() { return create_data_from_output::get(*this); } /** * @brief Convenient definition of a TypedOutput whose data representation * is DynamicData and info representation is dds::sub::SampleInfo. * * These data and info representations are expected be used by most * rti::routing::adapter::StreamWriter implementations. */ typedef TypedOutput DynamicDataOutput; typedef dds::pub::DataWriter DynamicDataWriter; } } } #endif // RTI_ROUTING_PROCESSOR_OUTPUT_HPP_