C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[509] DynamicArray 를 VC에서도 사용하자 ^^...
nicekr.황경록 [mpbox] 8496 읽음    2005-10-10 15:08
빌더의 Syndyn.h 파일에 포함되어 있는 DynamicArray 를 VC 등에서 사용할 수 있도록
Delphi 및 Builder 와의 Dependencies 를 제거하였습니다.

대충 테스트는 해봤는데 믿을 수가(?).... ^^:::::

혹시 잘못된 부분이 있다면 알려주세요 ^^....

DynamicArray.h 파일을 만들어서 paste 하시고 저장 ^^ 그리고 사용하시면 됩니다.

--------

#if !defined(DYNAMICARRAY_H)
#define DYNAMICARRAY_H

/////////////////////////////////////////////////////////////////////////////
//// Dynamic Array

#include <stdlib.h> // for  malloc, free

/////////////////////////////////////////////////////////////////////////////
// start of namespace VCBuilder
namespace VCBuilder
{

class DynArrayException
{};

/////////////////////////////////////////////////////////////////////////////
//// Exception thrown when 'out-of-range' of an DynamicArray

class DynArrayOutOfRange : public DynArrayException
{
public:
    DynArrayOutOfRange(int index, int count)
        : m_Index(index), m_Count(count)
    {

    }

