// **********************************************************************
//
// Copyright (c) 1999
// Object Oriented Concepts, Inc.
// Billerica, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#include <OB/Basic.h>
#include <OB/Except.h>
#include <OB/Template.h>
#include <OB/TemplateI.h>
#include <OB/Declarations.h>
#include <OB/Any.h>
#include <OB/TCKind.h>
#include <OB/TypeCode.h>
#include <OB/Principal.h>
#include <OB/IOP.h>
#include <OB/Object.h>

// ----------------------------------------------------------------------
// Template instantiations
// ----------------------------------------------------------------------

#ifndef HAVE_NO_EXPLICIT_TEMPLATES
template class OBVarVar< CORBA_Any >;
template class OBVarSeq< CORBA_Any >;
template class OBSeqVar< OBVarSeq< CORBA_Any > >;
#else
#ifdef HAVE_PRAGMA_DEFINE
#pragma define(OBVarVar< CORBA_Any >)
#pragma define(OBVarSeq< CORBA_Any >)
#pragma define(OBSeqVar< OBVarSeq< CORBA_Any > >)
#endif
#endif

// ----------------------------------------------------------------------
// Constructor and destructor
// ----------------------------------------------------------------------

CORBA_Any::CORBA_Any()
    : type_(CORBA_TypeCode::_duplicate(CORBA__tc_null)), value_(0),
      rel_(false), info_(0)
{
}

CORBA_Any::CORBA_Any(const CORBA_Any& r)
    : type_(CORBA_TypeCode::_duplicate(CORBA__tc_null)), value_(0),
      rel_(false), info_(0)
{
    *this = r;
}

CORBA_Any::CORBA_Any(CORBA_TypeCode_ptr tc, void* val, CORBA_Boolean rel)
    : type_(CORBA_TypeCode::_duplicate(tc)), value_(val),
      rel_(rel), info_(0)
{
}

CORBA_Any::~CORBA_Any()
{
    replace(CORBA_TypeCode::_nil(), 0, false);
}

// ----------------------------------------------------------------------
// Assignment
// ----------------------------------------------------------------------

CORBA_Any&
CORBA_Any::operator=(const CORBA_Any& any)
{
    if(this != &any)
    {
	if(any.value_)
	{
	    void* val = 0;

	    CORBA_TypeCode_var p = OBGetOrigType(any.type_);

	    switch(p -> kind())
	    {
	    case CORBA_tk_null:
	    case CORBA_tk_void:
		break;
		
	    case CORBA_tk_short:
		val = new CORBA_Short(*(const CORBA_Short*)any.value_);
		break;
		
	    case CORBA_tk_long:
		val = new CORBA_Long(*(const CORBA_Long*)any.value_);
		break;
		
	    case CORBA_tk_ushort:
		val = new CORBA_UShort(*(const CORBA_UShort*)any.value_);
		break;
		
	    case CORBA_tk_ulong:
	    case CORBA_tk_enum:
		val = new CORBA_ULong(*(const CORBA_ULong*)any.value_);
		break;
		
	    case CORBA_tk_float:
		val = new CORBA_Float(*(const CORBA_Float*)any.value_);
		break;
		
	    case CORBA_tk_double:
		val = new CORBA_Double(*(const CORBA_Double*)any.value_);
		break;
		
	    case CORBA_tk_boolean:
		val = new CORBA_Boolean(*(const CORBA_Boolean*)any.value_);
		break;
		
	    case CORBA_tk_char:
		val = new CORBA_Char(*(const CORBA_Char*)any.value_);
		break;
		
	    case CORBA_tk_octet:
		val = new CORBA_Octet(*(const CORBA_Octet*)any.value_);
		break;
		
	    case CORBA_tk_any:
		val = new CORBA_Any(*(const CORBA_Any*)any.value_);
		break;
		
	    case CORBA_tk_TypeCode:
		val = CORBA_TypeCode::_duplicate((CORBA_TypeCode_ptr)
						 any.value_);
		break;
		
	    case CORBA_tk_Principal:
		val = CORBA_Principal::_duplicate((CORBA_Principal_ptr)
						  any.value_);
		break;
		
	    case CORBA_tk_objref:
		{
		    OBObjAny* objAnyFrom = (OBObjAny*)any.value_;
		    OBObjAny* objAnyTo = new OBObjAny;
		    objAnyTo -> b = CORBA_Object::_duplicate(objAnyFrom -> b);
		    objAnyTo -> d = CORBA_Object::_duplicate(objAnyFrom -> d);
		    val = objAnyTo;
		    break;
		}
		
	    case CORBA_tk_struct:
	    case CORBA_tk_sequence:
	    case CORBA_tk_union:
	    case CORBA_tk_array:
	    case CORBA_tk_except:
		
		if(p -> _OB_isSystemException())
		{
		    CORBA_Exception* ex =
		    ((CORBA_SystemException*)any.value_) -> _OB_clone();
		    val = CORBA_SystemException::_narrow(ex);
		    assert(val);
		}
		else if(any.info_)
		{
		    val = any.info_ -> dup(any.value_);
		}
		else
		{
		    const OBBuffer* cbufp = (const OBBuffer*)any.value_;
		    OBBuffer* bufp = new OBBuffer(cbufp -> len);
		    val = bufp;
		    memcpy(bufp -> data, cbufp -> data, cbufp -> len);
		}
		break;
		
	    case CORBA_tk_string:
		val = CORBA_string_dup((const char*)any.value_);
		break;
		
	    case CORBA_tk_alias: // No alias possible here,
		break;     // this is to keep the compiler happy
	    }
	
	    replace(any.type_, val, true, any.info_);
	}
	else
	    replace(any.type_, 0);
    }
    
    return *this;
}

