Teuchos Package Browser (Single Doxygen Collection) 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   assertNotNull();
01181   // Assert a valid iterator and get vector iterator
01182   const typename std::vector<T>::iterator raw_first = raw_position(first);
01183   const typename std::vector<T>::iterator raw_last = raw_position(last);
01184   const difference_type i = first - begin();
01185   vec(true,true).erase(raw_first,raw_last);
01186   return begin() + i;
01187 #else
01188   return vec_.erase(first,last);
01189 #endif
01190 }
01191 
01192 
01193 template<typename T> inline
01194 void Array<T>::swap(Array& x)
01195 {
01196   vec(true).swap(x.vec());
01197 }
01198 
01199 
01200 template<typename T> inline
01201 void Array<T>::clear()
01202 {
01203   vec(true).clear();
01204 }
01205 
01206 
01207 // Non-standard functions
01208 
01209 
01210 template<typename T> inline
01211 Array<T>& Array<T>::append(const T& x)
01212 {
01213   this->push_back(x);
01214   return *this;
01215 }
01216 
01217 
01218 template<typename T> inline
01219 void Array<T>::remove(int i)
01220 {
01221 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01222   assertIndex(i);
01223 #endif
01224   // Erase the i-th element of this array.
01225   this->erase( this->begin() + i );
01226 }
01227 
01228 
01229 template<typename T> inline
01230 int Array<T>::length() const
01231 {
01232   return this->size();
01233 }
01234 
01235 
01236 template<typename T> inline
01237 std::string Array<T>::toString() const
01238 {
01239   return (*this)().toString();
01240 }
01241 
01242 
01243 template<typename T> inline
01244 bool Array<T>::hasBoundsChecking()
01245 {
01246 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK  
01247   return true;
01248 #else
01249   return false;
01250 #endif
01251 }
01252 
01253 
01254 template<typename T> inline
01255 T* Array<T>::getRawPtr()
01256 {
01257   return ( size() ? &(*this)[0] : 0 );
01258 }
01259 
01260 
01261 template<typename T> inline
01262 const T* Array<T>::getRawPtr() const
01263 {
01264   return ( size() ? &(*this)[0] : 0 );
01265 }
01266 
01267 
01268 // Conversions to and from std::vector
01269 
01270 
01271 template<typename T> inline
01272 Array<T>::Array( const std::vector<T> &v ) :
01273 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01274   vec_(new std::vector<T>(v))
01275 #else
01276   vec_(v)
01277 #endif
01278 {}
01279 
01280 
01281 template<typename T> inline
01282 std::vector<T> Array<T>::toVector() const
01283 {
01284   if (!size())
01285     return std::vector<T>();
01286   std::vector<T> v(begin(),end());
01287   return v;
01288 }
01289 
01290 
01291 template<typename T> inline
01292 Array<T>& Array<T>::operator=( const std::vector<T> &v )
01293 {
01294   vec(true) = v;
01295   return *this;
01296 }
01297 
01298 
01299 // Views
01300 
01301 
01302 template<typename T> inline
01303 ArrayView<T> Array<T>::view( size_type offset, size_type size_in )
01304 {
01305   if (size_in) {
01306 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01307     return ArrayView<T>(this->begin().persistingView(offset, size_in));
01308 #else
01309     return arrayView( &vec()[offset], size_in );
01310 #endif
01311   }
01312   return Teuchos::null;
01313 }
01314 
01315 
01316 template<typename T> inline
01317 ArrayView<const T> Array<T>::view( size_type offset, size_type size_in ) const
01318 {
01319   if (size_in) {
01320 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01321     return ArrayView<const T>(this->begin().persistingView(offset, size_in));
01322 #else
01323     return arrayView( &vec()[offset], size_in );
01324 #endif
01325   }
01326   return Teuchos::null;
01327   // NOTE: Above, we use a different implementation to call the const version
01328   // of begin() instead of the non-const version.  This sets up a different
01329   // ArrayRCP object that gets checked.
01330 }
01331 
01332 
01333 template<typename T> inline
01334 ArrayView<T> Array<T>::operator()( size_type offset, size_type size_in )
01335 {
01336   return view(offset, size_in);
01337 }
01338 
01339 
01340 template<typename T> inline
01341 ArrayView<const T> Array<T>::operator()( size_type offset, size_type size_in ) const
01342 {
01343   return view(offset, size_in);
01344 }
01345 
01346 
01347 template<typename T> inline
01348 ArrayView<T> Array<T>::operator()()
01349 {
01350   if (!size())
01351     return null;
01352   return this->view(0, size());
01353 }
01354 
01355 
01356 template<typename T> inline
01357 ArrayView<const T> Array<T>::operator()() const
01358 {
01359   if (!size())
01360     return null;
01361   return this->view(0, size());
01362 }
01363 
01364 
01365 template<typename T> inline
01366 Array<T>::operator ArrayView<T>()
01367 {
01368   return this->operator()();
01369 }
01370 
01371 
01372 template<typename T> inline
01373 Array<T>::operator ArrayView<const T>() const
01374 {
01375   return this->operator()();
01376 }
01377 
01378 
01379 // private
01380 
01381 
01382 template<typename T>
01383 std::vector<T>&
01384 Array<T>::vec( bool isStructureBeingModified, bool activeIter )
01385 {
01386 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01387   (void)activeIter;
01388   if (isStructureBeingModified) {
01389     // Give up my ArrayRCPs used for iterator access since the array we be
01390     // getting modifed!  Any clients that have views through weak pointers
01391     // better not touch them!
01392     extern_arcp_ = null;
01393     extern_carcp_ = null;
01394   }
01395   return *vec_;
01396 #else
01397   // get rid of "unused parameter" warnings
01398   (void)isStructureBeingModified;
01399   (void)activeIter;
01400   return vec_;
01401 #endif
01402 }
01403 
01404 
01405 template<typename T> inline
01406 const std::vector<T>&
01407 Array<T>::vec() const
01408 {
01409 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01410   return *vec_;
01411 #else
01412   return vec_;
01413 #endif
01414 }
01415 
01416 
01417 template<typename T> inline
01418 typename std::vector<T>::iterator
01419 Array<T>::raw_position( iterator position )
01420 {
01421 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
01422   const iterator first = this->begin();
01423   const iterator last = this->end();
01424   TEUCHOS_TEST_FOR_EXCEPTION(
01425     !(first <= position && position <= last), DanglingReferenceError,
01426     "Error, this iterator is no longer valid for this Aray!"
01427     );
01428   // Note, above operator<=(...) functions will throw
01429   // IncompatibleIteratorsError if the iterators do not share the same
01430   // RCP_node object!
01431   return vec_->begin() + (position - this->begin());
01432 #else
01433   return position;
01434 #endif
01435 }
01436 
01437 
01438 template<typename T> inline
01439 void Array<T>::assertIndex(int i) const
01440 {
01441   TEUCHOS_TEST_FOR_EXCEPTION(
01442     !( 0 <= i && i < length() ), RangeError,
01443     "Array<T>::assertIndex(i): i="<<i<<" out of range [0, "<< length() << ")"
01444     );
01445 }
01446 
01447 
01448 template<typename T> inline
01449 void Array<T>::assertNotNull() const
01450 {
01451   TEUCHOS_TEST_FOR_EXCEPTION(
01452     !size(), NullReferenceError,
01453     typeName(*this)<<"::assertNotNull(): "
01454     "Error, the array has size zero!"
01455     );
01456 }
01457 
01458 
01459 } // namespace Teuchos
01460 
01461 
01462 // Nonmember functions
01463 
01464 
01465 template<typename T> inline
01466 bool Teuchos::operator==( const Array<T> &a1, const Array<T> &a2 )
01467 { return (a1.vec() == a2.vec()); }
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 void Teuchos::swap( Array<T> &a1, Array<T> &a2 )
01477 { a1.swap(a2); }
01478 
01479 
01480 template<typename T> inline
01481 bool Teuchos::operator<( const Array<T> &a1, const Array<T> &a2 )
01482 { return (a1.vec() < a2.vec()); }
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 std::ostream& Teuchos::operator<<(
01502   std::ostream& os, const Array<T>& array
01503   )
01504 {
01505   return os << Teuchos::toString(array);
01506 }
01507 
01508 
01509 template<typename T> inline
01510 int Teuchos::hashCode(const Array<T>& array)
01511 {
01512   int rtn = hashCode(array.length());
01513   for (int i=0; i<array.length(); i++)
01514   {
01515     rtn += hashCode(array[i]);
01516   }
01517   return rtn;
01518 }
01519 
01520 
01521 template<typename T> inline
01522 std::vector<T> Teuchos::createVector( const Array<T> &a )
01523 {
01524   return a.toVector();
01525 }
01526 
01527 
01528 template<typename T> inline
01529 std::string Teuchos::toString(const Array<T>& array)
01530 {
01531   return array.toString();
01532 }
01533 
01534 
01535 template<typename T>
01536 Teuchos::Array<T>
01537 Teuchos::fromStringToArray(const std::string& arrayStr)
01538 {
01539   const std::string str = Utils::trimWhiteSpace(arrayStr);
01540   std::istringstream iss(str);
01541   TEUCHOS_TEST_FOR_EXCEPTION(
01542     ( str[0]!='{' || str[str.length()-1] != '}' )
01543     ,InvalidArrayStringRepresentation
01544     ,"Error, the std::string:\n"
01545     "----------\n"
01546     <<str<<
01547     "\n----------\n"
01548     "is not a valid array represntation!"
01549     );
01550   char c;
01551   c = iss.get(); // Read initial '{'
01552   TEUCHOS_TEST_FOR_EXCEPT(c!='{'); // Should not throw!
01553   // Now we are ready to begin reading the entries of the array!
01554   Array<T> a;
01555   while( !iss.eof() ) {
01556     // Get the basic entry std::string
01557     std::string entryStr;
01558     std::getline(iss,entryStr,','); // Get next entry up to ,!
01559     // ToDo: Above, we might have to be careful to look for the opening and
01560     // closing of parentheses in order not to pick up an internal ',' in the
01561     // middle of an entry (for a std::complex number for instance).  The above
01562     // implementation assumes that there will be no commas in the middle of
01563     // the std::string representation of an entry.  This is certainly true for
01564     // the types bool, int, float, and double.
01565     //
01566     // Trim whitespace from beginning and end
01567     entryStr = Utils::trimWhiteSpace(entryStr);
01568     // Remove the final '}' if this is the last entry and we did not
01569     // actually terminate the above getline(...) on ','
01570     bool found_end = false;
01571     if(entryStr[entryStr.length()-1]=='}') {
01572       entryStr = entryStr.substr(0,entryStr.length()-1);
01573       found_end = true;
01574       if( entryStr.length()==0 && a.size()==0 )
01575         return a; // This is the empty array "{}" (with any spaces in it!)
01576     }
01577     TEUCHOS_TEST_FOR_EXCEPTION(
01578       0 == entryStr.length()
01579       ,InvalidArrayStringRepresentation
01580       ,"Error, the std::string:\n"
01581       "----------\n"
01582       <<str<<
01583       "\n----------\n"
01584       "is not a valid array represntation!"
01585       );
01586     // Finally we can convert the entry and add it to the array!
01587     std::istringstream entryiss(entryStr);
01588     T entry;
01589     Teuchos::extractDataFromISS( entryiss, entry );
01590     // ToDo: We may need to define a traits class to allow us to specialized
01591     // how conversion from a std::string to a object is done!
01592     a.push_back(entry);
01593     // At the end of the loop body here, if we have reached the last '}'
01594     // then the input stream iss should be empty and iss.eof() should be
01595     // true, so the loop should terminate.  We put an std::exception test here
01596     // just in case something has gone wrong.
01597     TEUCHOS_TEST_FOR_EXCEPTION(
01598       found_end && !iss.eof()
01599       ,InvalidArrayStringRepresentation
01600       ,"Error, the std::string:\n"
01601       "----------\n"
01602       <<str<<
01603       "\n----------\n"
01604       "is not a valid array represntation!"
01605       );
01606   }
01607   return a;
01608 }
01609 
01610 
01611 #endif // TEUCHOS_ARRAY_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines