// univ.cpp -- // $Id$ // This is part of Metakit, see http://www.equi4.com/metakit/ /** @file * A simple implementation of dynamic arrays */ #include "header.h" #if q4_UNIV // until end of source ///////////////////////////////////////////////////////////////////////////// #include // malloc #if !q4_INLINE #include "univ.inl" #endif ///////////////////////////////////////////////////////////////////////////// #if q4_UNIX || __MINGW32__ #define _strdup strdup #elif !q4_BORC && !q4_MSVC && !q4_WATC && !(q4_MWCW && defined(_WIN32)) && \ !(q4_MWCW && __MWERKS__ >= 0x3000) static char* _strdup(const char* p) { if (!p) return 0; char* s = (char*) malloc(strlen(p) + 1); return strcpy(s, p); } #endif // The Borland C++ RTL does not want file handle objects to cross // DLL boundaries, so we add special fopen/fclose hooks to this DLL. #if q4_BORC #include #if q4_WIN32 __declspec(dllexport) FILE* #else FILE* __export #endif f4_FileOpenInDLL(const char* name_, const char* mode_) { return fopen(name_, mode_); } #if q4_WIN32 __declspec(dllexport) #else int __export #endif f4_FileCloseInDLL(FILE* file_) { return fclose(file_); } #endif ///////////////////////////////////////////////////////////////////////////// // c4_BaseArray c4_BaseArray::c4_BaseArray () : _data (0), _size (0) { } c4_BaseArray::~c4_BaseArray () { SetLength(0); } void c4_BaseArray::SetLength(int nNewSize) { // 2001-11-25: use more granular allocation, as optimization const int bits = 6; if (((_size - 1) ^ (nNewSize - 1)) >> bits) { const int n = (nNewSize + (1< n) memset(GetData(n), 0, nNewSize - n); } void c4_BaseArray::Grow(int nIndex) { if (nIndex > _size) SetLength(nIndex); } void c4_BaseArray::InsertAt(int nIndex, int nCount) { SetLength(_size + nCount); int to = nIndex + nCount; if (_size > to) d4_memmove(GetData(to), GetData(nIndex), _size - to); } void c4_BaseArray::RemoveAt(int nIndex, int nCount) { int from = nIndex + nCount; if (_size > from) d4_memmove(GetData(nIndex), GetData(from), _size - from); SetLength(_size - nCount); } ///////////////////////////////////////////////////////////////////////////// // c4_DWordArray int c4_DWordArray::Add(t4_i32 newElement) { int n = GetSize(); _vector.Grow(Off(n + 1)); SetAt(n, newElement); return n; } void c4_DWordArray::InsertAt(int nIndex, t4_i32 newElement, int nCount) { _vector.InsertAt(Off(nIndex), nCount * sizeof (t4_i32)); while (--nCount >= 0) SetAt(nIndex++, newElement); } void c4_DWordArray::RemoveAt(int nIndex, int nCount) { _vector.RemoveAt(Off(nIndex), nCount * sizeof (t4_i32)); } ///////////////////////////////////////////////////////////////////////////// // c4_PtrArray int c4_PtrArray::Add(void* newElement) { int n = GetSize(); _vector.Grow(Off(n + 1)); SetAt(n, newElement); return n; } void c4_PtrArray::InsertAt(int nIndex, void* newElement, int nCount) { _vector.InsertAt(Off(nIndex), nCount * sizeof (void*)); while (--nCount >= 0) SetAt(nIndex++, newElement); } void c4_PtrArray::RemoveAt(int nIndex, int nCount) { _vector.RemoveAt(Off(nIndex), nCount * sizeof (void*)); } ///////////////////////////////////////////////////////////////////////////// // c4_StringArray c4_StringArray::~c4_StringArray() { SetSize(0); } void c4_StringArray::SetSize(int nNewSize, int) { int i = nNewSize; while (i < GetSize()) SetAt(i++, 0); _ptrs.SetSize(nNewSize); while (i < GetSize()) _ptrs.SetAt(i++, ""); } void c4_StringArray::SetAt(int nIndex, const char* newElement) { char* s = (char*) _ptrs.GetAt(nIndex); if (s && *s) free(s); _ptrs.SetAt(nIndex, newElement && *newElement? _strdup(newElement) : ""); } int c4_StringArray::Add(const char* newElement) { int n = _ptrs.Add(0); SetAt(n, newElement); return n; } void c4_StringArray::InsertAt(int nIndex, const char* newElement, int nCount) { _ptrs.InsertAt(nIndex, 0, nCount); while (--nCount >= 0) SetAt(nIndex++, newElement); } void c4_StringArray::RemoveAt(int nIndex, int nCount) { for (int i = 0; i < nCount; ++i) SetAt(nIndex + i, 0); _ptrs.RemoveAt(nIndex, nCount); } ///////////////////////////////////////////////////////////////////////////// #endif // q4_UNIV