// ----------------------------------------------------------------------
// Insertion into Any
// ----------------------------------------------------------------------

void
CORBA_Any::operator<<=(CORBA_Short v)
{
    replace(CORBA__tc_short, new CORBA_Short(v), true);
}

void
CORBA_Any::operator<<=(CORBA_UShort v)
{
    replace(CORBA__tc_ushort, new CORBA_UShort(v), true);
}

void
CORBA_Any::operator<<=(CORBA_Long v)
{
    replace(CORBA__tc_long, new CORBA_Long(v), true);
}

void
CORBA_Any::operator<<=(CORBA_ULong v)
{
    replace(CORBA__tc_ulong, new CORBA_ULong(v), true);
}

void
CORBA_Any::operator<<=(CORBA_Float v)
{
    replace(CORBA__tc_float, new CORBA_Float(v), true);
}

void
CORBA_Any::operator<<=(CORBA_Double v)
{
    replace(CORBA__tc_double, new CORBA_Double(v), true);
}

void
CORBA_Any::operator<<=(const char* v)
{
    replace(CORBA__tc_string, CORBA_string_dup(v), true);
}

void
CORBA_Any::operator<<=(const CORBA_Any& v)
{
    replace(CORBA__tc_any, new CORBA_Any(v), true);
}

void
CORBA_Any::operator<<=(CORBA_Any* v)
{
    replace(CORBA__tc_any, v, true);
}

void
CORBA_Any::operator<<=(CORBA_TypeCode_ptr v)
{
    replace(CORBA__tc_TypeCode, CORBA_TypeCode::_duplicate(v), true);
}

void
CORBA_Any::operator<<=(CORBA_TypeCode_ptr* v)
{
    replace(CORBA__tc_TypeCode, *v, true);
}

void
CORBA_Any::operator<<=(CORBA_Principal_ptr v)
{
    replace(CORBA__tc_Principal, CORBA_Principal::_duplicate(v), true);
}

void
CORBA_Any::operator<<=(CORBA_Principal_ptr* v)
{
    replace(CORBA__tc_Principal, *v, true);
}

void
CORBA_Any::operator<<=(CORBA_Object_ptr v)
{
    OBObjAny* objAny = new OBObjAny;
    objAny -> b = CORBA_Object::_duplicate(v);
    objAny -> d = CORBA_Object::_duplicate(v);
    replace(CORBA__tc_Object, objAny, true);
}

void
CORBA_Any::operator<<=(CORBA_Object_ptr* v)
{
    OBObjAny* objAny = new OBObjAny;
    objAny -> b = *v;
    objAny -> d = CORBA_Object::_duplicate(*v);
    replace(CORBA__tc_Object, objAny, true);
}

