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