Scopira 20080306

array.h

00001 
00002 /*
00003  *  Copyright (c) 2002-2004    National Research Council
00004  *
00005  *  All rights reserved.
00006  *
00007  *  This material is confidential and proprietary information of
00008  *  National Research Council Canada ("Confidential Information").
00009  *  This Confidential Information may only be used and reproduced
00010  *  in accordance with the terms of the license agreement.
00011  *
00012  */
00013 
00014 #ifndef __INCLUDED_SCOPIRA_TOOL_ARRAY_H__
00015 #define __INCLUDED_SCOPIRA_TOOL_ARRAY_H__
00016 
00017 #include <assert.h>
00018 #include <stddef.h>    //for size_t
00019 #include <string.h>    //for memset
00020 
00021 // THIS FILE HAS BEEN FULLY DOCUMENTED
00022 
00023 namespace scopira
00024 {
00025   namespace tool
00026   {
00027     template <class T> class array_view;
00028     template <class T> class const_array_view;
00029 
00030     template <class T> class basic_array;
00031     template <class T> class basic_matrix;
00032     template <class T, size_t N> class fixed_array;
00033     template <class T, size_t N> class hybrid_array;
00034   }
00035 }
00036 
00041 template <class T> class scopira::tool::array_view
00042 {
00043   public:
00044     typedef T data_type;
00045     typedef T* iterator;
00046     typedef const T* const_iterator;
00047   protected:
00048     T *dm_ary, *dm_end;
00049 
00050   public:
00055     array_view(basic_array<T> &rhs) : dm_ary(rhs.begin()), dm_end(rhs.end()) { }
00060     array_view(T *b, T *e) : dm_ary(b), dm_end(e) { }
00065     template <size_t N>
00066       array_view(fixed_array<T, N> &rhs) : dm_ary(rhs.begin()), dm_end(rhs.end()) { }
00071     template <size_t N>
00072       array_view(hybrid_array<T, N> &rhs) : dm_ary(rhs.begin()), dm_end(rhs.end()) { }
00077     T * array(void) { return dm_ary; }
00082     const T * array(void) const { return dm_ary; }
00087     T * c_array(void) { return dm_ary; }
00092     const T * c_array(void) const { return dm_ary; }
00097     iterator begin(void) { return dm_ary; }
00102     iterator end(void) { return dm_end; }
00107     const_iterator begin(void) const { return dm_ary; }
00112     const_iterator end(void) const { return dm_end; }
00113 
00120     void clear_zero(void) { ::memset(dm_ary, 0, sizeof(T)*(size())); }
00121 
00126     size_t size(void) const { return dm_end - dm_ary; }
00131     bool empty(void) const { return dm_ary == dm_end; }
00132 
00137     void set(size_t idx, const T &v) {
00138       assert("[array_view element access was out of bounds]" && (dm_ary+idx)<dm_end);
00139       dm_ary[idx] = v;
00140     }
00145     const T & get(size_t idx) const {
00146       assert("[array_view element access was out of bounds]" && (dm_ary+idx)<dm_end);
00147       return dm_ary[idx];
00148     }
00153     T & get(size_t idx) {
00154       assert("[array_view element access was out of bounds]" && (dm_ary+idx)<dm_end);
00155       return dm_ary[idx];
00156     }
00161     const T & operator[](size_t idx) const {
00162       assert("[array_view element access was out of bounds]" && (dm_ary+idx)<dm_end);
00163       return dm_ary[idx];
00164     }
00169     T & operator[](size_t idx) {
00170       assert("[array_view element access was out of bounds]" && (dm_ary+idx)<dm_end);
00171       return dm_ary[idx];
00172     }
00173 };
00174 
00179 template <class T> class scopira::tool::const_array_view
00180 {
00181   public:
00182     typedef T data_type;
00183     typedef const T* const_iterator;
00184   protected:
00185     const T *dm_ary, *dm_end;
00186 
00187   public:
00193     const_array_view(array_view<T> rhs) : dm_ary(rhs.begin()), dm_end(rhs.end()) { }
00198     const_array_view(const basic_array<T> &rhs) : dm_ary(rhs.begin()), dm_end(rhs.end()) { }
00203     const_array_view(const T *b, const T *e) : dm_ary(b), dm_end(e) { }
00208     template <size_t N>
00209       const_array_view(const fixed_array<T, N> &rhs) : dm_ary(rhs.begin()), dm_end(rhs.end()) { }
00214     template <size_t N>
00215       const_array_view(const hybrid_array<T, N> &rhs) : dm_ary(rhs.begin()), dm_end(rhs.end()) { }
00220     const T * array(void) const { return dm_ary; }
00225     const T * c_array(void) const { return dm_ary; }
00230     const_iterator begin(void) const { return dm_ary; }
00235     const_iterator end(void) const { return dm_end; }
00236 
00241     size_t size(void) const { return dm_end - dm_ary; }
00246     bool empty(void) const { return dm_ary == dm_end; }
00247 
00252     const T & get(size_t idx) const {
00253       assert("[const_array_view element access was out of bounds]" && (dm_ary+idx)<dm_end);
00254       return dm_ary[idx];
00255     }
00260     const T & operator[](size_t idx) const {
00261       assert("[const_array_view element access was out of bounds]" && (dm_ary+idx)<dm_end);
00262       return dm_ary[idx];
00263     }
00264 };
00265 
00275 template <class T> class scopira::tool::basic_array
00276 {
00277   public:
00278     typedef T data_type;
00279     typedef T* iterator;
00280     typedef const T* const_iterator;
00281   protected:
00282     T *dm_ary;
00283     size_t dm_len;
00284   public:
00289     basic_array(void) : dm_ary(0), dm_len(0) { }
00298     explicit basic_array(size_t len) : dm_ary(0), dm_len(0) { resize(len); }
00303     basic_array(const basic_array &rhs);
00305     ~basic_array() { resize(0); }
00306 
00318     void resize(size_t newlen);
00319 
00329     void array_swap(basic_array<T> &other) {
00330       T *ary = dm_ary;
00331       size_t len = dm_len;
00332       dm_ary = other.dm_ary;
00333       dm_len = other.dm_len;
00334       other.dm_ary = ary;
00335       other.dm_len = len;
00336     }
00341     T * array(void) { return dm_ary; }
00346     const T * array(void) const { return dm_ary; }
00351     T * c_array(void) { return dm_ary; }
00356     const T * c_array(void) const { return dm_ary; }
00361     iterator begin(void) { return dm_ary; }
00366     iterator end(void) { return dm_ary+dm_len; }
00371     const_iterator begin(void) const { return dm_ary; }
00376     const_iterator end(void) const { return dm_ary+dm_len; }
00377 
00382     basic_array & operator=(const basic_array &rhs);
00387     void clear(void) { resize(0); }
00394     void clear_zero(void) { ::memset(dm_ary, 0, sizeof(T)*dm_len); }
00395 
00400     size_t size(void) const { return dm_len; }
00405     bool empty(void) const { return dm_len == 0; }
00406 
00411     void set(size_t idx, const T &v) {
00412       assert("[basic_array element access was out of bounds]" && idx<dm_len);
00413       dm_ary[idx] = v;
00414     }
00419     const T & get(size_t idx) const {
00420       assert("[basic_array element access was out of bounds]" && idx<dm_len);
00421       return dm_ary[idx];
00422     }
00427     T & get(size_t idx) {
00428       assert("[basic_array element access was out of bounds]" && idx<dm_len);
00429       return dm_ary[idx];
00430     }
00435     const T & operator[](size_t idx) const {
00436       assert("[basic_array element access was out of bounds]" && idx<dm_len);
00437       return dm_ary[idx];
00438     }
00443     T & operator[](size_t idx) {
00444       assert("[basic_array element access was out of bounds]" && idx<dm_len);
00445       return dm_ary[idx];
00446     }
00447 };
00448 
00449 template <class T>
00450   scopira::tool::basic_array<T>::basic_array(const basic_array &rhs)
00451   : dm_ary(0), dm_len(0)
00452 {
00453   if (rhs.dm_len>0) {
00454     resize(rhs.dm_len);
00455     iterator ii, endii = end();
00456     const_iterator jj;
00457     // copy
00458     for (ii=begin(), jj=rhs.begin(); ii != endii; ++ii, ++jj)
00459       *ii = *jj;
00460   }
00461 }
00462 
00463 template <class T>
00464   void scopira::tool::basic_array<T>::resize(size_t newlen)
00465 {
00466   if (dm_len == newlen)
00467     return; // no need to change anything
00468   if (dm_len > 0)
00469     delete []dm_ary;
00470   dm_len = newlen;
00471   if (dm_len == 0)
00472     dm_ary = 0;
00473   else
00474     dm_ary = new T[dm_len];
00475 }
00476 
00477 template <class T>
00478   scopira::tool::basic_array<T> & scopira::tool::basic_array<T>::operator=(const basic_array &rhs)
00479 {
00480   resize(rhs.dm_len);
00481 
00482   iterator ii, endii = end();
00483   const_iterator jj;
00484   // copy
00485   for (ii=begin(), jj=rhs.begin(); ii != endii; ++ii, ++jj)
00486     *ii = *jj;
00487 
00488   return *this;
00489 }
00490 
00496 template <class T> class scopira::tool::basic_matrix : public scopira::tool::basic_array<T>
00497 {
00498   private:
00499     typedef scopira::tool::basic_array<T> parent_type;
00500   protected:
00501     size_t dm_w, dm_h;
00502   public:
00507     basic_matrix(void) {
00508       dm_w = dm_h = 0;
00509     }
00514     basic_matrix(size_t w, size_t h) {
00515       dm_w = w;
00516       dm_h = h;
00517       resize(dm_w*dm_h);
00518     }
00525     void resize(size_t w, size_t h) {
00526       dm_w = w;
00527       dm_h = h;
00528       resize(dm_w*dm_h);
00529     }
00530 
00535     size_t width(void) const { return dm_w; }
00540     size_t height(void) const { return dm_h; }
00541 
00546     void set(size_t x, size_t y, const T &v) {
00547       assert("[basic_matrix x axis out of bounds]" && x<dm_w);
00548       assert("[basic_matrix y axis out of bounds]" && y<dm_h);
00549       basic_array<T>::dm_ary[y*dm_w+x] = v;
00550     }
00555     const T & get(size_t x, size_t y) const {
00556       assert("[basic_matrix x axis out of bounds]" && x<dm_w);
00557       assert("[basic_matrix y axis out of bounds]" && y<dm_h);
00558       return basic_array<T>::dm_ary[y*dm_w+x];
00559     }
00564     T & get(size_t x, size_t y) {
00565       assert("[basic_matrix x axis out of bounds]" && x<dm_w);
00566       assert("[basic_matrix y axis out of bounds]" && y<dm_h);
00567       return basic_array<T>::dm_ary[y*dm_w+x];
00568     }
00573     const T & operator()(size_t x, size_t y) const {
00574       assert("[basic_matrix x axis out of bounds]" && x<dm_w);
00575       assert("[basic_matrix y axis out of bounds]" && y<dm_h);
00576       return basic_array<T>::dm_ary[y*dm_w+x];
00577     }
00582     T & operator()(size_t x, size_t y) {
00583       assert("[basic_matrix x axis out of bounds]" && x<dm_w);
00584       assert("[basic_matrix y axis out of bounds]" && y<dm_h);
00585       return basic_array<T>::dm_ary[y*dm_w+x];
00586     }
00587 
00588   protected:
00589     // lets hide this from the 2D users
00590     void resize(size_t newlen) {
00591       parent_type::resize(newlen);
00592     }
00593 };
00594 
00607 template <class T, size_t N> class scopira::tool::fixed_array
00608 {
00609   public:
00610     typedef T data_type;
00611     typedef T* iterator;
00612     enum { size_c = N };
00613     typedef const T* const_iterator;
00614   protected:
00615     T dm_ary[N];
00616 
00617   public:
00622     T * array(void) { return dm_ary; }
00627     const T * array(void) const { return dm_ary; }
00632     T * c_array(void) { return dm_ary; }
00637     const T * c_array(void) const { return dm_ary; }
00642     iterator begin(void) { return dm_ary; }
00647     iterator end(void) { return dm_ary+N; }
00652     const_iterator begin(void) const { return dm_ary; }
00657     const_iterator end(void) const { return dm_ary+N; }
00664     void clear_zero(void) { ::memset(dm_ary, 0, sizeof(T)*N); }
00669     size_t size(void) const { return N; }
00674     bool empty(void) const { return false; }
00675 
00680     void set(size_t idx, const T &v) {
00681       assert("[fixed_array element access out of bounds]" && idx<N);
00682       dm_ary[idx] = v;
00683     }
00688     const T & get(size_t idx) const {
00689       assert("[fixed_array element access out of bounds]" && idx<N);
00690       return dm_ary[idx];
00691     }
00696     T & get(size_t idx) {
00697       assert("[fixed_array element access out of bounds]" && idx<N);
00698       return dm_ary[idx];
00699     }
00704     const T & operator[](size_t idx) const {
00705       assert("[fixed_array element access out of bounds]" && idx<N);
00706       return dm_ary[idx];
00707     }
00712     T & operator[](size_t idx) {
00713       assert("[fixed_array element access out of bounds]" && idx<N);
00714       return dm_ary[idx];
00715     }
00716 };
00717 
00733 template <class T, size_t RES> class scopira::tool::hybrid_array
00734 {
00735   public:
00736     typedef T data_type;
00737     typedef T* iterator;
00738     typedef const T* const_iterator;
00739   protected:
00740     fixed_array<T, RES> dm_fixed;
00741     basic_array<T> dm_basic;
00742 
00743     T *dm_ary;
00744     size_t dm_len;
00745 
00746   public:
00751     hybrid_array(void);
00760     explicit hybrid_array(size_t len);
00765     hybrid_array(const hybrid_array &rhs);
00770     hybrid_array(const_array_view<T> rhs);
00772     ~hybrid_array() { }
00773 
00785     void resize(size_t newlen);
00790     T * array(void) { return dm_ary; }
00795     const T * array(void) const { return dm_ary; }
00800     T * c_array(void) { return dm_ary; }
00805     const T * c_array(void) const { return dm_ary; }
00810     iterator begin(void) { return dm_ary; }
00815     iterator end(void) { return dm_ary+dm_len; }
00820     const_iterator begin(void) const { return dm_ary; }
00825     const_iterator end(void) const { return dm_ary+dm_len; }
00826 
00831     hybrid_array & operator=(const hybrid_array &rhs);
00836     hybrid_array & operator=(const_array_view<T> rhs);
00841     void clear(void) { resize(0); }
00848     void clear_zero(void) { ::memset(dm_ary, 0, sizeof(T)*dm_len); }
00849 
00854     size_t size(void) const { return dm_len; }
00859     bool empty(void) const { return dm_len == 0; }
00860 
00865     void set(size_t idx, const T &v) {
00866       assert("[hybrid_array element access was out of bounds]" && idx<dm_len);
00867       dm_ary[idx] = v;
00868     }
00873     const T & get(size_t idx) const {
00874       assert("[hybrid_array element access was out of bounds]" && idx<dm_len);
00875       return dm_ary[idx];
00876     }
00881     T & get(size_t idx) {
00882       assert("[hybrid_array element access was out of bounds]" && idx<dm_len);
00883       return dm_ary[idx];
00884     }
00889     const T & operator[](size_t idx) const {
00890       assert("[hybrid_array element access was out of bounds]" && idx<dm_len);
00891       return dm_ary[idx];
00892     }
00897     T & operator[](size_t idx) {
00898       assert("[hybrid_array element access was out of bounds]" && idx<dm_len);
00899       return dm_ary[idx];
00900     }
00901 };
00902 
00903 template <class T, size_t RES>
00904   scopira::tool::hybrid_array<T,RES>::hybrid_array(void)
00905   : dm_ary(0), dm_len(0)
00906 {
00907 }
00908 
00909 template <class T, size_t RES>
00910   scopira::tool::hybrid_array<T,RES>::hybrid_array(size_t len)
00911   : dm_ary(0), dm_len(0)
00912 {
00913   resize(len);
00914 }
00915 
00916 template <class T, size_t RES>
00917   scopira::tool::hybrid_array<T,RES>::hybrid_array(const hybrid_array &rhs)
00918   : dm_ary(0), dm_len(0)
00919 {
00920   resize(rhs.size());
00921   if (!empty()) {
00922     iterator ii, endii = end();
00923     const_iterator jj;
00924     // copy
00925     for (ii=begin(), jj=rhs.begin(); ii != endii; ++ii, ++jj)
00926       *ii = *jj;
00927   }
00928 }
00929 
00930 template <class T, size_t RES>
00931   scopira::tool::hybrid_array<T,RES>::hybrid_array(const_array_view<T> rhs)
00932   : dm_ary(0), dm_len(0)
00933 {
00934   resize(rhs.size());
00935   if (!empty()) {
00936     iterator ii, endii = end();
00937     const_iterator jj;
00938     // copy
00939     for (ii=begin(), jj=rhs.begin(); ii != endii; ++ii, ++jj)
00940       *ii = *jj;
00941   }
00942 }
00943 
00944 template <class T, size_t RES>
00945   void scopira::tool::hybrid_array<T,RES>::resize(size_t newlen)
00946 {
00947   if (dm_len == newlen)
00948     return; // no need to change anything
00949   if (dm_len > RES)
00950     dm_basic.resize(0);
00951   dm_len = newlen;
00952   if (dm_len == 0)
00953     dm_ary = 0;
00954   else if (dm_len <= RES)
00955     dm_ary = dm_fixed.c_array();
00956   else {
00957     dm_basic.resize(dm_len);
00958     dm_ary = dm_basic.c_array();
00959   }
00960 }
00961 
00962 template <class T, size_t RES>
00963   scopira::tool::hybrid_array<T,RES> & scopira::tool::hybrid_array<T,RES>::operator=(const hybrid_array &rhs)
00964 {
00965   resize(rhs.dm_len);
00966 
00967   iterator ii, endii = end();
00968   const_iterator jj;
00969   // copy
00970   for (ii=begin(), jj=rhs.begin(); ii != endii; ++ii, ++jj)
00971     *ii = *jj;
00972 
00973   return *this;
00974 }
00975 
00976 template <class T, size_t RES>
00977   scopira::tool::hybrid_array<T,RES> & scopira::tool::hybrid_array<T,RES>::operator=(const_array_view<T> rhs)
00978 {
00979   resize(rhs.size());
00980 
00981   iterator ii, endii = end();
00982   const_iterator jj;
00983   // copy
00984   for (ii=begin(), jj=rhs.begin(); ii != endii; ++ii, ++jj)
00985     *ii = *jj;
00986 
00987   return *this;
00988 }
00989 
01082 #endif
01083