Simbody 3.7
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-15 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#include <type_traits>
44#include <initializer_list>
45#include <utility>
46
47namespace SimTK {
48
49// These are the classes defined in this header.
50template <class X> struct ArrayIndexTraits;
51template <class T, class X=unsigned> class ArrayViewConst_;
52template <class T, class X=unsigned> class ArrayView_;
53template <class T, class X=unsigned> class Array_;
54
55namespace Xml {
56class Element;
57}
58
59// NOTE: I have attempted to force the compilers to inline certain trivial
60// methods here because I observed Visual C++ 2013 fail to inline operator[]
61// in a performance-critical method (getCacheEntry() to be specific). It is
62// essential that there be no overhead introduced by the Array_ classes, which
63// Simbody uses extensively specifically because std::vector was too slow.
64// (sherm 20140404).
65
66//==============================================================================
67// CLASS ArrayIndexTraits
68//==============================================================================
69
112template <class X> struct ArrayIndexTraits {
115 typedef typename X::size_type size_type;
118 typedef typename X::difference_type difference_type;
121 static size_type max_size() {return X::max_size();}
122};
123
126template <> struct ArrayIndexTraits<unsigned> {
127 typedef unsigned size_type;
128 typedef int difference_type;
129 static size_type max_size() {return (unsigned)INT_MAX;}
130};
131
133template <> struct ArrayIndexTraits<int> {
134 typedef int size_type;
135 typedef int difference_type;
136 static size_type max_size() {return INT_MAX;}
137};
138
146template <> struct ArrayIndexTraits<unsigned long> {
147 typedef unsigned long size_type;
148 typedef long difference_type;
149 static size_type max_size() {return (unsigned long)LONG_MAX;}
150};
151
159template <> struct ArrayIndexTraits<long> {
160 typedef long size_type;
161 typedef long difference_type;
162 static size_type max_size() {return LONG_MAX;}
163};
164
170template <> struct ArrayIndexTraits<unsigned short> {
171 typedef unsigned short size_type;
172 typedef int difference_type;
173 static size_type max_size() {return USHRT_MAX;}
174};
175
180template <> struct ArrayIndexTraits<short> {
181 typedef short size_type;
182 typedef short difference_type;
183 static size_type max_size() {return SHRT_MAX;}
184};
185
186
191template <> struct ArrayIndexTraits<unsigned char> {
192 typedef unsigned char size_type;
193 typedef short difference_type;
194 static size_type max_size() {return UCHAR_MAX;} // not CHAR_MAX
195};
196
202template <> struct ArrayIndexTraits<signed char> {
203 typedef signed char size_type;
204 typedef signed char difference_type;
205 static size_type max_size() {return SCHAR_MAX;}
206};
207
214template <> struct ArrayIndexTraits<char> {
215 typedef char size_type;
216 typedef signed char difference_type;
217 static size_type max_size() {return (char)SCHAR_MAX;}
218};
219
225template <> struct ArrayIndexTraits<bool> {
226 typedef unsigned char size_type;
227 typedef signed char difference_type;
228 static size_type max_size() {return 2;}
229};
230
233template <> struct ArrayIndexTraits<unsigned long long> {
234 typedef unsigned long long size_type;
235 typedef long long difference_type;
237 {return (unsigned long long)LLONG_MAX;}
238};
239
242template <> struct ArrayIndexTraits<long long> {
243 typedef long long size_type;
244 typedef long long difference_type;
245 static size_type max_size() {return LLONG_MAX;}
246};
247
248// Don't show this in Doxygen.
250// This helper class decides what integral type we should use to best pack
251// the index type's size_type representation. The idea is to pack the whole
252// Array_ structure into 8 bytes on a 32 bit machine, 16 bytes on a 64 bit
253// machine, using the largest integral type that will work, giving a layout
254// like this: | data pointer |
255// | nUsed | nAllocated |
256
257// The default implementation just uses the integral type itself.
258template <class Integral, class is64Bit> struct ArrayIndexPackTypeHelper
259{ typedef Integral packed_size_type;};
260
261// On 32 bit machine, pack anything smaller than a short into a short.
262template<> struct ArrayIndexPackTypeHelper<bool,FalseType>
263{ typedef unsigned short packed_size_type;};
264template<> struct ArrayIndexPackTypeHelper<char,FalseType>
265{ typedef unsigned short packed_size_type;};
266template<> struct ArrayIndexPackTypeHelper<unsigned char,FalseType>
267{ typedef unsigned short packed_size_type;};
268template<> struct ArrayIndexPackTypeHelper<signed char,FalseType>
269{ typedef short packed_size_type;};
270
271// On 64 bit machine, pack anything smaller than an int into an int.
272template<> struct ArrayIndexPackTypeHelper<bool,TrueType>
273{ typedef unsigned int packed_size_type;};
274template<> struct ArrayIndexPackTypeHelper<char,TrueType>
275{ typedef unsigned int packed_size_type;};
276template<> struct ArrayIndexPackTypeHelper<unsigned char,TrueType>
277{ typedef unsigned int packed_size_type;};
278template<> struct ArrayIndexPackTypeHelper<signed char,TrueType>
279{ typedef int packed_size_type;};
280template<> struct ArrayIndexPackTypeHelper<unsigned short,TrueType>
281{ typedef unsigned int packed_size_type;};
282template<> struct ArrayIndexPackTypeHelper<short,TrueType>
283{ typedef int packed_size_type;};
284
285template <class Integral> struct ArrayIndexPackType
286{ typedef typename ArrayIndexPackTypeHelper<Integral,Is64BitPlatformType>
287 ::packed_size_type packed_size_type;};
295//==============================================================================
296// CLASS ArrayViewConst_
297//==============================================================================
324template <class T, class X> class ArrayViewConst_ {
325public:
326
327
328//------------------------------------------------------------------------------
335typedef T value_type;
337typedef X index_type;
339typedef T* pointer;
341typedef const T* const_pointer;
343typedef T& reference;
345typedef const T& const_reference;
347typedef T* iterator;
349typedef const T* const_iterator;
351typedef std::reverse_iterator<iterator> reverse_iterator;
353typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
360typedef typename ArrayIndexPackType<size_type>::packed_size_type
365//------------------------------------------------------------------------------
371
373ArrayViewConst_() : pData(0), nUsed(0), nAllocated(0) {}
374
385: pData(0), nUsed(src.nUsed), nAllocated(0) {
386 if (nUsed) pData = const_cast<T*>(src.pData);
387}
388
389// Copy assignment is suppressed.
390
413ArrayViewConst_(const T* first, const T* last1)
414: pData(0),nUsed(0),nAllocated(0) {
415 if (last1==first) return; // empty
416
417 SimTK_ERRCHK((first&&last1)||(first==last1),
418 "ArrayViewConst_<T>(first,last1)",
419 "One of the source pointers was null (0); either both must be"
420 " non-null or both must be null.");
421
422 SimTK_ERRCHK3(this->isSizeOK(last1-first),
423 "ArrayViewConst_<T>(first,last1)",
424 "The source data's size %llu is too big for this array which"
425 " is limited to %llu elements by its index type %s.",
426 this->ull(last1-first), ullMaxSize(), indexName());
427
428 pData = const_cast<T*>(first);
429 nUsed = packed_size_type(last1-first);
430 // nAllocated is already zero
431}
432
460template <class A>
461ArrayViewConst_(const std::vector<T,A>& src)
462: pData(0),nUsed(0),nAllocated(0) {
463 if (src.empty()) return;
464
465 SimTK_ERRCHK3(this->isSizeOK(src.size()),
466 "ArrayViewConst_<T>::ctor(std::vector<T>)",
467 "The source std::vector's size %llu is too big for this array which"
468 " is limited to %llu elements by its index type %s.",
469 this->ull(src.size()), ullMaxSize(), indexName());
470
471 pData = const_cast<T*>(&src.front());
472 nUsed = packed_size_type(src.size());
473 // nAllocated is already zero
474}
477operator const ArrayView_<T,X>&() const
478{ return *reinterpret_cast<const ArrayView_<T,X>*>(this); }
481operator const Array_<T,X>&() const
482{ return *reinterpret_cast<const Array_<T,X>*>(this); }
483
490 SimTK_ASSERT(nAllocated==0,
491 "ArrayViewConst_::deallocate(): called on an owner Array_");
492 nUsed = 0;
493 pData = 0;
494}
495
499 disconnect();
500}
504//------------------------------------------------------------------------------
511
513size_type size() const {return size_type(nUsed);}
519bool empty() const {return nUsed==0;}
525{ return size_type(nAllocated?nAllocated:nUsed); }
529size_type allocated() const {return size_type(nAllocated);}
535bool isOwner() const {return nAllocated || pData==0;}
536/*}*/
537
538
539//------------------------------------------------------------------------------
546
555 SimTK_INDEXCHECK(size_type(i),size(),"ArrayViewConst_<T>::operator[]()");
556 return pData[i];
557}
562const T& at(index_type i) const {
563 SimTK_INDEXCHECK_ALWAYS(size_type(i),size(),"ArrayViewConst_<T>::at()");
564 return pData[i];
565}
569 SimTK_INDEXCHECK(size_type(i),size(),"ArrayViewConst_<T>::getElt()");
570 return pData[i];
571}
577SimTK_FORCE_INLINE const T& front() const
578{ SimTK_ERRCHK(!empty(), "ArrayViewConst_<T>::front()", "Array was empty.");
579 return pData[0]; }
585SimTK_FORCE_INLINE const T& back() const
586{ SimTK_ERRCHK(!empty(), "ArrayViewConst_<T>::back()", "Array was empty.");
587 return pData[nUsed-1]; }
588
608 const size_type ix(index);
609 SimTK_ERRCHK2(isSizeInRange(ix, size()), "ArrayViewConst_<T>(index,length)",
610 "For this operator, we must have 0 <= index <= size(), but"
611 " index==%llu and size==%llu.", this->ull(ix), ullSize());
613 "ArrayViewConst_<T>(index,length)",
614 "This operator requires 0 <= length <= size()-index, but"
615 " length==%llu and size()-index==%llu.",this->ull(length),this->ull(size()-ix));
616
617 return ArrayViewConst_(pData+ix, pData+ix+length);
618}
622{ return (*this)(index,length); }
623
627//------------------------------------------------------------------------------
636
641const T* cbegin() const {return pData;}
646const T* cend() const {return pData + nUsed;}
648const T* begin() const {return pData;}
650const T* end() const {return pData + nUsed;}
651
655{ return const_reverse_iterator(cend()); }
660{ return const_reverse_iterator(cbegin()); }
665
672const T* cdata() const {return pData;}
674const T* data() const {return pData;}
678//------------------------------------------------------------------------------
679 protected:
680//------------------------------------------------------------------------------
681// The remainder of this class is for the use of the ArrayView_<T,X> and
682// Array_<T,X> derived classes only and should not be documented for users to
683// see.
684
685// Don't let doxygen see any of this.
687packed_size_type psize() const {return nUsed;}
688packed_size_type pallocated() const {return nAllocated;}
689
690// These provide direct access to the data members for our trusted friends.
691void setData(const T* p) {pData = const_cast<T*>(p);}
692void setSize(size_type n) {nUsed = packed_size_type(n);}
693void incrSize() {++nUsed;}
694void decrSize() {--nUsed;}
695void setAllocated(size_type n) {nAllocated = packed_size_type(n);}
696
697// Check whether a given size is the same as the current size of this array,
698// avoiding any compiler warnings due to mismatched integral types.
699template <class S>
700bool isSameSize(S sz) const
701{ return ull(sz) == ullSize(); }
702
703// Check that a source object's size will fit in the array being careful to
704// avoid overflow and warnings in the comparison.
705template <class S>
706bool isSizeOK(S srcSz) const
707{ return ull(srcSz) <= ullMaxSize(); }
708
709// This is identical in function to std::distance() (reports how many
710// elements lie between two iterators) but avoids any slow
711// Release-build bugcatchers that Microsoft may have felt compelled to add.
712// The implementation is specialized for random access iterators because
713// they can measure distance very fast.
714template<class Iter> static
715typename std::iterator_traits<Iter>::difference_type
716iterDistance(const Iter& first, const Iter& last1) {
717 return iterDistanceImpl(first,last1,
718 typename std::iterator_traits<Iter>::iterator_category());
719}
720
721// Generic slow implementation for non-random access iterators. This is fine
722// for forward and bidirectional iterators, but it will *consume* input
723// iterators so is useless for them.
724template<class Iter> static
725typename std::iterator_traits<Iter>::difference_type
726iterDistanceImpl(const Iter& first, const Iter& last1, std::input_iterator_tag) {
727 typename std::iterator_traits<Iter>::difference_type d = 0;
728 for (Iter src=first; src != last1; ++src, ++d)
729 ;
730 return d;
731}
732
733// Fast specialization for random access iterators (including ordinary
734// pointers) -- just subtract.
735template<class Iter> static
736typename std::iterator_traits<Iter>::difference_type
737iterDistanceImpl(const Iter& first, const Iter& last1,
738 std::random_access_iterator_tag) {
739 return last1 - first;
740}
741
742// This method attempts to determine whether any elements in the iterator range
743// [first,last1) overlap with the elements stored in this array. This is used
744// for error checks for operations where source is not permitted to overlap the
745// destination. For random access iterators (including ordinary pointers), we
746// can answer this question definitively because we expect the data to be
747// consecutive in memory. For other kinds of iterators, we will just assume
748// there is no overlap. Note that null ranges do not overlap even if the
749// pair of equal iterators points within the other range -- what matters is
750// the number of overlapping elements.
751template<class Iter> bool
752overlapsWithData(const Iter& first, const Iter& last1) {
753 return overlapsWithDataImpl(first,last1,
754 typename std::iterator_traits<Iter>::iterator_category());
755}
756
757// This is a partial specialization of the above where the data is given
758// with ordinary pointers.
759template <class T2> bool
760overlapsWithData(const T2* first, const T2* last1) {
761 // Find the start and end+1 of the alleged overlap region. There is
762 // overlap iff end+1 > start. Note that this works if either range
763 // is [0,0) or [p,p), or if last1 is illegally less than first (we just
764 // want to report no overlap in that case -- it is someone else's business
765 // to complain).
766 const T* obegin = std::max(cbegin(), (const T*)first);
767 const T* oend1 = std::min(cend(), (const T*)last1);
768
769 return obegin < oend1;
770}
771
772// This is the generic implementation for any type of input iterator other than
773// random access (i.e., bidirectional, forward, or input) -- assume no overlap.
774template<class Iter> bool
775overlapsWithDataImpl(const Iter&, const Iter&, std::input_iterator_tag)
776{ return false; }
777
778// Here we can actually test for overlap since we have random access iterators.
779// We convert them to pointers and then look for memory overlap.
780template<class Iter> bool
781overlapsWithDataImpl(const Iter& first, const Iter& last1,
782 std::random_access_iterator_tag) {
783 // We must check that the input iterators span a non-zero range before
784 // assuming we can dereference them.
785 if (last1 <= first)
786 return false; // zero or malformed source range: no overlap
787
788 // We now know we can dereference first and last1-1 (can't safely
789 // dereference last1 but we can use pointer arithmetic to point past
790 // the (last-1)th element in memory). We then take the dereferenced
791 // object's address to get ordinary pointers that we can use to
792 // watch for illegal overlap.
793 return overlapsWithData(&*first, &*(last1-1)); // use pointer overload
794}
795
796// Cast an integral type to maximal-width unsigned long long to avoid accidental
797// overflows that might otherwise occur due to wraparound that can happen
798// with small index types.
799template <class S>
800static unsigned long long ull(S sz)
801{ return (unsigned long long)sz; }
802
803// Return size(), capacity(), and max_size() cast to unsigned long long.
804unsigned long long ullSize() const {return ull(size());}
805unsigned long long ullCapacity() const {return ull(capacity());}
806unsigned long long ullMaxSize() const {return ull(max_size());}
807
808// Useful in error messages for explaining why something was too big.
809const char* indexName() const {return NiceTypeName<X>::name();}
810
813private:
814//------------------------------------------------------------------------------
815// DATA MEMBERS
816// These are the only data members and this layout is guaranteed not to change
817// from release to release. If data is null, then nUsed==nAllocated==0.
818
819T* pData; // ptr to data referenced here, or 0 if none
820packed_size_type nUsed; // number of elements currently present (size)
821packed_size_type nAllocated; // heap allocation; 0 if pData is not owned
822
823ArrayViewConst_& operator=(const ArrayViewConst_& src); // suppressed
824};
825
826
827
828
829
830
831//==============================================================================
832// CLASS ArrayView_
833//==============================================================================
845template <class T, class X> class ArrayView_ : public ArrayViewConst_<T,X> {
847public:
848//------------------------------------------------------------------------------
853/*{*/
854typedef T value_type;
855typedef X index_type;
856typedef T* pointer;
857typedef const T* const_pointer;
858typedef T& reference;
859typedef const T& const_reference;
860typedef T* iterator;
861typedef const T* const_iterator;
862typedef std::reverse_iterator<iterator> reverse_iterator;
863typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
866typedef typename ArrayIndexPackType<size_type>::packed_size_type
868/*}*/
869
870
871//------------------------------------------------------------------------------
877
880
882ArrayView_(const ArrayView_& src) : CBase(src) {}
883
885ArrayView_(T* first, const T* last1) : CBase(first,last1) {}
886
888template <class A>
889ArrayView_(std::vector<T,A>& v) : CBase(v) {}
890
892operator const Array_<T,X>&() const
893{ return *reinterpret_cast<const Array_<T,X>*>(this); }
894
896operator Array_<T,X>&()
897{ return *reinterpret_cast<Array_<T,X>*>(this); }
898
902
909//------------------------------------------------------------------------------
921
924 if (&src != this)
925 avAssignIteratorDispatch(src.cbegin(), src.cend(),
926 std::random_access_iterator_tag(),
927 "ArrayView_<T>::operator=(ArrayView_<T>)");
928 return *this;
929}
930
931
934template <class T2, class X2>
936 if ((const void*)&src != (void*)this)
937 avAssignIteratorDispatch(src.cbegin(), src.cend(),
938 std::random_access_iterator_tag(),
939 "ArrayView_<T>::operator=(Array_<T2>)");
940 return *this;
941}
942
943// Help out dumb compilers struggling to match the template arguments and
944// promote the Array_ or ArrayView_ to ArrayConstView_ at the same time.
945
948template <class T2, class X2>
950{ return *this = static_cast<const ArrayViewConst_<T2,X2>&>(src); }
953template <class T2, class X2>
955{ return *this = static_cast<const ArrayViewConst_<T2,X2>&>(src); }
956
959template <class T2, class A2>
960ArrayView_& operator=(const std::vector<T2,A2>& src) {
961 avAssignIteratorDispatch(src.begin(), src.end(),
962 std::random_access_iterator_tag(),
963 "ArrayView_<T>::operator=(std::vector<T2>)");
964 return *this;
965}
966
968ArrayView_& operator=(const T& fillValue)
969{ fill(fillValue); return *this; }
970
976ArrayView_& fill(const T& fillValue) {
977 for (T* d = begin(); d != end(); ++d)
978 *d = fillValue; // using T::operator=(T)
979 return *this;
980}
981
985void assign(size_type n, const T& fillValue) {
986 SimTK_ERRCHK2(n == size(), "ArrayView_<T>::assign(n,value)",
987 "Assignment to an ArrayView is permitted only if the source"
988 " is the same size. Here n==%llu element(s) but the"
989 " ArrayView has a fixed size of %llu.",
990 this->ull(n), this->ull(size()));
991
992 fill(fillValue);
993}
994
1012template <class T2>
1013void assign(const T2* first, const T2* last1) {
1014 const char* methodName = "ArrayView_<T>::assign(T2* first, T2* last1)";
1015 SimTK_ERRCHK((first&&last1)||(first==last1), methodName,
1016 "One of the source pointers was null (0); either both must be"
1017 " non-null or both must be null.");
1018 // Valid pointers are random access iterators.
1019 avAssignIteratorDispatch(first, last1, std::random_access_iterator_tag(),
1020 methodName);
1021}
1022
1052// Watch out for integral types matching this signature -- they must be
1053// forwarded to the assign(n, fillValue) signature instead.
1054template <class Iter>
1055void assign(const Iter& first, const Iter& last1)
1056{ avAssignDispatch(first,last1,typename IsIntegralType<Iter>::Result(),
1057 "ArrayView_<T>::assign(Iter first, Iter last1)"); }
1061//------------------------------------------------------------------------------
1068
1076{ return this->CBase::operator[](i); }
1077
1086{ return const_cast<T&>(this->CBase::operator[](i)); }
1087
1092const T& at(index_type i) const {return this->CBase::at(i);}
1093
1098T& at(index_type i) {return const_cast<T&>(this->CBase::at(i));}
1099
1103{ return this->CBase::getElt(i); }
1107{ return const_cast<T&>(this->CBase::getElt(i)); }
1108
1114SimTK_FORCE_INLINE const T& front() const {return this->CBase::front();}
1115
1121SimTK_FORCE_INLINE T& front() {return const_cast<T&>(this->CBase::front());}
1122
1128SimTK_FORCE_INLINE const T& back() const {return this->CBase::back();}
1129
1135SimTK_FORCE_INLINE T& back() {return const_cast<T&>(this->CBase::back());}
1136
1156 const size_type ix(index);
1157 SimTK_ERRCHK2(isSizeInRange(ix, size()), "ArrayView_<T>(index,length)",
1158 "For this operator, we must have 0 <= index <= size(), but"
1159 " index==%llu and size==%llu.", this->ull(ix), ullSize());
1160 SimTK_ERRCHK2(isSizeInRange(length, size_type(size()-ix)),
1161 "ArrayView_<T>(index,length)",
1162 "This operator requires 0 <= length <= size()-index, but"
1163 " length==%llu and size()-index==%llu.",this->ull(length),this->ull(size()-ix));
1164
1165 return ArrayView_(data()+ix, data()+ix+length);
1166}
1170{ return (*this)(index,length); }
1174//------------------------------------------------------------------------------
1183
1188SimTK_FORCE_INLINE const T* cbegin() const {return this->CBase::cbegin();}
1190SimTK_FORCE_INLINE const T* begin() const {return this->CBase::cbegin();}
1195SimTK_FORCE_INLINE T* begin() {return const_cast<T*>(this->CBase::cbegin());}
1196
1201SimTK_FORCE_INLINE const T* cend() const {return this->CBase::cend();}
1203SimTK_FORCE_INLINE const T* end() const {return this->CBase::cend();}
1208SimTK_FORCE_INLINE T* end() {return const_cast<T*>(this->CBase::cend());}
1209
1212const_reverse_iterator crbegin() const
1213{ return this->CBase::crbegin(); }
1215const_reverse_iterator rbegin() const
1216{ return this->CBase::crbegin(); }
1219reverse_iterator rbegin() {return reverse_iterator(end());}
1220
1225{ return this->CBase::crend(); }
1227const_reverse_iterator rend() const
1228{ return this->CBase::crend(); }
1232reverse_iterator rend() {return reverse_iterator(begin());}
1233
1240SimTK_FORCE_INLINE const T* cdata() const {return this->CBase::cdata();}
1243SimTK_FORCE_INLINE const T* data() const {return this->CBase::cdata();}
1247SimTK_FORCE_INLINE T* data() {return const_cast<T*>(this->CBase::cdata());}
1251//------------------------------------------------------------------------------
1257
1258// Note: these have to be explicitly forwarded to the base class methods
1259// in order to keep gcc from complaining. Note that the "this->" is
1260// apparently necessary in order to permit delayed definition of templatized
1261// methods. Doxygen picks up the comments from the base class.
1262
1263SimTK_FORCE_INLINE size_type size() const {return this->CBase::size();}
1264size_type max_size() const {return this->CBase::max_size();}
1265bool empty() const {return this->CBase::empty();}
1266size_type capacity() const {return this->CBase::capacity();}
1267size_type allocated() const {return this->CBase::allocated();}
1268bool isOwner() const {return this->CBase::isOwner();}
1272//------------------------------------------------------------------------------
1273 private:
1274//------------------------------------------------------------------------------
1275// no data members are allowed
1276
1277//------------------------------------------------------------------------------
1278// ARRAY VIEW ASSIGN DISPATCH
1279// This is the assign() implementation for ArrayView_ when the class that
1280// matched the alleged InputIterator template argument turned out to be one of
1281// the integral types in which case this should match the assign(n, fillValue)
1282// signature.
1283template <class IntegralType>
1284void avAssignDispatch(IntegralType n, IntegralType v, TrueType isIntegralType,
1285 const char*)
1286{ assign(size_type(n), value_type(v)); }
1287
1288// This is the assign() implementation for ArrayView_ when the class that
1289// matched the alleged InputIterator template argument is NOT an integral type
1290// and may very well be an iterator.
1291template <class InputIterator>
1292void avAssignDispatch(const InputIterator& first, const InputIterator& last1,
1293 FalseType isIntegralType, const char* methodName)
1294{ avAssignIteratorDispatch(first, last1,
1295 typename std::iterator_traits<InputIterator>::iterator_category(),
1296 methodName); }
1297
1298// This is the assign() implementation for a plain input_iterator
1299// (i.e., not a forward, bidirectional, or random access iterator). These
1300// have the unfortunate property that we can't count the elements in advance.
1301// Here we're going to complain if there aren't enough; but will simply stop
1302// when we get size() elements and not insist that the input stream reached
1303// the supplied last1 iterator. Semantics is elementwise assignment.
1304template <class InputIterator>
1305void avAssignIteratorDispatch(const InputIterator& first,
1306 const InputIterator& last1,
1307 std::input_iterator_tag,
1308 const char* methodName)
1309{
1310 T* p = begin();
1311 InputIterator 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 input_iterator provided only %llu elements but this"
1319 " ArrayView has a fixed size of %llu elements.",
1320 this->ull(nCopied), ullSize());
1321
1322 // We don't care if there are still more input elements available.
1323}
1324
1325// This is the assign() implementation that works for forward and bidirectional
1326// iterators, but is not used for random_access_iterators. Here we'll count
1327// the elements as we copy them and complain at the end if there were too
1328// few or too many.
1329template <class ForwardIterator>
1330void avAssignIteratorDispatch(const ForwardIterator& first,
1331 const ForwardIterator& last1,
1332 std::forward_iterator_tag,
1333 const char* methodName)
1334{
1335 T* p = begin();
1336 ForwardIterator src = first;
1337 while (src != last1 && p != end())
1338 *p++ = *src++; // call T's assignment operator
1339
1340 // p now points just after the last element that was copied.
1341 const size_type nCopied = size_type(p - begin());
1342 SimTK_ERRCHK2_ALWAYS(nCopied == size(), methodName,
1343 "The supplied forward_ or bidirectional_iterator source range provided"
1344 " only %llu elements but this ArrayView has a fixed size of"
1345 " %llu elements.", this->ull(nCopied), ullSize());
1346
1347 // Make sure we ran out of source elements.
1348 SimTK_ERRCHK1_ALWAYS(src == last1, methodName,
1349 "The supplied forward_ or bidirectional_iterator source range"
1350 " contained too many elements; this ArrayView has a fixed size of"
1351 " %llu elements.", ullSize());
1352}
1353
1354// This is the assign() implementation that works for random_access_iterators
1355// including ordinary pointers. Here we check the number of elements in advance
1356// and complain if the source and destination aren't the same size. The
1357// copying loop can be done faster in this case.
1358template <class RandomAccessIterator>
1359void avAssignIteratorDispatch(const RandomAccessIterator& first,
1360 const RandomAccessIterator& last1,
1361 std::random_access_iterator_tag,
1362 const char* methodName)
1363{
1364 SimTK_ERRCHK2_ALWAYS(this->isSameSize(last1-first), methodName,
1365 "Assignment to an ArrayView is permitted only if the source"
1366 " is the same size. Here the source had %llu element(s) but the"
1367 " ArrayView has a fixed size of %llu.",
1368 this->ull(last1-first), this->ull(size()));
1369
1370 SimTK_ERRCHK_ALWAYS(!this->overlapsWithData(first,last1), methodName,
1371 "Source range can't overlap with the destination data.");
1372
1373 T* p = begin();
1374 RandomAccessIterator src = first;
1375 while (p != end())
1376 *p++ = *src++; // call T's assignment operator
1377}
1378
1379
1380//------------------------------------------------------------------------------
1381// The following private methods are protected methods in the ArrayViewConst_
1382// base class, so they should not need repeating here. However, we explicitly
1383// forward to the base methods to avoid gcc errors. The gcc complaint
1384// is due to their not depending on any template parameters; the "this->"
1385// apparently fixes that problem.
1386
1387packed_size_type psize() const
1388{ return this->CBase::psize(); }
1389packed_size_type pallocated() const
1390{ return this->CBase::pallocated(); }
1391
1392// This just cast sizes to unsigned long long so that we can do comparisons
1393// without getting warnings.
1394unsigned long long ullSize() const
1395{ return this->CBase::ullSize(); }
1396unsigned long long ullCapacity() const
1397{ return this->CBase::ullCapacity(); }
1398unsigned long long ullMaxSize() const
1399{ return this->CBase::ullMaxSize(); }
1400// This is the index type name and is handy for error messages to explain
1401// why some size was too big.
1402const char* indexName() const {return this->CBase::indexName();}
1403};
1404
1405
1406//==============================================================================
1407// CLASS Array_
1408//==============================================================================
1520template <class T, class X> class Array_ : public ArrayView_<T,X> {
1521 typedef ArrayView_<T,X> Base;
1523public:
1524
1525
1526//------------------------------------------------------------------------------
1532// Doxygen picks up individual descriptions from the base class.
1533/*{*/
1534typedef T value_type;
1535typedef X index_type;
1536typedef T* pointer;
1537typedef const T* const_pointer;
1538typedef T& reference;
1539typedef const T& const_reference;
1540typedef T* iterator;
1541typedef const T* const_iterator;
1542typedef std::reverse_iterator<iterator> reverse_iterator;
1543typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
1546typedef typename ArrayIndexPackType<size_type>::packed_size_type
1548/*}*/
1549
1550//------------------------------------------------------------------------------
1557/*{*/
1558
1560Array_() : Base() {}
1561
1566explicit Array_(size_type n) : Base() {
1567 SimTK_SIZECHECK(n, max_size(), "Array_<T>::ctor(n)");
1568 allocateNoConstruct(n);
1569 defaultConstruct(data(), data()+n);
1570 setSize(n);
1571}
1572
1576Array_(size_type n, const T& initVal) : Base() {
1577 SimTK_SIZECHECK(n, max_size(), "Array_<T>::ctor(n,T)");
1578 setSize(n);
1579 allocateNoConstruct(size());
1580 fillConstruct(begin(), cend(), initVal);
1581}
1597template <class InputIter>
1598Array_(const InputIter& first, const InputIter& last1) : Base() {
1599 ctorDispatch(first,last1,typename IsIntegralType<InputIter>::Result());
1600}
1601
1607template <class T2>
1608Array_(const T2* first, const T2* last1) : Base() {
1609 static_assert(std::is_assignable<T&,T2>::value,
1610 "Array_<T> construction from T2 requires that "
1611 "T2 implicitly converts to T");
1612 SimTK_ERRCHK((first&&last1)||(first==last1), "Array_<T>(first,last1)",
1613 "Pointers must be non-null unless they are both null.");
1614 SimTK_ERRCHK3(this->isSizeOK(last1-first), "Array_<T>(first,last1)",
1615 "Source has %llu elements but this array is limited to %llu"
1616 " elements by its index type %s.",
1617 this->ull(last1-first), ullMaxSize(), indexName());
1618
1619 setSize(size_type(last1-first));
1620 allocateNoConstruct(size());
1621 copyConstruct(begin(), cend(), first);
1622}
1623
1628Array_(std::initializer_list<T> ilist)
1629: Array_(ilist.begin(), ilist.end()) {} // invoke above constructor for T*
1630
1635template <class T2>
1636explicit Array_(const std::vector<T2>& v) : Base() {
1637 if (v.empty()) return;
1638
1639 SimTK_ERRCHK3(this->isSizeOK(v.size()), "Array_<T>::ctor(std::vector<T2>)",
1640 "The source std::vector's size %llu is too big for this array which"
1641 " is limited to %llu elements by its index type %s.",
1642 this->ull(v.size()), ullMaxSize(), indexName());
1643
1644 // Call the above constructor, making sure to use pointers into the
1645 // vector's data rather than the iterators begin() and end() in case
1646 // they are different types.
1647 new (this) Array_(&v.front(), (&v.back())+1);
1648}
1649
1654Array_(const Array_& src) : Base() {
1655 setSize(src.size());
1656 allocateNoConstruct(size());
1657 copyConstruct(begin(), cend(), src.data());
1658}
1659
1662Array_(Array_&& src) : Base() {
1663 swap(src);
1664}
1665
1672template <class T2, class X2>
1673Array_(const Array_<T2,X2>& src) : Base() {
1674 new (this) Array_(src.begin(), src.cend()); // see above
1675}
1676
1706Array_(T* first, const T* last1, const DontCopy&) : Base(first,last1) {}
1707
1735template <class A>
1736Array_(std::vector<T,A>& v, const DontCopy&) : Base(v) {}
1737
1742 deallocate();
1743}
1744
1754 if (allocated()) { // owner with non-zero allocation
1755 clear(); // each element is destructed; size()=0; allocated() unchanged
1756 deallocateNoDestruct(); // free data(); allocated()=0
1757 }
1758 this->Base::disconnect(); // clear the handle
1759 return *this;
1760}
1761
1765//------------------------------------------------------------------------------
1800
1818void assign(size_type n, const T& fillValue) {
1819 SimTK_ERRCHK3(this->isSizeOK(n), "Array_<T>::assign(n,value)",
1820 "Requested size %llu is too big for this array which is limited"
1821 " to %llu elements by its index type %s.",
1822 this->ull(n), ullMaxSize(), indexName());
1823
1824 SimTK_ERRCHK2(isOwner() || n==size(), "Array_<T>::assign(n,value)",
1825 "Requested size %llu is not allowed because this is a non-owner"
1826 " array of fixed size %llu.", this->ull(n), this->ull(size()));
1827
1828 if (!isOwner())
1829 this->Base::fill(fillValue);
1830 else {
1831 clear(); // all elements destructed; allocation unchanged
1832 reallocateIfAdvisable(n); // change size if too small or too big
1833 fillConstruct(data(), cdata()+n, fillValue);
1834 setSize(n);
1835 }
1836}
1837
1852void fill(const T& fillValue) {this->Base::fill(fillValue);}
1853
1854
1876template <class T2>
1877void assign(const T2* first, const T2* last1) {
1878 const char* methodName = "Array_<T>::assign(T2* first, T2* last1)";
1879 SimTK_ERRCHK((first&&last1)||(first==last1), methodName,
1880 "Pointers must be non-null unless they are both null.");
1881 SimTK_ERRCHK(!this->overlapsWithData(first,last1), methodName,
1882 "Source range can't overlap the current array contents.");
1883 // Pointers are random access iterators.
1884 assignIteratorDispatch(first,last1,std::random_access_iterator_tag(),
1885 methodName);
1886}
1887
1888
1924template <class Iter>
1925void assign(const Iter& first, const Iter& last1) {
1926 assignDispatch(first,last1,typename IsIntegralType<Iter>::Result(),
1927 "Array_<T>::assign(Iter first, Iter last1)");
1928}
1929
1936 if (this != &src)
1937 assignIteratorDispatch(src.begin(), src.end(),
1938 std::random_access_iterator_tag(),
1939 "Array_<T>::operator=(Array_<T>)");
1940 return *this;
1941}
1942
1946 swap(src);
1947 return *this;
1948}
1949
1955template <class T2, class X2>
1957 assignIteratorDispatch(src.begin(), src.end(),
1958 std::random_access_iterator_tag(),
1959 "Array_<T>::operator=(Array_<T2,X2>)");
1960 return *this;
1961}
1962
1963
1968template <class T2, class A>
1969Array_& operator=(const std::vector<T2,A>& src) {
1970 assignIteratorDispatch(src.begin(), src.end(),
1971 std::random_access_iterator_tag(),
1972 "Array_<T>::operator=(std::vector)");
1973 return *this;
1974}
1975
1983void swap(Array_& other) {
1984 T* const pTmp=data(); setData(other.data()); other.setData(pTmp);
1985 size_type nTmp=size(); setSize(other.size()); other.setSize(nTmp);
1986 nTmp=allocated(); setAllocated(other.allocated()); other.setAllocated(nTmp);
1987}
1988
1994Array_& adoptData(T* newData, size_type dataSize,
1995 size_type dataCapacity)
1996{
1997 SimTK_SIZECHECK(dataCapacity, max_size(), "Array_<T>::adoptData()");
1998 SimTK_ERRCHK2(dataSize <= dataCapacity, "Array_<T>::adoptData()",
1999 "Specified data size %llu was greater than the specified data"
2000 " capacity of %llu.", this->ull(dataSize), this->ull(dataCapacity));
2001 SimTK_ERRCHK(newData || dataCapacity==0, "Array_<T>::adoptData()",
2002 "A null data pointer is allowed only if the size and capacity are"
2003 " specified as zero.");
2004 SimTK_ERRCHK(!this->overlapsWithData(newData, newData+dataSize),
2005 "Array_<T>::adoptData()",
2006 "The new data can't overlap with the old data.");
2007
2008 deallocate();
2009 setData(newData);
2010 setSize(dataSize);
2011 setAllocated(dataCapacity);
2012 return *this;
2013}
2016Array_& adoptData(T* newData, size_type dataSize)
2017{ return adoptData(newData, dataSize, dataSize); }
2018
2019
2033Array_& shareData(T* newData, size_type dataSize) {
2034 SimTK_SIZECHECK(dataSize, max_size(), "Array_<T>::shareData()");
2035 SimTK_ERRCHK(newData || dataSize==0, "Array_<T>::shareData()",
2036 "A null data pointer is allowed only if the size is zero.");
2037 SimTK_ERRCHK(!this->overlapsWithData(newData, newData+dataSize),
2038 "Array_<T>::shareData()",
2039 "The new data can't overlap with the old data.");
2040
2041 deallocate();
2042 setData(newData);
2043 setSize(dataSize);
2044 setAllocated(0); // indicates shared data
2045 return *this;
2046}
2047
2050Array_& shareData(T* first, const T* last1) {
2051 SimTK_ERRCHK3(this->isSizeOK(last1-first),
2052 "Array_<T>::shareData(first,last1)",
2053 "Requested size %llu is too big for this array which is limited"
2054 " to %llu elements by its index type %s.",
2055 this->ull(last1-first), ullMaxSize(), indexName());
2056 return shareData(first, size_type(last1-first));
2057}
2058
2062//------------------------------------------------------------------------------
2068
2069// Note: these have to be explicitly forwarded to the base class methods
2070// in order to keep gcc from complaining. Note that the "this->" is
2071// apparently necessary in order to permit delayed definition of templatized
2072// methods.
2073
2077size_type max_size() const {return this->CBase::max_size();}
2080bool empty() const {return this->CBase::empty();}
2085size_type capacity() const {return this->CBase::capacity();}
2086
2091void resize(size_type n) {
2092 if (n == size()) return;
2093
2094 SimTK_ERRCHK2(isOwner(), "Array_<T>::resize(n)",
2095 "Requested size change to %llu is not allowed because this is a "
2096 "non-owner array of fixed size %llu.",
2097 this->ull(n), this->ull(size()));
2098
2099 if (n < size()) {
2100 erase(data()+n, cend());
2101 return;
2102 }
2103 // n > size()
2104 reserve(n);
2105 defaultConstruct(data()+size(), cdata()+n); // data() has changed
2106 setSize(n);
2107}
2108
2113void resize(size_type n, const T& initVal) {
2114 if (n == size()) return;
2115
2116 SimTK_ERRCHK2(isOwner(), "Array_<T>::resize(n,value)",
2117 "Requested size change to %llu is not allowed because this is a"
2118 " non-owner array of fixed size %llu.", this->ull(n), this->ull(size()));
2119
2120 if (n < size()) {
2121 erase(data()+n, cend());
2122 return;
2123 }
2124 // n > size()
2125 reserve(n);
2126 fillConstruct(data()+size(), cdata()+n, initVal);
2127 setSize(n);
2128}
2129
2137 if (capacity() >= n)
2138 return;
2139
2140 SimTK_ERRCHK2(isOwner(), "Array_<T>::reserve()",
2141 "Requested capacity change to %llu is not allowed because this is a "
2142 "non-owner array of fixed size %llu.",
2143 this->ull(n), this->ull(size()));
2144
2145 T* newData = allocN(n); // no construction yet
2146 moveConstructThenDestructSource(newData, newData+size(), data());
2147 freeN(data());
2148 setData(newData);
2149 setAllocated(n);
2150}
2151
2173 // Allow 25% slop, but note that if size()==0 this will always reallocate
2174 // unless capacity is already zero.
2175 if (capacity() - size()/4 <= size()) // avoid overflow if size() near max
2176 return;
2177 T* newData = allocN(size());
2178 moveConstructThenDestructSource(newData, newData+size(), data());
2179 deallocateNoDestruct(); // data()=0, allocated()=0, size() unchanged
2180 setData(newData);
2181 setAllocated(size());
2182}
2183
2188{ return this->CBase::allocated(); }
2194bool isOwner() const {return this->CBase::isOwner();}
2198//------------------------------------------------------------------------------
2207
2212SimTK_FORCE_INLINE const T* cbegin() const {return this->CBase::cbegin();}
2214SimTK_FORCE_INLINE const T* begin() const {return this->CBase::cbegin();}
2220
2225SimTK_FORCE_INLINE const T* cend() const {return this->CBase::cend();}
2227SimTK_FORCE_INLINE const T* end() const {return this->CBase::cend();}
2232SimTK_FORCE_INLINE T* end() {return this->Base::end();}
2233
2236const_reverse_iterator crbegin() const
2237{ return this->CBase::crbegin(); }
2239const_reverse_iterator rbegin() const
2240{ return this->CBase::crbegin(); }
2243reverse_iterator rbegin() {return this->Base::rbegin();}
2244
2248const_reverse_iterator crend() const
2249{ return this->CBase::crend(); }
2251const_reverse_iterator rend() const
2252{ return this->CBase::crend(); }
2256reverse_iterator rend() {return this->Base::rend();}
2257
2264SimTK_FORCE_INLINE const T* cdata() const {return this->CBase::cdata();}
2267SimTK_FORCE_INLINE const T* data() const {return this->CBase::cdata();}
2271SimTK_FORCE_INLINE T* data() {return this->Base::data();}
2279
2287{ return this->CBase::operator[](i); }
2288
2297
2302const T& at(index_type i) const {return this->CBase::at(i);}
2303
2308T& at(index_type i) {return const_cast<T&>(this->Base::at(i));}
2309
2313{ return this->CBase::getElt(i); }
2317
2323SimTK_FORCE_INLINE const T& front() const {return this->CBase::front();}
2324
2330SimTK_FORCE_INLINE T& front() {return const_cast<T&>(this->Base::front());}
2331
2337SimTK_FORCE_INLINE const T& back() const {return this->CBase::back();}
2338
2344SimTK_FORCE_INLINE T& back() {return const_cast<T&>(this->Base::back());}
2345
2349{ return CBase::operator()(index,length); }
2353{ return CBase::getSubArray(index,length); }
2354
2358{ return Base::operator()(index,length); }
2362{ return Base::updSubArray(index,length); }
2366//------------------------------------------------------------------------------
2372
2399void push_back(const T& value) {
2400 if (pallocated() == psize())
2401 growAtEnd(1,"Array_<T>::push_back(const T& value)");
2402 copyConstruct(end(), value);
2403 incrSize();
2404}
2405
2410void push_back(T&& value) {
2411 if (pallocated() == psize())
2412 growAtEnd(1,"Array_<T>::push_back(T&& value)");
2413 moveConstruct(end(), std::move(value));
2414 incrSize();
2415}
2416
2425template<class... Args>
2426void emplace_back(Args&&... args) { // special syntax; not an rvalue reference
2427 if (pallocated() == psize())
2428 growAtEnd(1,"Array_<T>::emplace_back(Args...)");
2429 new(end()) T(std::forward<Args>(args)...); // invoke constructor for T
2430 incrSize();
2431}
2432
2451 if (pallocated() == psize())
2452 growAtEnd(1,"Array_<T>::push_back()");
2453 defaultConstruct(end());
2454 incrSize();
2455}
2456
2478 if (pallocated() == psize())
2479 growAtEnd(1,"Array_<T>::raw_push_back()");
2480 T* const p = end();
2481 incrSize();
2482 return p;
2483}
2484
2487void pop_back() {
2488 SimTK_ERRCHK(!empty(), "Array_<T>::pop_back()", "Array was empty.");
2489 destruct(&back());
2490 decrSize();
2491}
2492
2510T* erase(T* first, const T* last1) {
2511 SimTK_ERRCHK(begin() <= first && first <= last1 && last1 <= end(),
2512 "Array_<T>::erase(first,last1)", "Pointers out of range or out of order.");
2513
2514 const size_type nErased = size_type(last1-first);
2515 SimTK_ERRCHK(isOwner() || nErased==0, "Array_<T>::erase(first,last1)",
2516 "No elements can be erased from a non-owner array.");
2517
2518 if (nErased) {
2519 destruct(first, last1); // Destruct the elements we're erasing.
2520 moveElementsDown(first+nErased, nErased); //Compress followers into gap.
2521 setSize(size()-nErased);
2522 }
2523 return first;
2524}
2525
2545T* erase(T* p) {
2546 SimTK_ERRCHK(begin() <= p && p < end(),
2547 "Array_<T>::erase(p)", "Pointer must point to a valid element.");
2548 SimTK_ERRCHK(isOwner(), "Array_<T>::erase(p)",
2549 "No elements can be erased from a non-owner array.");
2550
2551 destruct(p); // Destruct the element we're erasing.
2552 moveElementsDown(p+1, 1); // Compress followers into the gap.
2553 decrSize();
2554 return p;
2555}
2556
2557
2578T* eraseFast(T* p) {
2579 SimTK_ERRCHK(begin() <= p && p < end(),
2580 "Array_<T>::eraseFast(p)", "Pointer must point to a valid element.");
2581 SimTK_ERRCHK(isOwner(), "Array_<T>::eraseFast(p)",
2582 "No elements can be erased from a non-owner array.");
2583
2584 destruct(p);
2585 if (p+1 != end())
2586 moveOneElement(p, &back());
2587 decrSize();
2588 return p;
2589}
2590
2598void clear() {
2599 SimTK_ERRCHK(isOwner() || empty(), "Array_<T>::clear()",
2600 "clear() is not allowed for a non-owner array.");
2601 destruct(begin(), end());
2602 setSize(0);
2603}
2604
2605
2632T* insert(T* p, size_type n, const T& value) {
2633 T* const gap = insertGapAt(p, n, "Array_<T>::insert(p,n,value)");
2634 // Copy construct into the inserted elements and note the size change.
2635 fillConstruct(gap, gap+n, value);
2636 setSize(size()+n);
2637 return gap;
2638}
2639
2644T* insert(T* p, const T& value) {
2645 T* const gap = insertGapAt(p, 1, "Array_<T>::insert(p,value)");
2646 // Copy construct into the inserted element and note the size change.
2647 copyConstruct(gap, value);
2648 incrSize();
2649 return gap;
2650}
2651
2657template <class... Args>
2658T* emplace(T* p, Args&&... args) { // special syntax; not an rvalue reference
2659 T* const gap = insertGapAt(p, 1, "Array_<T>::emplace(p,Args...)");
2660 // Construct into the inserted element and note the size change.
2661 new(gap) T(std::forward<Args>(args)...); // invoke the constructor
2662 incrSize();
2663 return gap;
2664}
2665
2695template <class T2>
2696T* insert(T* p, const T2* first, const T2* last1) {
2697 const char* methodName = "Array_<T>::insert(T* p, T2* first, T2* last1)";
2698 SimTK_ERRCHK((first&&last1) || (first==last1), methodName,
2699 "One of first or last1 was null; either both or neither must be null.");
2700 SimTK_ERRCHK(!this->overlapsWithData(first,last1), methodName,
2701 "Source range can't overlap with the current array contents.");
2702 // Pointers are random access iterators.
2703 return insertIteratorDispatch(p, first, last1,
2704 std::random_access_iterator_tag(),
2705 methodName);
2706}
2707
2710template <class Iter>
2711T* insert(T* p, const Iter& first, const Iter& last1) {
2712 return insertDispatch(p, first, last1,
2714 "Array_<T>::insert(T* p, Iter first, Iter last1)");
2715}
2720//------------------------------------------------------------------------------
2721 private:
2722//------------------------------------------------------------------------------
2723
2724
2725// This method is used when we have already decided we need to make room for
2726// some new elements by reallocation, by creating a gap somewhere within the
2727// existing data. We'll issue an error message if this would violate the
2728// max_size restriction (we can afford to do that even in a Release build since
2729// we don't expect to grow very often). Otherwise we'll allocate some more space
2730// and move construct the existing elements into the new space, leaving a gap
2731// where indicated. Note that this method does not change the current size but
2732// does change the capacity.
2733//
2734// The gapPos must point within the existing data with null OK if the array
2735// itself is null, and end() being OK any time although you should use the
2736// more specialized growAtEnd() method if you know that's what's happening.
2737//
2738// Don't call this with a gapSz of zero.
2739T* growWithGap(T* gapPos, size_type gapSz, const char* methodName) {
2740 assert(gapSz > 0); // <= 0 is a bug, not a user error
2741
2742 // Note that gapPos may be null if begin() and end() are also.
2743 SimTK_ERRCHK(begin() <= gapPos && gapPos <= end(), methodName,
2744 "Given insertion point is not valid for this array.");
2745
2746 // Get some new space of a reasonable size.
2747 setAllocated(calcNewCapacityForGrowthBy(gapSz, methodName));
2748 T* newData = allocN(allocated());
2749
2750 // How many elements will be before the gap?
2751 const size_type nBefore = (size_type)(gapPos-begin());
2752
2753 // Locate the gap in the new space allocation.
2754 T* newGap = newData + nBefore;
2755 T* newGapEnd = newGap + gapSz; // one past the last element in the gap
2756
2757 // Move elements before insertion point; destruct source as we go.
2758 moveConstructThenDestructSource(newData, newGap, data());
2759 // Move/destruct elements at and after insertion pt; leave gapSz gap.
2760 moveConstructThenDestructSource(newGapEnd, newData+size(), gapPos);
2761
2762 // Throw away the old data and switch to the new.
2763 freeN(data()); setData(newData);
2764 return newGap;
2765}
2766
2767// Same as growWithGap(end(), n, methodName); see above.
2768void growAtEnd(size_type n, const char* methodName) {
2769 assert(n > 0); // <= 0 is a bug, not a user error
2770 // Get some new space of a reasonable size.
2771 setAllocated(calcNewCapacityForGrowthBy(n, methodName));
2772 T* newData = allocN(allocated());
2773 // Copy all the elements; destruct source as we go.
2774 moveConstructThenDestructSource(newData, newData+size(), data());
2775 // Throw away the old data and switch to the new.
2776 freeN(data()); setData(newData);
2777}
2778
2779// This method determines how much we should increase the array's capacity
2780// when asked to insert n elements, due to an insertion or push_back. We will
2781// generally allocate more new space than requested, in anticipation of
2782// further insertions. This has to be based on the current size so that only
2783// log(n) reallocations are performed to insert n elements one at a time. Our
2784// policy here is to at least double the capacity unless that would exceed
2785// max_size(). There is also a minimum amount of allocation we'll do if the
2786// current size is zero or very small.
2787size_type calcNewCapacityForGrowthBy(size_type n, const char* methodName) const {
2788 SimTK_ERRCHK3_ALWAYS(isGrowthOK(n), methodName,
2789 "Can't grow this Array by %llu element(s) because it would"
2790 " then exceed the max_size of %llu set by its index type %s.",
2791 (unsigned long long)n, ullMaxSize(), indexName());
2792
2793 // At this point we know that capacity()+n <= max_size().
2794 const size_type mustHave = capacity() + n;
2795
2796 // Be careful not to overflow size_type as you could if you
2797 // double capacity() rather than halving max_size().
2798 const size_type wantToHave = capacity() <= max_size()/2
2799 ? 2*capacity()
2800 : max_size();
2801
2802 const size_type newCapacity = std::max(std::max(mustHave,wantToHave),
2803 minAlloc());
2804 return newCapacity;
2805}
2806
2807// Insert an unconstructed gap of size n beginning at position p. The return
2808// value is a pointer to the first element in the gap. It will be p if no
2809// reallocation occurred, otherwise it will be pointing into the new data.
2810// On return size() will be unchanged although allocated() may be bigger.
2811T* insertGapAt(T* p, size_type n, const char* methodName) {
2812 // Note that p may be null if begin() and end() are also.
2813 SimTK_ERRCHK(begin() <= p && p <= end(), methodName,
2814 "Given insertion point is not valid for this Array.");
2815
2816 if (n==0) return p; // nothing to do
2817
2818 SimTK_ERRCHK_ALWAYS(isOwner(), methodName,
2819 "No elements can be inserted into a non-owner array.");
2820
2821 // Determine the number of elements before the insertion point and
2822 // the number at or afterwards (those must be moved up by one slot).
2823 const size_type before = (size_type)(p-begin()), after = (size_type)(end()-p);
2824
2825 // Grow the container if necessary. Note that if we have to grow we
2826 // can create the gap at the same time we copy the old elements over
2827 // to the new space.
2828 if (capacity() >= size()+n) {
2829 moveElementsUp(p, n); // leave a gap at p
2830 } else { // need to grow
2831 setAllocated(calcNewCapacityForGrowthBy(n, methodName));
2832 T* newdata = allocN(allocated());
2833 // Move the elements before the insertion point, and destroy source.
2834 moveConstructThenDestructSource(newdata, newdata+before, data());
2835 // Copy the elements at and after the insertion point, leaving a gap
2836 // of n elements.
2837 moveConstructThenDestructSource(newdata+before+n,
2838 newdata+before+n+after,
2839 p); // i.e., pData+before
2840 p = newdata + before; // points into newdata now
2841 freeN(data());
2842 setData(newdata);
2843 }
2844
2845 return p;
2846}
2847
2848//------------------------------------------------------------------------------
2849// CTOR DISPATCH
2850// This is the constructor implementation for when the class that matches
2851// the alleged InputIterator type turns out to be one of the integral types
2852// in which case this should be the ctor(n, initValue) constructor.
2853template <class IntegralType> void
2854ctorDispatch(IntegralType n, IntegralType v, TrueType isIntegralType) {
2855 new(this) Array_(size_type(n), value_type(v));
2856}
2857
2858// This is the constructor implementation for when the class that matches
2859// the alleged InputIterator type is NOT an integral type and may very well
2860// be an iterator. In that case we split into iterators for which we can
2861// determine the number of elements in advance (forward, bidirectional,
2862// random access) and input iterators, for which we can't. Note: iterator
2863// types are arranged hierarchically random->bi->forward->input with each
2864// deriving from the one on its right, so the forward iterator tag also
2865// matches bi and random.
2866template <class InputIterator> void
2867ctorDispatch(const InputIterator& first, const InputIterator& last1,
2868 FalseType isIntegralType)
2869{ ctorIteratorDispatch(first, last1,
2870 typename std::iterator_traits<InputIterator>::iterator_category()); }
2871
2872// This is the slow generic ctor implementation for any iterator that can't
2873// make it up to forward_iterator capability (that is, an input_iterator).
2874// The issue here is that we can't advance the iterator to count the number
2875// of elements before allocating because input_iterators are consumed when
2876// reference so we can't go back to look. That means we may have to reallocate
2877// memory log n times as we "push back" these elements onto the array.
2878template <class InputIterator> void
2879ctorIteratorDispatch(const InputIterator& first, const InputIterator& last1,
2880 std::input_iterator_tag)
2881{
2882 InputIterator src = first;
2883 while (src != last1) {
2884 // We can afford to check this always since we are probably doing I/O.
2885 // Throwing an exception in a constructor is tricky, though -- this
2886 // won't go through the Array_ destructor although it will call the
2887 // Base (ArrayView_) destructor. Since we have already allocated
2888 // some space, we must call deallocate() manually.
2889 if (size() == max_size()) {
2890 deallocate();
2891 SimTK_ERRCHK2_ALWAYS(!"too many elements",
2892 "Array_::ctor(InputIterator first, InputIterator last1)",
2893 "There were still source elements available when the array"
2894 " reached its maximum size of %llu as determined by its index"
2895 " type %s.", ullMaxSize(), indexName());
2896 }
2897 push_back(*src++);
2898 }
2899}
2900
2901// This is the faster constructor implementation for iterator types for which
2902// we can calculate the number of elements in advance. This will be optimal
2903// for a random access iterator since we can count in constant time, but for
2904// forward or bidirectional we'll have to advance n times to count and then
2905// go back again to do the copy constructions.
2906template <class ForwardIterator> void
2907ctorIteratorDispatch(const ForwardIterator& first, const ForwardIterator& last1,
2908 std::forward_iterator_tag)
2909{
2910 typedef typename std::iterator_traits<ForwardIterator>::difference_type
2912 // iterDistance() is constant time for random access iterators, but
2913 // O(last1-first) for forward and bidirectional since it has to increment
2914 // to count how far apart they are.
2915 const difference_type nInput = this->iterDistance(first,last1);
2916
2917 SimTK_ERRCHK(nInput >= 0,
2918 "Array_(ForwardIterator first, ForwardIterator last1)",
2919 "Iterators were out of order.");
2920
2921 SimTK_ERRCHK3(this->isSizeOK(nInput),
2922 "Array_(ForwardIterator first, ForwardIterator last1)",
2923 "Source has %llu elements but this array is limited to %llu"
2924 " elements by its index type %s.",
2925 this->ull(nInput), ullMaxSize(), indexName());
2926
2927 const size_type n = size_type(nInput);
2928 setSize(n);
2929 allocateNoConstruct(n);
2930 copyConstruct(data(), data()+n, first);
2931}
2932
2933//------------------------------------------------------------------------------
2934// INSERT DISPATCH
2935// This is the insert() implementation for when the class that matches
2936// the alleged InputIterator type turns out to be one of the integral types
2937// in which case this should be the insert(p, n, initValue) constructor.
2938template <class IntegralType>
2939T* insertDispatch(T* p, IntegralType n, IntegralType v,
2940 TrueType isIntegralType, const char*)
2941{ return insert(p, size_type(n), value_type(v)); }
2942
2943// This is the insert() implementation for when the class that matches
2944// the alleged InputIterator type is NOT an integral type and may very well
2945// be an iterator. See ctorDispatch() above for more information.
2946template <class InputIterator>
2947T* insertDispatch(T* p, const InputIterator& first, const InputIterator& last1,
2948 FalseType isIntegralType, const char* methodName)
2949{ return insertIteratorDispatch(p, first, last1,
2950 typename std::iterator_traits<InputIterator>::iterator_category(),
2951 methodName); }
2952
2953// This is the slow generic insert implementation for any iterator that can't
2954// make it up to forward_iterator capability (that is, an input_iterator).
2955// See ctorIteratorDispatch() above for more information.
2956template <class InputIterator>
2957T* insertIteratorDispatch(T* p, InputIterator first, InputIterator last1,
2958 std::input_iterator_tag, const char* methodName)
2959{
2960 size_type nInserted = 0;
2961 while (first != last1) {
2962 // We can afford to check this always since we are probably doing I/O.
2963 SimTK_ERRCHK2_ALWAYS(size() < max_size(), methodName,
2964 "There were still source elements available when the array"
2965 " reached its maximum size of %llu as determined by its index"
2966 " type %s.", ullMaxSize(), indexName());
2967 p = insert(p, *first++); // p may now point to reallocated memory
2968 ++p; ++nInserted;
2969 }
2970 // p now points just after the last inserted element; subtract the
2971 // number inserted to get a pointer to the first inserted element.
2972 return p-nInserted;
2973}
2974
2975// This is the faster insert implementation for iterator types for which
2976// we can calculate the number of elements in advance. This will be optimal
2977// for a random access iterator since we can count in constant time, but for
2978// forward or bidirectional we'll have to advance n times to count and then
2979// go back again to do the copy constructions.
2980template <class ForwardIterator>
2981T* insertIteratorDispatch(T* p, const ForwardIterator& first,
2982 const ForwardIterator& last1,
2983 std::forward_iterator_tag,
2984 const char* methodName)
2985{
2986 typedef typename std::iterator_traits<ForwardIterator>::difference_type
2988 // iterDistance() is constant time for random access iterators, but
2989 // O(last1-first) for forward and bidirectional since it has to increment
2990 // to count how far apart they are.
2991 const difference_type nInput = this->iterDistance(first,last1);
2992
2993 SimTK_ERRCHK(nInput >= 0, methodName, "Iterators were out of order.");
2994
2995 SimTK_ERRCHK3(isGrowthOK(nInput), methodName,
2996 "Source has %llu elements which would make this array exceed the %llu"
2997 " elements allowed by its index type %s.",
2998 this->ull(nInput), ullMaxSize(), indexName());
2999
3000 const size_type n = size_type(nInput);
3001 p = insertGapAt(p, n, methodName);
3002 copyConstruct(p, p+n, first);
3003 setSize(size()+n);
3004 return p;
3005}
3006
3007//------------------------------------------------------------------------------
3008// ASSIGN DISPATCH
3009// This is the assign() implementation for when the class that matches
3010// the alleged InputIterator type turns out to be one of the integral types
3011// in which case this should be the assign(n, initValue) constructor.
3012template <class IntegralType>
3013void assignDispatch(IntegralType n, IntegralType v, TrueType isIntegralType,
3014 const char* methodName)
3015{ assign(size_type(n), value_type(v)); }
3016
3017// This is the assign() implementation for when the class that matches
3018// the alleged InputIterator type is NOT an integral type and may very well
3019// be an iterator. See ctorDispatch() above for more information.
3020template <class InputIterator>
3021void assignDispatch(const InputIterator& first, const InputIterator& last1,
3022 FalseType isIntegralType, const char* methodName)
3023{ assignIteratorDispatch(first, last1,
3024 typename std::iterator_traits<InputIterator>::iterator_category(),
3025 methodName); }
3026
3027// This is the slow generic implementation for a plain input_iterator
3028// (i.e., not a forward, bidirectional, or random access iterator). These
3029// have the unfortunate property that we can't count the elements in advance.
3030template <class InputIterator>
3031void assignIteratorDispatch(const InputIterator& first,
3032 const InputIterator& last1,
3033 std::input_iterator_tag,
3034 const char* methodName)
3035{
3036 // TODO: should probably allow this and just blow up when the size()+1st
3037 // element is seen.
3038 SimTK_ERRCHK_ALWAYS(isOwner(), methodName,
3039 "Assignment to a non-owner array can only be done from a source"
3040 " designated with forward iterators or pointers because we"
3041 " must be able to verify that the source and destination sizes"
3042 " are the same.");
3043
3044 clear(); // TODO: change space allocation here?
3045 InputIterator src = first;
3046 while (src != last1) {
3047 // We can afford to check this always since we are probably doing I/O.
3048 SimTK_ERRCHK2_ALWAYS(size() < max_size(), methodName,
3049 "There were still source elements available when the array"
3050 " reached its maximum size of %llu as determined by its index"
3051 " type %s.", ullMaxSize(), indexName());
3052
3053 push_back(*src++);
3054 }
3055}
3056
3057// This is the faster implementation that works for forward, bidirectional,
3058// and random access iterators including ordinary pointers. We can check here that the
3059// iterators are in the right order, and that the source is not too big to
3060// fit in this array. Null pointer checks should be done prior to calling,
3061// however, since iterators in general aren't pointers.
3062template <class ForwardIterator>
3063void assignIteratorDispatch(const ForwardIterator& first,
3064 const ForwardIterator& last1,
3065 std::forward_iterator_tag,
3066 const char* methodName)
3067{
3068 typedef typename std::iterator_traits<ForwardIterator>::difference_type
3069 IterDiffType;
3070 // iterDistance() is constant time for random access iterators, but
3071 // O(last1-first) for forward and bidirectional since it has to increment
3072 // to count how far apart they are.
3073 const IterDiffType nInput = this->iterDistance(first,last1);
3074
3075 SimTK_ERRCHK(nInput >= 0, methodName, "Iterators were out of order.");
3076
3077 SimTK_ERRCHK3(this->isSizeOK(nInput), methodName,
3078 "Source has %llu elements but this Array is limited to %llu"
3079 " elements by its index type %s.",
3080 this->ull(nInput), ullMaxSize(), indexName());
3081
3082 const size_type n = size_type(nInput);
3083 if (isOwner()) {
3084 // This is an owner Array; assignment is considered deallocation
3085 // followed by copy construction.
3086
3087 clear(); // all elements destructed; allocation unchanged
3088 reallocateIfAdvisable(n); // change allocation if too small or too big
3089 copyConstruct(data(), cdata()+n, first);
3090 setSize(n);
3091 } else {
3092 // This is a non-owner Array. Assignment can occur only if the
3093 // source is the same size as the array, and the semantics are of
3094 // repeated assignment using T::operator=() not destruction followed
3095 // by copy construction.
3096 SimTK_ERRCHK2(n == size(), methodName,
3097 "Source has %llu elements which does not match the size %llu "
3098 "of the non-owner array it is being assigned into.",
3099 this->ull(n), ullSize());
3100
3101 T* p = begin();
3102 ForwardIterator src = first;
3103 while (src != last1)
3104 *p++ = *src++; // call T's assignment operator
3105 }
3106}
3107
3108// We are going to put a total of n elements into the Array (probably
3109// because of an assignment or resize) and we want the space allocation
3110// to be reasonable. That means of course that the allocation must be
3111// *at least* n, but we also don't want it to be too big. Our policy
3112// here is that if it is currently less than twice what we need we
3113// won't reallocate, otherwise we'll shrink the space. When changing
3114// the size to zero or something very small we'll treat the Array as
3115// though its current size is minAlloc, meaning we won't reallocate
3116// if the existing space is less than twice minAlloc.
3117// nAllocated will be set appropriately; size() is not touched here.
3118// No constructors or destructors are called.
3119void reallocateIfAdvisable(size_type n) {
3120 if (allocated() < n || allocated()/2 > std::max(minAlloc(), n))
3121 reallocateNoDestructOrConstruct(n);
3122}
3123
3124
3125void allocateNoConstruct(size_type n)
3126{ setData(allocN(n)); setAllocated(n); } // size() left unchanged
3127void deallocateNoDestruct()
3128{ freeN(data()); setData(0); setAllocated(0); } // size() left unchanged
3129void reallocateNoDestructOrConstruct(size_type n)
3130{ deallocateNoDestruct(); allocateNoConstruct(n); }
3131
3132// This sets the smallest allocation we'll do when growing.
3133size_type minAlloc() const
3134{ return std::min(max_size(), size_type(4)); }
3135
3136// Allocate without construction. Returns a null pointer if asked
3137// to allocate 0 elements. In Debug mode we'll fill memory with
3138// all 1's as a bug catcher.
3139static T* allocN(size_type n) {
3140 if (n==0) return 0;
3141 unsigned char* newdata = new unsigned char[n * sizeof(T)];
3142 #ifndef NDEBUG
3143 unsigned char* b=newdata;
3144 const unsigned char* e=newdata+(n*sizeof(T));
3145 while (b != e) *b++ = 0xff;
3146 #endif
3147 return reinterpret_cast<T*>(newdata);
3148}
3149
3150// Free memory without calling T's destructor. Nothing happens if passed
3151// a null pointer.
3152static void freeN(T* p) {
3153 delete[] reinterpret_cast<char*>(p);
3154}
3155
3156// default construct one element
3157static void defaultConstruct(T* p) {new(p) T();}
3158// default construct range [b,e)
3159static void defaultConstruct(T* b, const T* e)
3160{ while (b!=e) new(b++) T(); }
3161
3162// copy construct range [b,e) with repeats of a given value
3163static void fillConstruct(T* b, const T* e, const T& v)
3164{ while(b!=e) new(b++) T(v); }
3165
3166// copy construct one element from a given value
3167static void copyConstruct(T* p, const T& v) {new(p) T(v);}
3168// move construct one element from a given value
3169static void moveConstruct(T* p, T&& v) {new(p) T(std::move(v));}
3170
3171// copy construct range [b,e) from sequence of source values
3172static void copyConstruct(T* b, const T* e, T* src)
3173{ while(b!=e) new(b++) T(*src++); }
3174// move construct range [b,e) from sequence of source values
3175static void moveConstruct(T* b, const T* e, T* src)
3176{ while(b!=e) new(b++) T(std::move(*src++)); }
3177
3178// Templatized copy construct will work if the source elements are
3179// assignment compatible with the destination elements.
3180template <class InputIterator>
3181static void copyConstruct(T* b, const T* e, InputIterator src)
3182{ while(b!=e) new(b++) T(*src++); }
3183
3184// Copy construct range [b,e] from sequence of source values and
3185// destruct the source after it is copied. It's better to alternate
3186// copying and destructing than to do this in two passes since we
3187// will already have touched the memory.
3188static void copyConstructThenDestructSource(T* b, const T* e, T* src)
3189{ while(b!=e) {new(b++) T(*src); src++->~T();} }
3190
3191// Move construct range [b,e] from sequence of source values and
3192// destruct the source after it is copied. It's better to alternate
3193// moving and destructing than to do this in two passes since we
3194// will already have touched the memory.
3195static void moveConstructThenDestructSource(T* b, const T* e, T* src)
3196{ while(b!=e) {new(b++) T(std::move(*src)); src++->~T();} }
3197
3198// We have an element at from that we would like to move into the currently-
3199// unconstructed slot at to. Both from and to are expected to be pointing to
3200// elements within the currently allocated space. From's slot will be left
3201// unconstructed.
3202void moveOneElement(T* to, T* from) {
3203 assert(data() <= to && to < data()+allocated());
3204 assert(data() <= from && from < data()+allocated());
3205 moveConstruct(to, std::move(*from));
3206 destruct(from);
3207}
3208
3209
3210// Move elements from p to end() down by n>0 places to fill an unconstructed
3211// gap beginning at p-n. Any leftover space at the end will be unconstructed.
3212void moveElementsDown(T* p, size_type n) {
3213 assert(n > 0);
3214 for (; p != end(); ++p)
3215 moveOneElement(p-n,p);
3216}
3217
3218// Move elements from p to end() up by n>0 places to make an unconstructed gap
3219// at [p,p+n). Note that this has to be done backwards so that we don't
3220// write on any elements until after they've been copied.
3221void moveElementsUp(T* p, size_type n) {
3222 assert(n > 0);
3223 T* src = end(); // points one past source element (begin()-1 not allowed)
3224 while (src != p) {
3225 --src; // now points to source
3226 moveOneElement(src+n, src);;
3227 }
3228}
3229
3230// destruct one element
3231static void destruct(T* p) {p->~T();}
3232// destruct range [b,e)
3233static void destruct(T* b, const T* e)
3234{ while(b!=e) b++->~T(); }
3235
3236// Check that growing this array by n elements wouldn't cause it to exceed
3237// its allowable maximum size.
3238template <class S>
3239bool isGrowthOK(S n) const
3240{ return this->isSizeOK(ullCapacity() + this->ull(n)); }
3241
3242// The following private methods are protected methods in the ArrayView base
3243// class, so they should not need repeating here. However, we explicitly
3244// forward to the Base methods to avoid gcc errors. The gcc complaint
3245// is due to their not depending on any template parameters; the "this->"
3246// apparently fixes that problem.
3247
3248// These provide direct access to the data members.
3249packed_size_type psize() const {return this->CBase::psize();}
3250packed_size_type pallocated() const {return this->CBase::pallocated();}
3251
3252void setData(const T* p) {this->CBase::setData(p);}
3253void setSize(size_type n) {this->CBase::setSize(n);}
3254void incrSize() {this->CBase::incrSize();}
3255void decrSize() {this->CBase::decrSize();}
3256void setAllocated(size_type n) {this->CBase::setAllocated(n);}
3257// This just cast sizes to unsigned long long so that we can do comparisons
3258// without getting warnings.
3259unsigned long long ullSize() const
3260{ return this->CBase::ullSize(); }
3261unsigned long long ullCapacity() const
3262{ return this->CBase::ullCapacity(); }
3263unsigned long long ullMaxSize() const
3264{ return this->CBase::ullMaxSize(); }
3265// This is the index type name and is handy for error messages to explain
3266// why some size was too big.
3267const char* indexName() const {return this->CBase::indexName();}
3268};
3269
3270
3271// This "private" static method is used to implement ArrayView's
3272// fillArrayViewFromStream() and Array's readArrayFromStream() namespace-scope
3273// static methods, which are in turn used to implement ArrayView's and
3274// Array's stream extraction operators ">>". This method has to be in the
3275// header file so that we don't need to pass streams through the API, but it
3276// is not intended for use by users and has no Doxygen presence, unlike
3277// fillArrayFromStream() and readArrayFromStream() and (more commonly)
3278// the extraction operators.
3279template <class T, class X> static inline
3281 (std::istream& in, bool isFixedSize, Array_<T,X>& out)
3282{
3283 // If already failed, bad, or eof, set failed bit and return without
3284 // touching the Array.
3285 if (!in.good()) {in.setstate(std::ios::failbit); return in;}
3286
3287 // If the passed-in Array isn't an owner, then we have to treat it as
3288 // a fixed size ArrayView regardless of the setting of the isFixedSize
3289 // argument.
3290 if (!out.isOwner())
3291 isFixedSize = true; // might be overriding the argument here
3292
3293 // numRequired will be ignored unless isFixedSize==true.
3294 const typename Array_<T,X>::size_type
3295 numRequired = isFixedSize ? out.size() : 0;
3296
3297 if (!isFixedSize)
3298 out.clear(); // We're going to replace the entire contents of the Array.
3299
3300 // Skip initial whitespace. If that results in eof this may be a successful
3301 // read of a 0-length, unbracketed Array. That is OK for either a
3302 // variable-length Array or a fixed-length ArrayView of length zero.
3303 std::ws(in); if (in.fail()) return in;
3304 if (in.eof()) {
3305 if (isFixedSize && numRequired != 0)
3306 in.setstate(std::ios_base::failbit); // zero elements not OK
3307 return in;
3308 }
3309
3310 // Here the stream is good and the next character is non-white.
3311 assert(in.good());
3312
3313 // Use this for raw i/o (peeks and gets).
3314 typename std::iostream::int_type ch;
3315
3316 #ifndef NDEBUG // avoid unused variable warnings in Release
3317 const typename std::iostream::int_type EOFch =
3318 std::iostream::traits_type::eof();
3319 #endif
3320
3321 // Now see if the sequence is bare or surrounded by (), [], or {}.
3322 bool lookForCloser = true;
3323 ch = in.peek(); if (in.fail()) return in;
3324 assert(ch != EOFch); // we already checked above
3325
3326 char openBracket{static_cast<char>(ch)}, closeBracket{};
3327 if (openBracket=='(') {in.get(); closeBracket = ')';}
3328 else if (openBracket=='[') {in.get(); closeBracket = ']';}
3329 else if (openBracket=='{') {in.get(); closeBracket = '}';}
3330 else lookForCloser = false;
3331
3332 // If lookForCloser is true, then closeBracket contains the terminating
3333 // delimiter, otherwise we're not going to quit until eof.
3334
3335 // Eat whitespace after the opening bracket to see what's next.
3336 if (in.good()) std::ws(in);
3337
3338 // If we're at eof now it must be because the open bracket was the
3339 // last non-white character in the stream, which is an error.
3340 if (!in.good()) {
3341 if (in.eof()) {
3342 assert(lookForCloser); // or we haven't read anything that could eof
3343 in.setstate(std::ios::failbit);
3344 }
3345 return in;
3346 }
3347
3348 // istream is good and next character is non-white; ready to read first
3349 // value or terminator.
3350
3351 // We need to figure out whether the elements are space- or comma-
3352 // separated and then insist on consistency.
3353 bool commaOK = true, commaRequired = false;
3354 bool terminatorSeen = false;
3355 X nextIndex(0);
3356 while (true) {
3357 char c;
3358
3359 // Here at the top of this loop, we have already successfully read
3360 // n=nextIndex values of type T. For fixed-size reads, it might be
3361 // the case that n==numRequired already, but we still may need to
3362 // look for a closing bracket before we can declare victory.
3363 // The stream is good() (not at eof) but it might be the case that
3364 // there is nothing but white space left; we don't know yet because
3365 // if we have satisfied the fixed-size count and are not expecting
3366 // a terminator then we should quit without absorbing the trailing
3367 // white space.
3368 assert(in.good());
3369
3370 // Look for closing bracket before trying to read value.
3371 if (lookForCloser) {
3372 // Eat white space to find the closing bracket.
3373 std::ws(in); if (!in.good()) break; // eof?
3374 ch = in.peek(); assert(ch != EOFch);
3375 if (!in.good()) break;
3376 c = (char)ch;
3377 if (c == closeBracket) {
3378 in.get(); // absorb the closing bracket
3379 terminatorSeen = true;
3380 break;
3381 }
3382 // next char not a closing bracket; fall through
3383 }
3384
3385 // We didn't look or didn't find a closing bracket. The istream is good
3386 // but we might be looking at white space.
3387
3388 // If we already got all the elements we want, break for final checks.
3389 if (isFixedSize && (nextIndex == numRequired))
3390 break; // that's a full count.
3391
3392 // Look for comma before value, except the first time.
3393 if (commaOK && nextIndex != 0) {
3394 // Eat white space to find the comma.
3395 std::ws(in); if (!in.good()) break; // eof?
3396 ch = in.peek(); assert(ch != EOFch);
3397 if (!in.good()) break;
3398 c = (char)ch;
3399 if (c == ',') {
3400 in.get(); // absorb comma
3401 commaRequired = true; // all commas from now on
3402 } else { // next char not a comma
3403 if (commaRequired) // bad, e.g.: v1, v2, v3 v4
3404 { in.setstate(std::ios::failbit); break; }
3405 else commaOK = false; // saw: v1 v2 (no commas now)
3406 }
3407 if (!in.good()) break; // might be eof
3408 }
3409
3410 // No closing bracket yet; don't have enough elements; skipped comma
3411 // if any; istream is good; might be looking at white space.
3412 assert(in.good());
3413
3414 // Now read in an element of type T.
3415 // The extractor T::operator>>() will ignore leading white space.
3416 if (!isFixedSize)
3417 out.push_back(); // grow by one (default consructed)
3418 in >> out[nextIndex]; if (in.fail()) break;
3419 ++nextIndex;
3420
3421 if (!in.good()) break; // might be eof
3422 }
3423
3424 // We will get here under a number of circumstances:
3425 // - the fail bit is set in the istream, or
3426 // - we reached eof
3427 // - we saw a closing brace
3428 // - we got all the elements we wanted (for a fixed-size read)
3429 // Note that it is possible that we consumed everything except some
3430 // trailing white space (meaning we're not technically at eof), but
3431 // for consistency with built-in operator>>()'s we won't try to absorb
3432 // that trailing white space.
3433
3434 if (!in.fail()) {
3435 if (lookForCloser && !terminatorSeen)
3436 in.setstate(std::ios::failbit); // missing terminator
3437
3438 if (isFixedSize && nextIndex != numRequired)
3439 in.setstate(std::ios::failbit); // wrong number of values
3440 }
3441
3442 return in;
3443}
3444
3445
3446
3447//------------------------------------------------------------------------------
3448// RELATED GLOBAL OPERATORS
3449//------------------------------------------------------------------------------
3450// These are logically part of the Array_<T,X> class but are not actually
3451// class members; that is, they are in the SimTK namespace.
3452
3453// Some of the serialization methods could have been member functions but
3454// then an attempt to explicitly instantiate the whole Array_<T> class for
3455// some type T would fail if T did not support the requisite I/O operations
3456// even if those operations were never used. This came up when Chris Bruns was
3457// trying to wrap Array objects for Python, which requires explicit
3458// instantiation.
3459
3467
3471template <class T, class X> inline void
3472writeUnformatted(std::ostream& o, const Array_<T,X>& v) {
3473 for (X i(0); i < v.size(); ++i) {
3474 if (i != 0) o << " ";
3475 writeUnformatted(o, v[i]);
3476 }
3477}
3478
3479
3483template <class T, class X> inline void
3484writeFormatted(std::ostream& o, const Array_<T,X>& v) {
3485 o << '(';
3486 for (X i(0); i < v.size(); ++i) {
3487 if (i != 0) o << ',';
3488 writeFormatted(o, v[i]);
3489 }
3490 o << ')';
3491}
3492
3499template <class T, class X> inline
3500std::ostream&
3501operator<<(std::ostream& o,
3502 const ArrayViewConst_<T,X>& a)
3503{
3504 o << '(';
3505 if (!a.empty()) {
3506 o << a.front();
3507 for (const T* p = a.begin()+1; p != a.end(); ++p)
3508 o << ',' << *p;
3509 }
3510 return o << ')';
3511}
3512
3513
3517template <class T, class X> inline bool
3518readUnformatted(std::istream& in, Array_<T,X>& v) {
3519 v.clear();
3520 T element;
3521 std::ws(in); // Make sure we're at eof if stream is all whitespace.
3522 while (!in.eof() && readUnformatted(in, element))
3523 v.push_back(element);
3524 return !in.fail(); // eof is expected and ok
3525}
3526
3531template <class T, class X> inline bool
3532readUnformatted(std::istream& in, ArrayView_<T,X>& v) {
3533 for (X i(0); i < v.size(); ++i)
3534 if (!readUnformatted(in, v[i])) return false;
3535 return true;
3536}
3537
3538
3544template <class T, class X> inline bool
3545readFormatted(std::istream& in, Array_<T,X>& v) {
3546 return !readArrayFromStream(in,v).fail();
3547}
3548
3554template <class T, class X> inline bool
3555readFormatted(std::istream& in, ArrayView_<T,X>& v) {
3556 return !fillArrayViewFromStream(in,v).fail();
3557}
3558
3588template <class T, class X> static inline
3589std::istream& readArrayFromStream(std::istream& in, Array_<T,X>& out)
3590{ return readArrayFromStreamHelper<T,X>(in, false /*variable sizez*/, out); }
3591
3592
3593
3618template <class T, class X> static inline
3619std::istream& fillArrayFromStream(std::istream& in, Array_<T,X>& out)
3620{ return readArrayFromStreamHelper<T,X>(in, true /*fixed size*/, out); }
3621
3626template <class T, class X> static inline
3627std::istream& fillArrayViewFromStream(std::istream& in, ArrayView_<T,X>& out)
3628{ return readArrayFromStreamHelper<T,X>(in, true /*fixed size*/, out); }
3629
3630
3631
3632
3642template <class T, class X> inline
3643std::istream& operator>>(std::istream& in, Array_<T,X>& out)
3644{ return readArrayFromStream<T,X>(in, out); }
3645
3653template <class T, class X> inline
3654std::istream& operator>>(std::istream& in, ArrayView_<T,X>& out)
3655{ return fillArrayViewFromStream<T,X>(in, out); }
3656
3666
3669template <class T1, class X1, class T2, class X2> inline bool
3671 // Avoid warnings in size comparison by using common type.
3672 const ptrdiff_t sz1 = a1.end()-a1.begin();
3673 const ptrdiff_t sz2 = a2.end()-a2.begin();
3674 if (sz1 != sz2) return false;
3675 const T1* p1 = a1.begin();
3676 const T2* p2 = a2.begin();
3677 while (p1 != a1.end())
3678 if (!(*p1++ == *p2++)) return false;
3679 return true;
3680}
3683template <class T1, class X1, class T2, class X2> inline bool
3685{ return !(a1 == a2); }
3686
3691template <class T1, class X1, class T2, class X2> inline bool
3693 const T1* p1 = a1.begin();
3694 const T2* p2 = a2.begin();
3695 while (p1 != a1.end() && p2 != a2.end()) {
3696 if (!(*p1 == *p2))
3697 return *p1 < *p2; // otherwise p1 > p2
3698 ++p1; ++p2;
3699 }
3700 // All elements were equal until one or both arrays ran out of elements.
3701 // a1 is less than a2 only if a1 ran out and a2 didn't.
3702 return p1 == a1.end() && p2 != a2.end();
3703}
3706template <class T1, class X1, class T2, class X2> inline bool
3708{ return !(a1 < a2); }
3712template <class T1, class X1, class T2, class X2> inline bool
3714{ return a2 < a1; }
3717template <class T1, class X1, class T2, class X2> inline bool
3719{ return !(a1 > a2); }
3720
3724template <class T1, class X1, class T2, class A2> inline bool
3725operator==(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3726{ return a1 == ArrayViewConst_<T2,size_t>(v2); }
3727
3731template <class T1, class A1, class T2, class X2> inline bool
3732operator==(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3733{ return a2 == v1; }
3734
3737template <class T1, class X1, class T2, class A2> inline bool
3738operator!=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3739{ return !(a1 == v2); }
3742template <class T1, class A1, class T2, class X2> inline bool
3743operator!=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3744{ return !(a2 == v1); }
3745
3751template <class T1, class X1, class T2, class A2> inline bool
3752operator<(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3753{ return a1 < ArrayViewConst_<T2,size_t>(v2); }
3754
3760template <class T1, class A1, class T2, class X2> inline bool
3761operator<(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3762{ return ArrayViewConst_<T1,size_t>(v1) < a2; }
3763
3766template <class T1, class X1, class T2, class A2> inline bool
3767operator>=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3768{ return !(a1 < v2); }
3771template <class T1, class A1, class T2, class X2> inline bool
3772operator>=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3773{ return !(v1 < a2); }
3774
3778template <class T1, class X1, class T2, class A2> inline bool
3779operator>(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3780{ return v2 < a1; }
3784template <class T1, class A1, class T2, class X2> inline bool
3785operator>(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3786{ return a2 < v1; }
3787
3790template <class T1, class X1, class T2, class A2> inline bool
3791operator<=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2)
3792{ return !(a1 > v2); }
3795template <class T1, class A1, class T2, class X2> inline bool
3796operator<=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2)
3797{ return !(v1 > a2); }
3798
3801} // namespace SimTK
3802
3803namespace std {
3807template <class T, class X> inline void
3809 a1.swap(a2);
3810}
3811
3812} // namespace std
3813
3814#endif // SimTK_SimTKCOMMON_ARRAY_H_
This file contains macros which are convenient to use for sprinkling error checking around liberally ...
#define SimTK_ERRCHK3_ALWAYS(cond, whereChecked, fmt, a1, a2, a3)
Definition: ExceptionMacros.h:293
#define SimTK_INDEXCHECK(ix, ub, where)
Definition: ExceptionMacros.h:145
#define SimTK_ERRCHK2_ALWAYS(cond, whereChecked, fmt, a1, a2)
Definition: ExceptionMacros.h:289
#define SimTK_ERRCHK_ALWAYS(cond, whereChecked, msg)
Definition: ExceptionMacros.h:281
#define SimTK_INDEXCHECK_ALWAYS(ix, ub, where)
Definition: ExceptionMacros.h:106
#define SimTK_ERRCHK2(cond, whereChecked, fmt, a1, a2)
Definition: ExceptionMacros.h:328
#define SimTK_ASSERT(cond, msg)
Definition: ExceptionMacros.h:373
#define SimTK_ERRCHK1_ALWAYS(cond, whereChecked, fmt, a1)
Definition: ExceptionMacros.h:285
#define SimTK_ERRCHK3(cond, whereChecked, fmt, a1, a2, a3)
Definition: ExceptionMacros.h:330
#define SimTK_ERRCHK(cond, whereChecked, msg)
Definition: ExceptionMacros.h:324
#define SimTK_SIZECHECK(sz, maxsz, where)
Definition: ExceptionMacros.h:146
This file contains definitions of templatized serialize-to-stream methods specialized for the built-i...
Mandatory first inclusion for any Simbody source or header file.
#define SimTK_FORCE_INLINE
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:269
This Array_ helper class is the base class for ArrayView_ which is the base class for Array_; here we...
Definition: Array.h:324
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:529
const T * end() const
The const version of end() is the same as cend().
Definition: Array.h:650
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:585
bool empty() const
Return true if there are no elements currently stored in this array.
Definition: Array.h:519
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:621
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:646
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:358
const T & operator[](index_type i) const
Select an element by its index, returning a const reference.
Definition: Array.h:554
T * pointer
A writable pointer to a value_type.
Definition: Array.h:339
T value_type
The type of object stored in this container.
Definition: Array.h:335
T * iterator
A writable iterator for this container (same as pointer here).
Definition: Array.h:347
const T & const_reference
A const value_type reference.
Definition: Array.h:345
size_type max_size() const
Return the maximum allowable size for this array.
Definition: Array.h:515
std::reverse_iterator< iterator > reverse_iterator
A writable reverse iterator for this container.
Definition: Array.h:351
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:568
ArrayViewConst_(const ArrayViewConst_ &src)
Copy constructor is shallow; the constructed const array object will be referencing the original sour...
Definition: Array.h:384
size_type size() const
Return the current number of elements stored in this array.
Definition: Array.h:513
~ArrayViewConst_()
The destructor just disconnects the array view handle from its data; see disconnect() for more inform...
Definition: Array.h:498
ArrayViewConst_()
Default constructor allocates no heap space and is very fast.
Definition: Array.h:373
const T * begin() const
The const version of begin() is the same as cbegin().
Definition: Array.h:648
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:672
const T * const_iterator
A const iterator for this container (same as const_pointer here).
Definition: Array.h:349
const T * const_pointer
A const pointer to a value_type.
Definition: Array.h:341
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:659
const_reverse_iterator rbegin() const
The const version of rbegin() is the same as crbegin().
Definition: Array.h:662
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:577
const T & at(index_type i) const
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:562
size_type capacity() const
Return the number of elements this array can currently hold without requiring reallocation.
Definition: Array.h:524
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:654
T & reference
A writable value_type reference.
Definition: Array.h:343
std::reverse_iterator< const_iterator > const_reverse_iterator
A const reverse iterator for this container.
Definition: Array.h:353
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:607
ArrayViewConst_(const T *first, const T *last1)
Construct an ArrayViewConst_<T> by referencing (sharing) a given range of const data [first,...
Definition: Array.h:413
ArrayIndexTraits< X >::size_type size_type
An integral type suitable for all indices and sizes for this array.
Definition: Array.h:355
ArrayViewConst_(const std::vector< T, A > &src)
Construct a ArrayViewConst_<T> by referencing (sharing) the data in a const std::vector<T>,...
Definition: Array.h:461
void disconnect()
Disconnect this array handle from any data to which it refers, restoring it to the condition it would...
Definition: Array.h:489
const T * data() const
The const version of the data() method is identical to cdata().
Definition: Array.h:674
const_reverse_iterator rend() const
The const version of rend() is the same as crend().
Definition: Array.h:664
ArrayIndexPackType< size_type >::packed_size_type packed_size_type
The integral type we actually use internally to store size_type values.
Definition: Array.h:361
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:535
X index_type
The index type (an extension).
Definition: Array.h:337
const T * cbegin() const
Return a const pointer to the first element of this array if any, otherwise cend(),...
Definition: Array.h:641
This Array_ helper class is the base class for Array_, extending ArrayViewConst_ to add the ability t...
Definition: Array.h:845
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:1240
T & back()
Return a writable reference to the last element in this array, which must not be empty.
Definition: Array.h:1135
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:985
bool isOwner() const
Definition: Array.h:1268
const T * const_iterator
Definition: Array.h:861
ArrayView_(std::vector< T, A > &v)
Construct to reference memory owned by a writable std::vector.
Definition: Array.h:889
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:935
const T & at(index_type i) const
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:1092
const T & back() const
Return a const reference to the last element in this array, which must not be empty.
Definition: Array.h:1128
ArrayView_ & operator=(const T &fillValue)
Fill assignment – all elements are set to fillValue.
Definition: Array.h:968
size_type max_size() const
Definition: Array.h:1264
const T * begin() const
The const version of begin() is the same as cbegin().
Definition: Array.h:1190
T & front()
Return a writable reference to the first element in this array, which must not be empty.
Definition: Array.h:1121
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:1212
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:3532
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:1169
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:1013
T * pointer
Definition: Array.h:856
T * end()
Return a writable pointer to what would be the element just after the last one in this array.
Definition: Array.h:1208
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:3627
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:1102
const T & front() const
Return a const reference to the first element in this array, which must not be empty.
Definition: Array.h:1114
~ArrayView_()
The destructor just disconnects the array view handle from its data; see ArrayViewConst_<T,...
Definition: Array.h:905
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:1201
size_type capacity() const
Definition: Array.h:1266
T & at(index_type i)
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:1098
const T & const_reference
Definition: Array.h:859
T * iterator
Definition: Array.h:860
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:954
const T * cbegin() const
Return a const pointer to the first element of this array if any, otherwise end(),...
Definition: Array.h:1188
std::reverse_iterator< iterator > reverse_iterator
Definition: Array.h:862
reverse_iterator rend()
Return a writable past-the-end reverse iterator that tests equal to a reverse iterator that has been ...
Definition: Array.h:1232
bool empty() const
Definition: Array.h:1265
const T * end() const
The const version of end() is the same as cend().
Definition: Array.h:1203
void disconnect()
Forward to base class disconnect() method – clears the handle without doing anything to the data.
Definition: Array.h:901
ArrayView_(T *first, const T *last1)
Construct from a range of writable memory.
Definition: Array.h:885
size_type size() const
Definition: Array.h:1263
ArrayIndexPackType< size_type >::packed_size_type packed_size_type
Definition: Array.h:867
T & operator[](index_type i)
Select an element by its index, returning a writable (lvalue) reference.
Definition: Array.h:1085
bool readFormatted(std::istream &in, ArrayView_< T, X > &v)
Specialization of readFormatted() for fixed-length ArrayView_<T,X>; uses fillArrayViewFromStream() to...
Definition: Array.h:3555
ArrayView_()
Default constructor allocates no heap space and is very fast.
Definition: Array.h:879
T * begin()
Return a writable pointer to the first element of this array if any, otherwise end().
Definition: Array.h:1195
T & reference
Definition: Array.h:858
ArrayIndexTraits< X >::size_type size_type
Definition: Array.h:864
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:1155
ArrayIndexTraits< X >::difference_type difference_type
Definition: Array.h:865
const T & operator[](index_type i) const
Select an element by its index, returning a const reference.
Definition: Array.h:1075
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: Array.h:863
size_type allocated() const
Definition: Array.h:1267
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:960
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:3654
const_reverse_iterator rbegin() const
The const version of rbegin() is the same as crbegin().
Definition: Array.h:1215
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:1224
ArrayView_(const ArrayView_ &src)
Copy constructor is shallow.
Definition: Array.h:882
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:976
const T * const_pointer
Definition: Array.h:857
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:1106
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:1219
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:949
const T * data() const
The const version of the data() method is identical to cdata().
Definition: Array.h:1243
X index_type
Definition: Array.h:855
T value_type
Definition: Array.h:854
const_reverse_iterator rend() const
The const version of rend() is the same as crend().
Definition: Array.h:1227
T * data()
Return a writable pointer to the first allocated element of the array, or a null pointer if no space ...
Definition: Array.h:1247
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:1055
ArrayView_ & operator=(const ArrayView_ &src)
Copy assignment; source must be the same size as this array.
Definition: Array.h:923
The Array_<T> container class is a plug-compatible replacement for the C++ standard template library ...
Definition: Array.h:1520
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:3472
T & back()
Return a writable reference to the last element in this array, which must not be empty.
Definition: Array.h:2344
T * iterator
Definition: Array.h:1540
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:3589
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:2357
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:2264
const T * begin() const
The const version of begin() is the same as cbegin().
Definition: Array.h:2214
void assign(size_type n, const T &fillValue)
Set this array to be n copies of the supplied fillValue.
Definition: Array.h:1818
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:2399
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:1877
void reserve(size_type n)
Ensure that this array has enough allocated capacity to hold the indicated number of elements.
Definition: Array.h:2136
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:1935
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:3772
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:2316
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:3670
const T * const_pointer
Definition: Array.h:1537
Array_ & operator=(const std::vector< T2, A > &src)
This is assignment from a source std::vector<T2>.
Definition: Array.h:1969
T * emplace(T *p, Args &&... args)
Insert a new element at a given location within this array, by invoking T's constructor whose signatu...
Definition: Array.h:2658
const T & front() const
Return a const reference to the first element in this array, which must not be empty.
Definition: Array.h:2323
T * raw_push_back()
(Deprecated, use emplace_back() instead) This dangerous non-standard method increases the Array's siz...
Definition: Array.h:2477
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:2696
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:1736
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:3619
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:2187
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:1956
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:3725
ArrayIndexTraits< X >::difference_type difference_type
Definition: Array.h:1545
X index_type
Definition: Array.h:1535
const T & const_reference
Definition: Array.h:1539
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:2091
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 doe...
Definition: Array.h:1636
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:2016
T & front()
Return a writable reference to the first element in this array, which must not be empty.
Definition: Array.h:2330
const T * const_iterator
Definition: Array.h:1541
void push_back(T &&value)
This is the move form of push_back(), taking an rvalue reference rather than an lvalue reference.
Definition: Array.h:2410
const T & at(index_type i) const
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:2302
void swap(Array_ &other)
This is a specialized algorithm providing constant time exchange of data with another array that has ...
Definition: Array.h:1983
Array_(T *first, const T *last1, const DontCopy &)
Construct an Array_<T> by referencing (sharing) a given range of data [first,last1),...
Definition: Array.h:1706
void pop_back()
Remove the last element from this array, which must not be empty.
Definition: Array.h:2487
reverse_iterator rend()
Return a writable past-the-end reverse iterator that tests equal to a reverse iterator that has been ...
Definition: Array.h:2256
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:3732
T * end()
Return a writable pointer to what would be the element just after the last one in this array.
Definition: Array.h:2232
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:2510
Array_ & deallocate()
Empty this array of its contents, returning the array to its default-constructed, all-zero state.
Definition: Array.h:1753
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:3545
void fill(const T &fillValue)
Assign all current elements of the array to the same fillValue.
Definition: Array.h:1852
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:3738
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:3484
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:3518
T & operator[](index_type i)
Select an element by its index, returning a writable (lvalue) reference.
Definition: Array.h:2296
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:1598
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:2632
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...
Definition: Array.h:1608
size_type capacity() const
Return the number of elements this array can currently hold without requiring reallocation.
Definition: Array.h:2085
Array_ & operator=(Array_ &&src)
Move assignment operator swaps the contents of this Array_ with the source Array_.
Definition: Array.h:1945
Array_(size_type n)
Construct an array containing n default-constructed elements.
Definition: Array.h:1566
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:2578
void push_back()
(Deprecated, use emplace_back() instead) This is a non-standard version of push_back() that increases...
Definition: Array.h:2450
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:2348
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:3743
ArrayIndexTraits< X >::size_type size_type
Definition: Array.h:1544
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:1994
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:3767
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:3808
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:2248
size_type size() const
Return the current number of elements stored in this array.
Definition: Array.h:2075
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:2050
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: Array.h:1543
T * data()
Return a writable pointer to the first allocated element of the array, or a null pointer if no space ...
Definition: Array.h:2271
std::reverse_iterator< iterator > reverse_iterator
Definition: Array.h:1542
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:2352
const_reverse_iterator rend() const
The const version of rend() is the same as crend().
Definition: Array.h:2251
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:3684
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:2243
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:2545
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:2172
void assign(const Iter &first, const Iter &last1)
Assign this array from a range [first,last1) given by non-pointer iterators.
Definition: Array.h:1925
ArrayIndexPackType< size_type >::packed_size_type packed_size_type
Definition: Array.h:1547
const T * end() const
The const version of end() is the same as cend().
Definition: Array.h:2227
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:2113
Array_(std::initializer_list< T > ilist)
Construct an Array_<T> from an std::initializer_list whose elements were convertible to type T,...
Definition: Array.h:1628
const T & back() const
Return a const reference to the last element in this array, which must not be empty.
Definition: Array.h:2337
T value_type
Definition: Array.h:1534
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,...
Definition: Array.h:3713
bool empty() const
Return true if there are no elements currently stored in this array.
Definition: Array.h:2080
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,...
Definition: Array.h:3779
const T * data() const
The const version of the data() method is identical to cdata().
Definition: Array.h:2267
~Array_()
The destructor performs a deallocate() operation which may result in element destruction and freeing ...
Definition: Array.h:1741
const T & operator[](index_type i) const
Select an element by its index, returning a const reference.
Definition: Array.h:2286
void emplace_back(Args &&... args)
This is similar to push_back() but rather than copying, it constructs the element in place at the end...
Definition: Array.h:2426
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:2361
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:1576
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,...
Definition: Array.h:3785
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:3707
const_reverse_iterator rbegin() const
The const version of rbegin() is the same as crbegin().
Definition: Array.h:2239
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:3643
Array_()
Default constructor allocates no heap space and is very fast.
Definition: Array.h:1560
size_type max_size() const
Return the maximum allowable size for this array.
Definition: Array.h:2077
T * pointer
Definition: Array.h:1536
T & reference
Definition: Array.h:1538
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:2312
T & at(index_type i)
Same as operator[] but always range-checked, even in a Release build.
Definition: Array.h:2308
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:2711
const T * cbegin() const
Return a const pointer to the first element of this array if any, otherwise cend(),...
Definition: Array.h:2212
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:2194
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:2236
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:2033
Array_(Array_ &&src)
Move constructor swaps in the source and leaves the source default constructed.
Definition: Array.h:1662
T * begin()
Return a writable pointer to the first element of this array if any, otherwise end().
Definition: Array.h:2219
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:1673
void clear()
Erase all the elements currently in this array without changing the capacity; equivalent to erase(beg...
Definition: Array.h:2598
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:2644
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:2225
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:1654
An element has (1) a tagword, (2) a map of (name,value) pairs called attributes, and (3) a list of ch...
Definition: Xml.h:1033
bool readUnformatted(std::istream &in, T &v)
The default implementation of readUnformatted<T> reads in the next whitespace-separated token and the...
Definition: Serialize.h:176
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:286
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:76
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition: Assembler.h:37
bool isSizeInRange(char sz, char mx)
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:338
ELEM max(const VectorBase< ELEM > &v)
Definition: VectorMath.h:251
ELEM min(const VectorBase< ELEM > &v)
Definition: VectorMath.h:178
std::ostream & operator<<(std::ostream &o, const ContactForce &f)
Definition: CompliantContactSubsystem.h:387
static std::istream & readArrayFromStreamHelper(std::istream &in, bool isFixedSize, Array_< T, X > &out)
Definition: Array.h:3281
bool operator<(const Row< N, E1, S1 > &l, const Row< N, E2, S2 > &r)
bool = v1[i] < v2[i], for all elements i
Definition: Row.h:822
bool operator<=(const L &left, const R &right)
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:653
signed char difference_type
Definition: Array.h:227
static size_type max_size()
Definition: Array.h:228
unsigned char size_type
Definition: Array.h:226
signed char difference_type
Definition: Array.h:216
char size_type
Definition: Array.h:215
static size_type max_size()
Definition: Array.h:217
int difference_type
Definition: Array.h:135
static size_type max_size()
Definition: Array.h:136
int size_type
Definition: Array.h:134
long size_type
Definition: Array.h:160
long difference_type
Definition: Array.h:161
static size_type max_size()
Definition: Array.h:162
long long difference_type
Definition: Array.h:244
long long size_type
Definition: Array.h:243
static size_type max_size()
Definition: Array.h:245
short size_type
Definition: Array.h:181
short difference_type
Definition: Array.h:182
static size_type max_size()
Definition: Array.h:183
static size_type max_size()
Definition: Array.h:205
signed char difference_type
Definition: Array.h:204
signed char size_type
Definition: Array.h:203
static size_type max_size()
Definition: Array.h:129
unsigned size_type
Definition: Array.h:127
int difference_type
Definition: Array.h:128
short difference_type
Definition: Array.h:193
unsigned char size_type
Definition: Array.h:192
static size_type max_size()
Definition: Array.h:194
unsigned long size_type
Definition: Array.h:147
long difference_type
Definition: Array.h:148
static size_type max_size()
Definition: Array.h:149
long long difference_type
Definition: Array.h:235
unsigned long long size_type
Definition: Array.h:234
static size_type max_size()
Definition: Array.h:236
int difference_type
Definition: Array.h:172
unsigned short size_type
Definition: Array.h:171
static size_type max_size()
Definition: Array.h:173
This templatized type is used by the Array_<T,X> classes to obtain the information they need to use t...
Definition: Array.h:112
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:121
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:118
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:115
This is a special type used for causing invocation of a particular constructor or method overload tha...
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:670
This is a compile-time equivalent of "false", used in compile-time condition checking in templatized ...
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:678
static const char * name()
The default implementation of name() here returns the raw result from typeid(T).
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:862
This is a compile-time equivalent of "true", used in compile-time condition checking in templatized i...
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:681