Revert "Minor modernization of DynamicAny code"
[ACE_TAO.git] / TAO / tao / Valuetype / ValueBase.cpp
blob2fa3079f778e0c90fe15b3bc46de9be383c8aec4
1 // -*- C++ -*-
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"
10 #include "tao/CDR.h"
11 #include "tao/ORB.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.
26 void
27 CORBA::add_ref (CORBA::ValueBase *val)
29 if (val)
31 val->_add_ref ();
35 void
36 CORBA::remove_ref (CORBA::ValueBase *val)
38 if (val)
40 val->_remove_ref ();
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),
50 chunk_size_pos_ (0),
51 length_to_chunk_octets_pos_ (0),
52 chunk_octets_end_pos_ (0)
56 CORBA::ValueBase *
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 (
69 __FILE__,
70 __LINE__,
71 ACE_TEXT_CHAR_TO_TCHAR ("Valuetype's _copy_value() should be implimented in user's most derived class"));
72 return 0;
75 CORBA::ValueBase::ValueBase ()
76 : is_truncatable_(0),
77 chunking_(0)
81 CORBA::ValueBase::ValueBase (const ValueBase& val)
82 : is_truncatable_ (val.is_truncatable_),
83 chunking_ (val.chunking_)
87 CORBA::ValueBase*
88 CORBA::ValueBase::_downcast (CORBA::ValueBase *vt)
90 // Every vt is a CORBA::ValueBase :-).
91 return vt;
94 void
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.
150 CORBA::Boolean
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);
159 else
160 return 1;
163 CORBA::Boolean
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).
170 // basically do:
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 ()
180 CORBA::Boolean
181 is_null_object = false,
182 is_indirected = false;
184 if (!CORBA::ValueBase::_tao_unmarshal_pre (
185 strm,
186 new_object,
187 0, // repo_id to be obtained from strm
188 is_null_object,
189 is_indirected ))
191 return false;
194 if (is_null_object || is_indirected)
196 return true;
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;
205 CORBA::Boolean
206 CORBA::ValueBase::_tao_unmarshal_pre (
207 TAO_InputCDR &strm,
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))
241 return false;
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)
253 valuetype = 0;
254 return result;
256 if (is_indirected)
258 return _tao_unmarshal_value_indirection (strm, valuetype);
261 CORBA::ValueBase::_tao_unmarshal_find_factory (
262 strm, start_of_valuetype, valuetype, ids, is_chunked);
264 return true;
267 CORBA::Boolean
268 CORBA::ValueBase::_tao_unmarshal_header (
269 TAO_InputCDR &strm,
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;
278 is_chunked = false;
280 CORBA::Long valuetag;
281 if (!strm.read_long (valuetag))
283 return false;
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;
292 return true;
295 if (TAO_OBV_GIOP_Flags::is_indirection_tag (valuetag))
297 // value is redirected
298 is_indirected = true;
299 return 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))
309 return false;
313 // Obtain the repo_id(s) of the type we are reading
315 if (TAO_OBV_GIOP_Flags::has_single_type_info (valuetag))
317 ACE_CString id;
318 if (!_tao_read_repository_id(strm, id))
320 return false;
322 ids.push_back (id);
324 else if (TAO_OBV_GIOP_Flags::has_list_type_info (valuetag))
326 if (!_tao_read_repository_id_list(strm, ids))
328 return false;
331 else if (TAO_OBV_GIOP_Flags::has_no_type_info (valuetag))
333 if (fallback_repo_id)
335 ids.push_back (fallback_repo_id);
337 else
339 TAOLIB_ERROR ((
340 LM_ERROR,
341 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_unmarshal_pre, ")
342 ACE_TEXT ("unknown repo_id\n") ));
343 return false;
346 else
348 if (TAO_debug_level)
350 TAOLIB_ERROR ((
351 LM_ERROR,
352 ACE_TEXT ("TAO (%P|%t) - %N:%l ValueBase::_tao_unmarshal_pre, ")
353 ACE_TEXT ("unknown value tag: %x\n"),
354 valuetag ));
357 return false;
360 return true;
363 void
364 CORBA::ValueBase::_tao_unmarshal_find_factory (
365 TAO_InputCDR &strm,
366 void *const start_of_valuetype,
367 CORBA::ValueBase *&valuetype,
368 Repository_Id_List &ids,
369 CORBA::Boolean &is_chunked)
371 valuetype = 0;
373 TAO_ORB_Core *orb_core = strm.orb_core ();
374 if (!orb_core)
376 orb_core = TAO_ORB_Core_instance ();
377 if (TAO_debug_level)
379 TAOLIB_DEBUG ((
380 LM_WARNING,
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);
403 break;
407 // Obtain the actual ValueType from the factory
408 if (factory.in() == 0 || !(valuetype = factory->create_for_unmarshal ()))
410 if (TAO_debug_level)
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"),
415 id));
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 ));
445 CORBA::Boolean
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
459 // exception there.
461 return true;
464 CORBA::Boolean
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;
472 null_object = false;
473 is_indirected = false;
475 if (!strm.read_long (value_tag))
477 return false;
480 if (TAO_OBV_GIOP_Flags::is_null_ref (value_tag))
481 { // ok, null reference unmarshaled
482 null_object = true;
483 return true;
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")));
499 return false;
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))
509 return false;
513 if (TAO_OBV_GIOP_Flags::has_no_type_info (value_tag))
515 // No type information so assume it is the correct type.
516 return true;
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.
522 ACE_CString id;
523 if (! _tao_read_repository_id (strm, id))
525 return false;
528 if (!ACE_OS::strcmp (id.c_str(), repo_id_expected))
529 { // Repository ids matched as expected
530 return true;
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.
538 return false;
541 return false;
544 CORBA::Boolean
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)
551 return false;
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),
557 buffer_size,
558 strm.byte_order ());
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 ();
566 CORBA::Boolean
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)
576 return 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_));
591 void * v = 0;
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"),
605 pos,v));
608 value = reinterpret_cast<CORBA::ValueBase *>(v);
609 return true;
612 CORBA::Boolean
613 CORBA::ValueBase::_tao_unmarshal_repo_id_indirection (TAO_InputCDR &strm,
614 ACE_CString& id)
616 CORBA::Long offset = 0;
617 if (!strm.read_long (offset) || offset >= 0)
619 return false;
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"),
631 pos, id.c_str ()));
634 return 1;
637 CORBA::Boolean
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)
644 return false;
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 ()));
660 return 1;
663 #if defined (GEN_OSTREAM_OPS)
664 std::ostream &
665 CORBA::ValueBase::_tao_stream (std::ostream &strm,
666 const CORBA::ValueBase *value)
668 return value->_tao_stream_v (strm);
671 std::ostream &
672 CORBA::ValueBase::_tao_stream_v (std::ostream &strm) const
674 return strm << "CORBA::ValueBase";
676 #endif /* GEN_OSTREAM_OPS */
678 // =================== methods for chunking ====================
680 CORBA::Boolean
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.
685 if (value == 0)
687 return strm.write_long (TAO_OBV_GIOP_Flags::Null_tag);
689 else
691 #ifdef TAO_HAS_VALUETYPE_OUT_INDIRECTION
692 // value indirection
694 VERIFY_MAP (TAO_OutputCDR, value_map, Value_Map);
695 char* pos = 0;
696 if (strm.get_value_map ()->get()->find (
697 reinterpret_cast<void*>(const_cast <CORBA::ValueBase *> (value)), pos) == 0)
699 if (TAO_debug_level)
701 TAOLIB_DEBUG ((LM_DEBUG,
702 ACE_TEXT ("(%P|%t)ValueBase::_tao_write_special_value, found value %x=%x\n"),
703 value, pos));
706 if (!strm.write_long (TAO_OBV_GIOP_Flags::Indirection_tag))
708 return false;
711 CORBA::Long const offset= -strm.offset (pos);
712 if (TAO_debug_level)
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);
721 else {
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()));
739 return false;
741 #endif
743 return false;
747 CORBA::Boolean
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))
754 return false;
757 if (! value->_tao_marshal_v (strm))
759 return false;
762 return true;
765 CORBA::Boolean
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
772 // type).
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);
781 #else
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;
810 if (num_ids > 1)
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>.
818 return false;
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
825 case */
826 || num_ids > 1)
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]))
834 return false;
837 #ifndef TAO_HAS_OPTIMIMIZED_VALUETYPE_MARSHALING
839 #endif /* !TAO_HAS_OPTIMIMIZED_VALUETYPE_MARSHALING */
841 return true;
844 CORBA::Boolean
845 CORBA::ValueBase::_tao_write_repository_id (TAO_OutputCDR &strm,
846 ACE_CString& id)
848 #ifdef TAO_HAS_VALUETYPE_OUT_INDIRECTION
850 VERIFY_MAP (TAO_OutputCDR, repo_id_map, Repo_Id_Map);
851 char* pos = 0;
852 if (strm.get_repo_id_map ()->get()->find (id, pos) == 0)
854 if (!strm.write_long (TAO_OBV_GIOP_Flags::Indirection_tag))
856 return false;
858 CORBA::Long offset= -strm.offset (pos);
859 if (TAO_debug_level)
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))
867 return false;
870 else
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 ();
880 if (TAO_debug_level)
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 ()))
888 return false;
891 #else
892 if (! strm.write_string (id.c_str ()))
894 return 0;
896 #endif
898 return 1;
901 // this method is called by the IDL generated _tao_marshal_state() method.
902 CORBA::Boolean
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.
907 if (this->chunking_)
909 if (! reserve_chunk_size(strm))
911 return false;
914 ++this->value_nesting_level_;
917 return true;
920 // this method is called by the IDL generated _tao_marshal_state() method.
921 CORBA::Boolean
922 TAO_ChunkInfo::end_chunk(TAO_OutputCDR &strm)
924 if (this->chunking_)
926 // Write actual chunk size at the reserved chunk size place.
927 if (! this->write_previous_chunk_size(strm))
929 return false;
932 // Write an end tag which is negation of value_nesting_level_.
933 if (! strm.write_long(- this->value_nesting_level_))
935 return false;
938 // -- this->value_nesting_level_;
939 if ( -- this->value_nesting_level_ == 0 )
941 // ending chunk for outermost value
942 this->chunking_ = 0;
945 return true;
948 CORBA::Boolean
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.
961 if (chunk_size == 0)
963 return false;
966 // Write the actual chunk size to the reserved chunk size position
967 // in the stream.
968 if (!strm.replace (chunk_size, this->chunk_size_pos_))
970 return false;
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;
978 return true;
981 CORBA::Boolean
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))
1002 return 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 ();
1010 return 1;
1013 CORBA::Boolean
1014 TAO_ChunkInfo::handle_chunking (TAO_InputCDR &strm)
1016 if (!this->chunking_)
1018 return 1;
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
1027 //that has parents.
1028 if (the_rd_ptr < this->chunk_octets_end_pos_)
1030 ++this->value_nesting_level_;
1031 return 1;
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_)
1038 return 0;
1041 // Read a long value that might be an endtag, the chunk size or the value tag
1042 // of the nested valuetype.
1043 CORBA::Long tag;
1045 if (!strm.read_long (tag))
1047 return 0;
1050 if (tag < 0)
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"),
1058 -tag,
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().
1086 return 0;
1089 return 1;
1092 CORBA::Boolean
1093 TAO_ChunkInfo::skip_chunks (TAO_InputCDR &strm)
1095 if (!this->chunking_)
1097 return 1;
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.
1103 CORBA::Long tag;
1104 if (!strm.read_long(tag))
1106 return 0;
1109 // end of the whole valuetype.
1110 if (tag == -1)
1112 return 1;
1114 else if (tag < 0)
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);
1127 else
1128 return 0;
1131 CORBA::Boolean
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))
1139 return 0;
1142 if (num_ids == TAO_OBV_GIOP_Flags::Indirection_tag)
1144 // Multiple repo id is not indirected.
1145 return 0;
1147 else
1149 for (CORBA::Long i = 0; i < num_ids; ++i)
1151 ACE_CString id;
1152 if (!_tao_read_repository_id (strm, id))
1154 return 0;
1156 ids.push_back (id);
1160 return 1;
1163 CORBA::Boolean
1164 CORBA::ValueBase::_tao_read_repository_id (TAO_InputCDR& strm,
1165 ACE_CString& id)
1167 CORBA::ULong length = 0;
1169 size_t buffer_size = strm.length();
1171 if (!strm.read_ulong (length))
1173 return 0;
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,
1193 buffer_size,
1194 strm.byte_order ());
1196 if (!id_stream.good_bit ())
1198 return 0;
1201 if (! id_stream.read_string (id))
1202 return 0;
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"),
1232 pos, id.c_str ()));
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);
1241 return 1;
1244 CORBA::Boolean
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))
1254 return false;
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,
1274 buffer_size,
1275 strm.byte_order ());
1277 if (!url_stream.good_bit ())
1279 return false;
1282 if (! url_stream.read_string (codebase_url))
1283 return false;
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 ();
1303 else
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);
1319 return true;
1322 void
1323 CORBA::ValueBase::truncation_hook ()
1325 throw ::CORBA::INTERNAL ();
1328 // ================== Typecode initializations ==================
1330 namespace TAO
1332 namespace TypeCode
1334 char const tc_value_base_id[] = "IDL:omg.org/CORBA/ValueBase:1.0";
1335 char const tc_value_base_name[] = "ValueBase";
1336 Value<char const *,
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,
1340 tc_value_base_id,
1341 tc_value_base_name,
1342 CORBA::VM_NONE,
1343 &CORBA::_tc_null,
1344 0, // Field array
1345 0); // Field count
1347 char const tc_event_base_id[] = "IDL:omg.org/CORBA/EventBase:1.0";
1348 char const tc_event_base_name[] = "EventBase";
1349 Value<char const *,
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,
1353 tc_event_base_id,
1354 tc_event_base_name,
1355 CORBA::VM_NONE,
1356 &CORBA::_tc_null,
1357 0, // Field array
1358 0); // Field count
1362 namespace CORBA
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 ============
1370 // destructor
1371 CORBA::DefaultValueRefCountBase::~DefaultValueRefCountBase ()
1375 void
1376 CORBA::DefaultValueRefCountBase::_add_ref ()
1378 this->_tao_add_ref ();
1381 void
1382 CORBA::DefaultValueRefCountBase::_remove_ref ()
1384 this->_tao_remove_ref ();
1387 CORBA::ULong
1388 CORBA::DefaultValueRefCountBase::_refcount_value ()
1390 return this->_tao_refcount_value ();
1393 // ===========================================================
1395 CORBA::DefaultValueRefCountBase::DefaultValueRefCountBase ()
1396 : refcount_ (1)
1400 // Copy constructor
1401 CORBA::DefaultValueRefCountBase::DefaultValueRefCountBase
1402 (const DefaultValueRefCountBase& rhs)
1403 : ValueBase (rhs),
1404 refcount_ (1)
1409 void
1410 CORBA::DefaultValueRefCountBase::_tao_add_ref ()
1412 ++this->refcount_;
1415 void
1416 CORBA::DefaultValueRefCountBase::_tao_remove_ref ()
1418 CORBA::ULong const new_count = --this->refcount_;
1420 if (new_count == 0)
1421 delete this;
1424 CORBA::ULong
1425 CORBA::DefaultValueRefCountBase::_tao_refcount_value () const
1427 return this->refcount_;
1430 // ===========================================================
1432 CORBA::Boolean
1433 operator<< (TAO_OutputCDR &strm,
1434 const CORBA::ValueBase *_tao_valuetype)
1436 return CORBA::ValueBase::_tao_marshal (
1437 strm,
1438 _tao_valuetype,
1439 reinterpret_cast<ptrdiff_t> (&CORBA::ValueBase::_downcast));
1442 CORBA::Boolean
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)
1450 std::ostream&
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 =====================
1459 namespace TAO
1461 void
1462 Value_Traits<CORBA::ValueBase>::add_ref (
1463 CORBA::ValueBase *p)
1465 CORBA::add_ref (p);
1468 void
1469 Value_Traits<CORBA::ValueBase>::remove_ref (
1470 CORBA::ValueBase * p)
1472 CORBA::remove_ref (p);
1475 void
1476 Value_Traits<CORBA::ValueBase>::release (
1477 CORBA::ValueBase * p)
1479 CORBA::remove_ref (p);
1483 TAO_END_VERSIONED_NAMESPACE_DECL