/*==================================================================
=  文件名  : TArray类定义文件                                       
=  主要功能: 提供对各种基本数据类型、结构的动态数组操作          
=  修改日期: 2004-10-5                                          
=  作者    : shen beide
====================================================================*/

#if !defined(_TYPEARRAY_H)
#define _TYPEARRAY_H

#include <stdio.h>
#include <stdlib.h>

#include "PubHeader.h"

#ifdef _DLL_PROJECT
template<class TYPE>class CLASS_EXPORT TArray
#else
template<class TYPE>class TArray
#endif
{
private:
    long    cur_array_size;
    TYPE*   array;

    long    m_block_size;
    long    max_array_size;

    TYPE    ErrData;

public:
	//////////////////////////////////////
    TArray(long initsize=0, long block_size=50)
	{
	    m_block_size=block_size;

	    if (initial_(initsize+block_size))
        {
            cur_array_size=initsize;
        }
	}
    
	//////////////////////////////////////
   ~TArray()
	{
	    if (array!=NULL) free(array);
	}

	//////////////////////////////////////
    long GetSize()
	{
	    return cur_array_size;
	}

    void SetSize(long num, TYPE& initialData)
    {
        RemoveAll();
        for(int i=0;i<num;i++)
        {
            Add(initialData);
        }
    }
    
	//////////////////////////////////////
    void RemoveAll()
	{
	    free(array); 
	    initial_(m_block_size);
	}

	//////////////////////////////////////
    long Add(TYPE& data)                    // return index of the new data
	{
	    if (cur_array_size+1>max_array_size) ReSizeArray(1);
	    array[cur_array_size++]=data;
	    return cur_array_size-1;
	}

	//////////////////////////////////////
    long InsertAt(long Index,TYPE& data)    // return index of the new data
	{
        if (Index<0) Index=0;
        if (Index>=cur_array_size) Index=cur_array_size;                               //
        
        if (cur_array_size+1>max_array_size) ReSizeArray();

	    for(long i=cur_array_size;i>Index;i--) array[i]=array[i-1];

	    array[Index]=data;                           
	    cur_array_size++;
	    return Index;
	}

	//////////////////////////////////////
    bool RemoveAt(long Index,TYPE* szdata=NULL)
	{
        if ( (Index>=0)&&(Index<cur_array_size) )
        {
            if (szdata) *szdata=array[Index];
            
            for(long i=Index;i<cur_array_size-1;i++) array[i]=array[i+1];
            
            cur_array_size--;
            ReSizeArray(-1);
            
            return true;
        }
        return false;
	}
    bool RemoveTail(TYPE* szdata=NULL)
    {
        if (cur_array_size>=0)
        {
            return RemoveAt(cur_array_size-1,szdata);
        }
        return false;
    }
    
	//////////////////////////////////////
    bool GetAt(long Index,TYPE& data)
	{
        if ( (Index>=0)&&(Index<cur_array_size) )
        {
            data=array[Index];
            return true;
        }
        return false;
    }
    bool GetTail(TYPE& data)
    {
        if (cur_array_size>0)
        {
            data=array[cur_array_size-1];
            return true;
        }
        return false;
    }
    
    TYPE& operator[](long Index)
    {
	    if ( (Index>=0)&&(Index<cur_array_size) )
        {
            return array[Index];
        }
        else
        {
            return ErrData;
        }
    }
    
	//////////////////////////////////////
    int Find(TYPE& data)
	{
	    for(long i=0;i<cur_array_size;i++) 
	    {
		    if (memcmp(&array[i],&data,sizeof(TYPE))==0) return i;
//		    if (array[i]==data) return i;
	    }
	    return -1;
	}

	//////////////////////////////////////
    bool SetAt(long Index,TYPE& data)
	{
	    if (Index<cur_array_size)
	    {
		    array[Index]=data;
		    return true;
	    }
	    return false;
	}

protected:
	//////////////////////////////////////
    bool initial_(long size)
	{
	    long m_memLen;
	    m_memLen=size*sizeof(TYPE);

	    array=(TYPE *)malloc(m_memLen);  // first get a memory
	    cur_array_size=0;
	    max_array_size=size;

        return (array!=NULL)? true:false;
	}

	//////////////////////////////////////
    void ReSizeArray(int mode=1)
	{
	    long m_memLen;

	    if (mode>0) //ADD
	    {
		    m_memLen=(max_array_size+m_block_size)*sizeof(TYPE);
		    array=(TYPE *)realloc(array,m_memLen);
		    max_array_size+=m_block_size;
	    }
	    else // Reduse
        {
		    if (max_array_size-m_block_size-m_block_size>cur_array_size)
		    {
			    m_memLen=(max_array_size-m_block_size)*sizeof(TYPE);
			    array=(TYPE *)realloc(array,m_memLen);
			    max_array_size-=m_block_size;
            }
	    }
	}
};


///////////////////////////////////////////////
#ifdef _DLL_PROJECT
template<class TYPE>class CLASS_EXPORT TArray_
#else
template<class TYPE>class TArray_
#endif
{
private:
    typedef struct ArrayNode
    {
        TYPE  Data;
        DWORD wParam;       // 带内部数据
        
    } Node;
    
    long    cur_array_size;
    Node*   array;

    long    m_block_size;
    long    max_array_size;

    TYPE    ErrData;

public:
	//////////////////////////////////////
    TArray_(long initsize=0, long block_size=50)
	{
	    m_block_size=block_size;

	    if (initial_(initsize+block_size))
        {
            cur_array_size=initsize;
        }
	}
    
	//////////////////////////////////////
   ~TArray_()
	{
	    if (array!=NULL) free(array);
	}

	//////////////////////////////////////
    long GetSize()
	{
	    return cur_array_size;
	}

    void SetSize(long num, TYPE& initialData,DWORD param=0)
    {
        RemoveAll();
        for(int i=0;i<num;i++)
        {
            Add(initialData,param);
        }
    }
    
	//////////////////////////////////////
    void RemoveAll()
	{
	    free(array); 
	    initial_(m_block_size);
	};

	//////////////////////////////////////
    long  Add(TYPE& data, DWORD param=0)
	{
	    if (cur_array_size+1>max_array_size) ReSizeArray(1);
	    array[cur_array_size].Data  =data;
        array[cur_array_size].wParam=param;
        cur_array_size++;
	    return cur_array_size-1;
	};

	//////////////////////////////////////
    long InsertAt(long Index,TYPE& data, DWORD param=0)
	{
        if (Index<0) Index=0;

	    if (cur_array_size+1>max_array_size) ReSizeArray();

	    for(long i=cur_array_size;i>Index;i--) array[i]=array[i-1];

	    if (Index>=cur_array_size) Index=cur_array_size;                               //
	    array[Index].Data  =data;                           
        array[Index].wParam=param;                           
        cur_array_size++;
	    return Index;
	}

	//////////////////////////////////////
    bool RemoveAt(long Index,TYPE* szdata=NULL, DWORD* lpParam=NULL)
	{
        if ( (Index>=0)&&(Index<cur_array_size) )
        {
            if (szdata ) *szdata =array[Index].Data;
            if (lpParam) *lpParam=array[Index].wParam;
            
            for(long i=Index;i<cur_array_size-1;i++) array[i]=array[i+1];
            cur_array_size--;

            ReSizeArray(-1);
            
            return true;
        }
        return false;
	}
    bool RemoveTail(TYPE* szdata=NULL, DWORD* lpParam=NULL)
    {
        if (cur_array_size>0)
        {
            return RemoveAt(cur_array_size-1,szdata,lpParam);
        }
        return false;
    }
    
	//////////////////////////////////////
    bool GetAt(long Index,TYPE& data, DWORD* lpParam=NULL)
	{
        if ( (Index>=0)&&(Index<cur_array_size) )
        {
            data=array[Index].Data;
            if (lpParam) *lpParam=array[Index].wParam;
            return true;
        }
        return false;
    }
    bool GetTail(TYPE& data, DWORD* lpParam=NULL)
    {
        if (cur_array_size>0)
        {
            data=array[cur_array_size-1].Data;
            if (lpParam) *lpParam=array[cur_array_size-1].wParam;
            return true;
        }
        return false;
    }
    
    TYPE& operator[](long Index)
    {
	    if ( (Index>=0)&&(Index<cur_array_size) )
        {
            return array[Index].Data;
        }
        else
        {
            return ErrData;
        }
    }
    
	//////////////////////////////////////
    int Find(TYPE& data)
	{
	    for(long i=0;i<cur_array_size;i++) 
	    {
		    if (memcmp(&array[i].Data,&data,sizeof(TYPE))==0) return i;
	    }
	    return -1;
	}

	//////////////////////////////////////
    bool SetAt(long Index,TYPE& data, DWORD param=0)
	{
	    if (Index<cur_array_size)
	    {
		    array[Index].Data  =data;
            array[Index].wParam=0;
		    return true;
	    }
	    return false;
	}

protected:
	//////////////////////////////////////
    bool initial_(long size)
	{
	    long m_memLen;
	    m_memLen=size*sizeof(Node);

	    array=(Node*)malloc(m_memLen);  // first get a memory
	    cur_array_size=0;
	    max_array_size=size;

        return (array!=NULL)? true:false;
	}

	//////////////////////////////////////
    void ReSizeArray(int mode=1)
	{
	    long m_memLen;

	    if (mode>0) //ADD
	    {
		    m_memLen=(max_array_size+m_block_size)*sizeof(Node);
		    array=(Node*)realloc(array,m_memLen);
		    max_array_size+=m_block_size;
	    }
	    else // Reduse
        {
		    if (max_array_size-m_block_size-m_block_size>cur_array_size)
		    {
			    m_memLen=(max_array_size-m_block_size)*sizeof(Node);
			    array=(Node*)realloc(array,m_memLen);
			    max_array_size-=m_block_size;
            }
	    }
	}
};


#endif
