// -*- C++ -*- //============================================================================= /** * @file CDR_Base.h * * ACE Common Data Representation (CDR) basic types. * * The current implementation assumes that the host has 1-byte, * 2-byte and 4-byte integral types, and that it has single * precision and double precision IEEE floats. * Those assumptions are pretty good these days, with Crays being * the only known exception. * * @author TAO version by * @author Aniruddha Gokhale * @author Carlos O'Ryan * @author ACE version by * @author Jeff Parsons * @author Istvan Buki */ //============================================================================= #ifndef ACE_CDR_BASE_H #define ACE_CDR_BASE_H #include /**/ "ace/pre.h" #include /**/ "ace/config-all.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/Basic_Types.h" #include "ace/Default_Constants.h" #include "ace/Global_Macros.h" #include "ace/iosfwd.h" #include ACE_BEGIN_VERSIONED_NAMESPACE_DECL // Stuff used by the ACE CDR classes. Watch these values... they're also used // in the ACE_CDR Byte_Order enum below. #if defined ACE_LITTLE_ENDIAN # define ACE_CDR_BYTE_ORDER 1 // little endian encapsulation byte order has value = 1 #else /* ! ACE_LITTLE_ENDIAN */ # define ACE_CDR_BYTE_ORDER 0 // big endian encapsulation byte order has value = 0 #endif /* ! ACE_LITTLE_ENDIAN */ class ACE_Message_Block; /** * @class ACE_CDR * * @brief Keep constants and some routines common to both Output and * Input CDR streams. */ class ACE_Export ACE_CDR { public: // = Constants defined by the CDR protocol. // By defining as many of these constants as possible as enums we // ensure they get inlined and avoid pointless static memory // allocations. enum { // Note that some of these get reused as part of the standard // binary format: unsigned is the same size as its signed cousin, // float is LONG_SIZE, and double is LONGLONG_SIZE. OCTET_SIZE = 1, SHORT_SIZE = 2, LONG_SIZE = 4, LONGLONG_SIZE = 8, LONGDOUBLE_SIZE = 16, OCTET_ALIGN = 1, SHORT_ALIGN = 2, LONG_ALIGN = 4, LONGLONG_ALIGN = 8, /// @note the CORBA LongDouble alignment requirements do not /// match its size... LONGDOUBLE_ALIGN = 8, /// Maximal CDR 1.1 alignment: "quad precision" FP (i.e. "CDR::Long /// double", size as above). MAX_ALIGNMENT = 8, /// The default buffer size. /** * @todo We want to add options to control this * default value, so this constant should be read as the default * default value ;-) */ DEFAULT_BUFSIZE = ACE_DEFAULT_CDR_BUFSIZE, /// The buffer size grows exponentially until it reaches this size; /// afterwards it grows linearly using the next constant EXP_GROWTH_MAX = ACE_DEFAULT_CDR_EXP_GROWTH_MAX, /// Once exponential growth is ruled out the buffer size increases /// in chunks of this size, note that this constants have the same /// value right now, but it does not need to be so. LINEAR_GROWTH_CHUNK = ACE_DEFAULT_CDR_LINEAR_GROWTH_CHUNK }; /** * @enum Byte_Order * * Defines values for the byte_order argument to ACE_OutputCDR and * ACE_InputCDR. */ enum Byte_Order { /// Use big-endian order (also known as network byte order). BYTE_ORDER_BIG_ENDIAN = 0, /// Use little-endian order. BYTE_ORDER_LITTLE_ENDIAN = 1, /// Use whichever byte order is native to this machine. BYTE_ORDER_NATIVE = ACE_CDR_BYTE_ORDER }; /** * Do byte swapping for each basic IDL type size. There exist only * routines to put byte, halfword (2 bytes), word (4 bytes), * doubleword (8 bytes) and quadword (16 byte); because those are * the IDL basic type sizes. */ static void swap_2 (char const *orig, char *target); static void swap_4 (char const *orig, char *target); static void swap_8 (char const *orig, char *target); static void swap_16 (char const *orig, char *target); static void swap_2_array (char const *orig, char *target, size_t length); static void swap_4_array (char const *orig, char *target, size_t length); static void swap_8_array (char const *orig, char *target, size_t length); static void swap_16_array (char const *orig, char *target, size_t length); /// Align the message block to ACE_CDR::MAX_ALIGNMENT, /// set by the CORBA spec at 8 bytes. static void mb_align (ACE_Message_Block *mb); /** * Compute the size of the smallest buffer that can contain at least * @a minsize bytes. * To understand how a "best fit" is computed look at the * algorithm in the code. * Basically the buffers grow exponentially, up to a certain point, * then the buffer size grows linearly. * The advantage of this algorithm is that is rapidly grows to a * large value, but does not explode at the end. */ static size_t first_size (size_t minsize); /// Compute not the smallest, but the second smallest buffer that /// will fir @a minsize bytes. static size_t next_size (size_t minsize); /** * Increase the capacity of mb to contain at least @a minsize bytes. * If @a minsize is zero the size is increased by an amount at least * large enough to contain any of the basic IDL types. * @retval -1 Failure * @retval 0 Success. */ static int grow (ACE_Message_Block *mb, size_t minsize); /** * Copy a message block chain into a single message block, * preserving the alignment of the first message block of the * original stream, not the following message blocks. * @retval -1 Failure * @retval 0 Success. */ static int consolidate (ACE_Message_Block *dst, const ACE_Message_Block *src); static size_t total_length (const ACE_Message_Block *begin, const ACE_Message_Block *end); /** * @name Basic OMG IDL Types * * These types are for use in the CDR classes. The cleanest way to * avoid complaints from all compilers is to define them all. */ //@{ typedef bool Boolean; typedef ACE_Byte Octet; typedef char Char; typedef ACE_WCHAR_T WChar; typedef ACE_INT16 Short; typedef ACE_UINT16 UShort; typedef ACE_INT32 Long; typedef ACE_UINT32 ULong; typedef ACE_INT64 LongLong; typedef ACE_UINT64 ULongLong; typedef ACE_INT8 Int8; typedef ACE_UINT8 UInt8; typedef Short Int16; typedef UShort UInt16; typedef Long Int32; typedef ULong UInt32; typedef LongLong Int64; typedef ULongLong UInt64; # if ACE_SIZEOF_FLOAT == 4 typedef float Float; # else /* ACE_SIZEOF_FLOAT != 4 */ struct Float { # if ACE_SIZEOF_INT == 4 // Use unsigned int to get word alignment. unsigned int f; # else /* ACE_SIZEOF_INT != 4 */ // Applications will probably have trouble with this. char f[4]; # endif /* ACE_SIZEOF_INT != 4 */ }; # endif /* ACE_SIZEOF_FLOAT != 4 */ # if ACE_SIZEOF_DOUBLE == 8 typedef double Double; # else /* ACE_SIZEOF_DOUBLE != 8 */ struct Double { # if ACE_SIZEOF_LONG == 8 // Use u long to get word alignment. unsigned long f; # else /* ACE_SIZEOF_INT != 8 */ // Applications will probably have trouble with this. char f[8]; # endif /* ACE_SIZEOF_INT != 8 */ }; # endif /* ACE_SIZEOF_DOUBLE != 8 */ // 94-9-32 Appendix A defines a 128 bit floating point "long // double" data type, with greatly extended precision and four // more bits of exponent (compared to "double"). This is an IDL // extension, not yet standard. # if ACE_SIZEOF_LONG_DOUBLE == 16 typedef long double LongDouble; # define ACE_CDR_LONG_DOUBLE_INITIALIZER 0 # define ACE_CDR_LONG_DOUBLE_ASSIGNMENT(LHS, RHS) LHS = RHS # else # define NONNATIVE_LONGDOUBLE # define ACE_CDR_LONG_DOUBLE_INITIALIZER {{0}} # define ACE_CDR_LONG_DOUBLE_ASSIGNMENT(LHS, RHS) LHS.assign (RHS) struct ACE_Export LongDouble { // VxWorks' compiler (gcc 2.96) gets confused by the operator long // double, so we avoid using long double as the NativeImpl. // Linux's x86 long double format (12 or 16 bytes) is incompatible // with Windows, Solaris, AIX, MacOS X and HP-UX (and probably others) // long double format (8 or 16 bytes). If you need 32-bit Linux to // inter-operate with 64-bit Linux you will want to define this // macro to 0 so that "long double" is used. Otherwise, do not define // this macro. # if defined (ACE_CDR_IMPLEMENT_WITH_NATIVE_DOUBLE) && \ (ACE_CDR_IMPLEMENT_WITH_NATIVE_DOUBLE == 1) typedef double NativeImpl; # else typedef long double NativeImpl; # endif /* ACE_CDR_IMPLEMENT_WITH_NATIVE_DOUBLE==1 */ char ld[16]; LongDouble& assign (const NativeImpl& rhs); LongDouble& assign (const LongDouble& rhs); bool operator== (const LongDouble &rhs) const; bool operator!= (const LongDouble &rhs) const; LongDouble& operator*= (const NativeImpl rhs) { return this->assign (static_cast (*this) * rhs); } LongDouble& operator/= (const NativeImpl rhs) { return this->assign (static_cast (*this) / rhs); } LongDouble& operator+= (const NativeImpl rhs) { return this->assign (static_cast (*this) + rhs); } LongDouble& operator-= (const NativeImpl rhs) { return this->assign (static_cast (*this) - rhs); } LongDouble& operator++ () { return this->assign (static_cast (*this) + 1); } LongDouble& operator-- () { return this->assign (static_cast (*this) - 1); } LongDouble operator++ (int) { LongDouble ldv = *this; this->assign (static_cast (*this) + 1); return ldv; } LongDouble operator-- (int) { LongDouble ldv = *this; this->assign (static_cast (*this) - 1); return ldv; } operator NativeImpl () const; }; # endif /* ACE_SIZEOF_LONG_DOUBLE != 16 */ #define ACE_HAS_CDR_FIXED /// Fixed-point data type: up to 31 decimal digits and a sign bit /// /// See OMG 2011-11-01 CORBA Interfaces v3.2 sections 7.10, 7.11.3.4 /// See OMG 2011-11-02 CORBA Interoperability v3.2 section 9.3.2.8 /// See OMG 2012-07-02 IDL-to-C++ Mapping v1.3 section 5.13 /// This class doesn't exactly match the IDL-to-C++ mapping because /// it is meant for use inside a union in the IDL compiler and therefore /// has no constructors. Standards-based middleware libraries such as /// ORBs and DDSs can wrap this class in a class of their own to provide /// the exact interface described by the mapping specification. class ACE_Export Fixed { public: enum { MAX_DIGITS = 31, MAX_STRING_SIZE = 4 + MAX_DIGITS, // includes -, 0, ., terminator POSITIVE = 0xc, NEGATIVE = 0xd }; static Fixed from_integer (LongLong val = 0); static Fixed from_integer (ULongLong val); static Fixed from_floating (LongDouble val); static Fixed from_string (const char *str); static Fixed from_octets (const Octet *array, int len, unsigned int scale = 0); operator LongLong () const; operator LongDouble () const; Fixed round (UShort scale) const; Fixed truncate (UShort scale) const; bool to_string (char *buffer, size_t buffer_size) const; const Octet *to_octets (int &n) const; Fixed &operator+= (const Fixed &rhs); Fixed &operator-= (const Fixed &rhs); Fixed &operator*= (const Fixed &rhs); Fixed &operator/= (const Fixed &rhs); Fixed &operator++ (); Fixed operator++ (int); Fixed &operator-- (); Fixed operator-- (int); Fixed operator+ () const; Fixed operator- () const; bool operator! () const; UShort fixed_digits () const; UShort fixed_scale () const; bool sign () const; Octet digit (int n) const; void digit (int n, int value); bool less (const Fixed &rhs) const; bool equal (const Fixed &rhs) const; class Proxy { bool high_nibble_; Octet &element_; public: Proxy (bool high_nibble, Octet &element); Proxy &operator= (Octet val); Proxy &operator+= (int rhs); Proxy &operator-= (int rhs); Proxy &operator++ (); Proxy &operator-- (); operator Octet () const; }; class IteratorBase { protected: explicit IteratorBase (int digit); bool high_nibble () const; Octet &storage (Fixed *outer) const; Octet storage (const Fixed *outer) const; bool compare (const IteratorBase &rhs) const; int digit_; }; class Iterator : private IteratorBase { public: typedef std::bidirectional_iterator_tag iterator_category; typedef Proxy value_type; typedef std::ptrdiff_t difference_type; typedef Proxy* pointer; typedef Proxy& reference; explicit Iterator (Fixed *outer, int digit = 0); Proxy operator* (); Iterator &operator+= (std::ptrdiff_t n); Iterator &operator++ (); Iterator operator++ (int); Iterator &operator-- (); Iterator operator-- (int); bool operator== (const Iterator &rhs) const; bool operator!= (const Iterator &rhs) const; private: Fixed *outer_; }; class ConstIterator : public IteratorBase { public: typedef std::bidirectional_iterator_tag iterator_category; typedef Octet value_type; typedef std::ptrdiff_t difference_type; typedef Octet* pointer; typedef Octet& reference; explicit ConstIterator (const Fixed *outer, int digit = 0); Octet operator* (); ConstIterator &operator+= (std::ptrdiff_t n); ConstIterator &operator++ (); ConstIterator operator++ (int); ConstIterator &operator-- (); ConstIterator operator-- (int); bool operator== (const ConstIterator &rhs) const; bool operator!= (const ConstIterator &rhs) const; private: const Fixed *outer_; }; Iterator begin (); ConstIterator begin () const; ConstIterator cbegin () const; Iterator end (); ConstIterator end () const; ConstIterator cend () const; private: /// CDR wire format for Fixed: marshaled as an octet array with /// index 0 as the most significant octet and index n the least /// significant. Each octet contains two decimal digits except for /// the last octet (least sig) which has one decimal digit in /// the high nibble and the sign indicator in the low nibble. Octet value_[16]; /// digits_ is not marshaled, the receiver needs to know it /// from the type information (for example, IDL). The value of /// digits_ determines how many octets of value_ are masharled. Octet digits_; /// scale_ is not marshaled, the receiver needs to know it /// from the type information (for example, IDL). Octet scale_; /// remove trailing zeros, shift down and reduce digits and scale void normalize (UShort min_scale = 0); /// Add up to 'digits' of additional scale by shifting left without /// removing significant digits. Returns number of digits shifted. int lshift (int digits); /// Prepare to add (or subtract) f by changing the digits and scale /// of *this, returnins an iterator to the least significant /// digit of f that will influence the sum (or difference). ConstIterator pre_add (const Fixed &f); Fixed div_helper2 (const Fixed &rhs, Fixed &r) const; Fixed div_helper1 (const Fixed &rhs, Fixed &r) const; Fixed join (int digits, const Fixed &bottom) const; void ltrim (); }; //@} #if !defined (ACE_CDR_GIOP_MAJOR_VERSION) # define ACE_CDR_GIOP_MAJOR_VERSION 1 #endif /*ACE_CDR_GIOP_MAJOR_VERSION */ #if !defined (ACE_CDR_GIOP_MINOR_VERSION) # define ACE_CDR_GIOP_MINOR_VERSION 2 #endif /* ACE_CDR_GIOP_MINOR_VERSION */ }; ACE_Export ACE_OSTREAM_TYPE &operator<< (ACE_OSTREAM_TYPE &lhs, const ACE_CDR::Fixed &rhs); #ifndef ACE_LACKS_IOSTREAM_TOTALLY ACE_Export std::istream &operator>> (std::istream &lhs, ACE_CDR::Fixed &rhs); #endif ACE_Export bool operator< (const ACE_CDR::Fixed &lhs, const ACE_CDR::Fixed &rhs); ACE_Export bool operator> (const ACE_CDR::Fixed &lhs, const ACE_CDR::Fixed &rhs); ACE_Export bool operator>= (const ACE_CDR::Fixed &lhs, const ACE_CDR::Fixed &rhs); ACE_Export bool operator<= (const ACE_CDR::Fixed &lhs, const ACE_CDR::Fixed &rhs); ACE_Export bool operator== (const ACE_CDR::Fixed &lhs, const ACE_CDR::Fixed &rhs); ACE_Export bool operator!= (const ACE_CDR::Fixed &lhs, const ACE_CDR::Fixed &rhs); ACE_Export ACE_CDR::Fixed operator+ (const ACE_CDR::Fixed &lhs, const ACE_CDR::Fixed &rhs); ACE_Export ACE_CDR::Fixed operator- (const ACE_CDR::Fixed &lhs, const ACE_CDR::Fixed &rhs); ACE_Export ACE_CDR::Fixed operator* (const ACE_CDR::Fixed &lhs, const ACE_CDR::Fixed &rhs); ACE_Export ACE_CDR::Fixed operator/ (const ACE_CDR::Fixed &lhs, const ACE_CDR::Fixed &rhs); ACE_END_VERSIONED_NAMESPACE_DECL #if defined (__ACE_INLINE__) # include "ace/CDR_Base.inl" #endif /* __ACE_INLINE__ */ #include /**/ "ace/post.h" #endif /* ACE_CDR_BASE_H */