00001 /*
00002 File: NArray.cc
00003
00004 Function: Provides methods for NBaseArray
00005
00006 Author(s): Andrew Willmott
00007
00008 Copyright: (c) 1995-2000, Andrew Willmott
00009
00010 Notes:
00011
00012 */
00013
00029 #include "cl/NArray.h"
00030 #include <string.h>
00031 #include <ctype.h>
00032
00033 NBaseArray::NBaseArray(UInt32 es, Int size, Int alloc) : items(size),
00034 allocated(alloc), eltSize(es)
00035 {
00036 Assert(size > 0, "(NBaseArray) Initial array size must be positive!");
00037
00038 if (allocated < size)
00039 allocated = size;
00040
00041 item = new Byte[eltSize * allocated];
00042 }
00043
00044 NBaseArray::NBaseArray(const NBaseArray &array) : items(array.items),
00045 allocated(array.allocated), eltSize(array.eltSize)
00046 {
00047 // XXX should we be sizing to allocated or just items?
00048 if (!allocated)
00049 allocated = items;
00050 item = new Byte[eltSize * allocated];
00051
00052 memcpy(item, array.item, items * eltSize);
00053 }
00054
00055 NBaseArray::~NBaseArray()
00056 {
00057 if (allocated) delete[] item;
00058 }
00059
00060 NBaseArray &NBaseArray::operator = (const NBaseArray &array)
00061 {
00062 Int i;
00063
00064 if (allocated < array.items)
00065 {
00066 if (allocated) delete[] item;
00067 allocated = array.items;
00068 item = new Byte[eltSize * allocated];
00069 }
00070
00071 items = array.items;
00072 memcpy(item, array.item, items * eltSize);
00073
00074 return(SELF);
00075 }
00076
00077 Void NBaseArray::PreAllocate(UInt32 newSize)
00078 {
00079 UInt32 i, oldAllocated = allocated;
00080 Byte *newArray;
00081
00082 if (newSize > allocated)
00083 {
00084 if (allocated == 0)
00085 allocated = kFirstNAllocation;
00086 else
00087 allocated *= 2;
00088
00089 while (newSize > allocated)
00090 allocated *= 2;
00091
00092 newArray = new Byte[eltSize * allocated];
00093
00094 memcpy(newArray, item, items * eltSize);
00095
00096 if (oldAllocated) delete[] item;
00097 item = newArray;
00098 }
00099 }
00100
00101 Void NBaseArray::SetSize(Int newSize)
00102 {
00103 PreAllocate(newSize);
00104 items = newSize;
00105 }
00106
00107 Void NBaseArray::Add(Int n)
00108 {
00109 SetSize(items + n);
00110 }
00111
00112 Void NBaseArray::Shrink(Int n)
00113 // take away n items.
00114 {
00115 items -= n;
00116 }
00117
00118 Void NBaseArray::Insert(Int i, Int n)
00119 // Make space at position i for n items.
00120 {
00121 Assert(i >= 0 && i <= items, "(NBaseArray:Insert) Illegal index");
00122 Assert(n > 0, "(NBaseArray:Insert) Illegal insert amount");
00123
00124 Byte *ip = item + (eltSize * i);
00125
00126 Add(n);
00127 memmove(ip + eltSize * n, ip, (items - i - n) * eltSize);
00128 }
00129
00130 Void NBaseArray::Delete(Int i, Int n)
00131 // Delete n items at position i.
00132 {
00133 Assert(i >= 0 && i <= items, "(NBaseArray:Delete) Illegal index");
00134 Assert(n > 0, "(NBaseArray:Delete) Illegal insert amount");
00135
00136 Byte *ip = item + (eltSize * i);
00137
00138 items -= n;
00139 memmove(ip, ip + eltSize * n, (items - i) * eltSize);
00140 }
00141
00142 Void NBaseArray::ShrinkWrap()
00143 // Shrink allocated space to be only the current size of array
00144 // There is no realloc version of new in C++, so this involves another copy.
00145 {
00146 Int i, oldAllocated = allocated;
00147 Byte *newArray;
00148
00149 allocated = items;
00150
00151 newArray = new Byte[eltSize * allocated];
00152
00153 memcpy(newArray, item, items * eltSize);
00154
00155 if (oldAllocated) delete[] item;
00156 item = newArray;
00157 }
00158
00159 Void NBaseArray::Grow()
00160 // Allocate more space for the array. Used internally prior to an items++.
00161 {
00162 UInt32 i, oldAllocated = allocated;
00163 Byte *newArray;
00164
00165 if (allocated == 0)
00166 allocated = kFirstNAllocation;
00167 else
00168 allocated *= 2;
00169
00170 newArray = new Byte[eltSize * allocated];
00171
00172 memcpy(newArray, item, items * eltSize);
00173
00174 if (oldAllocated) delete[] item;
00175 item = newArray;
00176 }
00177
00178 Void NBaseArray::Append(const NBaseArray &a)
00179 {
00180 Int i, j, start, newSize;
00181
00182 newSize = items + a.items;
00183 PreAllocate(newSize);
00184
00185 for (i = items, j = 0; j < a.items; i++, j++)
00186 item[i] = a.item[j];
00187 memcpy(item + (items * eltSize), a.item, a.items * eltSize);
00188
00189 items = newSize;
00190 }
00191
00192 Void NBaseArray::SwapWith(NBaseArray &a)
00193 {
00194 Int a1, b1;
00195
00196 Swap(a1, b1);
00197
00198 Swap(items, a.items);
00199 Swap(allocated, a.allocated);
00200 Swap(item, a.item);
00201 }
00202
00203 Void NBaseArray::Replace(NBaseArray &a)
00204 {
00205 if (allocated) delete[] item;
00206 item = a.item;
00207 items = a.items;
00208 allocated = a.allocated;
00209
00210 a.item = 0;
00211 a.items = 0;
00212 a.allocated = 0;
00213 }
00214
00215 #include <stdio.h>
00216
00217 Void NBaseArray::WriteFile(const Char *filename)
00218 {
00219 FILE *file;
00220
00221 file = fopen(filename, "wb");
00222 if (file)
00223 {
00224 fwrite(item, eltSize, items, file);
00225 fclose(file);
00226 }
00227 }
00228
00229 Void NBaseArray::ReadFile(const Char *filename)
00230 {
00231 FILE *file = fopen(filename, "rb");
00232
00233 if (file)
00234 {
00235 Int fsize;
00236
00237 fseek(file, 0, SEEK_END);
00238 fsize = ftell(file);
00239 rewind(file);
00240 items = fsize / eltSize;
00241 Assert(items * eltSize == fsize, "(NBaseArray::ReadFile) bad file size");
00242 item = new Byte[eltSize * items];
00243 allocated = items;
00244 fread(item, eltSize, items, file);
00245
00246 fclose(file);
00247 }
00248 }
00249
00250 Int NBaseArray::FWrite(FILE *file)
00251 {
00252 fwrite(&items, sizeof(UInt32), 1, file);
00253 fwrite(item, eltSize, items, file);
00254
00255 return(ferror(file));
00256 }
00257
00258 Int NBaseArray::FRead(FILE *file)
00259 {
00260 if (fread(&items, sizeof(UInt32), 1, file) != 1)
00261 return(-1);
00262 item = new Byte[eltSize * items];
00263 allocated = items;
00264
00265 return(fread(item, eltSize, items, file) != items);
00266 }
00267
00268 Void NBaseArray::Attach(Void *ptr, Int numItems, Bool shared)
00269 {
00270 Clear();
00271
00272 item = (Byte*) ptr;
00273 items = numItems;
00274
00275 if (!shared)
00276 allocated = numItems;
00277 }