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 }