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_IDLv4.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
);
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 () 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 () const;
207 /// Stub object associated with the request.
208 TAO_Stub
* stub () const;
210 /// Message semantics (twoway, oneway, reply)
211 TAO_Message_Semantics
message_semantics () const;
213 /// Maximum time to wait for outgoing message to be sent.
214 ACE_Time_Value
* timeout () 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 TAO_OutputCDR (const TAO_OutputCDR
&rhs
) = delete;
244 TAO_OutputCDR
& operator= (const TAO_OutputCDR
&) = delete;
245 TAO_OutputCDR (TAO_OutputCDR
&&) = delete;
246 TAO_OutputCDR
& operator= (TAO_OutputCDR
&&) = delete;
250 * @name Outgoing GIOP Fragment Related Attributes
252 * These attributes are only used when fragmenting outgoing GIOP
253 * requests and replies.
256 /// Strategy that sends data currently marshaled into this
257 /// TAO_OutputCDR stream if necessary.
258 TAO_GIOP_Fragmentation_Strategy
* const fragmentation_strategy_
;
260 /// Are there more data fragments to come?
261 bool more_fragments_
;
263 /// Request ID for the request currently being marshaled.
264 CORBA::ULong request_id_
;
266 /// Stub object associated with the request.
269 /// Twoway, oneway, reply?
273 TAO_Message_Semantics message_semantics_
;
275 /// Request/reply send timeout.
276 ACE_Time_Value
* timeout_
;
279 /// These maps are used by valuetype indirection support.
280 Repo_Id_Map_Handle repo_id_map_
;
281 #ifdef TAO_HAS_VALUETYPE_CODEBASE
282 Codebase_URL_Map_Handle codebase_map_
;
284 Value_Map_Handle value_map_
;
288 * @class TAO_InputCDR
290 * @brief A CDR stream for reading, i.e. for demarshalling.
292 * This class is based on the the CORBA spec for Java (98-02-29),
293 * java class omg.org.CORBA.portable.InputStream.
294 * It diverts in a few ways:
295 * + Operations to retrieve basic types take parameters by
297 * + Operations taking arrays don't have offsets, because in C++
298 * it is easier to describe an array starting from x+offset.
299 * + Operations return an error status, because exceptions are
300 * not widely available in C++ (yet).
301 * A particularly useful static member function for this buffer is
302 * an interpretive encoding routine, usable as a typecode
303 * interpreter callback. Ditto for decoding. These are used to
304 * support all OMG-IDL datatypes, even those not supported
305 * directly by put/get primitives.
307 class TAO_Export TAO_InputCDR
: public ACE_InputCDR
310 typedef ACE_Hash_Map_Manager
<void*, ACE_CString
, ACE_Null_Mutex
> Repo_Id_Map
;
311 typedef Repo_Id_Map Codebase_URL_Map
;
312 typedef ACE_Hash_Map_Manager
<void*, void*, ACE_Null_Mutex
> Value_Map
;
314 typedef TAO_Intrusive_Ref_Count_Object
<Repo_Id_Map
, ACE_Null_Mutex
> RC_Repo_Id_Map
;
315 typedef TAO_Intrusive_Ref_Count_Object
<Codebase_URL_Map
, ACE_Null_Mutex
> RC_Codebase_URL_Map
;
316 typedef TAO_Intrusive_Ref_Count_Object
<Value_Map
, ACE_Null_Mutex
> RC_Value_Map
;
318 typedef TAO_Intrusive_Ref_Count_Handle
<RC_Repo_Id_Map
> Repo_Id_Map_Handle
;
319 typedef TAO_Intrusive_Ref_Count_Handle
<RC_Codebase_URL_Map
> Codebase_URL_Map_Handle
;
320 typedef TAO_Intrusive_Ref_Count_Handle
<RC_Value_Map
> Value_Map_Handle
;
323 * Create an input stream from an arbitrary buffer, care must be
324 * exercised wrt alignment, because this constructor will *not* work
325 * if the buffer is unproperly aligned.
327 TAO_InputCDR (const char* buf
,
329 int byte_order
= ACE_CDR_BYTE_ORDER
,
330 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
331 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
,
332 TAO_ORB_Core
* orb_core
= 0);
334 /// Create an empty input stream. The caller is responsible for
335 /// putting the right data and providing the right alignment.
336 TAO_InputCDR (size_t bufsiz
,
337 int byte_order
= ACE_CDR_BYTE_ORDER
,
338 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
339 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
,
340 TAO_ORB_Core
* orb_core
= 0);
342 /// Create an input stream from an ACE_Message_Block
343 TAO_InputCDR (const ACE_Message_Block
*data
,
344 int byte_order
= ACE_CDR_BYTE_ORDER
,
345 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
346 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
,
347 TAO_ORB_Core
* orb_core
= 0);
349 /// Create an input stream from an ACE_Message_Block with an optional lock
350 /// used to protect the data.
351 TAO_InputCDR (const ACE_Message_Block
*data
,
353 int byte_order
= ACE_CDR_BYTE_ORDER
,
354 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
355 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
,
356 TAO_ORB_Core
* orb_core
= 0);
359 /// Create an input stream from an ACE_Data_Block
360 TAO_InputCDR (ACE_Data_Block
*data
,
361 ACE_Message_Block::Message_Flags flag
= 0,
362 int byte_order
= ACE_CDR_BYTE_ORDER
,
363 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
364 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
,
365 TAO_ORB_Core
* orb_core
= 0);
367 /// Create an input stream from an ACE_Data_Block
368 TAO_InputCDR (ACE_Data_Block
*data
,
369 ACE_Message_Block::Message_Flags flag
,
370 size_t read_pointer_position
,
371 size_t write_pointer_position
,
372 int byte_order
= ACE_CDR_BYTE_ORDER
,
373 ACE_CDR::Octet major_version
= TAO_DEF_GIOP_MAJOR
,
374 ACE_CDR::Octet minor_version
= TAO_DEF_GIOP_MINOR
,
375 TAO_ORB_Core
* orb_core
= 0);
378 * Make a copy of the current stream state, but does not copy the
379 * internal buffer; so the same stream can be read multiple times
382 TAO_InputCDR (const TAO_InputCDR
& rhs
);
384 /// When interpreting indirected TypeCodes it is useful to make a
385 /// "copy" of the stream starting in the new position.
386 TAO_InputCDR (const TAO_InputCDR
& rhs
,
388 ACE_CDR::Long offset
);
390 * This creates an encapsulated stream, the first byte must be (per
391 * the spec) the byte order of the encapsulation. The default
392 * values for the allocators in this constructor are not 0, but are
393 * generated by the ORB. Refer to the constructor body in CDR.cpp
394 * for the code that supplies these values to the base class
397 TAO_InputCDR (const TAO_InputCDR
& rhs
,
400 /// Create an input CDR from an output CDR.
401 TAO_InputCDR (const TAO_OutputCDR
& rhs
,
402 ACE_Allocator
* buffer_allocator
= 0,
403 ACE_Allocator
* data_block_allocator
= 0,
404 ACE_Allocator
* message_block_allocator
= 0,
405 TAO_ORB_Core
* orb_core
= 0);
407 /// Initialize the contents of one CDR from another, without data
408 /// copying and with minimum locking overhead.
409 TAO_InputCDR (ACE_InputCDR::Transfer_Contents rhs
,
410 TAO_ORB_Core
* orb_core
= 0);
412 TAO_InputCDR
& operator= (const TAO_InputCDR
&) = default;
415 virtual ~TAO_InputCDR ();
417 // = TAO specific methods.
420 TAO_ORB_Core
*orb_core () const;
422 ACE_Message_Block::Message_Flags
423 clr_mb_flags( ACE_Message_Block::Message_Flags less_flags
);
425 // = TAO specific methods.
426 static void throw_stub_exception (int error_num
);
427 static void throw_skel_exception (int error_num
);
429 /// These methods are used by valuetype indirection support.
430 /// Accessor to the indirect maps.
431 Repo_Id_Map_Handle
& get_repo_id_map ();
432 Codebase_URL_Map_Handle
& get_codebase_url_map ();
433 Value_Map_Handle
& get_value_map ();
435 /// Updater of the maps.
436 /// These updaters are used to make indirect maps in original stream
437 /// take effect even during marshalling/demarshalling a redirected stream.
438 void set_repo_id_map (Repo_Id_Map_Handle
& map
);
439 void set_codebase_url_map (Codebase_URL_Map_Handle
& map
);
440 void set_value_map (Value_Map_Handle
& map
);
442 /// If indirect map is not nil and not empty, unbind all entries.
443 /// Called after demarshalling.
444 void reset_vt_indirect_maps ();
447 /// The ORB_Core, required to extract object references.
448 TAO_ORB_Core
* orb_core_
;
450 /// These maps are used by valuetype indirection support.
451 Repo_Id_Map_Handle repo_id_map_
;
452 Codebase_URL_Map_Handle codebase_map_
;
453 Value_Map_Handle value_map_
;
456 TAO_END_VERSIONED_NAMESPACE_DECL
458 #if defined(__ACE_INLINE__)
459 # include "tao/CDR.inl"
462 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
464 // CDR output operators for CORBA types
466 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
468 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
470 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
472 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
474 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
476 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
478 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
& os
,
479 CORBA::LongDouble x
);
480 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
482 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
484 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
485 const CORBA::Char
* x
);
486 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
487 const CORBA::WChar
* x
);
488 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
489 ACE_OutputCDR::from_string x
);
490 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
491 ACE_OutputCDR::from_wstring x
);
492 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
493 const std::string
&x
);
494 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
495 const std::string_view
&x
);
496 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
497 ACE_OutputCDR::from_std_string x
);
498 #if !defined(ACE_LACKS_STD_WSTRING)
499 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
500 const std::wstring
&x
);
501 TAO_Export
CORBA::Boolean
operator<< (TAO_OutputCDR
&os
,
502 ACE_OutputCDR::from_std_wstring x
);
503 #endif /* ACE_LACKS_STD_WSTRING */
505 // CDR input operators for CORBA types
507 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
509 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
511 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
513 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
515 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
517 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
518 CORBA::ULongLong
&x
);
519 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
520 CORBA::LongDouble
&x
);
521 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
523 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
525 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
527 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&is
,
529 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&os
,
530 ACE_InputCDR::to_string x
);
531 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&os
,
532 ACE_InputCDR::to_wstring x
);
533 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&os
,
535 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&os
,
536 ACE_InputCDR::to_std_string x
);
537 #if !defined(ACE_LACKS_STD_WSTRING)
538 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&os
,
540 TAO_Export
CORBA::Boolean
operator>> (TAO_InputCDR
&os
,
541 ACE_InputCDR::to_std_wstring x
);
542 #endif /* ACE_LACKS_STD_WSTRING */
544 TAO_END_VERSIONED_NAMESPACE_DECL
546 #endif /* __ACE_INLINE */
548 #include /**/ "ace/post.h"
549 #endif /* TAO_CDR_H */