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

Generated on Fri Feb 12 20:05:26 2016 for OpenDDS by  doxygen 1.4.7