/*==================================================================
=  文件名  :                                       
=  主要功能:           
=  修改日期: 2005-10                                            
=  作者    : shen beide
====================================================================*/

#if !defined(_STRINGARRAY_H)
#define _STRINGARRAY_H

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

#include "PubHeader.h"
#include "otstr.h"
#include "ObArray.h"

//////////////////////////////////////////
#ifdef _DLL_PROJECT
class CLASS_EXPORT StringArray
#else
class StringArray
#endif
{
public:
    StringArray();
    virtual ~StringArray();

    int  GetSize();
    void SetSize(long size, char* lpstring="", DWORD param=0);

    void Add(char* lpstring, DWORD param=0);
    void Add(OTSTR& str, DWORD param=0);
    void InsertAt(int nIndex,char* lpstring, DWORD param=0);
    void InsertAt(int nIndex,OTSTR& str, DWORD param=0);
    
	OTSTR& GetAt  (int nIndex, DWORD* lpParam=NULL);
    OTSTR& GetTail(DWORD* lpParam=NULL);

    void RemoveAt(int nIndex);
    void RemoveTail();
    
    int  Find(char* lpstring, bool bcase, DWORD* lpParam=NULL);   // return Index,  -1 mean not found
    int  Find(OTSTR& str,     bool bcase, DWORD* lpParam=NULL);   // return Index,  -1 mean not found
    
    void RemoveAll();

    void   setName(char* szName);
    OTSTR& getName();

protected:
    ObArray m_ObArray;
    OTSTR   m_strRet;
    
protected:
    CNode* Add_(char* lpstring, DWORD param);
    CNode* GetAt_(int nIndex);

    virtual char* malloc_(long  size);  
    virtual void  free_  (char* pbuffer);
};


/////////////////////////////////////////////////////////////////////////////
template<class VALUETYPE>
class TStringMap : protected StringArray
{
public:
    TStringMap() 
    { 
        m_bCaseSensitive=true; 
        m_NullVal       =0;
    }
    virtual ~TStringMap() 
    { 
       RemoveAll(); 
    }

    void setNullVal(VALUETYPE val)  { m_NullVal=val; }

    void setCaseSensitive(bool bcase) 
    {
        m_bCaseSensitive=bcase;
    }

    int GetSize()
    {
        return StringArray::GetSize();
    }
    
    bool AddKey(char* szkey, VALUETYPE newValue)
    {
        int n=Find(szkey,m_bCaseSensitive);
        if (n>=0) return false;

        StringArray::Add(szkey,(DWORD)newValue);
        return true;
    }

    bool AddKey(OTSTR& strKey, VALUETYPE newValue)
    {
        AddKey(strKey.GetBuffer(),(DWORD)newValue);
    }

    bool setValue(char* szkey, VALUETYPE newValue)
    {
        CNode_* pNode;
        int n=Find(szkey,m_bCaseSensitive);
        if (n>=0)
        {
            pNode=StringArray::GetAt_(n);
            pNode->getparam()=newValue;
        }
        return false;
    }

    bool setValue(OTSTR& strkey, VALUETYPE newValue)
    {
        return setValue(strkey.GetBuffer(),newValue);
    }

    bool Lookup(char* szkey, VALUETYPE& rValue)
    {
        DWORD param;
        int n=Find(szkey,m_bCaseSensitive,&param);
        if (n>=0) 
        {
            rValue=(VALUETYPE)param;
            return true;
        }
        return false;
    }
    bool Lookup(OTSTR& strKey, VALUETYPE& rValue)
    {
        return Lookup(strKey.GetBuffer(),rValue,m_bCaseSensitive);
    }

    OTSTR& GetAt (int nIndex, VALUETYPE* rValue=NULL)
    {
        OTSTR str;
        DWORD param;
        StringArray::GetAt(nIndex,&param);
        if (rValue) 
        {
            if ( (nIndex>=0)&&(nIndex<GetSize()) )
              *rValue=(VALUETYPE)param;
            else
              *rValue=m_NullVal;
        }
        return StringArray::m_strRet;
    }
    
