2 #include "tao/AnyTypeCode/Null_RefCount_Policy.h"
3 #include "tao/AnyTypeCode/Alias_TypeCode_Static.h"
4 #include "tao/AnyTypeCode/Value_TypeCode_Static.h"
5 #include "tao/AnyTypeCode/TypeCode_Constants.h"
7 #include "tao/Valuetype/ValueBase.h"
8 #include "tao/Valuetype/ValueFactory.h"
12 #include "tao/ORB_Core.h"
13 #include "tao/debug.h"
14 #include "tao/SystemException.h"
16 #include "ace/OS_NS_string.h"
18 #if !defined (__ACE_INLINE__)
19 # include "tao/Valuetype/ValueBase.inl"
20 #endif /* ! __ACE_INLINE__ */
22 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
24 // Static operations in namespace CORBA.
27 CORBA::add_ref (CORBA::ValueBase
*val
)
36 CORBA::remove_ref (CORBA::ValueBase
*val
)
44 // ***********************************************************************
46 TAO_ChunkInfo::TAO_ChunkInfo (CORBA::Boolean do_chunking
,
47 CORBA::Long init_level
)
48 : chunking_(do_chunking
),
49 value_nesting_level_(init_level
),
51 length_to_chunk_octets_pos_ (0),
52 chunk_octets_end_pos_ (0)
57 CORBA::ValueBase::_copy_value ()
59 // Note that TAO traditionally has not enforced this functions PURE
60 // virtual nature, thus the end user didn't have to provide an
61 // implimentaion of _copy_value in their top level valuetype class
62 // that deriveds from the tao_idl generated OBV_* class. If they do
63 // not use _copy_value() then there was no requirement to impliment it.
64 // However as an option TAO can now be built to use _copy_value when
65 // inserting a copy of the valuetype into an any, instead of increasing
66 // it's referance count. It is now possiable that older code may end up
67 // here in error due to the lack of a user's override.
68 ACE_VERSIONED_NAMESPACE_NAME::__ace_assert (
71 ACE_TEXT_CHAR_TO_TCHAR ("Valuetype's _copy_value() should be implimented in user's most derived class"));
75 CORBA::ValueBase::ValueBase ()
81 CORBA::ValueBase::ValueBase (const ValueBase
& val
)
82 : is_truncatable_ (val
.is_truncatable_
),
83 chunking_ (val
.chunking_
)
88 CORBA::ValueBase::_downcast (CORBA::ValueBase
*vt
)
90 // Every vt is a CORBA::ValueBase :-).
95 CORBA::ValueBase::_tao_any_destructor (void *x
)
97 CORBA::ValueBase
*tmp
= static_cast<CORBA::ValueBase
*> (x
);
98 CORBA::remove_ref (tmp
);
101 // OBV marshaling in principle:
102 // _tao_marshal () is called from the CDR operator<< ()
103 // to marshal a valuetype. To marshal the state
104 // it calls (virtual) _tao_marshal_v () (IDL generated) on itself
105 // which 'jumps' to the most derived valuetype class. This function
106 // further calls (inline) _tao_marshal_state, which is generated from
107 // IDL too and does the marshaling of state members and base classes
108 // (before, if any) actually.
109 // Fragmentation (chunking) needs some cooperation with the CDR stream.
110 // It needs to keep track of the state we're in:
111 // (outside chunk, beginning of chunk - no data, inside chunk and
112 // the nesting level of valuetypes. (The chunks itself are not nested.))
114 // (see CORBA 2.3 GIOP 15.3.4)
116 // %! yet much to do ... look for +++ !
118 // 1. Is 'this' yet marshalled ? (->1a)
119 // If not then mark 'this' as marshalled. (->2) +++
120 // Or is it null ? (write null_ref and return ok)
121 // 1a. Put indirection and return successfull.
123 // 2. if (chunking) and we are in a chunk (look in strm),
124 // end the chunk by writing its length at its start.
125 // This is the responsibility of the CDR stream.
126 // But if nothing is writtern in this chunk yet,
127 // we want to overwrite the place of the dummy blocksize-tag
128 // with our <value-tag>.
129 // Increase the nesting level of valuetypes.
131 // 3. Build <value-tag>, which states if chunking is used
132 // and if type information ((list of) repository id(s))
133 // is provided. The latter is necessary if the formal_type_id
134 // is unequal the 'true derived' type of this object.
136 // 4. Marshal type information.
138 // 5. if (chunking) let room for a blocksize-tag. (i.e. write Long)
140 // 6. Now marshal state members. (%! Problem when state is empty
141 // and chunked encoding is used.)
143 // 7. if (chunking) let strm overwrite the last blocksize tag
144 // with its concrete value.
146 // 8. if (chunking) write an end tag, or (optimization) let the CDR
147 // care for collecting all end tags of nested values (e.g. linked
148 // list), so that only one end tag at all must be written.
151 CORBA::ValueBase::_tao_marshal (TAO_OutputCDR
&strm
,
152 const CORBA::ValueBase
*this_
,
153 ptrdiff_t formal_type_id
)
155 if ( ! _tao_write_special_value (strm
, this_
))
157 return _tao_write_value (strm
, this_
, formal_type_id
);
164 CORBA::ValueBase::_tao_unmarshal (TAO_InputCDR
&strm
,
165 CORBA::ValueBase
*&new_object
)
167 // This is for the special case only that one unmarshals in order
168 // to assign the newly created object directly to a ValueBase pointer.
169 // Implementation is like a specialized one (in TC.cpp, if T.idl is source).
171 // ValueBase::_tao_unmarshal_pre ()
172 // (Gets factory or possible a null or an existing object.
173 // Then the job is done. On an existing (backreferenced) object
174 // do a cast and a type check)
175 // new_object = factory->create_for_unmarshal ()
176 // (with apropriate cast)
177 // new_object->_tao_unmarshal_v ()
178 // new_object->_tao_unmarshal_post ()
181 is_null_object
= false,
182 is_indirected
= false;
184 if (!CORBA::ValueBase::_tao_unmarshal_pre (
187 0, // repo_id to be obtained from strm
194 if (is_null_object
|| is_indirected
)
199 // If we have now obtained the ValueType
200 // continue by unmarshalling the values into it.
201 return (new_object
) ?
202 new_object
->_tao_unmarshal_v (strm
) : false;
206 CORBA::ValueBase::_tao_unmarshal_pre (
208 CORBA::ValueBase
*&valuetype
,
209 const char *const fallback_repo_id
,
210 CORBA::Boolean
&is_null_object
,
211 CORBA::Boolean
&is_indirected
)
213 // %! yet much to do ... look for +++ !
215 // 1. Get the <value-tag> (else it may be <indirection-tag> or <null-ref>).
216 // Is object yet unmarshalled (<indirection-tag> is set) ? (->1a)
217 // Is <null-ref> given ? Set 0 and return ok.
218 // 1a. Lookup the real address in memory, which should be aligned +++
219 // to CORBA::ValueBase. Its possible at this point that worse
220 // type mismatch gets by undetected, if the CDR stream fakes.
221 // So the type should be checked ... +++
223 // 2. Now at this point it must be a <value-tag> (error else).
224 // if (chunking) check that any last chunk ends with matching
225 // size. If not raise marshal exception.
226 // Increase the nesting level of valuetypes.
228 // 3. if (chunking) read and record the blocksize-tag.
230 // 4. Unmarshal type information and lookup factory.
231 // If no type information is given in the CDR encoding, as told
232 // from the <value-tag>, then use the repository id parameter
233 // (it _must_ be right).
235 CORBA::Boolean is_chunked
= false;
237 // Save the position of the start of the ValueType
238 // to allow caching for later indirection.
239 if (strm
.align_read_ptr (ACE_CDR::LONG_SIZE
))
243 void *const start_of_valuetype
= strm
.rd_ptr();
245 Repository_Id_List ids
;
246 CORBA::Boolean result
=
247 CORBA::ValueBase::_tao_unmarshal_header (
248 strm
, fallback_repo_id
, ids
,
249 is_null_object
, is_indirected
, is_chunked
);
251 if (!result
|| is_null_object
)
258 return _tao_unmarshal_value_indirection (strm
, valuetype
);
261 CORBA::ValueBase::_tao_unmarshal_find_factory (
262 strm
, start_of_valuetype
, valuetype
, ids
, is_chunked
);
268 CORBA::ValueBase::_tao_unmarshal_header (
270 const char *const fallback_repo_id
,
271 Repository_Id_List
&ids
,
272 CORBA::Boolean
&is_null_object
,
273 CORBA::Boolean
&is_indirected
,
274 CORBA::Boolean
&is_chunked
)
276 is_indirected
= false;
277 is_null_object
= false;
280 CORBA::Long valuetag
;
281 if (!strm
.read_long (valuetag
))
286 is_chunked
= TAO_OBV_GIOP_Flags::is_chunked (valuetag
);
288 if (TAO_OBV_GIOP_Flags::is_null_ref (valuetag
))
290 // null reference is unmarshalled.
291 is_null_object
= true;
295 if (TAO_OBV_GIOP_Flags::is_indirection_tag (valuetag
))
297 // value is redirected
298 is_indirected
= true;
302 if (TAO_OBV_GIOP_Flags::has_codebase_url (valuetag
))
304 // We don't do anything with this url, but it needs
305 // to be read and ignored.
306 ACE_CString codebase_url
;
307 if (!_tao_read_codebase_url (strm
, codebase_url
))
313 // Obtain the repo_id(s) of the type we are reading
315 if (TAO_OBV_GIOP_Flags::has_single_type_info (valuetag
))
318 if (!_tao_read_repository_id(strm
, id
))
324 else if (TAO_OBV_GIOP_Flags::has_list_type_info (valuetag
))
326 if (!_tao_read_repository_id_list(strm
, ids
))
331 else if (TAO_OBV_GIOP_Flags::has_no_type_info (valuetag
))
333 if (fallback_repo_id
)
335 ids
.push_back (fallback_repo_id
);
341 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_unmarshal_pre, ")
342 ACE_TEXT ("unknown repo_id\n") ));
352 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_unmarshal_pre, ")
353 ACE_TEXT ("unknown value tag: %x\n"),
364 CORBA::ValueBase::_tao_unmarshal_find_factory (
366 void *const start_of_valuetype
,
367 CORBA::ValueBase
*&valuetype
,
368 Repository_Id_List
&ids
,
369 CORBA::Boolean
&is_chunked
)
373 TAO_ORB_Core
*orb_core
= strm
.orb_core ();
376 orb_core
= TAO_ORB_Core_instance ();
381 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_unmarshal_find_factory, ")
382 ACE_TEXT ("WARNING: extracting valuetype using default ORB_Core\n") ));
386 // Find the registered factory for this unmarshalling valuetype. If any
387 // factory for the valuetype in its truncatable derivation hierarchy
388 // is registered, the factory is used to create value for unmarshalling.
389 // Value factories are reference counted. When we get a new value factory
390 // from the ORB, its reference count is increased.
392 CORBA::ValueFactory_var factory
;
393 CORBA::Boolean requires_truncation
= false;
394 const size_t num_ids
= ids
.size ();
395 const char *id
= (num_ids
) ? ids
[0].c_str () : "{Null}";
396 for (size_t i
= 0u; i
< num_ids
; ++i
)
398 factory
= orb_core
->orb ()->lookup_value_factory (ids
[i
].c_str ());
399 if (factory
.in() != 0)
401 id
= ids
[i
].c_str ();
402 requires_truncation
= (i
!= 0u);
407 // Obtain the actual ValueType from the factory
408 if (factory
.in() == 0 || !(valuetype
= factory
->create_for_unmarshal ()))
412 TAOLIB_ERROR ((LM_ERROR
,
413 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_unmarshal_find_factory, ")
414 ACE_TEXT ("OBV factory is null, id=%C\n"),
418 throw ::CORBA::MARSHAL (CORBA::OMGVMCID
| 1, CORBA::COMPLETED_MAYBE
);
421 if (requires_truncation
)
423 valuetype
->truncation_hook ();
425 valuetype
->chunking_
= is_chunked
;
427 // Cache the start of this ValueType for later possiable indirection
428 VERIFY_MAP (TAO_InputCDR
, value_map
, Value_Map
);
429 if (strm
.get_value_map ()->get()->bind (start_of_valuetype
, valuetype
) != 0)
431 TAOLIB_DEBUG ((LM_DEBUG
,
432 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_unmarshal_find_factory, ")
433 ACE_TEXT ("Failed to bound value %x=%x, id=%C\n"),
434 start_of_valuetype
, valuetype
, id
));
436 else if (TAO_debug_level
)
438 TAOLIB_DEBUG ((LM_DEBUG
,
439 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_unmarshal_find_factory, ")
440 ACE_TEXT ("bound value %x=%x, id=%C\n"),
441 start_of_valuetype
, valuetype
, id
));
446 CORBA::ValueBase::_tao_unmarshal_post (TAO_InputCDR
&)
448 // (... called from T::_tao_unmarshal)
449 // 7. if (chunking) check the last blocksize tag for correct value. +++
450 // And if we're gonna to truncate, skip all the state of the more
451 // derived classes. (But it might need to be accessed again,
452 // if there are embedded objects which are referenced later
453 // in this CDR encoding stream.)
455 // 8. if (chunking) there must be some end tag. Let the CDR stream deal
456 // with this (and decrease the nesting level of valuetypes).
457 // Also the CDR stream must check for eventually outstanding end tags
458 // at the end of the stream which have to cause a marshal
465 CORBA::ValueBase::_tao_validate_box_type (TAO_InputCDR
&strm
,
466 TAO_InputCDR
&indirected_strm
,
467 const char * const repo_id_expected
,
468 CORBA::Boolean
& null_object
,
469 CORBA::Boolean
& is_indirected
)
471 CORBA::Long value_tag
;
473 is_indirected
= false;
475 if (!strm
.read_long (value_tag
))
480 if (TAO_OBV_GIOP_Flags::is_null_ref (value_tag
))
481 { // ok, null reference unmarshaled
486 if (TAO_OBV_GIOP_Flags::is_indirection_tag (value_tag
))
488 is_indirected
= true;
490 // box value is redirected.
491 return _tao_unmarshal_value_indirection_pre (strm
, indirected_strm
);
494 if (!TAO_OBV_GIOP_Flags::is_value_tag (value_tag
))
496 TAOLIB_DEBUG ((LM_DEBUG
,
497 ACE_TEXT ("TAO (%P|%t) - %N:%l CORBA::ValueBase::_tao_validate_box_type, ")
498 ACE_TEXT ("not value_tag\n")));
503 if (TAO_OBV_GIOP_Flags::has_codebase_url (value_tag
))
504 { // Demarshal the codebase url (but we won't be using it).
506 ACE_CString codebase_url
;
507 if (! _tao_read_codebase_url (strm
, codebase_url
))
513 if (TAO_OBV_GIOP_Flags::has_no_type_info (value_tag
))
515 // No type information so assume it is the correct type.
519 if (TAO_OBV_GIOP_Flags::has_single_type_info (value_tag
))
521 // Demarshal the repository id and check if it is the expected one.
523 if (! _tao_read_repository_id (strm
, id
))
528 if (!ACE_OS::strcmp (id
.c_str(), repo_id_expected
))
529 { // Repository ids matched as expected
534 if (TAO_OBV_GIOP_Flags::has_list_type_info (value_tag
))
536 // Don't know how to handle a repository id list. It does not
537 // make sense for a value box anyway.
545 CORBA::ValueBase::_tao_unmarshal_value_indirection_pre (TAO_InputCDR
&strm
,
546 TAO_InputCDR
&indirected_strm
)
548 CORBA::Long offset
= 0;
549 if (!strm
.read_long (offset
) || offset
>= 0)
554 size_t const buffer_size
= -(offset
) + sizeof (CORBA::Long
);
555 // Cribbed from tc_demarshal_indirection in Typecode_CDR_Extraction.cpp
556 indirected_strm
= TAO_InputCDR (strm
.rd_ptr () + offset
- sizeof (CORBA::Long
),
560 indirected_strm
.set_repo_id_map (strm
.get_repo_id_map ());
561 indirected_strm
.set_codebase_url_map (strm
.get_codebase_url_map ());
562 indirected_strm
.set_value_map (strm
.get_value_map ());
563 return indirected_strm
.good_bit ();
567 CORBA::ValueBase::_tao_unmarshal_value_indirection (TAO_InputCDR
&strm
,
568 CORBA::ValueBase
*&value
)
570 if (strm
.get_value_map().is_nil ())
571 throw CORBA::INTERNAL ();
573 CORBA::Long offset
= 0;
574 if (!strm
.read_long (offset
) || offset
>= 0)
579 void* pos
= strm
.rd_ptr () + offset
- sizeof (CORBA::Long
);
581 if (9 < TAO_debug_level
)
583 TAOLIB_DEBUG ((LM_DEBUG
,
584 ACE_TEXT ("TAO (%P|%t) ValueBase::_tao_unmarshal_value_indirection, pos %x\n"), pos
));
585 TAO_InputCDR::Value_Map
* map
= strm
.get_value_map()->get ();
586 for (TAO_InputCDR::Value_Map::ITERATOR it
= map
->begin (); it
!= map
->end (); ++ it
)
588 TAOLIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("TAO (%P|%t) ValueBase::_tao_unmarshal_value_indirection, %x=%x\n"), it
->ext_id_
, it
->int_id_
));
592 if (strm
.get_value_map()->get()->find (pos
, v
) != 0)
594 TAOLIB_DEBUG ((LM_DEBUG
,
595 ACE_TEXT ("TAO (%P|%t) - %N:%l ")
596 ACE_TEXT ("ValueBase::_tao_unmarshal_value_indirection, ")
597 ACE_TEXT ("did not find %x in map %x\n"),
598 pos
, (void *) strm
.get_value_map()->get()));
599 throw CORBA::INTERNAL ();
601 else if (TAO_debug_level
)
603 TAOLIB_DEBUG ((LM_DEBUG
,
604 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_unmarshal_value_indirection, found %x=%x\n"),
608 value
= reinterpret_cast<CORBA::ValueBase
*>(v
);
613 CORBA::ValueBase::_tao_unmarshal_repo_id_indirection (TAO_InputCDR
&strm
,
616 CORBA::Long offset
= 0;
617 if (!strm
.read_long (offset
) || offset
>= 0)
622 void* pos
= strm
.rd_ptr () + offset
- sizeof (CORBA::Long
);
623 if (strm
.get_repo_id_map()->get()->find (pos
, id
) != 0)
625 throw CORBA::INTERNAL ();
627 else if (TAO_debug_level
)
629 TAOLIB_DEBUG ((LM_DEBUG
,
630 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_unmarshal_repo_id_indirection, found %x=%C\n"),
638 CORBA::ValueBase::_tao_unmarshal_codebase_url_indirection (TAO_InputCDR
&strm
,
639 ACE_CString
& codebase_url
)
641 CORBA::Long offset
= 0;
642 if (!strm
.read_long (offset
) || offset
>= 0)
647 void* pos
= strm
.rd_ptr () + offset
- sizeof (CORBA::Long
);
649 if (strm
.get_codebase_url_map()->get()->find (pos
, codebase_url
) != 0)
651 throw CORBA::INTERNAL ();
653 else if (TAO_debug_level
)
655 TAOLIB_DEBUG ((LM_DEBUG
,
656 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_unmarshal_codebase_url_indirection, found %x=%C\n"),
657 pos
, codebase_url
.c_str ()));
663 #if defined (GEN_OSTREAM_OPS)
665 CORBA::ValueBase::_tao_stream (std::ostream
&strm
,
666 const CORBA::ValueBase
*value
)
668 return value
->_tao_stream_v (strm
);
672 CORBA::ValueBase::_tao_stream_v (std::ostream
&strm
) const
674 return strm
<< "CORBA::ValueBase";
676 #endif /* GEN_OSTREAM_OPS */
678 // =================== methods for chunking ====================
681 CORBA::ValueBase::_tao_write_special_value (TAO_OutputCDR
&strm
,
682 const CORBA::ValueBase
*value
)
684 // If the 'value' is null then write the null value to the stream.
687 return strm
.write_long (TAO_OBV_GIOP_Flags::Null_tag
);
691 #ifdef TAO_HAS_VALUETYPE_OUT_INDIRECTION
694 VERIFY_MAP (TAO_OutputCDR
, value_map
, Value_Map
);
696 if (strm
.get_value_map ()->get()->find (
697 reinterpret_cast<void*>(const_cast <CORBA::ValueBase
*> (value
)), pos
) == 0)
701 TAOLIB_DEBUG ((LM_DEBUG
,
702 ACE_TEXT ("(%P|%t)ValueBase::_tao_write_special_value, found value %x=%x\n"),
706 if (!strm
.write_long (TAO_OBV_GIOP_Flags::Indirection_tag
))
711 CORBA::Long
const offset
= -strm
.offset (pos
);
714 TAOLIB_DEBUG ((LM_DEBUG
,
715 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_write_special_value, indirection %d=%x\n"),
716 offset
, (void *)(strm
.current()->wr_ptr () + offset
) ));
719 return strm
.write_long (offset
);
722 if (strm
.align_write_ptr (ACE_CDR::LONG_SIZE
) != 0)
724 throw CORBA::INTERNAL ();
726 if (strm
.get_value_map ()->get()->bind (
727 reinterpret_cast<void*>(const_cast <CORBA::ValueBase
*> (value
)),
728 strm
.current()->wr_ptr() ) != 0)
730 throw CORBA::INTERNAL ();
732 else if (TAO_debug_level
)
734 TAOLIB_DEBUG ((LM_DEBUG
,
735 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_marshal, bound value %x=%x\n"),
736 value
, strm
.current()->wr_ptr()));
748 CORBA::ValueBase::_tao_write_value (TAO_OutputCDR
&strm
,
749 const CORBA::ValueBase
* value
,
750 ptrdiff_t formal_type_id
)
752 if (! value
->_tao_write_value_header (strm
, formal_type_id
))
757 if (! value
->_tao_marshal_v (strm
))
766 CORBA::ValueBase::_tao_write_value_header (TAO_OutputCDR
&strm
,
767 ptrdiff_t formal_type_id
) const
769 #ifdef TAO_HAS_OPTIMIZED_VALUETYPE_MARSHALING
770 // this case allows TAO to avoid marshaling the typeID for values
771 // where the actual type matches the formal type (ie not a derived
774 // I would much prefer that there be a way to have a -ORB option to
775 // control this behavior, but for now there is no reference to the
776 // ORB Core available during marshaling (there is during unmarshaling)
777 // and no other way to communicate such configuration values.
779 CORBA::Boolean
const is_formal_type
=
780 this->_tao_match_formal_type (formal_type_id
);
782 // Unfortunately, all versions of tao prior to TAO 1.5.2 did not
783 // support unmarshaling of valuetypes that did not explicitly
784 // marshal the type id. At least it is benign to always encode the
785 // typecode value, even if it can be a little verbose.
786 CORBA::Boolean
const is_formal_type
= 0;
787 ACE_UNUSED_ARG (formal_type_id
);
788 #endif /* TAO_HAS_OPTIMIZED_VALUETYPE_MARSHALING */
790 // Get the list of repository ids for this valuetype.
791 Repository_Id_List repository_ids
;
792 this->_tao_obv_truncatable_repo_ids (repository_ids
);
793 CORBA::Long
const num_ids
=
794 static_cast <CORBA::Long
> (repository_ids
.size ());
796 // Build <value-tag>, which states if chunking is used
797 // and if type information ((list of) repository id(s))
798 // is provided. The latter is necessary if the formal_type_id
799 // is unequal the 'true derived' type of this object.
800 CORBA::Long valuetag
= TAO_OBV_GIOP_Flags::Value_tag_base
;
802 // Truncatable value type, must use chunking and list all repository
803 // ids in its "truncatable" derivation hierarchy.
804 if (this->is_truncatable_
|| this->chunking_
)
805 valuetag
|= TAO_OBV_GIOP_Flags::Chunking_tag_sigbits
;
807 if (!is_formal_type
|| this->is_truncatable_
)
808 valuetag
|= TAO_OBV_GIOP_Flags::Type_info_single
;
812 valuetag
|= TAO_OBV_GIOP_Flags::Type_info_list
;
815 if (! strm
.write_long (valuetag
) // Write <value-tag>.
816 || (num_ids
> 1 && !strm
.write_long (num_ids
))) // Write <num-ids>.
821 #ifndef TAO_HAS_OPTIMIMIZED_VALUETYPE_MARSHALING
822 if (this->is_truncatable_
823 || !is_formal_type
/* Always evaluates to 1 in the
824 !TAO_HAS_OPTIMIMIZED_VALUETYPE_MARSHALING
828 #endif /* !TAO_HAS_OPTIMIMIZED_VALUETYPE_MARSHALING */
829 // Marshal type information.
830 for (CORBA::Long i
= 0; i
< num_ids
; ++i
)
832 if (! _tao_write_repository_id (strm
, repository_ids
[i
]))
837 #ifndef TAO_HAS_OPTIMIMIZED_VALUETYPE_MARSHALING
839 #endif /* !TAO_HAS_OPTIMIMIZED_VALUETYPE_MARSHALING */
845 CORBA::ValueBase::_tao_write_repository_id (TAO_OutputCDR
&strm
,
848 #ifdef TAO_HAS_VALUETYPE_OUT_INDIRECTION
850 VERIFY_MAP (TAO_OutputCDR
, repo_id_map
, Repo_Id_Map
);
852 if (strm
.get_repo_id_map ()->get()->find (id
, pos
) == 0)
854 if (!strm
.write_long (TAO_OBV_GIOP_Flags::Indirection_tag
))
858 CORBA::Long offset
= -strm
.offset (pos
);
861 TAOLIB_DEBUG ((LM_DEBUG
,
862 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_write_repository_id, id %C indirection %d\n"),
863 id
.c_str(), offset
));
865 if (!strm
.write_long (offset
))
872 if (strm
.align_write_ptr (ACE_CDR::LONG_SIZE
) != 0)
874 throw CORBA::INTERNAL ();
876 if (strm
.get_repo_id_map ()->get ()->bind (id
, strm
.current()->wr_ptr ()) != 0)
878 throw CORBA::INTERNAL ();
882 TAOLIB_DEBUG ((LM_DEBUG
,
883 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_write_repository_id, bound %C - %x\n"),
884 id
.c_str (), strm
.current()->wr_ptr ()));
886 if (! strm
.write_string (id
.c_str ()))
892 if (! strm
.write_string (id
.c_str ()))
901 // this method is called by the IDL generated _tao_marshal_state() method.
903 TAO_ChunkInfo::start_chunk(TAO_OutputCDR
&strm
)
905 // If chunking, reserve the space for the chunk size of next chunk
906 // and increase the nesting level.
909 if (! reserve_chunk_size(strm
))
914 ++this->value_nesting_level_
;
920 // this method is called by the IDL generated _tao_marshal_state() method.
922 TAO_ChunkInfo::end_chunk(TAO_OutputCDR
&strm
)
926 // Write actual chunk size at the reserved chunk size place.
927 if (! this->write_previous_chunk_size(strm
))
932 // Write an end tag which is negation of value_nesting_level_.
933 if (! strm
.write_long(- this->value_nesting_level_
))
938 // -- this->value_nesting_level_;
939 if ( -- this->value_nesting_level_
== 0 )
941 // ending chunk for outermost value
949 TAO_ChunkInfo::write_previous_chunk_size(TAO_OutputCDR
&strm
)
951 if (this->chunk_size_pos_
!= 0)
953 // Calculate the chunk size.
954 CORBA::Long
const chunk_size
=
955 static_cast<CORBA::Long
> (strm
.total_length () - this->length_to_chunk_octets_pos_
);
957 // This should not happen since this is called in end_chunk() and
958 // the idl generated code always have the matched start_chunk() and
959 // end_chunk() pair. There is always data written to the stream between
960 // the start_chunk() and end_chunk() calls.
966 // Write the actual chunk size to the reserved chunk size position
968 if (!strm
.replace (chunk_size
, this->chunk_size_pos_
))
973 // We finish writing the actual chunk size, now we need reset the state.
974 this->chunk_size_pos_
= 0;
975 this->length_to_chunk_octets_pos_
= 0;
982 TAO_ChunkInfo::reserve_chunk_size(TAO_OutputCDR
&strm
)
984 // This is called in the start_chunk().
985 // Reserve the chunk size the first time the start_chunk () is called
986 // if there are several start_chunk () called continuously without
987 // calling end_chunk (). This could happen in the _tao_marshal_state()
988 // in the most derived valuetype.
990 if (this->chunk_size_pos_
== 0)
992 // Align the wr_ptr before we reserve the space for chunk size.
993 strm
.align_write_ptr (ACE_CDR::LONG_SIZE
);
994 // Remember begin of the chunk (at chunk size position) that is needed
995 // when we write back actual chunk size to the stream.
996 this->chunk_size_pos_
= strm
.current ()->wr_ptr ();
998 // Insert four bytes here as a place-holder, we need to go back
999 // later and write the actual size.
1000 if (! strm
.write_long (0))
1005 // Remember length before writing chunk data. This is used to calculate
1006 // the actual size of the chunk.
1007 this->length_to_chunk_octets_pos_
= strm
.total_length ();
1014 TAO_ChunkInfo::handle_chunking (TAO_InputCDR
&strm
)
1016 if (!this->chunking_
)
1021 char* the_rd_ptr
= strm
.start()->rd_ptr ();
1023 //This case could happen if a handle_chunking() reads a chunk size
1024 //and then calls the handle_chunking() again without reading the chunk data.
1025 //The handle_chunking() called continuously without reading the chunk data
1026 //only happens at the beginning of _tao_unmarshal_state() in a valuetype
1028 if (the_rd_ptr
< this->chunk_octets_end_pos_
)
1030 ++this->value_nesting_level_
;
1034 //Safty check if reading is out of range of current chunk.
1035 if (this->chunk_octets_end_pos_
!= 0
1036 && the_rd_ptr
> this->chunk_octets_end_pos_
)
1041 // Read a long value that might be an endtag, the chunk size or the value tag
1042 // of the nested valuetype.
1045 if (!strm
.read_long (tag
))
1052 // tag is an end tag
1053 if (-tag
> this->value_nesting_level_
)
1055 TAOLIB_ERROR_RETURN ((LM_ERROR
,
1056 ACE_TEXT ("TAO (%P|%t) - %N:%l TAO_ChunkInfo::handle_chunking, received end tag ")
1057 ACE_TEXT ("%d > value_nesting_level %d\n"),
1059 this->value_nesting_level_
),
1063 this->value_nesting_level_
= - tag
;
1064 --this->value_nesting_level_
;
1066 this->chunk_octets_end_pos_
= 0;
1068 // Continue reading so that we can read the outmost endtag. This
1069 // would simplify the implementation in the derived valuetype.
1070 if (this->value_nesting_level_
> 0)
1072 this->handle_chunking(strm
);
1075 else if (tag
< TAO_OBV_GIOP_Flags::Value_tag_base
)
1077 // Read the chunk size of another chunk.
1078 this->chunk_octets_end_pos_
= strm
.rd_ptr () + tag
;
1079 ++this->value_nesting_level_
;
1081 else // (tag >= 0x7fffff00)
1083 // This should not happen since the valuetag of the nested
1084 // values are always unmarshalled in the
1085 // ValueBase::_tao_unmarshal_pre().
1093 TAO_ChunkInfo::skip_chunks (TAO_InputCDR
&strm
)
1095 if (!this->chunking_
)
1100 // This function is called after reading data of the truncated parent and
1101 // skips the remaining chunks until the outmost endtag (-1).
1102 // The tag read here is suppoused to be an endtag.
1104 if (!strm
.read_long(tag
))
1109 // end of the whole valuetype.
1116 // continue skip the chunk.
1117 return this->skip_chunks (strm
);
1119 else if (tag
< TAO_OBV_GIOP_Flags::Value_tag_base
)
1121 // Read the chunk size and move forward to skip the data.
1122 ACE_Message_Block
* current
=
1123 const_cast<ACE_Message_Block
*>(strm
.start ());
1124 current
->rd_ptr (tag
);
1125 return this->skip_chunks (strm
);
1132 CORBA::ValueBase::_tao_read_repository_id_list (TAO_InputCDR
& strm
,
1133 Repository_Id_List
& ids
)
1135 CORBA::Long num_ids
= 0;
1137 if (!strm
.read_long (num_ids
))
1142 if (num_ids
== TAO_OBV_GIOP_Flags::Indirection_tag
)
1144 // Multiple repo id is not indirected.
1149 for (CORBA::Long i
= 0; i
< num_ids
; ++i
)
1152 if (!_tao_read_repository_id (strm
, id
))
1164 CORBA::ValueBase::_tao_read_repository_id (TAO_InputCDR
& strm
,
1167 CORBA::ULong length
= 0;
1169 size_t buffer_size
= strm
.length();
1171 if (!strm
.read_ulong (length
))
1176 VERIFY_MAP (TAO_InputCDR
, repo_id_map
, Repo_Id_Map
);
1177 char * pos
= strm
.rd_ptr();
1179 // 'length' may not be the repo id length - it could be the
1180 // FFFFFFF indirection marker instead. If it is an indirection marker, we
1181 // get the offset following the indirection marker, otherwise we can follow
1182 // the same logic using the offset to simply rewind to the start of length
1183 // and re-read the length as part of the string
1184 if (TAO_OBV_GIOP_Flags::is_indirection_tag (length
))
1186 return _tao_unmarshal_repo_id_indirection (strm
, id
);
1189 pos
-= sizeof (CORBA::ULong
);
1191 // Cribbed from tc_demarshal_indirection in Typecode_CDR_Extraction.cpp
1192 TAO_InputCDR
id_stream (pos
,
1194 strm
.byte_order ());
1196 if (!id_stream
.good_bit ())
1201 if (! id_stream
.read_string (id
))
1204 // It's possible the id is read again from an indirection stream,
1205 // so make sure the id is the same.
1206 ACE_CString mapped_id
;
1207 if (strm
.get_repo_id_map ()->get()->find (pos
, mapped_id
) == 0)
1209 if (TAO_debug_level
)
1211 TAOLIB_DEBUG ((LM_DEBUG
,
1212 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_read_repository_id, found %x=%C\n"),
1213 pos
, mapped_id
.c_str ()));
1216 if (ACE_OS::strcmp (mapped_id
.c_str (), id
.c_str ()) != 0)
1218 TAOLIB_DEBUG ((LM_DEBUG
,
1219 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_read_repository_id, found %C in map for %C\n"),
1220 mapped_id
.c_str (), id
.c_str ()));
1221 throw CORBA::INTERNAL ();
1224 else if (strm
.get_repo_id_map ()->get ()->bind (pos
, id
) != 0)
1226 throw CORBA::INTERNAL ();
1228 else if (TAO_debug_level
)
1230 TAOLIB_DEBUG ((LM_DEBUG
,
1231 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_read_repository_id, bound %x=%C\n"),
1235 // Since the ID is always read from the indirection cdr we have to skip
1236 // the main CDR forward if we were in fact reading from the current
1237 // location and not rewinding back some offset.
1239 strm
.skip_bytes (length
);
1245 CORBA::ValueBase::_tao_read_codebase_url (TAO_InputCDR
& strm
,
1246 ACE_CString
& codebase_url
)
1248 CORBA::ULong length
= 0;
1250 size_t buffer_size
= strm
.length();
1252 if (!strm
.read_ulong (length
))
1257 VERIFY_MAP (TAO_InputCDR
, codebase_url_map
, Codebase_URL_Map
);
1258 char * pos
= strm
.rd_ptr();
1260 // 'length' may not be the codebase url length - it could be the
1261 // FFFFFFF indirection marker instead. If it is an indirection marker, we
1262 // get the offset following the indirection marker, otherwise we can follow
1263 // the same logic using the offset to simply rewind to the start of length
1264 // and re-read the length as part of the string
1265 if (TAO_OBV_GIOP_Flags::is_indirection_tag (length
))
1267 return _tao_unmarshal_codebase_url_indirection (strm
, codebase_url
);
1270 pos
-= sizeof (CORBA::ULong
);
1272 // Cribbed from tc_demarshal_indirection in Typecode_CDR_Extraction.cpp
1273 TAO_InputCDR
url_stream (pos
,
1275 strm
.byte_order ());
1277 if (!url_stream
.good_bit ())
1282 if (! url_stream
.read_string (codebase_url
))
1285 // It's possible the codebase url is read again from an indirection stream,
1286 // so make sure the codebase url is the same.
1287 ACE_CString mapped_url
;
1288 if (strm
.get_codebase_url_map ()->get()->find (pos
, mapped_url
) == 0)
1290 if (TAO_debug_level
)
1292 TAOLIB_DEBUG ((LM_DEBUG
,
1293 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_read_codebase_url, found %x=%C\n"),
1294 pos
, mapped_url
.c_str ()));
1296 if (ACE_OS::strcmp (mapped_url
.c_str (), codebase_url
.c_str ()) != 0)
1297 throw CORBA::INTERNAL ();
1299 else if (strm
.get_codebase_url_map ()->get()->bind (pos
, codebase_url
) != 0)
1301 throw CORBA::INTERNAL ();
1305 if (TAO_debug_level
)
1307 TAOLIB_DEBUG ((LM_DEBUG
,
1308 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_read_codebase_url, bound %x=%C\n"),
1309 pos
, codebase_url
.c_str ()));
1313 // Since the codebase url is always read from the indirection cdr we have to skip
1314 // the main CDR forward if we were in fact reading from the current
1315 // location and not rewinding back some offset.
1317 strm
.skip_bytes (length
);
1323 CORBA::ValueBase::truncation_hook ()
1325 throw ::CORBA::INTERNAL ();
1328 // ================== Typecode initializations ==================
1334 char const tc_value_base_id
[] = "IDL:omg.org/CORBA/ValueBase:1.0";
1335 char const tc_value_base_name
[] = "ValueBase";
1337 CORBA::TypeCode_ptr
const *,
1338 Value_Field
<char const *, CORBA::TypeCode_ptr
const *> const *,
1339 TAO::Null_RefCount_Policy
> tc_ValueBase (CORBA::tk_value
,
1347 char const tc_event_base_id
[] = "IDL:omg.org/CORBA/EventBase:1.0";
1348 char const tc_event_base_name
[] = "EventBase";
1350 CORBA::TypeCode_ptr
const *,
1351 Value_Field
<char const *, CORBA::TypeCode_ptr
const *> const *,
1352 TAO::Null_RefCount_Policy
> tc_EventBase (CORBA::tk_event
,
1364 TypeCode_ptr
const _tc_ValueBase
= &TAO::TypeCode::tc_ValueBase
;
1365 TypeCode_ptr
const _tc_EventBase
= &TAO::TypeCode::tc_EventBase
;
1368 // member functions for CORBA::DefaultValueRefCountBase ============
1371 CORBA::DefaultValueRefCountBase::~DefaultValueRefCountBase ()
1376 CORBA::DefaultValueRefCountBase::_add_ref ()
1378 this->_tao_add_ref ();
1382 CORBA::DefaultValueRefCountBase::_remove_ref ()
1384 this->_tao_remove_ref ();
1388 CORBA::DefaultValueRefCountBase::_refcount_value ()
1390 return this->_tao_refcount_value ();
1393 // ===========================================================
1395 CORBA::DefaultValueRefCountBase::DefaultValueRefCountBase ()
1401 CORBA::DefaultValueRefCountBase::DefaultValueRefCountBase
1402 (const DefaultValueRefCountBase
& rhs
)
1410 CORBA::DefaultValueRefCountBase::_tao_add_ref ()
1416 CORBA::DefaultValueRefCountBase::_tao_remove_ref ()
1418 CORBA::ULong
const new_count
= --this->refcount_
;
1425 CORBA::DefaultValueRefCountBase::_tao_refcount_value () const
1427 return this->refcount_
;
1430 // ===========================================================
1433 operator<< (TAO_OutputCDR
&strm
,
1434 const CORBA::ValueBase
*_tao_valuetype
)
1436 return CORBA::ValueBase::_tao_marshal (
1439 reinterpret_cast<ptrdiff_t> (&CORBA::ValueBase::_downcast
));
1443 operator>> (TAO_InputCDR
&strm
,
1444 CORBA::ValueBase
*&_tao_valuetype
)
1446 return CORBA::ValueBase::_tao_unmarshal (strm
, _tao_valuetype
);
1449 #if defined (GEN_OSTREAM_OPS)
1451 operator<< (std::ostream
&strm
,
1452 CORBA::ValueBase
*_tao_valuetype
)
1454 return CORBA::ValueBase::_tao_stream (strm
, _tao_valuetype
);
1456 #endif /* GEN_OSTREAM_OPS */
1458 // =============== Template Specializations =====================
1462 Value_Traits
<CORBA::ValueBase
>::add_ref (
1463 CORBA::ValueBase
*p
)
1469 Value_Traits
<CORBA::ValueBase
>::remove_ref (
1470 CORBA::ValueBase
* p
)
1472 CORBA::remove_ref (p
);
1476 Value_Traits
<CORBA::ValueBase
>::release (
1477 CORBA::ValueBase
* p
)
1479 CORBA::remove_ref (p
);
1483 TAO_END_VERSIONED_NAMESPACE_DECL