    int m_Index;
    int m_Count;
};

/////////////////////////////////////////////////////////////////////////////
//// Exceptions thrown when 'accessing a Null' DynamicArray

class DynArrayNullData : public DynArrayException
{};

template <class T> class DynamicArray;

/////////////////////////////////////////////////////////////////////////////
// NOTE: The following two template functions are used to determine the number of
//       dimensions in a dynamic array. This approach relies on the fact that the
//       resolution mechanism will use the first version of 'GetDimensions' as long
//       as we're dealing with a DynamicArray Of DynamicArray.

template <class T> inline int
GetDimensions(const DynamicArray<T>& t) { return t.DimCount();}

template <class T> inline int
GetDimensions(const T&) { return 0;}

/////////////////////////////////////////////////////////////////////////////
// DynamicArray
// ============
// Template providing Delphi style Dynamic Array support in C++

template<class T> class DynamicArray
{
public:
    DynamicArray();
    ~DynamicArray();

    // Construct from another DynArray
    DynamicArray(const DynamicArray<T>& src);

    // Assign data from another DynArray
    DynamicArray& operator=(const DynamicArray<T>& src);

    // Subscript operator to access data
    T& operator[](int index);
    T  operator[](int index) const;

    // Comparison (NOTE: only pointer is compared)
    bool operator == (const DynamicArray<T> &other) const;

    // Make copy of data (non-refcounted)
    DynamicArray<T> Copy() const;
    void            Copy(DynamicArray<T> &dst) const;
    DynamicArray<T> CopyRange(int startIndex, int count) const;
    void            CopyRange(DynamicArray<T> &dst, int startIndex, int count) const;

    // High and low bounds of DynArray
    int             get_high() const;
    int             get_low() const;

    // Set/get length of DynArray
    int             get_length() const;
    void            set_length(int l);

    #if defined(DEBUG)
    int             get_refCount() const;
    #endif

    #if defined(DEBUG)
    __property    int RefCount = {read=get_refCount};
    #endif

    // Returns number of dimensions of dynamic array
    // NOTE: Used with 'GetDimensions' template functions above.
    //       If T happens to be another DynamicArray, the compiler
    //       resolves the call to the first version of GetDimensions.
    //       Otherwise, it defaults to the second version.
    //
    static    int    DimCount()
    {
      return 1 + GetDimensions(*((T*)(0)));
    }

protected:
    void        IncRefCount();
    void        DecRefCount();
    static T*    AllocData(int count);
    void        SetData(T* t);
    void        FreeData();

private:
    T*    Data;
};

// Operator used in placement syntax
//
inline void* operator new(size_t size, char *p)
{
    return p;
}

template <class T>
DynamicArray<T>::DynamicArray() : Data(0)
{}

template <class T>
DynamicArray<T>::~DynamicArray()
{
    DecRefCount();
    Data = 0;
}

template <class T>
DynamicArray<T>::DynamicArray(const DynamicArray<T>& src) : Data(src.Data)
{
    IncRefCount();
}

template <class T> DynamicArray<T>&
DynamicArray<T>::operator =(const DynamicArray<T>& src)
{
    if (&src != this)
    {
        DecRefCount();
        Data = src.Data;
        IncRefCount();
    }
    return *this;
}

template <class T> T&
DynamicArray<T>::operator[](int index)
{
    if (index < 0 || index >= this->get_length())
        throw DynArrayOutOfRange(index, this->get_length());
    if (!Data)
        throw DynArrayNullData();

    return *(Data + index);
}

template <class T> T
DynamicArray<T>::operator[](int index) const
{
    if (index < 0 || index >= this->get_length())
        throw DynArrayOutOfRange(index, this->get_length());
    if (!Data)
        throw DynArrayNullData();

    return *(Data + index);
}

template <class T> bool
DynamicArray<T>::operator == (const DynamicArray<T> &other) const
{
    return Data == other.Data;
}

template <class T> DynamicArray<T>
DynamicArray<T>::Copy() const
{
    DynamicArray<T> cpy;
    Copy(cpy);
    return cpy;
}

template <class T> void
DynamicArray<T>::Copy(DynamicArray<T>& dst) const
{
    // Update length of destination if necessary
    int l = (*this).get_length();
    if (dst.get_length() != l)
        dst.get_length() = l;

    // Copy data over
    for (int i=0; i<l; i++)
        dst[i] = (*this)[i];
}

template <class T> DynamicArray<T>
DynamicArray<T>::CopyRange(int startIndex, int  count) const
{
    DynamicArray<T> cpy;
    CopyRange(cpy, startIndex, count);
    return cpy;
}

template <class T> void
DynamicArray<T>::CopyRange(DynamicArray<T>& dst, int startIndex, int count) const
{
    // Resize destination if necessary
    // (Could optimize to only resize if too small!! However, Delphi always resizes)
    if (dst.get_length() != count)
        dst.get_length() = count;
    // Copy data over
    for (int i=0; i<count; i++)
        dst[i] = (*this)[startIndex+i];
}

template <class T> int
DynamicArray<T>::get_high() const
{
    return Data ? get_length()-1 : 0;
}

template <class T> int
DynamicArray<T>::get_low() const
{
    return 0;
}

template <class T> int
DynamicArray<T>::get_length() const
{
    int *p_i = (int*)Data;
    return Data ? *(p_i-1) : 0;
}

template <class T> void
DynamicArray<T>::set_length(int l)
{
    // Allocate space for new length
    T* p = AllocData(l);

    // Copy data other if necessary
    if (p)
    {
        // Compute length of data to be copied
        int copyLen = (*this).get_length();
        if (l < copyLen)
            copyLen = l;

        // Copy data
        while (copyLen-- > 0)
            p[copyLen] = (*this)[copyLen];
    }   

    // Assign new data...
    SetData(p);
}

#if defined(DEBUG)
template <class T> int
DynamicArray<T>::get_refCount() const
{
int* p_i = (int*)Data;
return Data ? *(p_i-2) : 0;
}
#endif;

template <class T> void
DynamicArray<T>::IncRefCount()
{
    if (Data)
    {
        int* p_i = (int*)Data;
        int &refcount = *(p_i-2);
        refcount++;
    }
}

template <class T> void
DynamicArray<T>::DecRefCount()
{
    if (Data)
    {
        int* p_i = (int*)Data;
        int &refcount = *(p_i-2);
        if (--refcount == 0)
            FreeData();
    }
}

template <class T> T*
DynamicArray<T>::AllocData(int count)
{
    // NOTE: Length of zero results in a null data pointer
    if (count == 0)
        return 0;

    // Allocate memory: Array members + 2 integers (refcount and length)
    //  NOTE: Don't use new to be compatible with Pascal memory manager
    /* int *pi = (int*)new char[sizeof(T)*count + 2*sizeof(int)]; */
    int *pi = (int*)malloc(sizeof(T)*count + 2*sizeof(int));

    // Initialize refcount + length
    *pi++ = 1;         // RefCount initialized to 1
    *pi++ = count;     // Set length of array

    T *pt = (T*)pi;
    char *pc = (char*)pi;
    T *p  = (T*)pc;

    // Invoke constructor for each member of array
    while (count-- > 0)
    {
        new  (pc) T;
        pc = (char*)(++p);
    }

    // Return pointer
    return pt;
}

template <class T> void
DynamicArray<T>::SetData(T* t)
{
    if (Data != t)
    {
        DecRefCount();
        Data = t;
    }
}

template <class T> void
DynamicArray<T>::FreeData()
{
    if (Data)
    {
        // Invoke destructor on each element
        T*  p = Data;
        int l = (*this).get_length();

        for (; l-- > 0; p++) {
            if (p)    /* Not necessary but shuts off compiler warning */
                p->~T();
        }

        // Free chunk of memory
        // NOTE: Don't use delete []p_i to be compatible with Delphi's memory manager
        int* p_i = (int*)Data;
        p_i -= 2;
        free(p_i);
        Data = 0;
    }
}

// Low overhead (include-wise) for RAII of newed objects.
// NOTE: This is mainly used by WebServices code generation currently
template <typename T>
class sPointer {
    T* ptr;
public:
    sPointer()     : ptr(0) {}
    sPointer(T* p) : ptr(p) {}
    ~sPointer()     { delete ptr; }
    T* operator& () { return ptr; }
    T* operator->() { return ptr; }
private:
    sPointer(const sPointer<T>&);
    const sPointer<T>& operator=(const sPointer<T>&);
};

} // end of namespace
/////////////////////////////////////////////////////////////////////////////

