Merge pull request #2216 from jwillemsen/jwi-cxxversionchecks
[ACE_TAO.git] / TAO / tao / CodecFactory / CDR_Encaps_Codec.cpp
blob24a528eda8a057c0e94fe59ee1809d4ad4d132a1
1 // -*- C++ -*-
2 #include "tao/CodecFactory/CDR_Encaps_Codec.h"
4 #include "tao/CDR.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 (
22 CORBA::Octet major,
23 CORBA::Octet minor,
24 TAO_ORB_Core * orb_core,
25 TAO_Codeset_Translator_Base * char_trans,
26 TAO_Codeset_Translator_Base * wchar_trans)
27 : major_ (major),
28 minor_ (minor),
29 orb_core_ (orb_core),
30 char_translator_ (char_trans),
31 wchar_translator_ (wchar_trans)
35 TAO_CDR_Encaps_Codec::~TAO_CDR_Encaps_Codec ()
39 CORBA::OctetSeq *
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
51 0, // memcpy_tradeoff
52 this->major_,
53 this->minor_);
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))
65 && (cdr << data))
67 CORBA::OctetSeq * octet_seq = 0;
69 ACE_NEW_THROW_EX (octet_seq,
70 CORBA::OctetSeq,
71 CORBA::NO_MEMORY (
72 CORBA::SystemException::_tao_minor_code (
74 ENOMEM),
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 ();
83 i != 0;
84 i = i->cont ())
86 size_t const len = i->length ();
87 ACE_OS::memcpy (buf, i->rd_ptr (), len);
88 buf += len;
91 return safe_octet_seq._retn ();
94 throw ::CORBA::MARSHAL ();
97 CORBA::Any *
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,
118 rd_pos,
119 wr_pos,
120 ACE_CDR_BYTE_ORDER,
121 this->major_,
122 this->minor_,
123 this->orb_core_);
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,
141 CORBA::Any,
142 CORBA::NO_MEMORY (
143 CORBA::SystemException::_tao_minor_code (
145 ENOMEM),
146 CORBA::COMPLETED_NO));
148 CORBA::Any_var safe_any = any;
150 if (cdr >> (*any))
151 return safe_any._retn ();
154 throw IOP::Codec::FormatMismatch ();
157 CORBA::OctetSeq *
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
169 this->major_,
170 this->minor_);
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);
190 if (!unk)
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 (),
198 &for_reading,
199 &cdr);
201 else
203 impl->marshal_value (cdr);
206 // TAO extension: replace the contents of the octet sequence with
207 // the CDR stream.
208 CORBA::OctetSeq * octet_seq = 0;
210 ACE_NEW_THROW_EX (octet_seq,
211 CORBA::OctetSeq,
212 CORBA::NO_MEMORY (
213 CORBA::SystemException::_tao_minor_code (
215 ENOMEM
217 CORBA::COMPLETED_NO
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 ();
226 i != 0;
227 i = i->cont ())
229 size_t len = i->length ();
230 ACE_OS::memcpy (buf,
231 i->rd_ptr (),
232 len);
233 buf += len;
236 return safe_octet_seq._retn ();
239 throw ::CORBA::MARSHAL ();
242 CORBA::Any *
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 (),
256 data.get_buffer (),
257 data.length ());
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.
263 // -Ossama
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
270 // encapsulation.
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,
277 rd_pos,
278 wr_pos,
279 ACE_CDR_BYTE_ORDER,
280 this->major_,
281 this->minor_,
282 this->orb_core_);
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,
301 CORBA::Any,
302 CORBA::NO_MEMORY (
303 CORBA::SystemException::_tao_minor_code (
305 ENOMEM
307 CORBA::COMPLETED_NO
310 CORBA::Any_var safe_any = any;
312 // Stick it into the Any.
313 TAO::Unknown_IDL_Type *unk = 0;
314 ACE_NEW_RETURN (unk,
315 TAO::Unknown_IDL_Type (tc, cdr),
317 any->replace (unk);
318 return safe_any._retn ();
321 throw IOP::Codec::FormatMismatch ();
324 void
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
331 && this->minor_ == 0
332 && typecode->equivalent (CORBA::_tc_wstring))
333 throw IOP::Codec::InvalidTypeForEncoding ();
336 TAO_END_VERSIONED_NAMESPACE_DECL