3 //=============================================================================
7 * ACE Common Data Representation (CDR) basic types.
9 * The current implementation assumes that the host has 1-byte,
10 * 2-byte and 4-byte integral types, and that it has single
11 * precision and double precision IEEE floats.
12 * Those assumptions are pretty good these days, with Crays being
13 * the only known exception.
15 * @author TAO version by
16 * @author Aniruddha Gokhale <gokhale@cs.wustl.edu>
17 * @author Carlos O'Ryan<coryan@cs.wustl.edu>
18 * @author ACE version by
19 * @author Jeff Parsons <parsons@cs.wustl.edu>
20 * @author Istvan Buki <istvan.buki@euronet.be>
22 //=============================================================================
24 #ifndef ACE_CDR_BASE_H
25 #define ACE_CDR_BASE_H
27 #include /**/ "ace/pre.h"
29 #include /**/ "ace/config-all.h"
31 #if !defined (ACE_LACKS_PRAGMA_ONCE)
33 #endif /* ACE_LACKS_PRAGMA_ONCE */
35 #include "ace/Basic_Types.h"
36 #include "ace/Default_Constants.h"
37 #include "ace/Global_Macros.h"
38 #include "ace/iosfwd.h"
42 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
44 // Stuff used by the ACE CDR classes. Watch these values... they're also used
45 // in the ACE_CDR Byte_Order enum below.
46 #if defined ACE_LITTLE_ENDIAN
47 # define ACE_CDR_BYTE_ORDER 1
48 // little endian encapsulation byte order has value = 1
49 #else /* ! ACE_LITTLE_ENDIAN */
50 # define ACE_CDR_BYTE_ORDER 0
51 // big endian encapsulation byte order has value = 0
52 #endif /* ! ACE_LITTLE_ENDIAN */
54 class ACE_Message_Block
;
59 * @brief Keep constants and some routines common to both Output and
62 class ACE_Export ACE_CDR
65 // = Constants defined by the CDR protocol.
66 // By defining as many of these constants as possible as enums we
67 // ensure they get inlined and avoid pointless static memory
72 // Note that some of these get reused as part of the standard
73 // binary format: unsigned is the same size as its signed cousin,
74 // float is LONG_SIZE, and double is LONGLONG_SIZE.
86 /// @note the CORBA LongDouble alignment requirements do not
90 /// Maximal CDR 1.1 alignment: "quad precision" FP (i.e. "CDR::Long
91 /// double", size as above).
94 /// The default buffer size.
96 * @todo We want to add options to control this
97 * default value, so this constant should be read as the default
100 DEFAULT_BUFSIZE
= ACE_DEFAULT_CDR_BUFSIZE
,
102 /// The buffer size grows exponentially until it reaches this size;
103 /// afterwards it grows linearly using the next constant
104 EXP_GROWTH_MAX
= ACE_DEFAULT_CDR_EXP_GROWTH_MAX
,
106 /// Once exponential growth is ruled out the buffer size increases
107 /// in chunks of this size, note that this constants have the same
108 /// value right now, but it does not need to be so.
109 LINEAR_GROWTH_CHUNK
= ACE_DEFAULT_CDR_LINEAR_GROWTH_CHUNK
115 * Defines values for the byte_order argument to ACE_OutputCDR and
120 /// Use big-endian order (also known as network byte order).
121 BYTE_ORDER_BIG_ENDIAN
= 0,
122 /// Use little-endian order.
123 BYTE_ORDER_LITTLE_ENDIAN
= 1,
124 /// Use whichever byte order is native to this machine.
125 BYTE_ORDER_NATIVE
= ACE_CDR_BYTE_ORDER
129 * Do byte swapping for each basic IDL type size. There exist only
130 * routines to put byte, halfword (2 bytes), word (4 bytes),
131 * doubleword (8 bytes) and quadword (16 byte); because those are
132 * the IDL basic type sizes.
134 static void swap_2 (char const *orig
, char *target
);
135 static void swap_4 (char const *orig
, char *target
);
136 static void swap_8 (char const *orig
, char *target
);
137 static void swap_16 (char const *orig
, char *target
);
138 static void swap_2_array (char const *orig
,
141 static void swap_4_array (char const *orig
,
144 static void swap_8_array (char const *orig
,
147 static void swap_16_array (char const *orig
,
151 /// Align the message block to ACE_CDR::MAX_ALIGNMENT,
152 /// set by the CORBA spec at 8 bytes.
153 static void mb_align (ACE_Message_Block
*mb
);
156 * Compute the size of the smallest buffer that can contain at least
158 * To understand how a "best fit" is computed look at the
159 * algorithm in the code.
160 * Basically the buffers grow exponentially, up to a certain point,
161 * then the buffer size grows linearly.
162 * The advantage of this algorithm is that is rapidly grows to a
163 * large value, but does not explode at the end.
165 static size_t first_size (size_t minsize
);
167 /// Compute not the smallest, but the second smallest buffer that
168 /// will fir @a minsize bytes.
169 static size_t next_size (size_t minsize
);
172 * Increase the capacity of mb to contain at least @a minsize bytes.
173 * If @a minsize is zero the size is increased by an amount at least
174 * large enough to contain any of the basic IDL types.
178 static int grow (ACE_Message_Block
*mb
, size_t minsize
);
181 * Copy a message block chain into a single message block,
182 * preserving the alignment of the first message block of the
183 * original stream, not the following message blocks.
187 static int consolidate (ACE_Message_Block
*dst
,
188 const ACE_Message_Block
*src
);
190 static size_t total_length (const ACE_Message_Block
*begin
,
191 const ACE_Message_Block
*end
);
194 * @name Basic OMG IDL Types
196 * These types are for use in the CDR classes. The cleanest way to
197 * avoid complaints from all compilers is to define them all.
200 typedef bool Boolean
;
201 typedef ACE_Byte Octet
;
203 typedef ACE_WCHAR_T WChar
;
204 typedef ACE_INT16 Short
;
205 typedef ACE_UINT16 UShort
;
206 typedef ACE_INT32 Long
;
207 typedef ACE_UINT32 ULong
;
208 typedef ACE_INT64 LongLong
;
209 typedef ACE_UINT64 ULongLong
;
210 typedef ACE_INT8 Int8
;
211 typedef ACE_UINT8 UInt8
;
213 typedef UShort UInt16
;
215 typedef ULong UInt32
;
216 typedef LongLong Int64
;
217 typedef ULongLong UInt64
;
219 # if ACE_SIZEOF_FLOAT == 4
221 # else /* ACE_SIZEOF_FLOAT != 4 */
224 # if ACE_SIZEOF_INT == 4
225 // Use unsigned int to get word alignment.
227 # else /* ACE_SIZEOF_INT != 4 */
228 // Applications will probably have trouble with this.
230 # endif /* ACE_SIZEOF_INT != 4 */
232 # endif /* ACE_SIZEOF_FLOAT != 4 */
234 # if ACE_SIZEOF_DOUBLE == 8
235 typedef double Double
;
236 # else /* ACE_SIZEOF_DOUBLE != 8 */
239 # if ACE_SIZEOF_LONG == 8
240 // Use u long to get word alignment.
242 # else /* ACE_SIZEOF_INT != 8 */
243 // Applications will probably have trouble with this.
245 # endif /* ACE_SIZEOF_INT != 8 */
247 # endif /* ACE_SIZEOF_DOUBLE != 8 */
249 // 94-9-32 Appendix A defines a 128 bit floating point "long
250 // double" data type, with greatly extended precision and four
251 // more bits of exponent (compared to "double"). This is an IDL
252 // extension, not yet standard.
254 # if ACE_SIZEOF_LONG_DOUBLE == 16
255 typedef long double LongDouble
;
256 # define ACE_CDR_LONG_DOUBLE_INITIALIZER 0
257 # define ACE_CDR_LONG_DOUBLE_ASSIGNMENT(LHS, RHS) LHS = RHS
259 # define NONNATIVE_LONGDOUBLE
260 # define ACE_CDR_LONG_DOUBLE_INITIALIZER {{0}}
261 # define ACE_CDR_LONG_DOUBLE_ASSIGNMENT(LHS, RHS) LHS.assign (RHS)
262 struct ACE_Export LongDouble
264 // VxWorks' compiler (gcc 2.96) gets confused by the operator long
265 // double, so we avoid using long double as the NativeImpl.
266 // Linux's x86 long double format (12 or 16 bytes) is incompatible
267 // with Windows, Solaris, AIX, MacOS X and HP-UX (and probably others)
268 // long double format (8 or 16 bytes). If you need 32-bit Linux to
269 // inter-operate with 64-bit Linux you will want to define this
270 // macro to 0 so that "long double" is used. Otherwise, do not define
272 # if defined (ACE_CDR_IMPLEMENT_WITH_NATIVE_DOUBLE) && \
273 (ACE_CDR_IMPLEMENT_WITH_NATIVE_DOUBLE == 1)
274 typedef double NativeImpl
;
276 typedef long double NativeImpl
;
277 # endif /* ACE_CDR_IMPLEMENT_WITH_NATIVE_DOUBLE==1 */
281 LongDouble
& assign (const NativeImpl
& rhs
);
282 LongDouble
& assign (const LongDouble
& rhs
);
284 bool operator== (const LongDouble
&rhs
) const;
285 bool operator!= (const LongDouble
&rhs
) const;
287 LongDouble
& operator*= (const NativeImpl rhs
) {
288 return this->assign (static_cast<NativeImpl
> (*this) * rhs
);
290 LongDouble
& operator/= (const NativeImpl rhs
) {
291 return this->assign (static_cast<NativeImpl
> (*this) / rhs
);
293 LongDouble
& operator+= (const NativeImpl rhs
) {
294 return this->assign (static_cast<NativeImpl
> (*this) + rhs
);
296 LongDouble
& operator-= (const NativeImpl rhs
) {
297 return this->assign (static_cast<NativeImpl
> (*this) - rhs
);
299 LongDouble
& operator++ () {
300 return this->assign (static_cast<NativeImpl
> (*this) + 1);
302 LongDouble
& operator-- () {
303 return this->assign (static_cast<NativeImpl
> (*this) - 1);
305 LongDouble
operator++ (int) {
306 LongDouble ldv
= *this;
307 this->assign (static_cast<NativeImpl
> (*this) + 1);
310 LongDouble
operator-- (int) {
311 LongDouble ldv
= *this;
312 this->assign (static_cast<NativeImpl
> (*this) - 1);
316 operator NativeImpl () const;
318 # endif /* ACE_SIZEOF_LONG_DOUBLE != 16 */
320 #define ACE_HAS_CDR_FIXED
321 /// Fixed-point data type: up to 31 decimal digits and a sign bit
323 /// See OMG 2011-11-01 CORBA Interfaces v3.2 sections 7.10, 7.11.3.4
324 /// See OMG 2011-11-02 CORBA Interoperability v3.2 section 9.3.2.8
325 /// See OMG 2012-07-02 IDL-to-C++ Mapping v1.3 section 5.13
326 /// This class doesn't exactly match the IDL-to-C++ mapping because
327 /// it is meant for use inside a union in the IDL compiler and therefore
328 /// has no constructors. Standards-based middleware libraries such as
329 /// ORBs and DDSs can wrap this class in a class of their own to provide
330 /// the exact interface described by the mapping specification.
331 class ACE_Export Fixed
337 MAX_STRING_SIZE
= 4 + MAX_DIGITS
, // includes -, 0, ., terminator
342 static Fixed
from_integer (LongLong val
= 0);
343 static Fixed
from_integer (ULongLong val
);
344 static Fixed
from_floating (LongDouble val
);
345 static Fixed
from_string (const char *str
);
346 static Fixed
from_octets (const Octet
*array
, int len
,
347 unsigned int scale
= 0);
349 operator LongLong () const;
350 operator LongDouble () const;
352 Fixed
round (UShort scale
) const;
353 Fixed
truncate (UShort scale
) const;
355 bool to_string (char *buffer
, size_t buffer_size
) const;
356 const Octet
*to_octets (int &n
) const;
358 Fixed
&operator+= (const Fixed
&rhs
);
359 Fixed
&operator-= (const Fixed
&rhs
);
360 Fixed
&operator*= (const Fixed
&rhs
);
361 Fixed
&operator/= (const Fixed
&rhs
);
363 Fixed
&operator++ ();
364 Fixed
operator++ (int);
365 Fixed
&operator-- ();
366 Fixed
operator-- (int);
368 Fixed
operator+ () const;
369 Fixed
operator- () const;
370 bool operator! () const;
372 UShort
fixed_digits () const;
373 UShort
fixed_scale () const;
376 Octet
digit (int n
) const;
377 void digit (int n
, int value
);
379 bool less (const Fixed
&rhs
) const;
380 bool equal (const Fixed
&rhs
) const;
387 Proxy (bool high_nibble
, Octet
&element
);
388 Proxy
&operator= (Octet val
);
389 Proxy
&operator+= (int rhs
);
390 Proxy
&operator-= (int rhs
);
391 Proxy
&operator++ ();
392 Proxy
&operator-- ();
393 operator Octet () const;
399 explicit IteratorBase (int digit
);
400 bool high_nibble () const;
401 Octet
&storage (Fixed
*outer
) const;
402 Octet
storage (const Fixed
*outer
) const;
403 bool compare (const IteratorBase
&rhs
) const;
408 : private IteratorBase
411 typedef std::bidirectional_iterator_tag iterator_category
;
412 typedef Proxy value_type
;
413 typedef std::ptrdiff_t difference_type
;
414 typedef Proxy
* pointer
;
415 typedef Proxy
& reference
;
417 explicit Iterator (Fixed
*outer
, int digit
= 0);
419 Iterator
&operator+= (std::ptrdiff_t n
);
420 Iterator
&operator++ ();
421 Iterator
operator++ (int);
422 Iterator
&operator-- ();
423 Iterator
operator-- (int);
424 bool operator== (const Iterator
&rhs
) const;
425 bool operator!= (const Iterator
&rhs
) const;
431 : public IteratorBase
434 typedef std::bidirectional_iterator_tag iterator_category
;
435 typedef Octet value_type
;
436 typedef std::ptrdiff_t difference_type
;
437 typedef Octet
* pointer
;
438 typedef Octet
& reference
;
440 explicit ConstIterator (const Fixed
*outer
, int digit
= 0);
442 ConstIterator
&operator+= (std::ptrdiff_t n
);
443 ConstIterator
&operator++ ();
444 ConstIterator
operator++ (int);
445 ConstIterator
&operator-- ();
446 ConstIterator
operator-- (int);
447 bool operator== (const ConstIterator
&rhs
) const;
448 bool operator!= (const ConstIterator
&rhs
) const;
454 ConstIterator
begin () const;
455 ConstIterator
cbegin () const;
457 ConstIterator
end () const;
458 ConstIterator
cend () const;
461 /// CDR wire format for Fixed: marshaled as an octet array with
462 /// index 0 as the most significant octet and index n the least
463 /// significant. Each octet contains two decimal digits except for
464 /// the last octet (least sig) which has one decimal digit in
465 /// the high nibble and the sign indicator in the low nibble.
468 /// digits_ is not marshaled, the receiver needs to know it
469 /// from the type information (for example, IDL). The value of
470 /// digits_ determines how many octets of value_ are masharled.
473 /// scale_ is not marshaled, the receiver needs to know it
474 /// from the type information (for example, IDL).
477 /// remove trailing zeros, shift down and reduce digits and scale
478 void normalize (UShort min_scale
= 0);
480 /// Add up to 'digits' of additional scale by shifting left without
481 /// removing significant digits. Returns number of digits shifted.
482 int lshift (int digits
);
484 /// Prepare to add (or subtract) f by changing the digits and scale
485 /// of *this, returnins an iterator to the least significant
486 /// digit of f that will influence the sum (or difference).
487 ConstIterator
pre_add (const Fixed
&f
);
489 Fixed
div_helper2 (const Fixed
&rhs
, Fixed
&r
) const;
490 Fixed
div_helper1 (const Fixed
&rhs
, Fixed
&r
) const;
491 Fixed
join (int digits
, const Fixed
&bottom
) const;
497 #if !defined (ACE_CDR_GIOP_MAJOR_VERSION)
498 # define ACE_CDR_GIOP_MAJOR_VERSION 1
499 #endif /*ACE_CDR_GIOP_MAJOR_VERSION */
501 #if !defined (ACE_CDR_GIOP_MINOR_VERSION)
502 # define ACE_CDR_GIOP_MINOR_VERSION 2
503 #endif /* ACE_CDR_GIOP_MINOR_VERSION */
507 ACE_OSTREAM_TYPE
&operator<< (ACE_OSTREAM_TYPE
&lhs
, const ACE_CDR::Fixed
&rhs
);
509 #ifndef ACE_LACKS_IOSTREAM_TOTALLY
511 std::istream
&operator>> (std::istream
&lhs
, ACE_CDR::Fixed
&rhs
);
515 bool operator< (const ACE_CDR::Fixed
&lhs
, const ACE_CDR::Fixed
&rhs
);
518 bool operator> (const ACE_CDR::Fixed
&lhs
, const ACE_CDR::Fixed
&rhs
);
521 bool operator>= (const ACE_CDR::Fixed
&lhs
, const ACE_CDR::Fixed
&rhs
);
524 bool operator<= (const ACE_CDR::Fixed
&lhs
, const ACE_CDR::Fixed
&rhs
);
527 bool operator== (const ACE_CDR::Fixed
&lhs
, const ACE_CDR::Fixed
&rhs
);
530 bool operator!= (const ACE_CDR::Fixed
&lhs
, const ACE_CDR::Fixed
&rhs
);
533 ACE_CDR::Fixed
operator+ (const ACE_CDR::Fixed
&lhs
, const ACE_CDR::Fixed
&rhs
);
536 ACE_CDR::Fixed
operator- (const ACE_CDR::Fixed
&lhs
, const ACE_CDR::Fixed
&rhs
);
539 ACE_CDR::Fixed
operator* (const ACE_CDR::Fixed
&lhs
, const ACE_CDR::Fixed
&rhs
);
542 ACE_CDR::Fixed
operator/ (const ACE_CDR::Fixed
&lhs
, const ACE_CDR::Fixed
&rhs
);
544 ACE_END_VERSIONED_NAMESPACE_DECL
546 #if defined (__ACE_INLINE__)
547 # include "ace/CDR_Base.inl"
548 #endif /* __ACE_INLINE__ */
551 #include /**/ "ace/post.h"
553 #endif /* ACE_CDR_BASE_H */