You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
4.6 KiB
228 lines
4.6 KiB
// 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 <stdlib.h> // 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 <stdio.h>
|
|
|
|
#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<<bits) - 1) & -(1<<bits);
|
|
_data = _data == 0 ? n == 0 ? (char*) 0
|
|
: (char*) malloc(n)
|
|
: n == 0 ? (free(_data), (char*) 0)
|
|
: (char*) realloc(_data, n);
|
|
}
|
|
|
|
d4_assert(_data != 0 || nNewSize == 0);
|
|
|
|
int n = _size;
|
|
_size = nNewSize;
|
|
|
|
if (nNewSize > 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
|