=default for generated implementation copy ctor
[ACE_TAO.git] / TAO / tao / DynamicAny / DynStruct_i.cpp
blobbfa40f2874ea91b95836508488a6004c8504710e
1 // -*- C++ -*-
2 #include "tao/DynamicAny/DynStruct_i.h"
3 #include "tao/DynamicAny/DynAnyFactory.h"
4 #include "tao/DynamicAny/DynAnyUtils_T.h"
6 #include "tao/AnyTypeCode/Marshal.h"
7 #include "tao/AnyTypeCode/Any_Unknown_IDL_Type.h"
8 #include "tao/AnyTypeCode/AnyTypeCode_methods.h"
10 #include "tao/CDR.h"
12 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
14 TAO_DynStruct_i::TAO_DynStruct_i (CORBA::Boolean allow_truncation)
15 : TAO_DynCommon (allow_truncation)
19 TAO_DynStruct_i::~TAO_DynStruct_i ()
23 void
24 TAO_DynStruct_i::check_typecode (CORBA::TypeCode_ptr tc)
26 CORBA::TCKind kind = TAO_DynAnyFactory::unalias (tc);
28 if (kind == CORBA::tk_struct || kind == CORBA::tk_except)
30 return;
33 throw DynamicAny::DynAnyFactory::InconsistentTypeCode ();
36 void
37 TAO_DynStruct_i::init_common ()
39 this->ref_to_component_ = false;
40 this->container_is_destroying_ = false;
41 this->has_components_ = true;
42 this->destroyed_ = false;
43 this->component_count_ = static_cast <CORBA::ULong> (this->da_members_.size ());
44 this->current_position_ = this->component_count_ ? 0 : -1;
47 void
48 TAO_DynStruct_i::init (const CORBA::Any& any)
50 CORBA::TypeCode_ptr tc = any._tao_get_typecode ();
51 this->check_typecode (tc);
53 this->type_ = CORBA::TypeCode::_duplicate (tc);
55 this->set_from_any (any);
59 // This code is common to from_any() and the init() overload that takes
60 // an Any argument.
61 void
62 TAO_DynStruct_i::set_from_any (const CORBA::Any & any)
64 // member_type() does not work with aliased type codes.
65 CORBA::TypeCode_var unaliased_tc =
66 TAO_DynAnyFactory::strip_alias (any._tao_get_typecode ());
68 CORBA::ULong numfields =
69 unaliased_tc->member_count ();
71 // Resize the array.
72 this->da_members_.size (numfields);
74 this->init_common ();
76 // Get the CDR stream of the Any, if there isn't one, make one.
77 TAO::Any_Impl *impl = any.impl ();
78 TAO_OutputCDR out;
79 TAO_InputCDR in (static_cast<ACE_Message_Block *> (0));
80 TAO::Unknown_IDL_Type *unk = 0;
82 if (impl->encoded ())
84 unk = dynamic_cast<TAO::Unknown_IDL_Type *> (impl);
86 if (!unk)
87 throw CORBA::INTERNAL ();
89 in = unk->_tao_get_cdr ();
91 else
93 impl->marshal_value (out);
94 TAO_InputCDR tmp_in (out);
95 in = tmp_in;
98 // If we have an exception type, unmarshal the repository ID.
99 CORBA::TCKind kind = TAO_DynAnyFactory::unalias (any._tao_get_typecode ());
101 if (kind == CORBA::tk_except)
103 CORBA::String_var str;
104 in >> str.out ();
107 for (CORBA::ULong i = 0; i < numfields; i++)
109 CORBA::TypeCode_var field_tc =
110 unaliased_tc->member_type (i);
112 CORBA::Any field_any;
113 TAO_InputCDR unk_in (in);
114 ACE_NEW (unk,
115 TAO::Unknown_IDL_Type (field_tc.in (),
116 unk_in));
117 field_any.replace (unk);
119 // This recursive step will call the correct constructor
120 // based on the type of field_any.
121 this->da_members_[i] =
122 TAO::MakeDynAnyUtils::make_dyn_any_t<const CORBA::Any&> (
123 field_any._tao_get_typecode (),
124 field_any,
125 this->allow_truncation_);
127 // Move to the next field in the CDR stream.
128 (void) TAO_Marshal_Object::perform_skip (field_tc.in (), &in);
132 void
133 TAO_DynStruct_i::init (CORBA::TypeCode_ptr tc)
135 this->check_typecode (tc);
137 this->type_ = CORBA::TypeCode::_duplicate (tc);
139 // member_type() does not work with aliased type codes.
140 CORBA::TypeCode_var unaliased_tc =
141 TAO_DynAnyFactory::strip_alias (this->type_.in ());
143 this->component_count_ =
144 unaliased_tc->member_count ();
146 // Resize the array.
147 this->da_members_.size (this->component_count_);
149 this->init_common ();
151 CORBA::TypeCode_var mtype;
153 for (CORBA::ULong i = 0; i < this->component_count_; ++i)
155 mtype = unaliased_tc->member_type (i);
157 // Recursively initialize each member.
158 this->da_members_[i] =
159 TAO::MakeDynAnyUtils::make_dyn_any_t<CORBA::TypeCode_ptr> (
160 mtype.in (),
161 mtype.in (),
162 this->allow_truncation_);
166 // ****************************************************************
168 TAO_DynStruct_i *
169 TAO_DynStruct_i::_narrow (CORBA::Object_ptr _tao_objref)
171 if (CORBA::is_nil (_tao_objref))
173 return 0;
176 return dynamic_cast<TAO_DynStruct_i *> (_tao_objref);
179 // ****************************************************************
181 DynamicAny::FieldName
182 TAO_DynStruct_i::current_member_name ()
184 if (this->destroyed_)
186 throw ::CORBA::OBJECT_NOT_EXIST ();
189 // Is this an empty exception?
190 if (this->component_count_ == 0)
192 throw DynamicAny::DynAny::TypeMismatch ();
195 if (this->current_position_ == -1)
197 throw DynamicAny::DynAny::InvalidValue ();
200 // member_name() does not work with aliased type codes.
201 CORBA::TypeCode_var unaliased_tc =
202 TAO_DynAnyFactory::strip_alias (this->type_.in ());
203 const char *name =
204 unaliased_tc->member_name (this->current_position_);
206 return CORBA::string_dup (name);
209 // Returns the unaliased TCKind.
210 CORBA::TCKind
211 TAO_DynStruct_i::current_member_kind ()
213 if (this->destroyed_)
215 throw ::CORBA::OBJECT_NOT_EXIST ();
218 // Is this an empty exception?
219 if (this->component_count_ == 0)
221 throw DynamicAny::DynAny::TypeMismatch ();
224 if (this->current_position_ == -1)
226 throw DynamicAny::DynAny::InvalidValue ();
229 // member_type() does not work with aliased type codes.
230 CORBA::TypeCode_var unaliased_tc =
231 TAO_DynAnyFactory::strip_alias (this->type_.in ());
232 CORBA::TypeCode_var tc =
233 unaliased_tc->member_type (this->current_position_);
235 CORBA::TCKind retval = TAO_DynAnyFactory::unalias (tc.in ());
237 return retval;
240 DynamicAny::NameValuePairSeq *
241 TAO_DynStruct_i::get_members ()
243 if (this->destroyed_)
245 throw ::CORBA::OBJECT_NOT_EXIST ();
248 DynamicAny::NameValuePairSeq* members;
249 ACE_NEW_THROW_EX (members,
250 DynamicAny::NameValuePairSeq (this->component_count_),
251 CORBA::NO_MEMORY ());
253 // We must do this explicitly.
254 members->length (this->component_count_);
256 DynamicAny::NameValuePairSeq_var safe_retval = members;
257 CORBA::Any_var temp;
258 CORBA::TypeCode_var unaliased_tc;
260 CORBA::TCKind const tc_kind =
261 this->type_->kind ();
263 if (tc_kind == CORBA::tk_alias)
265 unaliased_tc = TAO_DynAnyFactory::strip_alias (this->type_.in ());
267 else
269 unaliased_tc = CORBA::TypeCode::_duplicate (this->type_.in ());
272 // Assign name and value to each pearl on the string.
273 for (CORBA::ULong i = 0; i < this->component_count_; ++i)
275 safe_retval[i].id =
276 CORBA::string_dup (unaliased_tc->member_name (i));
278 temp = this->da_members_[i]->to_any ();
280 safe_retval[i].value = temp.in ();
283 return safe_retval._retn ();
286 void
287 TAO_DynStruct_i::set_members (const DynamicAny::NameValuePairSeq & values)
289 if (this->destroyed_)
291 throw ::CORBA::OBJECT_NOT_EXIST ();
294 CORBA::ULong length = values.length ();
296 // Check for length match.
297 if (length != this->component_count_)
299 throw DynamicAny::DynAny::InvalidValue ();
302 CORBA::TypeCode_var value_tc;
303 CORBA::TypeCode_var my_tc;
304 CORBA::Boolean equivalent;
306 // member_type() does not work with aliased type codes.
307 CORBA::TypeCode_var unaliased_tc =
308 TAO_DynAnyFactory::strip_alias (this->type_.in ());
310 for (CORBA::ULong i = 0; i < length; ++i)
312 // Check for type and name match.
313 my_tc = unaliased_tc->member_type (i);
315 value_tc = values[i].value.type ();
317 equivalent = my_tc->equivalent (value_tc.in ());
319 if (!equivalent)
321 throw DynamicAny::DynAny::TypeMismatch ();
324 this->da_members_[i]->destroy ();
326 this->da_members_[i] =
327 TAO::MakeDynAnyUtils::make_dyn_any_t<const CORBA::Any&> (
328 values[i].value._tao_get_typecode (),
329 values[i].value,
330 this->allow_truncation_);
333 this->current_position_ = length ? 0 : -1;
336 DynamicAny::NameDynAnyPairSeq *
337 TAO_DynStruct_i::get_members_as_dyn_any ()
339 if (this->destroyed_)
341 throw ::CORBA::OBJECT_NOT_EXIST ();
344 DynamicAny::NameDynAnyPairSeq * members;
345 ACE_NEW_THROW_EX (members,
346 DynamicAny::NameDynAnyPairSeq (this->component_count_),
347 CORBA::NO_MEMORY ());
349 // We must do this explicitly.
350 members->length (this->component_count_);
352 DynamicAny::NameDynAnyPairSeq_var safe_retval = members;
354 // member_name() does not work with aliased type codes.
355 CORBA::TypeCode_var unaliased_tc =
356 TAO_DynAnyFactory::strip_alias (this->type_.in ());
358 // Assign name and value to each pearl on the string.
359 for (CORBA::ULong i = 0; i < this->component_count_; ++i)
361 safe_retval[i].id = CORBA::string_dup (unaliased_tc->member_name (i));
363 // A deep copy is made only by copy() (CORBA 2.4.2 section 9.2.3.6).
364 // Set the flag so the caller can't destroy.
365 this->set_flag (this->da_members_[i].in (), 0);
367 safe_retval[i].value =
368 DynamicAny::DynAny::_duplicate (this->da_members_[i].in ());
371 return safe_retval._retn ();
374 void
375 TAO_DynStruct_i::set_members_as_dyn_any (
376 const DynamicAny::NameDynAnyPairSeq & values
380 if (this->destroyed_)
382 throw ::CORBA::OBJECT_NOT_EXIST ();
385 CORBA::ULong length = values.length ();
387 // Check for length match.
388 if (length != this->component_count_)
390 throw DynamicAny::DynAny::InvalidValue ();
393 CORBA::TypeCode_var value_tc;
394 CORBA::TypeCode_var my_tc;
395 CORBA::Boolean equivalent;
397 // member_type() does not work with aliased type codes.
398 CORBA::TypeCode_var unaliased_tc =
399 TAO_DynAnyFactory::strip_alias (this->type_.in ());
401 for (CORBA::ULong i = 0; i < length; ++i)
403 // Check for type and name match.
404 my_tc = unaliased_tc->member_type (i);
406 value_tc = values[i].value->type ();
408 equivalent = my_tc->equivalent (value_tc.in ());
410 if (!equivalent)
412 throw DynamicAny::DynAny::TypeMismatch ();
415 this->da_members_[i]->destroy ();
417 this->da_members_[i] =
418 values[i].value->copy ();
421 this->current_position_ = length ? 0 : -1;
424 // ****************************************************************
426 void
427 TAO_DynStruct_i::from_any (const CORBA::Any & any)
429 if (this->destroyed_)
431 throw ::CORBA::OBJECT_NOT_EXIST ();
434 CORBA::TypeCode_var tc = any.type ();
435 CORBA::Boolean equivalent =
436 this->type_->equivalent (tc.in ());
438 if (equivalent)
440 // Get the CDR stream of the Any, if there isn't one, make one.
441 TAO::Any_Impl *impl = any.impl ();
442 TAO_OutputCDR out;
443 TAO_InputCDR in (static_cast<ACE_Message_Block *> (0));
444 TAO::Unknown_IDL_Type *unk = 0;
446 if (impl->encoded ())
448 unk = dynamic_cast<TAO::Unknown_IDL_Type *> (impl);
450 if (!unk)
451 throw CORBA::INTERNAL ();
453 in = unk->_tao_get_cdr ();
455 else
457 impl->marshal_value (out);
458 TAO_InputCDR tmp_in (out);
459 in = tmp_in;
462 // If we have an exception type, unmarshal the repository ID.
463 CORBA::TCKind kind =
464 TAO_DynAnyFactory::unalias (this->type_.in ());
466 if (kind == CORBA::tk_except)
468 CORBA::String_var str;
469 in >> str.out ();
472 CORBA::TypeCode_var field_tc;
473 CORBA::TypeCode_var unaliased =
474 TAO::unaliased_typecode (this->type_.in ());
476 for (CORBA::ULong i = 0; i < this->component_count_; ++i)
478 field_tc = unaliased->member_type (i);
480 CORBA::Any field_any;
481 TAO_InputCDR unk_in (in);
482 TAO::Unknown_IDL_Type *unk = 0;
483 ACE_NEW (unk,
484 TAO::Unknown_IDL_Type (field_tc.in (),
485 unk_in));
486 field_any.replace (unk);
488 this->da_members_[i]->destroy ();
490 this->da_members_[i] =
491 TAO::MakeDynAnyUtils::make_dyn_any_t<const CORBA::Any&> (
492 field_any._tao_get_typecode (),
493 field_any,
494 this->allow_truncation_);
496 // Move to the next field in the CDR stream.
497 (void) TAO_Marshal_Object::perform_skip (field_tc.in (), &in);
500 this->current_position_ = this->component_count_ ? 0 : -1;
502 else
504 throw DynamicAny::DynAny::TypeMismatch ();
508 CORBA::Any_ptr
509 TAO_DynStruct_i::to_any ()
511 if (this->destroyed_)
513 throw ::CORBA::OBJECT_NOT_EXIST ();
516 TAO_OutputCDR out_cdr;
518 // If we have an exception type, marshal the repository ID.
519 CORBA::TCKind kind = TAO_DynAnyFactory::unalias (this->type_.in ());
521 if (kind == CORBA::tk_except)
523 out_cdr << this->type_->id ();
526 TAO::Any_Impl *field_impl = 0;
527 TAO::Unknown_IDL_Type *field_unk = 0;
528 TAO_InputCDR field_in_cdr (static_cast<ACE_Message_Block *> (0));
530 for (CORBA::ULong i = 0; i < this->component_count_; ++i)
532 CORBA::TypeCode_var field_tc =
533 this->da_members_[i]->type ();
535 // Recursive step.
536 CORBA::Any_var field_any =
537 this->da_members_[i]->to_any ();
539 TAO_OutputCDR field_out_cdr;
540 field_impl = field_any->impl ();
542 if (field_impl->encoded ())
544 field_unk =
545 dynamic_cast<TAO::Unknown_IDL_Type *> (field_impl);
547 if (!field_unk)
548 throw CORBA::INTERNAL ();
550 field_in_cdr = field_unk->_tao_get_cdr ();
552 else
554 field_impl->marshal_value (field_out_cdr);
555 TAO_InputCDR tmp (field_out_cdr);
556 field_in_cdr = tmp;
559 (void) TAO_Marshal_Object::perform_append (field_tc.in (),
560 &field_in_cdr,
561 &out_cdr);
564 TAO_InputCDR in_cdr (out_cdr);
566 CORBA::Any_ptr retval = 0;
567 ACE_NEW_THROW_EX (retval,
568 CORBA::Any,
569 CORBA::NO_MEMORY ());
571 TAO::Unknown_IDL_Type *unk = 0;
572 ACE_NEW_THROW_EX (unk,
573 TAO::Unknown_IDL_Type (this->type_.in (),
574 in_cdr),
575 CORBA::NO_MEMORY ());
577 retval->replace (unk);
578 return retval;
581 CORBA::Boolean
582 TAO_DynStruct_i::equal (DynamicAny::DynAny_ptr rhs)
584 if (this->destroyed_)
586 throw ::CORBA::OBJECT_NOT_EXIST ();
589 CORBA::TypeCode_var tc = rhs->type ();
591 if (!tc->equivalent (this->type_.in ()))
593 return false;
596 DynamicAny::DynAny_var tmp;
597 CORBA::Boolean member_equal;
599 for (CORBA::ULong i = 0; i < this->component_count_; ++i)
601 rhs->seek (static_cast <CORBA::Long> (i));
603 tmp = rhs->current_component ();
605 // Recursive step.
606 member_equal = tmp->equal (this->da_members_[i].in ());
608 if (!member_equal)
610 return 0;
614 return true;
617 void
618 TAO_DynStruct_i::destroy ()
620 if (this->destroyed_)
622 throw ::CORBA::OBJECT_NOT_EXIST ();
625 if (!this->ref_to_component_ || this->container_is_destroying_)
627 // Do a deep destroy.
628 for (CORBA::ULong i = 0; i < this->component_count_; ++i)
630 this->set_flag (da_members_[i].in (), 1);
632 this->da_members_[i]->destroy ();
635 this->destroyed_ = 1;
639 DynamicAny::DynAny_ptr
640 TAO_DynStruct_i::current_component ()
642 if (this->destroyed_)
644 throw ::CORBA::OBJECT_NOT_EXIST ();
647 if (this->component_count_ == 0)
649 // Empty exception - no component.
650 throw DynamicAny::DynAny::TypeMismatch ();
653 if (this->current_position_ == -1)
655 return DynamicAny::DynAny::_nil ();
658 CORBA::ULong index = static_cast <CORBA::ULong> (this->current_position_);
660 this->set_flag (this->da_members_[index].in (), 0);
662 return DynamicAny::DynAny::_duplicate (this->da_members_[index].in ());
665 TAO_END_VERSIONED_NAMESPACE_DECL