void
CORBA_Any::operator<<=(from_boolean v)
{
    replace(CORBA__tc_boolean, new CORBA_Boolean(v.val), true);
}

void
CORBA_Any::operator<<=(from_char v)
{
    replace(CORBA__tc_char, new CORBA_Char(v.val), true);
}

void
CORBA_Any::operator<<=(from_octet v)
{
    replace(CORBA__tc_octet, new CORBA_Octet(v.val), true);
}

void
CORBA_Any::operator<<=(from_string v)
{
    CORBA_TypeCode_var tc = CORBA__tc_string.bounded(v.bound);

    if(v.nocopy)
	replace(tc, v.val, true);
    else
	replace(tc, CORBA_string_dup(v.val), true);
}

// ----------------------------------------------------------------------
// Extraction from Any
// ----------------------------------------------------------------------

CORBA_Boolean
CORBA_Any::operator>>=(CORBA_Short& v) const
{
    if(check_type(CORBA__tc_short))
    {
	v = *(CORBA_Short*)value_;
	return true;
    }
    else
	return false;
}

CORBA_Boolean
CORBA_Any::operator>>=(CORBA_UShort& v) const
{
    if(check_type(CORBA__tc_ushort))
    {
	v = *(CORBA_UShort*)value_;
	return true;
    }
    else
	return false;
}

CORBA_Boolean
CORBA_Any::operator>>=(CORBA_Long& v) const
{
    if(check_type(CORBA__tc_long))
    {
	v = *(CORBA_Long*)value_;
	return true;
    }
    else
	return false;
}

CORBA_Boolean
CORBA_Any::operator>>=(CORBA_ULong& v) const
{
    if(check_type(CORBA__tc_ulong))
    {
	v = *(CORBA_ULong*)value_;
	return true;
    }
    else
	return false;
}

CORBA_Boolean
CORBA_Any::operator>>=(CORBA_Float& v) const
{
    if(check_type(CORBA__tc_float))
    {
	v = *(CORBA_Float*)value_;
	return true;
    }
    else
	return false;
}

CORBA_Boolean
CORBA_Any::operator>>=(CORBA_Double& v) const
{
    if(check_type(CORBA__tc_double))
    {
	v = *(CORBA_Double*)value_;
	return true;
    }
    else
	return false;
}

CORBA_Boolean 
CORBA_Any::operator>>=(char*& v) const
{
    if(check_type(CORBA__tc_string))
    {
	v = (char*)value_;
	return true;
    }
    else
	return false;
}

CORBA_Boolean 
CORBA_Any::operator>>=(CORBA_Any*& v) const
{
    if(check_type(CORBA__tc_any))
    {
	v = (CORBA_Any*)value_;
	return true;
    }
    else
	return false;
}

CORBA_Boolean 
CORBA_Any::operator>>=(CORBA_TypeCode_ptr& v) const
{
    if(check_type(CORBA__tc_TypeCode))
    {
	v = (CORBA_TypeCode_ptr)value_;
	return true;
    }
    else
	return false;
}

CORBA_Boolean 
CORBA_Any::operator>>=(CORBA_Principal_ptr& v) const
{
    if(check_type(CORBA__tc_Principal))
    {
	v = (CORBA_Principal_ptr)value_;
	return true;
    }
    else
	return false;
}

CORBA_Boolean 
CORBA_Any::operator>>=(CORBA_Object_ptr& v) const
{
    if(check_type(CORBA__tc_Object))
    {
	OBObjAny* objAny = (OBObjAny*)value_;
	assert(objAny);
	v = objAny -> d;
	return true;
    }
    else
	return false;
}

CORBA_Boolean
CORBA_Any::operator>>=(to_boolean v) const
{
    if(check_type(CORBA__tc_boolean))
    {
	v.val = *(CORBA_Boolean*)value_;
	return true;
    }
    else
	return false;
}

CORBA_Boolean
CORBA_Any::operator>>=(to_char v) const
{
    if(check_type(CORBA__tc_char))
    {
	v.val = *(CORBA_Char*)value_;
	return true;
    }
    else
	return false;
}

