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