|
STK++ 1.0
|
00001 /*--------------------------------------------------------------------*/ 00002 /* Copyright (C) 2004 Serge Iovleff 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU Lesser General Public License as 00006 published by the Free Software Foundation; either version 2 of the 00007 License, or (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public 00015 License along with this program; if not, write to the 00016 Free Software Foundation, Inc., 00017 59 Temple Place, 00018 Suite 330, 00019 Boston, MA 02111-1307 00020 USA 00021 00022 Contact : Serge.Iovleff@stkpp.org 00023 */ 00024 00025 /* 00026 * Project: stkpp::Arrays 00027 * Purpose: Define the Base Interface for the Array classes. 00028 * Author: Serge Iovleff, serge.iovleff@stkpp.org 00029 * 00030 **/ 00031 00036 #ifndef STK_IARRAYBASE_H 00037 #define STK_IARRAYBASE_H 00038 00039 #include <stdexcept> 00040 00041 #include "../../Sdk/include/STK_IContainerRef.h" 00042 #include "../../STKernel/include/STK_Range.h" 00043 00044 namespace STK 00045 { 00046 00058 template<class DATA> 00059 class IArrayBase : public IContainerRef 00060 { 00061 protected: 00065 IArrayBase( Range const& I = Range()) : IContainerRef(false) 00066 , p_data_(0) 00067 , rangeData_(I) 00068 { mallocPtrData( I.size(), I.first());} 00069 00074 IArrayBase( const IArrayBase& T, bool ref = false) 00075 : IContainerRef(ref) 00076 { 00077 if (ref) // set T data 00078 { 00079 p_data_ = T.p_data_; 00080 rangeData_ = T.rangeData_; 00081 } 00082 else // Allocate memory in base class 00083 { 00084 setDefault(); 00085 } 00086 } 00087 00092 IArrayBase(DATA* q, Range const& I) : IContainerRef(true) 00093 , p_data_(q) 00094 , rangeData_(I) 00095 { ;} 00096 00097 public: 00099 virtual ~IArrayBase() 00100 { if (!this->isRef()) this->freePtrData(); } 00101 00105 inline Integer const& firstData() const { return rangeData_.first();} 00109 inline Integer const& lastData() const { return rangeData_.last();} 00113 inline Integer const& sizeData() const { return rangeData_.size();} 00117 inline Range const& rangeData() const { return rangeData_;} 00121 inline DATA const* const ptrData() const { return p_data_;} 00122 00126 inline DATA const& data( Integer const& pos) const 00127 { 00128 #ifdef STK_BOUNDS_CHECK 00129 if (pos < firstData()) 00130 { throw std::out_of_range("IArrayBase::data(pos) const " 00131 "IArrayBase::firstData() > pos"); 00132 } 00133 if (pos > lastData()) 00134 { throw std::out_of_range("IArrayBase::data(pos) const " 00135 "IArrayBase::lastData() < pos"); 00136 } 00137 #endif 00138 return p_data_[pos]; 00139 } 00140 00145 static Integer evalCapacity(Integer const& m) 00146 { 00147 Integer n = 0; 00148 Integer b = m; 00149 for (Integer k=1 ; k <= b; n++, k <<= 1); 00150 return m+n; 00151 } 00152 00153 protected: 00155 inline DATA* ptrData() 00156 { return p_data_;} 00157 00161 inline DATA& data(Integer const& pos) 00162 { 00163 #ifdef STK_BOUNDS_CHECK 00164 if (pos < firstData()) 00165 { throw std::out_of_range("IArrayBase::data(pos) " 00166 "IArrayBase::firstData() > pos"); 00167 } 00168 if (pos > lastData()) 00169 { throw std::out_of_range("IArrayBase::data(pos) " 00170 "IArrayBase::lastData() < pos"); 00171 } 00172 #endif 00173 return p_data_[pos]; 00174 } 00175 00182 inline void setData( Integer const& pos, DATA const& data = DATA()) 00183 { 00184 #ifdef STK_BOUNDS_CHECK 00185 if (pos < firstData()) 00186 { throw std::out_of_range("IArrayBase::setData(pos, data) " 00187 "IArrayBase::firstData() > pos"); 00188 } 00189 if (pos > lastData()) 00190 { throw std::out_of_range("IArrayBase::setData(pos, data) " 00191 "IArrayBase::lastData() > pos"); 00192 } 00193 #endif 00194 p_data_[pos] = data; 00195 } 00196 00200 void swap(IArrayBase &T) 00201 { 00202 // copy main ptr data and range of this 00203 DATA* auxMainPtr(p_data_); 00204 Range auxRange(rangeData_); 00205 bool auxRef(this->isRef()); 00206 00207 // overwrite main ptr data of this 00208 this->setPtrData(T.p_data_); 00209 this->setRangeData(T.rangeData_); 00210 this->setRef(T.isRef()); 00211 00212 // overwrite main PTRCOL of T 00213 T.setPtrData(auxMainPtr); 00214 T.setRangeData(auxRange); 00215 T.setRef(auxRef); 00216 } 00217 00221 void shiftPtrData(Integer const& first) 00222 { 00223 // check if there is something to do 00224 if (first == firstData()) return; 00225 // check for reference 00226 if (this->isRef()) 00227 { throw std::runtime_error("In IArrayBase::shiftPtrData(first)" 00228 " can't operate on reference."); 00229 } 00230 // compute increment 00231 Integer inc = first - firstData(); 00232 // translate data 00233 decPtrData(inc); 00234 } 00239 void mallocPtrData( Integer const& size, Integer const& inc = 0) 00240 { 00241 // check for reference 00242 if (this->isRef()) 00243 { throw std::runtime_error("In IArrayBase::mallocPtrData(first)" 00244 " can't operate on reference."); 00245 } 00246 // delete any memory allocated 00247 freePtrData(); 00248 // check size 00249 if (size <= 0) 00250 { 00251 // set initial values 00252 setRangeData(Range(0,size-1)); 00253 // first index is 0 00254 return; 00255 } 00256 // allocate memory 00257 try 00258 { 00259 setPtrData(new DATA[size]); 00260 } 00261 catch (std::bad_alloc & error) // if an alloc error occur 00262 { 00263 // initialize to default 00264 setDefault(); 00265 // and throw an exception 00266 throw std::runtime_error("IArrayBase::mallocPtrData(size, inc) " 00267 "memory allocation failed."); 00268 } 00269 // set initial values 00270 setRangeData(Range(0,size-1)); // first index is 0 00271 // apply increment 00272 decPtrData(inc); 00273 } 00274 00287 void reallocPtrData( Integer const& size, Integer const& inc = 0) 00288 { 00289 // check for reference 00290 if (this->isRef()) 00291 { throw std::runtime_error("In IArrayBase::reallocPtrData(first)" 00292 " can't operate on reference."); 00293 } 00294 // if there is no memory allocated, we use mallocPtrData 00295 if (!p_data_) 00296 { 00297 mallocPtrData(size, inc); 00298 return; 00299 } 00300 // if the new size is empty we can safely remove existing data 00301 if (size <= 0) 00302 { 00303 freePtrData(); 00304 return; 00305 } 00306 // reset to zero increment and get data adress 00307 incPtrData(firstData()); 00308 DATA* p_data = p_data_; 00309 // allocate memory 00310 try 00311 { 00312 setPtrData(new DATA[size]); 00313 } 00314 catch (std::bad_alloc & error) // if an alloc error occur 00315 { 00316 // delete existing data 00317 delete [] p_data; 00318 // initialize members to default 00319 setDefault(); 00320 // and throw an exception 00321 throw std::runtime_error("IArrayBase::reallocPtrData(size, inc) " 00322 "memory allocation failed."); 00323 } 00324 // copy existing data 00325 Integer nbData = min(size, sizeData()); 00326 for (Integer i=0; i< nbData; i++) 00327 { p_data_[i] = p_data[i];} 00328 // delete previous allocated data 00329 // delete existing data 00330 delete [] p_data; 00331 // set initial values 00332 setRangeData(Range(0,size-1)); // first index is 0 00333 // apply increment 00334 decPtrData(inc); 00335 } 00336 00338 void freePtrData() 00339 { 00340 // nothing to do for ref 00341 if (this->isRef()) return; 00342 // if there is elts 00343 if (p_data_) 00344 { 00345 incPtrData(firstData()); // translate 00346 delete [] p_data_; // erase 00347 setPtrData(); // set default values 00348 } 00349 } 00350 00355 inline void setPtrData( DATA* p_data = 0) 00356 { p_data_ = p_data;} 00357 00362 inline void setRangeData( Range const& rangeData = Range()) 00363 { rangeData_ = rangeData;} 00364 00365 private: 00370 inline void incPtrData( Integer const& inc) 00371 { 00372 // translate p_data_ only if there exists data 00373 if (this->p_data_) { p_data_ += inc;} 00374 rangeData_.dec(inc); 00375 } 00376 00381 inline void decPtrData( Integer const& dec) 00382 { 00383 // translate p_data_ only if there exists data 00384 if (this->p_data_) { p_data_ -= dec;} 00385 rangeData_.inc(dec); 00386 } 00387 00389 inline void setDefault() 00390 { 00391 setPtrData(); 00392 setRangeData(); 00393 } 00394 00395 private: 00397 DATA* p_data_; 00399 Range rangeData_; 00400 }; 00401 00402 } // namespace STK 00403 00404 #endif 00405 // STK_IARRAYBASE_H