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

#ifndef OB_ANY_H
#define OB_ANY_H

//
// Helper struct for object references
//
struct OBObjAny
{
    CORBA_Object_ptr b, d;
};

//
// The Any class
//
class CORBA_Any
{
    CORBA_TypeCode_var type_;
    void* value_;
    CORBA_Boolean rel_;
    const OBConstructedInfo* info_;

    //
    // Hide to catch erroneous attempts to insert or extract
    // to unsigned char
    //
    void operator<<=(unsigned char);
    CORBA_Boolean operator>>=(unsigned char&) const;

public:

    CORBA_Any();
    CORBA_Any(const CORBA_Any&);
    CORBA_Any(CORBA_TypeCode_ptr, void*, CORBA_Boolean = false);
    ~CORBA_Any();

    CORBA_Any& operator=(const CORBA_Any&);

    void operator<<=(CORBA_Short);
    void operator<<=(CORBA_UShort);
    void operator<<=(CORBA_Long);
    void operator<<=(CORBA_ULong);
    void operator<<=(CORBA_Float);
    void operator<<=(CORBA_Double);
    void operator<<=(const char*);
    void operator<<=(const CORBA_Any&);
    void operator<<=(CORBA_Any*);
    void operator<<=(CORBA_TypeCode_ptr);
    void operator<<=(CORBA_TypeCode_ptr*);
    void operator<<=(CORBA_Principal_ptr);
    void operator<<=(CORBA_Principal_ptr*);
    void operator<<=(CORBA_Object_ptr);
    void operator<<=(CORBA_Object_ptr*);

    CORBA_Boolean operator>>=(CORBA_Short&) const;
    CORBA_Boolean operator>>=(CORBA_UShort&) const;
    CORBA_Boolean operator>>=(CORBA_Long&) const;
    CORBA_Boolean operator>>=(CORBA_ULong&) const;
    CORBA_Boolean operator>>=(CORBA_Float&) const;
    CORBA_Boolean operator>>=(CORBA_Double&) const;
    CORBA_Boolean operator>>=(char*&) const;
    CORBA_Boolean operator>>=(CORBA_Any*&) const;
    CORBA_Boolean operator>>=(CORBA_TypeCode_ptr&) const;
    CORBA_Boolean operator>>=(CORBA_Principal_ptr&) const;
    CORBA_Boolean operator>>=(CORBA_Object_ptr&) const;

    //
    // Special types for boolean, cotet, char insertion and extraction
    //
    struct from_boolean
    {
	CORBA_Boolean val;

	from_boolean(CORBA_Boolean v) : val(v) {};
	from_boolean(const from_boolean& v) : val(v.val) {};
    };

    struct from_octet
    {
	CORBA_Octet val;

	from_octet(CORBA_Octet v) : val(v) {};
	from_octet(const from_octet& v) : val(v.val) {};
    };

    struct from_char
    {
	CORBA_Char val;

	from_char(CORBA_Char v) : val(v) {};
	from_char(const from_char& v) : val(v.val) {};
    };

    struct from_string
    {
	char* val;
	CORBA_ULong bound;
	CORBA_Boolean nocopy;

	from_string(char* v, CORBA_ULong b, CORBA_Boolean nc = false)
	    : val(v), bound(b), nocopy(nc) {};
	from_string(const from_string& v)
	    : val(v.val), bound(v.bound), nocopy(v.nocopy) {};
    };

    void operator<<=(from_boolean);
    void operator<<=(from_octet);
    void operator<<=(from_char);
    void operator<<=(from_string);

    struct to_boolean
    {
	CORBA_Boolean& val;

	to_boolean(CORBA_Boolean& v) : val(v) {};
	to_boolean(const to_boolean& v) : val(v.val) {};
    };

    struct to_octet
    {
	CORBA_Octet& val;

	to_octet(CORBA_Octet& v) : val(v) {};
	to_octet(const to_octet& v) : val(v.val) {};
    };

    struct to_char
    {
	CORBA_Char& val;

	to_char(CORBA_Char& v) : val(v) {};
	to_char(const to_char& v) : val(v.val) {};
    };

    struct to_string
    {
	char*& val;
	CORBA_ULong bound;

	to_string(char*& v, CORBA_ULong b) : val(v), bound(b) {};
	to_string(const to_string& v) : val(v.val), bound(v.bound) {};
    };

    struct to_object
    {
	CORBA_Object_ptr& val;

	to_object(CORBA_Object_ptr& v) : val(v) {};
	to_object(const to_object& v) : val(v.val) {};
    };

