Teuchos - Trilinos Tools Package Version of the Day
Teuchos_Array.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #ifndef TEUCHOS_ARRAY_H
00043 #define TEUCHOS_ARRAY_H
00044 
00049 #include "Teuchos_ConfigDefs.hpp"
00050 #include "Teuchos_TestForException.hpp"
00051 #include "Teuchos_TypeNameTraits.hpp"
00052 #include "Teuchos_ArrayRCP.hpp"
00053 #include "Teuchos_Tuple.hpp"
00054 #include "Teuchos_Utils.hpp"
00055 #include "Teuchos_Assert.hpp"
00056 
00057 
00058 namespace Teuchos {
00059 
00060 
00065 class InvalidArrayStringRepresentation : public std::logic_error
00066 {public:InvalidArrayStringRepresentation(const std::string& what_arg) : std::logic_error(what_arg) {}};
00067 
00068 
00069 template<typename T> class Array;
00070 
00071 
00072 // 2007/11/30: rabartl: Below, I had to move the initial declaration of these
00073 // non-member template functions outside of the Array class since the Sun
00074 // compiler on sass9000 would not accept this.  However, this did work on a
00075 // number of other compilers such a g++, Intel C++ etc.  The old in-class
00076 // non-member friend definition is clearly ISO 98 C++ as shown in Item 46 of
00077 // "Effective C++: Third Edition".  This is not the end of the world but this
00078 // is something to remember for this platform.
00079 
00080 
00085 template<typename T> inline
00086 bool operator==( const Array<T> &a1, const Array<T> &a2 );
00087 
00088 
00093 template<typename T> inline
00094 bool operator!=( const Array<T> &a1, const Array<T> &a2 );
00095 
00096 
00101 template<typename T> inline
00102 void swap( Array<T> &a1, Array<T> &a2 );
00103 
00104 
00109 template<typename T> inline
00110 bool operator<( const Array<T> &a1, const Array<T> &a2 );
00111 
00112 
00117 template<typename T> inline
00118 bool operator<=( const Array<T> &a1, const Array<T> &a2 );
00119 
00120 
00125 template<typename T> inline
00126 bool operator>( const Array<T> &a1, const Array<T> &a2 );
00127 
00128 
00133 template<typename T> inline
00134 bool operator>=( const Array<T> &a1, const Array<T> &a2 );
00135 
00136 
00174 template<typename T>
00175 class Array
00176 {
00177 public:
00178 
00179   // 2007/11/30: rabartl: Below, note that the only reason that these
00180   // functions are declared as friends is so that the compiler will do
00181   // automatic type conversions as described in "Effective C++: Third Edition"
00182   // Item 46.
00183 
00185   template<typename T2>
00186   friend bool Teuchos::operator==( const Array<T2> &a1, const Array<T2> &a2 );
00187 
00189   template<typename T2>
00190   friend bool Teuchos::operator!=( const Array<T2> &a1, const Array<T2> &a2 );
00191 
00193   template<typename T2>
00194   friend void swap( Array<T2> &a1, Array<T2> &a2 );
00195 
00197   template<typename T2>
00198   friend bool Teuchos::operator<( const Array<T2> &a1, const Array<T2> &a2 );
00199 
00201   template<typename T2>
00202   friend bool Teuchos::operator<=( const Array<T2> &a1, const Array<T2> &a2 );
00203 
00205   template<typename T2>
00206   friend bool Teuchos::operator>( const Array<T2> &a1, const Array<T2> &a2 );
00207 
00209   template<typename T2>
00210   friend bool Teuchos::operator>=( const Array<T2> &a1, const Array<T2> &a2 );
00211 
00214 
00216   typedef Teuchos_Ordinal Ordinal;
00218   typedef Ordinal size_type;
00220   typedef Ordinal difference_type;
00222   typedef typename std::vector<T>::value_type value_type;
00224   typedef typename std::vector<T>::pointer pointer;
00226   typedef typename std::vector<T>::const_pointer const_pointer;
00228   typedef typename std::vector<T>::reference reference;
00230   typedef typename std::vector<T>::const_reference const_reference;
00232   typedef typename std::vector<T>::allocator_type allocator_type;
00233 
00234 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00235 
00236   typedef ArrayRCP<T> iterator;
00238   typedef ArrayRCP<const T> const_iterator;
00240   typedef std::reverse_iterator<iterator> reverse_iterator;
00242   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00243 #else
00244 
00245   typedef typename std::vector<T>::iterator iterator;
00247   typedef typename std::vector<T>::const_iterator const_iterator;
00249   typedef typename std::vector<T>::reverse_iterator reverse_iterator;
00251   typedef typename std::vector<T>::const_reverse_iterator const_reverse_iterator;
00252 #endif
00253 
00254 
00256 
00259 
00261   inline Array();
00263   inline explicit Array(size_type n, const value_type& value = value_type());
00265   inline Array(const Array<T>& x);
00267   template<typename InputIterator>
00268   inline Array(InputIterator first, InputIterator last);
00270   inline Array(const ArrayView<const T>& a);
00272   template<int N>
00273   inline Array(const Tuple<T,N>& t);
00275   inline ~Array();
00277   inline Array& operator=(const Array<T>& a);
00278 
00280 
00283 
00285   inline void assign(size_type n, const value_type& val);
00287   template<typename InputIterator>
00288   inline void assign(InputIterator first, InputIterator last);
00290   inline iterator begin();
00292   inline iterator end();
00294   inline const_iterator begin() const;
00296   inline const_iterator end() const;
00298   inline reverse_iterator rbegin();
00300   inline reverse_iterator rend();
00302   inline const_reverse_iterator rbegin() const;
00304   inline const_reverse_iterator rend() const;
00306   inline size_type size() const;
00308   inline size_type max_size() const;
00310   inline void resize(size_type new_size, const value_type& x = value_type());
00312   inline size_type capacity() const;
00314   inline bool empty() const;
00316   inline void reserve(size_type n);
00318   inline reference operator[](size_type i);
00320   inline const_reference operator[](size_type i) const;
00322   inline reference at(size_type i);
00324   inline const_reference at(size_type i) const;
00326   inline reference front();
00328   inline const_reference front() const;
00330   inline reference back();
00332   inline const_reference back() const;
00334   inline void push_back(const value_type& x);
00336   inline void pop_back();
00338   inline iterator insert(iterator position, const value_type& x);
00340   inline void insert(iterator position, size_type n, const value_type& x);
00342   template<typename InputIterator>
00343   inline void insert(iterator position, InputIterator first, InputIterator last);
00345   inline iterator erase(iterator position);
00347   inline iterator erase(iterator first, iterator last);
00349   inline void swap(Array& x);
00351   inline void clear();
00352 
00354 
00357 
00362   inline Array<T>& append(const T& x);
00363 
00367   inline void remove(int i);
00368 
00373   inline int length() const;
00374 
00376   inline std::string toString() const;
00377 
00379   inline static bool hasBoundsChecking();
00380 
00382   inline T* getRawPtr();
00383 
00385   inline const T* getRawPtr() const;
00386 
00388 
00391 
00393   inline Array( const std::vector<T> &v );
00394 
00396   inline std::vector<T> toVector() const;
00397 
00399   inline Array& operator=( const std::vector<T> &v );
00400 
00402 
00404 
00405 
00417   inline ArrayView<T> view( size_type offset, size_type size );
00418 
00430   inline ArrayView<const T> view( size_type offset, size_type size ) const;
00431 
00435   inline ArrayView<T> operator()( size_type offset, size_type size );
00436 
00440   inline ArrayView<const T> operator()( size_type offset, size_type size ) const;
00441 
00446   inline ArrayView<T> operator()();
00447 
00452   inline ArrayView<const T> operator()() const;
00453 
00457   inline operator ArrayView<T>();
00458 
00462   inline operator ArrayView<const T>() const;
00463 
00465 
00466 private:
00467 
00468 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00469   RCP<std::vector<T> > vec_;
00470   mutable ArrayRCP<T> extern_arcp_;
00471   mutable ArrayRCP<const T> extern_carcp_;
00472 #else
00473   std::vector<T> vec_;
00474 #endif
00475 
00476   inline std::vector<T>& vec(
00477     bool isStructureBeingModified = false,
00478     bool activeIter = false
00479     );
00480 
00481   inline const std::vector<T>& vec() const;
00482 
00483   inline typename std::vector<T>::iterator
00484   raw_position( iterator position );
00485   
00486   inline void assertIndex(int i) const;
00487 
00488   inline void assertNotNull() const;
00489 
00490 };
00491 
00492 
00498 template<class T>
00499 ArrayRCP<T> arcp( const RCP<Array<T> > &v )
00500 {
00501   if ( is_null(v) || !v->size() )
00502     return null;
00503   return arcpWithEmbeddedObjPostDestroy<T,RCP<Array<T> > >(
00504     &(*v)[0], 0, v->size(),
00505     v, false
00506     );
00507 }
00508 
00509 
00515 template<class T>
00516 ArrayRCP<const T> arcp( const RCP<const Array<T> > &v )
00517 {
00518   if ( is_null(v) || !v->size() )
00519     return null;
00520   return arcpWithEmbeddedObjPostDestroy<const T,RCP<const Array<T> > >(
00521     &(*v)[0], 0, v->size(),
00522     v, false
00523     );
00524 }
00525 
00526 
00532 template<class T>
00533 ArrayRCP<T> arcpFromArray( Array<T> &a )
00534 {
00535   if (a.size() == 0)
00536     return null;
00537 #ifdef TEUCHOS_DEBUG
00538   return a.begin(); // Catch dangling reference!
00539 #else
00540   return arcp(a.getRawPtr(), 0, a.size(), false);
00541 #endif
00542 }
00543 
00544 
00550 template<class T>
00551 ArrayRCP<const T> arcpFromArray( const Array<T> &a )
00552 {
00553   if (a.size() == 0)
00554     return null;
00555 #ifdef TEUCHOS_DEBUG
00556   return a.begin(); // Catch dangling reference!
00557 #else
00558   return arcp(a.getRawPtr(), 0, a.size(), false);
00559 #endif
00560 }
00561 
00562 
00575 template<typename T>
00576 std::ostream& operator<<(std::ostream& os, const Array<T>& array);
00577 
00578 
00583 template<typename T> inline
00584 int hashCode(const Array<T>& array);
00585 
00586 
00593 template<typename T> inline
00594 std::vector<T> createVector( const Array<T> &a );
00595 
00596 
00601 template<typename T>
00602 std::string toString(const Array<T>& array);
00603 
00604 
00656 template<typename T>
00657 Array<T> fromStringToArray(const std::string& arrayStr);
00658 
00664 template<typename T>
00665 std::istringstream& operator>> (std::istringstream& in, Array<T>& array){
00666   array = fromStringToArray<T>(in.str());
00667   return in;
00668 }
00669 
00675 template<typename T> inline
00676 void extractDataFromISS( std::istringstream& iss, T& data )
00677 {
00678   iss >> data; // Assumes type has operator>>(...) defined!
00679 }
00680 
00687 inline
00688 void extractDataFromISS( std::istringstream& iss, std::string& data )
00689 {
00690   // grab unformatted string.
00691   data = iss.str();
00692   // remove white space from beginning and end of string.
00693   data = Utils::trimWhiteSpace(data);
00694 }
00695 
00705 inline
00706 std::string getArrayTypeNameTraitsFormat(){
00707   return "Array(*)";
00708 }
00709 
00710 
00711 
00725 template<typename T>
00726 class TEUCHOS_LIB_DLL_EXPORT TypeNameTraits<Array<T> > {
00727 public:
00728   static std::string name(){ 
00729     std::string formatString = getArrayTypeNameTraitsFormat();
00730     size_t starPos = formatString.find("*");
00731     std::string prefix = formatString.substr(0,starPos);
00732     std::string postFix = formatString.substr(starPos+1);
00733     return prefix+TypeNameTraits<T>::name()+postFix;
00734   }
00735   static std::string concreteName(const Array<T>&)
00736     { return name(); }
00737 };
00738 
00739 
00740 } // namespace Teuchos
00741 
00742 
00743 //
00744 // Implementation
00745 //
00746 
00747 
00748 namespace Teuchos {
00749 
00750 
00751 // All constructors
00752 
00753 
00754 template<typename T> inline
00755 Array<T>::Array()
00756 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00757   : vec_(rcp(new std::vector<T>()))
00758 #endif
00759 {}
00760 
00761 
00762 template<typename T> inline
00763 Array<T>::Array(size_type n, const value_type& value) :
00764 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00765   vec_(rcp(new std::vector<T>(n,value)))
00766 #else
00767   vec_(n, value)
00768 #endif
00769 {}
00770 
00771 
00772 template<typename T> inline
00773 Array<T>::Array(const Array<T>& x) :
00774 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00775   vec_(rcp(new std::vector<T>(*x.vec_)))
00776 #else
00777   vec_(x.vec_)
00778 #endif
00779 {}
00780 
00781 
00782 template<typename T> template<typename InputIterator> inline
00783 Array<T>::Array(InputIterator first, InputIterator last) :
00784 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00785   vec_(rcp(new std::vector<T>(first, last)))
00786 #else
00787   vec_(first, last)
00788 #endif
00789 {}
00790 
00791 
00792 template<typename T> inline
00793 Array<T>::~Array()
00794 {}
00795 
00796 
00797 template<typename T> inline
00798 Array<T>::Array(const ArrayView<const T>& a)
00799 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00800   : vec_(rcp(new std::vector<T>()))
00801 #endif
00802 {
00803   insert(begin(), a.begin(), a.end());
00804 }
00805 
00806 
00807 template<typename T>
00808 template<int N>
00809 inline
00810 Array<T>::Array(const Tuple<T,N>& t)
00811 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00812   : vec_(rcp(new std::vector<T>()))
00813 #endif
00814 {
00815   insert(begin(), t.begin(), t.end());
00816 }
00817 
00818 
00819 template<typename T> inline
00820 Array<T>& Array<T>::operator=(const Array& a)
00821 {
00822   vec(true) = a.vec();
00823   return *this;
00824 }
00825 
00826 
00827 // Other std::vector functions
00828 
00829 
00830 template<typename T> inline
00831 void Array<T>::assign(size_type n, const value_type& val)
00832 {
00833   vec(true).assign(n,val);
00834 }
00835 
00836 
00837 template<typename T> template<typename InputIterator> inline
00838 void Array<T>::assign(InputIterator first, InputIterator last)
00839 {
00840   vec(true).assign(first,last);
00841 }
00842 
00843 
00844 template<typename T> inline
00845 typename Array<T>::iterator
00846 Array<T>::begin()
00847 {
00848 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00849   if (is_null(extern_arcp_)) {
00850     // Here we must use the same RCP to avoid creating two unrelated RCPNodes!
00851     extern_arcp_ = arcp(vec_); // Will be null if vec_ is sized!
00852   }
00853   // Returning a weak pointer will help to catch dangling references but still
00854   // keep the same behavior as optimized code.
00855   return extern_arcp_.create_weak();
00856 #else
00857   return vec().begin();
00858 #endif
00859 }
00860 
00861 
00862 template<typename T> inline
00863 typename Array<T>::iterator
00864 Array<T>::end()
00865 {
00866 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00867   return begin() + size();
00868 #else
00869   return vec().end();
00870 #endif
00871 }
00872 
00873 
00874 template<typename T> inline
00875 typename Array<T>::const_iterator
00876 Array<T>::begin() const
00877 {
00878 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00879   if (is_null(extern_carcp_)) {
00880     extern_carcp_ = const_cast<Array<T>*>(this)->begin();
00881   }
00882   // Returning a weak pointer will help to catch dangling references but still
00883   // keep the same behavior as optimized code.
00884   return extern_carcp_.create_weak();
00885 #else
00886   return vec().begin();
00887 #endif
00888 }
00889 
00890 
00891 template<typename T> inline
00892 typename Array<T>::const_iterator
00893 Array<T>::end() const
00894 {
00895 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00896   return begin() + size();
00897 #else
00898   return vec().end();
00899 #endif
00900 }
00901 
00902 
00903 template<typename T> inline
00904 typename Array<T>::reverse_iterator
00905 Array<T>::rbegin()
00906 {
00907 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00908   return reverse_iterator(end());
00909 #else
00910   return vec().rbegin();
00911 #endif
00912 }
00913 
00914 
00915 template<typename T> inline
00916 typename Array<T>::reverse_iterator
00917 Array<T>::rend()
00918 {
00919 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00920   return reverse_iterator(begin());
00921 #else
00922   return vec().rend();
00923 #endif
00924 }
00925 
00926 
00927 template<typename T> inline
00928 typename Array<T>::const_reverse_iterator
00929 Array<T>::rbegin() const
00930 {
00931 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00932   return const_reverse_iterator(end());
00933 #else
00934   return vec().rbegin();
00935 #endif
00936 }
00937 
00938 
00939 template<typename T> inline
00940 typename Array<T>::const_reverse_iterator
00941 Array<T>::rend() const
00942 {
00943 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00944   return const_reverse_iterator(begin());
00945 #else
00946   return vec().rend();
00947 #endif
00948 }
00949 
00950 
00951 template<typename T> inline
00952 typename Array<T>::size_type
00953 Array<T>::size() const
00954 {
00955   return vec().size();
00956 }
00957 
00958 
00959 template<typename T> inline
00960 typename Array<T>::size_type
00961 Array<T>::max_size() const
00962 {
00963   return std::numeric_limits<size_type>::max();
00964 }
00965 
00966 
00967 template<typename T> inline
00968 void
00969 Array<T>::resize(size_type new_size, const value_type& x)
00970 {
00971   vec(true).resize(new_size,x);
00972 }
00973 
00974 
00975 template<typename T> inline
00976 typename Array<T>::size_type
00977 Array<T>::capacity() const
00978 {
00979   return vec().capacity();
00980 }
00981 
00982 
00983 template<typename T> inline
00984 bool Array<T>::empty() const
00985 {
00986   return vec().empty();
00987 }
00988 
00989 
00990 template<typename T> inline
00991 void Array<T>::reserve(size_type n)
00992 {
00993   vec(true).reserve(n);
00994 }
00995 
00996 
00997 template<typename T> inline
00998 typename Array<T>::reference
00999 Array<T>::operator[](size_type i)
01000 {
01001 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01002   assertIndex(i);
01003 #endif
01004   return vec()[i];
01005 }
01006 
01007 
01008 template<typename T> inline
01009 typename Array<T>::const_reference
01010 Array<T>::operator[](size_type i) const
01011 {
01012 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01013   assertIndex(i);
01014 #endif
01015   return vec()[i];
01016 }
01017 
01018 
01019 template<typename T> inline
01020 typename Array<T>::reference
01021 Array<T>::at(size_type i)
01022 {
01023 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01024   assertIndex(i);
01025 #endif
01026   return vec().at(i);
01027 }
01028 
01029 
01030 template<typename T> inline
01031 typename Array<T>::const_reference
01032 Array<T>::at(size_type i) const
01033 {
01034 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01035   assertIndex(i);
01036 #endif
01037   return vec().at(i);
01038 }
01039 
01040 
01041 template<typename T> inline
01042 typename Array<T>::reference
01043 Array<T>::front()
01044 {
01045 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01046   assertNotNull();
01047 #endif
01048   return vec().front();
01049 }
01050 
01051 
01052 template<typename T> inline
01053 typename Array<T>::const_reference
01054 Array<T>::front() const
01055 {
01056 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01057   assertNotNull();
01058 #endif
01059   return vec().front();
01060 }
01061 
01062 
01063 template<typename T> inline
01064 typename Array<T>::reference
01065 Array<T>::back()
01066 {
01067 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01068   assertNotNull();
01069 #endif
01070   return vec().back();
01071 }
01072 
01073 
01074 template<typename T> inline
01075 typename Array<T>::const_reference
01076 Array<T>::back() const
01077 {
01078 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01079   assertNotNull();
01080 #endif
01081   return vec().back();
01082 }
01083 
01084 
01085 template<typename T> inline
01086 void Array<T>::push_back(const value_type& x)
01087 {
01088   vec(true).push_back(x);
01089 }
01090 
01091 
01092 template<typename T> inline
01093 void Array<T>::pop_back()
01094 {
01095 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01096   assertNotNull();
01097 #endif
01098   vec(true).pop_back();
01099 }
01100 
01101 
01102 // 2009/11/13:: rabartl: After moving to a full RCPNode tracing and lookup
01103 // model, I had to how modifying functions like insert(...) and erase(...) 
01104 // work which have active iterators controled by the client and yet need to
01105 // allow the structure of the container change.  The way these troublesome
01106 // functions work is that first the raw std::vector iterator is extracted.
01107 // The function vec(true, true) then deletes the strong iterators but there is
01108 // still a weak ArrayRCP object that is owned by the client which is being
01109 // passed into this function.  The issue is that the design of ArrayRCP is
01110 // such that the RCPNode object is not removed but instead remains in order to
01111 // perform runtime checking.
01112 
01113 
01114 template<typename T> inline
01115 typename Array<T>::iterator
01116 Array<T>::insert(iterator position, const value_type& x)
01117 {
01118 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01119   // Assert a valid iterator and get vector iterator
01120   const typename std::vector<T>::iterator raw_poss = raw_position(position);
01121   const difference_type i = position - begin();
01122   vec(true, true).insert(raw_poss, x);
01123   return begin() + i;
01124 #else
01125   return vec_.insert(position, x);
01126 #endif
01127 }
01128 
01129 
01130 template<typename T> inline
01131 void Array<T>::insert(iterator position, size_type n, const value_type& x)
01132 {
01133 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01134   const typename std::vector<T>::iterator raw_poss = raw_position(position);
01135   vec(true, true).insert(raw_poss, n, x);
01136 #else
01137   return vec_.insert(position, n, x);
01138 #endif
01139 }
01140 
01141 
01142 template<typename T> template<typename InputIterator> inline
01143 void Array<T>::insert(iterator position, InputIterator first, InputIterator last)
01144 {
01145 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01146   const typename std::vector<T>::iterator raw_poss = raw_position(position);
01147   vec(true, true).insert(raw_poss, first, last);
01148 #else
01149   return vec_.insert(position, first, last);
01150 #endif
01151 }
01152 
01153 
01154 template<typename T> inline
01155 typename Array<T>::iterator
01156 Array<T>::erase(iterator position)
01157 {
01158 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01159   assertNotNull();
01160   // Assert a valid iterator and get vector iterator
01161   const typename std::vector<T>::iterator raw_poss = raw_position(position);
01162   const difference_type i = position - begin();
01163   vec(true, true).erase(raw_poss);
01164   return begin() + i;
01165 #else
01166   return vec_.erase(position);
01167 #endif
01168 }
01169 
01170 
01171 template<typename T> inline
01172 typename Array<T>::iterator
01173 Array<T>::erase(iterator first, iterator last)
01174 {
01175 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01176   assertNotNull();
01177   // Assert a valid iterator and get vector iterator
01178   const typename std::vector<T>::iterator raw_first = raw_position(first);
01179   const typename std::vector<T>::iterator raw_last = raw_position(last);
01180   const difference_type i = first - begin();
01181   vec(true,true).erase(raw_first,raw_last);
01182   return begin() + i;
01183 #else
01184   return vec_.erase(first,last);
01185 #endif
01186 }
01187 
01188 
01189 template<typename T> inline
01190 void Array<T>::swap(Array& x)
01191 {
01192   vec(true).swap(x.vec());
01193 }
01194 
01195 
01196 template<typename T> inline
01197 void Array<T>::clear()
01198 {
01199   vec(true).clear();
01200 }
01201 
01202 
01203 // Non-standard functions
01204 
01205 
01206 template<typename T> inline
01207 Array<T>& Array<T>::append(const T& x)
01208 {
01209   this->push_back(x);
01210   return *this;
01211 }
01212 
01213 
01214 template<typename T> inline
01215 void Array<T>::remove(int i)
01216 {
01217 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01218   assertIndex(i);
01219 #endif
01220   // Erase the i-th element of this array.
01221   this->erase( this->begin() + i );
01222 }
01223 
01224 
01225 template<typename T> inline
01226 int Array<T>::length() const
01227 {
01228   return this->size();
01229 }
01230 
01231 
01232 template<typename T> inline
01233 std::string Array<T>::toString() const
01234 {
01235   return (*this)().toString();
01236 }
01237 
01238 
01239 template<typename T> inline
01240 bool Array<T>::hasBoundsChecking()
01241 {
01242 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK  
01243   return true;
01244 #else
01245   return false;
01246 #endif
01247 }
01248 
01249 
01250 template<typename T> inline
01251 T* Array<T>::getRawPtr()
01252 {
01253   return ( size() ? &(*this)[0] : 0 );
01254 }
01255 
01256 
01257 template<typename T> inline
01258 const T* Array<T>::getRawPtr() const
01259 {
01260   return ( size() ? &(*this)[0] : 0 );
01261 }
01262 
01263 
01264 // Conversions to and from std::vector
01265 
01266 
01267 template<typename T> inline
01268 Array<T>::Array( const std::vector<T> &v ) :
01269 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01270   vec_(new std::vector<T>(v))
01271 #else
01272   vec_(v)
01273 #endif
01274 {}
01275 
01276 
01277 template<typename T> inline
01278 std::vector<T> Array<T>::toVector() const
01279 {
01280   if (!size())
01281     return std::vector<T>();
01282   std::vector<T> v(begin(),end());
01283   return v;
01284 }
01285 
01286 
01287 template<typename T> inline
01288 Array<T>& Array<T>::operator=( const std::vector<T> &v )
01289 {
01290   vec(true) = v;
01291   return *this;
01292 }
01293 
01294 
01295 // Views
01296 
01297 
01298 template<typename T> inline
01299 ArrayView<T> Array<T>::view( size_type offset, size_type size_in )
01300 {
01301   if (size_in) {
01302 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01303     return ArrayView<T>(this->begin().persistingView(offset, size_in));
01304 #else
01305     return arrayView( &vec()[offset], size_in );
01306 #endif
01307   }
01308   return Teuchos::null;
01309 }
01310 
01311 
01312 template<typename T> inline
01313 ArrayView<const T> Array<T>::view( size_type offset, size_type size_in ) const
01314 {
01315   if (size_in) {
01316 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01317     return ArrayView<const T>(this->begin().persistingView(offset, size_in));
01318 #else
01319     return arrayView( &vec()[offset], size_in );
01320 #endif
01321   }
01322   return Teuchos::null;
01323   // NOTE: Above, we use a different implementation to call the const version
01324   // of begin() instead of the non-const version.  This sets up a different
01325   // ArrayRCP object that gets checked.
01326 }
01327 
01328 
01329 template<typename T> inline
01330 ArrayView<T> Array<T>::operator()( size_type offset, size_type size_in )
01331 {
01332   return view(offset, size_in);
01333 }
01334 
01335 
01336 template<typename T> inline
01337 ArrayView<const T> Array<T>::operator()( size_type offset, size_type size_in ) const
01338 {
01339   return view(offset, size_in);
01340 }
01341 
01342 
01343 template<typename T> inline
01344 ArrayView<T> Array<T>::operator()()
01345 {
01346   if (!size())
01347     return null;
01348   return this->view(0, size());
01349 }
01350 
01351 
01352 template<typename T> inline
01353 ArrayView<const T> Array<T>::operator()() const
01354 {
01355   if (!size())
01356     return null;
01357   return this->view(0, size());
01358 }
01359 
01360 
01361 template<typename T> inline
01362 Array<T>::operator ArrayView<T>()
01363 {
01364   return this->operator()();
01365 }
01366 
01367 
01368 template<typename T> inline
01369 Array<T>::operator ArrayView<const T>() const
01370 {
01371   return this->operator()();
01372 }
01373 
01374 
01375 // private
01376 
01377 
01378 template<typename T>
01379 std::vector<T>&
01380 Array<T>::vec( bool isStructureBeingModified, bool activeIter )
01381 {
01382 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01383   (void)activeIter;
01384   if (isStructureBeingModified) {
01385     // Give up my ArrayRCPs used for iterator access since the array we be
01386     // getting modifed!  Any clients that have views through weak pointers
01387     // better not touch them!
01388     extern_arcp_ = null;
01389     extern_carcp_ = null;
01390   }
01391   return *vec_;
01392 #else
01393   // get rid of "unused parameter" warnings
01394   (void)isStructureBeingModified;
01395   (void)activeIter;
01396   return vec_;
01397 #endif
01398 }
01399 
01400 
01401 template<typename T> inline
01402 const std::vector<T>&
01403 Array<T>::vec() const
01404 {
01405 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01406   return *vec_;
01407 #else
01408   return vec_;
01409 #endif
01410 }
01411 
01412 
01413 template<typename T> inline
01414 typename std::vector<T>::iterator
01415 Array<T>::raw_position( iterator position )
01416 {
01417 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01418   const iterator first = this->begin();
01419   const iterator last = this->end();
01420   TEST_FOR_EXCEPTION(
01421     !(first <= position && position <= last), DanglingReferenceError,
01422     "Error, this iterator is no longer valid for this Aray!"
01423     );
01424   // Note, above operator<=(...) functions will throw
01425   // IncompatibleIteratorsError if the iterators do not share the same
01426   // RCP_node object!
01427   return vec_->begin() + (position - this->begin());
01428 #else
01429   return position;
01430 #endif
01431 }
01432 
01433 
01434 template<typename T> inline
01435 void Array<T>::assertIndex(int i) const
01436 {
01437   TEST_FOR_EXCEPTION(
01438     !( 0 <= i && i < length() ), RangeError,
01439     "Array<T>::assertIndex(i): i="<<i<<" out of range [0, "<< length() << ")"
01440     );
01441 }
01442 
01443 
01444 template<typename T> inline
01445 void Array<T>::assertNotNull() const
01446 {
01447   TEST_FOR_EXCEPTION(
01448     !size(), NullReferenceError,
01449     typeName(*this)<<"::assertNotNull(): "
01450     "Error, the array has size zero!"
01451     );
01452 }
01453 
01454 
01455 } // namespace Teuchos
01456 
01457 
01458 // Nonmember functions
01459 
01460 
01461 template<typename T> inline
01462 bool Teuchos::operator==( const Array<T> &a1, const Array<T> &a2 )
01463 { return (a1.vec() == a2.vec()); }
01464 
01465 
01466 template<typename T> inline
01467 bool Teuchos::operator!=( const Array<T> &a1, const Array<T> &a2 )
01468 { return (a1.vec() != a2.vec()); }
01469 
01470 
01471 template<typename T> inline
01472 void Teuchos::swap( Array<T> &a1, Array<T> &a2 )
01473 { a1.swap(a2); }
01474 
01475 
01476 template<typename T> inline
01477 bool Teuchos::operator<( const Array<T> &a1, const Array<T> &a2 )
01478 { return (a1.vec() < a2.vec()); }
01479 
01480 
01481 template<typename T> inline
01482 bool Teuchos::operator<=( const Array<T> &a1, const Array<T> &a2 )
01483 { return (a1.vec() <= a2.vec()); }
01484 
01485 
01486 template<typename T> inline
01487 bool Teuchos::operator>( const Array<T> &a1, const Array<T> &a2 )
01488 { return (a1.vec() > a2.vec()); }
01489 
01490 
01491 template<typename T> inline
01492 bool Teuchos::operator>=( const Array<T> &a1, const Array<T> &a2 )
01493 { return (a1.vec() >= a2.vec()); }
01494 
01495 
01496 template<typename T> inline
01497 std::ostream& Teuchos::operator<<(
01498   std::ostream& os, const Array<T>& array
01499   )
01500 {
01501   return os << Teuchos::toString(array);
01502 }
01503 
01504 
01505 template<typename T> inline
01506 int Teuchos::hashCode(const Array<T>& array)
01507 {
01508   int rtn = hashCode(array.length());
01509   for (int i=0; i<array.length(); i++)
01510   {
01511     rtn += hashCode(array[i]);
01512   }
01513   return rtn;
01514 }
01515 
01516 
01517 template<typename T> inline
01518 std::vector<T> Teuchos::createVector( const Array<T> &a )
01519 {
01520   return a.toVector();
01521 }
01522 
01523 
01524 template<typename T> inline
01525 std::string Teuchos::toString(const Array<T>& array)
01526 {
01527   return array.toString();
01528 }
01529 
01530 
01531 template<typename T>
01532 Teuchos::Array<T>
01533 Teuchos::fromStringToArray(const std::string& arrayStr)
01534 {
01535   const std::string str = Utils::trimWhiteSpace(arrayStr);
01536   std::istringstream iss(str);
01537   TEST_FOR_EXCEPTION(
01538     ( str[0]!='{' || str[str.length()-1] != '}' )
01539     ,InvalidArrayStringRepresentation
01540     ,"Error, the std::string:\n"
01541     "----------\n"
01542     <<str<<
01543     "\n----------\n"
01544     "is not a valid array represntation!"
01545     );
01546   char c;
01547   c = iss.get(); // Read initial '{'
01548   TEST_FOR_EXCEPT(c!='{'); // Should not throw!
01549   // Now we are ready to begin reading the entries of the array!
01550   Array<T> a;
01551   while( !iss.eof() ) {
01552     // Get the basic entry std::string
01553     std::string entryStr;
01554     std::getline(iss,entryStr,','); // Get next entry up to ,!
01555     // ToDo: Above, we might have to be careful to look for the opening and
01556     // closing of parentheses in order not to pick up an internal ',' in the
01557     // middle of an entry (for a std::complex number for instance).  The above
01558     // implementation assumes that there will be no commas in the middle of
01559     // the std::string representation of an entry.  This is certainly true for
01560     // the types bool, int, float, and double.
01561     //
01562     // Trim whitespace from beginning and end
01563     entryStr = Utils::trimWhiteSpace(entryStr);
01564     // Remove the final '}' if this is the last entry and we did not
01565     // actually terminate the above getline(...) on ','
01566     bool found_end = false;
01567     if(entryStr[entryStr.length()-1]=='}') {
01568       entryStr = entryStr.substr(0,entryStr.length()-1);
01569       found_end = true;
01570       if( entryStr.length()==0 && a.size()==0 )
01571         return a; // This is the empty array "{}" (with any spaces in it!)
01572     }
01573     TEST_FOR_EXCEPTION(
01574       0 == entryStr.length()
01575       ,InvalidArrayStringRepresentation
01576       ,"Error, the std::string:\n"
01577       "----------\n"
01578       <<str<<
01579       "\n----------\n"
01580       "is not a valid array represntation!"
01581       );
01582     // Finally we can convert the entry and add it to the array!
01583     std::istringstream entryiss(entryStr);
01584     T entry;
01585     Teuchos::extractDataFromISS( entryiss, entry );
01586     // ToDo: We may need to define a traits class to allow us to specialized
01587     // how conversion from a std::string to a object is done!
01588     a.push_back(entry);
01589     // At the end of the loop body here, if we have reached the last '}'
01590     // then the input stream iss should be empty and iss.eof() should be
01591     // true, so the loop should terminate.  We put an std::exception test here
01592     // just in case something has gone wrong.
01593     TEST_FOR_EXCEPTION(
01594       found_end && !iss.eof()
01595       ,InvalidArrayStringRepresentation
01596       ,"Error, the std::string:\n"
01597       "----------\n"
01598       <<str<<
01599       "\n----------\n"
01600       "is not a valid array represntation!"
01601       );
01602   }
01603   return a;
01604 }
01605 
01606 
01607 #endif // TEUCHOS_ARRAY_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines