00001 #ifndef SimTK_SimTKCOMMON_ARRAY_H_
00002 #define SimTK_SimTKCOMMON_ARRAY_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00041 #include "SimTKcommon/internal/common.h"
00042 #include "SimTKcommon/internal/ExceptionMacros.h"
00043
00044 #include <algorithm>
00045 #include <iterator>
00046 #include <vector>
00047 #include <ostream>
00048 #include <climits>
00049 #include <typeinfo>
00050
00051 namespace SimTK {
00052
00053
00054 template <class X> struct ArrayIndexTraits;
00055 template <class T, class X=unsigned> class ArrayViewConst_;
00056 template <class T, class X=unsigned> class ArrayView_;
00057 template <class T, class X=unsigned> class Array_;
00058
00059
00060
00061
00062
00063
00064
00107 template <class X> struct ArrayIndexTraits {
00110 typedef typename X::size_type size_type;
00113 typedef typename X::difference_type difference_type;
00116 static size_type max_size() {return X::max_size();}
00117 };
00118
00121 template <> struct ArrayIndexTraits<unsigned> {
00122 typedef unsigned size_type;
00123 typedef int difference_type;
00124 static size_type max_size() {return (unsigned)INT_MAX;}
00125 };
00126
00128 template <> struct ArrayIndexTraits<int> {
00129 typedef int size_type;
00130 typedef int difference_type;
00131 static size_type max_size() {return INT_MAX;}
00132 };
00133
00141 template <> struct ArrayIndexTraits<unsigned long> {
00142 typedef unsigned long size_type;
00143 typedef long difference_type;
00144 static size_type max_size() {return (unsigned long)LONG_MAX;}
00145 };
00146
00154 template <> struct ArrayIndexTraits<long> {
00155 typedef long size_type;
00156 typedef long difference_type;
00157 static size_type max_size() {return LONG_MAX;}
00158 };
00159
00165 template <> struct ArrayIndexTraits<unsigned short> {
00166 typedef unsigned short size_type;
00167 typedef int difference_type;
00168 static size_type max_size() {return USHRT_MAX;}
00169 };
00170
00175 template <> struct ArrayIndexTraits<short> {
00176 typedef short size_type;
00177 typedef short difference_type;
00178 static size_type max_size() {return SHRT_MAX;}
00179 };
00180
00181
00186 template <> struct ArrayIndexTraits<unsigned char> {
00187 typedef unsigned char size_type;
00188 typedef short difference_type;
00189 static size_type max_size() {return UCHAR_MAX;}
00190 };
00191
00197 template <> struct ArrayIndexTraits<signed char> {
00198 typedef signed char size_type;
00199 typedef signed char difference_type;
00200 static size_type max_size() {return SCHAR_MAX;}
00201 };
00202
00209 template <> struct ArrayIndexTraits<char> {
00210 typedef char size_type;
00211 typedef signed char difference_type;
00212 static size_type max_size() {return (char)SCHAR_MAX;}
00213 };
00214
00220 template <> struct ArrayIndexTraits<bool> {
00221 typedef unsigned char size_type;
00222 typedef signed char difference_type;
00223 static size_type max_size() {return 2;}
00224 };
00225
00228 template <> struct ArrayIndexTraits<unsigned long long> {
00229 typedef unsigned long long size_type;
00230 typedef long long difference_type;
00231 static size_type max_size()
00232 {return (unsigned long long)LLONG_MAX;}
00233 };
00234
00237 template <> struct ArrayIndexTraits<long long> {
00238 typedef long long size_type;
00239 typedef long long difference_type;
00240 static size_type max_size() {return LLONG_MAX;}
00241 };
00242
00243
00245
00246
00247
00248
00249
00250
00251
00252
00253 template <class Integral, class is64Bit> struct ArrayIndexPackTypeHelper
00254 { typedef Integral packed_size_type;};
00255
00256
00257 template<> struct ArrayIndexPackTypeHelper<bool,FalseType>
00258 { typedef unsigned short packed_size_type;};
00259 template<> struct ArrayIndexPackTypeHelper<char,FalseType>
00260 { typedef unsigned short packed_size_type;};
00261 template<> struct ArrayIndexPackTypeHelper<unsigned char,FalseType>
00262 { typedef unsigned short packed_size_type;};
00263 template<> struct ArrayIndexPackTypeHelper<signed char,FalseType>
00264 { typedef short packed_size_type;};
00265
00266
00267 template<> struct ArrayIndexPackTypeHelper<bool,TrueType>
00268 { typedef unsigned int packed_size_type;};
00269 template<> struct ArrayIndexPackTypeHelper<char,TrueType>
00270 { typedef unsigned int packed_size_type;};
00271 template<> struct ArrayIndexPackTypeHelper<unsigned char,TrueType>
00272 { typedef unsigned int packed_size_type;};
00273 template<> struct ArrayIndexPackTypeHelper<signed char,TrueType>
00274 { typedef int packed_size_type;};
00275 template<> struct ArrayIndexPackTypeHelper<unsigned short,TrueType>
00276 { typedef unsigned int packed_size_type;};
00277 template<> struct ArrayIndexPackTypeHelper<short,TrueType>
00278 { typedef int packed_size_type;};
00279
00280 template <class Integral> struct ArrayIndexPackType
00281 { typedef typename ArrayIndexPackTypeHelper<Integral,Is64BitPlatformType>
00282 ::packed_size_type packed_size_type;};
00290
00291
00292
00319 template <class T, class X> class ArrayViewConst_ {
00320 public:
00321
00322
00323
00330 typedef T value_type;
00332 typedef X index_type;
00334 typedef T* pointer;
00336 typedef const T* const_pointer;
00338 typedef T& reference;
00340 typedef const T& const_reference;
00342 typedef T* iterator;
00344 typedef const T* const_iterator;
00346 typedef std::reverse_iterator<iterator> reverse_iterator;
00348 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00350 typedef typename ArrayIndexTraits<X>::size_type size_type;
00353 typedef typename ArrayIndexTraits<X>::difference_type difference_type;
00355 typedef typename ArrayIndexPackType<size_type>::packed_size_type
00356 packed_size_type;
00360
00366
00368 ArrayViewConst_() : pData(0), nUsed(0), nAllocated(0) {}
00369
00379 ArrayViewConst_(const ArrayViewConst_& src)
00380 : pData(0), nUsed(src.nUsed), nAllocated(0) {
00381 if (nUsed) pData = const_cast<T*>(src.pData);
00382 }
00383
00384
00385
00408 ArrayViewConst_(const T* first, const T* last1)
00409 : pData(0),nUsed(0),nAllocated(0) {
00410 if (last1==first) return;
00411
00412 const char* methodName = "ArrayViewConst_<T>::ctor(first,last1)";
00413
00414 SimTK_ERRCHK((first&&last1)||(first==last1), methodName,
00415 "One of the source pointers was null (0); either both must be"
00416 " non-null or both must be null.");
00417
00418 SimTK_ERRCHK3(isSizeOK(last1-first), methodName,
00419 "The source data's size %llu is too big for this array which"
00420 " is limited to %llu elements by its index type %s.",
00421 ull(last1-first), ullMaxSize(), indexName());
00422
00423 pData = const_cast<T*>(first);
00424 nUsed = packed_size_type(last1-first);
00425
00426 }
00427
00455 template <class A>
00456 ArrayViewConst_(const std::vector<T,A>& src)
00457 : pData(0),nUsed(0),nAllocated(0) {
00458 if (src.empty()) return;
00459
00460 SimTK_ERRCHK3(isSizeOK(src.size()),
00461 "ArrayViewConst_<T>::ctor(std::vector<T>)",
00462 "The source std::vector's size %llu is too big for this array which"
00463 " is limited to %llu elements by its index type %s.",
00464 ull(src.size()), ullMaxSize(), indexName());
00465
00466 pData = const_cast<T*>(&src.front());
00467 nUsed = packed_size_type(src.size());
00468
00469 }
00472 operator const ArrayView_<T,X>&() const
00473 { return *reinterpret_cast<const ArrayView_<T,X>*>(this); }
00476 operator const Array_<T,X>&() const
00477 { return *reinterpret_cast<const Array_<T,X>*>(this); }
00478
00484 void disconnect() {
00485 SimTK_ASSERT(nAllocated==0,
00486 "ArrayViewConst_::deallocate(): called on an owner Array_");
00487 nUsed = 0;
00488 pData = 0;
00489 }
00490
00493 ~ArrayViewConst_() {
00494 disconnect();
00495 }
00499
00506
00508 size_type size() const {return size_type(nUsed);}
00510 size_type max_size() const {return ArrayIndexTraits<X>::max_size();}
00513 bool empty() const {return nUsed==0;}
00518 size_type capacity() const {return size_type(nAllocated?nAllocated:nUsed);}
00522 size_type allocated() const {return size_type(nAllocated);}
00528 bool isOwner() const {return nAllocated || pData==0;}
00529
00530
00531
00532
00539
00546 const T& operator[](index_type i) const {
00547 SimTK_INDEXCHECK(size_type(i),size(),"ArrayViewConst_<T>::operator[]()");
00548 return pData[i];
00549 }
00554 const T& at(index_type i) const {
00555 SimTK_INDEXCHECK_ALWAYS(size_type(i),size(),"ArrayViewConst_<T>::at()");
00556 return pData[i];
00557 }
00560 const T& getElt(index_type i) const {
00561 SimTK_INDEXCHECK(size_type(i),size(),"ArrayViewConst_<T>::getElt()");
00562 return pData[i];
00563 }
00569 const T& front() const
00570 { SimTK_ERRCHK(!empty(), "ArrayViewConst_<T>::front()", "Array was empty.");
00571 return pData[0]; }
00577 const T& back() const
00578 { SimTK_ERRCHK(!empty(), "ArrayViewConst_<T>::back()", "Array was empty.");
00579 return pData[nUsed-1]; }
00580
00599 ArrayViewConst_ operator()(index_type index, size_type length) const {
00600 const char* methodName = "ArrayViewConst_<T>(index,length)";
00601 const size_type ix(index);
00602 SimTK_ERRCHK2(isSizeInRange(ix, size()), methodName,
00603 "For this operator, we must have 0 <= index <= size(), but"
00604 " index==%llu and size==%llu.", ull(ix), ullSize());
00605 SimTK_ERRCHK2(isSizeInRange(length, size_type(size()-ix)), methodName,
00606 "This operator requires 0 <= length <= size()-index, but"
00607 " length==%llu and size()-index==%llu.",ull(length),ull(size()-ix));
00608
00609 return ArrayViewConst_(pData+ix, pData+ix+length);
00610 }
00613 ArrayViewConst_ getSubArray(index_type index, size_type length) const
00614 { return (*this)(index,length); }
00615
00619
00628
00633 const T* cbegin() const {return pData;}
00638 const T* cend() const {return pData + nUsed;}
00640 const T* begin() const {return pData;}
00642 const T* end() const {return pData + nUsed;}
00643
00646 const_reverse_iterator crbegin() const {return const_reverse_iterator(cend());}
00650 const_reverse_iterator crend() const {return const_reverse_iterator(cbegin());}
00652 const_reverse_iterator rbegin() const {return crbegin();}
00654 const_reverse_iterator rend() const {return crend();}
00655
00662 const T* cdata() const {return pData;}
00664 const T* data() const {return pData;}
00668
00669 protected:
00670
00671
00672
00673
00674
00675
00677 packed_size_type psize() const {return nUsed;}
00678 packed_size_type pallocated() const {return nAllocated;}
00679
00680
00681 void setData(const T* p) {pData = const_cast<T*>(p);}
00682 void setSize(size_type n) {nUsed = packed_size_type(n);}
00683 void incrSize() {++nUsed;}
00684 void decrSize() {--nUsed;}
00685 void setAllocated(size_type n) {nAllocated = packed_size_type(n);}
00686
00687
00688
00689 template <class S>
00690 bool isSameSize(S sz) const
00691 { return ull(sz) == ullSize(); }
00692
00693
00694
00695 template <class S>
00696 bool isSizeOK(S srcSz) const
00697 { return ull(srcSz) <= ullMaxSize(); }
00698
00699
00700
00701
00702
00703
00704 template<class Iter> static
00705 typename std::iterator_traits<Iter>::difference_type
00706 iterDistance(const Iter& first, const Iter& last1) {
00707 return iterDistanceImpl(first,last1,
00708 typename std::iterator_traits<Iter>::iterator_category());
00709 }
00710
00711
00712
00713
00714 template<class Iter> static
00715 typename std::iterator_traits<Iter>::difference_type
00716 iterDistanceImpl(const Iter& first, const Iter& last1, std::input_iterator_tag) {
00717 typename std::iterator_traits<Iter>::difference_type d = 0;
00718 for (Iter src=first; src != last1; ++src, ++d)
00719 ;
00720 return d;
00721 }
00722
00723
00724
00725 template<class Iter> static
00726 typename std::iterator_traits<Iter>::difference_type
00727 iterDistanceImpl(const Iter& first, const Iter& last1,
00728 std::random_access_iterator_tag) {
00729 return last1 - first;
00730 }
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741 template<class Iter> bool
00742 overlapsWithData(const Iter& first, const Iter& last1) {
00743 return overlapsWithDataImpl(first,last1,
00744 typename std::iterator_traits<Iter>::iterator_category());
00745 }
00746
00747
00748
00749 template <class T2> bool
00750 overlapsWithData(const T2* first, const T2* last1) {
00751
00752
00753
00754
00755
00756 const T* obegin = std::max(cbegin(), (const T*)first);
00757 const T* oend1 = std::min(cend(), (const T*)last1);
00758
00759 return obegin < oend1;
00760 }
00761
00762
00763
00764 template<class Iter> bool
00765 overlapsWithDataImpl(const Iter&, const Iter&, std::input_iterator_tag)
00766 { return false; }
00767
00768
00769
00770 template<class Iter> bool
00771 overlapsWithDataImpl(const Iter& first, const Iter& last1,
00772 std::random_access_iterator_tag) {
00773
00774
00775 if (last1 <= first)
00776 return false;
00777
00778
00779
00780
00781
00782
00783 return overlapsWithData(&*first, &*(last1-1));
00784 }
00785
00786
00787
00788
00789 template <class S>
00790 static unsigned long long ull(S sz)
00791 { return (unsigned long long)sz; }
00792
00793
00794 unsigned long long ullSize() const {return ull(size());}
00795 unsigned long long ullCapacity() const {return ull(capacity());}
00796 unsigned long long ullMaxSize() const {return ull(max_size());}
00797
00798
00799 const char* indexName() const {return NiceTypeName<X>::name();}
00800
00803 private:
00804
00805
00806
00807
00808
00809 T* pData;
00810 packed_size_type nUsed;
00811 packed_size_type nAllocated;
00812
00813 ArrayViewConst_& operator=(const ArrayViewConst_& src);
00814 };
00815
00816
00817
00818
00819
00820
00821
00822
00823
00835 template <class T, class X> class ArrayView_ : public ArrayViewConst_<T,X> {
00836 typedef ArrayViewConst_<T,X> CBase;
00837 public:
00838
00843
00844 typedef T value_type;
00845 typedef X index_type;
00846 typedef T* pointer;
00847 typedef const T* const_pointer;
00848 typedef T& reference;
00849 typedef const T& const_reference;
00850 typedef T* iterator;
00851 typedef const T* const_iterator;
00852 typedef std::reverse_iterator<iterator> reverse_iterator;
00853 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00854 typedef typename ArrayIndexTraits<X>::size_type size_type;
00855 typedef typename ArrayIndexTraits<X>::difference_type difference_type;
00856 typedef typename ArrayIndexPackType<size_type>::packed_size_type
00857 packed_size_type;
00858
00859
00860
00861
00867
00869 ArrayView_() : CBase() {}
00870
00872 ArrayView_(const ArrayView_& src) : CBase(src) {}
00873
00875 ArrayView_(T* first, const T* last1) : CBase(first,last1) {}
00876
00878 template <class A>
00879 ArrayView_(std::vector<T,A>& v) : CBase(v) {}
00880
00882 operator const Array_<T,X>&() const
00883 { return *reinterpret_cast<const Array_<T,X>*>(this); }
00884
00886 operator Array_<T,X>&()
00887 { return *reinterpret_cast<Array_<T,X>*>(this); }
00888
00891 void disconnect() {this->CBase::disconnect();}
00892
00895 ~ArrayView_() {this->CBase::disconnect();}
00899
00911
00913 ArrayView_& operator=(const ArrayView_& src) {
00914 if (&src != this)
00915 avAssignIteratorDispatch(src.cbegin(), src.cend(),
00916 std::random_access_iterator_tag(),
00917 "ArrayView_<T>::operator=(ArrayView_<T>)");
00918 return *this;
00919 }
00920
00921
00924 template <class T2, class X2>
00925 ArrayView_& operator=(const ArrayViewConst_<T2,X2>& src) {
00926 if ((const void*)&src != (void*)this)
00927 avAssignIteratorDispatch(src.cbegin(), src.cend(),
00928 std::random_access_iterator_tag(),
00929 "ArrayView_<T>::operator=(Array_<T2>)");
00930 return *this;
00931 }
00932
00933
00934
00935
00938 template <class T2, class X2>
00939 ArrayView_& operator=(const ArrayView_<T2,X2>& src)
00940 { return *this = static_cast<const ArrayViewConst_<T2,X2>&>(src); }
00943 template <class T2, class X2>
00944 ArrayView_& operator=(const Array_<T2,X2>& src)
00945 { return *this = static_cast<const ArrayViewConst_<T2,X2>&>(src); }
00946
00949 template <class T2, class A2>
00950 ArrayView_& operator=(const std::vector<T2,A2>& src) {
00951 avAssignIteratorDispatch(src.begin(), src.end(),
00952 std::random_access_iterator_tag(),
00953 "ArrayView_<T>::operator=(std::vector<T2>)");
00954 return *this;
00955 }
00956
00958 ArrayView_& operator=(const T& fillValue)
00959 { fill(fillValue); return *this; }
00960
00966 ArrayView_& fill(const T& fillValue) {
00967 for (T* d = begin(); d != end(); ++d)
00968 *d = fillValue;
00969 return *this;
00970 }
00971
00975 void assign(size_type n, const T& fillValue) {
00976 SimTK_ERRCHK2(n == size(), "ArrayView_<T>::assign(n,value)",
00977 "Assignment to an ArrayView is permitted only if the source"
00978 " is the same size. Here n==%llu element(s) but the"
00979 " ArrayView has a fixed size of %llu.",
00980 ull(n), ull(size()));
00981
00982 fill(fillValue);
00983 }
00984
01002 template <class T2>
01003 void assign(const T2* first, const T2* last1) {
01004 const char* methodName = "ArrayView_<T>::assign(T2* first, T2* last1)";
01005 SimTK_ERRCHK((first&&last1)||(first==last1), methodName,
01006 "One of the source pointers was null (0); either both must be"
01007 " non-null or both must be null.");
01008
01009 avAssignIteratorDispatch(first, last1, std::random_access_iterator_tag(),
01010 methodName);
01011 }
01012
01042
01043
01044 template <class Iter>
01045 void assign(const Iter& first, const Iter& last1)
01046 { avAssignDispatch(first,last1,typename IsIntegralType<Iter>::Result(),
01047 "ArrayView_<T>::assign(Iter first, Iter last1)"); }
01051
01058
01065 const T& operator[](index_type i) const {return this->CBase::operator[](i);}
01066
01074 T& operator[](index_type i) {return const_cast<T&>(this->CBase::operator[](i));}
01075
01080 const T& at(index_type i) const {return this->CBase::at(i);}
01081
01086 T& at(index_type i) {return const_cast<T&>(this->CBase::at(i));}
01087
01090 const T& getElt(index_type i) const {return this->CBase::getElt(i);}
01093 T& updElt(index_type i) {return const_cast<T&>(this->CBase::getElt(i));}
01094
01100 const T& front() const {return this->CBase::front();}
01101
01107 T& front() {return const_cast<T&>(this->CBase::front());}
01108
01114 const T& back() const {return this->CBase::back();}
01115
01121 T& back() {return const_cast<T&>(this->CBase::back());}
01122
01141 ArrayView_ operator()(index_type index, size_type length) {
01142 const char* methodName = "ArrayView_<T>(index,length)";
01143 const size_type ix(index);
01144 SimTK_ERRCHK2(isSizeInRange(ix, size()), methodName,
01145 "For this operator, we must have 0 <= index <= size(), but"
01146 " index==%llu and size==%llu.", ull(ix), ullSize());
01147 SimTK_ERRCHK2(isSizeInRange(length, size_type(size()-ix)), methodName,
01148 "This operator requires 0 <= length <= size()-index, but"
01149 " length==%llu and size()-index==%llu.",ull(length),ull(size()-ix));
01150
01151 return ArrayView_(data()+ix, data()+ix+length);
01152 }
01155 ArrayView_ updSubArray(index_type index, size_type length)
01156 { return (*this)(index,length); }
01160
01169
01174 const T* cbegin() const {return this->CBase::cbegin();}
01176 const T* begin() const {return this->CBase::cbegin();}
01181 T* begin() {return const_cast<T*>(this->CBase::cbegin());}
01182
01187 const T* cend() const {return this->CBase::cend();}
01189 const T* end() const {return this->CBase::cend();}
01194 T* end() {return const_cast<T*>(this->CBase::cend());}
01195
01198 const_reverse_iterator crbegin() const {return this->CBase::crbegin();}
01200 const_reverse_iterator rbegin() const {return this->CBase::crbegin();}
01203 reverse_iterator rbegin() {return reverse_iterator(end());}
01204
01208 const_reverse_iterator crend() const {return this->CBase::crend();}
01210 const_reverse_iterator rend() const {return this->CBase::crend();}
01214 reverse_iterator rend() {return reverse_iterator(begin());}
01215
01222 const T* cdata() const {return this->CBase::cdata();}
01225 const T* data() const {return this->CBase::cdata();}
01229 T* data() {return const_cast<T*>(this->CBase::cdata());}
01233
01239
01240
01241
01242
01243
01244
01245 size_type size() const {return this->CBase::size();}
01246 size_type max_size() const {return this->CBase::max_size();}
01247 bool empty() const {return this->CBase::empty();}
01248 size_type capacity() const {return this->CBase::capacity();}
01249 size_type allocated() const {return this->CBase::allocated();}
01250 bool isOwner() const {return this->CBase::isOwner();}
01254
01255 private:
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265 template <class IntegralType>
01266 void avAssignDispatch(IntegralType n, IntegralType v, TrueType isIntegralType,
01267 const char*)
01268 { assign(size_type(n), value_type(v)); }
01269
01270
01271
01272
01273 template <class InputIterator>
01274 void avAssignDispatch(const InputIterator& first, const InputIterator& last1,
01275 FalseType isIntegralType, const char* methodName)
01276 { avAssignIteratorDispatch(first, last1,
01277 typename std::iterator_traits<InputIterator>::iterator_category(),
01278 methodName); }
01279
01280
01281
01282
01283
01284
01285
01286 template <class InputIterator>
01287 void avAssignIteratorDispatch(const InputIterator& first,
01288 const InputIterator& last1,
01289 std::input_iterator_tag,
01290 const char* methodName)
01291 {
01292 T* p = begin();
01293 InputIterator src = first;
01294 while (src != last1 && p != end())
01295 *p++ = *src++;
01296
01297
01298 const size_type nCopied = size_type(p - begin());
01299 SimTK_ERRCHK2_ALWAYS(nCopied == size(), methodName,
01300 "The supplied input_iterator provided only %llu elements but this"
01301 " ArrayView has a fixed size of %llu elements.",
01302 ull(nCopied), ullSize());
01303
01304
01305 }
01306
01307
01308
01309
01310
01311 template <class ForwardIterator>
01312 void avAssignIteratorDispatch(const ForwardIterator& first,
01313 const ForwardIterator& last1,
01314 std::forward_iterator_tag,
01315 const char* methodName)
01316 {
01317 T* p = begin();
01318 ForwardIterator src = first;
01319 while (src != last1 && p != end())
01320 *p++ = *src++;
01321
01322
01323 const size_type nCopied = size_type(p - begin());
01324 SimTK_ERRCHK2_ALWAYS(nCopied == size(), methodName,
01325 "The supplied forward_ or bidirectional_iterator source range provided"
01326 " only %llu elements but this ArrayView has a fixed size of"
01327 " %llu elements.", ull(nCopied), ullSize());
01328
01329
01330 SimTK_ERRCHK1_ALWAYS(src == last1, methodName,
01331 "The supplied forward_ or bidirectional_iterator source range"
01332 " contained too many elements; this ArrayView has a fixed size of"
01333 " %llu elements.", ullSize());
01334 }
01335
01336
01337
01338
01339
01340 template <class RandomAccessIterator>
01341 void avAssignIteratorDispatch(const RandomAccessIterator& first,
01342 const RandomAccessIterator& last1,
01343 std::random_access_iterator_tag,
01344 const char* methodName)
01345 {
01346 SimTK_ERRCHK2_ALWAYS(isSameSize(last1-first), methodName,
01347 "Assignment to an ArrayView is permitted only if the source"
01348 " is the same size. Here the source had %llu element(s) but the"
01349 " ArrayView has a fixed size of %llu.",
01350 ull(last1-first), ull(size()));
01351
01352 SimTK_ERRCHK_ALWAYS(!overlapsWithData(first,last1), methodName,
01353 "Source range can't overlap with the destination data.");
01354
01355 T* p = begin();
01356 RandomAccessIterator src = first;
01357 while (p != end())
01358 *p++ = *src++;
01359 }
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369 packed_size_type psize() const {return this->CBase::psize();}
01370 packed_size_type pallocated() const {return this->CBase::pallocated();}
01371
01372
01373
01374 unsigned long long ullSize() const {return this->CBase::ullSize();}
01375 unsigned long long ullCapacity() const {return this->CBase::ullCapacity();}
01376 unsigned long long ullMaxSize() const {return this->CBase::ullMaxSize();}
01377
01378
01379 const char* indexName() const {return this->CBase::indexName();}
01380 };
01381
01382
01383
01384
01385
01386
01387
01388
01491 template <class T, class X> class Array_ : public ArrayView_<T,X> {
01492 typedef ArrayView_<T,X> Base;
01493 typedef ArrayViewConst_<T,X> CBase;
01494 public:
01495
01496
01497
01503
01504
01505 typedef T value_type;
01506 typedef X index_type;
01507 typedef T* pointer;
01508 typedef const T* const_pointer;
01509 typedef T& reference;
01510 typedef const T& const_reference;
01511 typedef T* iterator;
01512 typedef const T* const_iterator;
01513 typedef std::reverse_iterator<iterator> reverse_iterator;
01514 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
01515 typedef typename ArrayIndexTraits<X>::size_type size_type;
01516 typedef typename ArrayIndexTraits<X>::difference_type difference_type;
01517 typedef typename ArrayIndexPackType<size_type>::packed_size_type
01518 packed_size_type;
01519
01520
01521
01528
01529
01531 Array_() : Base() {}
01532
01537 explicit Array_(size_type n) : Base() {
01538 SimTK_SIZECHECK(n, max_size(), "Array_<T>::ctor(n)");
01539 allocateNoConstruct(n);
01540 defaultConstruct(data(), data()+n);
01541 setSize(n);
01542 }
01543
01547 Array_(size_type n, const T& initVal) : Base() {
01548 SimTK_SIZECHECK(n, max_size(), "Array_<T>::ctor(n,T)");
01549 setSize(n);
01550 allocateNoConstruct(size());
01551 fillConstruct(begin(), cend(), initVal);
01552 }
01568 template <class InputIter>
01569 Array_(const InputIter& first, const InputIter& last1) : Base() {
01570 ctorDispatch(first,last1,typename IsIntegralType<InputIter>::Result());
01571 }
01572
01578 template <class T2>
01579 Array_(const T2* first, const T2* last1) : Base() {
01580 const char* methodName = "Array_<T>::ctor(first,last1)";
01581 SimTK_ERRCHK((first&&last1)||(first==last1), methodName,
01582 "Pointers must be non-null unless they are both null.");
01583 SimTK_ERRCHK3(isSizeOK(last1-first), methodName,
01584 "Source has %llu elements but this array is limited to %llu"
01585 " elements by its index type %s.",
01586 ull(last1-first), ullMaxSize(), indexName());
01587
01588 setSize(size_type(last1-first));
01589 allocateNoConstruct(size());
01590 copyConstruct(begin(), cend(), first);
01591 }
01592
01597 template <class T2>
01598 explicit Array_(const std::vector<T2>& v) : Base() {
01599 if (v.empty()) return;
01600
01601 SimTK_ERRCHK3(isSizeOK(v.size()), "Array_<T>::ctor(std::vector<T2>)",
01602 "The source std::vector's size %llu is too big for this array which"
01603 " is limited to %llu elements by its index type %s.",
01604 ull(v.size()), ullMaxSize(), indexName());
01605
01606
01607
01608
01609 new (this) Array_(&v.front(), (&v.back())+1);
01610 }
01611
01616 Array_(const Array_& src) : Base() {
01617 setSize(src.size());
01618 allocateNoConstruct(size());
01619 copyConstruct(begin(), cend(), src.data());
01620 }
01621
01628 template <class T2, class X2>
01629 Array_(const Array_<T2,X2>& src) : Base() {
01630 new (this) Array_(src.begin(), src.cend());
01631 }
01632
01662 Array_(T* first, const T* last1, const DontCopy&) : Base(first,last1) {}
01663
01691 template <class A>
01692 Array_(std::vector<T,A>& v, const DontCopy&) : Base(v) {}
01693
01697 ~Array_() {
01698 deallocate();
01699 }
01700
01709 Array_& deallocate() {
01710 if (allocated()) {
01711 clear();
01712 deallocateNoDestruct();
01713 }
01714 this->Base::disconnect();
01715 return *this;
01716 }
01717
01721
01756
01774 void assign(size_type n, const T& fillValue) {
01775 const char* methodName = "Array_<T>::assign(n,value)";
01776 SimTK_ERRCHK3(isSizeOK(n), methodName,
01777 "Requested size %llu is too big for this array which is limited"
01778 " to %llu elements by its index type %s.",
01779 ull(n), ullMaxSize(), indexName());
01780
01781 SimTK_ERRCHK2(isOwner() || n==size(), methodName,
01782 "Requested size %llu is not allowed because this is a non-owner"
01783 " array of fixed size %llu.", ull(n), ull(size()));
01784
01785 if (!isOwner())
01786 this->Base::fill(fillValue);
01787 else {
01788 clear();
01789 reallocateIfAdvisable(n);
01790 fillConstruct(data(), cdata()+n, fillValue);
01791 setSize(n);
01792 }
01793 }
01794
01809 void fill(const T& fillValue) {this->Base::fill(fillValue);}
01810
01811
01833 template <class T2>
01834 void assign(const T2* first, const T2* last1) {
01835 const char* methodName = "Array_<T>::assign(T2* first, T2* last1)";
01836 SimTK_ERRCHK((first&&last1)||(first==last1), methodName,
01837 "Pointers must be non-null unless they are both null.");
01838 SimTK_ERRCHK(!overlapsWithData(first,last1), methodName,
01839 "Source range can't overlap the current array contents.");
01840
01841 assignIteratorDispatch(first,last1,std::random_access_iterator_tag(),
01842 methodName);
01843 }
01844
01845
01881 template <class Iter>
01882 void assign(const Iter& first, const Iter& last1) {
01883 assignDispatch(first,last1,typename IsIntegralType<Iter>::Result(),
01884 "Array_<T>::assign(Iter first, Iter last1)");
01885 }
01886
01892 Array_& operator=(const Array_& src) {
01893 if (this != &src)
01894 assignIteratorDispatch(src.begin(), src.end(),
01895 std::random_access_iterator_tag(),
01896 "Array_<T>::operator=(Array_<T>)");
01897 return *this;
01898 }
01899
01905 template <class T2, class X2>
01906 Array_& operator=(const Array_<T2,X2>& src) {
01907 assignIteratorDispatch(src.begin(), src.end(),
01908 std::random_access_iterator_tag(),
01909 "Array_<T>::operator=(Array_<T2,X2>)");
01910 return *this;
01911 }
01912
01913
01918 template <class T2, class A>
01919 Array_& operator=(const std::vector<T2,A>& src) {
01920 assignIteratorDispatch(src.begin(), src.end(),
01921 std::random_access_iterator_tag(),
01922 "Array_<T>::operator=(std::vector)");
01923 return *this;
01924 }
01925
01932 void swap(Array_& other) {
01933 T* const pTmp=data(); setData(other.data()); other.setData(pTmp);
01934 size_type nTmp=size(); setSize(other.size()); other.setSize(nTmp);
01935 nTmp=allocated(); setAllocated(other.allocated()); other.setAllocated(nTmp);
01936 }
01937
01943 Array_& adoptData(T* newData, size_type dataSize,
01944 size_type dataCapacity)
01945 {
01946 const char* methodName = "Array_<T>::adoptData()";
01947 SimTK_SIZECHECK(dataCapacity, max_size(), methodName);
01948 SimTK_ERRCHK2(dataSize <= dataCapacity, methodName,
01949 "Specified data size %llu was greater than the specified data"
01950 " capacity of %llu.", ull(dataSize), ull(dataCapacity));
01951 SimTK_ERRCHK(newData || dataCapacity==0, methodName,
01952 "A null data pointer is allowed only if the size and capacity are"
01953 " specified as zero.");
01954 SimTK_ERRCHK(!overlapsWithData(newData, newData+dataSize), methodName,
01955 "The new data can't overlap with the old data.");
01956
01957 deallocate();
01958 setData(newData);
01959 setSize(dataSize);
01960 setAllocated(dataCapacity);
01961 return *this;
01962 }
01965 Array_& adoptData(T* newData, size_type dataSize)
01966 { return adoptData(newData, dataSize, dataSize); }
01967
01968
01982 Array_& shareData(T* newData, size_type dataSize) {
01983 const char* methodName = "Array_<T>::shareData()";
01984 SimTK_SIZECHECK(dataSize, max_size(), methodName);
01985 SimTK_ERRCHK(newData || dataSize==0, methodName,
01986 "A null data pointer is allowed only if the size is zero.");
01987 SimTK_ERRCHK(!overlapsWithData(newData, newData+dataSize), methodName,
01988 "The new data can't overlap with the old data.");
01989
01990 deallocate();
01991 setData(newData);
01992 setSize(dataSize);
01993 setAllocated(0);
01994 return *this;
01995 }
01996
01999 Array_& shareData(T* first, const T* last1) {
02000 SimTK_ERRCHK3(isSizeOK(last1-first), "Array_<T>::shareData(first,last1)",
02001 "Requested size %llu is too big for this array which is limited"
02002 " to %llu elements by its index type %s.",
02003 ull(last1-first), ullMaxSize(), indexName());
02004 return shareData(first, size_type(last1-first));
02005 }
02006
02010
02016
02017
02018
02019
02020
02021
02023 size_type size() const {return this->CBase::size();}
02025 size_type max_size() const {return this->CBase::max_size();}
02028 bool empty() const {return this->CBase::empty();}
02033 size_type capacity() const {return this->CBase::capacity();}
02034
02039 void resize(size_type n) {
02040 if (n == size()) return;
02041
02042 SimTK_ERRCHK2(isOwner(), "Array_<T>::resize(n)",
02043 "Requested size change to %llu is not allowed because this is a"
02044 " non-owner array of fixed size %llu.", ull(n), ull(size()));
02045
02046 if (n < size()) {
02047 erase(data()+n, cend());
02048 return;
02049 }
02050
02051 reserve(n);
02052 defaultConstruct(data()+size(), cdata()+n);
02053 setSize(n);
02054 }
02055
02060 void resize(size_type n, const T& initVal) {
02061 if (n == size()) return;
02062
02063 SimTK_ERRCHK2(isOwner(), "Array_<T>::resize(n,value)",
02064 "Requested size change to %llu is not allowed because this is a"
02065 " non-owner array of fixed size %llu.", ull(n), ull(size()));
02066
02067 if (n < size()) {
02068 erase(data()+n, cend());
02069 return;
02070 }
02071
02072 reserve(n);
02073 fillConstruct(data()+size(), cdata()+n, initVal);
02074 setSize(n);
02075 }
02076
02083 void reserve(size_type n) {
02084 if (capacity() >= n)
02085 return;
02086
02087 SimTK_ERRCHK2(isOwner(), "Array_<T>::reserve()",
02088 "Requested capacity change to %llu is not allowed because this is a"
02089 " non-owner array of fixed size %llu.", ull(n), ull(size()));
02090
02091 T* newData = allocN(n);
02092 copyConstructThenDestructSource(newData, newData+size(), data());
02093 freeN(data());
02094 setData(newData);
02095 setAllocated(n);
02096 }
02097
02118 void shrink_to_fit() {
02119
02120
02121 if (capacity() - size()/4 <= size())
02122 return;
02123 T* newData = allocN(size());
02124 copyConstructThenDestructSource(newData, newData+size(), data());
02125 deallocateNoDestruct();
02126 setData(newData);
02127 setAllocated(size());
02128 }
02129
02133 size_type allocated() const {return this->CBase::allocated();}
02139 bool isOwner() const {return this->CBase::isOwner();}
02143
02152
02157 const T* cbegin() const {return this->CBase::cbegin();}
02159 const T* begin() const {return this->CBase::cbegin();}
02164 T* begin() {return this->Base::begin();}
02165
02170 const T* cend() const {return this->CBase::cend();}
02172 const T* end() const {return this->CBase::cend();}
02177 T* end() {return this->Base::end();}
02178
02181 const_reverse_iterator crbegin() const {return this->CBase::crbegin();}
02183 const_reverse_iterator rbegin() const {return this->CBase::crbegin();}
02186 reverse_iterator rbegin() {return this->Base::rbegin();}
02187
02191 const_reverse_iterator crend() const {return this->CBase::crend();}
02193 const_reverse_iterator rend() const {return this->CBase::crend();}
02197 reverse_iterator rend() {return this->Base::rend();}
02198
02205 const T* cdata() const {return this->CBase::cdata();}
02208 const T* data() const {return this->CBase::cdata();}
02212 T* data() {return this->Base::data();}
02220
02227 const T& operator[](index_type i) const {return this->CBase::operator[](i);}
02228
02236 T& operator[](index_type i) {return this->Base::operator[](i);}
02237
02242 const T& at(index_type i) const {return this->CBase::at(i);}
02243
02248 T& at(index_type i) {return const_cast<T&>(this->Base::at(i));}
02249
02252 const T& getElt(index_type i) const {return this->CBase::getElt(i);}
02255 T& updElt(index_type i) {return this->Base::updElt(i);}
02256
02262 const T& front() const {return this->CBase::front();}
02263
02269 T& front() {return const_cast<T&>(this->Base::front());}
02270
02276 const T& back() const {return this->CBase::back();}
02277
02283 T& back() {return const_cast<T&>(this->Base::back());}
02284
02287 ArrayViewConst_<T,X> operator()(index_type index, size_type length) const
02288 { return CBase::operator()(index,length); }
02291 ArrayViewConst_<T,X> getSubArray(index_type index, size_type length) const
02292 { return CBase::getSubArray(index,length); }
02293
02296 ArrayView_<T,X> operator()(index_type index, size_type length)
02297 { return Base::operator()(index,length); }
02300 ArrayView_<T,X> updSubArray(index_type index, size_type length)
02301 { return Base::updSubArray(index,length); }
02305
02311
02338 void push_back(const T& value) {
02339 if (pallocated() == psize())
02340 growAtEnd(1,"Array_<T>::push_back(value)");
02341 copyConstruct(end(), value);
02342 incrSize();
02343 }
02344
02358 void push_back() {
02359 if (pallocated() == psize())
02360 growAtEnd(1,"Array_<T>::push_back()");
02361 defaultConstruct(end());
02362 incrSize();
02363 }
02364
02380 T* raw_push_back() {
02381 if (pallocated() == psize())
02382 growAtEnd(1,"Array_<T>::raw_push_back()");
02383 T* const p = end();
02384 incrSize();
02385 return p;
02386 }
02387
02390 void pop_back() {
02391 SimTK_ERRCHK(!empty(), "Array_<T>::pop_back()", "Array was empty.");
02392 destruct(&back());
02393 decrSize();
02394 }
02395
02413 T* erase(T* first, const T* last1) {
02414 SimTK_ERRCHK(begin() <= first && first <= last1 && last1 <= end(),
02415 "Array<T>::erase(first,last1)", "Pointers out of range or out of order.");
02416
02417 const size_type nErased = size_type(last1-first);
02418 SimTK_ERRCHK(isOwner() || nErased==0, "Array<T>::erase(first,last1)",
02419 "No elements can be erased from a non-owner array.");
02420
02421 if (nErased) {
02422 destruct(first, last1);
02423 moveElementsDown(first+nErased, nErased);
02424 setSize(size()-nErased);
02425 }
02426 return first;
02427 }
02428
02448 T* erase(T* p) {
02449 SimTK_ERRCHK(begin() <= p && p < end(),
02450 "Array<T>::erase(p)", "Pointer must point to a valid element.");
02451 SimTK_ERRCHK(isOwner(), "Array<T>::erase(p)",
02452 "No elements can be erased from a non-owner array.");
02453
02454 destruct(p);
02455 moveElementsDown(p+1, 1);
02456 decrSize();
02457 return p;
02458 }
02459
02460
02481 T* eraseFast(T* p) {
02482 SimTK_ERRCHK(begin() <= p && p < end(),
02483 "Array<T>::eraseFast(p)", "Pointer must point to a valid element.");
02484 SimTK_ERRCHK(isOwner(), "Array<T>::eraseFast(p)",
02485 "No elements can be erased from a non-owner array.");
02486
02487 destruct(p);
02488 if (p+1 != end())
02489 moveOneElement(p, &back());
02490 decrSize();
02491 return p;
02492 }
02493
02501 void clear() {
02502 SimTK_ERRCHK(isOwner() || empty(), "Array_<T>::clear()",
02503 "clear() is not allowed for a non-owner array.");
02504 destruct(begin(), end());
02505 setSize(0);
02506 }
02507
02508
02535 T* insert(T* p, size_type n, const T& value) {
02536 T* const gap = insertGapAt(p, n, "Array<T>::insert(p,n,value)");
02537
02538 fillConstruct(gap, gap+n, value);
02539 setSize(size()+n);
02540 return gap;
02541 }
02542
02547 T* insert(T* p, const T& value) {
02548 T* const gap = insertGapAt(p, 1, "Array<T>::insert(p,value)");
02549
02550 copyConstruct(gap, value);
02551 incrSize();
02552 return gap;
02553 }
02554
02584 template <class T2>
02585 T* insert(T* p, const T2* first, const T2* last1) {
02586 const char* methodName = "Array_<T>::insert(T* p, T2* first, T2* last1)";
02587 SimTK_ERRCHK((first&&last1) || (first==last1), methodName,
02588 "One of first or last1 was null; either both or neither must be null.");
02589 SimTK_ERRCHK(!overlapsWithData(first,last1), methodName,
02590 "Source range can't overlap with the current array contents.");
02591
02592 return insertIteratorDispatch(p, first, last1,
02593 std::random_access_iterator_tag(),
02594 methodName);
02595 }
02596
02599 template <class Iter>
02600 T* insert(T* p, const Iter& first, const Iter& last1) {
02601 return insertDispatch(p, first, last1,
02602 typename IsIntegralType<Iter>::Result(),
02603 "Array_<T>::insert(T* p, Iter first, Iter last1)");
02604 }
02609
02610 private:
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628 T* growWithGap(T* gapPos, size_type gapSz, const char* methodName) {
02629 assert(gapSz > 0);
02630
02631
02632 SimTK_ERRCHK(begin() <= gapPos && gapPos <= end(), methodName,
02633 "Given insertion point is not valid for this array.");
02634
02635
02636 setAllocated(calcNewCapacityForGrowthBy(gapSz, methodName));
02637 T* newData = allocN(allocated());
02638
02639
02640 const size_type nBefore = gapPos-begin();
02641
02642
02643 T* newGap = newData + nBefore;
02644 T* newGapEnd = newGap + gapSz;
02645
02646
02647 copyConstructThenDestructSource(newData, newGap, data());
02648
02649 copyConstructThenDestructSource(newGapEnd, newData+size(), gapPos);
02650
02651
02652 freeN(data()); setData(newData);
02653 return newGap;
02654 }
02655
02656
02657 void growAtEnd(size_type n, const char* methodName) {
02658 assert(n > 0);
02659
02660 setAllocated(calcNewCapacityForGrowthBy(n, methodName));
02661 T* newData = allocN(allocated());
02662
02663 copyConstructThenDestructSource(newData, newData+size(), data());
02664
02665 freeN(data()); setData(newData);
02666 }
02667
02668
02669
02670
02671
02672
02673
02674
02675
02676 size_type calcNewCapacityForGrowthBy(size_type n, const char* methodName) const {
02677 SimTK_ERRCHK3_ALWAYS(isGrowthOK(n), methodName,
02678 "Can't grow this Array by %llu element(s) because it would"
02679 " then exceed the max_size of %llu set by its index type %s.",
02680 (unsigned long long)n, ullMaxSize(), indexName());
02681
02682
02683 const size_type mustHave = capacity() + n;
02684
02685
02686
02687 const size_type wantToHave = capacity() <= max_size()/2
02688 ? 2*capacity()
02689 : max_size();
02690
02691 const size_type newCapacity = std::max(std::max(mustHave,wantToHave),
02692 minAlloc());
02693 return newCapacity;
02694 }
02695
02696
02697
02698
02699
02700 T* insertGapAt(T* p, size_type n, const char* methodName) {
02701
02702 SimTK_ERRCHK(begin() <= p && p <= end(), methodName,
02703 "Given insertion point is not valid for this Array.");
02704
02705 if (n==0) return p;
02706
02707 SimTK_ERRCHK_ALWAYS(isOwner(), methodName,
02708 "No elements can be inserted into a non-owner array.");
02709
02710
02711
02712 const size_type before = (size_type)(p-begin()), after = (size_type)(end()-p);
02713
02714
02715
02716
02717 if (capacity() >= size()+n) {
02718 moveElementsUp(p, n);
02719 } else {
02720 setAllocated(calcNewCapacityForGrowthBy(n, methodName));
02721 T* newdata = allocN(allocated());
02722
02723 copyConstructThenDestructSource(newdata, newdata+before, data());
02724
02725
02726 copyConstructThenDestructSource(newdata+before+n,
02727 newdata+before+n+after,
02728 p);
02729 p = newdata + before;
02730 freeN(data());
02731 setData(newdata);
02732 }
02733
02734 return p;
02735 }
02736
02737
02738
02739
02740
02741
02742 template <class IntegralType> void
02743 ctorDispatch(IntegralType n, IntegralType v, TrueType isIntegralType) {
02744 new(this) Array_(size_type(n), value_type(v));
02745 }
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755 template <class InputIterator> void
02756 ctorDispatch(const InputIterator& first, const InputIterator& last1,
02757 FalseType isIntegralType)
02758 { ctorIteratorDispatch(first, last1,
02759 typename std::iterator_traits<InputIterator>::iterator_category()); }
02760
02761
02762
02763
02764
02765
02766
02767 template <class InputIterator> void
02768 ctorIteratorDispatch(const InputIterator& first, const InputIterator& last1,
02769 std::input_iterator_tag)
02770 {
02771 InputIterator src = first;
02772 while (src != last1) {
02773
02774
02775
02776
02777
02778 if (size() == max_size()) {
02779 deallocate();
02780 SimTK_ERRCHK2_ALWAYS(!"too many elements",
02781 "Array_::ctor(InputIterator first, InputIterator last1)",
02782 "There were still source elements available when the array"
02783 " reached its maximum size of %llu as determined by its index"
02784 " type %s.", ullMaxSize(), indexName());
02785 }
02786 push_back(*src++);
02787 }
02788 }
02789
02790
02791
02792
02793
02794
02795 template <class ForwardIterator> void
02796 ctorIteratorDispatch(const ForwardIterator& first, const ForwardIterator& last1,
02797 std::forward_iterator_tag)
02798 {
02799 const char* methodName =
02800 "Array_::ctor(ForwardIterator first, ForwardIterator last1)";
02801 typedef typename std::iterator_traits<ForwardIterator>::difference_type
02802 difference_type;
02803
02804
02805
02806 const difference_type nInput = iterDistance(first,last1);
02807
02808 SimTK_ERRCHK(nInput >= 0, methodName, "Iterators were out of order.");
02809
02810 SimTK_ERRCHK3(isSizeOK(nInput), methodName,
02811 "Source has %llu elements but this array is limited to %llu"
02812 " elements by its index type %s.",
02813 ull(nInput), ullMaxSize(), indexName());
02814
02815 const size_type n = size_type(nInput);
02816 setSize(n);
02817 allocateNoConstruct(n);
02818 copyConstruct(data(), data()+n, first);
02819 }
02820
02821
02822
02823
02824
02825
02826 template <class IntegralType>
02827 T* insertDispatch(T* p, IntegralType n, IntegralType v,
02828 TrueType isIntegralType, const char*)
02829 { return insert(p, size_type(n), value_type(v)); }
02830
02831
02832
02833
02834 template <class InputIterator>
02835 T* insertDispatch(T* p, const InputIterator& first, const InputIterator& last1,
02836 FalseType isIntegralType, const char* methodName)
02837 { return insertIteratorDispatch(p, first, last1,
02838 typename std::iterator_traits<InputIterator>::iterator_category(),
02839 methodName); }
02840
02841
02842
02843
02844 template <class InputIterator>
02845 T* insertIteratorDispatch(T* p, InputIterator first, InputIterator last1,
02846 std::input_iterator_tag, const char* methodName)
02847 {
02848 size_type nInserted = 0;
02849 while (first != last1) {
02850
02851 SimTK_ERRCHK2_ALWAYS(size() < max_size(), methodName,
02852 "There were still source elements available when the array"
02853 " reached its maximum size of %llu as determined by its index"
02854 " type %s.", ullMaxSize(), indexName());
02855 p = insert(p, *first++);
02856 ++p; ++nInserted;
02857 }
02858
02859
02860 return p-nInserted;
02861 }
02862
02863
02864
02865
02866
02867
02868 template <class ForwardIterator>
02869 T* insertIteratorDispatch(T* p, const ForwardIterator& first,
02870 const ForwardIterator& last1,
02871 std::forward_iterator_tag,
02872 const char* methodName)
02873 {
02874 typedef typename std::iterator_traits<ForwardIterator>::difference_type
02875 difference_type;
02876
02877
02878
02879 const difference_type nInput = iterDistance(first,last1);
02880
02881 SimTK_ERRCHK(nInput >= 0, methodName, "Iterators were out of order.");
02882
02883 SimTK_ERRCHK3(isGrowthOK(nInput), methodName,
02884 "Source has %llu elements which would make this array exceed the %llu"
02885 " elements allowed by its index type %s.",
02886 ull(nInput), ullMaxSize(), indexName());
02887
02888 const size_type n = size_type(nInput);
02889 p = insertGapAt(p, n, methodName);
02890 copyConstruct(p, p+n, first);
02891 setSize(size()+n);
02892 return p;
02893 }
02894
02895
02896
02897
02898
02899
02900 template <class IntegralType>
02901 void assignDispatch(IntegralType n, IntegralType v, TrueType isIntegralType,
02902 const char* methodName)
02903 { assign(size_type(n), value_type(v)); }
02904
02905
02906
02907
02908 template <class InputIterator>
02909 void assignDispatch(const InputIterator& first, const InputIterator& last1,
02910 FalseType isIntegralType, const char* methodName)
02911 { assignIteratorDispatch(first, last1,
02912 typename std::iterator_traits<InputIterator>::iterator_category(),
02913 methodName); }
02914
02915
02916
02917
02918 template <class InputIterator>
02919 void assignIteratorDispatch(const InputIterator& first,
02920 const InputIterator& last1,
02921 std::input_iterator_tag,
02922 const char* methodName)
02923 {
02924
02925
02926 SimTK_ERRCHK_ALWAYS(isOwner(), methodName,
02927 "Assignment to a non-owner array can only be done from a source"
02928 " designated with forward iterators or pointers because we"
02929 " must be able to verify that the source and destination sizes"
02930 " are the same.");
02931
02932 clear();
02933 InputIterator src = first;
02934 while (src != last1) {
02935
02936 SimTK_ERRCHK2_ALWAYS(size() < max_size(), methodName,
02937 "There were still source elements available when the array"
02938 " reached its maximum size of %llu as determined by its index"
02939 " type %s.", ullMaxSize(), indexName());
02940
02941 push_back(*src++);
02942 }
02943 }
02944
02945
02946
02947
02948
02949
02950 template <class ForwardIterator>
02951 void assignIteratorDispatch(const ForwardIterator& first,
02952 const ForwardIterator& last1,
02953 std::forward_iterator_tag,
02954 const char* methodName)
02955 {
02956 typedef typename std::iterator_traits<ForwardIterator>::difference_type
02957 IterDiffType;
02958
02959
02960
02961 const IterDiffType nInput = iterDistance(first,last1);
02962
02963 SimTK_ERRCHK(nInput >= 0, methodName, "Iterators were out of order.");
02964
02965 SimTK_ERRCHK3(isSizeOK(nInput), methodName,
02966 "Source has %llu elements but this Array is limited to %llu"
02967 " elements by its index type %s.",
02968 ull(nInput), ullMaxSize(), indexName());
02969
02970 const size_type n = size_type(nInput);
02971 if (isOwner()) {
02972
02973
02974
02975 clear();
02976 reallocateIfAdvisable(n);
02977 copyConstruct(data(), cdata()+n, first);
02978 setSize(n);
02979 } else {
02980
02981
02982
02983
02984 SimTK_ERRCHK2(n == size(), methodName,
02985 "Source has %llu elements which does not match the size %llu"
02986 " of the non-owner array it is being assigned into.",
02987 ull(n), ullSize());
02988
02989 T* p = begin();
02990 ForwardIterator src = first;
02991 while (src != last1)
02992 *p++ = *src++;
02993 }
02994 }
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007 void reallocateIfAdvisable(size_type n) {
03008 if (allocated() < n || allocated()/2 > std::max(minAlloc(), n))
03009 reallocateNoDestructOrConstruct(n);
03010 }
03011
03012
03013 void allocateNoConstruct(size_type n)
03014 { setData(allocN(n)); setAllocated(n); }
03015 void deallocateNoDestruct()
03016 { freeN(data()); setData(0); setAllocated(0); }
03017 void reallocateNoDestructOrConstruct(size_type n)
03018 { deallocateNoDestruct(); allocateNoConstruct(n); }
03019
03020
03021 size_type minAlloc() const
03022 { return std::min(max_size(), size_type(4)); }
03023
03024
03025
03026
03027 static T* allocN(size_type n) {
03028 if (n==0) return 0;
03029 unsigned char* newdata = new unsigned char[n * sizeof(T)];
03030 #ifndef NDEBUG
03031 unsigned char* b=newdata;
03032 const unsigned char* e=newdata+(n*sizeof(T));
03033 while (b != e) *b++ = 0xff;
03034 #endif
03035 return reinterpret_cast<T*>(newdata);
03036 }
03037
03038
03039
03040 static void freeN(T* p) {
03041 delete[] reinterpret_cast<char*>(p);
03042 }
03043
03044
03045 static void defaultConstruct(T* p) {new(p) T();}
03046
03047 static void defaultConstruct(T* b, const T* e)
03048 { while (b!=e) new(b++) T(); }
03049
03050
03051 static void fillConstruct(T* b, const T* e, const T& v)
03052 { while(b!=e) new(b++) T(v); }
03053
03054
03055 static void copyConstruct(T* p, const T& v) {new(p) T(v);}
03056
03057 static void copyConstruct(T* b, const T* e, T* src)
03058 { while(b!=e) new(b++) T(*src++); }
03059
03060
03061 template <class InputIterator>
03062 static void copyConstruct(T* b, const T* e, InputIterator src)
03063 { while(b!=e) new(b++) T(*src++); }
03064
03065
03066
03067
03068
03069 static void copyConstructThenDestructSource(T* b, const T* e, T* src)
03070 { while(b!=e) {new(b++) T(*src); src++->~T();} }
03071
03072
03073
03074
03075
03076 void moveOneElement(T* to, T* from) {
03077 assert(data() <= to && to < data()+allocated());
03078 assert(data() <= from && from < data()+allocated());
03079 copyConstruct(to, *from);
03080 destruct(from);
03081 }
03082
03083
03084
03085
03086 void moveElementsDown(T* p, size_type n) {
03087 assert(n > 0);
03088 for (; p != end(); ++p)
03089 moveOneElement(p-n,p);
03090 }
03091
03092
03093
03094
03095 void moveElementsUp(T* p, size_type n) {
03096 assert(n > 0);
03097 T* src = end();
03098 while (src != p) {
03099 --src;
03100 moveOneElement(src+n, src);;
03101 }
03102 }
03103
03104
03105 static void destruct(T* p) {p->~T();}
03106
03107 static void destruct(T* b, const T* e)
03108 { while(b!=e) b++->~T(); }
03109
03110
03111
03112 template <class S>
03113 bool isGrowthOK(S n) const
03114 { return isSizeOK(ullCapacity() + ull(n)); }
03115
03116
03117
03118
03119
03120
03121
03122
03123 packed_size_type psize() const {return this->CBase::psize();}
03124 packed_size_type pallocated() const {return this->CBase::pallocated();}
03125
03126 void setData(const T* p) {this->CBase::setData(p);}
03127 void setSize(size_type n) {this->CBase::setSize(n);}
03128 void incrSize() {this->CBase::incrSize();}
03129 void decrSize() {this->CBase::decrSize();}
03130 void setAllocated(size_type n) {this->CBase::setAllocated(n);}
03131
03132
03133 unsigned long long ullSize() const {return this->CBase::ullSize();}
03134 unsigned long long ullCapacity() const {return this->CBase::ullCapacity();}
03135 unsigned long long ullMaxSize() const {return this->CBase::ullMaxSize();}
03136
03137
03138 const char* indexName() const {return this->CBase::indexName();}
03139 };
03140
03141
03142
03143
03144
03145
03146
03147
03148
03149
03150 template <class T, class X> static inline
03151 std::istream& readArrayFromStreamHelper
03152 (std::istream& in, bool isFixedSize, Array_<T,X>& out)
03153 {
03154
03155
03156 if (!in.good()) {in.setstate(std::ios::failbit); return in;}
03157
03158
03159
03160
03161 if (!out.isOwner())
03162 isFixedSize = true;
03163
03164
03165 const typename Array_<T,X>::size_type
03166 numRequired = isFixedSize ? out.size() : 0;
03167
03168 if (!isFixedSize)
03169 out.clear();
03170
03171
03172
03173
03174 std::ws(in); if (in.fail()) return in;
03175 if (in.eof()) {
03176 if (isFixedSize && numRequired != 0)
03177 in.setstate(std::ios_base::failbit);
03178 return in;
03179 }
03180
03181
03182 assert(in.good());
03183
03184
03185 typename std::iostream::int_type ch;
03186 const typename std::iostream::int_type EOFch =
03187 std::iostream::traits_type::eof();
03188
03189
03190 bool lookForCloser = true;
03191 char openBracket, closeBracket;
03192 ch = in.peek(); if (in.fail()) return in;
03193 assert(ch != EOFch);
03194
03195 openBracket = (char)ch;
03196 if (openBracket=='(') {in.get(); closeBracket = ')';}
03197 else if (openBracket=='[') {in.get(); closeBracket = ']';}
03198 else if (openBracket=='{') {in.get(); closeBracket = '}';}
03199 else lookForCloser = false;
03200
03201
03202
03203
03204
03205 if (in.good()) std::ws(in);
03206
03207
03208
03209 if (!in.good()) {
03210 if (in.eof()) {
03211 assert(lookForCloser);
03212 in.setstate(std::ios::failbit);
03213 }
03214 return in;
03215 }
03216
03217
03218
03219
03220
03221
03222 bool commaOK = true, commaRequired = false;
03223 bool terminatorSeen = false;
03224 X nextIndex(0);
03225 while (true) {
03226 char c;
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237 assert(in.good());
03238
03239
03240 if (lookForCloser) {
03241
03242 std::ws(in); if (!in.good()) break;
03243 ch = in.peek(); assert(ch != EOFch);
03244 if (!in.good()) break;
03245 c = (char)ch;
03246 if (c == closeBracket) {
03247 in.get();
03248 terminatorSeen = true;
03249 break;
03250 }
03251
03252 }
03253
03254
03255
03256
03257
03258 if (isFixedSize && (nextIndex == numRequired))
03259 break;
03260
03261
03262 if (commaOK && nextIndex != 0) {
03263
03264 std::ws(in); if (!in.good()) break;
03265 ch = in.peek(); assert(ch != EOFch);
03266 if (!in.good()) break;
03267 c = (char)ch;
03268 if (c == ',') {
03269 in.get();
03270 commaRequired = true;
03271 } else {
03272 if (commaRequired)
03273 { in.setstate(std::ios::failbit); break; }
03274 else commaOK = false;
03275 }
03276 if (!in.good()) break;
03277 }
03278
03279
03280
03281 assert(in.good());
03282
03283
03284
03285 if (!isFixedSize)
03286 out.push_back();
03287 in >> out[nextIndex]; if (in.fail()) break;
03288 ++nextIndex;
03289
03290 if (!in.good()) break;
03291 }
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303 if (!in.fail()) {
03304 if (lookForCloser && !terminatorSeen)
03305 in.setstate(std::ios::failbit);
03306
03307 if (isFixedSize && nextIndex != numRequired)
03308 in.setstate(std::ios::failbit);
03309 }
03310
03311 return in;
03312 }
03313
03314
03315
03316
03317
03318
03319
03320
03321
03322
03323
03324
03325
03326
03327
03328
03336
03343 template <class T, class X> inline
03344 std::ostream&
03345 operator<<(std::ostream& o,
03346 const ArrayViewConst_<T,X>& a)
03347 {
03348 o << '(';
03349 if (!a.empty()) {
03350 o << a.front();
03351 for (const T* p = a.begin()+1; p != a.end(); ++p)
03352 o << ',' << *p;
03353 }
03354 return o << ')';
03355 }
03356
03357
03387 template <class T, class X> static inline
03388 std::istream& readArrayFromStream(std::istream& in, Array_<T,X>& out)
03389 { return readArrayFromStreamHelper<T,X>(in, false , out); }
03390
03391
03392
03417 template <class T, class X> static inline
03418 std::istream& fillArrayFromStream(std::istream& in, Array_<T,X>& out)
03419 { return readArrayFromStreamHelper<T,X>(in, true , out); }
03420
03425 template <class T, class X> static inline
03426 std::istream& fillArrayViewFromStream(std::istream& in, ArrayView_<T,X>& out)
03427 { return readArrayFromStreamHelper<T,X>(in, true , out); }
03428
03429
03430
03431
03441 template <class T, class X> inline
03442 std::istream& operator>>(std::istream& in, Array_<T,X>& out)
03443 { return readArrayFromStream<T,X>(in, out); }
03444
03452 template <class T, class X> inline
03453 std::istream& operator>>(std::istream& in, ArrayView_<T,X>& out)
03454 { return fillArrayViewFromStream<T,X>(in, out); }
03455
03465
03468 template <class T1, class X1, class T2, class X2> inline bool
03469 operator==(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2) {
03470
03471 const ptrdiff_t sz1 = a1.end()-a1.begin();
03472 const ptrdiff_t sz2 = a2.end()-a2.begin();
03473 if (sz1 != sz2) return false;
03474 const T1* p1 = a1.begin();
03475 const T2* p2 = a2.begin();
03476 while (p1 != a1.end())
03477 if (!(*p1++ == *p2++)) return false;
03478 return true;
03479 }
03482 template <class T1, class X1, class T2, class X2> inline bool
03483 operator!=(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2)
03484 { return !(a1 == a2); }
03485
03490 template <class T1, class X1, class T2, class X2> inline bool
03491 operator<(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2) {
03492 const T1* p1 = a1.begin();
03493 const T2* p2 = a2.begin();
03494 while (p1 != a1.end() && p2 != a2.end()) {
03495 if (!(*p1 == *p2))
03496 return *p1 < *p2; // otherwise p1 > p2
03497 ++p1; ++p2;
03498 }
03499
03500
03501 return p1 == a1.end() && p2 != a2.end();
03502 }
03505 template <class T1, class X1, class T2, class X2> inline bool
03506 operator>=(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2)
03507 { return !(a1 < a2); }
03511 template <class T1, class X1, class T2, class X2> inline bool
03512 operator>(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2)
03513 { return a2 < a1; }
03516 template <class T1, class X1, class T2, class X2> inline bool
03517 operator<=(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2)
03518 { return !(a1 > a2); }
03519
03523 template <class T1, class X1, class T2, class A2> inline bool
03524 operator==(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
03525 { return a1 == ArrayViewConst_<T2,size_t>(v2); }
03526
03530 template <class T1, class A1, class T2, class X2> inline bool
03531 operator==(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
03532 { return a2 == v1; }
03533
03536 template <class T1, class X1, class T2, class A2> inline bool
03537 operator!=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
03538 { return !(a1 == v2); }
03541 template <class T1, class A1, class T2, class X2> inline bool
03542 operator!=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
03543 { return !(a2 == v1); }
03544
03550 template <class T1, class X1, class T2, class A2> inline bool
03551 operator<(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
03552 { return a1 < ArrayViewConst_<T2,size_t>(v2); }
03553
03559 template <class T1, class A1, class T2, class X2> inline bool
03560 operator<(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
03561 { return ArrayViewConst_<T1,size_t>(v1) < a2; }
03562
03565 template <class T1, class X1, class T2, class A2> inline bool
03566 operator>=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
03567 { return !(a1 < v2); }
03570 template <class T1, class A1, class T2, class X2> inline bool
03571 operator>=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
03572 { return !(v1 < a2); }
03573
03577 template <class T1, class X1, class T2, class A2> inline bool
03578 operator>(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
03579 { return v2 < a1; }
03583 template <class T1, class A1, class T2, class X2> inline bool
03584 operator>(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
03585 { return a2 < v1; }
03586
03589 template <class T1, class X1, class T2, class A2> inline bool
03590 operator<=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
03591 { return !(a1 > v2); }
03594 template <class T1, class A1, class T2, class X2> inline bool
03595 operator<=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
03596 { return !(v1 > a2); }
03597
03600 }
03601
03602 namespace std {
03605 template <class T, class X> inline void
03606 swap(SimTK::Array_<T,X>& a1, SimTK::Array_<T,X>& a2) {
03607 a1.swap(a2);
03608 }
03609
03610 }
03611
03612 #endif // SimTK_SimTKCOMMON_ARRAY_H_