CORBA_Boolean
CORBA_Any::operator>>=(to_octet v) const
{
    if(check_type(CORBA__tc_octet))
    {
	v.val = *(CORBA_Octet*)value_;
	return true;
    }
    else
	return false;
}

CORBA_Boolean
CORBA_Any::operator>>=(to_string v) const
{
    if(type_ -> kind() == CORBA_tk_string && type_ -> length() == v.bound)
    {
	v.val = (char*)value_;
	return true;
    }
    else
	return false;
}

CORBA_Boolean
CORBA_Any::operator>>=(to_object v) const
{
    if(type_ -> kind() == CORBA_tk_objref)
    {
	OBObjAny* objAny = (OBObjAny*)value_;
	assert(objAny);
	v.val = objAny -> b;
	return true;
    }
    else
	return false;
}

// ----------------------------------------------------------------------
// Replace type
// ----------------------------------------------------------------------

void
CORBA_Any::replace(CORBA_TypeCode_ptr tc, void* val, CORBA_Boolean rel)
{
    replace(tc, val, rel, 0);
}

// ----------------------------------------------------------------------
// TypeCode accessor and modifier
// ----------------------------------------------------------------------

CORBA_TypeCode_ptr
CORBA_Any::type() const
{
    return CORBA_TypeCode::_duplicate(type_);
}

void
CORBA_Any::type(CORBA_TypeCode_ptr tc)
{
    if(type_ -> equal(tc))
        type_ = CORBA_TypeCode::_duplicate(tc);
    else
        throw CORBA_BAD_TYPECODE();
}

// ----------------------------------------------------------------------
// Return value
// ----------------------------------------------------------------------

const void*
CORBA_Any::value() const
{
    return value_;
}

// ----------------------------------------------------------------------
// Additional ORBacus functions
// ----------------------------------------------------------------------

void
CORBA_Any::replace(CORBA_TypeCode_ptr tc, void* val,
		   CORBA_Boolean rel, const OBConstructedInfo* info)
{
    if(rel_ && value_)
    {
	CORBA_TypeCode_var p = OBGetOrigType(type_);
	
	switch(p -> kind())
	{
	case CORBA_tk_null:
	case CORBA_tk_void:
	    break;
	    
	case CORBA_tk_short:
	    assert_nca(value_ == 0 || value_ != val, OBNCAAnySelfReplace);
	    delete (CORBA_Short*)value_;
	    break;
	    
	case CORBA_tk_long:
	    assert_nca(value_ == 0 || value_ != val, OBNCAAnySelfReplace);
	    delete (CORBA_Long*)value_;
	    break;
	    
	case CORBA_tk_ushort:
	    assert_nca(value_ == 0 || value_ != val, OBNCAAnySelfReplace);
	    delete (CORBA_UShort*)value_;
	    break;
	    
	case CORBA_tk_ulong:
	case CORBA_tk_enum:
	    assert_nca(value_ == 0 || value_ != val, OBNCAAnySelfReplace);
	    delete (CORBA_ULong*)value_;
	    break;
	    
	case CORBA_tk_float:
	    assert_nca(value_ == 0 || value_ != val, OBNCAAnySelfReplace);
	    delete (CORBA_Float*)value_;
	    break;
	    
	case CORBA_tk_double:
	    assert_nca(value_ == 0 || value_ != val, OBNCAAnySelfReplace);
	    delete (CORBA_Double*)value_;
	    break;
	    
	case CORBA_tk_boolean:
	    assert_nca(value_ == 0 || value_ != val, OBNCAAnySelfReplace);
	    delete (CORBA_Boolean*)value_;
	    break;
	    
	case CORBA_tk_char:
	    assert_nca(value_ == 0 || value_ != val, OBNCAAnySelfReplace);
	    delete (CORBA_Char*)value_;
	    break;
	    
	case CORBA_tk_octet:
	    assert_nca(value_ == 0 || value_ != val, OBNCAAnySelfReplace);
	    delete (CORBA_Octet*)value_;
	    break;
	    
	case CORBA_tk_any:
	    assert_nca(value_ == 0 || value_ != val, OBNCAAnySelfReplace);
	    delete (CORBA_Any*)value_;
	    break;
	    
	case CORBA_tk_TypeCode:
	    CORBA_release((CORBA_TypeCode_ptr)value_);
	    break;
	    
	case CORBA_tk_Principal:
	    CORBA_release((CORBA_Principal_ptr)value_);
	    break;
	    
	case CORBA_tk_objref:
	{
	    OBObjAny* objAny = (OBObjAny*)value_;
	    assert(objAny);
	    CORBA_release(objAny -> b);
	    CORBA_release(objAny -> d);
	    delete objAny;
	    break;
	}
	    
	case CORBA_tk_struct:
	case CORBA_tk_sequence:
	case CORBA_tk_union:
	case CORBA_tk_array:
	case CORBA_tk_except:

	    assert_nca(value_ == 0 || value_ != val, OBNCAAnySelfReplace);

	    if(p -> _OB_isSystemException())
	    {
		delete (CORBA_SystemException*)value_;
	    }
	    else if(info_)
	    {
		info_ -> free(value_);
	    }
	    else
	    {
		delete (OBBuffer*)value_;
	    }
	    break;
	    
	case CORBA_tk_string:
	    assert_nca(value_ == 0 || value_ != val, OBNCAAnySelfReplace);
	    CORBA_string_free((char*)value_);
	    break;
	    
	case CORBA_tk_alias: // No alias possible here,
	    break;     // this is to keep the compiler happy
	}
    }

    type_ = CORBA_TypeCode::_duplicate(tc);
    value_ = val;
    rel_ = rel;
    info_ = info;
}

