00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00049 #ifndef __BasicArray_h
00050 #define __BasicArray_h
00051
00052 #ifdef NON_ANSI
00053 #include <iostream.h>
00054 #else
00055 #include <iostream>
00056 using namespace std;
00057 #endif
00058 #ifndef ANSI_HDRS
00059 #include <stdlib.h>
00060 #else
00061 #include <cstdlib>
00062 #endif
00063 #include "_generic.h"
00064 #include "_math.h"
00065 #include "errmsg.h"
00066 #include "ClassRef.h"
00067
00068
00081 #if !defined(ArraySanityChecking)
00082 #define ArraySanityChecking 1
00083 #endif
00084
00085 template <class T>
00086 class UTILIB_API BasicArray;
00087
00088
00089 template <class T>
00090 class BasicArray {
00091
00092 friend class ArrayRef<T,BasicArray<T> >;
00093
00094 public:
00095
00097 BasicArray()
00098 {construct(0,(T*)0,DataNotOwned);}
00109 #ifndef NON_ANSI
00110 explicit
00111 #endif
00112 BasicArray(const size_type mylen, T *d=((T*)0),
00113 const EnumDataOwned o=DataNotOwned)
00114 {construct(mylen,d,o);}
00116 BasicArray(const BasicArray<T>& array)
00117 {construct(array.size(), array.data(), AcquireOwnership);}
00119 virtual ~BasicArray()
00120 {free();}
00121
00123 int shared_mem() const
00124 {return (shared != NULL);}
00126 virtual int resize(const size_type newl);
00128 size_type size() const
00129 { return Len; }
00131 int len() const
00132 {return (int)size();}
00134 T* data() const
00135 { return Data; }
00136 #ifndef SWIG
00137
00138 operator T* () const
00139 { return Data; }
00140 #endif
00141
00142 int nrefs() const
00143 {if (shared) return shared->ref; return 0;}
00150 T & operator[](const int i);
00152 const T & operator[](const int i) const;
00159 T & operator[](const size_type i);
00161 const T & operator[](const size_type i) const;
00162
00164 BasicArray<T>& operator=(const BasicArray<T>& array);
00166 BasicArray<T>& operator&=(const BasicArray<T>& array);
00168 BasicArray<T>& operator&=(BasicArray<T>& array);
00170 BasicArray<T>& operator=(const T& val);
00171
00173 BasicArray<T>& set_data(const size_type len, T *data,
00174 const EnumDataOwned o=DataNotOwned);
00182 BasicArray<T>& set_data(const BasicArray<T>& vec, const size_type start,
00183 const size_type newlen);
00185 BasicArray<T>& set_data(const BasicArray<T>& vec, const size_type start=0)
00186 {return set_data(vec,start,vec.size()-start);}
00188 BasicArray<T>& set_subvec(const size_type start, const size_type len,
00189 const BasicArray<T>& datavec,
00190 const size_type offset=0);
00191 #ifndef SWIG
00192
00193 BasicArray<T>& at(const size_type start, const size_type newlen,
00194 BasicArray<T>* array = (BasicArray<T>*)0) const;
00196 BasicArray<T>& at(const size_type start=0) const
00197 {return at(start, size()-start);}
00198 #endif
00199
00201 void append(T& element)
00202 {
00203 size_type tmp=Len;
00204 resize(tmp+1);
00205 (*this)[tmp] = element;
00206 }
00207
00209 void append(BasicArray<T>& vec)
00210 {
00211 size_type tmp=Len;
00212 resize(tmp+vec.size());
00213 for (size_type i=tmp; i<Len; i++)
00214 (*this)[i] = vec[i-tmp];
00215 }
00216
00218 static void set_ref_limit(const int num)
00219 { ClassRef<BasicArray<T> >::num_refs_limit = num; }
00220
00222 void freeze_memory()
00223 {
00224 if (!shared)
00225 set_shared_data(Data, Len, AcquireOwnership);
00226 shared->freeze();
00227 }
00228
00229 protected:
00230
00232 T* Data;
00234 size_type Len;
00236 ArrayRef<T,BasicArray<T> >* shared;
00237
00239 virtual void construct(const size_type mylen, T *d,
00240 const EnumDataOwned o=DataNotOwned);
00242 virtual void initialize(T* , const size_type ,
00243 const size_type )
00244 {}
00246 void free();
00248 void set_shared_data(T *data, const size_type len_,
00249 const EnumDataOwned o=DataNotOwned);
00250
00251 };
00252
00253
00257
00258 template <class T>
00259 inline T & BasicArray<T>::operator[](const int idx)
00260 {
00261 #if (ArraySanityChecking==1)
00262 if ((idx < 0) || ((size_type)idx >= Len))
00263 ErrAbort(errmsg("BasicArray<T>::operator[] : iterator out of range. idx=%d len=%d",idx,Len));
00264 #endif
00265
00266 return Data[idx];
00267 }
00268
00269
00270 template <class T>
00271 inline const T & BasicArray<T>::operator[](const int idx) const
00272 {
00273 #if (ArraySanityChecking==1)
00274 if ((idx < 0) || ((size_type)idx >= Len))
00275 ErrAbort(errmsg("BasicArray<T>::operator[] : iterator out of range. idx=%d len=%d",idx,Len));
00276 #endif
00277
00278 return Data[idx];
00279 }
00280
00281
00282 template <class T>
00283 inline T & BasicArray<T>::operator[](const size_type idx)
00284 {
00285 #if (ArraySanityChecking==1)
00286 if (idx >= Len)
00287 ErrAbort(errmsg("BasicArray<T>::operator[] : iterator out of range. idx=%d len=%d",idx,Len));
00288 #endif
00289
00290 return Data[idx];
00291 }
00292
00293
00294 template <class T>
00295 inline const T & BasicArray<T>::operator[](const size_type idx) const
00296 {
00297 #if (ArraySanityChecking==1)
00298 if (idx >= Len)
00299 ErrAbort(errmsg("BasicArray<T>::operator[] : iterator out of range. idx=%d len=%d",idx,Len));
00300 #endif
00301
00302 return Data[idx];
00303 }
00304
00305
00309
00310 template <class T>
00311 void BasicArray<T>::construct(const size_type mylen, T *d, const EnumDataOwned o)
00312 {
00313 Len = mylen;
00314 if (d == NULL) {
00315 if (mylen > 0) {
00316 Data = new T [mylen] ;
00317 if (Data == 0)
00318 ErrAbort(errmsg("BasicArray::construct - new T [%d] failed.",mylen));
00319 }
00320 else
00321 Data = NULL;
00322 }
00323
00324 else {
00325 if (o == AcquireOwnership) {
00326 if (mylen > 0) {
00327 Data = new T [mylen] ;
00328 if (Data == 0)
00329 ErrAbort(errmsg("BasicArray::construct - new T [%d] failed.",mylen));
00330 for (size_type i=0; i<mylen; i++) Data[i] = d[i] ;
00331 }
00332 }
00333 else
00334 Data = d;
00335 }
00336
00337 shared=0;
00338 if ((d != NULL) && (o != AcquireOwnership))
00339 set_shared_data(Data,Len,o);
00340 }
00341
00342
00343 template <class T>
00344 void BasicArray<T>::free()
00345 {
00346 if (shared) {
00347 bool flag = shared->release(this);
00348 if (flag)
00349 delete shared;
00350 shared=0;
00351 }
00352 else if (Len > 0) {
00353 delete [] Data;
00354 Data=NULL;
00355 Len=0;
00356 }
00357 }
00358
00359
00360 template <class T>
00361 BasicArray<T>& BasicArray<T>::operator=(const BasicArray<T>& array)
00362 {
00363 if (this != &array) {
00364 free();
00365 construct(array.size(),array.data(),AcquireOwnership);
00366 }
00367 return *this;
00368 }
00369
00370
00371 template <class T>
00372 BasicArray<T>& BasicArray<T>::operator=(const T& val)
00373 {
00374 if (size() == 0)
00375 return *this;
00376 T *start = Data;
00377 T *end = start + size();
00378 for ( ; start < end ; start++ )
00379 *start = val;
00380 return *this;
00381 }
00382
00383
00384 template <class T>
00385 BasicArray<T>& BasicArray<T>::operator&=(const BasicArray<T>& array)
00386 {
00387 if ((Data != NULL) && (array.Data == Data)) return *this;
00388
00389 if (!array.shared)
00390 ErrAbort("BasicArray<T>::operator&= - argument is an array with unshared memory!");
00391
00392 free();
00393 shared = array.shared;
00394 shared->acquire(this);
00395
00396 return *this;
00397 }
00398
00399
00400
00401 template <class T>
00402 BasicArray<T>& BasicArray<T>::operator&=(BasicArray<T>& array)
00403 {
00404 if ((Data != NULL) && (array.Data == Data)) return *this;
00405
00406 if (!array.shared)
00407 array.set_shared_data(array.Data, array.Len, AcquireOwnership);
00408
00409 free();
00410 shared = array.shared;
00411 shared->acquire(this);
00412
00413 return *this;
00414 }
00415
00416
00417
00418 template <class T>
00419 int BasicArray<T>::resize(const size_type newl)
00420 {
00421 if (newl == Len) return OK;
00422
00423 if (newl == 0) {
00424 if (shared)
00425 shared->set_data(0,0,AcquireOwnership);
00426 else if (Len > 0) {
00427 delete [] Data;
00428 Data = 0;
00429 Len = 0;
00430 }
00431 return OK;
00432 }
00433
00434 T *d;
00435 d = new T [newl];
00436 if (d == 0)
00437 ErrAbort(errmsg("BasicArray::resize - new T [%d] failed.",newl));
00438 if (Len > 0) {
00439 T* start = Data;
00440 for (size_type i=0; i<min(newl,Len); i++,start++)
00441 d[i] = *start;
00442 }
00443
00444 if (newl > Len)
00445 initialize(d,Len,newl);
00446
00447 if (shared)
00448 shared->set_data(d,newl,AcquireOwnership);
00449 else {
00450 if (Len > 0)
00451 delete [] Data;
00452 Data = d;
00453 Len = newl;
00454 }
00455
00456 return OK;
00457 }
00458
00459
00460 template <class T>
00461 void BasicArray<T>::set_shared_data(T* data, const size_type len,
00462 const EnumDataOwned o)
00463 {
00464 if (!shared) {
00465 if ((Len > 0) && (data != Data))
00466 delete [] Data;
00467 shared = new ArrayRef<T,BasicArray<T> >();
00468 if (!shared)
00469 ErrAbort("BasicArray<T>::set_shared_data - error allocated a ArrayRef object");
00470 shared->acquire(this);
00471 }
00472
00473 shared->set_data(data,len,o);
00474 }
00475
00476
00477 template <class T>
00478 BasicArray<T>& BasicArray<T>::set_data(const size_type len, T * data,
00479 const EnumDataOwned o)
00480 {
00481 if (Data == data) return *this;
00482
00483 set_shared_data(data, len, o);
00484 return *this;
00485 }
00486
00487
00488
00489 template <class T>
00490 BasicArray<T>& BasicArray<T>::set_data(const BasicArray<T>& array,
00491 const size_type start,
00492 const size_type newlen)
00493 {
00494 if (array.Data == Data)
00495 return *this;
00496
00497 if (array.Data)
00498 set_shared_data( &(array.Data[start]), newlen, DataNotOwned);
00499 else
00500 resize(0);
00501 return *this;
00502 }
00503
00504
00505 template <class T>
00506 BasicArray<T>& BasicArray<T>::set_subvec(const size_type start,
00507 const size_type len,
00508 const BasicArray<T>& array, const size_type offset)
00509 {
00510 T* begin = Data + start;
00511 T* newdata = array.Data + offset;
00512 for (size_type i=0; i<len; i++, begin++, newdata++)
00513 *begin = *newdata;
00514
00515 return *this;
00516 }
00517
00518
00519 template <class T>
00520 BasicArray<T>& BasicArray<T>::at(const size_type start, const size_type newlen,
00521 BasicArray<T>* array ) const
00522 {
00523 BasicArray<T> *tmp;
00524
00525 if (array == NULL) {
00526 tmp = new BasicArray<T>();
00527 if (tmp == 0)
00528 ErrAbort("BasicArray::at - new BasicArray failed.");
00529 }
00530 else
00531 tmp = array;
00532 tmp->set_data((*this), start, newlen);
00533 return *tmp;
00534 }
00535
00536 #define BasicArray_DEFN
00537
00538
00539
00540
00541
00542 template <class T, class V>
00543 BasicArray<T>& operator<<(BasicArray<T>& x, const BasicArray<V>& y)
00544 {
00545 if (((void*)(x.data())) == ((void*)(y.data())))
00546 return x;
00547 if (x.size() != y.size())
00548 ErrAbort(errmsg("operator<< : Unequal array lengths %d and %d",
00549 x.size(), y.size()));
00550
00551 size_type len = x.size();
00552 for (size_type i=0; i<len; i++)
00553 x[i] = y[i];
00554
00555 return x;
00556 }
00557
00558 #endif