From 49f4cab93b2f50a8132c6b8c26f1535f4f9ebb63 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Mon, 21 May 2012 15:17:41 +0000 Subject: - added ChangeClientNotify - CommonLibs finally became common ;) git-svn-id: http://svn.miranda-ng.org/main/trunk@118 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/CommonLibs/TMyArray.h | 353 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 353 insertions(+) create mode 100644 plugins/CommonLibs/TMyArray.h (limited to 'plugins/CommonLibs/TMyArray.h') diff --git a/plugins/CommonLibs/TMyArray.h b/plugins/CommonLibs/TMyArray.h new file mode 100644 index 0000000000..68ca908fe1 --- /dev/null +++ b/plugins/CommonLibs/TMyArray.h @@ -0,0 +1,353 @@ +/* + TMyArray.h - TMyArray template + Copyright (c) 2005-2008 Chervov Dmitry + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#pragma once + +#include + +#define ARRAY_GROWBY 4 +// if there is more than ARRAY_FREETHRESHOLD free array elements, then we're reallocating the array +#define ARRAY_FREETHRESHOLD 16 + +template +class TMyArray +{ +public: + TMyArray(); + TMyArray(const TMyArray &A); + ~TMyArray(); + + int GetSize() const; + T* GetData() const; + int AddElem(ARG_T pElem); + int Add(const T *pItems, int nItems); + void InsertElem(ARG_T pElem, int nInsertAt); + void MoveElem(int nIndex, int nMoveTo); + T& SetAtGrow(int nIndex); + int Find(ARG_T pElem); // returns an index of the specified item, or -1 if the array doesn't contain the item + int BinarySearch(int (*CmpFunc)(ARG_T pItem, LPARAM lParam), LPARAM lParam, int *pIndex = NULL); // returns an index of the specified item, or -1 if the array doesn't contain the item; + // also it's possible to specify pIndex so that even if the array doesn't contain the item, the function will set *pIndex to a position where the item can be inserted; + // CmpFunc must return -1, 0 and 1 depending whether pItem is lesser, equal or greater than needed; + // BinarySearch() requires the array to be sorted in an ascending order + void RemoveElem(int nIndex, int nItems = 1); + void RemoveAll(); + const T& operator[](int nIndex) const; + T& operator[](int nIndex); + TMyArray& operator = (const TMyArray &A); + TMyArray& operator += (const TMyArray &A); + +private: + int SetAllocNum(int nNewAllocNum); + + T* pData; + int nElemNum; + int nAllocNum; +}; + +template +TMyArray::TMyArray() +{ + nElemNum = 0; + nAllocNum = 0; + pData = NULL; +} + +template +TMyArray::TMyArray(const TMyArray &A)//: TMyArray() +{ + nElemNum = 0; + nAllocNum = 0; + pData = NULL; + *this = A; +} + +template +TMyArray::~TMyArray() +{ + RemoveAll(); +} + +template +__forceinline int TMyArray::GetSize() const +{ + return nElemNum; +} + +template +__forceinline T* TMyArray::GetData() const +{ + return pData; +} + +template +__forceinline int TMyArray::SetAllocNum(int nNewAllocNum) +{ + _ASSERT(nNewAllocNum >= nElemNum); + T*pNewData = (nNewAllocNum) ? (T*)malloc(sizeof(T) * nNewAllocNum) : NULL; + if (pData) + { + if (pNewData) + { + memcpy(pNewData, pData, sizeof(T) * nElemNum); + } + free(pData); + } + pData = pNewData; + if (!pNewData) + { + nAllocNum = 0; + return -1; // not enough memory? + } else + { + nAllocNum = nNewAllocNum; + return 0; // everything's ok + } +} + +template +__forceinline int TMyArray::AddElem(ARG_T pElem) +{ + if (nElemNum >= nAllocNum) + { // reallocate memory to fit new element + SetAllocNum(nAllocNum + GrowBy); + } + memset(pData + nElemNum, 0, sizeof(T)); + pData[nElemNum] = pElem; + return nElemNum++; +} + +template +__forceinline int TMyArray::Add(const T *pItems, int nItems) +{ + if (nElemNum + nItems > nAllocNum) + { // reallocate memory to fit new items + SetAllocNum(nAllocNum + nElemNum + nItems - 1 - ((nElemNum + nItems - 1) % GrowBy) + GrowBy); + } + memset(pData + nElemNum, 0, sizeof(T) * nItems); + int I; + for (I = 0; I < nItems; I++) + { + pData[nElemNum++] = pItems[I]; + } + return nElemNum - nItems; // returns an index of the first item added +} + +template +__forceinline void TMyArray::InsertElem(ARG_T pElem, int nInsertAt) +{ + _ASSERT(nInsertAt >= 0 && nInsertAt <= nElemNum); + if (nElemNum >= nAllocNum) + { // reallocate memory to fit new items + SetAllocNum(nAllocNum + GrowBy); + } + memmove(pData + nInsertAt + 1, pData + nInsertAt, sizeof(T) * (nElemNum - nInsertAt)); + memset(pData + nInsertAt, 0, sizeof(T)); + pData[nInsertAt] = pElem; + nElemNum++; +} + +template +__forceinline void TMyArray::MoveElem(int nIndex, int nMoveTo) +{ + _ASSERT(nIndex >= 0 && nIndex < nElemNum && nMoveTo >= 0 && nMoveTo < nElemNum); + if (nIndex == nMoveTo) + { + return; // nothing to do + } + char Elem[sizeof(T)]; + memmove(Elem, pData + nIndex, sizeof(T)); + if (nIndex < nMoveTo) + { + memmove(pData + nIndex, pData + nIndex + 1, sizeof(T) * (nMoveTo - nIndex)); + } else + { + memmove(pData + nMoveTo + 1, pData + nMoveTo, sizeof(T) * (nIndex - nMoveTo)); + } + memmove(pData + nMoveTo, Elem, sizeof(T)); +} + +template +__forceinline T& TMyArray::SetAtGrow(int nIndex) +{ + _ASSERT(nIndex >= 0); + if (nIndex < nElemNum) + { + return pData[nIndex]; + } + if (nIndex >= nAllocNum) + { + if (SetAllocNum(nIndex - (nIndex % GrowBy) + GrowBy)) + { // if there was an error + nElemNum = 0; + return *pData; + } + } + memset(pData + nElemNum, 0, sizeof(T) * (nIndex - nElemNum + 1)); + nElemNum = nIndex + 1; + return pData[nIndex]; +} + +template +__forceinline int TMyArray::Find(ARG_T pElem) +{ + int I; + for (I = 0; I < nElemNum; I++) + { + if (pData[I] == pElem) + { + return I; + } + } + return -1; +} + +template +__forceinline int TMyArray::BinarySearch(int (*CmpFunc)(ARG_T pItem, LPARAM lParam), LPARAM lParam, int *pIndex) +{ + int L, R; + int CmpResult; + if (!nElemNum) + { + if (pIndex) + { + *pIndex = -1; + } + return -1; + } + for (L = 0, R = nElemNum; R - L > 1;) + { + int C = (L + R) >> 1; // rounds always to a lesser index if L + R is odd + CmpResult = CmpFunc(pData[C], lParam); // usually, CmpFunc = pData[C] - lParam; i.e. CmpFunc > 0 when pData[C] is greater than necessary, < 0 when pData[C] is less, and = 0 when pData[C] is the item we search for + if (CmpResult < 0) + { + L = C; + } else if (CmpResult > 0) + { + R = C; + } else + { // CmpResult == 0 + if (pIndex) + { + *pIndex = C; + } + return C; + } + } + if (pIndex) + { + *pIndex = L; + } + CmpResult = CmpFunc(pData[L], lParam); + if (!CmpResult) + { + return L; + } + if (CmpResult > 0) + { // we don't need to check pData[R], as pData[R] > pData[L] > lParam, i.e. there are no suitable item in the array + return -1; + } +// CmpResult < 0, we have to check pData[R] too + if (pIndex) + { + *pIndex = R; + } + if (R >= nElemNum) + { + return -1; + } + return CmpFunc(pData[R], lParam) ? -1 : R; +} + +template +__forceinline void TMyArray::RemoveElem(int nIndex, int nItems) +{ + _ASSERT(nIndex >= 0 && nIndex + nItems <= nElemNum); + if (!nItems) + { + return; + } +// delete pData[nIndex]; +// ~pData[nIndex]; + int I; + for (I = nIndex; I < nIndex + nItems; I++) + { + (pData + I)->~T(); + } + memmove(pData + nIndex, pData + nIndex + nItems, sizeof(T) * (nElemNum - nIndex - nItems)); + nElemNum -= nItems; + if (nAllocNum - nElemNum >= FreeThreshold) + { + SetAllocNum(nAllocNum - FreeThreshold); + }/* else + { + memset(pData + nElemNum, 0, sizeof(T)); + }*/ +} + +template +__forceinline void TMyArray::RemoveAll() +{ + int I; + for (I = 0; I < nElemNum; I++) + { + //delete pData[I]; + (pData + I)->~T(); + } + nElemNum = 0; + SetAllocNum(0); +} + +template +__forceinline const T& TMyArray::operator[](int nIndex) const +{ + _ASSERT(nIndex >= 0 && nIndex < nElemNum); + return pData[nIndex]; +} + +template +__forceinline T& TMyArray::operator[](int nIndex) +{ + _ASSERT(nIndex >= 0 && nIndex < nElemNum); + return pData[nIndex]; +} + +template +__forceinline TMyArray& TMyArray::operator = (const TMyArray &A) +{ + RemoveAll(); + int I; + for (I = 0; I < A.GetSize(); I++) + { + AddElem(A[I]); + } + return *this; +} + +template +__forceinline TMyArray& TMyArray::operator += (const TMyArray &A) +{ + int I; + for (I = 0; I < A.GetSize(); I++) + { + AddElem(A[I]); + } + return *this; +} + +typedef TMyArray CHARARRAY; -- cgit v1.2.3