
#ifndef  _LIBSTL_HPP
#define _LIBSTL_HPP

#include <vcl.h>
#include <math.h>
#include <map>
#include <list>
#include <vector>
#include <algorithm>
//#include <functional>

#ifndef FOR_STL
#define FOR_STL(_class, _pointer, _list)		for(_class _pointer = (_list).GetHead(); !(_list).IsEnd(); _pointer = (_list).GetNext())
#endif

#ifndef REV_STL
#define REV_STL(_class, _pointer, _list)		for(_class _pointer = (_list).GetTail(); !(_list).IsBegin(); _pointer = (_list).GetPrev())
#endif

#define DB_INIT     0
#define DB_NEW      1
#define DB_DELETE   2
#define DB_UPDATE   3

class TLockObj
{
private:
    CRITICAL_SECTION CS;
public:
    TLockObj(CRITICAL_SECTION &ACS)
    {
        EnterCriticalSection(&CS);
    }
    ~TLockObj()
    {
        LeaveCriticalSection(&CS);
    }
};

namespace LibSTL
{
    template<class T>
    class LibStrMap
    {
    protected:
        typedef std::map<AnsiString, T*>                    MapObject;
        typedef std::map<AnsiString, T*>::iterator          MapPosition;
        typedef std::map<AnsiString, T*>::reverse_iterator  MapRevPosition;

        MapPosition         FMapPosition;
        MapRevPosition      FMapRevPosition;
        //TCriticalSection   *FCS;
        //TRTLCriticalSection CS;
        CRITICAL_SECTION    CS;

    public:
        MapObject           FMapObject;
        LibStrMap()
        {
            //FCS = new TCriticalSection();
            FMapObject.clear();
            InitializeCriticalSection(&CS);
        };

        virtual ~LibStrMap()
        {
            RemoveAll();
            //if (FCS) delete FCS;
            DeleteCriticalSection(&CS);
        };

    public:
        inline bool Lock()
        {
            EnterCriticalSection(&CS);
            //FCS->Acquire();
            return true;
        };
        inline void UnLock()
        {
            LeaveCriticalSection(&CS);
            //FCS->Release();
        };
        inline bool Push(AnsiString AKey, T* AData)
        {
            //std::pair<map<AnsiString, T*>::iterator, bool> pairTwo;
            std::pair<MapPosition, bool> pairTwo;

            pairTwo = FMapObject.insert(std::make_pair<AnsiString, T*>(AKey, AData));
            // if (pairTwo->second == false) //데이터가 중복으로 들어간것임.
            return pairTwo.second;
        };

        inline T* Find(AnsiString AKey)
        {
            MapPosition it;
            it = FMapObject.find(AKey);
            if (it == FMapObject.end())
                return (T*)NULL;
            return it->second;
        }

        inline void RemoveAll()
        {
            MapPosition it;
            for (it = FMapObject.begin(); it != FMapObject.end(); ++it)
            {
                T* pData = it->second;
                if (pData)
                    delete pData;
            }
            FMapObject.clear();
        }

        inline void Clear()
        {
            FMapObject.clear();
        }

        inline bool Remove(AnsiString AKey)
        {
            MapPosition it;
            it = FMapObject.find(AKey);
            if (it != FMapObject.end())
            {
                T* pData = it->second;
                if (pData)
                    delete pData;
                
                FMapObject.erase(AKey);
                return true;
            }
            return false;
        }

        inline bool Erase(AnsiString AKey)
        {
            MapPosition it;
            it = FMapObject.find(AKey);
            if (it != FMapObject.end())
            {
                FMapObject.erase(AKey);
                return true;
            }
            return false;
        }
        
        inline int Size()
        {
            return(int)FMapObject.size();
        }

        inline bool IsExist(AnsiString AKey)
        {
            MapPosition it;
            it = FMapObject.find(AKey);
            if (it == FMapObject.end())
                return false;
            return true;
        }

        inline T* GetTail()
        {
            FMapRevPosition = FMapObject.rbegin();
            if (FMapRevPosition == FMapObject.rend())
                return (T*)NULL;
            return FMapRevPosition->second;
        }

        inline T* GetPrev()
        {
            if (FMapRevPosition != FMapObject.rend()) {
                FMapRevPosition++;
                if (FMapRevPosition != FMapObject.rend())
                    return FMapRevPosition->second;
            }
            return(T*)NULL;
        }

