00001 /* 00002 File: NArray.h 00003 00004 Function: Defines an array type that manages its own storage space, 00005 and can be used as a stack or a list. 00006 This is the sister of the array class -- it, so 00007 it doesn't have to be instantiated for every new 00008 data type, at the cost of an extra word of storage. 00009 00010 Array<> should be used just for standard data types 00011 (char, int, float, double) and NArray for everything else. 00012 00013 00014 Author(s): Andrew Willmott 00015 00016 Copyright: (c) 1995-2000, Andrew Willmott 00017 */ 00018 00019 #ifndef __NArray__ 00020 #define __NArray__ 00021 00022 #include <iostream.h> 00023 #include "cl/Basics.h" 00024 #include <stdio.h> 00025 00026 const Int kFirstNAllocation = 16; 00027 00028 00029 00030 class NBaseArray 00031 { 00032 public: 00033 inline NBaseArray(UInt32 eltSize); 00034 NBaseArray(UInt32 eltSize, Int size, Int alloc = kFirstNAllocation); 00035 NBaseArray(const NBaseArray &array); 00036 ~NBaseArray(); 00037 00038 // NBaseArray operators 00039 00040 inline Int NumItems() const; 00041 00042 NBaseArray &operator = (const NBaseArray &array); 00043 00044 // Useful for stack implementations 00045 00046 inline Void Pop(); 00047 00048 // List Operations 00049 00050 Void Clear(); 00051 00052 Void PreAllocate(UInt32 numItems); 00053 Void SetSize(Int newSize); 00054 Void Add(Int n = 1); 00055 Void Shrink(Int n = 1); 00056 Void Insert(Int i, Int n = 1); 00057 Void Delete(Int i, Int n = 1); 00058 Void ShrinkWrap(); 00061 Void Append(const NBaseArray &a); 00062 Void SwapWith(NBaseArray &a); 00063 Void Replace(NBaseArray &a); 00066 Void MemMap(const Char* filename); 00067 Void WriteFile(const Char *filename); 00068 Void ReadFile(const Char *filename); 00069 00070 Int FWrite(FILE *file); 00071 Int FRead(FILE *file); 00072 00073 Void Attach(Void *ptr, Int numItems, Bool shared = false); 00074 00075 UInt32 EltSize() 00076 { return(eltSize); }; 00077 00078 protected: 00079 Byte *item; 00080 UInt32 items; 00081 UInt32 allocated; 00082 UInt32 eltSize; 00083 00084 Void Grow(); 00085 }; 00086 00087 00088 00089 #define TMPLArray template<class T> 00090 #define TNArray NArray<T> 00091 00092 TMPLArray class NArray : public NBaseArray 00099 { 00100 public: 00101 NArray() : NBaseArray(sizeof(T)) {}; 00102 NArray(Int size, Int alloc = kFirstNAllocation) : 00103 NBaseArray(sizeof(T), size, alloc) {}; 00104 00105 inline T &operator [] (Int i); 00106 inline const T &operator [] (Int i) const; 00107 00108 inline Void Append(const T &t); 00109 inline T &Last(); 00110 00111 inline T &Top(); 00112 inline Void Push(const T &t); 00113 00114 const T &Item(Int i) const 00115 { return(SELF[i]); }; 00116 T &Item(Int i) 00117 { return(SELF[i]); }; 00118 00119 Void ClearTo(const T &t); 00120 Void Append(const TNArray &a) 00121 { ((NBaseArray*) this)->Append(a); }; 00122 // C++: can't live with it, pass the beer nuts. 00123 00124 // Low level access 00125 00126 inline T *Ref() const; 00127 inline T *Detach(); 00129 }; 00130 00131 TMPLArray ostream &operator << (ostream &s, TNArray &array); 00132 TMPLArray istream &operator >> (istream &s, TNArray &array); 00133 00134 00135 // --- Inlines ---------------------------------------------------------------- 00136 00137 00138 inline NBaseArray::NBaseArray(UInt32 es) 00139 : items(0), item(0), allocated(0), eltSize(es) 00140 { 00141 } 00142 00143 inline Int NBaseArray::NumItems() const 00144 { 00145 return(items); 00146 } 00147 00148 inline Void NBaseArray::Pop() 00149 { 00150 items--; 00151 } 00152 00153 inline Void NBaseArray::Clear() 00154 { 00155 items = 0; 00156 allocated = 0; 00157 delete[] item; 00158 item = 0; 00159 } 00160 00161 TMPLArray inline T &TNArray::operator [] (Int i) 00162 { 00163 CheckRange(i, 0, items, "(NArray::[]) index out of range"); 00164 00165 return(*((T*) (item + i * eltSize))); 00166 } 00167 00168 TMPLArray inline const T &TNArray::operator [] (Int i) const 00169 { 00170 CheckRange(i, 0, items, "(NArray::[]) index out of range"); 00171 00172 return(*((T*) (item + i * eltSize))); 00173 } 00174 00175 TMPLArray inline T &TNArray::Top() 00176 { 00177 return(*(((T*) item) + (items - 1))); 00178 } 00179 00180 TMPLArray inline T &TNArray::Last() 00181 { 00182 return(*(((T*) item) + (items - 1))); 00183 } 00184 00185 TMPLArray inline Void TNArray::Push(const T &t) 00186 { 00187 if (items >= allocated) 00188 Grow(); 00189 00190 *(((T*) item) + items++) = t; 00191 } 00192 00193 TMPLArray inline Void TNArray::ClearTo(const T &t) 00194 { 00195 for (Int i = 0; i < items; i++) 00196 *(((T*) item) + i) = t; 00197 } 00198 00199 TMPLArray inline Void TNArray::Append(const T &t) 00200 { 00201 if (items >= allocated) 00202 Grow(); 00203 00204 *(((T*) item) + items++) = t; 00205 } 00206 00207 TMPLArray inline T *TNArray::Ref() const 00208 { 00209 return((T*) item); 00210 } 00211 00212 TMPLArray inline T *TNArray::Detach() 00213 { 00214 T* result = (T*) item; 00215 00216 items = 0; 00217 allocated = 0; 00218 item = 0; 00219 00220 return(result); 00221 } 00222 00223 // --- I/O -------------------------------------------------------------------- 00224 00225 // XXX convert these to generic NBaseArray routine with the stream 00226 // function handed in 00227 00228 TMPLArray ostream &operator << (ostream &s, TNArray &array) 00229 { 00230 Int i; 00231 Char sepChar; 00232 00233 s << '['; 00234 if (array.NumItems() >= 16) 00235 sepChar = '\n'; 00236 else 00237 sepChar = ' '; 00238 00239 if (array.NumItems() > 0) 00240 { 00241 s << array[0]; 00242 00243 for (i = 1; i < array.NumItems(); i++) 00244 s << sepChar << array[i]; 00245 } 00246 00247 s << ']'; 00248 00249 return(s); 00250 } 00251 00252 TMPLArray istream &operator >> (istream &s, TNArray &array) 00253 { 00254 Char c; 00255 00256 // Expected format: [a b c d ...] 00257 00258 while (isspace(s.peek())) // chomp white space 00259 s.get(c); 00260 00261 if (s.peek() == '[') 00262 { 00263 s.get(c); 00264 array.Clear(); 00265 00266 while (isspace(s.peek())) // chomp white space 00267 s.get(c); 00268 00269 while (s.peek() != ']') 00270 { 00271 array.Add(1); 00272 s >> array.Top(); // read an item 00273 00274 if (!s) 00275 { 00276 _Warning("Couldn't read array component"); 00277 return(s); 00278 } 00279 00280 while (isspace(s.peek())) // chomp white space 00281 s.get(c); 00282 } 00283 s.get(c); 00284 } 00285 else 00286 { 00287 s.clear(ios::failbit); 00288 _Warning("Error: Expected '[' while reading array"); 00289 return(s); 00290 } 00291 00292 return(s); 00293 } 00294 00295 00296 #endif