    CORBA_Boolean operator>>=(to_boolean) const;
    CORBA_Boolean operator>>=(to_octet) const;
    CORBA_Boolean operator>>=(to_char) const;
    CORBA_Boolean operator>>=(to_string) const;
    CORBA_Boolean operator>>=(to_object) const;

    void replace(CORBA_TypeCode_ptr, void*, CORBA_Boolean = false);
    CORBA_TypeCode_ptr type() const;
    void type(CORBA_TypeCode_ptr);
    const void* value() const;

    //
    // Additional ORBacus functions
    //
    void replace(CORBA_TypeCode_ptr, void*, CORBA_Boolean,
		 const OBConstructedInfo*);
    CORBA_Boolean check_type(CORBA_TypeCode_ptr) const;
    const OBConstructedInfo* info() const { return info_; }

    //
    // CDR
    //
    friend void OBMarshal(const CORBA_Any&, CORBA_Octet*&);
    friend void OBMarshalNoTypeCode(const CORBA_Any&, CORBA_Octet*&);
    friend void OBMarshalCount(const CORBA_Any&, CORBA_ULong&);
    friend void OBMarshalCountNoTypeCode(const CORBA_Any&, CORBA_ULong&);
    friend void OBUnmarshal(CORBA_Any&, const CORBA_Octet*&, bool);
    friend void OBUnmarshalNoTypeCode(CORBA_Any&, const CORBA_Octet*&, bool,
				      CORBA_TypeCode_ptr);
};

//
// CDR
//
void OBMarshal(const OBVarSeq< CORBA_Any >&, CORBA_Octet*&);
void OBMarshalCount(const OBVarSeq< CORBA_Any >&, CORBA_ULong&);
void OBUnmarshal(OBVarSeq< CORBA_Any >&, const CORBA_Octet*&, bool);

//
// Create variable type
//
typedef OBVarVar< CORBA_Any > CORBA_Any_var;

//
// Insertion and extraction on Any_var
//
// Because of the conversion operator that convert 'Any_var' to
// 'const Any&' only member functions of Any must be explicitly
// defined for Any_var
//
void operator<<=(CORBA_Any_var&, CORBA_Short);
void operator<<=(CORBA_Any_var&, CORBA_UShort);
void operator<<=(CORBA_Any_var&, CORBA_Long);
void operator<<=(CORBA_Any_var&, CORBA_ULong);
void operator<<=(CORBA_Any_var&, CORBA_Float);
void operator<<=(CORBA_Any_var&, CORBA_Double);
void operator<<=(CORBA_Any_var&, const char*);
void operator<<=(CORBA_Any_var&, char*);
void operator<<=(CORBA_Any_var&, const CORBA_Any&);
void operator<<=(CORBA_Any_var&, CORBA_Any*);
void operator<<=(CORBA_Any_var&, CORBA_TypeCode_ptr);
void operator<<=(CORBA_Any_var&, CORBA_TypeCode_ptr*);
void operator<<=(CORBA_Any_var&, CORBA_Principal_ptr);
void operator<<=(CORBA_Any_var&, CORBA_Principal_ptr*);
void operator<<=(CORBA_Any_var&, CORBA_Object_ptr);
void operator<<=(CORBA_Any_var&, CORBA_Object_ptr*);

CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_Short&);
CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_UShort&);
CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_Long&);
CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_ULong&);
CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_Float&);
CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_Double&);
CORBA_Boolean operator>>=(const CORBA_Any_var&, char*&);
CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_Any*&);
CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_TypeCode_ptr&);
CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_Principal_ptr&);
CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_Object_ptr&);

void operator<<=(CORBA_Any_var&, CORBA_Any::from_boolean);
void operator<<=(CORBA_Any_var&, CORBA_Any::from_octet);
void operator<<=(CORBA_Any_var&, CORBA_Any::from_char);
void operator<<=(CORBA_Any_var&, CORBA_Any::from_string);

CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_Any::to_boolean);
CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_Any::to_octet);
CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_Any::to_char);
CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_Any::to_string);
CORBA_Boolean operator>>=(const CORBA_Any_var&, CORBA_Any::to_object);

//
// Insertion and extraction for system exceptions
//
#define OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION(T) \
class CORBA_##T; \
void operator<<=(CORBA_Any&, CORBA_##T*); \
void operator<<=(CORBA_Any&, const CORBA_##T&); \
CORBA_Boolean operator>>=(const CORBA_Any&, CORBA_##T*&);

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

#endif
