Serializer.h

Go to the documentation of this file.
00001 /*
00002  *
00003  *
00004  * Distributed under the OpenDDS License.
00005  * See: http://www.opendds.org/license.html
00006  */
00007 
00008 #ifndef OPENDDS_DCPS_SERIALIZER_H
00009 #define OPENDDS_DCPS_SERIALIZER_H
00010 
00011 #include "ace/CDR_Base.h"
00012 #include "ace/CDR_Stream.h"
00013 #include "tao/String_Alloc.h"
00014 
00015 #include "dcps_export.h"
00016 
00017 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00018 #pragma once
00019 #endif /* ACE_LACKS_PRAGMA_ONCE */
00020 
00021 #include "dds/DCPS/Definitions.h"
00022 
00023 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00024 class ACE_Message_Block;
00025 ACE_END_VERSIONED_NAMESPACE_DECL
00026 
00027 OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
00028 
00029 namespace OpenDDS {
00030 namespace DCPS {
00031 
00032 /**
00033  * @class Serializer
00034  *
00035  * @brief Class to serialize and deserialize data for DDS.
00036  *
00037  * This class provides a mechanism to insert and extract data to and
00038  * from an ACE_Message_Block chain that represents the data which
00039  * can be transported on the wire to other DDS service participants.
00040  */
00041 class OpenDDS_Dcps_Export Serializer {
00042 public:
00043 
00044   enum Alignment {
00045     ALIGN_NONE,           // no alignment needed
00046     ALIGN_INITIALIZE,     // align to CDR rules and zero-out padding
00047     ALIGN_CDR             // align to CDR rules with uninitialized padding
00048 #ifdef ACE_INITIALIZE_MEMORY_BEFORE_USE
00049       = ALIGN_INITIALIZE  // if the above macro is set, always init padding
00050 #endif
00051   };
00052 
00053 
00054   /**
00055    * Constructor with a message block chain.  This installs the
00056    * message block chain and sets the current block to the first in
00057    * the chain.  Memory management is the responsibility of the owner
00058    * of this object, and is not performed internally.  Ownership of
00059    * the message block chain is retained by the owner of this object
00060    * and the lifetime of the chain must be longer than the use of
00061    * this object.
00062    *
00063    * Bytes are swapped when either reading or writing from the
00064    * message chain if the swap_bytes argument is true.  It is the
00065    * responsibility of the owner of this object to determine whether
00066    * this should be performed or not.
00067    */
00068   explicit Serializer(ACE_Message_Block* chain,
00069                       bool swap_bytes = false,
00070                       Alignment align = ALIGN_NONE);
00071 
00072   virtual ~Serializer();
00073 
00074   /// Establish byte swapping behavior.
00075   void swap_bytes(bool do_swap);
00076 
00077   /// Examine byte swapping behavior.
00078   bool swap_bytes() const;
00079 
00080   /// Examine alignment behavior.
00081   Alignment alignment() const;
00082 
00083   /// Reset alignment as if a new instance were created
00084   void reset_alignment();
00085 
00086   /// Examine the state of the stream abstraction.
00087   bool good_bit() const;
00088 
00089   /// Number of bytes left to read in message block chain
00090   size_t length() const;
00091 
00092   /// Read a narrow string.
00093   size_t read_string(ACE_CDR::Char*& dest,
00094     ACE_CDR::Char* str_alloc(ACE_CDR::ULong) = CORBA::string_alloc,
00095     void str_free(ACE_CDR::Char*) = CORBA::string_free);
00096 
00097   /// Read a wide string.
00098   size_t read_string(ACE_CDR::WChar*& dest,
00099     ACE_CDR::WChar* str_alloc(ACE_CDR::ULong) = CORBA::wstring_alloc,
00100     void str_free(ACE_CDR::WChar*) = CORBA::wstring_free);
00101 
00102   /// Skip the logical rd_ptr() over a given number of bytes = n * size.
00103   /// If alignment is enabled, skips any padding to align to 'size' before
00104   /// skipping the n * size bytes.
00105   /// This is used by the RTPS protocol to allow reading messages from
00106   /// future versions of the spec which may have additional optional fields.
00107   bool skip(ACE_CDR::UShort n, int size = 1);
00108 
00109   size_t available_r() const { return current_ ? current_->total_length() : 0; }
00110 
00111   /**
00112    * The buffer @a x must be large enough to contain @a length
00113    * elements.
00114    * Return @c false on failure and @c true on success.
00115    */
00116   //@{ @name Read basic IDL types arrays
00117   bool read_boolean_array(ACE_CDR::Boolean* x, ACE_CDR::ULong length);
00118   bool read_char_array(ACE_CDR::Char* x, ACE_CDR::ULong length);
00119   bool read_wchar_array(ACE_CDR::WChar* x, ACE_CDR::ULong length);
00120   bool read_octet_array(ACE_CDR::Octet* x, ACE_CDR::ULong length);
00121   bool read_short_array(ACE_CDR::Short* x, ACE_CDR::ULong length);
00122   bool read_ushort_array(ACE_CDR::UShort* x, ACE_CDR::ULong length);
00123   bool read_long_array(ACE_CDR::Long* x, ACE_CDR::ULong length);
00124   bool read_ulong_array(ACE_CDR::ULong* x, ACE_CDR::ULong length);
00125   bool read_longlong_array(ACE_CDR::LongLong* x, ACE_CDR::ULong length);
00126   bool read_ulonglong_array(ACE_CDR::ULongLong* x, ACE_CDR::ULong length);
00127   bool read_float_array(ACE_CDR::Float* x, ACE_CDR::ULong length);
00128   bool read_double_array(ACE_CDR::Double* x, ACE_CDR::ULong length);
00129   bool read_longdouble_array(ACE_CDR::LongDouble* x, ACE_CDR::ULong length);
00130   //@}
00131 
00132   /// Note: the portion written starts at x and ends
00133   ///    at x + length.
00134   /// The length is *NOT* stored into the CDR stream.
00135   //@{ @name Array write operations
00136   bool write_boolean_array(const ACE_CDR::Boolean* x, ACE_CDR::ULong length);
00137   bool write_char_array(const ACE_CDR::Char* x, ACE_CDR::ULong length);
00138   bool write_wchar_array(const ACE_CDR::WChar* x, ACE_CDR::ULong length);
00139   bool write_octet_array(const ACE_CDR::Octet* x, ACE_CDR::ULong length);
00140   bool write_short_array(const ACE_CDR::Short* x, ACE_CDR::ULong length);
00141   bool write_ushort_array(const ACE_CDR::UShort* x, ACE_CDR::ULong length);
00142   bool write_long_array(const ACE_CDR::Long* x, ACE_CDR::ULong length);
00143   bool write_ulong_array(const ACE_CDR::ULong* x, ACE_CDR::ULong length);
00144   bool write_longlong_array(const ACE_CDR::LongLong* x, ACE_CDR::ULong length);
00145   bool write_ulonglong_array(const ACE_CDR::ULongLong* x, ACE_CDR::ULong length);
00146   bool write_float_array(const ACE_CDR::Float* x, ACE_CDR::ULong length);
00147   bool write_double_array(const ACE_CDR::Double* x, ACE_CDR::ULong length);
00148   bool write_longdouble_array(const ACE_CDR::LongDouble* x, ACE_CDR::ULong length);
00149   //@}
00150 
00151   // Insertion operators.
00152   friend OpenDDS_Dcps_Export
00153   bool operator<<(Serializer& s, ACE_CDR::Char x);
00154   friend OpenDDS_Dcps_Export
00155   bool operator<<(Serializer& s, ACE_CDR::Short x);
00156   friend OpenDDS_Dcps_Export
00157   bool operator<<(Serializer& s, ACE_CDR::UShort x);
00158   friend OpenDDS_Dcps_Export
00159   bool operator<<(Serializer& s, ACE_CDR::Long x);
00160   friend OpenDDS_Dcps_Export
00161   bool operator<<(Serializer& s, ACE_CDR::ULong x);
00162   friend OpenDDS_Dcps_Export
00163   bool operator<<(Serializer& s, ACE_CDR::LongLong x);
00164   friend OpenDDS_Dcps_Export
00165   bool operator<<(Serializer& s, ACE_CDR::ULongLong x);
00166   friend OpenDDS_Dcps_Export
00167   bool operator<<(Serializer& s, ACE_CDR::LongDouble x);
00168   friend OpenDDS_Dcps_Export
00169   bool operator<<(Serializer& s, ACE_CDR::Float x);
00170   friend OpenDDS_Dcps_Export
00171   bool operator<<(Serializer& s, ACE_CDR::Double x);
00172   friend OpenDDS_Dcps_Export
00173   bool operator<<(Serializer& s, const ACE_CDR::Char* x);
00174   friend OpenDDS_Dcps_Export
00175   bool operator<<(Serializer& s, const ACE_CDR::WChar* x);
00176 
00177   // Using the ACE CDR Stream disambiguators.
00178   friend OpenDDS_Dcps_Export
00179   bool operator<<(Serializer& s, ACE_OutputCDR::from_boolean x);
00180   friend OpenDDS_Dcps_Export
00181   bool operator<<(Serializer& s, ACE_OutputCDR::from_char x);
00182   friend OpenDDS_Dcps_Export
00183   bool operator<<(Serializer& s, ACE_OutputCDR::from_wchar x);
00184   friend OpenDDS_Dcps_Export
00185   bool operator<<(Serializer& s, ACE_OutputCDR::from_octet x);
00186   friend OpenDDS_Dcps_Export
00187   bool operator<<(Serializer& s, ACE_OutputCDR::from_string x);
00188   friend OpenDDS_Dcps_Export
00189   bool operator<<(Serializer& s, ACE_OutputCDR::from_wstring x);
00190 
00191 #ifndef OPENDDS_SAFETY_PROFILE
00192   friend OpenDDS_Dcps_Export
00193   bool operator<<(Serializer& s, const std::string& x);
00194 #ifdef DDS_HAS_WCHAR
00195   friend OpenDDS_Dcps_Export
00196   bool operator<<(Serializer& s, const std::wstring& x);
00197 #endif /* DDS_HAS_WCHAR */
00198 #endif /* !OPENDDS_SAFETYP_PROFILE */
00199 
00200   // Extraction operators.
00201   friend OpenDDS_Dcps_Export
00202   bool operator>>(Serializer& s, ACE_CDR::Char& x);
00203   friend OpenDDS_Dcps_Export
00204   bool operator>>(Serializer& s, ACE_CDR::Short& x);
00205   friend OpenDDS_Dcps_Export
00206   bool operator>>(Serializer& s, ACE_CDR::UShort& x);
00207   friend OpenDDS_Dcps_Export
00208   bool operator>>(Serializer& s, ACE_CDR::Long& x);
00209   friend OpenDDS_Dcps_Export
00210   bool operator>>(Serializer& s, ACE_CDR::ULong& x);
00211   friend OpenDDS_Dcps_Export
00212   bool operator>>(Serializer& s, ACE_CDR::LongLong& x);
00213   friend OpenDDS_Dcps_Export
00214   bool operator>>(Serializer& s, ACE_CDR::ULongLong& x);
00215   friend OpenDDS_Dcps_Export
00216   bool operator>>(Serializer& s, ACE_CDR::LongDouble& x);
00217   friend OpenDDS_Dcps_Export
00218   bool operator>>(Serializer& s, ACE_CDR::Float& x);
00219   friend OpenDDS_Dcps_Export
00220   bool operator>>(Serializer& s, ACE_CDR::Double& x);
00221   friend OpenDDS_Dcps_Export
00222   bool operator>>(Serializer& s, ACE_CDR::Char*& x);
00223   friend OpenDDS_Dcps_Export
00224   bool operator>>(Serializer& s, ACE_CDR::WChar*& x);
00225 
00226   // Using the ACE CDR Stream disambiguators.
00227   friend OpenDDS_Dcps_Export
00228   bool operator>>(Serializer& s, ACE_InputCDR::to_boolean x);
00229   friend OpenDDS_Dcps_Export
00230   bool operator>>(Serializer& s, ACE_InputCDR::to_char x);
00231   friend OpenDDS_Dcps_Export
00232   bool operator>>(Serializer& s, ACE_InputCDR::to_wchar x);
00233   friend OpenDDS_Dcps_Export
00234   bool operator>>(Serializer& s, ACE_InputCDR::to_octet x);
00235   friend OpenDDS_Dcps_Export
00236   bool operator>>(Serializer& s, ACE_InputCDR::to_string x);
00237   friend OpenDDS_Dcps_Export
00238   bool operator>>(Serializer& s, ACE_InputCDR::to_wstring x);
00239 
00240 #ifndef OPENDDS_SAFETY_PROFILE
00241   friend OpenDDS_Dcps_Export
00242   bool operator>>(Serializer& s, std::string& x);
00243 #ifdef DDS_HAS_WCHAR
00244   friend OpenDDS_Dcps_Export
00245   bool operator>>(Serializer& s, std::wstring& x);
00246 #endif /* DDS_HAS_WCHAR */
00247 #endif /* !OPENDDS_SAFETY_PROFILE */
00248 
00249   /// Read from the chain into a destination buffer.
00250   // This method doesn't respect alignment, so use with care.
00251   // Any of the other public methods (which know the type) are preferred.
00252   void buffer_read(char* dest, size_t size, bool swap);
00253 
00254   /// Align for reading: moves current_->rd_ptr() past the alignment padding.
00255   /// Alignments of 2, 4, or 8 are supported by CDR and this implementation.
00256   int align_r(size_t alignment);
00257 
00258   /// Align for writing: moves current_->wr_ptr() past the padding, possibly
00259   /// zero-filling the pad bytes (based on the alignment_ setting).
00260   /// Alignments of 2, 4, or 8 are supported by CDR and this implementation.
00261   int align_w(size_t alignment);
00262 
00263 private:
00264   /// Read an array of values from the chain.
00265   /// NOTE: This assumes that the buffer contains elements that are
00266   ///       properly aligned.  The buffer must have padding if the
00267   ///       elements are not naturally aligned; or this routine should
00268   ///       not be used.
00269   void read_array(char* x, size_t size, ACE_CDR::ULong length);
00270   void read_array(char* x, size_t size, ACE_CDR::ULong length, bool swap);
00271 
00272   /// Write to the chain from a source buffer.
00273   void buffer_write(const char* src, size_t size, bool swap);
00274 
00275   /// Write an array of values to the chain.
00276   /// NOTE: This assumes that there is _no_ padding between the array
00277   ///       elements.  If this is not the case, do not use this
00278   ///       method.  If padding exists in the array, it will be
00279   ///       written when _not_ swapping, and will _not_ be written
00280   ///       when swapping, resulting in corrupted data.
00281   void write_array(const char* x, size_t size, ACE_CDR::ULong length);
00282   void write_array(const char* x, size_t size, ACE_CDR::ULong length, bool swap);
00283 
00284   /// Efficient straight copy for quad words and shorter.  This is
00285   /// an instance method to match the swapcpy semantics.
00286   void smemcpy(char* to, const char* from, size_t n);
00287 
00288   /// Efficient swapping copy for quad words and shorter.  This is an
00289   /// instance method to allow clearing the good_bit_ on error.
00290   void swapcpy(char* to, const char* from, size_t n);
00291 
00292   /// Implementation of the actual read from the chain.
00293   size_t doread(char* dest, size_t size, bool swap, size_t offset);
00294 
00295   /// Implementation of the actual write to the chain.
00296   size_t dowrite(const char* dest, size_t size, bool swap, size_t offset);
00297 
00298   /// Update alignment state when a cont() chain is followed during a read.
00299   void align_cont_r();
00300 
00301   /// Update alignment state when a cont() chain is followed during a write.
00302   void align_cont_w();
00303 
00304   /// Currently active message block in chain.
00305   ACE_Message_Block* current_;
00306 
00307   /// Indicates whether bytes will be swapped for this stream.
00308   bool swap_bytes_;
00309 
00310   /// Indicates the current state of the stream abstraction.
00311   bool good_bit_;
00312 
00313   /// Current alignment mode, see Alignment enum above.
00314   Alignment alignment_;
00315 
00316   /// Number of bytes off of max alignment (8) that the current_ block's
00317   /// rd_ptr() started at.
00318   unsigned char align_rshift_;
00319 
00320   /// Number of bytes off of max alignment (8) that the current_ block's
00321   /// wr_ptr() started at.
00322   unsigned char align_wshift_;
00323 
00324   static const size_t MAX_ALIGN = 8;
00325   static const char ALIGN_PAD[MAX_ALIGN];
00326   static bool use_rti_serialization_;
00327 
00328 public:
00329   static const size_t WCHAR_SIZE = 2; // Serialize wchar as UTF-16BE
00330 
00331   static bool use_rti_serialization();
00332   static void set_use_rti_serialization(bool should_use);
00333 
00334 #if defined ACE_LITTLE_ENDIAN
00335   static const bool SWAP_BE = true;
00336 #else
00337   static const bool SWAP_BE = false;
00338 #endif
00339 };
00340 
00341 template<typename T> struct KeyOnly {
00342   explicit KeyOnly(T& mess) : t(mess) { }
00343   T& t;
00344 };
00345 
00346 } // namespace DCPS
00347 } // namespace OpenDDS
00348 
00349 OPENDDS_END_VERSIONED_NAMESPACE_DECL
00350 
00351 #if defined (__ACE_INLINE__)
00352 # include "Serializer.inl"
00353 #else  /* __ACE_INLINE__ */
00354 
00355 #include <ace/CDR_Stream.h>
00356 
00357 OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
00358 
00359 namespace OpenDDS {
00360 namespace DCPS {
00361 
00362 // predefined type gen_max_marshaled_size methods
00363 OpenDDS_Dcps_Export
00364 size_t gen_max_marshaled_size(const ACE_CDR::Short& x);
00365 OpenDDS_Dcps_Export
00366 size_t gen_max_marshaled_size(const ACE_CDR::UShort& x);
00367 OpenDDS_Dcps_Export
00368 size_t gen_max_marshaled_size(const ACE_CDR::Long& x);
00369 OpenDDS_Dcps_Export
00370 size_t gen_max_marshaled_size(const ACE_CDR::ULong& x);
00371 OpenDDS_Dcps_Export
00372 size_t gen_max_marshaled_size(const ACE_CDR::LongLong& x);
00373 OpenDDS_Dcps_Export
00374 size_t gen_max_marshaled_size(const ACE_CDR::ULongLong& x);
00375 OpenDDS_Dcps_Export
00376 size_t gen_max_marshaled_size(const ACE_CDR::LongDouble& x);
00377 OpenDDS_Dcps_Export
00378 size_t gen_max_marshaled_size(const ACE_CDR::Float& x);
00379 OpenDDS_Dcps_Export
00380 size_t gen_max_marshaled_size(const ACE_CDR::Double& x);
00381 
00382 // predefined type gen_max_marshaled_size method disambiguators.
00383 OpenDDS_Dcps_Export
00384 size_t gen_max_marshaled_size(const ACE_OutputCDR::from_boolean x);
00385 OpenDDS_Dcps_Export
00386 size_t gen_max_marshaled_size(const ACE_OutputCDR::from_char x);
00387 OpenDDS_Dcps_Export
00388 size_t gen_max_marshaled_size(const ACE_OutputCDR::from_wchar x);
00389 OpenDDS_Dcps_Export
00390 size_t gen_max_marshaled_size(const ACE_OutputCDR::from_octet x);
00391 
00392 /// predefined type max_marshaled_size method explicit disambiguators.
00393 OpenDDS_Dcps_Export
00394 size_t max_marshaled_size_boolean();
00395 OpenDDS_Dcps_Export
00396 size_t max_marshaled_size_char();
00397 OpenDDS_Dcps_Export
00398 size_t max_marshaled_size_wchar();
00399 OpenDDS_Dcps_Export
00400 size_t max_marshaled_size_octet();
00401 
00402 /// lengths of strings and sequences are ulong
00403 OpenDDS_Dcps_Export
00404 size_t max_marshaled_size_ulong();
00405 OpenDDS_Dcps_Export
00406 void find_size_ulong(size_t& size, size_t& padding);
00407 
00408 } // namespace DCPS
00409 } // namespace OpenDDS
00410 
00411 OPENDDS_END_VERSIONED_NAMESPACE_DECL
00412 
00413 
00414 #endif  /* __ACE_INLINE__ */
00415 
00416 #endif /* OPENDDS_DCPS_SERIALIZER_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1