Simbody  3.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Array.h
Go to the documentation of this file.
1 #ifndef SimTK_SimTKCOMMON_ARRAY_H_
2 #define SimTK_SimTKCOMMON_ARRAY_H_
3 
4 /* -------------------------------------------------------------------------- *
5  * Simbody(tm): SimTKcommon *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from *
8  * Simbios, the NIH National Center for Physics-Based Simulation of *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11  * *
12  * Portions copyright (c) 2010-13 Stanford University and the Authors. *
13  * Authors: Michael Sherman *
14  * Contributors: *
15  * *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17  * not use this file except in compliance with the License. You may obtain a *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19  * *
20  * Unless required by applicable law or agreed to in writing, software *
21  * distributed under the License is distributed on an "AS IS" BASIS, *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23  * See the License for the specific language governing permissions and *
24  * limitations under the License. *
25  * -------------------------------------------------------------------------- */
26 
36 
37 #include <algorithm>
38 #include <iterator>
39 #include <vector>
40 #include <ostream>
41 #include <climits>
42 #include <typeinfo>
43 
44 namespace SimTK {
45 
46 // These are the classes defined in this header.
47 template <class X> struct ArrayIndexTraits;
48 template <class T, class X=unsigned> class ArrayViewConst_;
49 template <class T, class X=unsigned> class ArrayView_;
50 template <class T, class X=unsigned> class Array_;
51 
52 
53 
54 //==============================================================================
55 // CLASS ArrayIndexTraits
56 //==============================================================================
57 
100 template <class X> struct ArrayIndexTraits {
103  typedef typename X::size_type size_type;
106  typedef typename X::difference_type difference_type;
109  static size_type max_size() {return X::max_size();}
110 };
111 
114 template <> struct ArrayIndexTraits<unsigned> {
115  typedef unsigned size_type;
116  typedef int difference_type;
117  static size_type max_size() {return (unsigned)INT_MAX;}
118 };
119 
121 template <> struct ArrayIndexTraits<int> {
122  typedef int size_type;
123  typedef int difference_type;
124  static size_type max_size() {return INT_MAX;}
125 };
126 
134 template <> struct ArrayIndexTraits<unsigned long> {
135  typedef unsigned long size_type;
136  typedef long difference_type;
137  static size_type max_size() {return (unsigned long)LONG_MAX;}
138 };
139 
147 template <> struct ArrayIndexTraits<long> {
148  typedef long size_type;
149  typedef long difference_type;
150  static size_type max_size() {return LONG_MAX;}
151 };
152 
158 template <> struct ArrayIndexTraits<unsigned short> {
159  typedef unsigned short size_type;
160  typedef int difference_type;
161  static size_type max_size() {return USHRT_MAX;}
162 };
163 
168 template <> struct ArrayIndexTraits<short> {
169  typedef short size_type;
170  typedef short difference_type;
171  static size_type max_size() {return SHRT_MAX;}
172 };
173 
174 
179 template <> struct ArrayIndexTraits<unsigned char> {
180  typedef unsigned char size_type;
181  typedef short difference_type;
182  static size_type max_size() {return UCHAR_MAX;} // not CHAR_MAX
183 };
184 
190 template <> struct ArrayIndexTraits<signed char> {
191  typedef signed char size_type;
192  typedef signed char difference_type;
193  static size_type max_size() {return SCHAR_MAX;}
194 };
195 
202 template <> struct ArrayIndexTraits<char> {
203  typedef char size_type;
204  typedef signed char difference_type;
205  static size_type max_size() {return (char)SCHAR_MAX;}
206 };
207 
213 template <> struct ArrayIndexTraits<bool> {
214  typedef unsigned char size_type;
215  typedef signed char difference_type;
216  static size_type max_size() {return 2;}
217 };
218 
221 template <> struct ArrayIndexTraits<unsigned long long> {
222  typedef unsigned long long size_type;
223  typedef long long difference_type;
224  static size_type max_size()
225  {return (unsigned long long)LLONG_MAX;}
226 };
227 
230 template <> struct ArrayIndexTraits<long long> {
231  typedef long long size_type;
232  typedef long long difference_type;
233  static size_type max_size() {return LLONG_MAX;}
234 };
235 
236 // Don't show this in Doxygen.
238 // This helper class decides what integral type we should use to best pack
239 // the index type's size_type representation. The idea is to pack the whole
240 // Array_ structure into 8 bytes on a 32 bit machine, 16 bytes on a 64 bit
241 // machine, using the largest integral type that will work, giving a layout
242 // like this: | data pointer |
243 // | nUsed | nAllocated |
244 
245 // The default implementation just uses the integral type itself.
246 template <class Integral, class is64Bit> struct ArrayIndexPackTypeHelper
247 { typedef Integral packed_size_type;};
248 
249 // On 32 bit machine, pack anything smaller than a short into a short.
250 template<> struct ArrayIndexPackTypeHelper<bool,FalseType>
251 { typedef unsigned short packed_size_type;};
252 template<> struct ArrayIndexPackTypeHelper<char,FalseType>
253 { typedef unsigned short packed_size_type;};
254 template<> struct ArrayIndexPackTypeHelper<unsigned char,FalseType>
255 { typedef unsigned short packed_size_type;};
256 template<> struct ArrayIndexPackTypeHelper<signed char,FalseType>
257 { typedef short packed_size_type;};
258 
259 // On 64 bit machine, pack anything smaller than an int into an int.
260 template<> struct ArrayIndexPackTypeHelper<bool,TrueType>
261 { typedef unsigned int packed_size_type;};
262 template<> struct ArrayIndexPackTypeHelper<char,TrueType>
263 { typedef unsigned int packed_size_type;};
264 template<> struct ArrayIndexPackTypeHelper<unsigned char,TrueType>
265 { typedef unsigned int packed_size_type;};
266 template<> struct ArrayIndexPackTypeHelper<signed char,TrueType>
267 { typedef int packed_size_type;};
268 template<> struct ArrayIndexPackTypeHelper<unsigned short,TrueType>
269 { typedef unsigned int packed_size_type;};
270 template<> struct ArrayIndexPackTypeHelper<short,TrueType>
271 { typedef int packed_size_type;};
272 
273 template <class Integral> struct ArrayIndexPackType
274 { typedef typename ArrayIndexPackTypeHelper<Integral,Is64BitPlatformType>
275  ::packed_size_type packed_size_type;};
283 //==============================================================================
284 // CLASS ArrayViewConst_
285 //==============================================================================
312 template <class T, class X> class ArrayViewConst_ {
313 public:
314 
315 
316 //------------------------------------------------------------------------------
323 typedef T value_type;
325 typedef X index_type;
327 typedef T* pointer;
329 typedef const T* const_pointer;
331 typedef T& reference;
333 typedef const T& const_reference;
335 typedef T* iterator;
337 typedef const T* const_iterator;
339 typedef std::reverse_iterator<iterator> reverse_iterator;
341 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
348 typedef typename ArrayIndexPackType<size_type>::packed_size_type
353 //------------------------------------------------------------------------------
359 
361 ArrayViewConst_() : pData(0), nUsed(0), nAllocated(0) {}
362 
373 : pData(0), nUsed(src.nUsed), nAllocated(0) {
374  if (nUsed) pData = const_cast<T*>(src.pData);
375 }
376 
377 // Copy assignment is suppressed.
378 
401 ArrayViewConst_(const T* first, const T* last1)
402 : pData(0),nUsed(0),nAllocated(0) {
403  if (last1==first) return; // empty
404 
405  SimTK_ERRCHK((first&&last1)||(first==last1),
406  "ArrayViewConst_<T>(first,last1)",
407  "One of the source pointers was null (0); either both must be"
408  " non-null or both must be null.");
409 
410  SimTK_ERRCHK3(this->isSizeOK(last1-first),
411  "ArrayViewConst_<T>(first,last1)",
412  "The source data's size %llu is too big for this array which"
413  " is limited to %llu elements by its index type %s.",
414  this->ull(last1-first), ullMaxSize(), indexName());
415 
416  pData = const_cast<T*>(first);
417  nUsed = packed_size_type(last1-first);
418  // nAllocated is already zero
419 }
420 
448 template <class A>
449 ArrayViewConst_(const std::vector<T,A>& src)
450 : pData(0),nUsed(0),nAllocated(0) {
451  if (src.empty()) return;
452 
453  SimTK_ERRCHK3(this->isSizeOK(src.size()),
454  "ArrayViewConst_<T>::ctor(std::vector<T>)",
455  "The source std::vector's size %llu is too big for this array which"
456  " is limited to %llu elements by its index type %s.",
457  this->ull(src.size()), ullMaxSize(), indexName());
458 
459  pData = const_cast<T*>(&src.front());
460  nUsed = packed_size_type(src.size());
461  // nAllocated is already zero
462 }
465 operator const ArrayView_<T,X>&() const
466 { return *reinterpret_cast<const ArrayView_<T,X>*>(this); }
469 operator const Array_<T,X>&() const
470 { return *reinterpret_cast<const Array_<T,X>*>(this); }
471 
477 void disconnect() {
478  SimTK_ASSERT(nAllocated==0,
479  "ArrayViewConst_::deallocate(): called on an owner Array_");
480  nUsed = 0;
481  pData = 0;
482 }
483 
487  disconnect();
488 }
492 //------------------------------------------------------------------------------
499 
501 size_type size() const {return size_type(nUsed);}
506 bool empty() const {return nUsed==0;}
511 size_type capacity() const {return size_type(nAllocated?nAllocated:nUsed);}
515 size_type allocated() const {return size_type(nAllocated);}
521 bool isOwner() const {return nAllocated || pData==0;}
522 /*}*/
523 
524 
525 //------------------------------------------------------------------------------
532 
539 const T& operator[](index_type i) const {
540  SimTK_INDEXCHECK(size_type(i),size(),"ArrayViewConst_<T>::operator[]()");
541  return pData[i];
542 }
547 const T& at(index_type i) const {
548  SimTK_INDEXCHECK_ALWAYS(size_type(i),size(),"ArrayViewConst_<T>::at()");
549  return pData[i];
550 }
553 const T& getElt(index_type i) const {
554  SimTK_INDEXCHECK(size_type(i),size(),"ArrayViewConst_<T>::getElt()");
555  return pData[i];
556 }
562 const T& front() const
563 { SimTK_ERRCHK(!empty(), "ArrayViewConst_<T>::front()", "Array was empty.");
564  return pData[0]; }
570 const T& back() const
571 { SimTK_ERRCHK(!empty(), "ArrayViewConst_<T>::back()", "Array was empty.");
572  return pData[nUsed-1]; }
573 
593  const size_type ix(index);
594  SimTK_ERRCHK2(isSizeInRange(ix, size()), "ArrayViewConst_<T>(index,length)",
595  "For this operator, we must have 0 <= index <= size(), but"
596  " index==%llu and size==%llu.", this->ull(ix), ullSize());
597  SimTK_ERRCHK2(isSizeInRange(length, size_type(size()-ix)),
598  "ArrayViewConst_<T>(index,length)",
599  "This operator requires 0 <= length <= size()-index, but"
600  " length==%llu and size()-index==%llu.",this->ull(length),this->ull(size()-ix));
601 
602  return ArrayViewConst_(pData+ix, pData+ix+length);
603 }
607 { return (*this)(index,length); }
608 
612 //------------------------------------------------------------------------------
621 
626 const T* cbegin() const {return pData;}
631 const T* cend() const {return pData + nUsed;}
633 const T* begin() const {return pData;}
635 const T* end() const {return pData + nUsed;}
636 
647 const_reverse_iterator rend() const {return crend();}
648 
655 const T* cdata() const {return pData;}
657 const T* data() const {return pData;}
661 //------------------------------------------------------------------------------
662  protected:
663 //------------------------------------------------------------------------------
664 // The remainder of this class is for the use of the ArrayView_<T,X> and
665 // Array_<T,X> derived classes only and should not be documented for users to
666 // see.
667 
668 // Don't let doxygen see any of this.
670 packed_size_type psize() const {return nUsed;}
671 packed_size_type pallocated() const {return nAllocated;}
672 
673 // These provide direct access to the data members for our trusted friends.
674 void setData(const T* p) {pData = const_cast<T*>(p);}
675 void setSize(size_type n) {nUsed = packed_size_type(n);}
676 void incrSize() {++nUsed;}
677 void decrSize() {--nUsed;}
678 void setAllocated(size_type n) {nAllocated = packed_size_type(n);}
679 
680 // Check whether a given size is the same as the current size of this array,
681 // avoiding any compiler warnings due to mismatched integral types.
682 template <class S>
683 bool isSameSize(S sz) const
684 { return ull(sz) == ullSize(); }
685 
686 // Check that a source object's size will fit in the array being careful to
687 // avoid overflow and warnings in the comparison.
688 template <class S>
689 bool isSizeOK(S srcSz) const
690 { return ull(srcSz) <= ullMaxSize(); }
691 
692 // This is identical in function to std::distance() (reports how many
693 // elements lie between two iterators) but avoids any slow
694 // Release-build bugcatchers that Microsoft may have felt compelled to add.
695 // The implementation is specialized for random access iterators because
696 // they can measure distance very fast.
697 template<class Iter> static
698 typename std::iterator_traits<Iter>::difference_type
699 iterDistance(const Iter& first, const Iter& last1) {
700  return iterDistanceImpl(first,last1,
701  typename std::iterator_traits<Iter>::iterator_category());
702 }
703 
704 // Generic slow implementation for non-random access iterators. This is fine
705 // for forward and bidirectional iterators, but it will *consume* input
706 // iterators so is useless for them.
707 template<class Iter> static
708 typename std::iterator_traits<Iter>::difference_type
709 iterDistanceImpl(const Iter& first, const Iter& last1, std::input_iterator_tag) {
710  typename std::iterator_traits<Iter>::difference_type d = 0;
711  for (Iter src=first; src != last1; ++src, ++d)
712  ;
713  return d;
714 }
715 
716 // Fast specialization for random access iterators (including ordinary
717 // pointers) -- just subtract.
718 template<class Iter> static
719 typename std::iterator_traits<Iter>::difference_type
720 iterDistanceImpl(const Iter& first, const Iter& last1,
721  std::random_access_iterator_tag) {
722  return last1 - first;
723 }
724 
725 // This method attempts to determine whether any elements in the iterator range
726 // [first,last1) overlap with the elements stored in this array. This is used
727 // for error checks for operations where source is not permitted to overlap the
728 // destination. For random access iterators (including ordinary pointers), we
729 // can answer this question definitively because we expect the data to be
730 // consecutive in memory. For other kinds of iterators, we will just assume
731 // there is no overlap. Note that null ranges do not overlap even if the
732 // pair of equal iterators points within the other range -- what matters is
733 // the number of overlapping elements.
734 template<class Iter> bool
735 overlapsWithData(const Iter& first, const Iter& last1) {
736  return overlapsWithDataImpl(first,last1,
737  typename std::iterator_traits<Iter>::iterator_category());
738 }
739 
740 // This is a partial specialization of the above where the data is given
741 // with ordinary pointers.
742 template <class T2> bool
743 overlapsWithData(const T2* first, const T2* last1) {
744  // Find the start and end+1 of the alleged overlap region. There is
745  // overlap iff end+1 > start. Note that this works if either range
746  // is [0,0) or [p,p), or if last1 is illegally less than first (we just
747  // want to report no overlap in that case -- it is someone else's business
748  // to complain).
749  const T* obegin = std::max(cbegin(), (const T*)first);
750  const T* oend1 = std::min(cend(), (const T*)last1);
751 
752  return obegin < oend1;
753 }
754 
755 // This is the generic implementation for any type of input iterator other than
756 // random access (i.e., bidirectional, forward, or input) -- assume no overlap.
757 template<class Iter> bool
758 overlapsWithDataImpl(const Iter&, const Iter&, std::input_iterator_tag)
759 { return false; }
760 
761 // Here we can actually test for overlap since we have random access iterators.
762 // We convert them to pointers and then look for memory overlap.
763 template<class Iter> bool
764 overlapsWithDataImpl(const Iter& first, const Iter& last1,
765  std::random_access_iterator_tag) {
766  // We must check that the input iterators span a non-zero range before
767  // assuming we can dereference them.
768  if (last1 <= first)
769  return false; // zero or malformed source range: no overlap
770 
771  // We now know we can dereference first and last1-1 (can't safely
772  // dereference last1 but we can use pointer arithmetic to point past
773  // the (last-1)th element in memory). We then take the dereferenced
774  // object's address to get ordinary pointers that we can use to
775  // watch for illegal overlap.
776  return overlapsWithData(&*first, &*(last1-1)); // use pointer overload
777 }
778 
779 // Cast an integral type to maximal-width unsigned long long to avoid accidental
780 // overflows that might otherwise occur due to wraparound that can happen
781 // with small index types.
782 template <class S>
783 static unsigned long long ull(S sz)
784 { return (unsigned long long)sz; }
785 
786 // Return size(), capacity(), and max_size() cast to unsigned long long.
787 unsigned long long ullSize() const {return ull(size());}
788 unsigned long long ullCapacity() const {return ull(capacity());}
789 unsigned long long ullMaxSize() const {return ull(max_size());}
790 
791 // Useful in error messages for explaining why something was too big.
792 const char* indexName() const {return NiceTypeName<X>::name();}
793 
796 private:
797 //------------------------------------------------------------------------------
798 // DATA MEMBERS
799 // These are the only data members and this layout is guaranteed not to change
800 // from release to release. If data is null, then nUsed==nAllocated==0.
801 
802 T* pData; // ptr to data referenced here, or 0 if none
803 packed_size_type nUsed; // number of elements currently present (size)
804 packed_size_type nAllocated; // heap allocation; 0 if pData is not owned
805 
806 ArrayViewConst_& operator=(const ArrayViewConst_& src); // suppressed
807 };
808 
809 
810 
811 
812 
813 
814 //==============================================================================
815 // CLASS ArrayView_
816 //==============================================================================
828 template <class T, class X> class ArrayView_ : public ArrayViewConst_<T,X> {
829 typedef ArrayViewConst_<T,X> CBase;
830 public:
831 //------------------------------------------------------------------------------
836 /*{*/
837 typedef T value_type;
838 typedef X index_type;
839 typedef T* pointer;
840 typedef const T* const_pointer;
841 typedef T& reference;
842 typedef const T& const_reference;
843 typedef T* iterator;
844 typedef const T* const_iterator;
845 typedef std::reverse_iterator<iterator> reverse_iterator;
846 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
849 typedef typename ArrayIndexPackType<size_type>::packed_size_type
851 /*}*/
852 
853 
854 //------------------------------------------------------------------------------
860 
863 
865 ArrayView_(const ArrayView_& src) : CBase(src) {}
866 
868 ArrayView_(T* first, const T* last1) : CBase(first,last1) {}
869 
871 template <class A>
872 ArrayView_(std::vector<T,A>& v) : CBase(v) {}
873 
875 operator const Array_<T,X>&() const
876 { return *reinterpret_cast<const Array_<T,X>*>(this); }
877 
879 operator Array_<T,X>&()
880 { return *reinterpret_cast<Array_<T,X>*>(this); }
881 
884 void disconnect() {this->CBase::disconnect();}
885 
892 //------------------------------------------------------------------------------
904 
907  if (&src != this)
908  avAssignIteratorDispatch(src.cbegin(), src.cend(),
909  std::random_access_iterator_tag(),
910  "ArrayView_<T>::operator=(ArrayView_<T>)");
911  return *this;
912 }
913 
914 
917 template <class T2, class X2>
919  if ((const void*)&src != (void*)this)
920  avAssignIteratorDispatch(src.cbegin(), src.cend(),
921  std::random_access_iterator_tag(),
922  "ArrayView_<T>::operator=(Array_<T2>)");
923  return *this;
924 }
925 
926 // Help out dumb compilers struggling to match the template arguments and
927 // promote the Array_ or ArrayView_ to ArrayConstView_ at the same time.
928 
931 template <class T2, class X2>
933 { return *this = static_cast<const ArrayViewConst_<T2,X2>&>(src); }
936 template <class T2, class X2>
938 { return *this = static_cast<const ArrayViewConst_<T2,X2>&>(src); }
939 
942 template <class T2, class A2>
943 ArrayView_& operator=(const std::vector<T2,A2>& src) {
944  avAssignIteratorDispatch(src.begin(), src.end(),
945  std::random_access_iterator_tag(),
946  "ArrayView_<T>::operator=(std::vector<T2>)");
947  return *this;
948 }
949 
951 ArrayView_& operator=(const T& fillValue)
952 { fill(fillValue); return *this; }
953 
959 ArrayView_& fill(const T& fillValue) {
960  for (T* d = begin(); d != end(); ++d)
961  *d = fillValue; // using T::operator=(T)
962  return *this;
963 }
964 
968 void assign(size_type n, const T& fillValue) {
969  SimTK_ERRCHK2(n == size(), "ArrayView_<T>::assign(n,value)",
970  "Assignment to an ArrayView is permitted only if the source"
971  " is the same size. Here n==%llu element(s) but the"
972  " ArrayView has a fixed size of %llu.",
973  this->ull(n), this->ull(size()));
974 
975  fill(fillValue);
976 }
977 
995 template <class T2>
996 void assign(const T2* first, const T2* last1) {
997  const char* methodName = "ArrayView_<T>::assign(T2* first, T2* last1)";
998  SimTK_ERRCHK((first&&last1)||(first==last1), methodName,
999  "One of the source pointers was null (0); either both must be"
1000  " non-null or both must be null.");
1001  // Valid pointers are random access iterators.
1002  avAssignIteratorDispatch(first, last1, std::random_access_iterator_tag(),
1003  methodName);
1004 }
1005 
1035 // Watch out for integral types matching this signature -- they must be
1036 // forwarded to the assign(n, fillValue) signature instead.
1037 template <class Iter>
1038 void assign(const Iter& first, const Iter& last1)
1039 { avAssignDispatch(first,last1,typename IsIntegralType<Iter>::Result(),
1040  "ArrayView_<T>::assign(Iter first, Iter last1)"); }
1044 //------------------------------------------------------------------------------
1051 
1058 const T& operator[](index_type i) const {return this->CBase::operator[](i);}
1059 
1067 T& operator[](index_type i) {return const_cast<T&>(this->CBase::operator[](i));}
1068 
1073 const T& at(index_type i) const {return this->CBase::at(i);}
1074 
1079 T& at(index_type i) {return const_cast<T&>(this->CBase::at(i));}
1080 
1083 const T& getElt(index_type i) const {return this->CBase::getElt(i);}
1086 T& updElt(index_type i) {return const_cast<T&>(this->CBase::getElt(i));}
1087 
1093 const T& front() const {return this->CBase::front();}
1094 
1100 T& front() {return const_cast<T&>(this->CBase::front());}
1101 
1107 const T& back() const {return this->CBase::back();}
1108 
1114 T& back() {return const_cast<T&>(this->CBase::back());}
1115 
1135  const size_type ix(index);
1136  SimTK_ERRCHK2(isSizeInRange(ix, size()), "ArrayView_<T>(index,length)",
1137  "For this operator, we must have 0 <= index <= size(), but"
1138  " index==%llu and size==%llu.", this->ull(ix), ullSize());
1139  SimTK_ERRCHK2(isSizeInRange(length, size_type(size()-ix)),
1140  "ArrayView_<T>(index,length)",
1141  "This operator requires 0 <= length <= size()-index, but"
1142  " length==%llu and size()-index==%llu.",this->ull(length),this->ull(size()-ix));
1143 
1144  return ArrayView_(data()+ix, data()+ix+length);
1145 }
1149 { return (*this)(index,length); }
1153 //------------------------------------------------------------------------------
1162 
1167 const T* cbegin() const {return this->CBase::cbegin();}
1169 const T* begin() const {return this->CBase::cbegin();}
1174 T* begin() {return const_cast<T*>(this->CBase::cbegin());}
1175 
1180 const T* cend() const {return this->CBase::cend();}
1182 const T* end() const {return this->CBase::cend();}
1187 T* end() {return const_cast<T*>(this->CBase::cend());}
1188 
1197 
1201 const_reverse_iterator crend() const {return this->CBase::crend();}
1203 const_reverse_iterator rend() const {return this->CBase::crend();}
1208 
1215 const T* cdata() const {return this->CBase::cdata();}
1218 const T* data() const {return this->CBase::cdata();}
1222 T* data() {return const_cast<T*>(this->CBase::cdata());}
1226 //------------------------------------------------------------------------------
1232 
1233 // Note: these have to be explicitly forwarded to the base class methods
1234 // in order to keep gcc from complaining. Note that the "this->" is
1235 // apparently necessary in order to permit delayed definition of templatized
1236 // methods. Doxygen picks up the comments from the base class.
1237 
1238 size_type size() const {return this->CBase::size();}
1239 size_type max_size() const {return this->CBase::max_size();}
1240 bool empty() const {return this->CBase::empty();}
1241 size_type capacity() const {return this->CBase::capacity();}
1242 size_type allocated() const {return this->CBase::allocated();}
1243 bool isOwner() const {return this->CBase::isOwner();}
1247 //------------------------------------------------------------------------------
1248  private:
1249 //------------------------------------------------------------------------------
1250 // no data members are allowed
1251 
1252 //------------------------------------------------------------------------------
1253 // ARRAY VIEW ASSIGN DISPATCH
1254 // This is the assign() implementation for ArrayView_ when the class that
1255 // matched the alleged InputIterator template argument turned out to be one of
1256 // the integral types in which case this should match the assign(n, fillValue)
1257 // signature.
1258 template <class IntegralType>
1259 void avAssignDispatch(IntegralType n, IntegralType v, TrueType isIntegralType,
1260  const char*)
1261 { assign(size_type(n), value_type(v)); }
1262 
1263 // This is the assign() implementation for ArrayView_ when the class that
1264 // matched the alleged InputIterator template argument is NOT an integral type
1265 // and may very well be an iterator.
1266 template <class InputIterator>
1267 void avAssignDispatch(const InputIterator& first, const InputIterator& last1,
1268  FalseType isIntegralType, const char* methodName)
1269 { avAssignIteratorDispatch(first, last1,
1270  typename std::iterator_traits<InputIterator>::iterator_category(),
1271  methodName); }
1272 
1273 // This is the assign() implementation for a plain input_iterator
1274 // (i.e., not a forward, bidirectional, or random access iterator). These
1275 // have the unfortunate property that we can't count the elements in advance.
1276 // Here we're going to complain if there aren't enough; but will simply stop
1277 // when we get size() elements and not insist that the input stream reached
1278 // the supplied last1 iterator. Semantics is elementwise assignment.
1279 template <class InputIterator>
1280 void avAssignIteratorDispatch(const InputIterator& first,
1281  const InputIterator& last1,
1282  std::input_iterator_tag,
1283  const char* methodName)
1284 {
1285  T* p = begin();
1286  InputIterator src = first;
1287  while (src != last1 && p != end())
1288  *p++ = *src++; // call T's assignment operator
1289 
1290  // p now points just after the last element that was copied.
1291  const size_type nCopied = size_type(p - begin());
1292  SimTK_ERRCHK2_ALWAYS(nCopied == size(), methodName,
1293  "The supplied input_iterator provided only %llu elements but this"
1294  " ArrayView has a fixed size of %llu elements.",
1295  this->ull(nCopied), ullSize());
1296 
1297  // We don't care if there are still more input elements available.
1298 }
1299 
1300 // This is the assign() implementation that works for forward and bidirectional
1301 // iterators, but is not used for random_access_iterators. Here we'll count
1302 // the elements as we copy them and complain at the end if there were too
1303 // few or too many.
1304 template <class ForwardIterator>
1305 void avAssignIteratorDispatch(const ForwardIterator& first,
1306  const ForwardIterator& last1,
1307  std::forward_iterator_tag,
1308  const char* methodName)
1309 {
1310  T* p = begin();
1311  ForwardIterator src = first;
1312  while (src != last1 && p != end())
1313  *p++ = *src++; // call T's assignment operator
1314 
1315  // p now points just after the last element that was copied.
1316  const size_type nCopied = size_type(p - begin());
1317  SimTK_ERRCHK2_ALWAYS(nCopied == size(), methodName,
1318  "The supplied forward_ or bidirectional_iterator source range provided"
1319  " only %llu elements but this ArrayView has a fixed size of"
1320  " %llu elements.", this->ull(nCopied), ullSize());
1321 
1322  // Make sure we ran out of source elements.
1323  SimTK_ERRCHK1_ALWAYS(src == last1, methodName,
1324  "The supplied forward_ or bidirectional_iterator source range"
1325  " contained too many elements; this ArrayView has a fixed size of"
1326  " %llu elements.", ullSize());
1327 }
1328 
1329 // This is the assign() implementation that works for random_access_iterators
1330 // including ordinary pointers. Here we check the number of elements in advance
1331 // and complain if the source and destination aren't the same size. The
1332 // copying loop can be done faster in this case.
1333 template <class RandomAccessIterator>
1334 void avAssignIteratorDispatch(const RandomAccessIterator& first,
1335  const RandomAccessIterator& last1,
1336  std::random_access_iterator_tag,
1337  const char* methodName)
1338 {
1339  SimTK_ERRCHK2_ALWAYS(this->isSameSize(last1-first), methodName,
1340  "Assignment to an ArrayView is permitted only if the source"
1341  " is the same size. Here the source had %llu element(s) but the"
1342  " ArrayView has a fixed size of %llu.",
1343  this->ull(last1-first), this->ull(size()));
1344 
1345  SimTK_ERRCHK_ALWAYS(!this->overlapsWithData(first,last1), methodName,
1346  "Source range can't overlap with the destination data.");
1347 
1348  T* p = begin();
1349  RandomAccessIterator src = first;
1350  while (p != end())
1351  *p++ = *src++; // call T's assignment operator
1352 }
1353 
1354 
1355 //------------------------------------------------------------------------------
1356 // The following private methods are protected methods in the ArrayViewConst_
1357 // base class, so they should not need repeating here. However, we explicitly
1358 // forward to the base methods to avoid gcc errors. The gcc complaint
1359 // is due to their not depending on any template parameters; the "this->"
1360 // apparently fixes that problem.
1361 
1362 packed_size_type psize() const {return this->CBase::psize();}
1363 packed_size_type pallocated() const {return this->CBase::pallocated();}
1364 
1365 // This just cast sizes to unsigned long long so that we can do comparisons
1366 // without getting warnings.
1367 unsigned long long ullSize() const {return this->CBase::ullSize();}
1368 unsigned long long ullCapacity() const {return this->CBase::ullCapacity();}
1369 unsigned long long ullMaxSize() const {return this->CBase::ullMaxSize();}
1370 // This is the index type name and is handy for error messages to explain
1371 // why some size was too big.
1372 const char* indexName() const {return this->CBase::indexName();}
1373 };
1374 
1375 
1376 
1377 
1378 
1379 //==============================================================================
1380 // CLASS Array_
1381 //==============================================================================
1484 template <class T, class X> class Array_ : public ArrayView_<T,X> {
1485  typedef ArrayView_<T,X> Base;
1486  typedef ArrayViewConst_<T,X> CBase;
1487 public:
1488 
1489 
1490 //------------------------------------------------------------------------------
1496 // Doxygen picks up individual descriptions from the base class.
1497 /*{*/
1498 typedef T value_type;
1499 typedef X index_type;
1500 typedef T* pointer;
1501 typedef const T* const_pointer;
1502 typedef T& reference;
1503 typedef const T& const_reference;
1504 typedef T* iterator;
1505 typedef const T* const_iterator;
1506 typedef std::reverse_iterator<iterator> reverse_iterator;
1507 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
1510 typedef typename ArrayIndexPackType<size_type>::packed_size_type
1512 /*}*/
1513 
1514 //------------------------------------------------------------------------------
1521 /*{*/
1522 
1524 Array_() : Base() {}
1525 
1530 explicit Array_(size_type n) : Base() {
1531  SimTK_SIZECHECK(n, max_size(), "Array_<T>::ctor(n)");
1532  allocateNoConstruct(n);
1533  defaultConstruct(data(), data()+n);
1534  setSize(n);
1535 }
1536 
1540 Array_(size_type n, const T& initVal) : Base() {
1541  SimTK_SIZECHECK(n, max_size(), "Array_<T>::ctor(n,T)");
1542  setSize(n);
1543  allocateNoConstruct(size());
1544  fillConstruct(begin(), cend(), initVal);
1545 }
1561 template <class InputIter>
1562 Array_(const InputIter& first, const InputIter& last1) : Base() {
1563  ctorDispatch(first,last1,typename IsIntegralType<InputIter>::Result());
1564 }
1565 
1571 template <class T2>
1572 Array_(const T2* first, const T2* last1) : Base() {
1573  SimTK_ERRCHK((first&&last1)||(first==last1), "Array_<T>(first,last1)",
1574  "Pointers must be non-null unless they are both null.");
1575  SimTK_ERRCHK3(this->isSizeOK(last1-first), "Array_<T>(first,last1)",
1576  "Source has %llu elements but this array is limited to %llu"
1577  " elements by its index type %s.",
1578  this->ull(last1-first), ullMaxSize(), indexName());
1579 
1580  setSize(size_type(last1-first));
1581  allocateNoConstruct(size());
1582  copyConstruct(begin(), cend(), first);
1583 }
1584 
1589 template <class T2>
1590 explicit Array_(const std::vector<T2>& v) : Base() {
1591  if (v.empty()) return;
1592 
1593  SimTK_ERRCHK3(this->isSizeOK(v.size()), "Array_<T>::ctor(std::vector<T2>)",
1594  "The source std::vector's size %llu is too big for this array which"
1595  " is limited to %llu elements by its index type %s.",
1596  this->ull(v.size()), ullMaxSize(), indexName());
1597 
1598  // Call the above constructor, making sure to use pointers into the
1599  // vector's data rather than the iterators begin() and end() in case
1600  // they are different types.
1601  new (this) Array_(&v.front(), (&v.back())+1);
1602 }
1603 
1608 Array_(const Array_& src) : Base() {
1609  setSize(src.size());
1610  allocateNoConstruct(size());
1611  copyConstruct(begin(), cend(), src.data());
1612 }
1613 
1620 template <class T2, class X2>
1621 Array_(const Array_<T2,X2>& src) : Base() {
1622  new (this) Array_(src.begin(), src.cend()); // see above
1623 }
1624 
1654 Array_(T* first, const T* last1, const DontCopy&) : Base(first,last1) {}
1655 
1683 template <class A>
1684 Array_(std::vector<T,A>& v, const DontCopy&) : Base(v) {}
1685 
1690  deallocate();
1691 }
1692 
1702  if (allocated()) { // owner with non-zero allocation
1703  clear(); // each element is destructed; size()=0; allocated() unchanged
1704  deallocateNoDestruct(); // free data(); allocated()=0
1705  }
1706  this->Base::disconnect(); // clear the handle
1707  return *this;
1708 }
1709 
1713 //------------------------------------------------------------------------------
1748 
1766 void assign(size_type n, const T& fillValue) {
1767  SimTK_ERRCHK3(this->isSizeOK(n), "Array_<T>::assign(n,value)",
1768  "Requested size %llu is too big for this array which is limited"
1769  " to %llu elements by its index type %s.",
1770  this->ull(n), ullMaxSize(), indexName());
1771 
1772  SimTK_ERRCHK2(isOwner() || n==size(), "Array_<T>::assign(n,value)",
1773  "Requested size %llu is not allowed because this is a non-owner"
1774  " array of fixed size %llu.", this->ull(n), this->ull(size()));
1775 
1776  if (!isOwner())
1777  this->Base::fill(fillValue);
1778  else {
1779  clear(); // all elements destructed; allocation unchanged
1780  reallocateIfAdvisable(n); // change size if too small or too big
1781  fillConstruct(data(), cdata()+n, fillValue);
1782  setSize(n);
1783  }
1784 }
1785 
1800 void fill(const T& fillValue) {this->Base::fill(fillValue);}
1801 
1802 
1824 template <class T2>
1825 void assign(const T2* first, const T2* last1) {
1826  const char* methodName = "Array_<T>::assign(T2* first, T2* last1)";
1827  SimTK_ERRCHK((first&&last1)||(first==last1), methodName,
1828  "Pointers must be non-null unless they are both null.");
1829  SimTK_ERRCHK(!this->overlapsWithData(first,last1), methodName,
1830  "Source range can't overlap the current array contents.");
1831  // Pointers are random access iterators.
1832  assignIteratorDispatch(first,last1,std::random_access_iterator_tag(),
1833  methodName);
1834 }
1835 
1836 
1872 template <class Iter>
1873 void assign(const Iter& first, const Iter& last1) {
1874  assignDispatch(first,last1,typename IsIntegralType<Iter>::Result(),
1875  "Array_<T>::assign(Iter first, Iter last1)");
1876 }
1877 
1883 Array_& operator=(const Array_& src) {
1884  if (this != &src)
1885  assignIteratorDispatch(src.begin(), src.end(),
1886  std::random_access_iterator_tag(),
1887  "Array_<T>::operator=(Array_<T>)");
1888  return *this;
1889 }
1890 
1896 template <class T2, class X2>
1898  assignIteratorDispatch(src.begin(), src.end(),
1899  std::random_access_iterator_tag(),
1900  "Array_<T>::operator=(Array_<T2,X2>)");
1901  return *this;
1902 }
1903 
1904 
1909 template <class T2, class A>
1910 Array_& operator=(const std::vector<T2,A>& src) {
1911  assignIteratorDispatch(src.begin(), src.end(),
1912  std::random_access_iterator_tag(),
1913  "Array_<T>::operator=(std::vector)");
1914  return *this;
1915 }
1916 
1923 void swap(Array_& other) {
1924  T* const pTmp=data(); setData(other.data()); other.setData(pTmp);
1925  size_type nTmp=size(); setSize(other.size()); other.setSize(nTmp);
1926  nTmp=allocated(); setAllocated(other.allocated()); other.setAllocated(nTmp);
1927 }
1928 
1934 Array_& adoptData(T* newData, size_type dataSize,
1935  size_type dataCapacity)
1936 {
1937  SimTK_SIZECHECK(dataCapacity, max_size(), "Array_<T>::adoptData()");
1938  SimTK_ERRCHK2(dataSize <= dataCapacity, "Array_<T>::adoptData()",
1939  "Specified data size %llu was greater than the specified data"
1940  " capacity of %llu.", this->ull(dataSize), this->ull(dataCapacity));
1941  SimTK_ERRCHK(newData || dataCapacity==0, "Array_<T>::adoptData()",
1942  "A null data pointer is allowed only if the size and capacity are"
1943  " specified as zero.");
1944  SimTK_ERRCHK(!this->overlapsWithData(newData, newData+dataSize),
1945  "Array_<T>::adoptData()",
1946  "The new data can't overlap with the old data.");
1947 
1948  deallocate();
1949  setData(newData);
1950  setSize(dataSize);
1951  setAllocated(dataCapacity);
1952  return *this;
1953 }
1956 Array_& adoptData(T* newData, size_type dataSize)
1957 { return adoptData(newData, dataSize, dataSize); }
1958 
1959 
1973 Array_& shareData(T* newData, size_type dataSize) {
1974  SimTK_SIZECHECK(dataSize, max_size(), "Array_<T>::shareData()");
1975  SimTK_ERRCHK(newData || dataSize==0, "Array_<T>::shareData()",
1976  "A null data pointer is allowed only if the size is zero.");
1977  SimTK_ERRCHK(!this->overlapsWithData(newData, newData+dataSize),
1978  "Array_<T>::shareData()",
1979  "The new data can't overlap with the old data.");
1980 
1981  deallocate();
1982  setData(newData);
1983  setSize(dataSize);
1984  setAllocated(0); // indicates shared data
1985  return *this;
1986 }
1987 
1990 Array_& shareData(T* first, const T* last1) {
1991  SimTK_ERRCHK3(this->isSizeOK(last1-first), "Array_<T>::shareData(first,last1)",
1992  "Requested size %llu is too big for this array which is limited"
1993  " to %llu elements by its index type %s.",
1994  this->ull(last1-first), ullMaxSize(), indexName());
1995  return shareData(first, size_type(last1-first));
1996 }
1997 
2001 //------------------------------------------------------------------------------
2007 
2008 // Note: these have to be explicitly forwarded to the base class methods
2009 // in order to keep gcc from complaining. Note that the "this->" is
2010 // apparently necessary in order to permit delayed definition of templatized
2011 // methods.
2012 
2014 size_type size() const {return this->CBase::size();}
2016 size_type max_size() const {return this->CBase::max_size();}
2019 bool empty() const {return this->CBase::empty();}
2024 size_type capacity() const {return this->CBase::capacity();}
2025 
2031  if (n == size()) return;
2032 
2033  SimTK_ERRCHK2(isOwner(), "Array_<T>::resize(n)",
2034  "Requested size change to %llu is not allowed because this is a"
2035  " non-owner array of fixed size %llu.", this->ull(n), this->ull(size()));
2036 
2037  if (n < size()) {
2038  erase(data()+n, cend());
2039  return;
2040  }
2041  // n > size()
2042  reserve(n);
2043  defaultConstruct(data()+size(), cdata()+n); // data() has changed
2044  setSize(n);
2045 }
2046 
2051 void resize(size_type n, const T& initVal) {
2052  if (n == size()) return;
2053 
2054  SimTK_ERRCHK2(isOwner(), "Array_<T>::resize(n,value)",
2055  "Requested size change to %llu is not allowed because this is a"
2056  " non-owner array of fixed size %llu.", this->ull(n), this->ull(size()));
2057 
2058  if (n < size()) {
2059  erase(data()+n, cend());
2060  return;
2061  }
2062  // n > size()
2063  reserve(n);
2064  fillConstruct(data()+size(), cdata()+n, initVal);
2065  setSize(n);
2066 }
2067 
2075  if (capacity() >= n)
2076  return;
2077 
2078  SimTK_ERRCHK2(isOwner(), "Array_<T>::reserve()",
2079  "Requested capacity change to %llu is not allowed because this is a"
2080  " non-owner array of fixed size %llu.", this->ull(n), this->ull(size()));
2081 
2082  T* newData = allocN(n); // no construction yet
2083  copyConstructThenDestructSource(newData, newData+size(), data());
2084  freeN(data());
2085  setData(newData);
2086  setAllocated(n);
2087 }
2088 
2110  // Allow 25% slop, but note that if size()==0 this will always reallocate
2111  // unless capacity is already zero.
2112  if (capacity() - size()/4 <= size()) // avoid overflow if size() near max
2113  return;
2114  T* newData = allocN(size());
2115  copyConstructThenDestructSource(newData, newData+size(), data());
2116  deallocateNoDestruct(); // data()=0, allocated()=0, size() unchanged
2117  setData(newData);
2118  setAllocated(size());
2119 }
2120 
2124 size_type allocated() const {return this->CBase::allocated();}
2130 bool isOwner() const {return this->CBase::isOwner();}
2134 //------------------------------------------------------------------------------
2143 
2148 const T* cbegin() const {return this->CBase::cbegin();}
2150 const T* begin() const {return this->CBase::cbegin();}
2155 T* begin() {return this->Base::begin();}
2156 
2161 const T* cend() const {return this->CBase::cend();}
2163 const T* end() const {return this->CBase::cend();}
2168 T* end() {return this->Base::end();}
2169 
2178 
2182 const_reverse_iterator crend() const {return this->CBase::crend();}
2184 const_reverse_iterator rend() const {return this->CBase::crend();}
2188 reverse_iterator rend() {return this->Base::rend();}
2189 
2196 const T* cdata() const {return this->CBase::cdata();}
2199 const T* data() const {return this->CBase::cdata();}
2203 T* data() {return this->Base::data();}
2211 
2218 const T& operator[](index_type i) const {return this->CBase::operator[](i);}
2219 
2227 T& operator[](index_type i) {return this->Base::operator[](i);}
2228 
2233 const T& at(index_type i) const {return this->CBase::at(i);}
2234 
2239 T& at(index_type i) {return const_cast<T&>(this->Base::at(i));}
2240 
2243 const T& getElt(index_type i) const {return this->CBase::getElt(i);}
2246 T& updElt(index_type i) {return this->Base::updElt(i);}
2247 
2253 const T& front() const {return this->CBase::front();}
2254 
2260 T& front() {return const_cast<T&>(this->Base::front());}
2261 
2267 const T& back() const {return this->CBase::back();}
2268 
2274 T& back() {return const_cast<T&>(this->Base::back());}
2275 
2279 { return CBase::operator()(index,length); }
2283 { return CBase::getSubArray(index,length); }
2284 
2288 { return Base::operator()(index,length); }
2292 { return Base::updSubArray(index,length); }
2296 //------------------------------------------------------------------------------
2302 
2329 void push_back(const T& value) {
2330  if (pallocated() == psize())
2331  growAtEnd(1,"Array_<T>::push_back(value)");
2332  copyConstruct(end(), value);
2333  incrSize();
2334 }
2335 
2349 void push_back() {
2350  if (pallocated() == psize())
2351  growAtEnd(1,"Array_<T>::push_back()");
2352  defaultConstruct(end());
2353  incrSize();
2354 }
2355 
2372  if (pallocated() == psize())
2373  growAtEnd(1,"Array_<T>::raw_push_back()");
2374  T* const p = end();
2375  incrSize();
2376  return p;
2377 }
2378 
2381 void pop_back() {
2382  SimTK_ERRCHK(!empty(), "Array_<T>::pop_back()", "Array was empty.");
2383  destruct(&back());
2384  decrSize();
2385 }
2386 
2404 T* erase(T* first, const T* last1) {
2405  SimTK_ERRCHK(begin() <= first && first <= last1 && last1 <= end(),
2406  "Array<T>::erase(first,last1)", "Pointers out of range or out of order.");
2407 
2408  const size_type nErased = size_type(last1-first);
2409  SimTK_ERRCHK(isOwner() || nErased==0, "Array<T>::erase(first,last1)",
2410  "No elements can be erased from a non-owner array.");
2411 
2412  if (nErased) {
2413  destruct(first, last1); // Destruct the elements we're erasing.
2414  moveElementsDown(first+nErased, nErased); // Compress followers into the gap.
2415  setSize(size()-nErased);
2416  }
2417  return first;
2418 }
2419 
2439 T* erase(T* p) {
2440  SimTK_ERRCHK(begin() <= p && p < end(),
2441  "Array<T>::erase(p)", "Pointer must point to a valid element.");
2442  SimTK_ERRCHK(isOwner(), "Array<T>::erase(p)",
2443  "No elements can be erased from a non-owner array.");
2444 
2445  destruct(p); // Destruct the element we're erasing.
2446  moveElementsDown(p+1, 1); // Compress followers into the gap.
2447  decrSize();
2448  return p;
2449 }
2450 
2451 
2472 T* eraseFast(T* p) {
2473  SimTK_ERRCHK(begin() <= p && p < end(),
2474  "Array<T>::eraseFast(p)", "Pointer must point to a valid element.");
2475  SimTK_ERRCHK(isOwner(), "Array<T>::eraseFast(p)",
2476  "No elements can be erased from a non-owner array.");
2477 
2478  destruct(p);
2479  if (p+1 != end())
2480  moveOneElement(p, &back());
2481  decrSize();
2482  return p;
2483 }
2484 
2492 void clear() {
2493  SimTK_ERRCHK(isOwner() || empty(), "Array_<T>::clear()",
2494  "clear() is not allowed for a non-owner array.");
2495  destruct(begin(), end());
2496  setSize(0);
2497 }
2498 
2499 
2526 T* insert(T* p, size_type n, const T& value) {
2527  T* const gap = insertGapAt(p, n, "Array<T>::insert(p,n,value)");
2528  // Copy construct into the inserted elements and note the size change.
2529  fillConstruct(gap, gap+n, value);
2530  setSize(size()+n);
2531  return gap;
2532 }
2533 
2538 T* insert(T* p, const T& value) {
2539  T* const gap = insertGapAt(p, 1, "Array<T>::insert(p,value)");
2540  // Copy construct into the inserted element and note the size change.
2541  copyConstruct(gap, value);
2542  incrSize();
2543  return gap;
2544 }
2545 
2575 template <class T2>
2576 T* insert(T* p, const T2* first, const T2* last1) {
2577  const char* methodName = "Array_<T>::insert(T* p, T2* first, T2* last1)";
2578  SimTK_ERRCHK((first&&last1) || (first==last1), methodName,
2579  "One of first or last1 was null; either both or neither must be null.");
2580  SimTK_ERRCHK(!this->overlapsWithData(first,last1), methodName,
2581  "Source range can't overlap with the current array contents.");
2582  // Pointers are random access iterators.
2583  return insertIteratorDispatch(p, first, last1,
2584  std::random_access_iterator_tag(),
2585  methodName);
2586 }
2587 
2590 template <class Iter>
2591 T* insert(T* p, const Iter& first, const Iter& last1) {
2592  return insertDispatch(p, first, last1,
2593  typename IsIntegralType<Iter>::Result(),
2594  "Array_<T>::insert(T* p, Iter first, Iter last1)");
2595 }
2600 //------------------------------------------------------------------------------
2601  private:
2602 //------------------------------------------------------------------------------
2603 
2604 
2605 // This method is used when we have already decided we need to make room for
2606 // some new elements by reallocation, by creating a gap somewhere within the
2607 // existing data. We'll issue an error message if this would violate the
2608 // max_size restriction (we can afford to do that even in a Release build since
2609 // we don't expect to grow very often). Otherwise we'll allocate some more space
2610 // and copy construct the existing elements into the new space, leaving a gap
2611 // where indicated. Note that this method does not change the current size but
2612 // does change the capacity.
2613 //
2614 // The gapPos must point within the existing data with null OK if the array
2615 // itself is null, and end() being OK any time although you should use the
2616 // more specialized growAtEnd() method if you know that's what's happening.
2617 //
2618 // Don't call this with a gapSz of zero.
2619 T* growWithGap(T* gapPos, size_type gapSz, const char* methodName) {
2620  assert(gapSz > 0); // <= 0 is a bug, not a user error
2621 
2622  // Note that gapPos may be null if begin() and end() are also.
2623  SimTK_ERRCHK(begin() <= gapPos && gapPos <= end(), methodName,
2624  "Given insertion point is not valid for this array.");
2625 
2626  // Get some new space of a reasonable size.
2627  setAllocated(calcNewCapacityForGrowthBy(gapSz, methodName));
2628  T* newData = allocN(allocated());
2629 
2630  // How many elements will be before the gap?
2631  const size_type nBefore = (size_type)(gapPos-begin());
2632 
2633  // Locate the gap in the new space allocation.
2634  T* newGap = newData + nBefore;
2635  T* newGapEnd = newGap + gapSz; // one past the last element in the gap
2636 
2637  // Copy elements before insertion point; destruct source as we go.
2638  copyConstructThenDestructSource(newData, newGap, data());
2639  // Copy/destruct elements at and after insertion pt; leave gapSz gap.
2640  copyConstructThenDestructSource(newGapEnd, newData+size(), gapPos);
2641 
2642  // Throw away the old data and switch to the new.
2643  freeN(data()); setData(newData);
2644  return newGap;
2645 }
2646 
2647 // Same as growWithGap(end(), n, methodName); see above.
2648 void growAtEnd(size_type n, const char* methodName) {
2649  assert(n > 0); // <= 0 is a bug, not a user error
2650  // Get some new space of a reasonable size.
2651  setAllocated(calcNewCapacityForGrowthBy(n, methodName));
2652  T* newData = allocN(allocated());
2653  // Copy all the elements; destruct source as we go.
2654  copyConstructThenDestructSource(newData, newData+size(), data());
2655  // Throw away the old data and switch to the new.
2656  freeN(data()); setData(newData);
2657 }
2658 
2659 // This method determines how much we should increase the array's capacity
2660 // when asked to insert n elements, due to an insertion or push_back. We will
2661 // generally allocate more new space than requested, in anticipation of
2662 // further insertions. This has to be based on the current size so that only
2663 // log(n) reallocations are performed to insert n elements one at a time. Our
2664 // policy here is to at least double the capacity unless that would exceed
2665 // max_size(). There is also a minimum amount of allocation we'll do if the
2666 // current size is zero or very small.
2667 size_type calcNewCapacityForGrowthBy(size_type n, const char* methodName) const {
2668  SimTK_ERRCHK3_ALWAYS(isGrowthOK(n), methodName,
2669  "Can't grow this Array by %llu element(s) because it would"
2670  " then exceed the max_size of %llu set by its index type %s.",
2671  (unsigned long long)n, ullMaxSize(), indexName());
2672 
2673  // At this point we know that capacity()+n <= max_size().
2674  const size_type mustHave = capacity() + n;
2675 
2676  // Be careful not to overflow size_type as you could if you
2677  // double capacity() rather than halving max_size().
2678  const size_type wantToHave = capacity() <= max_size()/2
2679  ? 2*capacity()
2680  : max_size();
2681 
2682  const size_type newCapacity = std::max(std::max(mustHave,wantToHave),
2683  minAlloc());
2684  return newCapacity;
2685 }
2686 
2687 // Insert an unconstructed gap of size n beginning at position p. The return
2688 // value is a pointer to the first element in the gap. It will be p if no
2689 // reallocation occurred, otherwise it will be pointing into the new data.
2690 // On return size() will be unchanged although allocated() may be bigger.
2691 T* insertGapAt(T* p, size_type n, const char* methodName) {
2692  // Note that p may be null if begin() and end() are also.
2693  SimTK_ERRCHK(begin() <= p && p <= end(), methodName,
2694  "Given insertion point is not valid for this Array.");
2695 
2696  if (n==0) return p; // nothing to do
2697 
2698  SimTK_ERRCHK_ALWAYS(isOwner(), methodName,
2699  "No elements can be inserted into a non-owner array.");
2700 
2701  // Determine the number of elements before the insertion point and
2702  // the number at or afterwards (those must be moved up by one slot).
2703  const size_type before = (size_type)(p-begin()), after = (size_type)(end()-p);
2704 
2705  // Grow the container if necessary. Note that if we have to grow we
2706  // can create the gap at the same time we copy the old elements over
2707  // to the new space.
2708  if (capacity() >= size()+n) {
2709  moveElementsUp(p, n); // leave a gap at p
2710  } else { // need to grow
2711  setAllocated(calcNewCapacityForGrowthBy(n, methodName));
2712  T* newdata = allocN(allocated());
2713  // Copy the elements before the insertion point, and destroy source.
2714  copyConstructThenDestructSource(newdata, newdata+before, data());
2715  // Copy the elements at and after the insertion point, leaving a gap
2716  // of n elements.
2717  copyConstructThenDestructSource(newdata+before+n,
2718  newdata+before+n+after,
2719  p); // i.e., pData+before
2720  p = newdata + before; // points into newdata now
2721  freeN(data());
2722  setData(newdata);
2723  }
2724 
2725  return p;
2726 }
2727 
2728 //------------------------------------------------------------------------------
2729 // CTOR DISPATCH
2730 // This is the constructor implementation for when the class that matches
2731 // the alleged InputIterator type turns out to be one of the integral types
2732 // in which case this should be the ctor(n, initValue) constructor.
2733 template <class IntegralType> void
2734 ctorDispatch(IntegralType n, IntegralType v, TrueType isIntegralType) {
2735  new(this) Array_(size_type(n), value_type(v));
2736 }
2737 
2738 // This is the constructor implementation for when the class that matches
2739 // the alleged InputIterator type is NOT an integral type and may very well
2740 // be an iterator. In that case we split into iterators for which we can
2741 // determine the number of elements in advance (forward, bidirectional,
2742 // random access) and input iterators, for which we can't. Note: iterator
2743 // types are arranged hierarchically random->bi->forward->input with each
2744 // deriving from the one on its right, so the forward iterator tag also
2745 // matches bi and random.
2746 template <class InputIterator> void
2747 ctorDispatch(const InputIterator& first, const InputIterator& last1,
2748  FalseType isIntegralType)
2749 { ctorIteratorDispatch(first, last1,
2750  typename std::iterator_traits<InputIterator>::iterator_category()); }
2751 
2752 // This is the slow generic ctor implementation for any iterator that can't
2753 // make it up to forward_iterator capability (that is, an input_iterator).
2754 // The issue here is that we can't advance the iterator to count the number
2755 // of elements before allocating because input_iterators are consumed when
2756 // reference so we can't go back to look. That means we may have to reallocate
2757 // memory log n times as we "push back" these elements onto the array.
2758 template <class InputIterator> void
2759 ctorIteratorDispatch(const InputIterator& first, const InputIterator& last1,
2760  std::input_iterator_tag)
2761 {
2762  InputIterator src = first;
2763  while (src != last1) {
2764  // We can afford to check this always since we are probably doing I/O.
2765  // Throwing an exception in a constructor is tricky, though -- this
2766  // won't go through the Array_ destructor although it will call the
2767  // Base (ArrayView_) destructor. Since we have already allocated
2768  // some space, we must call deallocate() manually.
2769  if (size() == max_size()) {
2770  deallocate();
2771  SimTK_ERRCHK2_ALWAYS(!"too many elements",
2772  "Array_::ctor(InputIterator first, InputIterator last1)",
2773  "There were still source elements available when the array"
2774  " reached its maximum size of %llu as determined by its index"
2775  " type %s.", ullMaxSize(), indexName());
2776  }
2777  push_back(*src++);
2778  }
2779 }
2780 
2781 // This is the faster constructor implementation for iterator types for which
2782 // we can calculate the number of elements in advance. This will be optimal
2783 // for a random access iterator since we can count in constant time, but for
2784 // forward or bidirectional we'll have to advance n times to count and then
2785 // go back again to do the copy constructions.
2786 template <class ForwardIterator> void
2787 ctorIteratorDispatch(const ForwardIterator& first, const ForwardIterator& last1,
2788  std::forward_iterator_tag)
2789 {
2790  typedef typename std::iterator_traits<ForwardIterator>::difference_type
2792  // iterDistance() is constant time for random access iterators, but
2793  // O(last1-first) for forward and bidirectional since it has to increment
2794  // to count how far apart they are.
2795  const difference_type nInput = this->iterDistance(first,last1);
2796 
2797  SimTK_ERRCHK(nInput >= 0,
2798  "Array_(ForwardIterator first, ForwardIterator last1)",
2799  "Iterators were out of order.");
2800 
2801  SimTK_ERRCHK3(this->isSizeOK(nInput),
2802  "Array_(ForwardIterator first, ForwardIterator last1)",
2803  "Source has %llu elements but this array is limited to %llu"
2804  " elements by its index type %s.",
2805  this->ull(nInput), ullMaxSize(), indexName());
2806 
2807  const size_type n = size_type(nInput);
2808  setSize(n);
2809  allocateNoConstruct(n);
2810  copyConstruct(data(), data()+n, first);
2811 }
2812 
2813 //------------------------------------------------------------------------------
2814 // INSERT DISPATCH
2815 // This is the insert() implementation for when the class that matches
2816 // the alleged InputIterator type turns out to be one of the integral types
2817 // in which case this should be the insert(p, n, initValue) constructor.
2818 template <class IntegralType>
2819 T* insertDispatch(T* p, IntegralType n, IntegralType v,
2820  TrueType isIntegralType, const char*)
2821 { return insert(p, size_type(n), value_type(v)); }
2822 
2823 // This is the insert() implementation for when the class that matches
2824 // the alleged InputIterator type is NOT an integral type and may very well
2825 // be an iterator. See ctorDispatch() above for more information.
2826 template <class InputIterator>
2827 T* insertDispatch(T* p, const InputIterator& first, const InputIterator& last1,
2828  FalseType isIntegralType, const char* methodName)
2829 { return insertIteratorDispatch(p, first, last1,
2830  typename std::iterator_traits<InputIterator>::iterator_category(),
2831  methodName); }
2832 
2833 // This is the slow generic insert implementation for any iterator that can't
2834 // make it up to forward_iterator capability (that is, an input_iterator).
2835 // See ctorIteratorDispatch() above for more information.
2836 template <class InputIterator>
2837 T* insertIteratorDispatch(T* p, InputIterator first, InputIterator last1,
2838  std::input_iterator_tag, const char* methodName)
2839 {
2840  size_type nInserted = 0;
2841  while (first != last1) {
2842  // We can afford to check this always since we are probably doing I/O.
2843  SimTK_ERRCHK2_ALWAYS(size() < max_size(), methodName,
2844  "There were still source elements available when the array"
2845  " reached its maximum size of %llu as determined by its index"
2846  " type %s.", ullMaxSize(), indexName());
2847  p = insert(p, *first++); // p may now point to reallocated memory
2848  ++p; ++nInserted;
2849  }
2850  // p now points just after the last inserted element; subtract the
2851  // number inserted to get a pointer to the first inserted element.
2852  return p-nInserted;
2853 }
2854 
2855 // This is the faster constructor implementation for iterator types for which
2856 // we can calculate the number of elements in advance. This will be optimal
2857 // for a random access iterator since we can count in constant time, but for
2858 // forward or bidirectional we'll have to advance n times to count and then
2859 // go back again to do the copy constructions.
2860 template <class ForwardIterator>
2861 T* insertIteratorDispatch(T* p, const ForwardIterator& first,
2862  const ForwardIterator& last1,
2863  std::forward_iterator_tag,
2864  const char* methodName)
2865 {
2866  typedef typename std::iterator_traits<ForwardIterator>::difference_type
2868  // iterDistance() is constant time for random access iterators, but
2869  // O(last1-first) for forward and bidirectional since it has to increment
2870  // to count how far apart they are.
2871  const difference_type nInput = this->iterDistance(first,last1);
2872 
2873  SimTK_ERRCHK(nInput >= 0, methodName, "Iterators were out of order.");
2874 
2875  SimTK_ERRCHK3(isGrowthOK(nInput), methodName,
2876  "Source has %llu elements which would make this array exceed the %llu"
2877  " elements allowed by its index type %s.",
2878  this->ull(nInput), ullMaxSize(), indexName());
2879 
2880  const size_type n = size_type(nInput);
2881  p = insertGapAt(p, n, methodName);
2882  copyConstruct(p, p+n, first);
2883  setSize(size()+n);
2884  return p;
2885 }
2886 
2887 //------------------------------------------------------------------------------
2888 // ASSIGN DISPATCH
2889 // This is the assign() implementation for when the class that matches
2890 // the alleged InputIterator type turns out to be one of the integral types
2891 // in which case this should be the assign(n, initValue) constructor.
2892 template <class IntegralType>
2893 void assignDispatch(IntegralType n, IntegralType v, TrueType isIntegralType,
2894  const char* methodName)
2895 { assign(size_type(n), value_type(v)); }
2896 
2897 // This is the assign() implementation for when the class that matches
2898 // the alleged InputIterator type is NOT an integral type and may very well
2899 // be an iterator. See ctorDispatch() above for more information.
2900 template <class InputIterator>
2901 void assignDispatch(const InputIterator& first, const InputIterator& last1,
2902  FalseType isIntegralType, const char* methodName)
2903 { assignIteratorDispatch(first, last1,
2904  typename std::iterator_traits<InputIterator>::iterator_category(),
2905  methodName); }
2906 
2907 // This is the slow generic implementation for a plain input_iterator
2908 // (i.e., not a forward, bidirectional, or random access iterator). These
2909 // have the unfortunate property that we can't count the elements in advance.
2910 template <class InputIterator>
2911 void assignIteratorDispatch(const InputIterator& first,
2912  const InputIterator& last1,
2913  std::input_iterator_tag,
2914  const char* methodName)
2915 {
2916  // TODO: should probably allow this and just blow up when the size()+1st
2917  // element is seen.
2918  SimTK_ERRCHK_ALWAYS(isOwner(), methodName,
2919  "Assignment to a non-owner array can only be done from a source"
2920  " designated with forward iterators or pointers because we"
2921  " must be able to verify that the source and destination sizes"
2922  " are the same.");
2923 
2924  clear(); // TODO: change space allocation here?
2925  InputIterator src = first;
2926  while (src != last1) {
2927  // We can afford to check this always since we are probably doing I/O.
2928  SimTK_ERRCHK2_ALWAYS(size() < max_size(), methodName,
2929  "There were still source elements available when the array"
2930  " reached its maximum size of %llu as determined by its index"
2931  " type %s.", ullMaxSize(), indexName());
2932 
2933  push_back(*src++);
2934  }
2935 }
2936 
2937 // This is the faster implementation that works for forward, bidirectional,
2938 // and random access iterators including ordinary pointers. We can check here that the
2939 // iterators are in the right order, and that the source is not too big to
2940 // fit in this array. Null pointer checks should be done prior to calling,
2941 // however, since iterators in general aren't pointers.
2942 template <class ForwardIterator>
2943 void assignIteratorDispatch(const ForwardIterator& first,
2944  const ForwardIterator& last1,
2945  std::forward_iterator_tag,
2946  const char* methodName)
2947 {
2948  typedef typename std::iterator_traits<ForwardIterator>::difference_type
2949  IterDiffType;
2950  // iterDistance() is constant time for random access iterators, but
2951  // O(last1-first) for forward and bidirectional since it has to increment
2952  // to count how far apart they are.
2953  const IterDiffType nInput = this->iterDistance(first,last1);
2954 
2955  SimTK_ERRCHK(nInput >= 0, methodName, "Iterators were out of order.");
2956 
2957  SimTK_ERRCHK3(this->isSizeOK(nInput), methodName,
2958  "Source has %llu elements but this Array is limited to %llu"
2959  " elements by its index type %s.",
2960  this->ull(nInput), ullMaxSize(), indexName());
2961 
2962  const size_type n = size_type(nInput);
2963  if (isOwner()) {
2964  // This is an owner Array; assignment is considered deallocation
2965  // followed by copy construction.
2966 
2967  clear(); // all elements destructed; allocation unchanged
2968  reallocateIfAdvisable(n); // change allocation if too small or too big
2969  copyConstruct(data(), cdata()+n, first);
2970  setSize(n);
2971  } else {
2972  // This is a non-owner Array. Assignment can occur only if the
2973  // source is the same size as the array, and the semantics are of
2974  // repeated assignment using T::operator=() not destruction followed
2975  // by copy construction.
2976  SimTK_ERRCHK2(n == size(), methodName,
2977  "Source has %llu elements which does not match the size %llu"
2978  " of the non-owner array it is being assigned into.",
2979  this->ull(n), ullSize());
2980 
2981  T* p = begin();
2982  ForwardIterator src = first;
2983  while (src != last1)
2984  *p++ = *src++; // call T's assignment operator
2985  }
2986 }
2987 
2988 // We are going to put a total of n elements into the Array (probably
2989 // because of an assignment or resize) and we want the space allocation
2990 // to be reasonable. That means of course that the allocation must be
2991 // *at least* n, but we also don't want it to be too big. Our policy
2992 // here is that if it is currently less than twice what we need we
2993 // won't reallocate, otherwise we'll shrink the space. When changing
2994 // the size to zero or something very small we'll treat the Array as
2995 // though its current size is minAlloc, meaning we won't reallocate
2996 // if the existing space is less than twice minAlloc.
2997 // nAllocated will be set appropriately; size() is not touched here.
2998 // No constructors or destructors are called.
2999 void reallocateIfAdvisable(size_type n) {
3000  if (allocated() < n || allocated()/2 > std::max(minAlloc(), n))
3001  reallocateNoDestructOrConstruct(n);
3002 }
3003 
3004 
3005 void allocateNoConstruct(size_type n)
3006 { setData(allocN(n)); setAllocated(n); } // size() left unchanged
3007 void deallocateNoDestruct()
3008 { freeN(data()); setData(0); setAllocated(0); } // size() left unchanged
3009 void reallocateNoDestructOrConstruct(size_type n)
3010 { deallocateNoDestruct(); allocateNoConstruct(n); }
3011 
3012 // This sets the smallest allocation we'll do when growing.
3013 size_type minAlloc() const
3014 { return std::min(max_size(), size_type(4)); }
3015 
3016 // Allocate without construction. Returns a null pointer if asked
3017 // to allocate 0 elements. In Debug mode we'll fill memory with
3018 // all 1's as a bug catcher.
3019 static T* allocN(size_type n) {
3020  if (n==0) return 0;
3021  unsigned char* newdata = new unsigned char[n * sizeof(T)];
3022  #ifndef NDEBUG
3023  unsigned char* b=newdata;
3024  const unsigned char* e=newdata+(n*sizeof(T));
3025  while (b != e) *b++ = 0xff;
3026  #endif
3027  return reinterpret_cast<T*>(newdata);
3028 }
3029 
3030 // Free memory without calling T's destructor. Nothing happens if passed
3031 // a null pointer.
3032 static void freeN(T* p) {
3033  delete[] reinterpret_cast<char*>(p);
3034 }
3035 
3036 // default construct one element
3037 static void defaultConstruct(T* p) {new(p) T();}
3038 // default construct range [b,e)
3039 static void defaultConstruct(T* b, const T* e)
3040 { while (b!=e) new(b++) T(); }
3041 
3042 // copy construct range [b,e) with repeats of a given value
3043 static void fillConstruct(T* b, const T* e, const T& v)
3044 { while(b!=e) new(b++) T(v); }
3045 
3046 // copy construct one element from a given value
3047 static void copyConstruct(T* p, const T& v) {new(p) T(v);}
3048 // copy construct range [b,e) from sequence of source values
3049 static void copyConstruct(T* b, const T* e, T* src)
3050 { while(b!=e) new(b++) T(*src++); }
3051 // Templatized copy construct will work if the source elements are
3052 // assignment compatible with the destination elements.
3053 template <class InputIterator>
3054 static void copyConstruct(T* b, const T* e, InputIterator src)
3055 { while(b!=e) new(b++) T(*src++); }
3056 
3057 // Copy construct range [b,e] from sequence of source values and
3058 // destruct the source after it is copied. It's better to alternate
3059 // copying and destructing than to do this in two passes since we
3060 // will already have touched the memory.
3061 static void copyConstructThenDestructSource(T* b, const T* e, T* src)
3062 { while(b!=e) {new(b++) T(*src); src++->~T();} }
3063 
3064 // We have an element at from that we would like to move into the currently-
3065 // unconstructed slot at to. Both from and to are expected to be pointing to
3066 // elements within the currently allocated space. From's slot will be left
3067 // unconstructed.
3068 void moveOneElement(T* to, T* from) {
3069  assert(data() <= to && to < data()+allocated());
3070  assert(data() <= from && from < data()+allocated());
3071  copyConstruct(to, *from);
3072  destruct(from);
3073 }
3074 
3075 
3076 // Move elements from p to end() down by n>0 places to fill an unconstructed
3077 // gap beginning at p-n. Any leftover space at the end will be unconstructed.
3078 void moveElementsDown(T* p, size_type n) {
3079  assert(n > 0);
3080  for (; p != end(); ++p)
3081  moveOneElement(p-n,p);
3082 }
3083 
3084 // Move elements from p to end() up by n>0 places to make an unconstructed gap
3085 // at [p,p+n). Note that this has to be done backwards so that we don't
3086 // write on any elements until after they've been copied.
3087 void moveElementsUp(T* p, size_type n) {
3088  assert(n > 0);
3089  T* src = end(); // points one past source element (begin()-1 not allowed)
3090  while (src != p) {
3091  --src; // now points to source
3092  moveOneElement(src+n, src);;
3093  }
3094 }
3095 
3096 // destruct one element
3097 static void destruct(T* p) {p->~T();}
3098 // destruct range [b,e)
3099 static void destruct(T* b, const T* e)
3100 { while(b!=e) b++->~T(); }
3101 
3102 // Check that growing this array by n elements wouldn't cause it to exceed
3103 // its allowable maximum size.
3104 template <class S>
3105 bool isGrowthOK(S n) const
3106 { return this->isSizeOK(ullCapacity() + this->ull(n)); }
3107 
3108 // The following private methods are protected methods in the ArrayView base
3109 // class, so they should not need repeating here. Howevr, we explicitly
3110 // forward to the Base methods to avoid gcc errors. The gcc complaint
3111 // is due to their not depending on any template parameters; the "this->"
3112 // apparently fixes that problem.
3113 
3114 // These provide direct access to the data members.
3115 packed_size_type psize() const {return this->CBase::psize();}
3116 packed_size_type pallocated() const {return this->CBase::pallocated();}
3117 
3118 void setData(const T* p) {this->CBase::setData(p);}
3119 void setSize(size_type n) {this->CBase::setSize(n);}
3120 void incrSize() {this->CBase::incrSize();}
3121 void decrSize() {this->CBase::decrSize();}
3122 void setAllocated(size_type n) {this->CBase::setAllocated(n);}
3123 // This just cast sizes to unsigned long long so that we can do comparisons
3124 // without getting warnings.
3125 unsigned long long ullSize() const {return this->CBase::ullSize();}
3126 unsigned long long ullCapacity() const {return this->CBase::ullCapacity();}
3127 unsigned long long ullMaxSize() const {return this->CBase::ullMaxSize();}
3128 // This is the index type name and is handy for error messages to explain
3129 // why some size was too big.
3130 const char* indexName() const {return this->CBase::indexName();}
3131 };
3132 
3133 
3134 // This "private" static method is used to implement ArrayView's
3135 // fillArrayViewFromStream() and Array's readArrayFromStream() namespace-scope
3136 // static methods, which are in turn used to implement ArrayView's and
3137 // Array's stream extraction operators ">>". This method has to be in the
3138 // header file so that we don't need to pass streams through the API, but it
3139 // is not intended for use by users and has no Doxygen presence, unlike
3140 // fillArrayFromStream() and readArrayFromStream() and (more commonly)
3141 // the extraction operators.
3142 template <class T, class X> static inline
3143 std::istream& readArrayFromStreamHelper
3144  (std::istream& in, bool isFixedSize, Array_<T,X>& out)
3145 {
3146  // If already failed, bad, or eof, set failed bit and return without
3147  // touching the Array.
3148  if (!in.good()) {in.setstate(std::ios::failbit); return in;}
3149 
3150  // If the passed-in Array isn't an owner, then we have to treat it as
3151  // a fixed size ArrayView regardless of the setting of the isFixedSize
3152  // argument.
3153  if (!out.isOwner())
3154  isFixedSize = true; // might be overriding the argument here
3155 
3156  // numRequired will be ignored unless isFixedSize==true.
3157  const typename Array_<T,X>::size_type
3158  numRequired = isFixedSize ? out.size() : 0;
3159 
3160  if (!isFixedSize)
3161  out.clear(); // We're going to replace the entire contents of the Array.
3162 
3163  // Skip initial whitespace. If that results in eof this may be a successful
3164  // read of a 0-length, unbracketed Array. That is OK for either a
3165  // variable-length Array or a fixed-length ArrayView of length zero.
3166  std::ws(in); if (in.fail()) return in;
3167  if (in.eof()) {
3168  if (isFixedSize && numRequired != 0)
3169  in.setstate(std::ios_base::failbit); // zero elements not OK
3170  return in;
3171  }
3172 
3173  // Here the stream is good and the next character is non-white.
3174  assert(in.good());
3175 
3176  // Use this for raw i/o (peeks and gets).
3177  typename std::iostream::int_type ch;
3178  const typename std::iostream::int_type EOFch =
3179  std::iostream::traits_type::eof();
3180 
3181  // Now see if the sequence is bare or surrounded by (), [], or {}.
3182  bool lookForCloser = true;
3183  char openBracket, closeBracket;
3184  ch = in.peek(); if (in.fail()) return in;
3185  assert(ch != EOFch); // we already checked above
3186 
3187  openBracket = (char)ch;
3188  if (openBracket=='(') {in.get(); closeBracket = ')';}
3189  else if (openBracket=='[') {in.get(); closeBracket = ']';}
3190  else if (openBracket=='{') {in.get(); closeBracket = '}';}
3191  else lookForCloser = false;
3192 
3193  // If lookForCloser is true, then closeBracket contains the terminating
3194  // delimiter, otherwise we're not going to quit until eof.
3195 
3196  // Eat whitespace after the opening bracket to see what's next.
3197  if (in.good()) std::ws(in);
3198 
3199  // If we're at eof now it must be because the open bracket was the
3200  // last non-white character in the stream, which is an error.
3201  if (!in.good()) {
3202  if (in.eof()) {
3203  assert(lookForCloser); // or we haven't read anything that could eof
3204  in.setstate(std::ios::failbit);
3205  }
3206  return in;
3207  }
3208 
3209  // istream is good and next character is non-white; ready to read first
3210  // value or terminator.
3211 
3212  // We need to figure out whether the elements are space- or comma-
3213  // separated and then insist on consistency.
3214  bool commaOK = true, commaRequired = false;
3215  bool terminatorSeen = false;
3216  X nextIndex(0);
3217  while (true) {
3218  char c;
3219 
3220  // Here at the top of this loop, we have already successfully read
3221  // n=nextIndex values of type T. For fixed-size reads, it might be
3222  // the case that n==numRequired already, but we still may need to
3223  // look for a closing bracket before we can declare victory.
3224  // The stream is good() (not at eof) but it might be the case that
3225  // there is nothing but white space left; we don't know yet because
3226  // if we have satisfied the fixed-size count and are not expecting
3227  // a terminator then we should quit without absorbing the trailing
3228  // white space.
3229  assert(in.good());
3230 
3231  // Look for closing bracket before trying to read value.
3232  if (lookForCloser) {
3233  // Eat white space to find the closing bracket.
3234  std::ws(in); if (!in.good()) break; // eof?
3235  ch = in.peek(); assert(ch != EOFch);
3236  if (!in.good()) break;
3237  c = (char)ch;
3238  if (c == closeBracket) {
3239  in.get(); // absorb the closing bracket
3240  terminatorSeen = true;
3241  break;
3242  }
3243  // next char not a closing bracket; fall through
3244  }
3245 
3246  // We didn't look or didn't find a closing bracket. The istream is good
3247  // but we might be looking at white space.
3248 
3249  // If we already got all the elements we want, break for final checks.
3250  if (isFixedSize && (nextIndex == numRequired))
3251  break; // that's a full count.
3252 
3253  // Look for comma before value, except the first time.
3254  if (commaOK && nextIndex != 0) {
3255  // Eat white space to find the comma.
3256  std::ws(in); if (!in.good()) break; // eof?
3257  ch = in.peek(); assert(ch != EOFch);
3258  if (!in.good()) break;
3259  c = (char)ch;
3260  if (c == ',') {
3261  in.get(); // absorb comma
3262  commaRequired = true; // all commas from now on
3263  } else { // next char not a comma
3264  if (commaRequired) // bad, e.g.: v1, v2, v3 v4
3265  { in.setstate(std::ios::failbit); break; }
3266  else commaOK = false; // saw: v1 v2 (no commas now)
3267  }
3268  if (!in.good()) break; // might be eof
3269  }
3270 
3271  // No closing bracket yet; don't have enough elements; skipped comma
3272  // if any; istream is good; might be looking at white space.
3273  assert(in.good());
3274 
3275  // Now read in an element of type T.
3276  // The extractor T::operator>>() will ignore leading white space.
3277  if (!isFixedSize)
3278  out.push_back(); // grow by one (default consructed)
3279  in >> out[nextIndex]; if (in.fail()) break;
3280  ++nextIndex;
3281 
3282  if (!in.good()) break; // might be eof
3283  }
3284 
3285  // We will get here under a number of circumstances:
3286  // - the fail bit is set in the istream, or
3287  // - we reached eof
3288  // - we saw a closing brace
3289  // - we got all the elements we wanted (for a fixed-size read)
3290  // Note that it is possible that we consumed everything except some
3291  // trailing white space (meaning we're not technically at eof), but
3292  // for consistency with built-in operator>>()'s we won't try to absorb
3293  // that trailing white space.
3294 
3295  if (!in.fail()) {
3296  if (lookForCloser && !terminatorSeen)
3297  in.setstate(std::ios::failbit); // missing terminator
3298 
3299  if (isFixedSize && nextIndex != numRequired)
3300  in.setstate(std::ios::failbit); // wrong number of values
3301  }
3302 
3303  return in;
3304 }
3305 
3306 
3307 
3308 //------------------------------------------------------------------------------
3309 // RELATED GLOBAL OPERATORS
3310 //------------------------------------------------------------------------------
3311 // These are logically part of the Array_<T,X> class but are not actually
3312 // class members; that is, they are in the SimTK namespace.
3313 
3314 // Some of the serialization methods could have been member functions but
3315 // then an attempt to explicitly instantiate the whole Array_<T> class for
3316 // some type T would fail if T did not support the requisite I/O operations
3317 // even if those operations were never used. This came up when Chris Bruns was
3318 // trying to wrap Array objects for Python, which requires explicit
3319 // instantiation.
3320 
3328 
3332 template <class T, class X> inline void
3333 writeUnformatted(std::ostream& o, const Array_<T,X>& v) {
3334  for (X i(0); i < v.size(); ++i) {
3335  if (i != 0) o << " ";
3336  writeUnformatted(o, v[i]);
3337  }
3338 }
3339 
3340 
3344 template <class T, class X> inline void
3345 writeFormatted(std::ostream& o, const Array_<T,X>& v) {
3346  o << '(';
3347  for (X i(0); i < v.size(); ++i) {
3348  if (i != 0) o << ',';
3349  writeFormatted(o, v[i]);
3350  }
3351  o << ')';
3352 }
3353 
3360 template <class T, class X> inline
3361 std::ostream&
3362 operator<<(std::ostream& o,
3363  const ArrayViewConst_<T,X>& a)
3364 {
3365  o << '(';
3366  if (!a.empty()) {
3367  o << a.front();
3368  for (const T* p = a.begin()+1; p != a.end(); ++p)
3369  o << ',' << *p;
3370  }
3371  return o << ')';
3372 }
3373 
3374 
3378 template <class T, class X> inline bool
3379 readUnformatted(std::istream& in, Array_<T,X>& v) {
3380  v.clear();
3381  T element;
3382  std::ws(in); // Make sure we're at eof if stream is all whitespace.
3383  while (!in.eof() && readUnformatted(in, element))
3384  v.push_back(element);
3385  return !in.fail(); // eof is expected and ok
3386 }
3387 
3392 template <class T, class X> inline bool
3393 readUnformatted(std::istream& in, ArrayView_<T,X>& v) {
3394  for (X i(0); i < v.size(); ++i)
3395  if (!readUnformatted(in, v[i])) return false;
3396  return true;
3397 }
3398 
3399 
3405 template <class T, class X> inline bool
3406 readFormatted(std::istream& in, Array_<T,X>& v) {
3407  return !readArrayFromStream(in,v).fail();
3408 }
3409 
3415 template <class T, class X> inline bool
3416 readFormatted(std::istream& in, ArrayView_<T,X>& v) {
3417  return !fillArrayViewFromStream(in,v).fail();
3418 }
3419 
3449 template <class T, class X> static inline
3450 std::istream& readArrayFromStream(std::istream& in, Array_<T,X>& out)
3451 { return readArrayFromStreamHelper<T,X>(in, false /*variable sizez*/, out); }
3452 
3453 
3454 
3479 template <class T, class X> static inline
3480 std::istream& fillArrayFromStream(std::istream& in, Array_<T,X>& out)
3481 { return readArrayFromStreamHelper<T,X>(in, true /*fixed size*/, out); }
3482 
3487 template <class T, class X> static inline
3488 std::istream& fillArrayViewFromStream(std::istream& in, ArrayView_<T,X>& out)
3489 { return readArrayFromStreamHelper<T,X>(in, true /*fixed size*/, out); }
3490 
3491 
3492 
3493 
3503 template <class T, class X> inline
3504 std::istream& operator>>(std::istream& in, Array_<T,X>& out)
3505 { return readArrayFromStream<T,X>(in, out); }
3506 
3514 template <class T, class X> inline
3515 std::istream& operator>>(std::istream& in, ArrayView_<T,X>& out)
3516 { return fillArrayViewFromStream<T,X>(in, out); }
3517 
3527 
3530 template <class T1, class X1, class T2, class X2> inline bool
3532  // Avoid warnings in size comparison by using common type.
3533  const ptrdiff_t sz1 = a1.end()-a1.begin();
3534  const ptrdiff_t sz2 = a2.end()-a2.begin();
3535  if (sz1 != sz2) return false;
3536  const T1* p1 = a1.begin();
3537  const T2* p2 = a2.begin();
3538  while (p1 != a1.end())
3539  if (!(*p1++ == *p2++)) return false;
3540  return true;
3541 }
3544 template <class T1, class X1, class T2, class X2> inline bool
3546 { return !(a1 == a2); }
3547 
3552 template <class T1, class X1, class T2, class X2> inline bool
3553 operator<(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2) {
3554  const T1* p1 = a1.begin();
3555  const T2* p2 = a2.begin();
3556  while (p1 != a1.end() && p2 != a2.end()) {
3557  if (!(*p1 == *p2))
3558  return *p1 < *p2; // otherwise p1 > p2
3559  ++p1; ++p2;
3560  }
3561  // All elements were equal until one or both arrays ran out of elements.
3562  // a1 is less than a2 only if a1 ran out and a2 didn't.
3563  return p1 == a1.end() && p2 != a2.end();
3564 }
3567 template <class T1, class X1, class T2, class X2> inline bool
3569 { return !(a1 < a2); }
3573 template <class T1, class X1, class T2, class X2> inline bool
3575 { return a2 < a1; }
3578 template <class T1, class X1, class T2, class X2> inline bool
3579 operator<=(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2)
3580 { return !(a1 > a2); }
3581 
3585 template <class T1, class X1, class T2, class A2> inline bool
3586 operator==(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3587 { return a1 == ArrayViewConst_<T2,size_t>(v2); }
3588 
3592 template <class T1, class A1, class T2, class X2> inline bool
3593 operator==(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3594 { return a2 == v1; }
3595 
3598 template <class T1, class X1, class T2, class A2> inline bool
3599 operator!=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3600 { return !(a1 == v2); }
3603 template <class T1, class A1, class T2, class X2> inline bool
3604 operator!=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3605 { return !(a2 == v1); }
3606 
3612 template <class T1, class X1, class T2, class A2> inline bool
3613 operator<(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3614 { return a1 < ArrayViewConst_<T2,size_t>(v2); }
3615 
3621 template <class T1, class A1, class T2, class X2> inline bool
3622 operator<(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3623 { return ArrayViewConst_<T1,size_t>(v1) < a2; }
3624 
3627 template <class T1, class X1, class T2, class A2> inline bool
3628 operator>=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3629 { return !(a1 < v2); }
3632 template <class T1, class A1, class T2, class X2> inline bool
3633 operator>=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3634 { return !(v1 < a2); }
3635 
3639 template <class T1, class X1, class T2, class A2> inline bool
3640 operator>(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3641 { return v2 < a1; }
3645 template <class T1, class A1, class T2, class X2> inline bool
3646 operator>(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3647 { return a2 < v1; }
3648 
3651 template <class T1, class X1, class T2, class A2> inline bool
3652 operator<=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3653 { return !(a1 > v2); }
3656 template <class T1, class A1, class T2, class X2> inline bool
3657 operator<=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3658 { return !(v1 > a2); }
3659 
3662 } // namespace SimTK
3663 
3664 namespace std {
3668 template <class T, class X> inline void
3670  a1.swap(a2);
3671 }
3672 
3673 } // namespace std
3674 
3675 #endif // SimTK_SimTKCOMMON_ARRAY_H_
static size_type max_size()
Definition: Array.h:233
void writeUnformatted(std::ostream &o, const Array_< T, X > &v)
Specialize writeUnformatted() for Array_<E,X> to delegate to element type E, with spaces separating t...
Definition: Array.h:3333
T & back()
Return a writable reference to the last element in this array, which must not be empty.
Definition: Array.h:1114
This Array_ helper class is the base class for Array_, extending ArrayViewConst_ to add the ability t...
Definition: Array.h:49
bool readUnformatted(std::istream &in, ArrayView_< T, X > &v)
Specialization of readUnformatted() for fixed-length ArrayView_<T,X>; reads whitespace-separated toke...
Definition: Array.h:3393
Array_ & operator=(const Array_< T2, X2 > &src)
This is assignment from a source array whose element type T2 and/or index type X2 are different from ...
Definition: Array.h:1897
unsigned char size_type
Definition: Array.h:214
const T & back() const
Return a const reference to the last element in this array, which must not be empty.
Definition: Array.h:2267
ArrayView_ & operator=(const ArrayViewConst_< T2, X2 > &src)
Assignment from any other array object is allowed as long as the number of elements matches and the t...
Definition: Array.h:918
const T * data() const
The const version of the data() method is identical to cdata().
Definition: Array.h:2199
ArrayIndexTraits< X >::difference_type difference_type
A signed integral type that can represent the difference between any two legitimate index values for ...
Definition: Array.h:346
const T * end() const
The const version of end() is the same as cend().
Definition: Array.h:635
static size_type max_size()
Definition: Array.h:193
static size_type max_size()
Definition: Array.h:205
const T & front() const
Return a const reference to the first element in this array, which must not be empty.
Definition: Array.h:1093
bool empty() const
Definition: Array.h:1240
const T * cend() const
Return a const pointer to what would be the element just after the last one in the array; this may be...
Definition: Array.h:1180
#define SimTK_ERRCHK2_ALWAYS(cond, whereChecked, fmt, a1, a2)
Definition: ExceptionMacros.h:289
void fill(const T &fillValue)
Assign all current elements of the array to the same fillValue.
Definition: Array.h:1800
bool operator>(const ArrayViewConst_< T1, X1 > &a1, const std::vector< T2, A2 > &v2)
The greater than operator is implemented by using less than with the arguments reversed, meaning the elements must have working comparison operators of the form T2==T1 and T2<T1.
Definition: Array.h:3640
T value_type
The type of object stored in this container.
Definition: Array.h:323
#define SimTK_SIZECHECK(sz, maxsz, where)
Definition: ExceptionMacros.h:146
ArrayView_()
Default constructor allocates no heap space and is very fast.
Definition: Array.h:862
bool operator==(const ArrayViewConst_< T1, X1 > &a1, const std::vector< T2, A2 > &v2)
An Array_<T1> and an std::vector<T2> are equal if and only if they are the same size() and each eleme...
Definition: Array.h:3586
const T & at(index_type i) const
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:1073
unsigned long long size_type
Definition: Array.h:222
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: Array.h:846
~ArrayViewConst_()
The destructor just disconnects the array view handle from its data; see disconnect() for more inform...
Definition: Array.h:486
const T * cdata() const
Return a const pointer to the first element of the array, or possibly (but not necessarily) null (0) ...
Definition: Array.h:2196
Array_(const Array_< T2, X2 > &src)
Construct this Array_<T,X> as a copy of another Array_<T2,X2> where T2!=T or X2!=X.
Definition: Array.h:1621
const T & front() const
Return a const reference to the first element in this array, which must not be empty.
Definition: Array.h:2253
T * iterator
A writable iterator for this container (same as pointer here).
Definition: Array.h:335
const_reverse_iterator crend() const
Return the past-the-end reverse iterator that tests equal to a reverse iterator that has been increme...
Definition: Array.h:643
const_reverse_iterator rbegin() const
The const version of rbegin() is the same as crbegin().
Definition: Array.h:2174
const T & at(index_type i) const
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:547
signed char difference_type
Definition: Array.h:204
#define SimTK_ERRCHK1_ALWAYS(cond, whereChecked, fmt, a1)
Definition: ExceptionMacros.h:285
void assign(size_type n, const T &fillValue)
Set this array to be n copies of the supplied fillValue.
Definition: Array.h:1766
size_type allocated() const
Return the amount of heap space owned by this array; this is the same as capacity() for owner arrays ...
Definition: Array.h:2124
std::reverse_iterator< iterator > reverse_iterator
Definition: Array.h:1506
T & reference
Definition: Array.h:1502
void assign(const T2 *first, const T2 *last1)
Assign to this array to to make it a copy of the elements in range [first,last1) given by ordinary po...
Definition: Array.h:1825
size_type size() const
Return the current number of elements stored in this array.
Definition: Array.h:501
bool readUnformatted(std::istream &in, Array_< T, X > &v)
Specialization of readUnformatted() for variable-length Array_<T,X>; continues reading whitespace-sep...
Definition: Array.h:3379
long size_type
Definition: Array.h:148
ArrayViewConst_(const std::vector< T, A > &src)
Construct a ArrayViewConst_<T> by referencing (sharing) the data in a const std::vector<T>, without copying the data; this is also an implicit conversion.
Definition: Array.h:449
const T & operator[](index_type i) const
Select an element by its index, returning a const reference.
Definition: Array.h:539
void resize(size_type n)
Change the size of this Array, preserving all the elements that will still fit, and default construct...
Definition: Array.h:2030
int difference_type
Definition: Array.h:116
T * iterator
Definition: Array.h:843
Array_(size_type n)
Construct an array containing n default-constructed elements.
Definition: Array.h:1530
char size_type
Definition: Array.h:203
This templatized type is used by the Array_<T,X> classes to obtain the information they need to use t...
Definition: Array.h:47
const T * begin() const
The const version of begin() is the same as cbegin().
Definition: Array.h:633
bool isOwner() const
Does this array own the data to which it refers? If not, it can't be resized, and the destructor will...
Definition: Array.h:521
const T & const_reference
A const value_type reference.
Definition: Array.h:333
static size_type max_size()
Definition: Array.h:216
T * pointer
A writable pointer to a value_type.
Definition: Array.h:327
const_reverse_iterator rend() const
The const version of rend() is the same as crend().
Definition: Array.h:647
const T * end() const
The const version of end() is the same as cend().
Definition: Array.h:1182
Array_(const InputIter &first, const InputIter &last1)
Construct an Array_<T> from a range [first,last1) of values identified by a pair of iterators...
Definition: Array.h:1562
size_type size() const
Definition: Array.h:1238
bool operator!=(const std::vector< T1, A1 > &v1, const ArrayViewConst_< T2, X2 > &a2)
The not equal operator is implemented using the equal operator.
Definition: Array.h:3604
unsigned long size_type
Definition: Array.h:135
long long difference_type
Definition: Array.h:232
T * pointer
Definition: Array.h:1500
reverse_iterator rbegin()
Return a writable reverse iterator pointing to the last element in the array or rend() if the array i...
Definition: Array.h:2177
T value_type
Definition: Array.h:837
ELEM min(const VectorBase< ELEM > &v)
Definition: VectorMath.h:178
T & at(index_type i)
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:2239
const_reverse_iterator rend() const
The const version of rend() is the same as crend().
Definition: Array.h:1203
bool operator>(const ArrayViewConst_< T1, X1 > &a1, const ArrayViewConst_< T2, X2 > &a2)
The greater than operator is implemented by using less than with the arguments reversed, meaning the elements must have working comparison operators of the form T2==T1 and T2<T1.
Definition: Array.h:3574
T * insert(T *p, const T &value)
Insert a new element at a given location within this array, initializing it to a copy of a given valu...
Definition: Array.h:2538
ArrayIndexPackType< size_type >::packed_size_type packed_size_type
Definition: Array.h:850
#define SimTK_ASSERT(cond, msg)
Definition: ExceptionMacros.h:374
unsigned size_type
Definition: Array.h:115
void pop_back()
Remove the last element from this array, which must not be empty.
Definition: Array.h:2381
ArrayIndexTraits< X >::size_type size_type
Definition: Array.h:1508
T * raw_push_back()
This dangerous method increases the Array's size by one element at the end but doesn't perform any co...
Definition: Array.h:2371
ArrayView_(std::vector< T, A > &v)
Construct to reference memory owned by a writable std::vector.
Definition: Array.h:872
#define SimTK_ERRCHK3(cond, whereChecked, fmt, a1, a2, a3)
Definition: ExceptionMacros.h:330
size_type size() const
Return the current number of elements stored in this array.
Definition: Array.h:2014
Array_(const std::vector< T2 > &v)
Construct an Array_<T> by copying from an std::vector<T2>, where T2 may be the same type as T but doesn't...
Definition: Array.h:1590
ArrayIndexTraits< X >::size_type size_type
Definition: Array.h:847
ArrayViewConst_(const ArrayViewConst_ &src)
Copy constructor is shallow; the constructed const array object will be referencing the original sour...
Definition: Array.h:372
Array_ & adoptData(T *newData, size_type dataSize, size_type dataCapacity)
This dangerous extension allows you to supply your own already-allocated heap space for use by this a...
Definition: Array.h:1934
~Array_()
The destructor performs a deallocate() operation which may result in element destruction and freeing ...
Definition: Array.h:1689
short difference_type
Definition: Array.h:181
T * begin()
Return a writable pointer to the first element of this array if any, otherwise end().
Definition: Array.h:1174
ArrayView_ updSubArray(index_type index, size_type length)
Same as non-const operator()(index,length); exists to provide non-operator access to that functionali...
Definition: Array.h:1148
static size_type max_size()
Definition: Array.h:224
ArrayViewConst_()
Default constructor allocates no heap space and is very fast.
Definition: Array.h:361
const T * end() const
The const version of end() is the same as cend().
Definition: Array.h:2163
T & reference
A writable value_type reference.
Definition: Array.h:331
const T * cbegin() const
Return a const pointer to the first element of this array if any, otherwise cend(), which may be null (0) in that case but does not have to be.
Definition: Array.h:2148
const T * cdata() const
Return a const pointer to the first element of the array, or possibly (but not necessarily) null (0) ...
Definition: Array.h:1215
T * erase(T *first, const T *last1)
Erase elements in range [first,last1), packing in any later elements into the newly-available space a...
Definition: Array.h:2404
static std::istream & readArrayFromStream(std::istream &in, Array_< T, X > &out)
Read in an Array_<T> from a stream, as a sequence of space-separated or comma-separated values option...
Definition: Array.h:3450
T & operator[](index_type i)
Select an element by its index, returning a writable (lvalue) reference.
Definition: Array.h:1067
X index_type
Definition: Array.h:838
Array_ & operator=(const std::vector< T2, A > &src)
This is assignment from a source std::vector<T2>.
Definition: Array.h:1910
This file contains macros which are convenient to use for sprinkling error checking around liberally ...
ArrayView_ & operator=(const ArrayView_ &src)
Copy assignment; source must be the same size as this array.
Definition: Array.h:906
Array_(size_type n, const T &initVal)
Construct an array containing n elements each set to a copy of the given initial value.
Definition: Array.h:1540
bool isOwner() const
Does this array own the data to which it refers? If not, it can't be resized, and the destructor will...
Definition: Array.h:2130
Array_ & adoptData(T *newData, size_type dataSize)
A variant of adoptData() that assumes the capacity is the same as the current size.
Definition: Array.h:1956
T * erase(T *p)
Erase just one element, moving all subsequent elements down one slot and reducing the array's size by...
Definition: Array.h:2439
int difference_type
Definition: Array.h:123
bool readUnformatted(std::istream &in, VectorView_< E > &v)
Read fixed-size VectorView from input stream.
Definition: BigMatrix.h:3325
ArrayViewConst_< T, X > getSubArray(index_type index, size_type length) const
Same as const form of operator()(index,length); exists to provide non-operator access to that functio...
Definition: Array.h:2282
const T * const_iterator
Definition: Array.h:844
size_type allocated() const
Return the amount of heap space owned by this array; this is the same as capacity() for owner arrays ...
Definition: Array.h:515
T & at(index_type i)
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:1079
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: Array.h:1507
const T * cbegin() const
Return a const pointer to the first element of this array if any, otherwise end(), which may be null (0) in that case but does not have to be.
Definition: Array.h:1167
ArrayView_ & operator=(const T &fillValue)
Fill assignment – all elements are set to fillValue.
Definition: Array.h:951
const T * begin() const
The const version of begin() is the same as cbegin().
Definition: Array.h:2150
void push_back()
This is a non-standard version of push_back() that increases the size of the array by one default-con...
Definition: Array.h:2349
static std::istream & fillArrayFromStream(std::istream &in, Array_< T, X > &out)
Read in a fixed number of elements from a stream into an Array.
Definition: Array.h:3480
reverse_iterator rbegin()
Return a writable reverse iterator pointing to the last element in the array or rend() if the array i...
Definition: Array.h:1196
const_reverse_iterator rend() const
The const version of rend() is the same as crend().
Definition: Array.h:2184
const_reverse_iterator rbegin() const
The const version of rbegin() is the same as crbegin().
Definition: Array.h:1193
static size_type max_size()
Definition: Array.h:171
T * insert(T *p, size_type n, const T &value)
Insert n copies of a given value at a particular location within this array, moving all following ele...
Definition: Array.h:2526
ArrayIndexTraits< X >::difference_type difference_type
Definition: Array.h:1509
short difference_type
Definition: Array.h:170
void assign(const T2 *first, const T2 *last1)
Assign to this array to make it a copy of the elements in range [first,last1) given by ordinary point...
Definition: Array.h:996
The SimTK::Array_<T> container class is a plug-compatible replacement for the C++ standard template l...
Definition: Array.h:50
T * end()
Return a writable pointer to what would be the element just after the last one in this array...
Definition: Array.h:1187
#define SimTK_ERRCHK_ALWAYS(cond, whereChecked, msg)
Definition: ExceptionMacros.h:281
ArrayIndexPackType< size_type >::packed_size_type packed_size_type
Definition: Array.h:1511
const T * cend() const
Return a const pointer to what would be the element just after the last one in the array; this may be...
Definition: Array.h:2161
ArrayIndexPackType< size_type >::packed_size_type packed_size_type
The integral type we actually use internally to store size_type values.
Definition: Array.h:349
const T * data() const
The const version of the data() method is identical to cdata().
Definition: Array.h:1218
const T & getElt(index_type i) const
Same as the const form of operator[]; exists to provide a non-operator method for element access in c...
Definition: Array.h:1083
void disconnect()
Forward to base class disconnect() method – clears the handle without doing anything to the data...
Definition: Array.h:884
bool empty() const
Return true if there are no elements currently stored in this array.
Definition: Array.h:506
const T & operator[](index_type i) const
Select an element by its index, returning a const reference.
Definition: Array.h:2218
T & front()
Return a writable reference to the first element in this array, which must not be empty...
Definition: Array.h:1100
signed char difference_type
Definition: Array.h:192
#define SimTK_ERRCHK3_ALWAYS(cond, whereChecked, fmt, a1, a2, a3)
Definition: ExceptionMacros.h:293
long long size_type
Definition: Array.h:231
const T & const_reference
Definition: Array.h:842
ELEM max(const VectorBase< ELEM > &v)
Definition: VectorMath.h:251
const_reverse_iterator rbegin() const
The const version of rbegin() is the same as crbegin().
Definition: Array.h:645
std::reverse_iterator< iterator > reverse_iterator
Definition: Array.h:845
ArrayView_ & operator=(const Array_< T2, X2 > &src)
Assignment from any other array object is allowed as long as the number of elements matches and the t...
Definition: Array.h:937
T * data()
Return a writable pointer to the first allocated element of the array, or a null pointer if no space ...
Definition: Array.h:1222
static size_type max_size()
Definition: Array.h:161
const T * const_pointer
Definition: Array.h:1501
void assign(size_type n, const T &fillValue)
This is the same as fill() but has the usual std::vector signature for compatibility; it will only wo...
Definition: Array.h:968
const T * const_pointer
A const pointer to a value_type.
Definition: Array.h:329
bool operator>=(const ArrayViewConst_< T1, X1 > &a1, const ArrayViewConst_< T2, X2 > &a2)
The greater than or equal operator is implemented using the less than operator.
Definition: Array.h:3568
void reserve(size_type n)
Ensure that this array has enough allocated capacity to hold the indicated number of elements...
Definition: Array.h:2074
T value_type
Definition: Array.h:1498
ArrayViewConst_ getSubArray(index_type index, size_type length) const
Same as const form of operator()(index,length); exists to provide non-operator access to that functio...
Definition: Array.h:606
bool operator!=(const ArrayViewConst_< T1, X1 > &a1, const std::vector< T2, A2 > &v2)
The not equal operator is implemented using the equal operator.
Definition: Array.h:3599
const T & const_reference
Definition: Array.h:1503
static size_type max_size()
Definition: Array.h:150
long long difference_type
Definition: Array.h:223
ArrayIndexTraits< X >::difference_type difference_type
Definition: Array.h:848
unsigned char size_type
Definition: Array.h:180
bool isOwner() const
Definition: Array.h:1243
size_type max_size() const
Definition: Array.h:1239
const T & getElt(index_type i) const
Same as the const form of operator[]; exists to provide a non-operator method for element access in c...
Definition: Array.h:2243
std::ostream & operator<<(std::ostream &o, const ContactForce &f)
Definition: CompliantContactSubsystem.h:387
int size_type
Definition: Array.h:122
bool operator>(const std::vector< T1, A1 > &v1, const ArrayViewConst_< T2, X2 > &a2)
The greater than operator is implemented by using less than with the arguments reversed, meaning the elements must have working comparison operators of the form T2==T1 and T2<T1.
Definition: Array.h:3646
unsigned short size_type
Definition: Array.h:159
std::reverse_iterator< iterator > reverse_iterator
A writable reverse iterator for this container.
Definition: Array.h:339
static size_type max_size()
Definition: Array.h:117
void swap(Array_ &other)
This is a specialized algorithm providing constant time exchange of data with another array that has ...
Definition: Array.h:1923
#define SimTK_INDEXCHECK_ALWAYS(ix, ub, where)
Definition: ExceptionMacros.h:106
void writeFormatted(std::ostream &o, const Array_< T, X > &v)
Specialize writeFormatted() for Array_<E,X> to delegate to element type E, with surrounding parenthes...
Definition: Array.h:3345
#define SimTK_ERRCHK(cond, whereChecked, msg)
Definition: ExceptionMacros.h:324
long difference_type
Definition: Array.h:136
T * end()
Return a writable pointer to what would be the element just after the last one in this array...
Definition: Array.h:2168
#define SimTK_ERRCHK2(cond, whereChecked, fmt, a1, a2)
Definition: ExceptionMacros.h:328
This Array_ helper class is the base class for ArrayView_ which is the base class for Array_; here we...
Definition: Array.h:48
const_reverse_iterator crend() const
Return the past-the-end reverse iterator that tests equal to a reverse iterator that has been increme...
Definition: Array.h:1201
T & back()
Return a writable reference to the last element in this array, which must not be empty.
Definition: Array.h:2274
ArrayViewConst_ operator()(index_type index, size_type length) const
Select a contiguous subarray of the elements of this array and create another ArrayViewConst_ that re...
Definition: Array.h:592
Array_()
Default constructor allocates no heap space and is very fast.
Definition: Array.h:1524
void swap(SimTK::Array_< T, X > &a1, SimTK::Array_< T, X > &a2)
This is a specialization of the STL std::swap() algorithm which uses the constant time built-in swap(...
Definition: Array.h:3669
const T & operator[](index_type i) const
Select an element by its index, returning a const reference.
Definition: Array.h:1058
Array_(T *first, const T *last1, const DontCopy &)
Construct an Array_<T> by referencing (sharing) a given range of data [first,last1), without copying that data; better to use the corresponding ArrayView_<T> constructor if you can.
Definition: Array.h:1654
const_reverse_iterator crbegin() const
Return a const reverse iterator pointing to the last element in the array or crend() if the array is ...
Definition: Array.h:2172
bool operator>=(const ArrayViewConst_< T1, X1 > &a1, const std::vector< T2, A2 > &v2)
The greater than or equal operator is implemented using the less than operator.
Definition: Array.h:3628
Mandatory first inclusion for any Simbody source or header file.
reverse_iterator rend()
Return a writable past-the-end reverse iterator that tests equal to a reverse iterator that has been ...
Definition: Array.h:2188
X index_type
Definition: Array.h:1499
const_reverse_iterator crbegin() const
Return a const reverse iterator pointing to the last element in the array or crend() if the array is ...
Definition: Array.h:639
Array_ & deallocate()
Empty this array of its contents, returning the array to its default-constructed, all-zero state...
Definition: Array.h:1701
This file contains definitions of templatized serialize-to-stream methods specialized for the built-i...
void clear()
Erase all the elements currently in this array without changing the capacity; equivalent to erase(beg...
Definition: Array.h:2492
const T * begin() const
The const version of begin() is the same as cbegin().
Definition: Array.h:1169
const T * cend() const
Return a const pointer to what would be the element just after the last one in the array; this may be...
Definition: Array.h:631
#define SimTK_INDEXCHECK(ix, ub, where)
Definition: ExceptionMacros.h:145
const_reverse_iterator crend() const
Return the past-the-end reverse iterator that tests equal to a reverse iterator that has been increme...
Definition: Array.h:2182
ArrayViewConst_(const T *first, const T *last1)
Construct an ArrayViewConst_<T> by referencing (sharing) a given range of const data [first...
Definition: Array.h:401
long difference_type
Definition: Array.h:149
X index_type
The index type (an extension).
Definition: Array.h:325
size_type allocated() const
Definition: Array.h:1242
T * iterator
Definition: Array.h:1504
bool operator==(const ArrayViewConst_< T1, X1 > &a1, const ArrayViewConst_< T2, X2 > &a2)
Two Array_ objects are equal if and only if they are the same size() and each element compares equal ...
Definition: Array.h:3531
ArrayIndexTraits< X >::size_type size_type
An integral type suitable for all indices and sizes for this array.
Definition: Array.h:343
void assign(const Iter &first, const Iter &last1)
Assign to this array to make it a copy of the elements in range [first,last1) given by non-pointer it...
Definition: Array.h:1038
Array_(const Array_ &src)
Copy constructor allocates exactly as much memory as is in use in the source (not its capacity) and c...
Definition: Array.h:1608
signed char difference_type
Definition: Array.h:215
T & updElt(index_type i)
Same as the non-const form of operator[]; exists to provide a non-operator method for element access ...
Definition: Array.h:1086
const T * const_pointer
Definition: Array.h:840
std::istream & operator>>(std::istream &in, ArrayView_< T, X > &out)
Read a (fixed size n) ArrayView_<T> from a stream as a sequence of space- or comma-separated values o...
Definition: Array.h:3515
static size_type max_size()
Definition: Array.h:182
const T * const_iterator
Definition: Array.h:1505
X::difference_type difference_type
A signed integral type large enough to hold the full range of possible signed differences i-j between...
Definition: Array.h:106
bool operator!=(const ArrayViewConst_< T1, X1 > &a1, const ArrayViewConst_< T2, X2 > &a2)
The not equal operator is implemented using the equal operator.
Definition: Array.h:3545
T * begin()
Return a writable pointer to the first element of this array if any, otherwise end().
Definition: Array.h:2155
T * insert(T *p, const Iter &first, const Iter &last1)
Insert elements in a range [first,last1) where the range is given by non-pointer iterators.
Definition: Array.h:2591
T & reference
Definition: Array.h:841
const T & front() const
Return a const reference to the first element in this array, which must not be empty (we'll check in ...
Definition: Array.h:562
static size_type max_size()
Definition: Array.h:124
const T * cdata() const
Return a const pointer to the first element of the array, or possibly (but not necessarily) null (0) ...
Definition: Array.h:655
reverse_iterator rend()
Return a writable past-the-end reverse iterator that tests equal to a reverse iterator that has been ...
Definition: Array.h:1207
bool readFormatted(std::istream &in, ArrayView_< T, X > &v)
Specialization of readFormatted() for fixed-length ArrayView_<T,X>; uses fillArrayViewFromStream() to...
Definition: Array.h:3416
const T & at(index_type i) const
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:2233
const T * const_iterator
A const iterator for this container (same as const_pointer here).
Definition: Array.h:337
ArrayView_ & fill(const T &fillValue)
Assign the supplied fill value to each element of this array, using T's copy assignment operator for ...
Definition: Array.h:959
const T & back() const
Return a const reference to the last element in this array, which must not be empty (we'll check in a...
Definition: Array.h:570
T * eraseFast(T *p)
Be careful with this non-standard extension; it erases one element and then moves the last one in its...
Definition: Array.h:2472
void disconnect()
Disconnect this array handle from any data to which it refers, restoring it to the condition it would...
Definition: Array.h:477
ArrayView_< T, X > updSubArray(index_type index, size_type length)
Same as non-const operator()(index,length); exists to provide non-operator access to that functionali...
Definition: Array.h:2291
Array_(std::vector< T, A > &v, const DontCopy &)
Construct an Array_<T> by referencing (sharing) the data in an std::vector<T>, without copying the da...
Definition: Array.h:1684
size_type capacity() const
Definition: Array.h:1241
signed char size_type
Definition: Array.h:191
void resize(size_type n, const T &initVal)
Change the size of this array, preserving all the elements that will still fit, and initializing any ...
Definition: Array.h:2051
bool operator>=(const std::vector< T1, A1 > &v1, const ArrayViewConst_< T2, X2 > &a2)
The greater than or equal operator is implemented using the less than operator.
Definition: Array.h:3633
T & front()
Return a writable reference to the first element in this array, which must not be empty...
Definition: Array.h:2260
int difference_type
Definition: Array.h:160
ArrayView_ operator()(index_type index, size_type length)
Select a contiguous subarray of the elements of this array and create another ArrayView_ that refers ...
Definition: Array.h:1134
size_type capacity() const
Return the number of elements this array can currently hold without requiring reallocation.
Definition: Array.h:511
ArrayView_ & operator=(const ArrayView_< T2, X2 > &src)
Assignment from any other array object is allowed as long as the number of elements matches and the t...
Definition: Array.h:932
void shrink_to_fit()
Request that the capacity of this array be reduced to the minimum necessary to hold the number of ele...
Definition: Array.h:2109
Array_ & operator=(const Array_ &src)
Copy assignment operator destructs the current contents of this array and then makes it a copy of the...
Definition: Array.h:1883
void push_back(const T &value)
This method increases the size of the Array by one element at the end and initializes that element by...
Definition: Array.h:2329
T & updElt(index_type i)
Same as the non-const form of operator[]; exists to provide a non-operator method for element access ...
Definition: Array.h:2246
size_type max_size() const
Return the maximum allowable size for this array.
Definition: Array.h:503
bool readFormatted(std::istream &in, Array_< T, X > &v)
Specialization of readFormatted() for variable-length Array_<T,X>; uses readArrayFromStream() to cons...
Definition: Array.h:3406
std::reverse_iterator< const_iterator > const_reverse_iterator
A const reverse iterator for this container.
Definition: Array.h:341
ArrayViewConst_< T, X > operator()(index_type index, size_type length) const
Select a subrange of this const array by starting index and length, and return a ArrayViewConst_ refe...
Definition: Array.h:2278
Array_ & shareData(T *newData, size_type dataSize)
This dangerous extension allows you to make this array handle refer to someone else's data without co...
Definition: Array.h:1973
T & operator[](index_type i)
Select an element by its index, returning a writable (lvalue) reference.
Definition: Array.h:2227
bool operator==(const std::vector< T1, A1 > &v1, const ArrayViewConst_< T2, X2 > &a2)
An std::vector<T1> and an Array_<T2> are equal if and only if they are the same size() and each eleme...
Definition: Array.h:3593
~ArrayView_()
The destructor just disconnects the array view handle from its data; see ArrayViewConst_<T,X>::disconnect() for more information.
Definition: Array.h:888
T * pointer
Definition: Array.h:839
ArrayView_(T *first, const T *last1)
Construct from a range of writable memory.
Definition: Array.h:868
void assign(const Iter &first, const Iter &last1)
Assign this array from a range [first,last1) given by non-pointer iterators.
Definition: Array.h:1873
Array_ & shareData(T *first, const T *last1)
Same as shareData(data,size) but uses a pointer range [first,last1) to identify the data to be refere...
Definition: Array.h:1990
T * data()
Return a writable pointer to the first allocated element of the array, or a null pointer if no space ...
Definition: Array.h:2203
const T & getElt(index_type i) const
Same as the const form of operator[]; exists to provide a non-operator method for element access in c...
Definition: Array.h:553
ArrayView_< T, X > operator()(index_type index, size_type length)
Select a subrange of this array by starting index and length, and return an ArrayView_ referencing th...
Definition: Array.h:2287
size_type capacity() const
Return the number of elements this array can currently hold without requiring reallocation.
Definition: Array.h:2024
static size_type max_size()
Definition: Array.h:137
const_reverse_iterator crbegin() const
Return a const reverse iterator pointing to the last element in the array or crend() if the array is ...
Definition: Array.h:1191
static size_type max_size()
The maximum allowable size for any Array_<T,X> that uses this type X as its index type...
Definition: Array.h:109
static std::istream & readArrayFromStreamHelper(std::istream &in, bool isFixedSize, Array_< T, X > &out)
Definition: Array.h:3144
size_type max_size() const
Return the maximum allowable size for this array.
Definition: Array.h:2016
bool empty() const
Return true if there are no elements currently stored in this array.
Definition: Array.h:2019
short size_type
Definition: Array.h:169
const T & back() const
Return a const reference to the last element in this array, which must not be empty.
Definition: Array.h:1107
static std::istream & fillArrayViewFromStream(std::istream &in, ArrayView_< T, X > &out)
Read in a fixed number of elements from a stream into an ArrayView.
Definition: Array.h:3488
X::size_type size_type
The signed or unsigned integral type to which an object of index type X can be converted without prod...
Definition: Array.h:103
std::istream & operator>>(std::istream &in, Array_< T, X > &out)
Read an Array_<T> from a stream as a sequence of space- or comma-separated values of type T...
Definition: Array.h:3504
void writeFormatted(std::ostream &o, const T &v)
The default implementation of writeFormatted<T> converts the object to a String using the templatized...
Definition: Serialize.h:312
void writeUnformatted(std::ostream &o, const T &v)
The default implementation of writeUnformatted<T> converts the object to a String using the templatiz...
Definition: Serialize.h:75
ArrayView_(const ArrayView_ &src)
Copy constructor is shallow.
Definition: Array.h:865
const T * data() const
The const version of the data() method is identical to cdata().
Definition: Array.h:657
const T * cbegin() const
Return a const pointer to the first element of this array if any, otherwise cend(), which may be null (0) in that case but does not have to be.
Definition: Array.h:626
Array_(const T2 *first, const T2 *last1)
Construct an Array_<T> from a range [first,last1) of values identified by a pair of ordinary pointers t...
Definition: Array.h:1572
T * insert(T *p, const T2 *first, const T2 *last1)
Insert elements in a range [first,last1) into this array at a given position p, moving all following ...
Definition: Array.h:2576
ArrayView_ & operator=(const std::vector< T2, A2 > &src)
Assignment from any std::vector object is allowed as long as the number of elements matches and the t...
Definition: Array.h:943