CORBA_Boolean
CORBA_Any::check_type(CORBA_TypeCode_ptr t) const
{
    return type_ -> equal(t);
}

// ----------------------------------------------------------------------
// CDR functions
// ----------------------------------------------------------------------

void OBMarshal(const CORBA_Any& any, CORBA_Octet*& oct)
{
    OBMarshal(any.type_, oct);
    OBMarshalNoTypeCode(any, oct);
}

void OBMarshalNoTypeCode(const CORBA_Any& any, CORBA_Octet*& oct)
{
    CORBA_TypeCode_var p = OBGetOrigType(any.type_);
    
    switch(p -> kind())
    {
    case CORBA_tk_null:
    case CORBA_tk_void:
	    break;
	    
    case CORBA_tk_short:
	OBMarshal(*(const CORBA_Short*)any.value_, oct);
	break;
	
    case CORBA_tk_long:
	OBMarshal(*(const CORBA_Long*)any.value_, oct);
	break;
	
    case CORBA_tk_ushort:
	OBMarshal(*(const CORBA_UShort*)any.value_, oct);
	break;
	
    case CORBA_tk_ulong:
    case CORBA_tk_enum:
	OBMarshal(*(const CORBA_ULong*)any.value_, oct);
	break;
	
    case CORBA_tk_float:
	OBMarshal(*(const CORBA_Float*)any.value_, oct);
	break;
	
    case CORBA_tk_double:
	OBMarshal(*(const CORBA_Double*)any.value_, oct);
	break;
	
    case CORBA_tk_boolean:
	OBMarshal(*(const CORBA_Boolean*)any.value_, oct);
	break;
	
    case CORBA_tk_char:
	OBMarshal(*(const CORBA_Char*)any.value_, oct);
	break;
	
    case CORBA_tk_octet:
	OBMarshal(*(const CORBA_Octet*)any.value_, oct);
	break;
	
    case CORBA_tk_any:
	OBMarshal(*(const CORBA_Any*)any.value_, oct);
	break;
	
    case CORBA_tk_TypeCode:
	OBMarshal((CORBA_TypeCode_ptr)any.value_, oct);
	break;
	
    case CORBA_tk_Principal:
	OBMarshal((CORBA_Principal_ptr)any.value_, oct);
	break;
	
    case CORBA_tk_objref:
    {
	OBObjAny* objAny = (OBObjAny*)any.value_;
	assert(objAny);
	OBMarshal(objAny -> b, oct);
	break;
    }
	
    case CORBA_tk_struct:
    case CORBA_tk_sequence:
    case CORBA_tk_union:
    case CORBA_tk_array:
    case CORBA_tk_except:

	if(p -> _OB_isSystemException())
	{
	    OBMarshal(*(CORBA_SystemException*)any.value_, oct);
	}
	else if(any.info_)
	{
	    any.info_ -> marshal(any.value_, oct);
	}
	else
	{
	    const OBBuffer* cbufp = (const OBBuffer*)any.value_;
	    const CORBA_Octet* from = cbufp -> data;
	    OBMarshalBuffer(p, from, oct, false);
	}
	break;
	
    case CORBA_tk_string:
	OBMarshal((const char*)any.value_, oct);
	break;
	
    case CORBA_tk_alias: // No alias possible here,
	break;     // this is to keep the compiler happy
    }
}

