$search
00001 00010 /***************************************************************************** 00011 ** Ifdefs 00012 *****************************************************************************/ 00013 00014 #ifndef ECL_CONTAINERS_STENCIL_STENCIL_HPP_ 00015 #define ECL_CONTAINERS_STENCIL_STENCIL_HPP_ 00016 00017 /***************************************************************************** 00018 ** Includes 00019 *****************************************************************************/ 00020 00021 #include <cstddef> // size_t 00022 #include <ecl/config/macros.hpp> 00023 #include <ecl/exceptions/standard_exception.hpp> 00024 #include <ecl/concepts/containers.hpp> 00025 #include <ecl/concepts/streams.hpp> 00026 #include "../initialiser.hpp" 00027 #include "formatters.hpp" 00028 00029 /***************************************************************************** 00030 ** Namespaces 00031 *****************************************************************************/ 00032 00033 namespace ecl 00034 { 00035 00036 /***************************************************************************** 00037 ** Interface 00038 *****************************************************************************/ 00071 template <typename Array> 00072 class ECL_PUBLIC Stencil 00073 { 00074 public: 00075 /********************* 00076 ** Typedefs 00077 **********************/ 00078 typedef typename Array::value_type value_type; 00079 // Looks like I'm now needing to rely on the underlying storage iterator definitions 00080 // Naturally, this means I can't do stencils of c arrays, but hey, thats dangerous anyway and we want to avoid that. 00081 typedef typename Array::iterator iterator; 00082 typedef typename Array::const_iterator const_iterator; 00083 typedef typename Array::reference reference; 00084 typedef typename Array::const_reference const_reference; 00085 // typedef typename Array::value_type* iterator; /**< @brief Uses the array's iterator type. **/ 00086 // typedef const typename Array::value_type* const_iterator; /**< @brief Uses the array's constant iterator type. **/ 00087 // typedef typename Array::value_type& reference; /**< @brief Uses the array's element reference type. **/ 00088 // typedef const typename Array::value_type& const_reference; /**< @brief Uses the array's element const reference type. **/ 00089 typedef std::size_t size_type; 00090 typedef std::ptrdiff_t difference_type; 00091 typedef std::reverse_iterator<iterator> reverse_iterator; 00092 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00093 typedef formatters::StencilFormatter<value_type,Array> Formatter; 00094 00095 /********************* 00096 ** C&D's 00097 **********************/ 00113 Stencil(Array& underlying_array, iterator begin_iter, iterator end_iter) ecl_assert_throw_decl(StandardException) : 00114 array(underlying_array), 00115 b_iter(begin_iter), 00116 e_iter(end_iter) 00117 { 00118 ecl_compile_time_concept_check(ContainerConcept<Array>); 00119 ecl_assert_throw((b_iter >= array.begin()) && (b_iter <= array.end()), StandardException(LOC, OutOfRangeError, "Begin iterator out of range.")); 00120 ecl_assert_throw((e_iter >= array.begin()) && (e_iter <= array.end()), StandardException(LOC, OutOfRangeError, "End iterator out of range.")); 00121 } 00122 00138 Stencil(Array& underlying_array, const unsigned int& start_index = 0, const unsigned int &n = 0) ecl_assert_throw_decl(StandardException) : 00139 array(underlying_array), 00140 b_iter(array.begin()+start_index), 00141 e_iter(array.begin()+start_index+n) 00142 { 00143 ecl_compile_time_concept_check(ContainerConcept<Array>); 00144 ecl_assert_throw((b_iter >= array.begin()) && (b_iter <= array.end()), StandardException(LOC, OutOfRangeError, "Begin iterator out of range.")); 00145 ecl_assert_throw((e_iter >= array.begin()) && (e_iter <= array.end()), StandardException(LOC, OutOfRangeError, "End iterator out of range.")); 00146 } 00147 00148 virtual ~Stencil() 00149 {}; 00150 00163 Stencil<Array> stencil(const unsigned int& start_index, const unsigned int& n) const ecl_assert_throw_decl(StandardException) 00164 { 00165 ecl_assert_throw( b_iter+start_index < array.end(), StandardException(LOC, OutOfRangeError, "Start index provided is larger than the underlying stencil size.")); 00166 ecl_assert_throw( b_iter+start_index+n <= array.end(), StandardException(LOC, OutOfRangeError, "Finish index provided is larger than the underlying stencil size.")); 00167 return Stencil<Array>(array,b_iter+start_index,b_iter+start_index+n); 00168 } 00169 00181 void resettle(const unsigned int& start_index, const unsigned int& n) ecl_assert_throw_decl(StandardException) 00182 { 00183 00184 b_iter = array.begin()+start_index; 00185 e_iter = array.begin()+start_index+n; 00186 ecl_assert_throw((b_iter >= array.begin()) && (b_iter <= array.end()), StandardException(LOC, OutOfRangeError, "Begin iterator out of range.")); 00187 ecl_assert_throw((e_iter >= array.begin()) && (e_iter <= array.end()), StandardException(LOC, OutOfRangeError, "End iterator out of range.")); 00188 } 00189 00190 /********************* 00191 ** Assignment 00192 **********************/ 00206 containers::BoundedListInitialiser<value_type,value_type*> operator<< (const value_type &value) 00207 { 00208 return containers::BoundedListInitialiser<value_type,iterator>(value, begin, size()); 00209 } 00240 Stencil<Array>& operator=(const Stencil<Array> &s) ecl_assert_throw_decl(StandardException) 00241 { 00242 if ( &array == &(s.array) ) 00243 { // resettle 00244 b_iter = s.b_iter; 00245 e_iter = s.e_iter; 00246 } 00247 else 00248 { // copy 00249 ecl_assert_throw( s.size() <= size(), StandardException(LOC, OutOfRangeError, "Stencil to be copied is larger than this stencil's size.")); 00250 for ( unsigned int i = 0; i < s.size(); ++i ) 00251 { 00252 *(b_iter+i) = *(s.b_iter+i); 00253 } 00254 } 00255 return *this; 00256 } 00257 00258 /********************* 00259 ** Iterators 00260 **********************/ 00266 iterator begin() ecl_assert_throw_decl(StandardException) 00267 { 00268 ecl_assert_throw( b_iter <= array.end(), StandardException(LOC,OutOfRangeError)); 00269 return b_iter; 00270 } 00276 const_iterator begin() const ecl_assert_throw_decl(StandardException) 00277 { 00278 ecl_assert_throw( b_iter <= array.end(), StandardException(LOC,OutOfRangeError)); 00279 return b_iter; 00280 } 00286 iterator end() ecl_assert_throw_decl(StandardException) 00287 { 00288 ecl_assert_throw( e_iter <= array.end(), StandardException(LOC,OutOfRangeError)); 00289 return e_iter; 00290 } 00296 const_iterator end() const ecl_assert_throw_decl(StandardException) 00297 { 00298 ecl_assert_throw( e_iter <= array.end(), StandardException(LOC,OutOfRangeError)); 00299 return e_iter; 00300 } 00306 reverse_iterator rbegin() ecl_assert_throw_decl(StandardException) 00307 { 00308 ecl_assert_throw( e_iter <= array.end(), StandardException(LOC,OutOfRangeError)); 00309 return reverse_iterator(end()); 00310 } 00316 const_reverse_iterator rbegin() const ecl_assert_throw_decl(StandardException) 00317 { 00318 ecl_assert_throw( e_iter <= array.end(), StandardException(LOC,OutOfRangeError)); 00319 return const_reverse_iterator(end()); 00320 } 00326 reverse_iterator rend() ecl_assert_throw_decl(StandardException) 00327 { 00328 ecl_assert_throw( b_iter <= array.end(), StandardException(LOC,OutOfRangeError)); 00329 return reverse_iterator(begin()); 00330 } 00336 const_reverse_iterator rend() const ecl_assert_throw_decl(StandardException) 00337 { 00338 ecl_assert_throw( b_iter <= array.end(), StandardException(LOC,OutOfRangeError)); 00339 return const_reverse_iterator(begin()); 00340 } 00341 00342 /********************* 00343 ** Front/Back 00344 **********************/ 00350 reference front() ecl_assert_throw_decl(StandardException) 00351 { 00352 ecl_assert_throw( b_iter <= array.end(), StandardException(LOC,OutOfRangeError)); 00353 return *b_iter; 00354 } 00360 const_reference front() const ecl_assert_throw_decl(StandardException) 00361 { 00362 ecl_assert_throw( b_iter <= array.end(), StandardException(LOC,OutOfRangeError)); 00363 return *b_iter; 00364 } 00370 reference back() ecl_assert_throw_decl(StandardException) 00371 { 00372 ecl_assert_throw( e_iter <= array.end(), StandardException(LOC,OutOfRangeError)); 00373 return *(e_iter-1); 00374 } 00380 const_reference back() const ecl_assert_throw_decl(StandardException) 00381 { 00382 ecl_assert_throw( e_iter <= array.end(), StandardException(LOC,OutOfRangeError)); 00383 return *(e_iter-1); 00384 } 00385 00386 /********************* 00387 ** Accessors 00388 **********************/ 00398 reference operator[](size_type i) ecl_assert_throw_decl(StandardException) 00399 { 00400 ecl_assert_throw( b_iter+i >= array.begin(), StandardException(LOC,OutOfRangeError)); 00401 ecl_assert_throw( b_iter+i <= array.end(), StandardException(LOC,OutOfRangeError)); 00402 return *(b_iter+i); 00403 } 00415 const_reference operator[](size_type i) const ecl_assert_throw_decl(StandardException) 00416 { 00417 ecl_assert_throw( b_iter+i >= array.begin(), StandardException(LOC,OutOfRangeError)); 00418 ecl_assert_throw( b_iter+i <= array.end(), StandardException(LOC,OutOfRangeError)); 00419 return *(b_iter+i); 00420 } 00431 reference at(size_type i) throw(StandardException) 00432 { 00433 if ( b_iter+i <= array.begin() ) 00434 { 00435 throw StandardException(LOC,OutOfRangeError); 00436 } 00437 if ( b_iter+i >= array.end() ) 00438 { 00439 throw StandardException(LOC,OutOfRangeError); 00440 } 00441 return *(b_iter+i); 00442 } 00455 const_reference at(size_type i) const throw(StandardException) 00456 { 00457 if ( b_iter+i <= array.begin() ) 00458 { 00459 throw StandardException(LOC,OutOfRangeError); 00460 } 00461 if ( b_iter+i >= array.end() ) 00462 { 00463 throw StandardException(LOC,OutOfRangeError); 00464 } 00465 return *(b_iter+i); 00466 } 00467 00468 /********************* 00469 ** Utilities 00470 **********************/ 00476 size_type size() const 00477 { return e_iter-b_iter;} 00478 00479 /********************* 00480 ** Streaming 00481 **********************/ 00497 template <typename OutputStream, typename ArrayType> 00498 friend OutputStream& operator<<(OutputStream &ostream , const Stencil<ArrayType> &stencil); 00499 00500 private: 00501 Array& array; 00502 iterator b_iter, e_iter; 00503 }; 00504 00505 /***************************************************************************** 00506 ** Implementation [Streaming] 00507 *****************************************************************************/ 00508 00509 template<typename OutputStream, typename ArrayType> 00510 OutputStream& operator<<(OutputStream &ostream, const Stencil<ArrayType> &stencil) 00511 { 00512 00513 ecl_compile_time_concept_check (StreamConcept<OutputStream> ); 00514 00515 ostream << "[ "; 00516 for (std::size_t i = 0; i < stencil.size(); ++i) 00517 { 00518 ostream << stencil[i] << " "; 00519 } 00520 ostream << "]"; 00521 ostream.flush(); 00522 00523 return ostream; 00524 } 00525 00526 } // namespace ecl 00527 00528 #endif /* ECL_CONTAINERS_STENCIL_STENCIL_HPP_ */