LCOV - code coverage report
Current view: top level - DCPS - Serializer.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 37 54 68.5 %
Date: 2023-04-30 01:32:43 Functions: 19 362 5.2 %

          Line data    Source code
       1             : /*
       2             :  * Distributed under the OpenDDS License.
       3             :  * See: http://www.opendds.org/license.html
       4             :  */
       5             : 
       6             : /**
       7             :  * @file Serializer.h
       8             :  *
       9             :  * The serialization interface for a C++ type called Type consists of the
      10             :  * following overloads:
      11             :  *
      12             :  *   void serialized_size(
      13             :  *       const Encoding& encoding, size_t& size, const Type& value);
      14             :  *     Get the size (in bytes) of the encoded representation of value.
      15             :  *
      16             :  *   bool operator<<(Serializer& serializer, const Type& value);
      17             :  *     Tries to encode value into the stream of the serializer. Returns true if
      18             :  *     successful, else false.
      19             :  *
      20             :  *   bool operator>>(Serializer& serializer, Type& value);
      21             :  *     Tries to decode a representation of Type located at the current
      22             :  *     position of the stream and use that to set value. Returns true if
      23             :  *     successful, else false.
      24             :  */
      25             : 
      26             : #ifndef OPENDDS_DCPS_SERIALIZER_H
      27             : #define OPENDDS_DCPS_SERIALIZER_H
      28             : 
      29             : #include <ace/config-macros.h>
      30             : #ifndef ACE_LACKS_PRAGMA_ONCE
      31             : #  pragma once
      32             : #endif /* ACE_LACKS_PRAGMA_ONCE */
      33             : 
      34             : #include "Definitions.h"
      35             : #include "PoolAllocator.h"
      36             : #include "Message_Block_Ptr.h"
      37             : #include "dcps_export.h"
      38             : 
      39             : #include <ace/CDR_Base.h>
      40             : #include <ace/CDR_Stream.h>
      41             : 
      42             : #include <limits>
      43             : #include <string>
      44             : 
      45             : ACE_BEGIN_VERSIONED_NAMESPACE_DECL
      46             : class ACE_Message_Block;
      47             : ACE_END_VERSIONED_NAMESPACE_DECL
      48             : 
      49             : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
      50             : 
      51             : namespace OpenDDS {
      52             : namespace DCPS {
      53             : 
      54             : enum Endianness {
      55             :   ENDIAN_BIG = 0,
      56             :   ENDIAN_LITTLE = 1,
      57             : #ifdef ACE_LITTLE_ENDIAN
      58             :   ENDIAN_NATIVE = ENDIAN_LITTLE,
      59             :   ENDIAN_NONNATIVE = ENDIAN_BIG
      60             : #else
      61             :   ENDIAN_NATIVE = ENDIAN_BIG,
      62             :   ENDIAN_NONNATIVE = ENDIAN_LITTLE
      63             : #endif
      64             : };
      65             : 
      66             : OpenDDS_Dcps_Export
      67             : String endianness_to_string(Endianness endianness);
      68             : 
      69             : enum Extensibility {
      70             :   FINAL,
      71             :   APPENDABLE,
      72             :   MUTABLE
      73             : };
      74             : 
      75           0 : inline const char* ext_to_string(Extensibility ext)
      76             : {
      77           0 :   switch (ext) {
      78           0 :   case FINAL:
      79           0 :     return "final";
      80           0 :   case APPENDABLE:
      81           0 :     return "appendable";
      82           0 :   case MUTABLE:
      83           0 :     return "mutable";
      84           0 :   default:
      85           0 :     return "invalid";
      86             :   }
      87             : }
      88             : 
      89             : const size_t boolean_cdr_size = 1;
      90             : const size_t byte_cdr_size = 1;
      91             : const size_t int8_cdr_size = 1;
      92             : const size_t uint8_cdr_size = 1;
      93             : const size_t int16_cdr_size = 2;
      94             : const size_t uint16_cdr_size = 2;
      95             : const size_t int32_cdr_size = 4;
      96             : const size_t uint32_cdr_size = 4;
      97             : const size_t int64_cdr_size = 8;
      98             : const size_t uint64_cdr_size = 8;
      99             : const size_t float32_cdr_size = 4;
     100             : const size_t float64_cdr_size = 8;
     101             : const size_t float128_cdr_size = 16;
     102             : const size_t char8_cdr_size = 1;
     103             : const size_t char16_cdr_size = 2;
     104             : const size_t xcdr1_pid_alignment = 4;
     105             : 
     106             : /// Align "value" by "by" if it's not already
     107             : OpenDDS_Dcps_Export
     108             : void align(size_t& value, size_t by);
     109             : 
     110             : /**
     111             :  * Represents the serialization rules. Used to construct a
     112             :  * Serializer and to pass to functions that are used without
     113             :  * a Serializer like serialized_size() and max_serialized_size()
     114             :  */
     115             : class OpenDDS_Dcps_Export Encoding {
     116             : public:
     117             :   /**
     118             :    * Kinds are the overall algorithm for serialization.
     119             :    * A Kind value along with other details like alignment and endianness
     120             :    * comprise an Encoding.
     121             :    */
     122             :   enum Kind {
     123             :     /**
     124             :      * Extensible CDR version 1 from XTypes.
     125             :      * This represents standard non-XTypes CDR if the type is final.
     126             :      */
     127             :     KIND_XCDR1,
     128             :     /**
     129             :      * Extensible CDR version 2 from XTypes.
     130             :      */
     131             :     KIND_XCDR2,
     132             :     /**
     133             :      * This is the classic encoding of OpenDDS used when there is no RTPS
     134             :      * transport being used. It has no padding bytes and no XCDR behavior.
     135             :      */
     136             :     KIND_UNALIGNED_CDR
     137             :   };
     138             : 
     139             :   enum Alignment {
     140             :     ALIGN_NONE = 0, ///< No Alignment Needed
     141             :     ALIGN_CDR = 8, ///< Align for CDR and XCDR1
     142             :     ALIGN_XCDR2 = 4, ///< Align for XCDR2
     143             :     ALIGN_MAX = ALIGN_CDR ///< Maximum alignment that could be used
     144             :   };
     145             : 
     146             :   /**
     147             :    * XCDR version derived from the Encoding kind.
     148             :    */
     149             :   enum XcdrVersion {
     150             :     XCDR_VERSION_NONE,
     151             :     XCDR_VERSION_1,
     152             :     XCDR_VERSION_2
     153             :   };
     154             : 
     155             :   /// Encoding with KIND_XCDR1 and ENDIAN_NATIVE
     156             :   Encoding();
     157             : 
     158             :   explicit Encoding(Kind kind, Endianness endianness = ENDIAN_NATIVE);
     159             : 
     160             :   Encoding(Kind kind, bool swap_bytes);
     161             : 
     162             :   Kind kind() const;
     163             :   void kind(Kind value);
     164             : 
     165             :   Endianness endianness() const;
     166             :   void endianness(Endianness value);
     167             : 
     168             :   Alignment alignment() const;
     169             :   void alignment(Alignment value);
     170             : 
     171             :   ///@{
     172             :   /**
     173             :    * Should the padding bytes being inserted into the stream be zero
     174             :    * initialized?
     175             :    */
     176             :   bool zero_init_padding() const;
     177             :   void zero_init_padding(bool value);
     178             :   ///@}
     179             : 
     180             :   ///@{
     181             :   /**
     182             :    * Should the XCDR2 sequence DHEADER be skipped?
     183             :    * This is not spec compliant -- used for compatibility with earlier
     184             :    * OpenDDS versions that had a bug.
     185             :    * Only used for XTypes::TypeObject and related structs.
     186             :    */
     187             :   bool skip_sequence_dheader() const;
     188             :   void skip_sequence_dheader(bool value);
     189             :   ///@}
     190             : 
     191             :   /// Return the maximum alignment dictated by the alignment policy.
     192             :   size_t max_align() const;
     193             : 
     194             :   /// Align "value" to "by" and according to the stream's alignment.
     195             :   void align(size_t& value, size_t by = (std::numeric_limits<size_t>::max)()) const;
     196             : 
     197             :   XcdrVersion xcdr_version() const;
     198             :   void xcdr_version(XcdrVersion value);
     199             : 
     200             :   ///@{
     201             :   /**
     202             :    * Returns true if the encoding kind is excepted to have a header for RTPS
     203             :    * serialized data payloads.
     204             :    */
     205             :   static bool is_encapsulated(Kind kind);
     206             :   bool is_encapsulated() const;
     207             :   ///@}
     208             : 
     209             :   String to_string() const;
     210             :   static String kind_to_string(Kind value);
     211             : 
     212             : private:
     213             :   Kind kind_;
     214             :   Endianness endianness_;
     215             :   Alignment alignment_;
     216             :   bool zero_init_padding_;
     217             :   bool skip_sequence_dheader_;
     218             :   XcdrVersion xcdr_version_;
     219             : };
     220             : 
     221             : /**
     222             :  * Represents the RTPS encapsulation header for serialized data.
     223             :  *
     224             :  * This consists of 4 bytes that appear in front of the data. The first two
     225             :  * bytes represents the kind of the encoding the data uses and the last two
     226             :  * bytes (known as "options") are traditionally reserved.
     227             :  *
     228             :  * See XTypes 1.3 7.6.3.1.2
     229             :  */
     230             : class OpenDDS_Dcps_Export EncapsulationHeader {
     231             : public:
     232             :   /**
     233             :    * The known possible values of the first 2 bytes represented as big endian
     234             :    * integers.
     235             :    */
     236             :   enum Kind {
     237             :     KIND_CDR_BE = 0x0000,
     238             :     KIND_CDR_LE = 0x0001,
     239             :     KIND_PL_CDR_BE = 0x0002,
     240             :     KIND_PL_CDR_LE = 0x0003,
     241             :     KIND_CDR2_BE = 0x0006,
     242             :     KIND_CDR2_LE = 0x0007,
     243             :     KIND_D_CDR2_BE = 0x0008,
     244             :     KIND_D_CDR2_LE = 0x0009,
     245             :     KIND_PL_CDR2_BE = 0x000a,
     246             :     KIND_PL_CDR2_LE = 0x000b,
     247             :     KIND_XML = 0x0004,
     248             :     KIND_INVALID = 0xFFFF
     249             :   };
     250             : 
     251             :   const static size_t serialized_size = 4;
     252             :   const static size_t padding_marker_byte_index = 3;
     253             :   const static size_t padding_marker_alignment = 4;
     254             : 
     255             :   EncapsulationHeader(Kind k = KIND_CDR_BE, ACE_CDR::UShort options = 0);
     256             : 
     257             :   /**
     258             :    * Success can be verified using is_good()
     259             :    */
     260             :   EncapsulationHeader(const Encoding& enc, Extensibility ext, ACE_CDR::UShort options = 0);
     261             : 
     262             :   Kind kind() const;
     263             :   void kind(Kind value);
     264             : 
     265             :   ACE_UINT16 options() const;
     266             :   void options(ACE_UINT16 value);
     267             : 
     268             :   /**
     269             :    * post-initialization test for a successful call to from_encoding during
     270             :    * construction of this encapsulation header.
     271             :    */
     272             :   bool is_good() const;
     273             : 
     274             :   /**
     275             :    * Translate from an encoding, returns false if it failed.
     276             :    */
     277             :   bool from_encoding(const Encoding& encoding, Extensibility extensibility);
     278             : 
     279             :   /**
     280             :    * Translate to an encoding, returns false if it failed.
     281             :    */
     282             :   bool to_encoding(Encoding& encoding, Extensibility expected_extensibility);
     283             : 
     284             :   /**
     285             :    * Like to_encoding, but without an expected extensibility.
     286             :    */
     287             :   bool to_any_encoding(Encoding& encoding);
     288             : 
     289             :   String to_string() const;
     290             : 
     291             :   static bool set_encapsulation_options(Message_Block_Ptr& mb);
     292             : 
     293             : private:
     294             :   /// The first two bytes as a big endian integer
     295             :   Kind kind_;
     296             :   /// The last two bytes as a big endian integer
     297             :   ACE_CDR::UShort options_;
     298             : 
     299             :   bool to_encoding_i(Encoding& encoding, Extensibility* expected_extensibility_ptr);
     300             : };
     301             : 
     302             : class Serializer;
     303             : 
     304             : OpenDDS_Dcps_Export
     305             : bool operator>>(Serializer& s, EncapsulationHeader& value);
     306             : 
     307             : OpenDDS_Dcps_Export
     308             : bool operator<<(Serializer& s, const EncapsulationHeader& value);
     309             : 
     310             : /**
     311             :  * Convenience function for the serialized_size of a single value with no
     312             :  * alignment needed.
     313             :  */
     314             : template <typename T>
     315         540 : size_t serialized_size(const Encoding& encoding, const T& value)
     316             : {
     317         540 :   size_t size = 0;
     318         540 :   serialized_size(encoding, size, value);
     319         540 :   return size;
     320             : }
     321             : 
     322             : /**
     323             :  * This helper class can be used to construct ACE message blocks from
     324             :  * IDL sequences of octet (or compatible substitutes) and be used with
     325             :  * the Serializer to serialize/deserialize directly into the byte
     326             :  * buffer.  The sequence must have its length set before constructing
     327             :  * this object.  T should provide a length() method which is the size
     328             :  * of the buffer and get_buffer() which returns a pointer to the
     329             :  * underlying byte sequence.
     330             :  */
     331             : template <typename T>
     332             : class MessageBlockHelper {
     333             : public:
     334             :   /**
     335             :    * This constructor receives an already populated OctetSeq so the write pointer is advanced
     336             :    */
     337          39 :   explicit MessageBlockHelper(const T& seq)
     338          39 :     : db_(seq.length(), ACE_Message_Block::MB_DATA,
     339          39 :           reinterpret_cast<const char*>(seq.get_buffer()),
     340             :           0 /*alloc*/, 0 /*lock*/, ACE_Message_Block::DONT_DELETE, 0 /*db_alloc*/)
     341          39 :     , mb_(&db_, ACE_Message_Block::DONT_DELETE, 0 /*mb_alloc*/)
     342             :   {
     343          39 :     mb_.wr_ptr(mb_.space());
     344          39 :   }
     345             : 
     346          81 :   explicit MessageBlockHelper(T& seq)
     347          81 :     : db_(seq.length(), ACE_Message_Block::MB_DATA,
     348          81 :           reinterpret_cast<const char*>(seq.get_buffer()),
     349             :           0 /*alloc*/, 0 /*lock*/, ACE_Message_Block::DONT_DELETE, 0 /*db_alloc*/)
     350          81 :     , mb_(&db_, ACE_Message_Block::DONT_DELETE, 0 /*mb_alloc*/)
     351          81 :   {}
     352             : 
     353         120 :   operator ACE_Message_Block*() { return &mb_; }
     354             : 
     355             : private:
     356             :   ACE_Data_Block db_;
     357             :   ACE_Message_Block mb_;
     358             : };
     359             : 
     360             : /**
     361             :  * @class Serializer
     362             :  *
     363             :  * @brief Class to serialize and deserialize data for DDS.
     364             :  *
     365             :  * This class provides a mechanism to insert and extract data to and
     366             :  * from an ACE_Message_Block chain that represents the data which
     367             :  * can be transported on the wire to other DDS service participants.
     368             :  */
     369             : class OpenDDS_Dcps_Export Serializer {
     370             : public:
     371             :   /// Flags and reserved ids used in parameter list ids.
     372             :   ///@{
     373             :   static const ACE_CDR::UShort pid_extended = 0x3f01;
     374             :   /**
     375             :    * Note that this is different than OpenDDS::RTPS::PID_SENTINEL(0x0001). See
     376             :    * XTypes 1.3 Table 34 for details.
     377             :    */
     378             :   static const ACE_CDR::UShort pid_list_end = 0x3f02;
     379             :   static const ACE_CDR::UShort pid_impl_extension = 0x8000;
     380             :   static const ACE_CDR::UShort pid_must_understand = 0x4000;
     381             :   ///@}
     382             : 
     383             :   // EMHEADER must understand flag
     384             :   static const ACE_CDR::ULong emheader_must_understand = 1U << 31U;
     385             : 
     386             :   /// Maximum value for member id.
     387             :   static const ACE_CDR::ULong MEMBER_ID_MAX = 0x0FFFFFFF;
     388             :   static const ACE_CDR::ULong MEMBER_ID_MASK = MEMBER_ID_MAX;
     389             : 
     390             :   /**
     391             :    * Constructor with a message block chain.  This installs the
     392             :    * message block chain and sets the current block to the first in
     393             :    * the chain.  Memory management is the responsibility of the owner
     394             :    * of this object, and is not performed internally.  Ownership of
     395             :    * the message block chain is retained by the owner of this object
     396             :    * and the lifetime of the chain must be longer than the use of
     397             :    * this object.
     398             :    *
     399             :    * This constructor is meant for using a specific predefined encoding scheme.
     400             :    */
     401             :   Serializer(ACE_Message_Block* chain, const Encoding& encoding);
     402             : 
     403             :   /**
     404             :    * More convenient version of the constructor above if you don't need to
     405             :    * reuse the Encoding object.
     406             :    */
     407             :   Serializer(ACE_Message_Block* chain, Encoding::Kind kind,
     408             :     Endianness endianness = ENDIAN_NATIVE);
     409             : 
     410             :   /**
     411             :    * Equivalent to: Serializer(chain, kind, swap_bytes ? ENDIAN_NONNATIVE : ENDIAN_NATIVE)
     412             :    */
     413             :   Serializer(ACE_Message_Block* chain, Encoding::Kind kind, bool swap_bytes);
     414             : 
     415             :   virtual ~Serializer();
     416             : 
     417             :   const Encoding& encoding() const;
     418             :   void encoding(const Encoding& value);
     419             : 
     420             :   void swap_bytes(bool do_swap);
     421             :   bool swap_bytes() const;
     422             : 
     423             :   Endianness endianness() const;
     424             :   void endianness(Endianness value);
     425             : 
     426             :   Encoding::Alignment alignment() const;
     427             :   void alignment(Encoding::Alignment value);
     428             : 
     429             :   /// Reset alignment as if a new instance were created
     430             :   void reset_alignment();
     431             : 
     432             :   bool good_bit() const;
     433             : 
     434             :   /// Number of bytes left to read in message block chain
     435             :   size_t length() const;
     436             : 
     437             :   typedef ACE_CDR::Char* (*StrAllocate)(ACE_CDR::ULong);
     438             :   typedef void (*StrFree)(ACE_CDR::Char*);
     439             :   typedef ACE_CDR::WChar* (*WStrAllocate)(ACE_CDR::ULong);
     440             :   typedef void (*WStrFree)(ACE_CDR::WChar*);
     441             : 
     442             :   size_t read_string(ACE_CDR::Char*& dest,
     443             :                      StrAllocate str_alloc = 0,
     444             :                      StrFree str_free = 0);
     445             : 
     446             :   void free_string(ACE_CDR::Char* str,
     447             :                    StrFree str_free = 0);
     448             : 
     449             :   size_t read_string(ACE_CDR::WChar*& dest,
     450             :                      WStrAllocate str_alloc = 0,
     451             :                      WStrFree str_free = 0);
     452             : 
     453             :   void free_string(ACE_CDR::WChar* str,
     454             :                    WStrFree str_free = 0);
     455             : 
     456             :   /// Skip the logical rd_ptr() over a given number of bytes = n * size.
     457             :   /// If alignment is enabled, skips any padding to align to 'size' before
     458             :   /// skipping the n * size bytes.
     459             :   /// This is used by the RTPS protocol to allow reading messages from
     460             :   /// future versions of the spec which may have additional optional fields.
     461             :   bool skip(size_t n, int size = 1);
     462             : 
     463             :   /// Return a duplicated Message Block (chain) which starts at the current
     464             :   /// read position (rpos) and extends for n bytes.
     465             :   /// This can be used to treat a subset of the original message as if it
     466             :   /// was itself a full message, for example the SerializedPayload or the
     467             :   /// Parameter value inside a ParameterList.
     468             :   /// The returned object should be release()'d (use Message_Block_Ptr)
     469             :   ACE_Message_Block* trim(size_t n) const;
     470             : 
     471           0 :   const char* pos_rd() const { return current_ ? current_->rd_ptr() : 0; }
     472             :   const char* pos_wr() const { return current_ ? current_->wr_ptr() : 0; }
     473             : 
     474             :   /// Examine the logical reading position of the stream.
     475        6433 :   size_t rpos() const { return rpos_; }
     476             : 
     477             :   /// Examine the logical writing position of the stream.
     478         271 :   size_t wpos() const { return wpos_; }
     479             : 
     480         287 :   ACE_Message_Block* current() const
     481             :   {
     482         287 :     return current_;
     483             :   }
     484             : 
     485             :   /**
     486             :    * Read basic IDL types arrays
     487             :    * The buffer @a x must be large enough to contain @a length
     488             :    * elements.
     489             :    * Return @c false on failure and @c true on success.
     490             :    */
     491             :   ///@{
     492             :   bool read_boolean_array(ACE_CDR::Boolean* x, ACE_CDR::ULong length);
     493             :   bool read_char_array(ACE_CDR::Char* x, ACE_CDR::ULong length);
     494             :   bool read_wchar_array(ACE_CDR::WChar* x, ACE_CDR::ULong length);
     495             :   bool read_octet_array(ACE_CDR::Octet* x, ACE_CDR::ULong length);
     496             : #if OPENDDS_HAS_EXPLICIT_INTS
     497             :   bool read_int8_array(ACE_CDR::Int8* x, ACE_CDR::ULong length);
     498             :   bool read_uint8_array(ACE_CDR::UInt8* x, ACE_CDR::ULong length);
     499             : #endif
     500             :   bool read_short_array(ACE_CDR::Short* x, ACE_CDR::ULong length);
     501             :   bool read_ushort_array(ACE_CDR::UShort* x, ACE_CDR::ULong length);
     502             :   bool read_long_array(ACE_CDR::Long* x, ACE_CDR::ULong length);
     503             :   bool read_ulong_array(ACE_CDR::ULong* x, ACE_CDR::ULong length);
     504             :   bool read_longlong_array(ACE_CDR::LongLong* x, ACE_CDR::ULong length);
     505             :   bool read_ulonglong_array(ACE_CDR::ULongLong* x, ACE_CDR::ULong length);
     506             :   bool read_float_array(ACE_CDR::Float* x, ACE_CDR::ULong length);
     507             :   bool read_double_array(ACE_CDR::Double* x, ACE_CDR::ULong length);
     508             :   bool read_longdouble_array(ACE_CDR::LongDouble* x, ACE_CDR::ULong length);
     509             :   ///@}
     510             : 
     511             :   /// Array write operations
     512             :   /// Note: the portion written starts at x and ends
     513             :   ///    at x + length.
     514             :   /// The length is *NOT* stored into the CDR stream.
     515             :   ///@{
     516             :   bool write_boolean_array(const ACE_CDR::Boolean* x, ACE_CDR::ULong length);
     517             :   bool write_char_array(const ACE_CDR::Char* x, ACE_CDR::ULong length);
     518             :   bool write_wchar_array(const ACE_CDR::WChar* x, ACE_CDR::ULong length);
     519             :   bool write_octet_array(const ACE_CDR::Octet* x, ACE_CDR::ULong length);
     520             : #if OPENDDS_HAS_EXPLICIT_INTS
     521             :   bool write_int8_array(const ACE_CDR::Int8* x, ACE_CDR::ULong length);
     522             :   bool write_uint8_array(const ACE_CDR::UInt8* x, ACE_CDR::ULong length);
     523             : #endif
     524             :   bool write_short_array(const ACE_CDR::Short* x, ACE_CDR::ULong length);
     525             :   bool write_ushort_array(const ACE_CDR::UShort* x, ACE_CDR::ULong length);
     526             :   bool write_long_array(const ACE_CDR::Long* x, ACE_CDR::ULong length);
     527             :   bool write_ulong_array(const ACE_CDR::ULong* x, ACE_CDR::ULong length);
     528             :   bool write_longlong_array(const ACE_CDR::LongLong* x, ACE_CDR::ULong length);
     529             :   bool write_ulonglong_array(const ACE_CDR::ULongLong* x, ACE_CDR::ULong length);
     530             :   bool write_float_array(const ACE_CDR::Float* x, ACE_CDR::ULong length);
     531             :   bool write_double_array(const ACE_CDR::Double* x, ACE_CDR::ULong length);
     532             :   bool write_longdouble_array(const ACE_CDR::LongDouble* x, ACE_CDR::ULong length);
     533             :   ///@}
     534             : 
     535             :   friend OpenDDS_Dcps_Export
     536             :   bool operator<<(Serializer& s, ACE_CDR::Char x);
     537             :   friend OpenDDS_Dcps_Export
     538             :   bool operator<<(Serializer& s, ACE_CDR::Short x);
     539             :   friend OpenDDS_Dcps_Export
     540             :   bool operator<<(Serializer& s, ACE_CDR::UShort x);
     541             :   friend OpenDDS_Dcps_Export
     542             :   bool operator<<(Serializer& s, ACE_CDR::Long x);
     543             :   friend OpenDDS_Dcps_Export
     544             :   bool operator<<(Serializer& s, ACE_CDR::ULong x);
     545             :   friend OpenDDS_Dcps_Export
     546             :   bool operator<<(Serializer& s, ACE_CDR::LongLong x);
     547             :   friend OpenDDS_Dcps_Export
     548             :   bool operator<<(Serializer& s, ACE_CDR::ULongLong x);
     549             :   friend OpenDDS_Dcps_Export
     550             :   bool operator<<(Serializer& s, ACE_CDR::Float x);
     551             :   friend OpenDDS_Dcps_Export
     552             :   bool operator<<(Serializer& s, ACE_CDR::Double x);
     553             :   friend OpenDDS_Dcps_Export
     554             :   bool operator<<(Serializer& s, ACE_CDR::LongDouble x);
     555             :   friend OpenDDS_Dcps_Export
     556             :   bool operator<<(Serializer& s, const ACE_CDR::Char* x);
     557             :   friend OpenDDS_Dcps_Export
     558             :   bool operator<<(Serializer& s, const ACE_CDR::WChar* x);
     559             : 
     560             : #ifdef NONNATIVE_LONGDOUBLE
     561             :   friend OpenDDS_Dcps_Export
     562             :   bool operator<<(Serializer& s, long double x);
     563             : #endif
     564             : 
     565             :   // Using the ACE CDR Stream disambiguators.
     566             :   friend OpenDDS_Dcps_Export
     567             :   bool operator<<(Serializer& s, ACE_OutputCDR::from_boolean x);
     568             :   friend OpenDDS_Dcps_Export
     569             :   bool operator<<(Serializer& s, ACE_OutputCDR::from_char x);
     570             :   friend OpenDDS_Dcps_Export
     571             :   bool operator<<(Serializer& s, ACE_OutputCDR::from_wchar x);
     572             :   friend OpenDDS_Dcps_Export
     573             :   bool operator<<(Serializer& s, ACE_OutputCDR::from_octet x);
     574             :   friend OpenDDS_Dcps_Export
     575             :   bool operator<<(Serializer& s, ACE_OutputCDR::from_string x);
     576             :   friend OpenDDS_Dcps_Export
     577             :   bool operator<<(Serializer& s, ACE_OutputCDR::from_wstring x);
     578             : #if OPENDDS_HAS_EXPLICIT_INTS
     579             :   friend OpenDDS_Dcps_Export
     580             :   bool operator<<(Serializer& s, ACE_OutputCDR::from_uint8 x);
     581             :   friend OpenDDS_Dcps_Export
     582             :   bool operator<<(Serializer& s, ACE_OutputCDR::from_int8 x);
     583             : #endif
     584             : 
     585             :   friend OpenDDS_Dcps_Export
     586             :   bool operator<<(Serializer& s, const String& x);
     587             : 
     588             :   template <typename CharT>
     589             :   struct FromBoundedString {
     590             :     typedef std::basic_string<CharT, std::char_traits<CharT>,
     591             :                               OPENDDS_ALLOCATOR(CharT) > string_t;
     592           0 :     FromBoundedString(const string_t& str, ACE_CDR::ULong bound)
     593           0 :       : str_(str), bound_(bound) {}
     594             :     const string_t& str_;
     595             :     const ACE_CDR::ULong bound_;
     596             :   };
     597             : 
     598             :   friend OpenDDS_Dcps_Export
     599             :   bool operator<<(Serializer& s, FromBoundedString<char> x);
     600             : 
     601             : #ifdef DDS_HAS_WCHAR
     602             :   friend OpenDDS_Dcps_Export
     603             :   bool operator<<(Serializer& s, const WString& x);
     604             : 
     605             :   friend OpenDDS_Dcps_Export
     606             :   bool operator<<(Serializer& s, FromBoundedString<wchar_t> x);
     607             : #endif /* DDS_HAS_WCHAR */
     608             : 
     609             :   // Extraction operators.
     610             :   friend OpenDDS_Dcps_Export
     611             :   bool operator>>(Serializer& s, ACE_CDR::Char& x);
     612             :   friend OpenDDS_Dcps_Export
     613             :   bool operator>>(Serializer& s, ACE_CDR::Short& x);
     614             :   friend OpenDDS_Dcps_Export
     615             :   bool operator>>(Serializer& s, ACE_CDR::UShort& x);
     616             :   friend OpenDDS_Dcps_Export
     617             :   bool operator>>(Serializer& s, ACE_CDR::Long& x);
     618             :   friend OpenDDS_Dcps_Export
     619             :   bool operator>>(Serializer& s, ACE_CDR::ULong& x);
     620             :   friend OpenDDS_Dcps_Export
     621             :   bool operator>>(Serializer& s, ACE_CDR::LongLong& x);
     622             :   friend OpenDDS_Dcps_Export
     623             :   bool operator>>(Serializer& s, ACE_CDR::ULongLong& x);
     624             :   friend OpenDDS_Dcps_Export
     625             :   bool operator>>(Serializer& s, ACE_CDR::Float& x);
     626             :   friend OpenDDS_Dcps_Export
     627             :   bool operator>>(Serializer& s, ACE_CDR::Double& x);
     628             :   friend OpenDDS_Dcps_Export
     629             :   bool operator>>(Serializer& s, ACE_CDR::LongDouble& x);
     630             :   friend OpenDDS_Dcps_Export
     631             :   bool operator>>(Serializer& s, ACE_CDR::Char*& x);
     632             :   friend OpenDDS_Dcps_Export
     633             :   bool operator>>(Serializer& s, ACE_CDR::WChar*& x);
     634             : 
     635             : #ifdef NONNATIVE_LONGDOUBLE
     636             :   friend OpenDDS_Dcps_Export
     637             :   bool operator>>(Serializer& s, long double& x);
     638             : #endif
     639             : 
     640             :   // Using the ACE CDR Stream disambiguators.
     641             :   friend OpenDDS_Dcps_Export
     642             :   bool operator>>(Serializer& s, ACE_InputCDR::to_boolean x);
     643             :   friend OpenDDS_Dcps_Export
     644             :   bool operator>>(Serializer& s, ACE_InputCDR::to_char x);
     645             :   friend OpenDDS_Dcps_Export
     646             :   bool operator>>(Serializer& s, ACE_InputCDR::to_wchar x);
     647             :   friend OpenDDS_Dcps_Export
     648             :   bool operator>>(Serializer& s, ACE_InputCDR::to_octet x);
     649             :   friend OpenDDS_Dcps_Export
     650             :   bool operator>>(Serializer& s, ACE_InputCDR::to_string x);
     651             :   friend OpenDDS_Dcps_Export
     652             :   bool operator>>(Serializer& s, ACE_InputCDR::to_wstring x);
     653             : #if OPENDDS_HAS_EXPLICIT_INTS
     654             :   friend OpenDDS_Dcps_Export
     655             :   bool operator>>(Serializer& s, ACE_InputCDR::to_uint8 x);
     656             :   friend OpenDDS_Dcps_Export
     657             :   bool operator>>(Serializer& s, ACE_InputCDR::to_int8 x);
     658             : #endif
     659             : 
     660             :   friend OpenDDS_Dcps_Export
     661             :   bool operator>>(Serializer& s, String& x);
     662             : 
     663             :   template <typename CharT>
     664             :   struct ToBoundedString {
     665             :     typedef std::basic_string<CharT, std::char_traits<CharT>,
     666             :                               OPENDDS_ALLOCATOR(CharT) > string_t;
     667        1026 :     ToBoundedString(string_t& str, ACE_CDR::ULong bound)
     668        1026 :       : str_(str), bound_(bound) {}
     669             :     string_t& str_;
     670             :     const ACE_CDR::ULong bound_;
     671             :   };
     672             : 
     673             :   friend OpenDDS_Dcps_Export
     674             :   bool operator>>(Serializer& s, ToBoundedString<char> x);
     675             : 
     676             : #ifdef DDS_HAS_WCHAR
     677             :   friend OpenDDS_Dcps_Export
     678             :   bool operator>>(Serializer& s, WString& x);
     679             : 
     680             :   friend OpenDDS_Dcps_Export
     681             :   bool operator>>(Serializer& s, ToBoundedString<wchar_t> x);
     682             : #endif /* DDS_HAS_WCHAR */
     683             : 
     684             :   /// Read from the chain into a destination buffer.
     685             :   // This method doesn't respect alignment, so use with care.
     686             :   // Any of the other public methods (which know the type) are preferred.
     687             :   void buffer_read(char* dest, size_t size, bool swap);
     688             : 
     689             :   /// Align for reading: moves current_->rd_ptr() past the alignment padding.
     690             :   /// Alignments of 2, 4, or 8 are supported by CDR and this implementation.
     691             :   bool align_r(size_t alignment);
     692             : 
     693             :   /// Align for writing: moves current_->wr_ptr() past the padding, possibly
     694             :   /// zero-filling the pad bytes (based on the alignment_ setting).
     695             :   /// Alignments of 2, 4, or 8 are supported by CDR and this implementation.
     696             :   bool align_w(size_t alignment);
     697             : 
     698             :   /**
     699             :    * Read a XCDR parameter ID used in XCDR parameter lists.
     700             :    *
     701             :    * Returns true if successful.
     702             :    */
     703             :   bool read_parameter_id(unsigned& id, size_t& size, bool& must_understand);
     704             : 
     705             :   /**
     706             :    * Write a XCDR parameter ID used in XCDR parameter lists.
     707             :    *
     708             :    * Returns true if successful.
     709             :    */
     710             :   bool write_parameter_id(const unsigned id, size_t size, bool must_understand = false);
     711             : 
     712             :   /**
     713             :    * Write the parameter ID that marks the end of XCDR1 parameter lists.
     714             :    *
     715             :    * Returns true if successful.
     716             :    */
     717             :   bool write_list_end_parameter_id();
     718             : 
     719             :   /**
     720             :    * Skip a delimiter used for XCDR2 delimited data.
     721             :    *
     722             :    * Returns true if successful
     723             :    */
     724             :   bool skip_delimiter();
     725             : 
     726             :   /**
     727             :    * Read a delimiter used for XCDR2 delimited data.
     728             :    *
     729             :    * Returns true if successful and size will be set to the size of the CDR
     730             :    * value excluding the delimiter.
     731             :    */
     732             :   bool read_delimiter(size_t& size);
     733             : 
     734             :   /**
     735             :    * Write a delimiter used for XCDR2 delimited data.
     736             :    *
     737             :    * Size is assumed to include the delimiter as serialized_size would return.
     738             :    * Returns true if successful.
     739             :    */
     740             :   bool write_delimiter(size_t size);
     741             : 
     742             :   enum ConstructionStatus {
     743             :     ConstructionSuccessful,
     744             :     ElementConstructionFailure,
     745             :     BoundConstructionFailure
     746             :   };
     747             : 
     748             :   ConstructionStatus get_construction_status() const;
     749             : 
     750             :   void set_construction_status(ConstructionStatus cs);
     751             : 
     752             :   struct OpenDDS_Dcps_Export ScopedAlignmentContext {
     753             :     explicit ScopedAlignmentContext(Serializer& ser, size_t min_read = 0);
     754          55 :     virtual ~ScopedAlignmentContext() { restore(ser_); }
     755             : 
     756             :     void restore(Serializer& ser) const;
     757             : 
     758             :     Serializer& ser_;
     759             :     const size_t max_align_;
     760             :     const size_t start_rpos_;
     761             :     const size_t rblock_;
     762             :     const size_t min_read_;
     763             :     const size_t start_wpos_;
     764             :     const size_t wblock_;
     765             :   };
     766             : 
     767             :   template <typename T>
     768         138 :   bool peek_helper(ACE_Message_Block* const block, size_t bytes, T& t)
     769             :   {
     770         138 :     bool result = false;
     771         138 :     char* const rd_ptr = block->rd_ptr();
     772         138 :     const size_t length = block->length();
     773         138 :     if (!block->cont() || length == 0 || (bytes != 0 && bytes <= length)) {
     774         118 :       result = *this >> t;
     775             :     } else {
     776          20 :       result = peek_helper(block->cont(), bytes - length, t);
     777             :     }
     778         138 :     block->rd_ptr(rd_ptr);
     779         138 :     return result;
     780             :   }
     781             : 
     782             :   template <typename T>
     783             :   bool peek(T& t)
     784             :   {
     785             :     // save
     786             :     const size_t rpos = rpos_;
     787             :     const unsigned char align_rshift = align_rshift_;
     788             :     ACE_Message_Block* const current = current_;
     789             : 
     790             :     // read
     791             :     if (!peek_helper(current_, 0, t)) {
     792             :       return false;
     793             :     }
     794             : 
     795             :     // reset
     796             :     current_ = current;
     797             :     align_rshift_ = align_rshift;
     798             :     rpos_ = rpos;
     799             :     return true;
     800             :   }
     801             : 
     802             :   bool peek(ACE_CDR::ULong& t);
     803             : 
     804             :   // This is used by DynamicData and must have all reading-related members of
     805             :   // of Serializer for DynamicData to work correctly.
     806             :   struct RdState {
     807         418 :     explicit RdState(unsigned char shift = 0, size_t pos = 0)
     808         418 :       : align_rshift(shift), rpos(pos) {}
     809             :     unsigned char align_rshift;
     810             :     size_t rpos;
     811             :   };
     812             : 
     813             :   RdState rdstate() const;
     814             :   void rdstate(const RdState& state);
     815             : 
     816             : private:
     817             :   ///@{
     818             :   /// Read an array of values from the chain.
     819             :   /// NOTE: This assumes that the buffer contains elements that are
     820             :   ///       properly aligned.  The buffer must have padding if the
     821             :   ///       elements are not naturally aligned; or this routine should
     822             :   ///       not be used.
     823             :   void read_array(char* x, size_t size, ACE_CDR::ULong length);
     824             :   void read_array(char* x, size_t size, ACE_CDR::ULong length, bool swap);
     825             :   ///@}
     826             : 
     827             :   /// Write to the chain from a source buffer.
     828             :   void buffer_write(const char* src, size_t size, bool swap);
     829             : 
     830             :   ///@{
     831             :   /// Write an array of values to the chain.
     832             :   /// NOTE: This assumes that there is _no_ padding between the array
     833             :   ///       elements.  If this is not the case, do not use this
     834             :   ///       method.  If padding exists in the array, it will be
     835             :   ///       written when _not_ swapping, and will _not_ be written
     836             :   ///       when swapping, resulting in corrupted data.
     837             :   void write_array(const char* x, size_t size, ACE_CDR::ULong length);
     838             :   void write_array(const char* x, size_t size, ACE_CDR::ULong length, bool swap);
     839             :   ///@}
     840             : 
     841             :   /// Efficient straight copy for quad words and shorter.  This is
     842             :   /// an instance method to match the swapcpy semantics.
     843             :   void smemcpy(char* to, const char* from, size_t n);
     844             : 
     845             :   /// Efficient swapping copy for quad words and shorter.  This is an
     846             :   /// instance method to allow clearing the good_bit_ on error.
     847             :   void swapcpy(char* to, const char* from, size_t n);
     848             : 
     849             :   /// Implementation of the actual read from the chain.
     850             :   size_t doread(char* dest, size_t size, bool swap, size_t offset);
     851             : 
     852             :   /// Implementation of the actual write to the chain.
     853             :   size_t dowrite(const char* dest, size_t size, bool swap, size_t offset);
     854             : 
     855             :   /// Update alignment state when a cont() chain is followed during a read.
     856             :   void align_cont_r();
     857             : 
     858             :   /// Update alignment state when a cont() chain is followed during a write.
     859             :   void align_cont_w();
     860             : 
     861             :   static unsigned char offset(char* index, size_t start, size_t align);
     862             : 
     863             :   /// Currently active message block in chain.
     864             :   ACE_Message_Block* current_;
     865             : 
     866             :   /// Encoding Settings
     867             :   Encoding encoding_;
     868             : 
     869             :   /// Indicates whether bytes will be swapped for this stream.
     870             :   bool swap_bytes_;
     871             : 
     872             :   /// Indicates the current state of the stream abstraction.
     873             :   bool good_bit_;
     874             : 
     875             :   /// The way to judge whether tryconstruct trim is able to be properly done
     876             :   ConstructionStatus construction_status_;
     877             : 
     878             :   /**
     879             :    * Number of bytes off of max alignment that the current_ block's rd_ptr()
     880             :    * started at.
     881             :    */
     882             :   unsigned char align_rshift_;
     883             : 
     884             :   /**
     885             :    * Number of bytes off of max alignment that the current_ block's wr_ptr()
     886             :    * started at.
     887             :    */
     888             :   unsigned char align_wshift_;
     889             : 
     890             :   /// Logical reading position of the stream.
     891             :   size_t rpos_;
     892             : 
     893             :   /// Logical writing position of the stream.
     894             :   size_t wpos_;
     895             : 
     896             :   /// Buffer that is copied for zero padding
     897             :   static const char ALIGN_PAD[Encoding::ALIGN_MAX];
     898             : };
     899             : 
     900             : template<typename Type>
     901             : struct KeyOnly {
     902          10 :   explicit KeyOnly(Type& value)
     903          10 :     : value(value)
     904             :   {
     905          10 :   }
     906             : 
     907             :   operator Type&() const
     908             :   {
     909             :     return value;
     910             :   }
     911             : 
     912             :   Type& value;
     913             : };
     914             : 
     915             : template<typename Type>
     916             : struct NestedKeyOnly {
     917           0 :   explicit NestedKeyOnly(Type& value)
     918           0 :     : value(value)
     919             :   {
     920           0 :   }
     921             : 
     922             :   operator Type&() const
     923             :   {
     924             :     return value;
     925             :   }
     926             : 
     927             :   Type& value;
     928             : };
     929             : 
     930             : namespace IDL {
     931             :   // Although similar to C++11 reference_wrapper, this template has the
     932             :   // additional Tag parameter to allow the IDL compiler to generate distinct
     933             :   // overloads for sequence/array typedefs that map to the same C++ types.
     934             :   template <typename T, typename /*Tag*/>
     935             :   struct DistinctType {
     936             :     typedef T value_type;
     937             :     T* val_;
     938           0 :     DistinctType(T& val) : val_(&val) {}
     939             :     operator T&() const { return *val_; }
     940             :   };
     941             : }
     942             : 
     943             : template<typename Type>
     944             : void set_default(Type&)
     945             : {
     946             :   OPENDDS_ASSERT(false);
     947             : }
     948             : 
     949             : template<typename Type, typename Tag>
     950             : void set_default(IDL::DistinctType<Type, Tag>)
     951             : {
     952             :   OPENDDS_ASSERT(false);
     953             : }
     954             : 
     955             : // predefined type methods
     956             : OpenDDS_Dcps_Export
     957             : bool primitive_serialized_size(
     958             :   const Encoding& encoding, size_t& size, const ACE_CDR::Short& value,
     959             :   size_t count = 1);
     960             : OpenDDS_Dcps_Export
     961             : bool primitive_serialized_size(
     962             :   const Encoding& encoding, size_t& size, const ACE_CDR::UShort& value,
     963             :   size_t count = 1);
     964             : OpenDDS_Dcps_Export
     965             : bool primitive_serialized_size(
     966             :   const Encoding& encoding, size_t& size, const ACE_CDR::Long& value,
     967             :   size_t count = 1);
     968             : OpenDDS_Dcps_Export
     969             : bool primitive_serialized_size(
     970             :   const Encoding& encoding, size_t& size, const ACE_CDR::ULong& value,
     971             :   size_t count = 1);
     972             : OpenDDS_Dcps_Export
     973             : bool primitive_serialized_size(
     974             :   const Encoding& encoding, size_t& size, const ACE_CDR::LongLong& value,
     975             :   size_t count = 1);
     976             : OpenDDS_Dcps_Export
     977             : bool primitive_serialized_size(
     978             :   const Encoding& encoding, size_t& size, const ACE_CDR::ULongLong& value,
     979             :   size_t count = 1);
     980             : OpenDDS_Dcps_Export
     981             : bool primitive_serialized_size(
     982             :   const Encoding& encoding, size_t& size, const ACE_CDR::Float& value,
     983             :   size_t count = 1);
     984             : OpenDDS_Dcps_Export
     985             : bool primitive_serialized_size(
     986             :   const Encoding& encoding, size_t& size, const ACE_CDR::Double& value,
     987             :   size_t count = 1);
     988             : OpenDDS_Dcps_Export
     989             : bool primitive_serialized_size(
     990             :   const Encoding& encoding, size_t& size, const ACE_CDR::LongDouble& value,
     991             :   size_t count = 1);
     992             : 
     993             : // predefined type method disambiguators.
     994             : OpenDDS_Dcps_Export
     995             : bool primitive_serialized_size(
     996             :   const Encoding& encoding, size_t& size,
     997             :   const ACE_OutputCDR::from_boolean value, size_t count = 1);
     998             : OpenDDS_Dcps_Export
     999             : bool primitive_serialized_size(
    1000             :   const Encoding& encoding, size_t& size,
    1001             :   const ACE_OutputCDR::from_char value, size_t count = 1);
    1002             : OpenDDS_Dcps_Export
    1003             : bool primitive_serialized_size(
    1004             :   const Encoding& encoding, size_t& size,
    1005             :   const ACE_OutputCDR::from_wchar value, size_t count = 1);
    1006             : OpenDDS_Dcps_Export
    1007             : bool primitive_serialized_size(
    1008             :   const Encoding& encoding, size_t& size,
    1009             :   const ACE_OutputCDR::from_octet value, size_t count = 1);
    1010             : #if OPENDDS_HAS_EXPLICIT_INTS
    1011             : OpenDDS_Dcps_Export
    1012             : bool primitive_serialized_size(
    1013             :   const Encoding& encoding, size_t& size,
    1014             :   const ACE_OutputCDR::from_uint8 value, size_t count = 1);
    1015             : OpenDDS_Dcps_Export
    1016             : bool primitive_serialized_size(
    1017             :   const Encoding& encoding, size_t& size,
    1018             :   const ACE_OutputCDR::from_int8 value, size_t count = 1);
    1019             : #endif
    1020             : 
    1021             : // predefined type method explicit disambiguators.
    1022             : OpenDDS_Dcps_Export
    1023             : void primitive_serialized_size_boolean(const Encoding& encoding, size_t& size,
    1024             :   size_t count = 1);
    1025             : OpenDDS_Dcps_Export
    1026             : void primitive_serialized_size_char(const Encoding& encoding, size_t& size,
    1027             :   size_t count = 1);
    1028             : OpenDDS_Dcps_Export
    1029             : void primitive_serialized_size_wchar(const Encoding& encoding, size_t& size,
    1030             :   size_t count = 1);
    1031             : OpenDDS_Dcps_Export
    1032             : void primitive_serialized_size_octet(const Encoding& encoding, size_t& size,
    1033             :   size_t count = 1);
    1034             : OpenDDS_Dcps_Export
    1035             : void primitive_serialized_size_ulong(const Encoding& encoding, size_t& size,
    1036             :   size_t count = 1);
    1037             : #if OPENDDS_HAS_EXPLICIT_INTS
    1038             : OpenDDS_Dcps_Export
    1039             : void primitive_serialized_size_uint8(const Encoding& encoding, size_t& size,
    1040             :   size_t count = 1);
    1041             : OpenDDS_Dcps_Export
    1042             : void primitive_serialized_size_int8(const Encoding& encoding, size_t& size,
    1043             :   size_t count = 1);
    1044             : #endif
    1045             : 
    1046             : /// Add delimiter to the size of a serialized size if the encoding has them.
    1047             : OpenDDS_Dcps_Export
    1048             : void serialized_size_delimiter(const Encoding& encoding, size_t& size);
    1049             : 
    1050             : OpenDDS_Dcps_Export
    1051             : void serialized_size_parameter_id(
    1052             :   const Encoding& encoding, size_t& size, size_t& running_size);
    1053             : 
    1054             : OpenDDS_Dcps_Export
    1055             : void serialized_size_list_end_parameter_id(
    1056             :   const Encoding& encoding, size_t& size, size_t& running_size);
    1057             : 
    1058             : } // namespace DCPS
    1059             : } // namespace OpenDDS
    1060             : 
    1061             : OPENDDS_END_VERSIONED_NAMESPACE_DECL
    1062             : 
    1063             : #ifdef __ACE_INLINE__
    1064             : #  include "Serializer.inl"
    1065             : #endif
    1066             : 
    1067             : #endif /* OPENDDS_DCPS_SERIALIZER_H */

Generated by: LCOV version 1.16