void OBMarshalCount(const CORBA_Any& any, CORBA_ULong& count)
{
    OBMarshalCount(any.type_, count);
    OBMarshalCountNoTypeCode(any, count);
}

void OBMarshalCountNoTypeCode(const CORBA_Any& any, CORBA_ULong& count)
{
    CORBA_TypeCode_var p = OBGetOrigType(any.type_);
	
    switch(p -> kind())
    {
    case CORBA_tk_null:
    case CORBA_tk_void:
	break;
	
    case CORBA_tk_short:
	OBMarshalCount(*(const CORBA_Short*)any.value_, count);
	break;
	
    case CORBA_tk_long:
	OBMarshalCount(*(const CORBA_Long*)any.value_, count);
	break;
	
    case CORBA_tk_ushort:
	OBMarshalCount(*(const CORBA_UShort*)any.value_, count);
	break;
	
    case CORBA_tk_ulong:
    case CORBA_tk_enum:
	OBMarshalCount(*(const CORBA_ULong*)any.value_, count);
	break;
	
    case CORBA_tk_float:
	OBMarshalCount(*(const CORBA_Float*)any.value_, count);
	break;
	
    case CORBA_tk_double:
	OBMarshalCount(*(const CORBA_Double*)any.value_, count);
	break;
	
    case CORBA_tk_boolean:
	OBMarshalCount(*(const CORBA_Boolean*)any.value_, count);
	break;
	
    case CORBA_tk_char:
	OBMarshalCount(*(const CORBA_Char*)any.value_, count);
	break;
	
    case CORBA_tk_octet:
	OBMarshalCount(*(const CORBA_Octet*)any.value_, count);
	break;
	
    case CORBA_tk_any:
	OBMarshalCount(*(const CORBA_Any*)any.value_, count);
	break;
	
    case CORBA_tk_TypeCode:
	OBMarshalCount((CORBA_TypeCode_ptr)any.value_, count);
	break;
	
    case CORBA_tk_Principal:
	OBMarshalCount((CORBA_Principal_ptr)any.value_, count);
	break;
	
    case CORBA_tk_objref:
    {
	OBObjAny* objAny = (OBObjAny*)any.value_;
	assert(objAny);
	OBMarshalCount(objAny -> b, count);
	break;
    }
	
    case CORBA_tk_struct:
    case CORBA_tk_sequence:
    case CORBA_tk_union:
    case CORBA_tk_array:
    case CORBA_tk_except:
	
	if(p -> _OB_isSystemException())
	{
	    OBMarshalCount(*(CORBA_SystemException*)any.value_, count);
	}
	else if(any.info_)
	{
	    any.info_ -> marshalCount(any.value_, count);
	}
	else
	{
	    const OBBuffer* cbufp = (const OBBuffer*)any.value_;
	    const CORBA_Octet* from = cbufp -> data;
	    OBMarshalBufferCount(p, from, count, false);
	}
	break;
	
    case CORBA_tk_string:
	OBMarshalCount((const char*)any.value_, count);
	break;
	
    case CORBA_tk_alias: // No alias possible here,
	break;     // this is to keep the compiler happy
    }
}

void OBUnmarshal(CORBA_Any& any, const CORBA_Octet*& oct, bool swap)
{
    CORBA_TypeCode_var tc;
    OBUnmarshal(tc.inout(), oct, swap);

    OBUnmarshalNoTypeCode(any, oct, swap, tc);
}

