// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*-
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
//
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
// ACDK
//
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
//
// $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/lang/ObjectArrayBase.h,v 1.50 2005/04/17 11:20:11 kommer Exp $
#ifndef acdk_lang_ObjectArrayBase_h
#define acdk_lang_ObjectArrayBase_h
namespace acdk {
namespace io {
template <class T> void readObjectArray(ObjectArrayImpl<T>* This, ::acdk::io::RObjectReader in);
}
namespace util {
ACDK_DECL_INTERFACE(Iterator);
ACDK_DECL_INTERFACE(List);
}
}
/*
Redesign of ObjectArray and BasicArray
Targets:
- Support for casting
- better DMI integration
- SubArrays (equal solution to StringArrays with copy on write mechanism)
(Not yet implemented)
- less generated template code
- Collection interface
*/
namespace acdk {
namespace lang {
ACDK_DECL_CLASS(ObjectArrayBaseImpl);
/**
acdk::lang::Object implements the array of acdk::lang::Object similar to the
Java acdk::lang::Object[] construct
Normally will not used directly
- and instance of template <class RefHolderClass> class RObjectArrayImpl;
- or via DMI
Java usage: Integer[] iarray = new Integer[3]; iarray[0] = new Integer(1);
ACDK usage: RIntegerArray iarray = new IntegerArray(3); iarray[0] = new Integer(1);
@author Roger Rene Kommer
@version $Revision: 1.50 $
@see Arrays.
*/
ACDK_CLASSATTRIBUTE(acdk.tools.mc.ClazzFlagAttribute(acdk.lang.dmi.MiCiArray))
ACDK_CLASSATTRIBUTE(acdk.tools.mc.ClazzNameAttribute("["))
class ACDK_CORE_PUBLIC ObjectArrayBaseImpl
: extends acdk::lang::Object
{
ACDK_WITH_METAINFO(ObjectArrayBaseImpl)
public:
foreign typedef acdk::lang::Object* array_iterator;
protected:
foreign array_iterator _begin;
int _length;
foreign array_iterator _endCap;
foreign const acdk::lang::dmi::ClazzInfo* _elementClazzInfo;
public:
/**
creates an Array with given size
*/
ACDK_METHODATTRIBUTE(acdk.tools.mc.SetDispatchAttribute("ObjectArrayBaseImpl::dmiConstructor", false))
ObjectArrayBaseImpl(int size = 0)
: _begin(0)
, _length(size)
, _endCap(0)
, _elementClazzInfo(Object::clazzInfo())
{
_init(size);
}
/**
Creating generic ObjectArray with given elemtype as member types
Used for DMI
*/
foreign ObjectArrayBaseImpl(const acdk::lang::dmi::ClazzInfo* elemtype, int size)
: _begin(0)
, _length(size)
, _endCap(0)
, _elementClazzInfo(elemtype)
{
_init(size);
}
foreign ~ObjectArrayBaseImpl()
{
_dispose();
}
foreign virtual acdk::lang::Object* _cast(const acdk::lang::dmi::ClazzInfo* ci);
static acdk::lang::Object create_instance();
/**
return the count of elements in this array
*/
inline int length() const { return _length; }
/**
STL like array_iterator
*/
foreign inline array_iterator begin() { return _begin; }
/**
STL like iterator
*/
foreign inline array_iterator end() { return _begin + _length; }
/**
STL like iterator
*/
foreign inline array_iterator endCap() { return _endCap; }
/**
return the element at idx position
@throw ArrayIndexOutOfBoundsException if idx not in valid range
*/
ACDK_METHODATTRIBUTE(acdk.tools.mc.MethodAltNameAttribute("get", 1))
IN(acdk::lang::Object) getElement(int idx)
{
_checkIndexAccess(idx);
return _begin[idx]; // before: .impl(), but why?
}
/**
return the element at idx position as reference (left side value)
@throw ArrayIndexOutOfBoundsException if idx not in valid range
*/
ACDK_METHODATTRIBUTE(acdk.tools.mc.MethodAltNameAttribute("getref", 1))
OUT(acdk::lang::Object) getElementRef(int idx)
{
_makeSetSlot(idx);
return _begin[idx];
}
OUT(acdk::lang::Object) operator[](int idx) { return getElementRef(idx); }
/**
set the element at idx position (method name in DMI is set)
@throw ArrayIndexOutOfBoundsException if idx not in valid range
*/
ACDK_METHODATTRIBUTE(acdk.tools.mc.MethodAltNameAttribute("set", 2))
void setElement(int idx, IN(acdk::lang::Object) value)
{
_makeSetSlot(idx);
_begin[idx] = _castAssignmentElement(value);
}
/**
Set element at idx to Nil
@throw ArrayIndexOutOfBoundsException if idx not in valid range
*/
foreign void set(int idx, NilRef nil)
{
_makeSetSlot(idx);
_begin[idx] = nil;
}
/**
append value to this array
*/
void append(IN(acdk::lang::Object) value)
{
_makeAppendSlot();
*(end() - 1) = _castAssignmentElement(value);
}
/** for DMI operator[](int idx) access */
OUT(acdk::lang::Object) operator_bo(int idx)
{
return getElementRef(idx);
}
/**
concat other array to this array
*/
void concat(IN(RObjectArrayBaseImpl) other);
/**
insert obj into idx possition
@throw IndexOutOfBoundsException if idx not in valid range
*/
void insert(int idx, IN(acdk::lang::Object) value)
{
_makeInsertSlot(idx);
*(_begin + idx) = _castAssignmentElement(value);
}
/**
removes element at idx position
@throw IndexOutOfBoundsException if idx not in valid range
*/
void remove(int idx);
/**
Find equals element (using el->equals())
If el == Nil find first element which also Nil.
@return found index position
or -1
*/
int find(IN(acdk::lang::Object) el)
{
for (int i = 0; i < _length; ++i)
{
if (el == Nil && _begin[i] == Nil)
return i;
if (el != Nil && _begin[i] != Nil)
if (el->equals(_begin[i]) == true)
return i;
}
return -1;
}
/**
alias for find(IN(acdk::lang::Object) el)
*/
int findFirst(IN(acdk::lang::Object) el) { return find(el); }
/**
find the element from starting with the last element
using equals()
@return found index position
or -1
*/
int findLast(IN(acdk::lang::Object) el)
{
int l = length();
for (int i = l - 1; i >= 0; --i)
{
acdk::lang::Object d = _begin[i];
if (el == Nil && d == Nil)
return i;
if (el != Nil && d != Nil)
if (el->equals(d) == true)
return i;
}
return -1;
}
/**
find same object instance (using == instead of equals())
@return found index position
or -1 of not found
*/
int findSame(IN(acdk::lang::Object) el)
{
int l = length();
for (int i = 0; i < l; ++i)
if (_begin[i] == el)
return i;
return -1;
}
/*
removes element element, which is equals
@return Nil if not found
*/
acdk::lang::Object removeEqualElement(IN(acdk::lang::Object) el)
{
int idx = find(el);
if (idx == -1)
return Nil;
acdk::lang::Object d = _begin[idx];
remove(idx);
return d;
}
/**
remove element which is same instance
@return Nil if not found
*/
acdk::lang::Object removeSameElement(IN(acdk::lang::Object) el)
{
int idx = findSame(el);
if (idx == -1)
return Nil;
acdk::lang::Object d = _begin[idx];
remove(idx);
return d;
}
/** creates a read only iterator from this array */
acdk::util::RIterator iterator();
/**
create this as an container (ArrayList)
@param copy take over this ObjectArray or crate internally an own
*/
acdk::util::RList asContainer(bool copy = false);
/**
return the capacity of this array
*/
inline int capacity() const { return _endCap - _begin; }
/**
make sure that internal storage capacity
is at least newsize elements
*/
void ensureCapacity(int newsize);
/// @internal
void makeCapacity(int newsize)
{
_makeCapacity(newsize);
}
/**
return the hashCode of this array
*/
virtual int hashCode();
virtual bool equals(IN(acdk::lang::Object) o);
/**
hard resize of this array. if newSize is less than
current size elements will be deleted.
if newSize is greater thatn current size new
element will be set to Nil
*/
void resize(int newSize);
/**
return stringified representation [element, element] of this array
*/
RString toString();
acdk::lang::Object clone() { return clone(allocator()); }
foreign acdk::lang::Object clone(::acdk::lang::sys::Allocator* alc);
/**
remove element from back and return the removed value
*/
ACDK_METHODATTRIBUTE(acdk.tools.mc.MethodAltNameAttribute("popBack", 0))
acdk::lang::Object pop_back_element()
{
acdk::lang::Object l = getElement(length() - 1);
remove(length() - 1);
return l;
}
/**
remove element from front (first element) and return the removed value
*/
ACDK_METHODATTRIBUTE(acdk.tools.mc.MethodAltNameAttribute("popFront", 0))
acdk::lang::Object pop_front_element()
{
acdk::lang::Object t = getElement(0);
remove(0);
return t;
}
/** return the last element */
ACDK_METHODATTRIBUTE(acdk.tools.mc.MethodAltNameAttribute("back", 0))
IN(acdk::lang::Object) back_element() { return getElement(length() - 1); }
/// STL style function
ACDK_METHODATTRIBUTE(acdk.tools.mc.MethodAltNameAttribute("front", 0))
IN(acdk::lang::Object) front_element() { return getElement(0); }
/// STL style function
ACDK_METHODATTRIBUTE(acdk.tools.mc.MethodAltNameAttribute("pushFront", 1))
void push_front_element(IN(acdk::lang::Object) obj) { insert(0, obj); }
/// STL style function
ACDK_METHODATTRIBUTE(acdk.tools.mc.MethodAltNameAttribute("pushBack", 1))
void push_back_element(IN(acdk::lang::Object) obj) { append(obj); }
/**
get the element from index beginning with last element
*/
ACDK_METHODATTRIBUTE(acdk.tools.mc.MethodAltNameAttribute("peekBack", 1))
IN(acdk::lang::Object) peekElementBack(int idx) { return getElement((length() - 1) - idx); }
/// @internal
foreign static const ObjectArrayBaseImpl* _tryCast(const acdk::lang::dmi::ClazzInfo* toClazz, const ObjectArrayBaseImpl* other);
foreign const acdk::lang::dmi::ClazzInfo* getElementClazzInfo() { return _elementClazzInfo; }
foreign void setElementClazzInfo(const acdk::lang::dmi::ClazzInfo* ci) { _elementClazzInfo = ci; }
protected:
/// @internal
foreign void _init(int size)
{
ensureCapacity(size);
}
/// @internal
foreign void _dispose();
/// @internal
foreign inline void _checkIndexAccess(int idx) const
{
if (idx >= _length || idx < 0)
_throwArrayIndexOutOfBoundsException(idx, _length, "ObjectArrayImpl::get()");
}
/// @internal
foreign inline acdk::lang::Object* _createData(int newsize)
{
acdk::lang::Object* data = new acdk::lang::Object[newsize];
memset(data, 0, sizeof(acdk::lang::Object) * newsize);
return data;
}
/// @internal
foreign inline void _destroyData()
{
acdk::lang::Object* data = _begin;
if (data != 0)
{
delete [] data;
data = 0;
}
}
/// @internal
foreign void _makeCapacity(int newCap);
/// @internal
foreign void _makeSetSlot(int idx) const
{
_checkIndexAccess(idx);
}
/// @internal
foreign void _makeInsertSlot(int idx);
/// @internal
foreign void _makeAppendSlot()
{
ensureCapacity(length() + 1);
++_length;
}
/**
throws ClassCastException if value is not assignable to array element type
*/
foreign acdk::lang::Object _castAssignmentElement(IN(acdk::lang::Object) value) const;
public:
/// @internal
foreign static const ::acdk::lang::dmi::ClazzMethodInfo* dmiConstructor(
::acdk::lang::Object* This,
IN(acdk::lang::RString) fname,
::acdk::lang::dmi::ScriptVar& ret,
::acdk::lang::dmi::ScriptVarArray& args,
::acdk::lang::dmi::DmiClient& dc,
IN(::acdk::lang::RStringArray) namedArgs,
int flags,
const ::acdk::lang::dmi::ClazzInfo* clazzinfo,
const ::acdk::lang::dmi::ClazzMethodInfo* methinf);
};
// ****************************************** ObjectArrayBase **************************
/**
base DMIable implementation of Arrays of Objects
Normally this class will not be used by application code
*/
class ACDK_CORE_PUBLIC ObjectArrayBase
: extends ObjectArrayBaseImpl
{
public:
ObjectArrayBase(int size = 0)
: ObjectArrayBaseImpl(size)
{
}
foreign ObjectArrayBase(const acdk::lang::dmi::ClazzInfo* elemtype, int size)
: ObjectArrayBaseImpl(elemtype, size)
{
}
/// @internal
virtual acdk::lang::dmi::ClazzInfo* getClazzInfo();
/// @internal
virtual ::acdk::lang::RClass getClass();
/// @internal
virtual void getCollectableFields(FieldReferences& fields);
/// @internal
virtual ::acdk::lang::dmi::SysFields getInternalFields(int flags, const ::acdk::lang::dmi::ClazzInfo* clazz = 0);
};
} // namespace lang
} // namespace acdk
// ****************************************** ObjectArrayImpl<T> **************************
/// @internal
template <class T> class RObjectArrayImpl;
/**
template implementation of acdk::lang::Object Arrays
This will be used via the ACDK_DECL_CLASS()
macro.
Different to Java acdk::lang::Object arrays in ACDK are resizable
@ingroup acdksmartptr
*/
template <class T>
class ObjectArrayImpl
: extends ::acdk::lang::ObjectArrayBase
{
public:
/// @internal
static acdk::lang::dmi::ClazzInfo* clazzInfo();
/// @internal
static ::acdk::lang::RClass GetClass();
typedef T* array_iterator;
//typedef T* iterator; NOT because there is also a method
ObjectArrayImpl(int size = 0)
: ObjectArrayBase(T::clazzInfo(), size)
{
}
ObjectArrayImpl(const acdk::lang::dmi::ClazzInfo* elemtype, int size)
: ObjectArrayBase(elemtype, size)
{
}
/**
return element at index idx
*/
const T& get(int idx) const
{
_checkIndexAccess(idx);
return _getData()[idx];
}
T& getref(int idx) const
{
_makeSetSlot(idx);
return _getData()[idx];
}
void set(int idx, const T& value)
{
_makeSetSlot(idx);
_getData()[idx] = value;
}
T& operator[](int idx) const { return getref(idx) ; }
void append(const T& value)
{
_makeAppendSlot();
_getData()[length() - 1] = value;
}
void insert(int idx, const T& value)
{
_makeInsertSlot(idx);
_getData()[idx] = value;
}
/**
Find equals element (using el->equals())
If el == Nil find first element which also Nil.
@return found index position
or -1 of not found
*/
int find(IN(T) el)
{
int l = length();
for (int i = 0; i < l; ++i)
{
T d = _getData()[i];
if (el == Nil && d == Nil)
return i;
if (el != Nil && d != Nil)
if (el->equals((::acdk::lang::RObject)&d) == true)
return i;
}
return -1;
}
/**
alias for findFirst(IN(T) el)
*/
int findFirst(IN(T) el) { return find(el); }
/**
find the element (using equals()) from behind
@return found index position or -1 if not found
*/
int findLast(IN(T) el)
{
int l = length();
for (int i = l - 1; i >= 0; --i)
{
T d = _getData()[i];
if (el == Nil && d == Nil)
return i;
if (el != Nil && d != Nil)
if (el->equals((::acdk::lang::RObject)&d) == true)
return i;
}
return -1;
}
/**
find same object
@return found index position
or -1 of not found
*/
int findSame(IN(T) el)
{
int l = length();
for (int i = 0; i < l; ++i)
if (_getData()[i] == el)
return i;
return -1;
}
/*
removes element element, which is equals
@return Nil if not found
*/
T removeEqualElement(IN(T) el)
{
int idx = find(el);
if (idx == -1)
return Nil;
T d = _getData()[idx];
remove(idx);
return d;
}
/**
remove element which is same instance
@return Nil if not found
*/
T removeSameElement(IN(T) el)
{
int idx = findSame(el);
if (idx == -1)
return Nil;
T d = _getData()[idx];
remove(idx);
return d;
}
/** append given other Array to this array */
void concat(IN(RObjectArrayImpl<T>) other)
{
ensureCapacity(length() + other->length());
array_iterator oit = other->begin();
array_iterator oend = other->end();
for (; oit < oend; ++oit)
append(*oit);
}
/// STL style function
array_iterator begin() { return _getData(); }
/// STL style function
array_iterator end() { return _getData() + length(); }
virtual void readObject(IN(::acdk::io::RObjectReader) in)
{
::acdk::io::readObjectArray(this, in);
}
/// STL style function
T pop_back()
{
T l = get(size() - 1);
remove(size() - 1);
return l;
}
/// STL style function
T popBack() { return pop_back(); }
/// STL style function
T pop_front()
{
T t = get(0);
remove(0);
return t;
}
T popFront() { return pop_front(); }
/// STL style function
const T& back() const { return get(size() - 1); }
/// STL style function
const T& front() const { return get(0); }
/// STL style function
void push_front(const T& t) { insert(0, t); }
void pushFront(const T& t) { insert(0, t); }
/// STL style function
void push_back(const T& t) { append(t); }
void pushBack(const T& t) { append(t); }
/// STL style function
int size() const { return length(); }
/// STL style function
inline bool empty() const { return length() == 0; }
const T& peekBack(int idx) { return get((length() - 1) - idx); }
protected:
T* _getData() const { return reinterpret_cast<T*>(_begin); }
};
// ****************************************** RObjectArrayImpl **************************
/**
reference holder for an array
@ingroup acdksmartptr
*/
template <class T>
class RObjectArrayImpl
: public RefHolder<ObjectArrayImpl<T> >
{
public:
static acdk::lang::dmi::ClazzInfo* clazzInfo();
static ::acdk::lang::RClass GetClass();
RObjectArrayImpl(NilRef nil = Nil)
: RefHolder<ObjectArrayImpl<T> >()
{
}
RObjectArrayImpl(size_t size)
: RefHolder<ObjectArrayImpl<T> >(new ObjectArrayImpl<T>(size))
{
}
template <class OT>
upcast_explicit
RObjectArrayImpl(ObjectArrayImpl<OT> *implptr)
: RefHolder<ObjectArrayImpl<T> >()
{
if (implptr == 0)
return;
ObjectArrayImpl<T>* t = dynamic_cast<ObjectArrayImpl<T> *>(implptr);
if (t == 0)
{
t = (ObjectArrayImpl<T>*)ObjectArrayBase::_tryCast(T::clazzInfo(), implptr);
if (t == 0)
{
_copyArray(implptr);
return;
}
}
RObjectArrayImpl<T>::_impl = implptr->_getObjectPtr();
RObjectArrayImpl<T>::_iptr = const_cast<ObjectArrayImpl<T>*>(t);
RObjectArrayImpl<T>::_impl->addRef();
}
RObjectArrayImpl(ObjectArrayImpl<T> *impl)
: RefHolder<ObjectArrayImpl<T> >(impl)
{
}
template <class OT>
upcast_explicit
RObjectArrayImpl(const RObjectArrayImpl<OT>& anotherarray)
: RefHolder<ObjectArrayImpl<T> >()
{
if (anotherarray.impl() == 0)
return;
ObjectArrayImpl<T>* t = dynamic_cast<ObjectArrayImpl<T> *>(anotherarray.impl());
if (t == 0)
{
t = (ObjectArrayImpl<T>*)ObjectArrayBase::_tryCast(T::clazzInfo(), anotherarray.iptr());
if (t == 0)
{
_copyArray(anotherarray.iptr());
return;
}
}
RObjectArrayImpl<T>::_impl = t;
RObjectArrayImpl<T>::_iptr = t;
RObjectArrayImpl<T>::_impl->addRef();
}
RObjectArrayImpl(const RObjectArrayImpl<T> &array)
: RefHolder<ObjectArrayImpl<T> >()
{
if (array.iptr() == 0)
return;
RObjectArrayImpl<T>::_impl = array.impl();
RObjectArrayImpl<T>::_iptr = array.iptr();
RObjectArrayImpl<T>::impl()->addRef();
}
/**
copy/cast constructor
*/
template <class OT>
upcast_explicit
RObjectArrayImpl(const RefHolder<OT>& other)
: RefHolder<ObjectArrayImpl<T> >()
{
if (other.impl() == 0)
return;
::acdk::lang::Object* o = const_cast< ::acdk::lang::Object*>(other.impl());
ObjectArrayImpl<T>* t = dynamic_cast<ObjectArrayImpl<T>*>(o);
if (t == 0)
{
ObjectArrayBaseImpl* oab = dynamic_cast<ObjectArrayBaseImpl*>(o);
if (oab == 0)
::acdk::lang::ObjectBase::_throwBadCastException();
t = (ObjectArrayImpl<T>*)ObjectArrayBase::_tryCast(T::clazzInfo(), oab);
if (t == 0)
{
_copyArray((ObjectArrayImpl<acdk::lang::RObject>*)other.impl());
return;
}
}
RObjectArrayImpl<T>::_impl = t;
RObjectArrayImpl<T>::_iptr = t;
RObjectArrayImpl<T>::_impl->addRef();
}
/* don't do this, it is too dangerous
RObjectArrayImpl(const ::acdk::lang::dmi::ScriptVar& sv)
: RefHolder<ObjectArrayImpl<T> >()
{
*this = (RObjectArrayImpl<T>) sv.getObjectVar();
}
*/
#ifdef ACDK_CORE_NEED_ROBJECT_CONVERTER
/**
because there is no implizite upcast functionality
*/
operator ::acdk::lang::RObject () { return ::acdk::lang::RObject(*this); }
#endif //ACDK_CORE_NEED_ROBJECT_CONVERTER
template <class OT>
RObjectArrayImpl<T>& operator=(const ObjectArrayImpl<OT> *anotherarray)
{
_forceCompilerCastError(anotherarray);
if (anotherarray == 0)
{
setImpl(0);
return *this;
}
const ObjectArrayImpl<T>* t = dynamic_cast<const ObjectArrayImpl<T> *>(anotherarray);
if (t == 0)
{
t = (ObjectArrayImpl<T>*)ObjectArrayBase::_tryCast(T::clazzInfo(), anotherarray);
if (t == 0)
{
_copyArray(anotherarray);
return;
}
}
setImpl(t);
return *this;
}
RObjectArrayImpl<T>& operator=(const ObjectArrayImpl<T> *anotherarray)
{
setImpl(const_cast<ObjectArrayImpl<T>*>(anotherarray));
return *this;
}
template <class OT>
RObjectArrayImpl<T>& operator=(const RObjectArrayImpl<OT>& array)
{
if (RObjectArrayImpl<T>::_iptr == 0 && array.iptr() == 0)
return *this;
return operator=(array.iptr());
}
RObjectArrayImpl<T>& operator=(NilRef nil)
{
RefHolder<ObjectArrayImpl<T> >::operator=(nil);
return *this;
}
ObjectArrayImpl<T>* operator->() const { return RObjectArrayImpl<T>::getIPtr(); }
//const ObjectArrayImpl<T>* operator->() const { return getIPtr(); }
int length() const { return RObjectArrayImpl<T>::getIPtr()->length(); }
void add(const T& t) { RObjectArrayImpl<T>::getIPtr()->add(t); }
const T& get(int idx) const
{
return RObjectArrayImpl<T>::getIPtr()->get(idx);
}
T& get(int idx)
{
return RObjectArrayImpl<T>::getIPtr()->getref(idx);
}
void set(int idx, T& t)
{
RObjectArrayImpl<T>::getIPtr()->set(idx, t);
}
T& operator[](int idx) const
{
return RObjectArrayImpl<T>::getIPtr()->getref(idx);
}
RObjectArrayImpl<T>* _ref_this() { return this; }
protected:
/// only used to force compiler cast error
void _forceCompilerCastError(const ObjectArrayImpl<T>* optr)
{}
void setImpl(const ObjectArrayImpl<T>* optr)
{
if (RObjectArrayImpl<T>::_iptr == optr)
return;
if (RObjectArrayImpl<T>::_iptr != 0)
RObjectArrayImpl<T>::_impl->releaseRef();
RObjectArrayImpl<T>::_impl = const_cast<ObjectArrayImpl<T>*>(optr);
RObjectArrayImpl<T>::_iptr = const_cast<ObjectArrayImpl<T>*>(optr);
if (RObjectArrayImpl<T>::_iptr != 0)
RObjectArrayImpl<T>::_impl->addRef();
}
protected:
template <class OT>
void _copyArray(const RObjectArrayImpl<OT>& array)
{
_copyArray(array.iptr());
}
template <class OT>
void _copyArray(ObjectArrayImpl<OT>* oim)
{
if (oim == 0) {
if (RObjectArrayImpl<T>::_iptr != 0)
RObjectArrayImpl<T>::impl()->releaseRef();
RObjectArrayImpl<T>::_impl = 0;
RObjectArrayImpl<T>::_iptr = 0;
return;
}
if (oim->length() == 0)
{
ObjectArrayImpl<T>* noa = new ObjectArrayImpl<T>(0);
RObjectArrayImpl<T>::setImpl(noa);
return;
}
if (oim->get(0).impl())
{
T testref = (T)(oim->get(0)); // if OT and T not = compatible, a BadCastException will thrown here
if ((void*)testref.iptr() != (void*)oim->get(0).iptr())
{
int nsize = oim->length();
ObjectArrayImpl<T>* noa = new ObjectArrayImpl<T>(nsize);
for (int i = 0; i < nsize; i++) {
noa->set(i, (T)oim->get(i));
}
setImpl(noa);
return;
}
}
//## may not correctly, especially if virtual base classes are involved
ObjectArrayImpl<T>* noa = reinterpret_cast<ObjectArrayImpl<T>*>(oim);
if (RObjectArrayImpl<T>::_iptr == noa)
return;
if (RObjectArrayImpl<T>::_iptr != 0)
RObjectArrayImpl<T>::impl()->releaseRef();
RObjectArrayImpl<T>::_impl = noa;
RObjectArrayImpl<T>::_iptr = noa;
if (RObjectArrayImpl<T>::_iptr != 0) {
RObjectArrayImpl<T>::impl()->addRef();
}
}
};
#endif //acdk_lang_ObjectArrayBase_h |