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_Assert.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 
00419         inline ArrayView<T> view( size_type offset, size_type size );
00420 
00434         inline ArrayView<const T> view( size_type offset, size_type size ) const;
00435 
00439         inline ArrayView<T> operator()( size_type offset, size_type size );
00440 
00444         inline ArrayView<const T> operator()( size_type offset, size_type size ) const;
00445 
00450         inline ArrayView<T> operator()();
00451 
00456         inline ArrayView<const T> operator()() const;
00457 
00461         inline operator ArrayView<T>();
00462 
00466         inline operator ArrayView<const T>() const;
00467 
00469 
00470 private:
00471 
00472 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00473   RCP<std::vector<T> > vec_;
00474   mutable ArrayRCP<T> extern_arcp_;
00475   mutable ArrayRCP<const T> extern_carcp_;
00476 #else
00477   std::vector<T> vec_;
00478 #endif
00479 
00480   inline std::vector<T>& vec(
00481     bool isStructureBeingModified = false,
00482     bool activeIter = false
00483     );
00484 
00485   inline const std::vector<T>& vec() const;
00486 
00487   inline typename std::vector<T>::iterator
00488   raw_position( iterator position );
00489 
00490   inline void assertIndex(int i) const;
00491 
00492   inline void assertNotNull() const;
00493 
00494 };
00495 
00496 
00502 template<class T>
00503 ArrayRCP<T> arcp( const RCP<Array<T> > &v )
00504 {
00505   if ( is_null(v) || !v->size() )
00506     return null;
00507   return arcpWithEmbeddedObjPostDestroy<T,RCP<Array<T> > >(
00508     &(*v)[0], 0, v->size(),
00509     v, false
00510     );
00511 }
00512 
00513 
00519 template<class T>
00520 ArrayRCP<const T> arcp( const RCP<const Array<T> > &v )
00521 {
00522   if ( is_null(v) || !v->size() )
00523     return null;
00524   return arcpWithEmbeddedObjPostDestroy<const T,RCP<const Array<T> > >(
00525     &(*v)[0], 0, v->size(),
00526     v, false
00527     );
00528 }
00529 
00530 
00536 template<class T>
00537 ArrayRCP<T> arcpFromArray( Array<T> &a )
00538 {
00539   if (a.size() == 0)
00540     return null;
00541 #ifdef TEUCHOS_DEBUG
00542   return a.begin(); // Catch dangling reference!
00543 #else
00544   return arcp(a.getRawPtr(), 0, a.size(), false);
00545 #endif
00546 }
00547 
00548 
00554 template<class T>
00555 ArrayRCP<const T> arcpFromArray( const Array<T> &a )
00556 {
00557   if (a.size() == 0)
00558     return null;
00559 #ifdef TEUCHOS_DEBUG
00560   return a.begin(); // Catch dangling reference!
00561 #else
00562   return arcp(a.getRawPtr(), 0, a.size(), false);
00563 #endif
00564 }
00565 
00566 
00579 template<typename T>
00580 std::ostream& operator<<(std::ostream& os, const Array<T>& array);
00581 
00582 
00587 template<typename T> inline
00588 int hashCode(const Array<T>& array);
00589 
00590 
00597 template<typename T> inline
00598 std::vector<T> createVector( const Array<T> &a );
00599 
00600 
00605 template<typename T>
00606 std::string toString(const Array<T>& array);
00607 
00608 
00660 template<typename T>
00661 Array<T> fromStringToArray(const std::string& arrayStr);
00662 
00668 template<typename T>
00669 std::istringstream& operator>> (std::istringstream& in, Array<T>& array){
00670   array = fromStringToArray<T>(in.str());
00671   return in;
00672 }
00673 
00679 template<typename T> inline
00680 void extractDataFromISS( std::istringstream& iss, T& data )
00681 {
00682   iss >> data; // Assumes type has operator>>(...) defined!
00683 }
00684 
00691 inline
00692 void extractDataFromISS( std::istringstream& iss, std::string& data )
00693 {
00694   // grab unformatted string.
00695   data = iss.str();
00696   // remove white space from beginning and end of string.
00697   data = Utils::trimWhiteSpace(data);
00698 }
00699 
00709 inline
00710 std::string getArrayTypeNameTraitsFormat(){
00711   return "Array(*)";
00712 }
00713 
00714 
00715 
00729 template<typename T>
00730 class TEUCHOS_LIB_DLL_EXPORT TypeNameTraits<Array<T> > {
00731 public:
00732   static std::string name(){
00733     std::string formatString = getArrayTypeNameTraitsFormat();
00734     size_t starPos = formatString.find("*");
00735     std::string prefix = formatString.substr(0,starPos);
00736     std::string postFix = formatString.substr(starPos+1);
00737     return prefix+TypeNameTraits<T>::name()+postFix;
00738   }
00739   static std::string concreteName(const Array<T>&)
00740     { return name(); }
00741 };
00742 
00743 
00744 } // namespace Teuchos
00745 
00746 
00747 //
00748 // Implementation
00749 //
00750 
00751 
00752 namespace Teuchos {
00753 
00754 
00755 // All constructors
00756 
00757 
00758 template<typename T> inline
00759 Array<T>::Array()
00760 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00761   : vec_(rcp(new std::vector<T>()))
00762 #endif
00763 {}
00764 
00765 
00766 template<typename T> inline
00767 Array<T>::Array(size_type n, const value_type& value) :
00768 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00769   vec_(rcp(new std::vector<T>(n,value)))
00770 #else
00771   vec_(n, value)
00772 #endif
00773 {}
00774 
00775 
00776 template<typename T> inline
00777 Array<T>::Array(const Array<T>& x) :
00778 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00779   vec_(rcp(new std::vector<T>(*x.vec_)))
00780 #else
00781   vec_(x.vec_)
00782 #endif
00783 {}
00784 
00785 
00786 template<typename T> template<typename InputIterator> inline
00787 Array<T>::Array(InputIterator first, InputIterator last) :
00788 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00789   vec_(rcp(new std::vector<T>(first, last)))
00790 #else
00791   vec_(first, last)
00792 #endif
00793 {}
00794 
00795 
00796 template<typename T> inline
00797 Array<T>::~Array()
00798 {}
00799 
00800 
00801 template<typename T> inline
00802 Array<T>::Array(const ArrayView<const T>& a)
00803 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00804   : vec_(rcp(new std::vector<T>()))
00805 #endif
00806 {
00807   insert(begin(), a.begin(), a.end());
00808 }
00809 
00810 
00811 template<typename T>
00812 template<int N>
00813 inline
00814 Array<T>::Array(const Tuple<T,N>& t)
00815 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00816   : vec_(rcp(new std::vector<T>()))
00817 #endif
00818 {
00819   insert(begin(), t.begin(), t.end());
00820 }
00821 
00822 
00823 template<typename T> inline
00824 Array<T>& Array<T>::operator=(const Array& a)
00825 {
00826   vec(true) = a.vec();
00827   return *this;
00828 }
00829 
00830 
00831 // Other std::vector functions
00832 
00833 
00834 template<typename T> inline
00835 void Array<T>::assign(size_type n, const value_type& val)
00836 {
00837   vec(true).assign(n,val);
00838 }
00839 
00840 
00841 template<typename T> template<typename InputIterator> inline
00842 void Array<T>::assign(InputIterator first, InputIterator last)
00843 {
00844   vec(true).assign(first,last);
00845 }
00846 
00847 
00848 template<typename T> inline
00849 typename Array<T>::iterator
00850 Array<T>::begin()
00851 {
00852 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00853   if (is_null(extern_arcp_)) {
00854     // Here we must use the same RCP to avoid creating two unrelated RCPNodes!
00855     extern_arcp_ = arcp(vec_); // Will be null if vec_ is sized!
00856   }
00857   // Returning a weak pointer will help to catch dangling references but still
00858   // keep the same behavior as optimized code.
00859   return extern_arcp_.create_weak();
00860 #else
00861   return vec().begin();
00862 #endif
00863 }
00864 
00865 
00866 template<typename T> inline
00867 typename Array<T>::iterator
00868 Array<T>::end()
00869 {
00870 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00871   return begin() + size();
00872 #else
00873   return vec().end();
00874 #endif
00875 }
00876 
00877 
00878 template<typename T> inline
00879 typename Array<T>::const_iterator
00880 Array<T>::begin() const
00881 {
00882 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00883   if (is_null(extern_carcp_)) {
00884     extern_carcp_ = const_cast<Array<T>*>(this)->begin();
00885   }
00886   // Returning a weak pointer will help to catch dangling references but still
00887   // keep the same behavior as optimized code.
00888   return extern_carcp_.create_weak();
00889 #else
00890   return vec().begin();
00891 #endif
00892 }
00893 
00894 
00895 template<typename T> inline
00896 typename Array<T>::const_iterator
00897 Array<T>::end() const
00898 {
00899 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00900   return begin() + size();
00901 #else
00902   return vec().end();
00903 #endif
00904 }
00905 
00906 
00907 template<typename T> inline
00908 typename Array<T>::reverse_iterator
00909 Array<T>::rbegin()
00910 {
00911 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00912   return reverse_iterator(end());
00913 #else
00914   return vec().rbegin();
00915 #endif
00916 }
00917 
00918 
00919 template<typename T> inline
00920 typename Array<T>::reverse_iterator
00921 Array<T>::rend()
00922 {
00923 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00924   return reverse_iterator(begin());
00925 #else
00926   return vec().rend();
00927 #endif
00928 }
00929 
00930 
00931 template<typename T> inline
00932 typename Array<T>::const_reverse_iterator
00933 Array<T>::rbegin() const
00934 {
00935 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00936   return const_reverse_iterator(end());
00937 #else
00938   return vec().rbegin();
00939 #endif
00940 }
00941 
00942 
00943 template<typename T> inline
00944 typename Array<T>::const_reverse_iterator
00945 Array<T>::rend() const
00946 {
00947 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
00948   return const_reverse_iterator(begin());
00949 #else
00950   return vec().rend();
00951 #endif
00952 }
00953 
00954 
00955 template<typename T> inline
00956 typename Array<T>::size_type
00957 Array<T>::size() const
00958 {
00959   return vec().size();
00960 }
00961 
00962 
00963 template<typename T> inline
00964 typename Array<T>::size_type
00965 Array<T>::max_size() const
00966 {
00967   return std::numeric_limits<size_type>::max();
00968 }
00969 
00970 
00971 template<typename T> inline
00972 void
00973 Array<T>::resize(size_type new_size, const value_type& x)
00974 {
00975   vec(true).resize(new_size,x);
00976 }
00977 
00978 
00979 template<typename T> inline
00980 typename Array<T>::size_type
00981 Array<T>::capacity() const
00982 {
00983   return vec().capacity();
00984 }
00985 
00986 
00987 template<typename T> inline
00988 bool Array<T>::empty() const
00989 {
00990   return vec().empty();
00991 }
00992 
00993 
00994 template<typename T> inline
00995 void Array<T>::reserve(size_type n)
00996 {
00997   vec(true).reserve(n);
00998 }
00999 
01000 
01001 template<typename T> inline
01002 typename Array<T>::reference
01003 Array<T>::operator[](size_type i)
01004 {
01005 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01006   assertIndex(i);
01007 #endif
01008   return vec()[i];
01009 }
01010 
01011 
01012 template<typename T> inline
01013 typename Array<T>::const_reference
01014 Array<T>::operator[](size_type i) const
01015 {
01016 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01017   assertIndex(i);
01018 #endif
01019   return vec()[i];
01020 }
01021 
01022 
01023 template<typename T> inline
01024 typename Array<T>::reference
01025 Array<T>::at(size_type i)
01026 {
01027 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01028   assertIndex(i);
01029 #endif
01030   return vec().at(i);
01031 }
01032 
01033 
01034 template<typename T> inline
01035 typename Array<T>::const_reference
01036 Array<T>::at(size_type i) const
01037 {
01038 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01039   assertIndex(i);
01040 #endif
01041   return vec().at(i);
01042 }
01043 
01044 
01045 template<typename T> inline
01046 typename Array<T>::reference
01047 Array<T>::front()
01048 {
01049 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01050   assertNotNull();
01051 #endif
01052   return vec().front();
01053 }
01054 
01055 
01056 template<typename T> inline
01057 typename Array<T>::const_reference
01058 Array<T>::front() const
01059 {
01060 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01061   assertNotNull();
01062 #endif
01063   return vec().front();
01064 }
01065 
01066 
01067 template<typename T> inline
01068 typename Array<T>::reference
01069 Array<T>::back()
01070 {
01071 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01072   assertNotNull();
01073 #endif
01074   return vec().back();
01075 }
01076 
01077 
01078 template<typename T> inline
01079 typename Array<T>::const_reference
01080 Array<T>::back() const
01081 {
01082 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01083   assertNotNull();
01084 #endif
01085   return vec().back();
01086 }
01087 
01088 
01089 template<typename T> inline
01090 void Array<T>::push_back(const value_type& x)
01091 {
01092   vec(true).push_back(x);
01093 }
01094 
01095 
01096 template<typename T> inline
01097 void Array<T>::pop_back()
01098 {
01099 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01100   assertNotNull();
01101 #endif
01102   vec(true).pop_back();
01103 }
01104 
01105 
01106 // 2009/11/13:: rabartl: After moving to a full RCPNode tracing and lookup
01107 // model, I had to how modifying functions like insert(...) and erase(...)
01108 // work which have active iterators controled by the client and yet need to
01109 // allow the structure of the container change.  The way these troublesome
01110 // functions work is that first the raw std::vector iterator is extracted.
01111 // The function vec(true, true) then deletes the strong iterators but there is
01112 // still a weak ArrayRCP object that is owned by the client which is being
01113 // passed into this function.  The issue is that the design of ArrayRCP is
01114 // such that the RCPNode object is not removed but instead remains in order to
01115 // perform runtime checking.
01116 
01117 
01118 template<typename T> inline
01119 typename Array<T>::iterator
01120 Array<T>::insert(iterator position, const value_type& x)
01121 {
01122 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01123   // Assert a valid iterator and get vector iterator
01124   const typename std::vector<T>::iterator raw_poss = raw_position(position);
01125   const difference_type i = position - begin();
01126   vec(true, true).insert(raw_poss, x);
01127   return begin() + i;
01128 #else
01129   return vec_.insert(position, x);
01130 #endif
01131 }
01132 
01133 
01134 template<typename T> inline
01135 void Array<T>::insert(iterator position, size_type n, const value_type& x)
01136 {
01137 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01138   const typename std::vector<T>::iterator raw_poss = raw_position(position);
01139   vec(true, true).insert(raw_poss, n, x);
01140 #else
01141   return vec_.insert(position, n, x);
01142 #endif
01143 }
01144 
01145 
01146 template<typename T> template<typename InputIterator> inline
01147 void Array<T>::insert(iterator position, InputIterator first, InputIterator last)
01148 {
01149 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01150   const typename std::vector<T>::iterator raw_poss = raw_position(position);
01151   vec(true, true).insert(raw_poss, first, last);
01152 #else
01153   return vec_.insert(position, first, last);
01154 #endif
01155 }
01156 
01157 
01158 template<typename T> inline
01159 typename Array<T>::iterator
01160 Array<T>::erase(iterator position)
01161 {
01162 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01163   assertNotNull();
01164   // Assert a valid iterator and get vector iterator
01165   const typename std::vector<T>::iterator raw_poss = raw_position(position);
01166   const difference_type i = position - begin();
01167   vec(true, true).erase(raw_poss);
01168   return begin() + i;
01169 #else
01170   return vec_.erase(position);
01171 #endif
01172 }
01173 
01174 
01175 template<typename T> inline
01176 typename Array<T>::iterator
01177 Array<T>::erase(iterator first, iterator last)
01178 {
01179 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01180   if (empty()) {
01181     TEUCHOS_ASSERT(first == begin());
01182     TEUCHOS_ASSERT(last == end());
01183     return end();
01184   }
01185   assertNotNull();
01186   // Assert a valid iterator and get vector iterator
01187   const typename std::vector<T>::iterator raw_first = raw_position(first);
01188   const typename std::vector<T>::iterator raw_last = raw_position(last);
01189   const difference_type i = first - begin();
01190   vec(true,true).erase(raw_first,raw_last);
01191   return begin() + i;
01192 #else
01193   return vec_.erase(first,last);
01194 #endif
01195 }
01196 
01197 
01198 template<typename T> inline
01199 void Array<T>::swap(Array& x)
01200 {
01201   vec(true).swap(x.vec());
01202 }
01203 
01204 
01205 template<typename T> inline
01206 void Array<T>::clear()
01207 {
01208   vec(true).clear();
01209 }
01210 
01211 
01212 // Non-standard functions
01213 
01214 
01215 template<typename T> inline
01216 Array<T>& Array<T>::append(const T& x)
01217 {
01218   this->push_back(x);
01219   return *this;
01220 }
01221 
01222 
01223 template<typename T> inline
01224 void Array<T>::remove(int i)
01225 {
01226 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01227   assertIndex(i);
01228 #endif
01229   // Erase the i-th element of this array.
01230   this->erase( this->begin() + i );
01231 }
01232 
01233 
01234 template<typename T> inline
01235 int Array<T>::length() const
01236 {
01237   return this->size();
01238 }
01239 
01240 
01241 template<typename T> inline
01242 std::string Array<T>::toString() const
01243 {
01244   return (*this)().toString();
01245 }
01246 
01247 
01248 template<typename T> inline
01249 bool Array<T>::hasBoundsChecking()
01250 {
01251 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01252   return true;
01253 #else
01254   return false;
01255 #endif
01256 }
01257 
01258 
01259 template<typename T> inline
01260 T* Array<T>::getRawPtr()
01261 {
01262   return ( size() ? &(*this)[0] : 0 );
01263 }
01264 
01265 
01266 template<typename T> inline
01267 const T* Array<T>::getRawPtr() const
01268 {
01269   return ( size() ? &(*this)[0] : 0 );
01270 }
01271 
01272 
01273 // Conversions to and from std::vector
01274 
01275 
01276 template<typename T> inline
01277 Array<T>::Array( const std::vector<T> &v ) :
01278 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01279   vec_(new std::vector<T>(v))
01280 #else
01281   vec_(v)
01282 #endif
01283 {}
01284 
01285 
01286 template<typename T> inline
01287 std::vector<T> Array<T>::toVector() const
01288 {
01289   if (!size())
01290     return std::vector<T>();
01291   std::vector<T> v(begin(),end());
01292   return v;
01293 }
01294 
01295 
01296 template<typename T> inline
01297 Array<T>& Array<T>::operator=( const std::vector<T> &v )
01298 {
01299   vec(true) = v;
01300   return *this;
01301 }
01302 
01303 
01304 // Views
01305 
01306 
01307 template<typename T> inline
01308 ArrayView<T> Array<T>::view( size_type offset, size_type size_in )
01309 {
01310   if (size_in) {
01311 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01312     return ArrayView<T>(this->begin().persistingView(offset, size_in));
01313 #else
01314     return arrayView( &vec()[offset], size_in );
01315 #endif
01316   }
01317   return Teuchos::null;
01318 }
01319 
01320 
01321 template<typename T> inline
01322 ArrayView<const T> Array<T>::view( size_type offset, size_type size_in ) const
01323 {
01324   if (size_in) {
01325 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01326     return ArrayView<const T>(this->begin().persistingView(offset, size_in));
01327 #else
01328     return arrayView( &vec()[offset], size_in );
01329 #endif
01330   }
01331   return Teuchos::null;
01332   // NOTE: Above, we use a different implementation to call the const version
01333   // of begin() instead of the non-const version.  This sets up a different
01334   // ArrayRCP object that gets checked.
01335 }
01336 
01337 
01338 template<typename T> inline
01339 ArrayView<T> Array<T>::operator()( size_type offset, size_type size_in )
01340 {
01341   return view(offset, size_in);
01342 }
01343 
01344 
01345 template<typename T> inline
01346 ArrayView<const T> Array<T>::operator()( size_type offset, size_type size_in ) const
01347 {
01348   return view(offset, size_in);
01349 }
01350 
01351 
01352 template<typename T> inline
01353 ArrayView<T> Array<T>::operator()()
01354 {
01355   if (!size())
01356     return null;
01357   return this->view(0, size());
01358 }
01359 
01360 
01361 template<typename T> inline
01362 ArrayView<const T> Array<T>::operator()() const
01363 {
01364   if (!size())
01365     return null;
01366   return this->view(0, size());
01367 }
01368 
01369 
01370 template<typename T> inline
01371 Array<T>::operator ArrayView<T>()
01372 {
01373   return this->operator()();
01374 }
01375 
01376 
01377 template<typename T> inline
01378 Array<T>::operator ArrayView<const T>() const
01379 {
01380   return this->operator()();
01381 }
01382 
01383 
01384 // private
01385 
01386 
01387 template<typename T>
01388 std::vector<T>&
01389 Array<T>::vec( bool isStructureBeingModified, bool activeIter )
01390 {
01391 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01392   (void)activeIter;
01393   if (isStructureBeingModified) {
01394     // Give up my ArrayRCPs used for iterator access since the array we be
01395     // getting modifed!  Any clients that have views through weak pointers
01396     // better not touch them!
01397     extern_arcp_ = null;
01398     extern_carcp_ = null;
01399   }
01400   return *vec_;
01401 #else
01402   // get rid of "unused parameter" warnings
01403   (void)isStructureBeingModified;
01404   (void)activeIter;
01405   return vec_;
01406 #endif
01407 }
01408 
01409 
01410 template<typename T> inline
01411 const std::vector<T>&
01412 Array<T>::vec() const
01413 {
01414 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01415   return *vec_;
01416 #else
01417   return vec_;
01418 #endif
01419 }
01420 
01421 
01422 template<typename T> inline
01423 typename std::vector<T>::iterator
01424 Array<T>::raw_position( iterator position )
01425 {
01426 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01427   const iterator first = this->begin();
01428   const iterator last = this->end();
01429   TEUCHOS_TEST_FOR_EXCEPTION(
01430     !(first <= position && position <= last), DanglingReferenceError,
01431     "Error, this iterator is no longer valid for this Aray!"
01432     );
01433   // Note, above operator<=(...) functions will throw
01434   // IncompatibleIteratorsError if the iterators do not share the same
01435   // RCP_node object!
01436   return vec_->begin() + (position - this->begin());
01437 #else
01438   return position;
01439 #endif
01440 }
01441 
01442 
01443 template<typename T> inline
01444 void Array<T>::assertIndex(int i) const
01445 {
01446   TEUCHOS_TEST_FOR_EXCEPTION(
01447     !( 0 <= i && i < length() ), RangeError,
01448     "Array<T>::assertIndex(i): i="<<i<<" out of range [0, "<< length() << ")"
01449     );
01450 }
01451 
01452 
01453 template<typename T> inline
01454 void Array<T>::assertNotNull() const
01455 {
01456   TEUCHOS_TEST_FOR_EXCEPTION(
01457     !size(), NullReferenceError,
01458     typeName(*this)<<"::assertNotNull(): "
01459     "Error, the array has size zero!"
01460     );
01461 }
01462 
01463 
01464 } // namespace Teuchos
01465 
01466 
01467 // Nonmember functions
01468 
01469 
01470 template<typename T> inline
01471 bool Teuchos::operator==( const Array<T> &a1, const Array<T> &a2 )
01472 { return (a1.vec() == a2.vec()); }
01473 
01474 
01475 template<typename T> inline
01476 bool Teuchos::operator!=( const Array<T> &a1, const Array<T> &a2 )
01477 { return (a1.vec() != a2.vec()); }
01478 
01479 
01480 template<typename T> inline
01481 void Teuchos::swap( Array<T> &a1, Array<T> &a2 )
01482 { a1.swap(a2); }
01483 
01484 
01485 template<typename T> inline
01486 bool Teuchos::operator<( const Array<T> &a1, const Array<T> &a2 )
01487 { return (a1.vec() < a2.vec()); }
01488 
01489 
01490 template<typename T> inline
01491 bool Teuchos::operator<=( const Array<T> &a1, const Array<T> &a2 )
01492 { return (a1.vec() <= a2.vec()); }
01493 
01494 
01495 template<typename T> inline
01496 bool Teuchos::operator>( const Array<T> &a1, const Array<T> &a2 )
01497 { return (a1.vec() > a2.vec()); }
01498 
01499 
01500 template<typename T> inline
01501 bool Teuchos::operator>=( const Array<T> &a1, const Array<T> &a2 )
01502 { return (a1.vec() >= a2.vec()); }
01503 
01504 
01505 template<typename T> inline
01506 std::ostream& Teuchos::operator<<(
01507   std::ostream& os, const Array<T>& array
01508   )
01509 {
01510   return os << Teuchos::toString(array);
01511 }
01512 
01513 
01514 template<typename T> inline
01515 int Teuchos::hashCode(const Array<T>& array)
01516 {
01517   int rtn = hashCode(array.length());
01518   for (int i=0; i<array.length(); i++)
01519   {
01520     rtn += hashCode(array[i]);
01521   }
01522   return rtn;
01523 }
01524 
01525 
01526 template<typename T> inline
01527 std::vector<T> Teuchos::createVector( const Array<T> &a )
01528 {
01529   return a.toVector();
01530 }
01531 
01532 
01533 template<typename T> inline
01534 std::string Teuchos::toString(const Array<T>& array)
01535 {
01536   return array.toString();
01537 }
01538 
01539 
01540 template<typename T>
01541 Teuchos::Array<T>
01542 Teuchos::fromStringToArray(const std::string& arrayStr)
01543 {
01544   const std::string str = Utils::trimWhiteSpace(arrayStr);
01545   std::istringstream iss(str);
01546   TEUCHOS_TEST_FOR_EXCEPTION(
01547     ( str[0]!='{' || str[str.length()-1] != '}' )
01548     ,InvalidArrayStringRepresentation
01549     ,"Error, the std::string:\n"
01550     "----------\n"
01551     <<str<<
01552     "\n----------\n"
01553     "is not a valid array represntation!"
01554     );
01555   char c;
01556   c = iss.get(); // Read initial '{'
01557   TEUCHOS_TEST_FOR_EXCEPT(c!='{'); // Should not throw!
01558   // Now we are ready to begin reading the entries of the array!
01559   Array<T> a;
01560   while( !iss.eof() ) {
01561     // Get the basic entry std::string
01562     std::string entryStr;
01563     std::getline(iss,entryStr,','); // Get next entry up to ,!
01564     // ToDo: Above, we might have to be careful to look for the opening and
01565     // closing of parentheses in order not to pick up an internal ',' in the
01566     // middle of an entry (for a std::complex number for instance).  The above
01567     // implementation assumes that there will be no commas in the middle of
01568     // the std::string representation of an entry.  This is certainly true for
01569     // the types bool, int, float, and double.
01570     //
01571     // Trim whitespace from beginning and end
01572     entryStr = Utils::trimWhiteSpace(entryStr);
01573     TEUCHOS_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 because it has an empty array entry!"
01581       );
01582     // Remove the final '}' if this is the last entry and we did not
01583     // actually terminate the above getline(...) on ','
01584     bool found_end = false;
01585     if(entryStr[entryStr.length()-1]=='}') {
01586       entryStr = entryStr.substr(0,entryStr.length()-1);
01587       found_end = true;
01588       if( entryStr.length()==0 && a.size()==0 )
01589         return a; // This is the empty array "{}" (with any spaces in it!)
01590     }
01591     // Finally we can convert the entry and add it to the array!
01592     std::istringstream entryiss(entryStr);
01593     T entry;
01594     Teuchos::extractDataFromISS( entryiss, entry );
01595     // ToDo: We may need to define a traits class to allow us to specialized
01596     // how conversion from a std::string to a object is done!
01597     a.push_back(entry);
01598     // At the end of the loop body here, if we have reached the last '}'
01599     // then the input stream iss should be empty and iss.eof() should be
01600     // true, so the loop should terminate.  We put an std::exception test here
01601     // just in case something has gone wrong.
01602     TEUCHOS_TEST_FOR_EXCEPTION(
01603       found_end && !iss.eof()
01604       ,InvalidArrayStringRepresentation
01605       ,"Error, the std::string:\n"
01606       "----------\n"
01607       <<str<<
01608       "\n----------\n"
01609       "is not a valid array represntation!"
01610       );
01611   }
01612   return a;
01613 }
01614 
01615 
01616 #endif // TEUCHOS_ARRAY_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines