#ifdef __DCL_INTERNAL__

__DCL_BEGIN_NAMESPACE

#ifdef __COMPILE_StringArray__
    #define THIS_NAME               __szStringArray_h__
    #define THIS_VALUE              __T("dcl/__ARRAY.h:String")
    #define ARRAY_T                 StringArray
    #define ELEMENT_T                   String
    #define CONST_ELEMENT_REF   const String&
    #define HAVE_CONSTRUCTOR    1
#elif defined(__COMPILE_ByteStringArray__)
    #define THIS_NAME               __szByteStringArray_h__
    #define THIS_VALUE              __T("dcl/__ARRAY.h:ByteString")
    #define ARRAY_T                 ByteStringArray
    #define ELEMENT_T                   ByteString
    #define CONST_ELEMENT_REF   const ByteString&
    #define HAVE_CONSTRUCTOR    1
#elif defined(__COMPILE_PointerArray__)
    #define THIS_NAME               __szPointerArray_h__
    #define THIS_VALUE              __T("dcl/__ARRAY.h:void*")
    #define ARRAY_T                 PointerArray
    #define ELEMENT_T                   void*
    #define CONST_ELEMENT_REF   const void*
    #define HAVE_CONSTRUCTOR    0
#elif defined(__COMPILE_StringStringArray__)
    #define THIS_NAME               __szStringStringArray_h__
    #define THIS_VALUE              __T("dcl/__ARRAY.h:StringString")
    #define ARRAY_T                 StringStringArray
    #define ELEMENT_T                   StringString
    #define CONST_ELEMENT_REF   const StringString&
    #define HAVE_CONSTRUCTOR    1
#endif

#if __DCL_HAVE_THIS_FILE__
    static const char_t THIS_NAME[] = THIS_VALUE;
    #undef __THIS_FILE__
    #define __THIS_FILE__ THIS_NAME
#endif

/**
 * template class Array의 DSO 호환성을 제공한다.
 * <p>C++의 template class는 해당 코드를 사용하기 전에는 실제 이진 코드를 생성하지 않으므로,
 * DSO(so, DLL)와 DSO, 또는 실행파일에서 객체를 주고받을 수 없다.<p>
 * <p>이 클래스는 DSO의 이러한 문제를 해결하며,
 * 포함파일은 <code><dcl/Array.h></code>이다.</p>
 * <p>이 코드를 사용하는 클래스는 다음과 같다.</p>
 * <ul>
 *      <li>class DCLCAPI StringArray</li>
 *      <li>class DCLCAPI ByteStringArray</li>
 *      <li>class DCLCAPI PointerArray</li>
 * </ul>
 *
 * @see Array
 */
class DCLCAPI ARRAY_T : public Object
{
    DECLARE_CLASSINFO(ARRAY_T)
public:
    virtual String toString() const;

public:
    typedef const ELEMENT_T*    ConstIterator;
    typedef ELEMENT_T*          Iterator;

public:
     virtual ~ARRAY_T();
    // ~ARRAY_T();
    ARRAY_T(size_t _size = 0);
    ARRAY_T(const ARRAY_T& _src);
    const ARRAY_T& operator=(const ARRAY_T& _src);

    ConstIterator begin() const;
    ConstIterator end() const;
    Iterator begin();
    Iterator end();

    void clear();
    void shrink();
    void resize(size_t _size);

    Iterator insert(Iterator _pos, CONST_ELEMENT_REF _element);
    ARRAY_T& insert(size_t _index, CONST_ELEMENT_REF _element);
    ARRAY_T& add(CONST_ELEMENT_REF _element);
    ARRAY_T& add(const ARRAY_T& _src);

    Iterator find(CONST_ELEMENT_REF _element);

    Iterator erase(Iterator _pos);                  
    Iterator erase(Iterator _first, Iterator _last);
    ARRAY_T& erase(size_t _index);
    ARRAY_T& erase(size_t _index, size_t _size);

    size_t index(Iterator _pos) const;
    size_t size() const;
    bool isEmpty() const;

