Merge pull request #2218 from jwillemsen/jwi-pthreadsigmask
[ACE_TAO.git] / TAO / tao / DynamicAny / DynValue_i.cpp
blob728b5614b1add08116646b58c847957236ef423a
1 // -*- C++ -*-
2 #include "tao/DynamicAny/DynValue_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"
11 #include "tao/Valuetype/ValueBase.h"
13 #include "ace/Truncate.h"
15 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
17 TAO_DynValue_i::TAO_DynValue_i (CORBA::Boolean allow_truncation)
18 : TAO_DynCommon (allow_truncation)
19 , TAO_DynAny_i (allow_truncation)
20 , TAO_DynValueCommon_i (allow_truncation)
24 TAO_DynValue_i::~TAO_DynValue_i ()
28 void
29 TAO_DynValue_i::init (const CORBA::Any & any)
31 this->init_helper (any._tao_get_typecode ());
32 this->from_any_helper (any);
34 // init() is called only from DynAnyFactory create_*
35 // methods. These are the only functions that can
36 // throw MustTruncate, so once init () has completed
37 // revert to always allowing truncation.
38 this->allow_truncation_ = true;
41 void
42 TAO_DynValue_i::init (CORBA::TypeCode_ptr tc, TAO_InputCDR &in)
44 this->init_helper (tc);
45 this->from_inputCDR (in);
47 // init() is called only from DynAnyFactory create_*
48 // methods. These are the only functions that can
49 // throw MustTruncate, so once init () has completed
50 // revert to always allowing truncation.
51 this->allow_truncation_ = true;
54 void
55 TAO_DynValue_i::init (CORBA::TypeCode_ptr tc)
57 this->init_helper (tc);
59 // Each member is now (recursively) set-up
60 // with its own correct typecode.
62 for (CORBA::ULong i = 0u;
63 i < this->component_count_;
64 ++i)
66 CORBA::TypeCode_var
67 member_type (
68 get_member_type (this->da_base_types_, i));
70 this->da_members_[i] = TAO::MakeDynAnyUtils::
71 make_dyn_any_t<CORBA::TypeCode_ptr>
72 (member_type.in (), member_type.in (), this->allow_truncation_);
75 this->set_to_null ();
77 // init() is called only from DynAnyFactory create_*
78 // methods. These are the only functions that can
79 // throw MustTruncate, so once init () has completed
80 // revert to always allowing truncation.
81 this->allow_truncation_ = true;
84 void
85 TAO_DynValue_i::init_helper (CORBA::TypeCode_ptr tc)
87 // Ensure we have been given a valid ValueType
88 // typecode and then store a copy of the original.
90 this->check_typecode (tc);
91 this->type_ = CORBA::TypeCode::_duplicate (tc);
93 // Work out how many total members and types there
94 // are in total in this derived->base hiarchy.
96 get_base_types (
97 tc,
98 this->da_base_types_,
99 &this->component_count_);
100 this->da_members_.size (this->component_count_);
102 // And initalize all of the DynCommon mix-in
104 this->init_common ();
107 void
108 TAO_DynValue_i::get_base_types (
109 CORBA::TypeCode_ptr tc,
110 BaseTypesList_t &base_types,
111 CORBA::ULong *total_member_count)
113 // First initalize to the fully derived type we are
114 // starting with.
116 CORBA::ULong numberOfBases = 1u;
117 base_types.size (numberOfBases);
118 base_types[0] = TAO_DynAnyFactory::strip_alias (tc);
119 if (total_member_count)
121 *total_member_count =
122 base_types[0]->member_count ();
125 // Obtain each derived type's basetype and add this to
126 // the list.
128 CORBA::TypeCode_var
129 base (base_types[0]->concrete_base_type());
130 while (base.in() &&
131 CORBA::tk_value ==
132 (base= // assignment
133 TAO_DynAnyFactory::strip_alias (base.in()))
134 ->kind ())
136 if (total_member_count)
138 *total_member_count += base->member_count ();
141 base_types.size (numberOfBases + 1);
142 base_types[numberOfBases++] =
143 CORBA::TypeCode::_duplicate (base.in ());
144 base = base->concrete_base_type();
148 CORBA::TypeCode_ptr
149 TAO_DynValue_i::get_correct_base_type (
150 const BaseTypesList_t &base_types,
151 CORBA::ULong &index)
153 // We work backwards through the list of derived types,
154 // so index 0 is the first member of the extreme base type
155 // (assuming it has any members) once we run out of that
156 // base types members we move up the list to the next
157 // derived type until that type's members are exhausted
158 // and so on until we reach the member we have asked for.
160 CORBA::ULong
161 currentBase = ACE_Utils::truncate_cast<CORBA::ULong> (base_types.size ());
162 if (!currentBase)
164 TAOLIB_DEBUG ((LM_DEBUG,
165 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::get_correct_base_type () ")
166 ACE_TEXT ("BaseTypesList_t is not initialised\n")));
167 return 0;
170 while (base_types[--currentBase]->member_count () <= index)
172 index -= base_types[currentBase]->member_count ();
173 if (!currentBase)
175 TAOLIB_DEBUG ((LM_DEBUG,
176 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::get_correct_base_type () ")
177 ACE_TEXT ("BaseTypesList_t is not large enough\n")));
178 return 0;
182 // Note that the "index" has now been reduced to the range
183 // of the returning base_type.
184 return base_types[currentBase].in ();
187 CORBA::TypeCode_ptr
188 TAO_DynValue_i::get_member_type (
189 const BaseTypesList_t &base_types,
190 CORBA::ULong index)
192 const CORBA::TypeCode_ptr
193 base = get_correct_base_type (base_types, index);
194 return base->member_type (index);
197 const char *
198 TAO_DynValue_i::get_member_name (
199 const BaseTypesList_t &base_types,
200 CORBA::ULong index)
202 const CORBA::TypeCode_ptr
203 base = get_correct_base_type (base_types, index);
204 return base->member_name (index);
207 void
208 TAO_DynValue_i::set_to_value ()
210 this->component_count_ =
211 static_cast <CORBA::ULong> (this->da_members_.size ());
212 this->current_position_ =
213 this->component_count_ ? 0 : -1;
214 this->is_null_ = false;
217 void
218 TAO_DynValue_i::check_typecode (CORBA::TypeCode_ptr tc)
220 if (CORBA::tk_value == TAO_DynAnyFactory::unalias (tc))
222 return;
225 throw DynamicAny::DynAnyFactory::InconsistentTypeCode ();
228 TAO_DynValue_i *
229 TAO_DynValue_i::_narrow (CORBA::Object_ptr _tao_objref)
231 return (CORBA::is_nil (_tao_objref)) ?
233 dynamic_cast<TAO_DynValue_i *> (_tao_objref);
236 DynamicAny::FieldName
237 TAO_DynValue_i::current_member_name ()
239 if (this->destroyed_)
241 throw ::CORBA::OBJECT_NOT_EXIST ();
244 if (-1 == this->current_position_)
246 throw DynamicAny::DynAny::InvalidValue ();
249 return CORBA::string_dup (
250 this->get_member_name (
251 this->da_base_types_,
252 this->current_position_));
255 CORBA::TCKind
256 TAO_DynValue_i::current_member_kind ()
258 if (this->destroyed_)
260 throw ::CORBA::OBJECT_NOT_EXIST ();
263 if (-1 == this->current_position_)
265 throw DynamicAny::DynAny::InvalidValue ();
268 CORBA::TypeCode_var tc (
269 get_member_type (
270 this->da_base_types_,
271 this->current_position_));
272 return TAO_DynAnyFactory::unalias (tc.in ());
275 DynamicAny::NameValuePairSeq *
276 TAO_DynValue_i::get_members ()
278 if (this->destroyed_)
280 throw ::CORBA::OBJECT_NOT_EXIST ();
283 // Create the return NameValuePairSeq
284 DynamicAny::NameValuePairSeq *members = 0;
285 ACE_NEW_THROW_EX (
286 members,
287 DynamicAny::NameValuePairSeq (this->component_count_),
288 CORBA::NO_MEMORY ());
289 members->length (this->component_count_);
290 DynamicAny::NameValuePairSeq_var
291 safe_retval (members);
293 // Assign member name and value to each slot.
294 for (CORBA::ULong i = 0u;
295 i < this->component_count_;
296 ++i)
298 safe_retval[i].id = CORBA::string_dup (
299 this->get_member_name (this->da_base_types_, i));
300 CORBA::Any_var
301 temp (this->da_members_[i]->to_any ());
302 safe_retval[i].value = temp.in ();
305 return safe_retval._retn ();
308 void
309 TAO_DynValue_i::set_members (
310 const DynamicAny::NameValuePairSeq &values)
312 if (this->destroyed_)
314 throw ::CORBA::OBJECT_NOT_EXIST ();
317 // Check lengths match.
318 const CORBA::ULong length = values.length ();
319 if (length !=
320 static_cast <CORBA::ULong>
321 (this->da_members_.size ()))
323 throw DynamicAny::DynAny::InvalidValue ();
326 // Check each member typecodes match.
327 CORBA::ULong i;
328 for (i = 0u; i < length; ++i)
330 CORBA::TypeCode_var my_member (
331 get_member_type (this->da_base_types_, i));
332 CORBA::TypeCode_var value_member (
333 values[i].value.type ());
334 if (!my_member->equivalent (value_member.in ()))
336 throw DynamicAny::DynAny::TypeMismatch ();
340 // Copy in the new values to each member ()
341 for (i = 0u; i < length; ++i)
343 this->da_members_[i] = TAO::MakeDynAnyUtils::
344 make_dyn_any_t<const CORBA::Any&> (
345 values[i].value._tao_get_typecode (),
346 values[i].value,
347 this->allow_truncation_);
350 this->set_to_value ();
353 DynamicAny::NameDynAnyPairSeq *
354 TAO_DynValue_i::get_members_as_dyn_any ()
356 if (this->destroyed_)
358 throw ::CORBA::OBJECT_NOT_EXIST ();
361 // Create the return NameDynAnyPairSeq
362 DynamicAny::NameDynAnyPairSeq *members = 0;
363 ACE_NEW_THROW_EX (
364 members,
365 DynamicAny::NameDynAnyPairSeq (this->component_count_),
366 CORBA::NO_MEMORY ());
367 members->length (this->component_count_);
368 DynamicAny::NameDynAnyPairSeq_var
369 safe_retval (members);
371 // Assign name and value to each pearl on the string.
372 for (CORBA::ULong i = 0u;
373 i < this->component_count_;
374 ++i)
376 safe_retval[i].id = CORBA::string_dup (
377 this->get_member_name (this->da_base_types_, i));
379 // A deep copy is made only by copy()
380 // (CORBA 2.4.2 section 9.2.3.6).
381 // Set the flag so the caller can't destroy.
382 this->set_flag (this->da_members_[i].in (), 0);
384 safe_retval[i].value =
385 DynamicAny::DynAny::_duplicate (
386 this->da_members_[i].in ());
389 return safe_retval._retn ();
392 void
393 TAO_DynValue_i::set_members_as_dyn_any (
394 const DynamicAny::NameDynAnyPairSeq & values)
396 if (this->destroyed_)
398 throw ::CORBA::OBJECT_NOT_EXIST ();
401 // Check lengths match.
402 CORBA::ULong length = values.length ();
403 if (length !=
404 static_cast <CORBA::ULong> (
405 this->da_members_.size ()))
407 throw DynamicAny::DynAny::InvalidValue ();
410 // Check each member typecodes match.
411 CORBA::ULong i = 0u;
412 for (; i < length; ++i)
414 CORBA::TypeCode_var
415 my_member (
416 get_member_type (this->da_base_types_, i)),
417 value_member (
418 values[i].value->type ());
419 if (!my_member->equivalent (value_member.in ()))
421 throw DynamicAny::DynAny::TypeMismatch ();
425 // Copy in the new values to each member ()
426 for (i = 0u; i < length; ++i)
428 this->da_members_[i] = values[i].value->copy ();
431 this->set_to_value ();
434 void
435 TAO_DynValue_i::from_any (const CORBA::Any &any)
437 if (this->destroyed_)
439 throw ::CORBA::OBJECT_NOT_EXIST ();
442 CORBA::TypeCode_var
443 tc (any.type ());
444 if (!this->type_->equivalent (tc.in ()))
446 throw DynamicAny::DynAny::TypeMismatch ();
449 this->from_any_helper (any);
452 CORBA::Boolean
453 TAO_DynValue_i::equal (DynamicAny::DynAny_ptr rhs)
455 if (this->destroyed_)
457 throw ::CORBA::OBJECT_NOT_EXIST ();
460 CORBA::TypeCode_var tc (rhs->type ());
461 if (!tc->equivalent (this->type_.in ()) ||
462 this->component_count_ !=
463 rhs->component_count () )
465 return false;
468 TAO_DynValue_i *rhs_v=
469 dynamic_cast<TAO_DynValue_i *> (rhs);
471 if (!rhs_v || this->is_null () != rhs_v->is_null ())
473 return false;
476 if (!this->is_null ())
478 for (CORBA::ULong i = 0u;
479 i < this->component_count_;
480 ++i)
482 if (!rhs_v->da_members_[i]
483 ->equal (this->da_members_[i].in ()))
485 return false;
490 return true;
493 void
494 TAO_DynValue_i::destroy ()
496 if (this->destroyed_)
498 throw ::CORBA::OBJECT_NOT_EXIST ();
501 if (!this->ref_to_component_ ||
502 this->container_is_destroying_)
504 // Do a deep destroy.
505 this->component_count_ =
506 static_cast <CORBA::ULong> (
507 this->da_members_.size () );
509 for (CORBA::ULong i = 0u;
510 i < this->component_count_;
511 ++i)
513 this->set_flag (da_members_[i].in (), 1);
514 this->da_members_[i]->destroy ();
517 this->destroyed_ = 1;
521 DynamicAny::DynAny_ptr
522 TAO_DynValue_i::current_component ()
524 if (this->destroyed_)
526 throw ::CORBA::OBJECT_NOT_EXIST ();
529 if (-1 == this->current_position_)
531 return DynamicAny::DynAny::_nil ();
534 const CORBA::ULong index =
535 static_cast <CORBA::ULong> (this->current_position_);
536 this->set_flag (this->da_members_[index].in (), 0);
538 return DynamicAny::DynAny::_duplicate (
539 this->da_members_[index].in () );
542 // Overrides TAO_DynCommon::insert_val (). Since we ARE
543 // a ValueType, it does not make sense to pass the value
544 // type input down to the current_component to deal with
545 // (even though we are a constructed type and should do
546 // so with any other type of input). If we don't assume
547 // the value type is for us, it will get passed down
548 // (recursivly) to the terminal non-valuetype member
549 // which then will be wrong type for the valuetype input
550 // we started with.
551 void
552 TAO_DynValue_i::insert_val (CORBA::ValueBase *value)
554 if (this->destroyed_)
556 throw ::CORBA::OBJECT_NOT_EXIST ();
559 // If the arg is 0 we can't do this kind of type
560 // checking, and the call to _tao_marshal() below
561 // will handle the null value correctly in any case.
562 if (value)
564 const char
565 *value_id = value->_tao_obv_repository_id (),
566 *my_id = this->type_->id ();
568 // Valuetypes, unlike interfaces, don't have a
569 // virtual method to check for a more derived
570 // type when the repo ids don't match. Valuetypes
571 // have only a static _downcast() method, which
572 // can't be used here, so if the repo ids don't
573 // match, we're hosed.
574 if (ACE_OS::strcmp (value_id, my_id))
576 throw DynamicAny::DynAny::TypeMismatch ();
580 // This will handle null values correctly, or
581 // otherwise make a virtual call to marshal the state.
582 TAO_OutputCDR out;
583 if (!CORBA::ValueBase::_tao_marshal (out, value))
585 TAOLIB_DEBUG ((LM_DEBUG,
586 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::insert_val ")
587 ACE_TEXT ("can not marshal value\n") ));
588 throw DynamicAny::DynAny::InvalidValue ();
591 TAO_InputCDR in (out);
592 this->from_inputCDR (in);
595 // Overrides TAO_DynCommon::get_val (). Since we ARE
596 // a ValueType, it does not make sense to pass the get
597 // request down to the current_component to deal with
598 // (even though we are a constructed type and should
599 // do so with any other type of output). If we don't
600 // assume the value type is us, it will get passed down
601 // (recursivly) to the terminal non-valuetype member
602 // which then will be wrong type for the valuetype
603 // output we want.
604 CORBA::ValueBase *
605 TAO_DynValue_i::get_val ()
607 if (this->destroyed_)
609 throw ::CORBA::OBJECT_NOT_EXIST ();
612 // Convert this value into an output stream
613 TAO_OutputCDR out_cdr;
614 this->to_outputCDR (out_cdr);
616 // Now read in this stream to create the actual value.
617 TAO_InputCDR for_reading (out_cdr);
618 CORBA::ValueBase *retval = 0;
619 if (!CORBA::ValueBase::_tao_unmarshal (
620 for_reading, retval ))
622 throw DynamicAny::DynAny::InvalidValue ();
625 return retval;
628 CORBA::Any_ptr
629 TAO_DynValue_i::to_any ()
631 if (this->destroyed_)
633 throw ::CORBA::OBJECT_NOT_EXIST ();
636 // First create the value as an output stream
637 TAO_OutputCDR out_cdr;
638 this->to_outputCDR (out_cdr);
640 // Convert the out_cdr into a new any.
641 TAO_InputCDR in_cdr (out_cdr);
642 TAO::Unknown_IDL_Type *unk = 0;
643 ACE_NEW_THROW_EX (
644 unk,
645 TAO::Unknown_IDL_Type (this->type_.in (), in_cdr),
646 CORBA::NO_MEMORY () );
647 CORBA::Any_ptr retval = 0;
648 ACE_NEW_THROW_EX (
649 retval,
650 CORBA::Any,
651 CORBA::NO_MEMORY ());
652 retval->replace (unk);
653 return retval;
656 // This code is common to from_any() and the init(any).
657 // Basically the type information for our DynValue has
658 // already been set-up, we are now just copying the any
659 // value into our type.
660 void
661 TAO_DynValue_i::from_any_helper (const CORBA::Any & any)
663 // Get the CDR stream of the Any, if there isn't one,
664 // make one by marshalling the value into a new stream.
666 TAO_OutputCDR out;
667 TAO_InputCDR in (static_cast<ACE_Message_Block *> (0));
668 TAO::Any_Impl *impl = any.impl ();
669 if (impl->encoded ())
671 TAO::Unknown_IDL_Type *unk =
672 dynamic_cast<TAO::Unknown_IDL_Type *> (impl);
673 if (!unk)
675 throw CORBA::INTERNAL ();
678 in = unk->_tao_get_cdr ();
680 else
682 impl->marshal_value (out);
683 TAO_InputCDR tmp_in (out);
684 in = tmp_in;
687 this->from_inputCDR (in);
690 void
691 TAO_DynValue_i::to_outputCDR (TAO_OutputCDR &out_cdr)
693 // Is this an NULL Valuetype? If so we need to
694 // output the special NULL value type header.
695 // Note that we don't actually have a CORBA::ValueBase *
696 // which this call expects as we are actually dealing
697 // with DynValue * instead. However the pointer isn't
698 // actually dereferanced by the _tao_write_special_value()
699 // call, its address (as a void *) is just used to
700 // check for the null value and any previous writen
701 // value for the indirection header and the saving of
702 // this current location for this new valuetype if it
703 // is not indirected (this time).
704 if (!CORBA::ValueBase::_tao_write_special_value (
705 out_cdr,
706 reinterpret_cast <CORBA::ValueBase *>
707 (this->is_null_ ? 0 : this)))
709 // OK since a special_value hasn't been written we are
710 // NOT a NULL or indirect ValueType. We need to create
711 // a normal valuetype header, which states if chunking
712 // is being used and if CodeBaseURL and type information
713 // ((none, single or list of) repository id(s)) is being
714 // provided. TAO NEVER sends a codebase URL and ALWAYS
715 // lists the full list of repository ids that are
716 // VM_TRUNCATABLE.
718 CORBA::Long valuetag =
719 TAO_OBV_GIOP_Flags::Value_tag_base |
720 TAO_OBV_GIOP_Flags::Type_info_single;
722 const CORBA::ULong num_ids =
723 ACE_Utils::truncate_cast<CORBA::ULong> (this->da_base_types_.size ());
724 CORBA::ULong trunc_ids;
725 for (trunc_ids= 0u; trunc_ids < num_ids - 1u; ++trunc_ids)
727 if (CORBA::VM_TRUNCATABLE !=
728 this->da_base_types_[trunc_ids]->type_modifier ())
730 break; // Found the first type that is not truncatable
733 ++trunc_ids; // Include non-truncatable id that stopped us.
735 if (1u < trunc_ids)
737 valuetag |=
738 TAO_OBV_GIOP_Flags::Type_info_list;
741 CORBA::Boolean we_are_chunking = (1u < trunc_ids);
742 if (!we_are_chunking)
744 for (CORBA::ULong i= trunc_ids - 1u; i < num_ids; ++i)
746 if (CORBA::VM_CUSTOM ==
747 this->da_base_types_[i]->type_modifier ())
749 we_are_chunking = true;
750 break;
755 if (we_are_chunking)
757 valuetag |=
758 TAO_OBV_GIOP_Flags::Chunking_tag_sigbits;
761 // Start writing out the value header (and if
762 // necessary, the number of repo_ids we are
763 // going to write).
764 if (!out_cdr.write_long (valuetag) ||
765 (1u < trunc_ids && !out_cdr.write_ulong (trunc_ids)) )
767 TAOLIB_DEBUG ((LM_DEBUG,
768 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::to_outputCDR() ")
769 ACE_TEXT ("problem writing <value-tag> header\n")));
770 throw CORBA::INTERNAL ();
773 // Marshal out the list of repo_ids we are sending from
774 // the most derived type_id to the most base type_id in
775 // order. NOTE these type_ids are the real / full /
776 // non-dealliased versions not the dealliased ones that
777 // are stored in the da_base_types_[] list.
778 CORBA::ULong i= 0u;
779 for (CORBA::TypeCode_var
780 next (CORBA::TypeCode::_duplicate (this->type_.in ()));
781 i < trunc_ids;
782 ++i)
784 ACE_CString repo_id (next->id ());
785 if (!CORBA::ValueBase::
786 _tao_write_repository_id (out_cdr, repo_id) )
788 TAOLIB_DEBUG ((LM_DEBUG,
789 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::to_outputCDR() ")
790 ACE_TEXT ("problem writing header repo_ids\n")));
791 throw CORBA::INTERNAL ();
794 // Using the dealliased tc for this current type, find
795 // the next non-dealliased base typecode.
796 next = this->da_base_types_[i]->concrete_base_type ();
799 // Write out the start chunking markers for the number
800 // of base types we are writing. If we are not a truncatable
801 // type there are none to write (i.e. we are writing one
802 // less than the trunc_ids we actually have).
803 TAO_ChunkInfo ci (we_are_chunking);
804 for (i= 0u; i < trunc_ids - 1u; ++i)
806 if (!ci.start_chunk (out_cdr))
808 TAOLIB_DEBUG ((LM_DEBUG,
809 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::to_outputCDR() ")
810 ACE_TEXT ("problem writing basetype start chucks\n")));
811 throw CORBA::INTERNAL ();
815 // Now write out every member's value (add further chunking
816 // marks for each seporate base-type's state).
817 CORBA::Boolean need_first = true;
818 CORBA::ULong
819 currentBase= num_ids, // Note NOT just the trunc_ids
820 currentBaseMember = 0u;
821 for (CORBA::ULong currentMember= 0u;
822 currentMember < this->component_count_;
823 ++currentMember)
825 // Are we starting a new base-type
826 if (!currentBaseMember)
828 // Move on to the next derived type in the
829 // list of our type hyarchy
830 while (!this->da_base_types_[--currentBase]
831 ->member_count ())
833 // Skipping over all types that have no
834 // state (i.e. no members to write).
837 if (currentBase < trunc_ids || need_first)
839 need_first = false;
840 // Start chunk for this base-type's STATE
841 if (!ci.start_chunk (out_cdr))
843 TAOLIB_DEBUG ((LM_DEBUG,
844 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::to_outputCDR() ")
845 ACE_TEXT ("problem writing base-type ")
846 ACE_TEXT ("%u state start chuck\n"),
847 currentBase ));
848 throw CORBA::INTERNAL ();
853 // Recursive step - Add this member to the out_cdr
854 if (TAO_DynValue_i *member= // Assignment
855 dynamic_cast<TAO_DynValue_i *>
856 (this->da_members_[currentMember].in ()))
858 member->to_outputCDR (out_cdr);
860 else
862 CORBA::Any_var
863 any (this->da_members_[currentMember]->to_any ());
864 TAO::Any_Impl *impl = any->impl ();
865 if (impl->encoded ())
867 // Already encoded as a stream, convert this
868 // into an unknown and copy the stream over.
869 TAO::Unknown_IDL_Type
870 *unk= dynamic_cast<TAO::Unknown_IDL_Type *> (impl);
871 if (!unk)
873 TAOLIB_DEBUG ((LM_DEBUG,
874 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::to_outputCDR() ")
875 ACE_TEXT ("problem obtaining Unknown_IDL_Type\n")));
876 throw CORBA::INTERNAL ();
879 // Create a new input CDR for this member's
880 // marshaled representation.
881 TAO_InputCDR
882 in_cdr (unk->_tao_get_cdr ());
884 // Ok append this member's value to the output stream.
885 CORBA::TypeCode_var
886 tc (this->da_members_[currentMember]->type ());
888 (void) TAO_Marshal_Object::perform_append (
889 tc.in (),
890 &in_cdr,
891 &out_cdr);
893 else
895 // Just need to marshal this value into the stream.
896 impl->marshal_value (out_cdr);
900 // Are we ending the current base-type?
901 if (this->da_base_types_[currentBase]->member_count ()
902 <= ++currentBaseMember)
904 // Remind us to start again with the next derived type
905 // for the next member to be writen.
906 currentBaseMember= 0u;
908 // We must end the chunk we started for this
909 // base-type's STATE if we have written the whole state.
910 if (currentBase < trunc_ids && !ci.end_chunk (out_cdr))
912 TAOLIB_DEBUG ((LM_DEBUG,
913 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::to_outputCDR() ")
914 ACE_TEXT ("problem writing base-type ")
915 ACE_TEXT ("%u state end chuck\n"),
916 currentBase ));
917 throw CORBA::INTERNAL ();
922 // Write out the end chunking markers for the number
923 // of base types we have writen.
924 for (i= 1u; i < trunc_ids; ++i)
926 if (!ci.end_chunk (out_cdr))
928 TAOLIB_DEBUG ((LM_DEBUG,
929 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::to_outputCDR() ")
930 ACE_TEXT ("problem writing basetype end chucks\n")));
931 throw CORBA::INTERNAL ();
937 void
938 TAO_DynValue_i::from_inputCDR (TAO_InputCDR &strm)
940 // Save the start of this ValueType position in the input stream
941 // to allow caching for later indirections.
942 VERIFY_MAP (TAO_InputCDR, value_map, Value_Map);
943 if (strm.align_read_ptr (ACE_CDR::LONG_SIZE))
945 this->set_to_null ();
946 throw CORBA::INTERNAL ();
948 void *const start_of_valuetype = strm.rd_ptr();
950 // Read in the ValueType header
951 CORBA::ValueBase::Repository_Id_List ids;
952 CORBA::Boolean
953 is_null_object= false,
954 is_indirected= false,
955 is_chunked = false,
956 result = CORBA::ValueBase::_tao_unmarshal_header (
957 strm, this->type_.in ()->id (), ids,
958 is_null_object, is_indirected, is_chunked);
960 if (!result)
962 TAOLIB_DEBUG ((LM_ERROR,
963 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::from_inputCDR() ")
964 ACE_TEXT ("_tao_unmarshal_header() failed\n") ));
965 this->set_to_null ();
966 throw CORBA::INTERNAL ();
968 if (is_null_object)
970 this->set_to_null ();
971 return;
973 if (is_indirected)
975 // Effectivly this member? is the same ValueType as previous
976 // seen either in another member of this container OR the
977 // whole container itself. (Possiably can happen as a
978 // circular linked list?)
979 if (TAO_debug_level)
981 TAOLIB_DEBUG ((LM_ERROR,
982 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::from_inputCDR() ")
983 ACE_TEXT ("Any contains Indirected ValueType\n") ));
986 // Force the originally created container to empty, it is up
987 // to the caller to delete it and replace it with the duplicate
988 // we are now about to find.
989 this->set_to_null ();
991 // Read the offset from the stream (should be negative to point
992 // back to original)
993 CORBA::Long offset = 0;
994 if (!strm.read_long (offset) || 0 <= offset)
996 TAOLIB_DEBUG ((LM_ERROR,
997 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::from_inputCDR() ")
998 ACE_TEXT ("Can't read/understand ")
999 ACE_TEXT ("Indirected ValueType offset\n") ));
1000 throw CORBA::INTERNAL ();
1003 // Work out the input stream location of the original valuetype
1004 // and find the address of the original TAO_DynValue_i that we
1005 // created last time and stored in the map.
1006 void
1007 *pos = strm.rd_ptr () + offset - sizeof (CORBA::Long),
1008 *original = 0;
1009 if (strm.get_value_map()->get()->find (pos, original))
1011 TAOLIB_DEBUG ((LM_ERROR,
1012 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::from_inputCDR() ")
1013 ACE_TEXT ("Can't find Indirected ValueType ")
1014 ACE_TEXT ("offset in map\n") ));
1015 throw CORBA::INTERNAL ();
1018 // Since this is a void * convert it back to our real type and
1019 // throw it for the caller to catch and replace "this"
1020 // TAO_DynValue_i.
1021 TAO_DynValue_i *this_one_instead=
1022 reinterpret_cast<TAO_DynValue_i *> (original);
1023 this_one_instead->_add_ref ();
1024 throw this_one_instead;
1027 // Ok since we are not indirected (this time), record "this"
1028 // DynValue_i for later possiable indirections to use.
1029 if (strm.get_value_map ()->get()
1030 ->bind (
1031 start_of_valuetype,
1032 reinterpret_cast<void *> (this)))
1034 TAOLIB_DEBUG ((LM_DEBUG,
1035 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::from_inputCDR() ")
1036 ACE_TEXT ("Failed to record this into value_map\n") ));
1037 throw CORBA::INTERNAL ();
1040 // Work out how many total types there
1041 // are in this derived->base hiarchy.
1042 const CORBA::ULong
1043 num_fields = static_cast <CORBA::ULong> (this->da_members_.size ()),
1044 num_ids = static_cast <CORBA::ULong> (ids.size ());
1046 // Work out if the encoded valuetype inside the any is
1047 // required to be truncated into our DynValue.
1048 CORBA::Boolean requires_truncation = false;
1049 const char *const our_id = this->da_base_types_[0]->id ();
1050 CORBA::ULong i;
1051 for (i= 0u; i < num_ids; ++i)
1053 // Does the current id match our DynValue id?
1054 if (!strcmp (our_id, ids[i].c_str ()))
1056 break; // Found a match, we have our answer
1059 if (!this->allow_truncation_)
1061 throw DynamicAny::MustTruncate ();
1064 // Since this does not match we must be attempting
1065 // to truncated to a base-type, thus the incomming
1066 // any must be chuncked and this outer type must
1067 // allow truncation.
1068 if (!is_chunked)
1070 TAOLIB_DEBUG ((LM_ERROR,
1071 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::from_inputCDR()\n")
1072 ACE_TEXT (" type %C requires truncation to %C but is not chunked type.\n"),
1073 ids[i].c_str (),
1074 our_id ));
1075 this->set_to_null ();
1076 throw DynamicAny::DynAny::TypeMismatch ();
1079 requires_truncation = true;
1081 if (i == num_ids)
1083 TAOLIB_DEBUG ((LM_DEBUG,
1084 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::from_inputCDR() ")
1085 ACE_TEXT ("couldn't find matching repo_id!\n")));
1086 this->set_to_null ();
1087 throw DynamicAny::DynAny::TypeMismatch ();
1090 // Read in the start chunking markers for the number
1091 // of base types we are reading. If we are not a derived
1092 // type there are none to read (i.e. we are reading one
1093 // less than the num_ids we actually have received).
1095 TAO_ChunkInfo ci (is_chunked, 1);
1096 for (i= 0u; i < num_ids - 1u; ++i)
1098 if (!ci.handle_chunking (strm))
1100 TAOLIB_DEBUG ((LM_DEBUG,
1101 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::from_inputCDR() ")
1102 ACE_TEXT ("problem reading basetype start chucks\n")));
1103 this->set_to_null ();
1104 throw DynamicAny::DynAny::InvalidValue ();
1108 // Now read in every member's value (reading further chunking
1109 // marks for each seporate base-type's state we pass).
1110 CORBA::Boolean need_first = true;
1111 CORBA::ULong
1112 currentBase = ACE_Utils::truncate_cast<CORBA::ULong> (this->da_base_types_.size ()),
1113 currentBaseMember = 0u;
1114 for (CORBA::ULong currentMember= 0u;
1115 currentMember < num_fields;
1116 ++currentMember)
1118 // Are we starting a new base-type
1119 if (!currentBaseMember)
1121 // Move on to the next derived type in the
1122 // list of our type hyarchy
1123 while (!this->da_base_types_[--currentBase]
1124 ->member_count ())
1126 // Skipping over all types that have no
1127 // state (i.e. no members to write).
1130 if (currentBase < num_ids || need_first)
1132 // Read past the start chunk for this base-type's state
1133 if (!ci.handle_chunking (strm))
1135 TAOLIB_DEBUG ((LM_DEBUG,
1136 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::from_inputCDR() ")
1137 ACE_TEXT ("problem reading base-type ")
1138 ACE_TEXT ("%u state start chuck\n"),
1139 currentBase ));
1140 this->set_to_null ();
1141 throw DynamicAny::DynAny::InvalidValue ();
1146 // OK read in the current member
1147 CORBA::TypeCode_var
1148 field_tc (this->da_base_types_[currentBase]
1149 ->member_type (currentBaseMember));
1150 if (CORBA::tk_value == field_tc->kind ())
1152 // This is recursive, keep reading from our inputCDR
1153 // this allows for indirection
1154 this->da_members_[currentMember]=
1155 TAO::CreateDynAnyUtils<TAO_DynValue_i, TAO_InputCDR &>
1156 ::create_dyn_any_t (
1157 field_tc.in (),
1158 strm,
1159 this->allow_truncation_);
1161 else
1163 // Need to create an any for this field.
1164 TAO_InputCDR unk_in (strm);
1165 TAO::Unknown_IDL_Type *unk= 0;
1166 ACE_NEW_THROW_EX (
1167 unk,
1168 TAO::Unknown_IDL_Type (field_tc.in (), unk_in),
1169 CORBA::NO_MEMORY ());
1171 CORBA::Any field_any;
1172 field_any.replace (unk);
1174 // This recursive step will call the correct
1175 // constructor based on the type of field_any.
1176 this->da_members_[currentMember] = TAO::MakeDynAnyUtils::
1177 make_dyn_any_t<const CORBA::Any&> (
1178 field_any._tao_get_typecode (),
1179 field_any,
1180 this->allow_truncation_);
1182 // Since the above Unknown used its own inputCDR we need
1183 // to move onto the next field in the real CDR stream as
1184 // IF we had just read the actual value from it.
1185 (void) TAO_Marshal_Object::perform_skip (
1186 field_tc.in (),
1187 &strm);
1190 // Are we ending the current base-type?
1191 if (this->da_base_types_[currentBase]->member_count ()
1192 <= ++currentBaseMember)
1194 // Remind us to start again with the next derived type
1195 // for the next member to be writen.
1196 currentBaseMember= 0u;
1198 if (currentBase < num_ids)
1200 // We must end the chunk that was started for this
1201 // base-type's state.
1202 if (!( (currentBase || !requires_truncation) ?
1203 ci.handle_chunking (strm) :
1204 ci.skip_chunks (strm)))
1206 TAOLIB_DEBUG ((LM_DEBUG,
1207 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_DynValue_i::from_inputCDR() ")
1208 ACE_TEXT ("problem reading base-type ")
1209 ACE_TEXT ("%u state end chuck\n"),
1210 currentBase ));
1211 this->set_to_null ();
1212 throw DynamicAny::DynAny::InvalidValue ();
1218 this->set_to_value ();
1221 TAO_END_VERSIONED_NAMESPACE_DECL