        inline bool IsBegin()
        {
            return (FMapRevPosition == FMapObject.rend());
        }

        inline T* GetHead()
        {
            FMapPosition = FMapObject.begin();
            if (FMapPosition == FMapObject.end())
                return (T*)NULL;
            return FMapPosition->second;
        }

        inline T* GetNext()
        {
            if (FMapPosition != FMapObject.end()) {
                FMapPosition++;
                if (FMapPosition != FMapObject.end())
                    return FMapPosition->second;
            }
            return(T*)NULL;
        }

        inline bool IsEnd()
        {
            return (FMapPosition == FMapObject.end());
        }
    };

    template<class T>
    class LibIntMap
    {
    protected:
        typedef std::map<int, T*>                   MapObject;
        typedef std::map<int, T*>::iterator         MapPosition;
        typedef std::map<int, T*>::reverse_iterator MapRevPosition;

        MapObject           FMapObject;
        MapPosition         FMapPosition;
        MapRevPosition      FMapRevPosition;
        CRITICAL_SECTION    CS;

    public:
        LibIntMap()
        {
            FMapObject.clear();
            InitializeCriticalSection(&CS);
        };

        virtual ~LibIntMap()
        {
            RemoveAll();
            DeleteCriticalSection(&CS);
        };

    public:
        inline bool Lock()
        {
            EnterCriticalSection(&CS);
            return true;
        };
        inline void UnLock()
        {
            LeaveCriticalSection(&CS);
        };
        inline bool Push(int AKey, T* AData)
        {
            std::pair<MapPosition, bool> pairTwo;
            pairTwo = FMapObject.insert(std::make_pair<int, T*>(AKey, AData));
            return pairTwo.second;
        };

        inline T* Find(int AKey)
        {
            MapPosition it;
            it = FMapObject.find(AKey);
            if (it == FMapObject.end())
                return (T*)NULL;
            return it->second;
        }

        inline void RemoveAll()
        {
            MapPosition it;
            for (it = FMapObject.begin(); it != FMapObject.end(); ++it)
            {
                T* pData = it->second;
                if (pData)
                    delete pData;
            }
            FMapObject.clear();
        }

        inline void Clear()
        {
            FMapObject.clear();
        }

        inline bool Remove(int AKey)
        {
            MapPosition it;
            it = FMapObject.find(AKey);
            if (it != FMapObject.end())
            {
                T* pData = it->second;
                if (pData)
                    delete pData;

                FMapObject.erase(AKey);
                return true;
            }
            return false;
        }

        inline bool Erase(int AKey)
        {
            MapPosition it;
            it = FMapObject.find(AKey);
            if (it != FMapObject.end())
            {
                FMapObject.erase(AKey);
                return true;
            }
            return false;
        }

        inline int Size()
        {
            return(int)FMapObject.size();
        }

        inline bool IsExist(int AKey)
        {
            MapPosition it;
            it = FMapObject.find(AKey);
            if (it == FMapObject.end())
                return false;
            return true;
        }

        inline T* GetTail()
        {
            FMapRevPosition = FMapObject.rbegin();
            if (FMapRevPosition == FMapObject.rend())
                return (T*)NULL;
            return FMapRevPosition->second;
        }

        inline T* GetPrev()
        {
            if (FMapRevPosition != FMapObject.rend()) {
                FMapRevPosition++;
                if (FMapRevPosition != FMapObject.rend())
                    return FMapRevPosition->second;
            }
            return(T*)NULL;
        }

        inline bool IsBegin()
        {
            return (FMapRevPosition == FMapObject.rend());
        }

        inline T* GetHead()
        {
            FMapPosition = FMapObject.begin();
            if (FMapPosition == FMapObject.end())
                return (T*)NULL;
            return FMapPosition->second;
        }

        inline T* GetNext()
        {
            if (FMapPosition != FMapObject.end()) {
                FMapPosition++;
                if (FMapPosition != FMapObject.end())
                    return FMapPosition->second;
            }
            return(T*)NULL;
        }

        inline bool IsEnd()
        {
            return (FMapPosition == FMapObject.end());
        }
    };

} // namespace

#define StrMap     LibSTL::LibStrMap
#define IntMap     LibSTL::LibIntMap
#define ListMap    LibSTL::LibStrMap

#endif //_LIBSTL_HPP