#endif
nicekr.황경록 [mpbox]   2005-10-10 15:24 X
VCBuilder::DynamicArray<int> arInt;
이런식으로 선언하시면 되구요.

arInt.set_length(100); <- 초기화
arInt[0] = 3454; <- 사용
사용이 끝난 후엔...
arInt.set_length(0); <- 이건 안해주셔도 무방~
nicekr.황경록 [mpbox]   2005-10-10 15:25 X
빌더쓰다 VC 쓰면 -_- 뭐 대략 C++컴파일러니까 별 관계는 없기는 한데...
뭐 ^^ 그냥 그냥 ^^ 빌더에서 쓰던걸 어떻게든 VC에서도 사용하고 싶다는 ㅋㅋ
소리바람.OJ [phonon]   2005-11-15 18:20 X
STL과 DynamicArray 둘다 Template을 이용한 것인데,  다른 점이 무엇인가요?
원론적인 문제에 약하기에 부탁드립니다.
nicekr.황경록 [mpbox]   2005-11-20 21:48 X
STL은 말 그대로 Standard Template Library입니다. 일반적인 검증이 되어 다수의(?)사람들이 사용하는것이고 Template는 C++에서 추가된 것으로 결국 STL도 Template으로 만든 것이죠. @@사실 저도 원론이 약해서요 ^^''' 프로그래밍이란게 그 구현방법과 범주가 매우넓다보니 ^^... 어떤걸 만들어야할때 그 결과는 동일하지만 그 구현방법은 이루다 말할수 없겠죠. 즉, Template라는 방법론으로 DynamicArray라는 이름으로 구현해서 사용하나 STL이나 Boost 그리고 STLPort 또는 명석한 프로그래머가 만들어 놓은 Template 클래스를 사용하나... 뭐 자신이 알고 있는 응용가는한 것으로 사용하면 되지않나 싶습니다 ^^;;

+ -

관련 글 리스트
509 DynamicArray 를 VC에서도 사용하자 ^^... nicekr.황경록 8496 2005/10/10
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.