2 #include "tao/CodecFactory/CDR_Encaps_Codec.h"
5 #include "tao/OctetSeqC.h"
6 #include "tao/AnyTypeCode/Any.h"
7 #include "tao/AnyTypeCode/Any_Impl.h"
8 #include "tao/AnyTypeCode/TypeCode.h"
9 #include "tao/AnyTypeCode/Marshal.h"
10 #include "tao/AnyTypeCode/Any_Unknown_IDL_Type.h"
11 #include "tao/AnyTypeCode/TypeCode_Constants.h"
12 #include "tao/SystemException.h"
13 #include "tao/ORB_Constants.h"
14 #include "tao/Codeset_Translator_Base.h"
16 #include "ace/OS_NS_string.h"
17 #include "ace/CORBA_macros.h"
19 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
21 TAO_CDR_Encaps_Codec::TAO_CDR_Encaps_Codec (
24 TAO_ORB_Core
* orb_core
,
25 TAO_Codeset_Translator_Base
* char_trans
,
26 TAO_Codeset_Translator_Base
* wchar_trans
)
30 char_translator_ (char_trans
),
31 wchar_translator_ (wchar_trans
)
35 TAO_CDR_Encaps_Codec::~TAO_CDR_Encaps_Codec ()
40 TAO_CDR_Encaps_Codec::encode (const CORBA::Any
& data
)
42 this->check_type_for_encoding (data
);
44 // ----------------------------------------------------------------
46 TAO_OutputCDR
cdr ((size_t) 0, // size
47 (int) TAO_ENCAP_BYTE_ORDER
,
48 (ACE_Allocator
*) 0, // buffer_allocator
49 (ACE_Allocator
*) 0, // data_block_allocator
50 (ACE_Allocator
*) 0, // message_block_allocator
55 if (this->char_translator_
)
57 this->char_translator_
->assign (&cdr
);
59 if (this->wchar_translator_
)
61 this->wchar_translator_
->assign (&cdr
);
64 if ((cdr
<< TAO_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER
))
67 CORBA::OctetSeq
* octet_seq
= 0;
69 ACE_NEW_THROW_EX (octet_seq
,
72 CORBA::SystemException::_tao_minor_code (
75 CORBA::COMPLETED_NO
));
77 CORBA::OctetSeq_var safe_octet_seq
= octet_seq
;
79 octet_seq
->length (static_cast<CORBA::ULong
> (cdr
.total_length ()));
80 CORBA::Octet
*buf
= octet_seq
->get_buffer ();
82 for (const ACE_Message_Block
*i
= cdr
.begin ();
86 size_t const len
= i
->length ();
87 ACE_OS::memcpy (buf
, i
->rd_ptr (), len
);
91 return safe_octet_seq
._retn ();
94 throw ::CORBA::MARSHAL ();
98 TAO_CDR_Encaps_Codec::decode (const CORBA::OctetSeq
& data
)
100 // @todo How do we check for a format mismatch so that we can throw
101 // a IOP::Codec::FormatMismatch exception?
102 // @todo Is this the best way to extract the Any from the OctetSeq?
104 // Notice that we need to extract the TypeCode and the value from
105 // the octet sequence, and place them into the Any. We can't just
106 // insert the octet sequence into the Any.
108 ACE_Message_Block
mb (data
.length () + 2 * ACE_CDR::MAX_ALIGNMENT
);
109 ACE_CDR::mb_align (&mb
);
111 ACE_OS::memcpy (mb
.rd_ptr (), data
.get_buffer (), data
.length ());
113 size_t rd_pos
= mb
.rd_ptr () - mb
.base ();
114 size_t wr_pos
= mb
.wr_ptr () - mb
.base () + data
.length ();
116 TAO_InputCDR
cdr (mb
.data_block (),
117 ACE_Message_Block::DONT_DELETE
,
125 if (this->char_translator_
)
127 this->char_translator_
->assign (&cdr
);
129 if (this->wchar_translator_
)
131 this->wchar_translator_
->assign (&cdr
);
134 CORBA::Boolean byte_order
;
135 if (cdr
>> TAO_InputCDR::to_boolean (byte_order
))
137 cdr
.reset_byte_order (static_cast<int> (byte_order
));
139 CORBA::Any
* any
= 0;
140 ACE_NEW_THROW_EX (any
,
143 CORBA::SystemException::_tao_minor_code (
146 CORBA::COMPLETED_NO
));
148 CORBA::Any_var safe_any
= any
;
151 return safe_any
._retn ();
154 throw IOP::Codec::FormatMismatch ();
158 TAO_CDR_Encaps_Codec::encode_value (const CORBA::Any
& data
)
160 this->check_type_for_encoding (data
);
162 // ----------------------------------------------------------------
163 TAO_OutputCDR
cdr ((size_t) 0, // size
164 (int) TAO_ENCAP_BYTE_ORDER
,
165 (ACE_Allocator
*) 0, // buffer_allocator
166 (ACE_Allocator
*) 0, // data_block_allocator
167 (ACE_Allocator
*) 0, // message_block_allocator
168 0, // memcpy_tradeoff
172 if (this->char_translator_
)
174 this->char_translator_
->assign (&cdr
);
176 if (this->wchar_translator_
)
178 this->wchar_translator_
->assign (&cdr
);
181 if ((cdr
<< TAO_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER
)))
183 TAO::Any_Impl
*impl
= data
.impl ();
185 if (impl
->encoded ())
187 TAO::Unknown_IDL_Type
* const unk
=
188 dynamic_cast<TAO::Unknown_IDL_Type
*> (impl
);
191 throw ::CORBA::INTERNAL ();
193 // We don't want unk's rd_ptr to move, in case we are shared by
194 // another Any, so we use this to copy the state, not the buffer.
195 TAO_InputCDR
for_reading (unk
->_tao_get_cdr ());
197 TAO_Marshal_Object::perform_append (data
._tao_get_typecode (),
203 impl
->marshal_value (cdr
);
206 // TAO extension: replace the contents of the octet sequence with
208 CORBA::OctetSeq
* octet_seq
= 0;
210 ACE_NEW_THROW_EX (octet_seq
,
213 CORBA::SystemException::_tao_minor_code (
220 CORBA::OctetSeq_var safe_octet_seq
= octet_seq
;
222 octet_seq
->length (static_cast<CORBA::ULong
> (cdr
.total_length ()));
223 CORBA::Octet
*buf
= octet_seq
->get_buffer ();
225 for (const ACE_Message_Block
*i
= cdr
.begin ();
229 size_t len
= i
->length ();
236 return safe_octet_seq
._retn ();
239 throw ::CORBA::MARSHAL ();
243 TAO_CDR_Encaps_Codec::decode_value (const CORBA::OctetSeq
& data
,
244 CORBA::TypeCode_ptr tc
)
246 // The ACE_CDR::mb_align() call can shift the rd_ptr by up
247 // to ACE_CDR::MAX_ALIGNMENT-1 bytes. Similarly, the offset
248 // adjustment can move the rd_ptr by up to the same amount.
249 // We accommodate this by including
250 // 2 * ACE_CDR::MAX_ALIGNMENT bytes of additional space in
251 // the message block.
252 ACE_Message_Block
mb (data
.length () + 2 * ACE_CDR::MAX_ALIGNMENT
);
253 ACE_CDR::mb_align (&mb
);
255 ACE_OS::memcpy (mb
.rd_ptr (),
259 // @todo How do we check for a type mismatch so that we can
260 // throw a IOP::Codec::TypeMismatch exception?
261 // @@ I added a check below. See the comment. I'm not sure
262 // if it is a valid check.
265 // @todo Most of this code was copied from
266 // operator>> (TAO_InputCDR &cdr, CORBA::Any &x)
267 // in Any.cpp. Rather than copy the code, the code should be
268 // refactored to make it possible to use the given TypeCode
269 // rather than attempt to extract it from the CDR
272 size_t rd_pos
= mb
.rd_ptr () - mb
.base ();
273 size_t wr_pos
= mb
.wr_ptr () - mb
.base () + data
.length ();
275 TAO_InputCDR
cdr (mb
.data_block (),
276 ACE_Message_Block::DONT_DELETE
,
284 if (this->char_translator_
)
286 this->char_translator_
->assign (&cdr
);
288 if (this->wchar_translator_
)
290 this->wchar_translator_
->assign (&cdr
);
293 CORBA::Boolean byte_order
;
295 if (cdr
>> TAO_InputCDR::to_boolean (byte_order
))
297 cdr
.reset_byte_order (static_cast<int> (byte_order
));
299 CORBA::Any
* any
= 0;
300 ACE_NEW_THROW_EX (any
,
303 CORBA::SystemException::_tao_minor_code (
310 CORBA::Any_var safe_any
= any
;
312 // Stick it into the Any.
313 TAO::Unknown_IDL_Type
*unk
= 0;
315 TAO::Unknown_IDL_Type (tc
, cdr
),
318 return safe_any
._retn ();
321 throw IOP::Codec::FormatMismatch ();
325 TAO_CDR_Encaps_Codec::check_type_for_encoding (const CORBA::Any
& data
)
327 // @@ TODO: Are there any other conditions we need to check?
329 CORBA::TypeCode_var typecode
= data
.type ();
330 if (this->major_
== 1
332 && typecode
->equivalent (CORBA::_tc_wstring
))
333 throw IOP::Codec::InvalidTypeForEncoding ();
336 TAO_END_VERSIONED_NAMESPACE_DECL