1// univ.cpp -- 2// $Id: univ.cpp 1230 2007-03-09 15:58:53Z jcw $ 3// This is part of Metakit, see http://www.equi4.com/metakit.html 4 5/** @file 6 * A simple implementation of dynamic arrays 7 */ 8 9#include "header.h" 10 11#if q4_UNIV // until end of source 12///////////////////////////////////////////////////////////////////////////// 13 14#include <stdlib.h> // malloc 15 16#if !q4_INLINE 17#include "univ.inl" 18#endif 19 20///////////////////////////////////////////////////////////////////////////// 21 22#if q4_UNIX || __MINGW32__ 23#define _strdup strdup 24#elif !q4_BORC && !q4_MSVC && !q4_WATC && !(q4_MWCW && defined(_WIN32)) && \ 25!(q4_MWCW && __MWERKS__ >= 0x3000) 26 27static char *_strdup(const char *p) { 28 if (!p) 29 return 0; 30 31 char *s = (char*)malloc(strlen(p) + 1); 32 return strcpy(s, p); 33} 34 35#endif 36 37// The Borland C++ RTL does not want file handle objects to cross 38// DLL boundaries, so we add special fopen/fclose hooks to this DLL. 39 40#if q4_BORC 41#include <stdio.h> 42 43#if q4_WIN32 44__declspec(dllexport)FILE * 45#else 46FILE *__export 47#endif 48f4_FileOpenInDLL(const char *name_, const char *mode_) { 49 return fopen(name_, mode_); 50} 51 52#if q4_WIN32 53__declspec(dllexport) 54#else 55int __export 56#endif 57f4_FileCloseInDLL(FILE *file_) { 58 return fclose(file_); 59} 60 61#endif 62 63///////////////////////////////////////////////////////////////////////////// 64// c4_BaseArray 65 66c4_BaseArray::c4_BaseArray(): _data(0), _size(0){} 67 68c4_BaseArray::~c4_BaseArray() { 69 SetLength(0); 70} 71 72void c4_BaseArray::SetLength(int nNewSize) { 73 // 2001-11-25: use more granular allocation, as optimization 74 const int bits = 6; 75 76 if (((_size - 1) ^ (nNewSize - 1)) >> bits) { 77 const int n = (nNewSize + (1 << bits) - 1) & - (1 << bits); 78 _data = _data == 0 ? n == 0 ? (char*)0: (char*)malloc(n): n == 0 ? (free 79 (_data), (char*)0): (char*)realloc(_data, n); 80 } 81 82 d4_assert(_data != 0 || nNewSize == 0); 83 84 int n = _size; 85 _size = nNewSize; 86 87 if (nNewSize > n) 88 memset(GetData(n), 0, nNewSize - n); 89} 90 91void c4_BaseArray::Grow(int nIndex) { 92 if (nIndex > _size) 93 SetLength(nIndex); 94} 95 96void c4_BaseArray::InsertAt(int nIndex, int nCount) { 97 SetLength(_size + nCount); 98 99 int to = nIndex + nCount; 100 if (_size > to) 101 d4_memmove(GetData(to), GetData(nIndex), _size - to); 102} 103 104void c4_BaseArray::RemoveAt(int nIndex, int nCount) { 105 int from = nIndex + nCount; 106 if (_size > from) 107 d4_memmove(GetData(nIndex), GetData(from), _size - from); 108 109 SetLength(_size - nCount); 110} 111 112///////////////////////////////////////////////////////////////////////////// 113// c4_DWordArray 114 115int c4_DWordArray::Add(t4_i32 newElement) { 116 int n = GetSize(); 117 _vector.Grow(Off(n + 1)); 118 SetAt(n, newElement); 119 return n; 120} 121 122void c4_DWordArray::InsertAt(int nIndex, t4_i32 newElement, int nCount) { 123 _vector.InsertAt(Off(nIndex), nCount *sizeof(t4_i32)); 124 125 while (--nCount >= 0) 126 SetAt(nIndex++, newElement); 127} 128 129void c4_DWordArray::RemoveAt(int nIndex, int nCount) { 130 _vector.RemoveAt(Off(nIndex), nCount *sizeof(t4_i32)); 131} 132 133///////////////////////////////////////////////////////////////////////////// 134// c4_PtrArray 135 136int c4_PtrArray::Add(void *newElement) { 137 int n = GetSize(); 138 _vector.Grow(Off(n + 1)); 139 SetAt(n, newElement); 140 return n; 141} 142 143void c4_PtrArray::InsertAt(int nIndex, void *newElement, int nCount) { 144 _vector.InsertAt(Off(nIndex), nCount *sizeof(void*)); 145 146 while (--nCount >= 0) 147 SetAt(nIndex++, newElement); 148} 149 150void c4_PtrArray::RemoveAt(int nIndex, int nCount) { 151 _vector.RemoveAt(Off(nIndex), nCount *sizeof(void*)); 152} 153 154///////////////////////////////////////////////////////////////////////////// 155// c4_StringArray 156 157c4_StringArray::~c4_StringArray() { 158 SetSize(0); 159} 160 161void c4_StringArray::SetSize(int nNewSize, int) { 162 int i = nNewSize; 163 164 while (i < GetSize()) 165 SetAt(i++, 0); 166 167 _ptrs.SetSize(nNewSize); 168 169 while (i < GetSize()) 170 _ptrs.SetAt(i++, ""); 171} 172 173void c4_StringArray::SetAt(int nIndex, const char *newElement) { 174 char *s = (char*)_ptrs.GetAt(nIndex); 175 if (s && *s) 176 free(s); 177 178 _ptrs.SetAt(nIndex, newElement && *newElement ? _strdup(newElement): ""); 179} 180 181int c4_StringArray::Add(const char *newElement) { 182 int n = _ptrs.Add(0); 183 SetAt(n, newElement); 184 return n; 185} 186 187void c4_StringArray::InsertAt(int nIndex, const char *newElement, int nCount) { 188 _ptrs.InsertAt(nIndex, 0, nCount); 189 190 while (--nCount >= 0) 191 SetAt(nIndex++, newElement); 192} 193 194void c4_StringArray::RemoveAt(int nIndex, int nCount) { 195 for (int i = 0; i < nCount; ++i) 196 SetAt(nIndex + i, 0); 197 198 _ptrs.RemoveAt(nIndex, nCount); 199} 200 201///////////////////////////////////////////////////////////////////////////// 202#endif // q4_UNIV 203