    VALUETYPE& operator[](char* szkey)
    {
        CNode_* pNode;
        int n=Find(szkey,m_bCaseSensitive);
        if (n>=0)
            pNode=StringArray::GetAt_(n);
          else
            pNode=StringArray::Add_(szkey,m_NullVal);   // it doesn't exist, add a new
        return (VALUETYPE&)(pNode->getparam());
    }
    
    VALUETYPE& operator[](OTSTR& strkey)
    {
        CNode_* pNode;
        int n=Find(strkey,m_bCaseSensitive);
        if (n>=0)
            pNode=StringArray::GetAt_(n);
          else
            pNode=StringArray::Add_(strkey,m_NullVal);   // it doesn't exist, add a new
        return (VALUETYPE&)(pNode->getparam());
    }

    void RemoveKey(char* szkey)
    {
        int n=Find(szkey,m_bCaseSensitive);
        if (n>=0)
        {
            StringArray::RemoveAt(n);
        }
    }
    
    void RemoveKey(OTSTR& strKey)
    {
        RemoveKey(strKey.GetBuffer());
    }

    void RemoveAt(int nIndex)
    {
        StringArray::RemoveAt(nIndex);
    }
    
    void RemoveAll()
    {
        StringArray::RemoveAll();        
    }

    void setName(char* szName)
    {
        StringArray::setName(szName);
    }
    
    OTSTR& getName()
    {
        return StringArray::getName();
    }
    
    
private:
    bool        m_bCaseSensitive;
    VALUETYPE   m_NullVal;
};


/////////////////////////////////////////////////////////////////////////////
class CString2Map: public TName
{
public:
    CString2Map();
    virtual ~CString2Map();
    
    int  GetSize();

    void setCaseSensitive(bool bcase);
    
    bool AddKey(char*  szkey,  char*  szVal,  DWORD Valparam=0);
    bool AddKey(OTSTR& strkey, OTSTR& strVal, DWORD Valparam=0);
    
    bool Lookup(char*  szkey,  char** szRetVal=NULL, DWORD* pValParam=NULL);
    bool Lookup(OTSTR& strkey, char** szRetVal=NULL, DWORD* pValParam=NULL);
    bool Lookup(char*  szkey,  OTSTR& strRetVal, DWORD* pValParam=NULL);
    bool Lookup(OTSTR& strkey, OTSTR& strRetVal, DWORD* pValParam=NULL);

    OTSTR& GetAt(int nIndex, char** szVal=NULL, DWORD* pValParam=NULL);
    OTSTR& GetAt(int nIndex, OTSTR& strVal, DWORD* pValParam=NULL);

    void RemoveKey(char* szkey);
    void RemoveKey(OTSTR& strKey);

    void RemoveAt(int nIndex);
        
    void RemoveAll();
    
private:
    bool            m_bCaseSensitive;
    
    StringArray     m_strKeyList;
    StringArray     m_strValList;

    OTSTR           m_strRet;
};

//////////////////////////////////////////////
//////////////////////////////////////////////
// OtstrArray: 用OTSTR保存数据,速度稍慢
//             但可修改串数组中的内容

#ifdef _DLL_PROJECT
class CLASS_EXPORT OtstrArray
#else
class OtstrArray
#endif
{
public:
    OtstrArray(int size=0, char* lpstring="");
    virtual ~OtstrArray();
    
    int  GetSize();
    void SetSize(int size, char* lpstring="");
    
    void Add(char* lpstring, DWORD param=0);
    void Add(OTSTR& str, DWORD param=0);
    void InsertAt(int nIndex,char* lpstring, DWORD param=0);
    void InsertAt(int nIndex,OTSTR& str, DWORD param=0);
    
    int  Find(char* lpstring, bool bcase, DWORD* lpParam=NULL);   // return Index,  -1 mean not found

    OTSTR& GetAt(int nIndex, DWORD* lpParam=NULL);
    OTSTR& GetTail(DWORD* lpParam=NULL);
    OTSTR& operator[](long nIndex);

    void RemoveAt(int nIndex);
    void RemoveTail();

    void RemoveAll();

private:
    ObArray	m_List;
    OTSTR   m_strRet;
};


#endif