void OBUnmarshalNoTypeCode(CORBA_Any& any, const CORBA_Octet*& oct, bool swap,
			   CORBA_TypeCode_ptr tc)
{
    void* val = 0;
    
    CORBA_TypeCode_var p = OBGetOrigType(tc);
    
    switch(p -> kind())
    {
    case CORBA_tk_null:
    case CORBA_tk_void:
	break;
	
    case CORBA_tk_short:
    {
	CORBA_Short v;
	OBUnmarshal(v, oct, swap);
	val = new CORBA_Short(v);
	break;
    }

    case CORBA_tk_long:
    {
	CORBA_Long v;
	OBUnmarshal(v, oct, swap);
	val = new CORBA_Long(v);
	break;
    }

    case CORBA_tk_ushort:
    {
	CORBA_UShort v;
	OBUnmarshal(v, oct, swap);
	val = new CORBA_UShort(v);
	break;
    }

    case CORBA_tk_ulong:
    case CORBA_tk_enum:
    {
	CORBA_ULong v;
	OBUnmarshal(v, oct, swap);
	val = new CORBA_ULong(v);
	break;
    }

    case CORBA_tk_float:
    {
	CORBA_Float v;
	OBUnmarshal(v, oct, swap);
	val = new CORBA_Float(v);
	break;
    }

    case CORBA_tk_double:
    {
	CORBA_Double v;
	OBUnmarshal(v, oct, swap);
	val = new CORBA_Double(v);
	break;
    }

    case CORBA_tk_boolean:
    {
	CORBA_Boolean v;
	OBUnmarshal(v, oct, swap);
	val = new CORBA_Boolean(v);
	break;
    }

    case CORBA_tk_char:
    {
	CORBA_Char v;
	OBUnmarshal(v, oct, swap);
	val = new CORBA_Char(v);
	break;
    }

    case CORBA_tk_octet:
    {
	CORBA_Octet v;
	OBUnmarshal(v, oct, swap);
	val = new CORBA_Octet(v);
	break;
    }

    case CORBA_tk_any:
    {
	CORBA_Any* v = new CORBA_Any;
	OBUnmarshal(*v, oct, swap);
	val = v;
	break;
    }

    case CORBA_tk_TypeCode:
    {
	CORBA_TypeCode_ptr v = CORBA_TypeCode::_nil();
	OBUnmarshal(v, oct, swap);
	val = v;
	break;
    }

    case CORBA_tk_Principal:
    {
	CORBA_Principal_ptr v = CORBA_Principal::_nil();
	OBUnmarshal(v, oct, swap);
	val = v;
	break;
    }
	
    case CORBA_tk_objref:
    {
	OBObjAny* objAny = new OBObjAny;
	objAny -> b = CORBA_Object::_nil();
	objAny -> d = CORBA_Object::_nil();
	OBUnmarshal(objAny -> b, oct, swap);
	objAny -> d = CORBA_Object::_duplicate(objAny -> b);
	val = objAny;
	break;
    }

    case CORBA_tk_struct:
    case CORBA_tk_sequence:
    case CORBA_tk_union:
    case CORBA_tk_array:
    case CORBA_tk_except:

	if(p -> _OB_isSystemException())
	{
	    val = OBUnmarshalSystemException(oct, swap);
	}
	else
	{
	    CORBA_ULong count = 0;
	    const CORBA_Octet* from = oct;
	    OBMarshalBufferCount(p, from, count, swap);
	    OBBuffer* bufp = new OBBuffer(count);
	    val = bufp;
	    CORBA_Octet* to = bufp -> data;
	    OBMarshalBuffer(p, oct, to, swap);
	}
	break;

    case CORBA_tk_string:
    {
	char* s = 0;
	OBUnmarshal(s, oct, swap);
	val = s;
	break;
    }
	
    case CORBA_tk_alias: // No alias possible here,
	break;     // this is to keep the compiler happy
    }

    any.replace(tc, val, true);
}

void
OBMarshal(const OBVarSeq< CORBA_Any >& seq, CORBA_Octet*& oct)
{
    OBMarshal(seq.length(), oct);
    for(CORBA_ULong i = 0 ; i < seq.length() ; i++)
        OBMarshal(seq[i], oct);
}

