3 //=============================================================================
7 * Common Data Representation (CDR) marshaling streams.
9 * This implementation assumes that the native numeric
10 * representation is two's complement for integers, IEEE
11 * single/double for floats. Also that characters are in ISO
14 * Note that CDR itself makes no such assumptions, but this
15 * implementation makes such assumptions for reasons of
16 * efficiency. Careful enhancements could preserve that
17 * efficiency where the assumptions are true, yet still allow the
18 * code to work when they aren't true.
20 * The implementation expects that buffers are aligned according
21 * to the strongest CDR alignment restriction.
23 * @note This does everything "CDR 1.1" does ... that is, it
24 * supports the five extended OMG-IDL data types in UNO Appendix
25 * A, which provide richer arithmetic types (64 bit integers,
26 * "quad precision" FP) and UNICODE-based characters and strings.
27 * Those types are not standard parts of OMG-IDL at this time.
29 * THREADING NOTE: CDR data structures must be protected against
30 * concurrent access by their owning thread.
32 * @author Copyright 1994-1995 by Sun Microsystems Inc.
33 * @author Aniruddha Gokhale
34 * @author Carlos O'Ryan
36 //=============================================================================
42 #include /**/ "ace/pre.h"
44 #include "tao/orbconf.h"
46 #if !defined (ACE_LACKS_PRAGMA_ONCE)
48 #endif /* ACE_LACKS_PRAGMA_ONCE */
50 #include /**/ "tao/TAO_Export.h"
51 #include "tao/Basic_Types.h"
52 #include "tao/GIOP_Message_Version.h"
53 #include "tao/Message_Semantics.h"
54 #include "tao/Intrusive_Ref_Count_Handle_T.h"
55 #include "tao/Intrusive_Ref_Count_Object_T.h"
57 #include "ace/CDR_Stream.h"
58 #include "ace/SString.h"
59 #include "ace/Hash_Map_Manager_T.h"
60 #include "ace/Null_Mutex.h"
64 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
67 class TAO_GIOP_Fragmentation_Strategy
;
71 * @class TAO_OutputCDR
73 * @brief A CDR stream for writing, i.e. for marshalling.
75 * This class is based on the the CORBA spec for Java (98-02-29),
76 * java class omg.org.CORBA.portable.OutputStream.
77 * It diverts in a few ways:
78 * + Operations taking arrays don't have offsets, because in C++
79 * it is easier to describe an array starting from x+offset.
80 * + Operations return an error status, because exceptions are
81 * not widely available in C++ (yet).
82 * A particularly useful static member function for this buffer is
83 * an interpretive encoding routine, usable as a typecode
84 * interpreter callback. Ditto for decoding. These are used to
85 * support all OMG-IDL datatypes, even those not supported
86 * directly by put/get primitives.
88 class TAO_Export TAO_OutputCDR
: public ACE_OutputCDR
91 /// For reading from a output CDR stream.
92 friend class TAO_InputCDR
;
93 typedef ACE_Hash_Map_Manager
<ACE_CString
, char*, ACE_Null_Mutex
> Repo_Id_Map
;
94 typedef Repo_Id_Map Codebase_URL_Map
;
95 typedef ACE_Hash_Map_Manager
<void*, char*, ACE_Null_Mutex
> Value_Map
;
97 typedef TAO_Intrusive_Ref_Count_Object
<Repo_Id_Map
, ACE_Null_Mutex
> RC_Repo_Id_Map
;
98 typedef TAO_Intrusive_Ref_Count_Object
<Codebase_URL_Map
, ACE_Null_Mutex
> RC_Codebase_URL_Map
;
99 typedef TAO_Intrusive_Ref_Count_Object
<Value_Map
, ACE_Null_Mutex
> RC_Value_Map
;
101 typedef TAO_Intrusive_Ref_Count_Handle
<RC_Repo_Id_Map
> Repo_Id_Map_Handle
;
102 typedef TAO_Intrusive_Ref_Count_Handle
<RC_Codebase_URL_Map
> Codebase_URL_Map_Handle
;
103 typedef TAO_Intrusive_Ref_Count_Handle
<RC_Value_Map
> Value_Map_Handle
;
105 // The default values for the allocators and memcpy_tradeoff
106 // in these constructors are not 0, but are generated by the
107 // ORB. Refer to the constructor bodies in CDR.cpp for the
108 // code that supplies these values to the base class constructor.
110 /// Default constructor, allocates @a size bytes in the internal
111 /// buffer, if @a size == 0 it allocates the default size.
112 TAO_OutputCDR (size_t size
= 0,
113 int byte_order
= ACE_CDR_BYTE_ORDER
,
114 ACE_Allocator
* buffer_allocator
= 0,
115 ACE_Allocator
* data_block_allocator
= 0,
116 ACE_Allocator
* message_block_allocator
= 0,
117 size_t memcpy_tradeoff
= 0,
118 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
119 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
);
121 /// Build a CDR stream with an initial buffer, it will *not* remove
122 /// @a data, since it did not allocated it.
123 TAO_OutputCDR (char *data
,
125 int byte_order
= ACE_CDR_BYTE_ORDER
,
126 ACE_Allocator
* buffer_allocator
= 0,
127 ACE_Allocator
* data_block_allocator
= 0,
128 ACE_Allocator
* message_block_allocator
= 0,
129 size_t memcpy_tradeoff
= 0,
130 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
131 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
);
133 /// Build a CDR stream with an initial buffer, it will *not* remove
134 /// @a data since it did not allocated it, and enable fragmentation
136 TAO_OutputCDR (char *data
,
139 ACE_Allocator
* buffer_allocator
,
140 ACE_Allocator
* data_block_allocator
,
141 ACE_Allocator
* message_block_allocator
,
142 size_t memcpy_tradeoff
,
143 TAO_GIOP_Fragmentation_Strategy
* fs
,
144 ACE_CDR::Octet major_version
,
145 ACE_CDR::Octet minor_version
);
147 /// Build a CDR stream with an initial Message_Block chain, it will *not*
148 /// remove @a data, since it did not allocate it.
149 TAO_OutputCDR (ACE_Message_Block
*data
,
150 int byte_order
= ACE_CDR_BYTE_ORDER
,
151 size_t memcpy_tradeoff
= 0,
152 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
153 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
);
155 /// Build a CDR stream with an initial data block, it will *not* remove
156 /// @a data, since it did not allocated it.
157 TAO_OutputCDR (ACE_Data_Block
*data
,
158 int byte_order
= ACE_CDR_BYTE_ORDER
,
159 ACE_Allocator
* message_block_allocator
= 0,
160 size_t memcpy_tradeoff
= 0,
161 TAO_GIOP_Fragmentation_Strategy
* fs
= 0,
162 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
163 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
);
166 ~TAO_OutputCDR (void);
168 // @todo do we want a special method to write an array of
169 // strings and wstrings?
171 // = TAO specific methods.
172 static void throw_stub_exception (int error_num
);
173 static void throw_skel_exception (int error_num
);
175 void get_version (TAO_GIOP_Message_Version
& giop_version
);
178 * @name Outgoing GIOP Fragment Related Methods
180 * These methods are only used when fragmenting outgoing GIOP
181 * requests and replies.
184 /// Fragment this output CDR stream if necessary.
186 * Fragmentation will done through GIOP fragments when the length of
187 * the CDR stream length will exceed the configured threshold.
189 bool fragment_stream (ACE_CDR::ULong pending_alignment
,
190 ACE_CDR::ULong pending_length
);
192 /// Are there more data fragments to come?
193 bool more_fragments (void) const;
195 /// Specify whether there are more data fragments to come.
196 void more_fragments (bool more
);
198 /// Set fragmented message attributes.
199 void message_attributes (CORBA::ULong request_id
,
201 TAO_Message_Semantics message_semantics
,
202 ACE_Time_Value
* timeout
);
204 /// Fragmented message request ID.
205 CORBA::ULong
request_id (void) const;
207 /// Stub object associated with the request.
208 TAO_Stub
* stub (void) const;
210 /// Message semantics (twoway, oneway, reply)
211 TAO_Message_Semantics
message_semantics (void) const;
213 /// Maximum time to wait for outgoing message to be sent.
214 ACE_Time_Value
* timeout (void) const;
217 /// These methods are used by valuetype indirection support.
218 /// Accessor to the indirect maps.
219 Repo_Id_Map_Handle
& get_repo_id_map ();
220 #ifdef TAO_HAS_VALUETYPE_CODEBASE
221 Codebase_URL_Map_Handle
& get_codebase_url_map ();
223 Value_Map_Handle
& get_value_map ();
225 /// Updater of the maps.
226 /// These updaters are used to make indirect maps in original stream
227 /// take effect even during marshalling/demarshalling a redirected stream.
228 void set_repo_id_map (Repo_Id_Map_Handle
& map
);
229 #ifdef TAO_HAS_VALUETYPE_CODEBASE
230 Codebase_URL_Map_Handle
& get_codebase_url_map ();
231 void set_codebase_url_map (Codebase_URL_Map_Handle
& map
);
233 void set_value_map (Value_Map_Handle
& map
);
235 /// If indirect map is not nil and not empty, unbind all entries.
236 /// Called after marshalling.
237 void reset_vt_indirect_maps ();
239 /// Calculate the offset between pos and current wr_ptr.
240 int offset (char* pos
);
243 // disallow copying...
244 TAO_OutputCDR (const TAO_OutputCDR
& rhs
);
245 TAO_OutputCDR
& operator= (const TAO_OutputCDR
& rhs
);
249 * @name Outgoing GIOP Fragment Related Attributes
251 * These attributes are only used when fragmenting outgoing GIOP
252 * requests and replies.
255 /// Strategy that sends data currently marshaled into this
256 /// TAO_OutputCDR stream if necessary.
257 TAO_GIOP_Fragmentation_Strategy
* const fragmentation_strategy_
;
259 /// Are there more data fragments to come?
260 bool more_fragments_
;
262 /// Request ID for the request currently being marshaled.
263 CORBA::ULong request_id_
;
265 /// Stub object associated with the request.
268 /// Twoway, oneway, reply?
272 TAO_Message_Semantics message_semantics_
;
274 /// Request/reply send timeout.
275 ACE_Time_Value
* timeout_
;
278 /// These maps are used by valuetype indirection support.
279 Repo_Id_Map_Handle repo_id_map_
;
280 #ifdef TAO_HAS_VALUETYPE_CODEBASE
281 Codebase_URL_Map_Handle codebase_map_
;
283 Value_Map_Handle value_map_
;
287 * @class TAO_InputCDR
289 * @brief A CDR stream for reading, i.e. for demarshalling.
291 * This class is based on the the CORBA spec for Java (98-02-29),
292 * java class omg.org.CORBA.portable.InputStream.
293 * It diverts in a few ways:
294 * + Operations to retrieve basic types take parameters by
296 * + Operations taking arrays don't have offsets, because in C++
297 * it is easier to describe an array starting from x+offset.
298 * + Operations return an error status, because exceptions are
299 * not widely available in C++ (yet).
300 * A particularly useful static member function for this buffer is
301 * an interpretive encoding routine, usable as a typecode
302 * interpreter callback. Ditto for decoding. These are used to
303 * support all OMG-IDL datatypes, even those not supported
304 * directly by put/get primitives.
306 class TAO_Export TAO_InputCDR
: public ACE_InputCDR
309 typedef ACE_Hash_Map_Manager
<void*, ACE_CString
, ACE_Null_Mutex
> Repo_Id_Map
;
310 typedef Repo_Id_Map Codebase_URL_Map
;
311 typedef ACE_Hash_Map_Manager
<void*, void*, ACE_Null_Mutex
> Value_Map
;
313 typedef TAO_Intrusive_Ref_Count_Object
<Repo_Id_Map
, ACE_Null_Mutex
> RC_Repo_Id_Map
;
314 typedef TAO_Intrusive_Ref_Count_Object
<Codebase_URL_Map
, ACE_Null_Mutex
> RC_Codebase_URL_Map
;
315 typedef TAO_Intrusive_Ref_Count_Object
<Value_Map
, ACE_Null_Mutex
> RC_Value_Map
;
317 typedef TAO_Intrusive_Ref_Count_Handle
<RC_Repo_Id_Map
> Repo_Id_Map_Handle
;
318 typedef TAO_Intrusive_Ref_Count_Handle
<RC_Codebase_URL_Map
> Codebase_URL_Map_Handle
;
319 typedef TAO_Intrusive_Ref_Count_Handle
<RC_Value_Map
> Value_Map_Handle
;
322 * Create an input stream from an arbitrary buffer, care must be
323 * exercised wrt alignment, because this constructor will *not* work
324 * if the buffer is unproperly aligned.
326 TAO_InputCDR (const char* buf
,
328 int byte_order
= ACE_CDR_BYTE_ORDER
,
329 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
330 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
,
331 TAO_ORB_Core
* orb_core
= 0);
333 /// Create an empty input stream. The caller is responsible for
334 /// putting the right data and providing the right alignment.
335 TAO_InputCDR (size_t bufsiz
,
336 int byte_order
= ACE_CDR_BYTE_ORDER
,
337 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
338 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
,
339 TAO_ORB_Core
* orb_core
= 0);
341 /// Create an input stream from an ACE_Message_Block
342 TAO_InputCDR (const ACE_Message_Block
*data
,
343 int byte_order
= ACE_CDR_BYTE_ORDER
,
344 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
345 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
,
346 TAO_ORB_Core
* orb_core
= 0);
348 /// Create an input stream from an ACE_Message_Block with an optional lock
349 /// used to protect the data.
350 TAO_InputCDR (const ACE_Message_Block
*data
,
352 int byte_order
= ACE_CDR_BYTE_ORDER
,
353 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
354 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
,
355 TAO_ORB_Core
* orb_core
= 0);
358 /// Create an input stream from an ACE_Data_Block
359 TAO_InputCDR (ACE_Data_Block
*data
,
360 ACE_Message_Block::Message_Flags flag
= 0,
361 int byte_order
= ACE_CDR_BYTE_ORDER
,
362 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
363 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
,
364 TAO_ORB_Core
* orb_core
= 0);
366 /// Create an input stream from an ACE_Data_Block
367 TAO_InputCDR (ACE_Data_Block
*data
,
368 ACE_Message_Block::Message_Flags flag
,
369 size_t read_pointer_position
,
370 size_t write_pointer_position
,
371 int byte_order
= ACE_CDR_BYTE_ORDER
,
372 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
373 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
,
374 TAO_ORB_Core
* orb_core
= 0);
377 * Make a copy of the current stream state, but does not copy the
378 * internal buffer; so the same stream can be read multiple times
381 TAO_InputCDR (const TAO_InputCDR
& rhs
);
383 /// When interpreting indirected TypeCodes it is useful to make a
384 /// "copy" of the stream starting in the new position.
385 TAO_InputCDR (const TAO_InputCDR
& rhs
,
387 ACE_CDR::Long offset
);
389 * This creates an encapsulated stream, the first byte must be (per
390 * the spec) the byte order of the encapsulation. The default
391 * values for the allocators in this constructor are not 0, but are
392 * generated by the ORB. Refer to the constructor body in CDR.cpp
393 * for the code that supplies these values to the base class
396 TAO_InputCDR (const TAO_InputCDR
& rhs
,
399 /// Create an input CDR from an output CDR.
400 TAO_InputCDR (const TAO_OutputCDR
& rhs
,
401 ACE_Allocator
* buffer_allocator
= 0,
402 ACE_Allocator
* data_block_allocator
= 0,
403 ACE_Allocator
* message_block_allocator
= 0,
404 TAO_ORB_Core
* orb_core
= 0);
406 /// Initialize the contents of one CDR from another, without data
407 /// copying and with minimum locking overhead.
408 TAO_InputCDR (ACE_InputCDR::Transfer_Contents rhs
,
409 TAO_ORB_Core
* orb_core
= 0);
411 #if defined (ACE_HAS_CPP11)
412 TAO_InputCDR
& operator= (const TAO_InputCDR
&) = default;
413 #endif /* ACE_HAS_CPP11 */
416 virtual ~TAO_InputCDR (void);
418 // = TAO specific methods.
421 TAO_ORB_Core
*orb_core (void) const;
423 ACE_Message_Block::Message_Flags
424 clr_mb_flags( ACE_Message_Block::Message_Flags less_flags
);
426 // = TAO specific methods.
427 static void throw_stub_exception (int error_num
);
428 static void throw_skel_exception (int error_num
);
430 /// These methods are used by valuetype indirection support.
431 /// Accessor to the indirect maps.
432 Repo_Id_Map_Handle
& get_repo_id_map ();
433 Codebase_URL_Map_Handle
& get_codebase_url_map ();
434 Value_Map_Handle
& get_value_map ();
436 /// Updater of the maps.
437 /// These updaters are used to make indirect maps in original stream
438 /// take effect even during marshalling/demarshalling a redirected stream.
439 void set_repo_id_map (Repo_Id_Map_Handle
& map
);
440 void set_codebase_url_map (Codebase_URL_Map_Handle
& map
);
441 void set_value_map (Value_Map_Handle
& map
);
443 /// If indirect map is not nil and not empty, unbind all entries.
444 /// Called after demarshalling.
445 void reset_vt_indirect_maps ();
448 /// The ORB_Core, required to extract object references.
449 TAO_ORB_Core
* orb_core_
;
451 /// These maps are used by valuetype indirection support.
452 Repo_Id_Map_Handle repo_id_map_
;
453 Codebase_URL_Map_Handle codebase_map_
;
454 Value_Map_Handle value_map_
;
457 TAO_END_VERSIONED_NAMESPACE_DECL
459 #if defined(__ACE_INLINE__)
460 # include "tao/CDR.inl"
463 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
465 // CDR output operators for CORBA types
467 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
469 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
471 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
473 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
475 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
477 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
479 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
& os
,
480 CORBA::LongDouble x
);
481 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
483 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
485 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
486 const CORBA::Char
* x
);
487 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
488 const CORBA::WChar
* x
);
489 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
490 ACE_OutputCDR::from_string x
);
491 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
492 ACE_OutputCDR::from_wstring x
);
493 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
494 const std::string
&x
);
495 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
496 ACE_OutputCDR::from_std_string x
);
497 #if !defined(ACE_LACKS_STD_WSTRING)
498 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
499 const std::wstring
&x
);
500 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
501 ACE_OutputCDR::from_std_wstring x
);
502 #endif /* ACE_LACKS_STD_WSTRING */
504 // CDR input operators for CORBA types
506 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
508 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
510 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
512 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
514 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
516 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
517 CORBA::ULongLong
&x
);
518 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
519 CORBA::LongDouble
&x
);
520 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
522 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
524 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
526 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
528 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&os
,
529 ACE_InputCDR::to_string x
);
530 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&os
,
531 ACE_InputCDR::to_wstring x
);
532 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&os
,
534 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&os
,
535 ACE_InputCDR::to_std_string x
);
536 #if !defined(ACE_LACKS_STD_WSTRING)
537 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&os
,
539 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&os
,
540 ACE_InputCDR::to_std_wstring x
);
541 #endif /* ACE_LACKS_STD_WSTRING */
543 TAO_END_VERSIONED_NAMESPACE_DECL
545 #endif /* __ACE_INLINE */
547 #include /**/ "ace/post.h"
548 #endif /* TAO_CDR_H */