    ELEMENT_T& operator[](size_t _index);
    ELEMENT_T operator[](size_t _index) const;
    ELEMENT_T* data() const;

    size_t size(ConstIterator _first, ConstIterator _last) const;
    size_t size(Iterator _first, Iterator _last) const;

protected:
    ELEMENT_T*  __pData;

    struct Buffer
    {
        size_t  __size;
        size_t  __maxSize;
        ELEMENT_T* data() { return (ELEMENT_T*) (this + 1); }
    } ;
    
    Buffer* __buf() const { return (Buffer*) __pData -1; }
    size_t& __size() const { return __buf()->__size; }
    size_t& __maxSize() const { return __buf()->__maxSize; }

#if HAVE_CONSTRUCTOR
    void constructElements(ELEMENT_T* _pElements, size_t _size);
    void destructElements(ELEMENT_T* _pElements, size_t _size);
#endif
};

//////////////// Inline ////////////////////

inline
ARRAY_T::ConstIterator
ARRAY_T::begin() const
{
    return (const ELEMENT_T*) __pData;
}

inline
ARRAY_T::ConstIterator
ARRAY_T::end() const
{
    return (const ELEMENT_T*) __pData + size();
}

inline
ARRAY_T::Iterator
ARRAY_T::begin()
{
    return __pData;
}

inline
ARRAY_T::Iterator
ARRAY_T::end()
{
    return __pData + size();
}

inline
ARRAY_T&
ARRAY_T::add(CONST_ELEMENT_REF _element)
{
    return insert(size(), _element);
}

inline
ARRAY_T::Iterator
ARRAY_T::erase(Iterator _pos)
{
    __DCL_ASSERT_PARAM(begin() <= _pos);
    __DCL_ASSERT_PARAM(_pos < end());
#if 0
    erase(_pos -begin(), 1);
    return _pos;
#endif
    size_t index = _pos -begin();
    erase(index, 1);
    return __pData + index;
}

inline
ARRAY_T::Iterator
ARRAY_T::erase(Iterator _first, Iterator _last)
{
    __DCL_ASSERT_PARAM(begin() <= _first);
    __DCL_ASSERT_PARAM(_last <= end());
    erase(_first -begin(), _last -_first);
    return _first;
}

inline
ARRAY_T&
ARRAY_T::erase(size_t _index)
{
    __DCL_ASSERT_PARAM(_index < size());
    return erase(_index, 1);
}

inline
size_t
ARRAY_T::index(Iterator _pos) const
{
    __DCL_ASSERT_PARAM(__pData <= _pos);
    return _pos -__pData;
}

inline
size_t
ARRAY_T::size() const
{
    return __buf()->__size;;
}

inline
bool
ARRAY_T::isEmpty() const
{
    return size() == 0;
}

inline
ELEMENT_T&
ARRAY_T::operator[] (size_t _index)
{
    __DCL_ASSERT_PARAM(_index < size());
    return __pData[_index];
}

inline
ELEMENT_T
ARRAY_T::operator[] (size_t _index) const
{
    __DCL_ASSERT_PARAM(_index < size());
    return __pData[_index];
}

inline
ELEMENT_T*
ARRAY_T::data() const
{
    return __pData;
}

inline
size_t
ARRAY_T::size(ConstIterator _first, ConstIterator _last) const
{
    __DCL_ASSERT_PARAM(_first <= _last);
    return _last -_first;
}

inline
size_t
ARRAY_T::size(Iterator _first, Iterator _last) const
{
    __DCL_ASSERT_PARAM(_first <= _last);
    return _last -_first;
}

#if __DCL_HAVE_THIS_FILE__
    #undef __THIS_FILE__
    #define __THIS_FILE__   __T(__FILE__)
#endif

#undef THIS_NAME
#undef THIS_VALUE
#undef ARRAY_T
#undef ELEMENT_T
#undef CONST_ELEMENT_REF
#undef HAVE_CONSTRUCTOR

__DCL_END_NAMESPACE

#endif          // __DCL_INTERNAL__