void
OBMarshalCount(const OBVarSeq< CORBA_Any >& seq, CORBA_ULong& count)
{
    OBMarshalCount(seq.length(), count);
    for(CORBA_ULong i = 0 ; i < seq.length() ; i++)
        OBMarshalCount(seq[i], count);
}

void
OBUnmarshal(OBVarSeq< CORBA_Any >& seq, const CORBA_Octet*& oct, bool swap)
{
    CORBA_ULong len;
    OBUnmarshal(len, oct, swap);
    seq.length(len);
    for(CORBA_ULong i = 0 ; i < len ; i++)
        OBUnmarshal(seq[i], oct, swap);
}

// ----------------------------------------------------------------------
// Insertion and extraction on Any_var
// ----------------------------------------------------------------------

void operator<<=(CORBA_Any_var& any, CORBA_Short val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_UShort val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_Long val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_ULong val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_Float val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_Double val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, const char* val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, char* val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, const CORBA_Any& val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_Any* val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_TypeCode_ptr val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_TypeCode_ptr* val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_Principal_ptr val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_Principal_ptr* val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_Object_ptr val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_Object_ptr* val)
{
    any.inout() <<= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_Short& val)
{
    return any.in() >>= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_UShort& val)
{
    return any.in() >>= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_Long& val)
{
    return any.in() >>= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_ULong& val)
{
    return any.in() >>= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_Float& val)
{
    return any.in() >>= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_Double& val)
{
    return any.in() >>= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, char*& val)
{
    return any.in() >>= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_Any*& val)
{
    return any.in() >>= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_TypeCode_ptr& val)
{
    return any.in() >>= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_Principal_ptr& val)
{
    return any.in() >>= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_Object_ptr& val)
{
    return any.in() >>= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_Any::from_boolean val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_Any::from_octet val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_Any::from_char val)
{
    any.inout() <<= val;
}

void operator<<=(CORBA_Any_var& any, CORBA_Any::from_string val)
{
    any.inout() <<= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_Any::to_boolean val)
{
    return any.in() >>= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_Any::to_octet val)
{
    return any.in() >>= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_Any::to_char val)
{
    return any.in() >>= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_Any::to_string val)
{
    return any.in() >>= val;
}

CORBA_Boolean operator>>=(const CORBA_Any_var& any, CORBA_Any::to_object val)
{
    return any.in() >>= val;
}

// ----------------------------------------------------------------------
// Insertion and extraction for system exceptions
// ----------------------------------------------------------------------

#define OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(T) \
\
void \
operator<<=(CORBA_Any& any, CORBA_##T* v) \
{ \
    CORBA_SystemException* ex = v; \
    any.replace(CORBA__tc_##T, ex, true); \
} \
\
void \
operator<<=(CORBA_Any& any, const CORBA_##T& v) \
{ \
    CORBA_SystemException* ex = new CORBA_##T(v); \
    any.replace(CORBA__tc_##T, ex, true); \
} \
\
CORBA_Boolean \
operator>>=(const CORBA_Any& any, CORBA_##T*& v) \
{ \
    if(any.check_type(CORBA__tc_##T)) \
    { \
	CORBA_SystemException* ex = (CORBA_SystemException*)any.value(); \
        v = CORBA_##T::_narrow(ex); \
        assert(v); \
        return true; \
    } \
    else \
        return false; \
}

OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(UNKNOWN)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(BAD_PARAM)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(NO_MEMORY)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(IMP_LIMIT)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(COMM_FAILURE)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(INV_OBJREF)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(NO_PERMISSION)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(INTERNAL)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(MARSHAL)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(INITIALIZE)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(NO_IMPLEMENT)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(BAD_TYPECODE)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(BAD_OPERATION)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(NO_RESOURCES)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(NO_RESPONSE)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(PERSIST_STORE)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(BAD_INV_ORDER)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(TRANSIENT)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(FREE_MEM)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(INV_IDENT)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(INV_FLAG)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(INTF_REPOS)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(BAD_CONTEXT)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(OBJ_ADAPTER)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(DATA_CONVERSION)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(OBJECT_NOT_EXIST)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(TRANSACTION_REQUIRED)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(TRANSACTION_ROLLEDBACK)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(INVALID_TRANSACTION)
OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I(INV_POLICY)
