// IBM Open Class Library
//
// Licensed Materials - Property of IBM
//
// (C) Copyright IBM Corporation, 1992, 1997 All Rights Reserved
//
// Revision: 19 1.3.1.4 source/core/collect/iptr.inl, collection, ioc.v400, 001006 
#ifndef _IPTR_INL_
#define _IPTR_INL_

#ifndef IC_BUILD
#define __IOC_INLINE inline
#else
#define __IOC_INLINE
#endif

// ------------
// IElemPointer
// ------------

// public members

template <class Element>
inline
IElemPointer <Element>::
IElemPointer ()
: ivPtr (0)
{
}

template <class Element>
inline
IElemPointer <Element>::
IElemPointer (Element* ptr, IExplicitInit)
: ivPtr (ptr)
{
}

template <class Element>
inline Element&
IElemPointer <Element>::
operator* () const
{ return *ivPtr;
}

template <class Element>
inline Element*
IElemPointer <Element>::
operator-> () const
{ return ivPtr;
}

template <class Element>
inline
IElemPointer <Element>::
operator Element* () const
{ return ivPtr;
}

template <class Element>
inline Element&
elementForOps (IElemPointer <Element>& ptr)
{ return *ptr.ivPtr;
}

template <class Element>
inline Element const&
elementForOps (IElemPointer <Element> const& ptr)
{ return *ptr.ivPtr;
}

// -----------
// IMngPointer
// -----------

// public members

template <class Element>
inline
IMngPointer <Element>::
IMngPointer ()
: ivPtrRc (0)
{
}

template <class Element>
inline
IMngPointer <Element>::
IMngPointer (Element *ptr, IExplicitInit)
: ivPtrRc (new PtrRc (ptr))
{
}

template <class Element>
inline
IMngPointer <Element>::
IMngPointer (IMngPointer <Element> const& ptr)
{ ivPtrRc = ptr.ivPtrRc;
  if (ivPtrRc != 0) ivPtrRc->ivRc++;
}

template <class Element>
inline
IMngPointer <Element>::
~IMngPointer ()
{ if (ivPtrRc != 0 && --ivPtrRc->ivRc == 0) delete ivPtrRc;
}

template <class Element>
inline IMngPointer <Element>&
IMngPointer <Element>::
operator= (IMngPointer <Element> const& ptr)
{ if (this != &ptr) {
    if (ivPtrRc && --ivPtrRc->ivRc == 0) delete ivPtrRc;
    ivPtrRc = ptr.ivPtrRc;
    if (ivPtrRc != 0) ivPtrRc->ivRc++;
  }
  return *this;
}

template <class Element>
inline Element&
IMngPointer <Element>::
operator* () const
{ return *ivPtrRc->ivPtr;
}

template <class Element>
inline Element*
IMngPointer <Element>::
operator-> () const
{ return ivPtrRc->ivPtr;
}

template <class Element>
inline
IMngPointer <Element>::
operator Element* () const
{ if (ivPtrRc == 0) return 0;
  else return ivPtrRc->ivPtr;
}

// ---------------
// IMngElemPointer
// ---------------

// public members

template <class Element>
inline
IMngElemPointer <Element>::
IMngElemPointer (Element *ptr, IExplicitInit)
: IMngPointer <Element> (ptr, IINIT)
{
}

template <class Element>
inline
IMngElemPointer <Element>::
IMngElemPointer ()
{
}

#if defined (ICLCC_COMPAT_PTR)
template <class Element>
inline
IMngElemPointer <Element>::
IMngElemPointer (Element const& e)
: IMngPointer <Element> (new Element (e), IINIT)
{
}

template <class Element>
inline
IMngElemPointer <Element>::
IMngElemPointer (Element *ptr)
: IMngPointer <Element> (ptr, IINIT)
{
}
#endif

template <class Element>
inline Element&
IMngElemPointer <Element>::
operator* () const
{ return IMngPointer <Element>::operator* ();
}

template <class Element>
inline Element*
IMngElemPointer <Element>::
operator-> () const
{ return IMngPointer <Element>::operator-> ();
}

template <class Element>
inline
IMngElemPointer <Element>::
operator Element* () const
{ return (IMngPointer <Element> const&)*this;
}

template <class Element>
inline Element&
elementForOps (IMngElemPointer <Element>& ptr)
{ return *(Element*)ptr;
}

template <class Element>
inline Element const&
elementForOps (IMngElemPointer <Element> const& ptr)
{ return *(Element*)ptr;
}

// ------------
// IAutoPointer
// ------------

// public members

