BasicArray.h

00001 /*  _________________________________________________________________________
00002  *
00003  *  UTILIB: A utility library for developing portable C++ codes.
00004  *  Copyright (c) 2001, Sandia National Laboratories.
00005  *  This software is distributed under the GNU Lesser General Public License.
00006  *  For more information, see the README file in the top UTILIB directory.
00007  *  _________________________________________________________________________
00008  */
00009 
00010 //
00011 // BasicArray.h
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* /*data*/, const size_type /*start*/, 
00243                                         const size_type /*stop*/)
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)                      // Return unmodified array when
00495    return *this;                             // you are setting yourself.
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 // Copies an array without memory allocation.
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