template <class Element>
inline
IAutoPointer <Element>::
IAutoPointer (Element* ptr, IExplicitInit)
: ivPtr (ptr)
{
}

template <class Element>
inline
IAutoPointer <Element>::
IAutoPointer ()
: ivPtr (0)
{
}

template <class Element>
inline
IAutoPointer <Element>::
IAutoPointer (IAutoPointer <Element> const& ptr)
{ ivPtr = ptr.ivPtr;
  ((IAutoPointer <Element>&)ptr).ivPtr = 0;
}

template <class Element>
inline
IAutoPointer <Element>::
~IAutoPointer ()
{ delete ivPtr;
}

template <class Element>
inline void
IAutoPointer <Element>::
operator= (IAutoPointer <Element> const& ptr)
{ if (this != &ptr) {
    delete ivPtr;
    ivPtr = ptr.ivPtr;
    ((IAutoPointer <Element>&) ptr).ivPtr = 0;
  }
}

template <class Element>
inline
IAutoPointer <Element>::
operator Element* () const
{ return ivPtr;
}

template <class Element>
inline Element&
IAutoPointer <Element>::
operator * () const
{ return *ivPtr;
}

template <class Element>
inline Element*
IAutoPointer <Element>::
operator-> () const
{ return ivPtr;
}


// ----------------
// IAutoElemPointer
// ----------------

// public members

template <class Element>
inline
IAutoElemPointer <Element>::
IAutoElemPointer ()
{
}

template <class Element>
inline
IAutoElemPointer <Element>::
IAutoElemPointer (Element *ptr, IExplicitInit)
: IAutoPointer <Element> (ptr, IINIT)
{
}

template <class Element>
inline Element&
IAutoElemPointer <Element>::
operator* () const
{ return IAutoPointer <Element>::operator* ();
}

template <class Element>
inline Element*
IAutoElemPointer <Element>::
operator-> () const
{ return IAutoPointer <Element>::operator->();
}

template <class Element>
inline
IAutoElemPointer <Element>::
operator Element* () const
{ return IAutoPointer <Element>::operator Element* ();
}

template <class Element>
inline Element&
elementForOps (IAutoElemPointer <Element>& ptr)
{ return *(Element*)ptr;
}

template <class Element>
inline Element const&
elementForOps (IAutoElemPointer <Element> const& ptr)
{ return *(Element*)ptr;
}

#if ! defined (__INO_STREAMING__)
// ------------------
// IStreamablePointer
// ------------------

// public members

template <class Element>
inline
IStreamablePointer <Element>::
IStreamablePointer ()
: ivPtrRc (0)
{
}

template <class Element>
inline
IStreamablePointer <Element>::
IStreamablePointer (Element *ptr, IExplicitInit)
: ivPtrRc (new PtrRc (ptr))
{
}

template <class Element>
inline
IStreamablePointer <Element>::
IStreamablePointer (IStreamablePointer <Element> const& ptr)
{ ivPtrRc = ptr.ivPtrRc;
  if (ivPtrRc != 0) ivPtrRc->ivRc++;
}

template <class Element>
inline
IStreamablePointer <Element>::
~IStreamablePointer ()
{ if (ivPtrRc != 0 && --ivPtrRc->ivRc == 0) delete ivPtrRc;
}

template <class Element>
inline IStreamablePointer <Element>&
IStreamablePointer <Element>::
operator= (IStreamablePointer <Element> const& ptr)
{ if (this != &ptr) {
    if (ivPtrRc && --ivPtrRc->ivRc == 0) delete ivPtrRc;
    ivPtrRc = ptr.ivPtrRc;
    if (ivPtrRc != 0) ivPtrRc->ivRc++;
  }
  return *this;
}

template <class Element>
inline Element&
IStreamablePointer <Element>::
operator* () const
{ return *ivPtrRc->ivPtr;
}

template <class Element>
inline Element*
IStreamablePointer <Element>::
operator-> () const
{ return ivPtrRc->ivPtr;
}

template <class Element>
inline
IStreamablePointer <Element>::
operator Element* () const
{ if (ivPtrRc == 0) return 0;
  else return ivPtrRc->ivPtr;
}

template <class Element>
__IOC_INLINE
void
operator<<=( IStreamablePointer<Element>& element, IDataStream& fromWhere)
{ element = IStreamablePointer<Element> (new Element(),IINIT);
  *((Element*)element) <<= fromWhere;
}

template <class Element>
__IOC_INLINE
void
operator>>=(const IStreamablePointer<Element>&element, IDataStream& toWhere)
{ *((Element*)element) >>= toWhere;
}
#endif

#endif // _IPTR_INL_
