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 27 /** @file 28 * This file defines the Array_<T,X> class and related support classes 29 * including base classes ArrayViewConst_<T,X> and ArrayView_<T,X>, and 30 * helper class ArrayIndexTraits<X>. 31 */ 32 33 #include "SimTKcommon/internal/common.h" 34 #include "SimTKcommon/internal/ExceptionMacros.h" 35 #include "SimTKcommon/internal/Serialize.h" 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 47 namespace SimTK { 48 49 // These are the classes defined in this header. 50 template <class X> struct ArrayIndexTraits; 51 template <class T, class X=unsigned> class ArrayViewConst_; 52 template <class T, class X=unsigned> class ArrayView_; 53 template <class T, class X=unsigned> class Array_; 54 55 namespace Xml { 56 class 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 70 /** This templatized type is used by the Array_<T,X> classes to obtain the 71 information they need to use the class X as an index class for the array. 72 There must be a specialization here providing ArrayIndexTraits for each of 73 the built-in integral types that is suitable for use as an index. Any other 74 type X will qualify as an index if it defines the following members: 75 76 - typedef size_type 77 - typedef difference_type 78 - static size_type max_size() 79 - operator size_type() const (conversion from X to size_type) 80 81 max_size() determines the largest number of elements that a container may hold 82 if its index type is X. 83 84 size_type must be an integral type large enough to hold 85 all the values from 0 to max_size(), including all the index values (which 86 range from 0 to max_size()-1). size_type may be signed or unsigned; it is the 87 type returned by size(), max_size(), capacity(), etc. and may be compared 88 directly against an index of type X without producing a compiler warning. 89 90 difference_type is a signed integral type that can hold all possible 91 differences between two indices, that is, values between -(max_size()-1) and 92 +(max_size()-1). In most cases we use an integral type with the same number of 93 bits for size_type and difference_type but when the index type is very small 94 (bool, unsigned char, or unsigned short) we want to allow the full range (2, 95 255, or 65535 elements, resp.) in which case we need a wider type to hold the 96 differences. 97 98 The conversion operator ensures that we can write size_type(i) for an index 99 i of type X. An explicit conversion member does not need to be present as long 100 as the conversion size_type(i) already works as it does for all the integral 101 type specializations. 102 103 The SimTK type-generating macro SimTK_DEFINE_UNIQUE_INDEX_TYPE() provides the 104 necessary members so that these types can be used directly as index types for 105 Array_ objects with no further preparation. For example, you can make an 106 Array_<int,MobilizedBodyIndex> that stores ints that can be indexed only via 107 MobilizedBodyIndex indices. 108 109 @tparam X A type suitable for use as an Array_ index. 110 @see Array_ 111 **/ 112 template <class X> struct ArrayIndexTraits { 113 /** The signed or unsigned integral type to which an object of index type 114 X can be converted without producing any compiler warnings. **/ 115 typedef typename X::size_type size_type; 116 /** A signed integral type large enough to hold the full range of 117 possible signed differences i-j between two indices i and j of type X. **/ 118 typedef typename X::difference_type difference_type; 119 /** The maximum allowable size for any Array_<T,X> that uses this type X 120 as its index type. **/ max_sizeArrayIndexTraits121 static size_type max_size() {return X::max_size();} 122 }; 123 124 /** Specialization of ArrayIndexTraits for \c unsigned (that is, \c unsigned 125 \c int) used as an index. **/ 126 template <> 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 132 /** Specialization of ArrayIndexTraits for (signed) \c int used as an index. **/ 133 template <> struct ArrayIndexTraits<int> { 134 typedef int size_type; 135 typedef int difference_type; 136 static size_type max_size() {return INT_MAX;} 137 }; 138 139 /** Specialization of ArrayIndexTraits for \c unsigned \c long used as an index. 140 @warning 141 Different 64 bit platforms have different lengths for long. In particular, 142 64 bit MSVC++ has sizeof(long)==sizeof(int) while 64 bit gcc has 143 sizeof(long)==sizeof(long long). We recommend that you avoid using long 144 and unsigned long (ever, not just here) and instead use int or long long (or 145 their unsigned versions) which are unambiguously 32 or 64 bits, resp. **/ 146 template <> 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 152 /** Specialization of ArrayIndexTraits for (signed) \c long used as an index. 153 @warning 154 Different 64 bit platforms have different lengths for long. In particular, 155 64 bit MSVC++ has sizeof(long)==sizeof(int) while 64 bit gcc has 156 sizeof(long)==sizeof(long long). We recommend that you avoid using long 157 and unsigned long (ever, not just here) and instead use int or long long (or 158 their unsigned versions) which are unambiguously 32 or 64 bits, resp. **/ 159 template <> struct ArrayIndexTraits<long> { 160 typedef long size_type; 161 typedef long difference_type; 162 static size_type max_size() {return LONG_MAX;} 163 }; 164 165 /** Specialization of ArrayIndexTraits for \c unsigned \c short used as an 166 index. We don't have any bits to spare here so we want to allow the full 167 65535 elements for an unsigned short indexed container. That means the index 168 difference range is -65534..+65534 which doesn't fit in a short so we have to 169 use an int for difference_type to accommodate the whole range. **/ 170 template <> 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 176 /** Specialization of ArrayIndexTraits for (signed) \c short used as an 177 index. In contrast to unsigned short, here the max size is 32767 so the index 178 difference range -32766..+32766 still fits in a short so we don't need a wider 179 type for difference_type. **/ 180 template <> 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 187 /** Specialization of ArrayIndexTraits for \c unsigned \c char used as 188 an index. Here we don't have any bits to spare and we want to use the full 189 max size of 255. The max index must then be 254, so the difference_type must 190 hold -254..254 which takes a short. **/ 191 template <> 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 197 /** Specialization of ArrayIndexTraits for \c signed \c char used as 198 an index. In contrast with the unsigned char case which allows 255 elements, 199 the max size here is 127 meaning the max index is 126 and the difference range 200 is -126..126 which still fits in a signed char so we don't need a wider type 201 for difference_type. **/ 202 template <> 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 208 /** Specialization of ArrayIndexTraits for \c char used as 209 an index. The C++ standard does not specify whether \c char is a signed or 210 unsigned type; here we'll limit its max size to 127 so that we don't have 211 to use the non-standard high bit. That means it behaves just like the signed 212 char case; if you want the full range to a size of 255, use unsigned char 213 instead. **/ 214 template <> 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 220 /** Specialization of ArrayIndexTraits for \c bool used as an index. OK, this 221 seems unlikely but it works fine -- you get a container that can hold only two 222 elements indexed by either \c false (0) or \c true (1). You'll get warnings 223 if you try to index with an ordinary int. If anyone finds a legitimate use for 224 this, please post to the forum and let us know! **/ 225 template <> 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 231 /** Specialization of ArrayIndexTraits for \c unsigned \c long \c long used as 232 an index. This only makes sense in a 64-bit compilation. **/ 233 template <> struct ArrayIndexTraits<unsigned long long> { 234 typedef unsigned long long size_type; 235 typedef long long difference_type; 236 static size_type max_size() 237 {return (unsigned long long)LLONG_MAX;} 238 }; 239 240 /** Specialization of ArrayIndexTraits for \c long \c long used as 241 an index. This only makes sense in a 64-bit compilation. **/ 242 template <> 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. 249 /** @cond **/ 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. 258 template <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. 262 template<> struct ArrayIndexPackTypeHelper<bool,FalseType> 263 { typedef unsigned short packed_size_type;}; 264 template<> struct ArrayIndexPackTypeHelper<char,FalseType> 265 { typedef unsigned short packed_size_type;}; 266 template<> struct ArrayIndexPackTypeHelper<unsigned char,FalseType> 267 { typedef unsigned short packed_size_type;}; 268 template<> 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. 272 template<> struct ArrayIndexPackTypeHelper<bool,TrueType> 273 { typedef unsigned int packed_size_type;}; 274 template<> struct ArrayIndexPackTypeHelper<char,TrueType> 275 { typedef unsigned int packed_size_type;}; 276 template<> struct ArrayIndexPackTypeHelper<unsigned char,TrueType> 277 { typedef unsigned int packed_size_type;}; 278 template<> struct ArrayIndexPackTypeHelper<signed char,TrueType> 279 { typedef int packed_size_type;}; 280 template<> struct ArrayIndexPackTypeHelper<unsigned short,TrueType> 281 { typedef unsigned int packed_size_type;}; 282 template<> struct ArrayIndexPackTypeHelper<short,TrueType> 283 { typedef int packed_size_type;}; 284 285 template <class Integral> struct ArrayIndexPackType 286 { typedef typename ArrayIndexPackTypeHelper<Integral,Is64BitPlatformType> 287 ::packed_size_type packed_size_type;}; 288 /** @endcond **/ 289 290 291 292 293 294 295 //============================================================================== 296 // CLASS ArrayViewConst_ 297 //============================================================================== 298 /** This Array_ helper class is the base class for ArrayView_ which is the 299 base class for Array_; here we provide only the minimal read-only "const" 300 functionality required by any Array_ object, and shallow copy semantics. The 301 ability to write is added by the ArrayView_ class, and the additional ability 302 to reallocate, insert, erase, etc. is added by the Array_ class. 303 304 This class is particularly useful for recasting existing const data into a 305 const Array_ without copying. For example a const std::vector can be passed 306 to a const Array& argument by an implicit, near-zero cost conversion to an 307 ArrayViewConst_ which can then convert to a const Array&. 308 309 An ArrayViewConst_ is given all the data it is going to have at the time it is 310 constructed (except when it is being accessed from the derived Array_ class 311 that has more capability). The contents and size of a ArrayViewConst_ cannot be 312 changed after construction. In particular, the default copy assignment operator 313 is suppressed. The destructor simply disconnects the ArrayViewConst_ handle 314 from the data it was referencing; no element destruction or heap deallocation 315 occurs. 316 317 @tparam T 318 The type of object to be stored in this container. 319 @tparam X 320 The type to be used for indexing this container, with default unsigned 321 (not size_t). Any integral type may be used, as well as user types that 322 satisfy the requirements discussed with class ArrayIndexTraits. 323 @see Array_, ArrayView_, ArrayIndexTraits **/ 324 template <class T, class X> class ArrayViewConst_ { 325 public: 326 327 328 //------------------------------------------------------------------------------ 329 /** @name Typedefs 330 331 Types required of STL containers, plus index_type which is an extension, and 332 packed_size_type which is an implementation detail. **/ 333 /*@{*/ 334 /** The type of object stored in this container. **/ 335 typedef T value_type; 336 /** The index type (an extension). **/ 337 typedef X index_type; 338 /** A writable pointer to a value_type. **/ 339 typedef T* pointer; 340 /** A const pointer to a value_type. **/ 341 typedef const T* const_pointer; 342 /** A writable value_type reference. **/ 343 typedef T& reference; 344 /** A const value_type reference. **/ 345 typedef const T& const_reference; 346 /** A writable iterator for this container (same as pointer here). **/ 347 typedef T* iterator; 348 /** A const iterator for this container (same as const_pointer here). **/ 349 typedef const T* const_iterator; 350 /** A writable reverse iterator for this container. **/ 351 typedef std::reverse_iterator<iterator> reverse_iterator; 352 /** A const reverse iterator for this container. **/ 353 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 354 /** An integral type suitable for all indices and sizes for this array. **/ 355 typedef typename ArrayIndexTraits<X>::size_type size_type; 356 /** A signed integral type that can represent the difference between any two 357 legitimate index values for this array. **/ 358 typedef typename ArrayIndexTraits<X>::difference_type difference_type; 359 /** The integral type we actually use internally to store size_type values. **/ 360 typedef typename ArrayIndexPackType<size_type>::packed_size_type 361 packed_size_type; 362 /*@} End of typedefs **/ 363 364 365 //------------------------------------------------------------------------------ 366 /** @name Construction, conversion, and destruction 367 368 Constructors here are limited to those that don't allocate new data, and can 369 only accept const data to reference. Copy assignment is suppressed. **/ 370 /*@{*/ 371 372 /** Default constructor allocates no heap space and is very fast. **/ 373 ArrayViewConst_() : pData(0), nUsed(0), nAllocated(0) {} 374 375 /** Copy constructor is shallow; the constructed const array object will be 376 referencing the original source data. However, if the source is zero length, 377 this will result in a default-constructed array view handle with a null data 378 pointer, even if the source had some unused data allocated. 379 380 @param[in] src 381 The object whose data will be referenced. 382 @par Complexity: 383 Constant time; extremely fast. **/ 384 ArrayViewConst_(const ArrayViewConst_& src) 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 391 /** Construct an ArrayViewConst_<T> by referencing (sharing) a given range of 392 const data [first,last1), without copying that data. This will work as long as 393 the size of the source data does not exceed the array's max_size. The resulting 394 object is not resizeable but can be used to read elements of the original data. 395 This will becomes invalid if the original data is destructed or resized, but 396 there is no way for the ArrayViewConst_ class to detect that. 397 398 @param[in] first 399 A pointer to the first data element to be referenced. 400 @param[in] last1 401 A pointer to the position one element past the last one in the range to be 402 referenced. 403 @remarks 404 - If the source data is empty, the resulting ArrayViewConst_ will also 405 be empty and will look as though it had been default-constructed. 406 - You can break the connection between the array handle and the data it 407 was constructed from by calling disconnect(). 408 @pre first <= last1, last1-first <= max_size() 409 @par Complexity: 410 Dirt cheap. There will be no construction, destruction, or heap allocation 411 performed. 412 @see disconnect() **/ 413 ArrayViewConst_(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 433 /** Construct a ArrayViewConst_<T> by referencing (sharing) the data in a const 434 std::vector<T>, without copying the data; this is also an implicit conversion. 435 This will work as long as the size of the vector does not exceed the array's 436 max_size. The resulting array object is not resizeable but can be used to read 437 elements of the original std::vector. The array becomes invalid if the original 438 std::vector is destructed or resized, but there is no way for the array class 439 to detect that. 440 441 @param[in] src 442 The std::vector<T> whose data will be referenced by the constructed 443 ArrayViewConst_ handle. 444 @remarks 445 - If the source std::vector is empty, the resulting array will also be empty 446 and will look as though it had been default-constructed. It will therefore 447 not have any connection to the source vector. 448 - This is quite dangerous to use since the connection between the array 449 and the vector is tenuous and subject to the vector remaining untouched 450 during the lifetime of the array handle. There is no reference 451 counting; destructing the vector leaves the array referring to garbage. Be 452 careful! 453 - You can break the connection between the array view and the vector it was 454 constructed from by calling disconnect(). 455 @pre src.size() <= max_size() 456 @par Complexity: 457 Dirt cheap. There will be no construction, destruction, or heap allocation 458 performed. 459 @see disconnect() **/ 460 template <class A> 461 ArrayViewConst_(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 } 475 /** This is an implicit conversion to const ArrayView_<T,X>&, which is 476 harmless since the const result won't permit writing on the elements. **/ 477 operator const ArrayView_<T,X>&() const 478 { return *reinterpret_cast<const ArrayView_<T,X>*>(this); } 479 /** This is an implicit conversion to const Array_<T,X>&, which is harmless 480 since the const result can't be used to write on or resize the data. **/ 481 operator const Array_<T,X>&() const 482 { return *reinterpret_cast<const Array_<T,X>*>(this); } 483 484 /** Disconnect this array handle from any data to which it refers, 485 restoring it to the condition it would be in if it had just been 486 default-constructed. The data pointer will simply be set to null; we'll assume 487 the owner will clean things up later. In either case the size() and capacity() 488 will be zero after this call and data() will return null (0). **/ 489 void disconnect() { 490 SimTK_ASSERT(nAllocated==0, 491 "ArrayViewConst_::deallocate(): called on an owner Array_"); 492 nUsed = 0; 493 pData = 0; 494 } 495 496 /** The destructor just disconnects the array view handle from its data; see 497 disconnect() for more information. @see disconnect() **/ 498 ~ArrayViewConst_() { 499 disconnect(); 500 } 501 /*@} End of constructors, etc. **/ 502 503 504 //------------------------------------------------------------------------------ 505 /** @name Size and capacity 506 507 These methods examine the number of elements (size) or the amount of allocated 508 heap space (capacity). See the derived Array_<T,X> class for methods that can 509 \e change the size or capacity. **/ 510 /*@{*/ 511 512 /** Return the current number of elements stored in this array. **/ 513 size_type size() const {return size_type(nUsed);} 514 /** Return the maximum allowable size for this array. **/ 515 size_type max_size() const 516 { return ArrayIndexTraits<X>::max_size(); } 517 /** Return true if there are no elements currently stored in this array. This 518 is equivalent to the tests begin()==end() or size()==0. **/ 519 bool empty() const {return nUsed==0;} 520 /** Return the number of elements this array can currently hold without 521 requiring reallocation. The value returned by capacity() is always greater 522 than or equal to size(), even if the data is not owned by this array in 523 which case we have capacity()==size() and the array is not reallocatable. **/ 524 size_type capacity() const 525 { return size_type(nAllocated?nAllocated:nUsed); } 526 /** Return the amount of heap space owned by this array; this is the same 527 as capacity() for owner arrays but is zero for non-owners. 528 @note There is no equivalent of this method for std::vector. **/ 529 size_type allocated() const {return size_type(nAllocated);} 530 /** Does this array own the data to which it refers? If not, it can't be 531 resized, and the destructor will not free any heap space nor call any element 532 destructors. If the array does not refer to any data it is considered to be 533 an owner since it is resizeable. 534 @note There is no equivalent of this method for std::vector. **/ 535 bool isOwner() const {return nAllocated || pData==0;} 536 /*}*/ 537 538 539 //------------------------------------------------------------------------------ 540 /** @name Read-only element access 541 542 These methods provide read-only (const) access to individual elements that are 543 currently present in the array. The derived ArrayView_<T,X> class adds the 544 non-const versions of these methods. **/ 545 /*@{*/ 546 547 /** Select an element by its index, returning a const reference. Note that only 548 a value of the array's templatized index type is allowed (default is unsigned). 549 This will be range-checked in a Debug build but not in Release. 550 @pre 0 <= \a i < size() 551 @par Complexity: 552 Constant time. **/ 553 554 SimTK_FORCE_INLINE const T& operator[](index_type i) const { 555 SimTK_INDEXCHECK(size_type(i),size(),"ArrayViewConst_<T>::operator[]()"); 556 return pData[i]; 557 } 558 /** Same as operator[] but always range-checked, even in a Release build. 559 @pre 0 <= \a i < size() 560 @par Complexity: 561 Constant time. **/ 562 const T& at(index_type i) const { 563 SimTK_INDEXCHECK_ALWAYS(size_type(i),size(),"ArrayViewConst_<T>::at()"); 564 return pData[i]; 565 } 566 /** Same as the const form of operator[]; exists to provide a non-operator 567 method for element access in case that's needed. **/ 568 SimTK_FORCE_INLINE const T& getElt(index_type i) const { 569 SimTK_INDEXCHECK(size_type(i),size(),"ArrayViewConst_<T>::getElt()"); 570 return pData[i]; 571 } 572 /** Return a const reference to the first element in this array, which must 573 not be empty (we'll check in a Debug build but not Release). 574 @pre The array is not empty. 575 @par Complexity: 576 Constant time. **/ 577 SimTK_FORCE_INLINE const T& front() const 578 { SimTK_ERRCHK(!empty(), "ArrayViewConst_<T>::front()", "Array was empty."); 579 return pData[0]; } 580 /** Return a const reference to the last element in this array, which must 581 not be empty (we'll check in a Debug build but not Release). 582 @pre The array is not empty. 583 @par Complexity: 584 Constant time. **/ 585 SimTK_FORCE_INLINE const T& back() const 586 { SimTK_ERRCHK(!empty(), "ArrayViewConst_<T>::back()", "Array was empty."); 587 return pData[nUsed-1]; } 588 589 /** Select a contiguous subarray of the elements of this array and create 590 another ArrayViewConst_ that refers only to those element (without copying). 591 @param[in] index 592 The index of the first element to be included in the subarray; this can 593 be one past the end of the array if \a length is zero. 594 @param[in] length 595 The length of the subarray to be produced. 596 @return 597 A new ArrayViewConst_<T,X> object referencing the original data. 598 @note 599 If \a length==0 the returned array will be in a default-constructed, 600 all-zero and null state with no connection to the original data. 601 @pre \a index >= 0, \a length >= 0 602 @pre \a index + \a length <= size() 603 @pre We'll validate preconditions in Debug builds but not Release. 604 @par Complexity: 605 Dirt cheap; no element construction or destruction or heap allocation 606 is required. **/ 607 ArrayViewConst_ operator()(index_type index, size_type length) const { 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()); 612 SimTK_ERRCHK2(isSizeInRange(length, size_type(size()-ix)), 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 } 619 /** Same as const form of operator()(index,length); exists to provide 620 non-operator access to that functionality in case it is needed. **/ 621 ArrayViewConst_ getSubArray(index_type index, size_type length) const 622 { return (*this)(index,length); } 623 624 /*@} End of element access. **/ 625 626 627 //------------------------------------------------------------------------------ 628 /** @name Iterators (const only) 629 630 These methods deal in iterators, which are STL generalized pointers. For this 631 class, iterators are just ordinary const pointers to T, and you may depend on 632 that. By necessity, reverse iterators can't be just pointers; however, they 633 contain an ordinary iterator (i.e. a pointer) that can be obtained by calling 634 the reverse iterator's base() method. **/ 635 /*@{*/ 636 637 /** Return a const pointer to the first element of this array if any, otherwise 638 cend(), which may be null (0) in that case but does not have to be. This method 639 is from the C++11 standard; there is also an overloaded begin() from 640 the original standard that returns a const pointer. **/ 641 const T* cbegin() const {return pData;} 642 /** Return a const pointer to what would be the element just after the last one 643 in the array; this may be null (0) if there are no elements but doesn't have to 644 be. This method is from the C++11 standard; there is also an 645 overloaded end() from the original standard that returns a const pointer. **/ 646 const T* cend() const {return pData + nUsed;} 647 /** The const version of begin() is the same as cbegin(). **/ 648 const T* begin() const {return pData;} 649 /** The const version of end() is the same as cend(). **/ 650 const T* end() const {return pData + nUsed;} 651 652 /** Return a const reverse iterator pointing to the last element in the array 653 or crend() if the array is empty. **/ 654 const_reverse_iterator crbegin() const 655 { return const_reverse_iterator(cend()); } 656 /** Return the past-the-end reverse iterator that tests equal to a reverse 657 iterator that has been incremented past the front of the array. You cannot 658 dereference this iterator. **/ 659 const_reverse_iterator crend() const 660 { return const_reverse_iterator(cbegin()); } 661 /** The const version of rbegin() is the same as crbegin(). **/ 662 const_reverse_iterator rbegin() const {return crbegin();} 663 /** The const version of rend() is the same as crend(). **/ 664 const_reverse_iterator rend() const {return crend();} 665 666 /** Return a const pointer to the first element of the array, or possibly 667 (but not necessarily) null (0) if the array is empty. 668 @note 669 cdata() is not in the C++11 standard although it would seem 670 obvious in view of the cbegin() and cend() methods that had to be added. 671 The C++11 overloaded const data() method is also available. **/ 672 const T* cdata() const {return pData;} 673 /** The const version of the data() method is identical to cdata(). **/ 674 const T* data() const {return pData;} 675 /*@} End of iterators. **/ 676 677 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. 686 /** @cond **/ 687 packed_size_type psize() const {return nUsed;} 688 packed_size_type pallocated() const {return nAllocated;} 689 690 // These provide direct access to the data members for our trusted friends. 691 void setData(const T* p) {pData = const_cast<T*>(p);} 692 void setSize(size_type n) {nUsed = packed_size_type(n);} 693 void incrSize() {++nUsed;} 694 void decrSize() {--nUsed;} 695 void 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. 699 template <class S> 700 bool 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. 705 template <class S> 706 bool 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. 714 template<class Iter> static 715 typename std::iterator_traits<Iter>::difference_type 716 iterDistance(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. 724 template<class Iter> static 725 typename std::iterator_traits<Iter>::difference_type 726 iterDistanceImpl(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. 735 template<class Iter> static 736 typename std::iterator_traits<Iter>::difference_type 737 iterDistanceImpl(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. 751 template<class Iter> bool 752 overlapsWithData(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. 759 template <class T2> bool 760 overlapsWithData(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. 774 template<class Iter> bool 775 overlapsWithDataImpl(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. 780 template<class Iter> bool 781 overlapsWithDataImpl(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. 799 template <class S> 800 static 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. 804 unsigned long long ullSize() const {return ull(size());} 805 unsigned long long ullCapacity() const {return ull(capacity());} 806 unsigned long long ullMaxSize() const {return ull(max_size());} 807 808 // Useful in error messages for explaining why something was too big. 809 const char* indexName() const {return NiceTypeName<X>::name();} 810 811 /** @endcond **/ 812 813 private: 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 819 T* pData; // ptr to data referenced here, or 0 if none 820 packed_size_type nUsed; // number of elements currently present (size) 821 packed_size_type nAllocated; // heap allocation; 0 if pData is not owned 822 823 ArrayViewConst_& operator=(const ArrayViewConst_& src); // suppressed 824 }; 825 826 827 828 829 830 831 //============================================================================== 832 // CLASS ArrayView_ 833 //============================================================================== 834 /** This Array_ helper class is the base class for Array_, extending 835 ArrayViewConst_ to add the ability to modify elements, but not the ability to 836 change size or reallocate. 837 838 @tparam T 839 The type of object to be stored in this container. 840 @tparam X 841 The type to be used for indexing this container, with default unsigned 842 (not size_t). Any integral type may be used, as well as user types that 843 satisfy the requirements discussed with class ArrayIndexTraits. 844 @see Array_, ArrayViewConst_, ArrayIndexTraits **/ 845 template <class T, class X> class ArrayView_ : public ArrayViewConst_<T,X> { 846 typedef ArrayViewConst_<T,X> CBase; 847 public: 848 //------------------------------------------------------------------------------ 849 /** @name Typedefs 850 851 Types required of STL containers, plus index_type which is an extension, and 852 packed_size_type which is an implementation detail. **/ 853 /*{*/ 854 typedef T value_type; 855 typedef X index_type; 856 typedef T* pointer; 857 typedef const T* const_pointer; 858 typedef T& reference; 859 typedef const T& const_reference; 860 typedef T* iterator; 861 typedef const T* const_iterator; 862 typedef std::reverse_iterator<iterator> reverse_iterator; 863 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 864 typedef typename ArrayIndexTraits<X>::size_type size_type; 865 typedef typename ArrayIndexTraits<X>::difference_type difference_type; 866 typedef typename ArrayIndexPackType<size_type>::packed_size_type 867 packed_size_type; 868 /*}*/ 869 870 871 //------------------------------------------------------------------------------ 872 /** @name Construction, conversion, and destruction 873 874 Constructors here are limited to those that don't allocate new data, however 875 they can reference writable data. **/ 876 /*@{*/ 877 878 /** Default constructor allocates no heap space and is very fast. **/ 879 ArrayView_() : CBase() {} 880 881 /** Copy constructor is shallow. **/ 882 ArrayView_(const ArrayView_& src) : CBase(src) {} 883 884 /** Construct from a range of writable memory. **/ 885 ArrayView_(T* first, const T* last1) : CBase(first,last1) {} 886 887 /** Construct to reference memory owned by a writable std::vector. **/ 888 template <class A> 889 ArrayView_(std::vector<T,A>& v) : CBase(v) {} 890 891 /** Implicit conversion of const ArrayView_ to const Array_& (zero cost). **/ 892 operator const Array_<T,X>&() const 893 { return *reinterpret_cast<const Array_<T,X>*>(this); } 894 895 /** Implicit conversion of non-const ArrayView_ to Array_& (zero cost). **/ 896 operator Array_<T,X>&() 897 { return *reinterpret_cast<Array_<T,X>*>(this); } 898 899 /** Forward to base class disconnect() method -- clears the handle without 900 doing anything to the data. */ 901 void disconnect() {this->CBase::disconnect();} 902 903 /** The destructor just disconnects the array view handle from its data; see 904 ArrayViewConst_<T,X>::disconnect() for more information. **/ 905 ~ArrayView_() {this->CBase::disconnect();} 906 /*@} End of construction, etc. **/ 907 908 909 //------------------------------------------------------------------------------ 910 /** @name Assignment 911 912 Assignment is permitted only if the source and destination are the same 913 size. The semantics here are different than for a resizeable Array_ 914 object: here the meaning is elementwise assignment rather than destruction 915 followed by copy construction. That is, if our elements are of type T, and 916 the source elements are of type T2, we will use the operator of T that 917 best matches the signature T::operator=(const T2&) to perform the assignments. 918 When the source also has type T, this is just T's copy assignment operator. 919 We never perform any element destruction or construction here. **/ 920 /*@{*/ 921 922 /** Copy assignment; source must be the same size as this array. **/ 923 ArrayView_& operator=(const ArrayView_& src) { 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 932 /** Assignment from any other array object is allowed as long as the number 933 of elements matches and the types are assignment compatible. **/ 934 template <class T2, class X2> 935 ArrayView_& operator=(const ArrayViewConst_<T2,X2>& src) { 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 946 /** Assignment from any other array object is allowed as long as the number 947 of elements matches and the types are assignment compatible. **/ 948 template <class T2, class X2> 949 ArrayView_& operator=(const ArrayView_<T2,X2>& src) 950 { return *this = static_cast<const ArrayViewConst_<T2,X2>&>(src); } 951 /** Assignment from any other array object is allowed as long as the number 952 of elements matches and the types are assignment compatible. **/ 953 template <class T2, class X2> 954 ArrayView_& operator=(const Array_<T2,X2>& src) 955 { return *this = static_cast<const ArrayViewConst_<T2,X2>&>(src); } 956 957 /** Assignment from any std::vector object is allowed as long as the number 958 of elements matches and the types are assignment compatible. **/ 959 template <class T2, class A2> 960 ArrayView_& 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 967 /** Fill assignment -- all elements are set to fillValue. @see fill() **/ 968 ArrayView_& operator=(const T& fillValue) 969 { fill(fillValue); return *this; } 970 971 /** Assign the supplied fill value to each element of this array, using T's 972 copy assignment operator for each element. Note that this also serves to allow 973 fill from an object whose type T2 is different from T, as long as there is a 974 constructor T(T2) that works since that can be invoked (implicitly or 975 explicitly) to convert the T2 object to type T prior to the call. **/ 976 ArrayView_& fill(const T& fillValue) { 977 for (T* d = begin(); d != end(); ++d) 978 *d = fillValue; // using T::operator=(T) 979 return *this; 980 } 981 982 /** This is the same as fill() but has the usual std::vector signature for 983 compatibility; it will only work if the given number of elements is the same 984 as this array's (fixed) size. **/ 985 void 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 995 /** Assign to this array to make it a copy of the elements in range 996 [first,last1) given by ordinary pointers, provided that the range is the same 997 size as the array. It is not allowed for the source range to include any of the 998 elements currently in the array. The source elements can be 999 of a type T2 that may be the same or different than this array's element type 1000 T as long as there is a T=T2 assignment operator that works. Note that although 1001 the source arguments are pointers, those may be iterators for some container 1002 depending on implementation details of the container. Specifically, any 1003 ArrayViewConst_, ArrayView_, or Array_ iterator is an ordinary pointer. 1004 1005 @param[in] first 1006 A pointer to the first element to be copied. 1007 @param[in] last1 1008 A pointer to the element one past the last element to be copied. 1009 @pre last1-first == size() 1010 @par Complexity: 1011 The T=T2 assignment operator will be called exactly size() times. **/ 1012 template <class T2> 1013 void 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 1023 /** Assign to this array to make it a copy of the elements in range 1024 [first,last1) given by non-pointer iterators (the pointer case is handled 1025 with a specialized assign() variant). It is not allowed for this range to 1026 include any of the elements currently in the array. The source elements can be 1027 of a type T2 that may be the same or different than this array's element type 1028 T as long as there is a T=T2 operator that works. 1029 1030 The source must have the same number of elements as the current (fixed) size 1031 of this ArrayView. For input_iterators we'll be happy if we get enough elements 1032 and won't insist that the input stream is empty after that. For forward_ and 1033 bidirectional_iterators we'll copy the elements and complain at the end if 1034 there are too few or too many. For random_access_iterators we'll check in 1035 advance since we can do that fast. 1036 1037 @param[in] first 1038 An iterator pointing to the first element to be copied. 1039 @param[in] last1 1040 An iterator pointing to the element one past the last element to be copied. 1041 1042 @remarks 1043 This variant of assign() will not be called when the iterators are forward 1044 iterators from ArrayViewConst_, ArrayView_, or Array_ objects since those are 1045 ordinary pointers. 1046 1047 @pre last1 is reachable from first 1048 @pre distance(first,last1)==size() 1049 @par Complexity: 1050 The T=T2 assignment operator will be called exactly size() times. **/ 1051 1052 // Watch out for integral types matching this signature -- they must be 1053 // forwarded to the assign(n, fillValue) signature instead. 1054 template <class Iter> 1055 void assign(const Iter& first, const Iter& last1) 1056 { avAssignDispatch(first,last1,typename IsIntegralType<Iter>::Result(), 1057 "ArrayView_<T>::assign(Iter first, Iter last1)"); } 1058 /*@} End of assignment. */ 1059 1060 1061 //------------------------------------------------------------------------------ 1062 /** @name Element access 1063 1064 These methods provide read and write access to individual elements that are 1065 currently present in the array; the ArrayViewConst_<T,X> base class provides the 1066 read-only (const) methods. **/ 1067 /*@{*/ 1068 1069 /** Select an element by its index, returning a const reference. Note that only 1070 a value of the array's templatized index type is allowed (default is unsigned). 1071 This will be range-checked in a Debug build but not in Release. 1072 @pre 0 <= \a i < size() 1073 @par Complexity: 1074 Constant time. **/ 1075 SimTK_FORCE_INLINE const T& operator[](index_type i) const 1076 { return this->CBase::operator[](i); } 1077 1078 /** Select an element by its index, returning a writable (lvalue) reference. 1079 Note that only a value of the Array's templatized index type is allowed 1080 (default is unsigned). This will be range-checked in a Debug build but not 1081 in Release. 1082 @pre 0 <= \a i < size() 1083 @par Complexity: 1084 Constant time. **/ 1085 SimTK_FORCE_INLINE T& operator[](index_type i) 1086 { return const_cast<T&>(this->CBase::operator[](i)); } 1087 1088 /** Same as operator[] but always range-checked, even in a Release build. 1089 @pre 0 <= \a i < size() 1090 @par Complexity: 1091 Constant time. **/ 1092 const T& at(index_type i) const {return this->CBase::at(i);} 1093 1094 /** Same as operator[] but always range-checked, even in a Release build. 1095 @pre 0 <= \a i < size() 1096 @par Complexity: 1097 Constant time. **/ 1098 T& at(index_type i) {return const_cast<T&>(this->CBase::at(i));} 1099 1100 /** Same as the const form of operator[]; exists to provide a non-operator 1101 method for element access in case that's needed. **/ 1102 SimTK_FORCE_INLINE const T& getElt(index_type i) const 1103 { return this->CBase::getElt(i); } 1104 /** Same as the non-const form of operator[]; exists to provide a non-operator 1105 method for element access in case that's needed. **/ 1106 SimTK_FORCE_INLINE T& updElt(index_type i) 1107 { return const_cast<T&>(this->CBase::getElt(i)); } 1108 1109 /** Return a const reference to the first element in this array, which must 1110 not be empty. 1111 @pre The array is not empty. 1112 @par Complexity: 1113 Constant time. **/ 1114 SimTK_FORCE_INLINE const T& front() const {return this->CBase::front();} 1115 1116 /** Return a writable reference to the first element in this array, which must 1117 not be empty. 1118 @pre The array is not empty. 1119 @par Complexity: 1120 Constant time. **/ 1121 SimTK_FORCE_INLINE T& front() {return const_cast<T&>(this->CBase::front());} 1122 1123 /** Return a const reference to the last element in this array, which must 1124 not be empty. 1125 @pre The array is not empty. 1126 @par Complexity: 1127 Constant time. **/ 1128 SimTK_FORCE_INLINE const T& back() const {return this->CBase::back();} 1129 1130 /** Return a writable reference to the last element in this array, which must 1131 not be empty. 1132 @pre The array is not empty. 1133 @par Complexity: 1134 Constant time. **/ 1135 SimTK_FORCE_INLINE T& back() {return const_cast<T&>(this->CBase::back());} 1136 1137 /** Select a contiguous subarray of the elements of this array and create 1138 another ArrayView_ that refers only to those element (without copying). 1139 @param[in] index 1140 The index of the first element to be included in the subarray; this can 1141 be one past the end of the array if \a length is zero. 1142 @param[in] length 1143 The length of the subarray to be produced. 1144 @return 1145 A new ArrayView_<T,X> object referencing the original data. 1146 @note 1147 If \a length==0 the returned array will be in a default-constructed, 1148 all-zero and null state with no connection to the original data. 1149 @pre \a index >= 0, \a length >= 0 1150 @pre \a index + \a length <= size() 1151 @pre We'll validate preconditions in Debug builds but not Release. 1152 @par Complexity: 1153 Dirt cheap; no element construction or destruction or heap allocation 1154 is required. **/ 1155 ArrayView_ operator()(index_type index, size_type length) { 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 } 1167 /** Same as non-const operator()(index,length); exists to provide non-operator 1168 access to that functionality in case it is needed. **/ 1169 ArrayView_ updSubArray(index_type index, size_type length) 1170 { return (*this)(index,length); } 1171 /*@} End of element access. **/ 1172 1173 1174 //------------------------------------------------------------------------------ 1175 /** @name Iterators 1176 1177 These methods deal in iterators, which are STL generalized pointers. For this 1178 class, iterators are just ordinary pointers to T, and you may depend on that. 1179 By necessity, reverse iterators can't be just pointers; however, they contain 1180 an ordinary iterator (i.e. a pointer) that can be obtained by calling the 1181 reverse iterator's base() method. **/ 1182 /*@{*/ 1183 1184 /** Return a const pointer to the first element of this array if any, otherwise 1185 end(), which may be null (0) in that case but does not have to be. This method 1186 is from the C++11 standard; there is also an overloaded begin() from 1187 the original standard that returns a const pointer. **/ 1188 SimTK_FORCE_INLINE const T* cbegin() const {return this->CBase::cbegin();} 1189 /** The const version of begin() is the same as cbegin(). **/ 1190 SimTK_FORCE_INLINE const T* begin() const {return this->CBase::cbegin();} 1191 /** Return a writable pointer to the first element of this array if any, 1192 otherwise end(). If the array is empty, this \e may return null (0) but does 1193 not have to -- the only thing you can be sure of is that begin() == end() for 1194 an empty array. **/ 1195 SimTK_FORCE_INLINE T* begin() {return const_cast<T*>(this->CBase::cbegin());} 1196 1197 /** Return a const pointer to what would be the element just after the last one 1198 in the array; this may be null (0) if there are no elements but doesn't have to 1199 be. This method is from the C++11 standard; there is also an 1200 overloaded end() from the original standard that returns a const pointer. **/ 1201 SimTK_FORCE_INLINE const T* cend() const {return this->CBase::cend();} 1202 /** The const version of end() is the same as cend(). **/ 1203 SimTK_FORCE_INLINE const T* end() const {return this->CBase::cend();} 1204 /** Return a writable pointer to what would be the element just after the last 1205 one in this array. If the array is empty, this \e may return null (0) but does 1206 not have to -- the only thing you can be sure of is that begin()==end() for an 1207 empty array. **/ 1208 SimTK_FORCE_INLINE T* end() {return const_cast<T*>(this->CBase::cend());} 1209 1210 /** Return a const reverse iterator pointing to the last element in the array 1211 or crend() if the array is empty. **/ 1212 const_reverse_iterator crbegin() const 1213 { return this->CBase::crbegin(); } 1214 /** The const version of rbegin() is the same as crbegin(). **/ 1215 const_reverse_iterator rbegin() const 1216 { return this->CBase::crbegin(); } 1217 /** Return a writable reverse iterator pointing to the last element in the 1218 array or rend() if the array is empty. **/ 1219 reverse_iterator rbegin() {return reverse_iterator(end());} 1220 1221 /** Return the past-the-end reverse iterator that tests equal to a reverse 1222 iterator that has been incremented past the front of the array. You cannot 1223 dereference this iterator. **/ 1224 const_reverse_iterator crend() const 1225 { return this->CBase::crend(); } 1226 /** The const version of rend() is the same as crend(). **/ 1227 const_reverse_iterator rend() const 1228 { return this->CBase::crend(); } 1229 /** Return a writable past-the-end reverse iterator that tests equal to a 1230 reverse iterator that has been incremented past the front of the array. You 1231 cannot dereference this iterator. **/ 1232 reverse_iterator rend() {return reverse_iterator(begin());} 1233 1234 /** Return a const pointer to the first element of the array, or possibly 1235 (but not necessarily) null (0) if the array is empty. 1236 @note 1237 cdata() is not in the C++11 standard although it would seem 1238 obvious in view of the cbegin() and cend() methods that had to be added. 1239 The C++11 overloaded const data() method is also available. **/ 1240 SimTK_FORCE_INLINE const T* cdata() const {return this->CBase::cdata();} 1241 /** The const version of the data() method is identical to cdata(). 1242 @note This method is from the C++11 std::vector. **/ 1243 SimTK_FORCE_INLINE const T* data() const {return this->CBase::cdata();} 1244 /** Return a writable pointer to the first allocated element of the array, or 1245 a null pointer if no space is associated with the array. 1246 @note This method is from the C++11 std::vector. **/ 1247 SimTK_FORCE_INLINE T* data() {return const_cast<T*>(this->CBase::cdata());} 1248 /*@} End of iterators. */ 1249 1250 1251 //------------------------------------------------------------------------------ 1252 /** @name Size and capacity 1253 1254 These methods report the number of elements (size) or the amount of allocated 1255 heap space (capacity) or both but cannot be used to change size. **/ 1256 /*@{*/ 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 1263 SimTK_FORCE_INLINE size_type size() const {return this->CBase::size();} 1264 size_type max_size() const {return this->CBase::max_size();} 1265 bool empty() const {return this->CBase::empty();} 1266 size_type capacity() const {return this->CBase::capacity();} 1267 size_type allocated() const {return this->CBase::allocated();} 1268 bool isOwner() const {return this->CBase::isOwner();} 1269 /*@} End of size and capacity. **/ 1270 1271 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. 1283 template <class IntegralType> 1284 void 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. 1291 template <class InputIterator> 1292 void 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. 1304 template <class InputIterator> 1305 void 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. 1329 template <class ForwardIterator> 1330 void 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. 1358 template <class RandomAccessIterator> 1359 void 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 1387 packed_size_type psize() const 1388 { return this->CBase::psize(); } 1389 packed_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. 1394 unsigned long long ullSize() const 1395 { return this->CBase::ullSize(); } 1396 unsigned long long ullCapacity() const 1397 { return this->CBase::ullCapacity(); } 1398 unsigned 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. 1402 const char* indexName() const {return this->CBase::indexName();} 1403 }; 1404 1405 1406 //============================================================================== 1407 // CLASS Array_ 1408 //============================================================================== 1409 /** The Array_<T> container class is a plug-compatible replacement for 1410 the C++ standard template library (STL) std::vector<T> class, but with some 1411 important advantages in performance, and functionality, and binary 1412 compatibility. 1413 1414 @tparam T 1415 The type of object to be stored in this container. 1416 @tparam X 1417 The type to be used for indexing this container, with default unsigned 1418 (not size_t). Any integral type may be used, as well as user types that 1419 satisfy the requirements discussed with class ArrayIndexTraits. 1420 1421 @par Performance: 1422 There are several performance and memory footprint problems with the C++ 1423 standard STL design in general, and with Microsoft's implementation in 1424 particular, that are addressed here. Microsoft in its wisdom decided that STL 1425 containers should still do runtime range checks in Release builds for safety, 1426 but that makes them too slow for use in some high-performance contexts (and 1427 also breaks the promise of generic programming but that's another rant). In 1428 practice, VC++12 (2013) std::vector runs about half speed for simple operations 1429 like indexing and push_back (see Simbody's TestArray regression test for an 1430 executable performance comparison). Attempting to disable these runtime checks 1431 with `_SECURE_SCL` breaks binary compatibility with other code built with the 1432 same compiler but without the flag. In contrast the performance of this 1433 Array_<T> class on any platform is indistinguishable from what you would 1434 get by managing your own heap-allocated arrays. 64 bit compilers vary on how 1435 well they handle 32 bit integers though, so in some cases the default index 1436 type (32 bit unsigned) won't be as fast as if you use a 64 bit unsigned type 1437 as does std::vector. 1438 1439 @par 1440 Regarding memory footprint, the typical implementation of std::vector uses 1441 three pointers: 12 bytes for 32 bit machines; 24 bytes for 64 bit machines. 1442 Microsoft somehow manages to trump this with 20 to 24 bytes on a 32 bit 1443 machine (last checked in VC++9); they are at 24 bytes for 64 bit Release builds 1444 in VC++12, 32 bytes in Debug builds. Array_ instead uses one pointer and two 1445 lengths for a total size as little as 8 bytes on 32 bits and 16 on 64 bits; 1446 see below for details. The binary representation for Array_ is the same in 1447 Release and Debug builds. 1448 1449 @par 1450 Some nuts and bolts: 1451 1452 - We promise that no heap allocation occurs when an empty Array_<T> object 1453 is declared (that is, when an Array_<T> is default-constructed); in 1454 that case both begin() and end() are null. 1455 - Array_<T> methods are extremely fast in Release builds with zero overhead, 1456 inline, unchecked methods. The implementations of inline methods are kept 1457 small to ensure that they are actually inlined in practice; and generated 1458 assembly code was examined to make sure. 1459 - There are some dangerous extensions provided that permit the expert user 1460 to construct objects directly into the array without having to copy them, 1461 a big win for complicated objects and even bigger for those that don't 1462 have copy constructors! 1463 - There is a constant-time eraseFast() method you can use if you don't mind the 1464 array being reordered after the erase. This avoids the extremely expensive 1465 "compress" activity required by the standard erase() method. 1466 - The optional index-type template parameter can be used to reduce the memory 1467 footprint to as little as 8 bytes on a 32 bit machine (e.g., a 32 bit 1468 pointer and two shorts). 1469 - The default size_type for an Array_<T> is a 32-bit unsigned integer rather 1470 than a size_t. On a 64-bit machine that keeps the memory footprint down 1471 substantially since the structure is then one 64-bit pointer and two 32-bit 1472 integers, fitting tightly into a cleanly alignable 16 bytes. 1473 1474 1475 @par Functionality: 1476 For the most part Array_<T> is a plug-compatible replacement for std::vector<T>, 1477 and everything that both classes can do is done with an identical API. However, 1478 there are a few additions and subtractions: 1479 1480 - This class always uses the default new/delete allocator; there is no option 1481 to specify your own as there is in std::vector. 1482 - Instead of an allocator, the second template argument X to Array_<T,X> is an 1483 optional index type which can be used to provide type-safe indexing (i.e. the 1484 array can only be indexed by indices of a particular type, like 1485 MobilizedBodyIndex). This has zero performance cost if the index is an 1486 integral type or class consisting of only an integral value such as those 1487 produced by the SimTK_DEFINE_UNIQUE_INDEX_TYPE macro. 1488 - You can create uninitialized slots in the array and construct directly into 1489 them rather than having to construct a temporary object which must then be 1490 copied into the array. 1491 - You can create Array_<T> objects that reference existing data, including 1492 the contents of std::vectors. 1493 - This class implements the std::vector features from the C++11 standard (with 1494 a few exceptions; see below). 1495 1496 @par Compatibility: 1497 Included here are binary compatibility issues and compatibility with the C++ 1498 standard STL objects. 1499 1500 - Most important, it is safe to pass an Array_<T> through an API to a binary 1501 library without worrying about compiler version or Release/Debug compatibility 1502 issues. For a given compiler (e.g. gcc or Microsoft cl) and word size (64 bit 1503 vs. 32 bit), Array_<T> has an extremely stable memory layout that is preserved 1504 across compiler versions, and between Release and Debug builds. This allows us 1505 to use Array_<T> in the SimTK API where use of std::vector<T> would be 1506 desirable but problematic. 1507 - It supports all standard types, methods, iterators, and operators of the 1508 C++11 standard std::vector, so it works smoothly with all STL containers and 1509 algorithms. However, it does not provide the same guarantees of behavior 1510 when exceptions occur. In particular, when resizing Array_ will use move 1511 construction if available even if the move constructor hasn't been marked 1512 "nothrow". 1513 - It is convertible to and from std::vector, usually without copying the 1514 elements. It is easy to provide APIs that accept either Array_<T> or 1515 std::vector<T>; the std::vector's data is referenced by an Array_ handle 1516 that is used to convey the data across the API without binary compatibility 1517 problems. 1518 1519 @see Array_, ArrayViewConst_, ArrayIndexTraits **/ 1520 template <class T, class X> class Array_ : public ArrayView_<T,X> { 1521 typedef ArrayView_<T,X> Base; 1522 typedef ArrayViewConst_<T,X> CBase; 1523 public: 1524 1525 1526 //------------------------------------------------------------------------------ 1527 /** @name Typedefs 1528 1529 Types required of STL containers, plus index_type which is an extension, and 1530 packed_size_type which is an implementation detail. **/ 1531 1532 // Doxygen picks up individual descriptions from the base class. 1533 /*{*/ 1534 typedef T value_type; 1535 typedef X index_type; 1536 typedef T* pointer; 1537 typedef const T* const_pointer; 1538 typedef T& reference; 1539 typedef const T& const_reference; 1540 typedef T* iterator; 1541 typedef const T* const_iterator; 1542 typedef std::reverse_iterator<iterator> reverse_iterator; 1543 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 1544 typedef typename ArrayIndexTraits<X>::size_type size_type; 1545 typedef typename ArrayIndexTraits<X>::difference_type difference_type; 1546 typedef typename ArrayIndexPackType<size_type>::packed_size_type 1547 packed_size_type; 1548 /*}*/ 1549 1550 //------------------------------------------------------------------------------ 1551 /** @name Construction, conversion and destruction 1552 1553 A variety of constructors are provided for this class, including all those 1554 required by the C++ standard for std::vector implementations, plus additional 1555 ones providing smooth conversions between Array_<T> and std::vector<T> objects. 1556 **/ 1557 /*{*/ 1558 1559 /** Default constructor allocates no heap space and is very fast. **/ 1560 Array_() : Base() {} 1561 1562 /** Construct an array containing \a n default-constructed elements. T's default 1563 constructor (if any) is called exactly \a n times. If \a n is zero no heap space 1564 will be allocated; although in that case it is preferable to use the default 1565 constructor if you can since that will be somewhat faster. **/ 1566 explicit 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 1573 /** Construct an array containing \a n elements each set to a copy of the given 1574 initial value. T's copy constructor will be called exactly \a n times. If \a n 1575 is zero no space will be allocated. **/ 1576 Array_(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 } 1582 /** Construct an Array_<T> from a range [first,last1) of values identified by a 1583 pair of iterators. 1584 @note 1585 The standard requires that if an integral type matches this signature, it must 1586 behave as the Array_(size_type,value_type) constructor. 1587 @par Complexity: 1588 The performance of this constructor depends on the type 1589 of iterator: 1590 - random_access_iterator: n=(last1-first); a single space allocation; 1591 n calls to T's copy constructor. 1592 - forward or bidirectional iterator: must increment from first to last1 to 1593 determine n; otherwise same as random access. 1594 - input iterator: can't determine n in advance; expect log n reallocations 1595 during construction as we "push back" one input element at a time. 1596 **/ 1597 template <class InputIter> 1598 Array_(const InputIter& first, const InputIter& last1) : Base() { 1599 ctorDispatch(first,last1,typename IsIntegralType<InputIter>::Result()); 1600 } 1601 1602 /** Construct an Array_<T> from a range [first,last1) of values identified by a 1603 pair of ordinary pointers to elements of type T2 (where T2 might be the same as 1604 T but doesn't have to be). This is templatized so can be used with any source 1605 type T2 which is either T or implicitly convertible to T, provided 1606 that the number of source elements does not exceed the array's max_size(). **/ 1607 template <class T2> 1608 Array_(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 1624 /** Construct an Array_<T> from an std::initializer_list whose elements were 1625 convertible to type T, provided that the number of source elements does not 1626 exceed the array's max_size(). Note that this constructor is not `explicit`, 1627 so a suitable std::initializer_list will implicitly convert to an Array_<T>. **/ 1628 Array_(std::initializer_list<T> ilist) 1629 : Array_(ilist.begin(), ilist.end()) {} // invoke above constructor for T* 1630 1631 /** Construct an Array_<T> by copying from an std::vector<T2>, where T2 may 1632 be the same type as T but doesn't have to be. This will work as long as the 1633 size of the vector does not exceed the array's max_size(), and provided there 1634 is a working T(T2) conversion constructor. **/ 1635 template <class T2> 1636 explicit 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 1650 /** Copy constructor allocates exactly as much memory as is in use in the 1651 source (not its capacity) and copy constructs the elements so that T's copy 1652 constructor will be called exactly src.size() times. If the source is empty, 1653 no heap space will be allocated. **/ 1654 Array_(const Array_& src) : Base() { 1655 setSize(src.size()); 1656 allocateNoConstruct(size()); 1657 copyConstruct(begin(), cend(), src.data()); 1658 } 1659 1660 /** Move constructor swaps in the source and leaves the source default 1661 constructed. **/ 1662 Array_(Array_&& src) : Base() { 1663 swap(src); 1664 } 1665 1666 /** Construct this Array_<T,X> as a copy of another Array_<T2,X2> where T2!=T 1667 or X2!=X. This will work as long as the source is not larger than will fit 1668 here, and as long as the source element type T2 is assignment compatible with 1669 this array's element type T. One of T's constructors will be called exactly 1670 src.size() times; the particular constructor is whichever one best matches 1671 T(T2). **/ 1672 template <class T2, class X2> 1673 Array_(const Array_<T2,X2>& src) : Base() { 1674 new (this) Array_(src.begin(), src.cend()); // see above 1675 } 1676 1677 /** Construct an Array_<T> by referencing (sharing) a given range of data 1678 [first,last1), without copying that data; better to use the corresponding 1679 ArrayView_<T> constructor if you can. This is very fast but can be 1680 dangerous -- it is most useful for argument passing where the array handle 1681 will be discarded immediately after use. Note that this is available only if 1682 you have write access to the data because there is no way to construct 1683 a non-writable array. This will work as long as the size of the data does 1684 not exceed the array's max_size. The resulting array object is not resizeable 1685 but can be used to read and write elements of the original data. The 1686 array is invalid if the original data is destructed or resized, but there is 1687 no way for the array class to detect that. 1688 1689 @remarks 1690 - If the source data is empty, the resulting array will also 1691 be empty and will look just like a default-constructed array. It will 1692 therefore not have any connection to the source and will be an 1693 ordinary resizable array. 1694 - This is quite dangerous to use since the connection between the array and 1695 the data is tenuous and subject to the data remaining untouched during 1696 the lifetime of the array handle. There is no reference counting; 1697 destructing the original data would leave the array referring to garbage. 1698 Be careful! 1699 - You can break the connection between the array and the data it was 1700 constructed from by calling deallocate(). 1701 1702 @par Complexity: 1703 Dirt cheap. There will be no construction, destruction, or heap allocation 1704 performed. 1705 @see deallocate() **/ 1706 Array_(T* first, const T* last1, const DontCopy&) : Base(first,last1) {} 1707 1708 /** Construct an Array_<T> by referencing (sharing) the data in an 1709 std::vector<T>, without copying the data; better to use the ArrayView_<T> 1710 constructor instead if you can. This is very fast but can be 1711 dangerous -- it is most useful for argument passing where the array handle 1712 will be discarded immediately after use. Note that this is available only if 1713 you have write access to the std::vector because there is no way to construct 1714 a non-writable array. This will work as long as the size of the vector does 1715 not exceed the array's max_size. The resulting array object is not resizeable 1716 but can be used to read and write elements of the original std::vector. The 1717 array is invalid if the original std::vector is destructed or resized. 1718 1719 @remarks 1720 - If the source std::vector is empty, the resulting array will also 1721 be empty and will look just like a default-constructed array. It will 1722 therefore not have any connection to the source vector and will be an 1723 ordinary resizable array. 1724 - This is quite dangerous to use since the connection between the array and 1725 the vector is tenuous and subject to the vector remaining untouched during 1726 the lifetime of the array handle. There is no reference counting; 1727 destructing the vector leaves the array referring to garbage. Be careful! 1728 - You can break the connection between the array and the vector it was 1729 constructed from by calling deallocate(). 1730 1731 @par Complexity: 1732 Dirt cheap. There will be no construction, destruction, or heap allocation 1733 performed. 1734 @see deallocate() **/ 1735 template <class A> 1736 Array_(std::vector<T,A>& v, const DontCopy&) : Base(v) {} 1737 1738 /** The destructor performs a deallocate() operation which may result in 1739 element destruction and freeing of heap space; see deallocate() for more 1740 information. @see deallocate() **/ 1741 ~Array_() { 1742 deallocate(); 1743 } 1744 1745 /** Empty this array of its contents, returning the array to its 1746 default-constructed, all-zero state. If this array is the owner of its data, 1747 the destructor (if any) is called for each data element and the array's 1748 allocated heap space is freed. If it is a non-owner the array handle is 1749 cleaned out using disconnect() but the referenced data is untouched. 1750 @note There is no equivalent to this method for std::vector. 1751 @return A reference to the now-empty, default-constructed array, ready for 1752 reassignment. **/ 1753 Array_& deallocate() { 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 1762 /*@} End of constructors, etc. **/ 1763 1764 1765 //------------------------------------------------------------------------------ 1766 /** @name Assignment methods and operators 1767 1768 These methods put new data values in an existing array, but the meaning of 1769 assignment is subtly different for resizeable (owner) arrays and fixed 1770 (non-owner) arrays. The standard std::vector type is always an owner so the 1771 non-owner description here is an extension applying only to Array_. 1772 1773 For the normal case of resizeable arrays, assignment does not have an 1774 elementwise definition because the source will typically have a different 1775 number of elements than the array's current size. So regardless of the actual 1776 numbers, assignment in the resizeable case is defined as it is for std::vector: 1777 first clear the array by erasing (destructing) all the current elements in the 1778 array, then reserve sufficient heap space to hold a copy of the source, then 1779 use appropriate constructors of type T (most commonly T's copy constructor 1780 T(T)) to initialize each element to be a copy of the corresponding source 1781 element. T's assignment operators are never used in this case. 1782 1783 For fixed arrays, the source must have the same number of elements as are 1784 currently in the array and the meaning is conventional elementwise assignment; 1785 that is, an appropriate assignment operator of type T (most commonly T's copy 1786 assignment operator T=T) is used to change the value of each existing element. 1787 1788 So there are different requirements on the value type T for owner and non-owner 1789 assignments to type T2: for owner assignment T must have a constructor T(T2) 1790 available; for non-owner assignment, T must have an assignment operator T=T2 1791 available. 1792 1793 @remarks 1794 - When reallocating the destination array, we may reuse the existing heap 1795 allocation if it is sufficient and not \e too big; otherwise we'll reallocate 1796 before copying. 1797 - The fill() method here has elementwise assignment semantics regardless of 1798 whether the array is an owner or non-owner. **/ 1799 /*@{*/ 1800 1801 /** Set this array to be \a n copies of the supplied \a fillValue. Note that 1802 this serves to allow fill from an object whose type T2 is different from T, as 1803 long as there is a constructor T(T2) that works since that can be invoked 1804 (implicitly or explicitly) to convert the T2 object to type T prior to the 1805 call. If this is a non-owner array then \a n must be the same as the current 1806 size(); consider using the fill() method instead. 1807 @param[in] n The number of elements to be in the result. 1808 @param[in] fillValue The value to which to initialize each element. 1809 1810 @pre \a n <= max_size() 1811 @pre for non-owner, n==size() 1812 @par Complexity: 1813 For a non-owner with \a n==size(), there will be exactly \a n calls to T's 1814 copy assignment operator. For an owner, there will be size() calls to T's 1815 destructor (if it has one), possibly a heap reallocation (but with no element 1816 copying), followed by \a n calls to T's copy constructor. 1817 @see fill() **/ 1818 void 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 1838 /** Assign all current elements of the array to the same \a fillValue. This is 1839 similar to assign(size(),fillValue) but the semantics are subtly different. 1840 Here we use repeated application of T's copy assignment operator T=fillValue, 1841 whereas the assign() semantics are to first destruct all the existing elements, 1842 then allocate if necessary, then use the copy constructor to initialize the 1843 new elements. Note that you can use this to fill from a source type T2 that 1844 is different from T as long as there exists a suitable constructor T(T2) that 1845 can be used to create the type T \a fillValue from the original T2 source. 1846 @note Unlike other assignment methods, the behavior of fill() is identical for 1847 owner and non-owner arrays. 1848 1849 @param[in] fillValue The value to which all existing elements are set. 1850 @par Complexity: 1851 Just size() calls to T's copy assignment operator. **/ 1852 void fill(const T& fillValue) {this->Base::fill(fillValue);} 1853 1854 1855 /** Assign to this array to to make it a copy of the elements in range 1856 [first,last1) given by ordinary pointers. It is not allowed for this range to 1857 include any of the elements currently in the array. The source elements can be 1858 of a type T2 that may be the same or different than this array's element type 1859 T as long as there is a working constructor T(T2) (for owner arrays) or a 1860 working assignment operator T=T2 (for non-owner arrays). Note that although the 1861 source arguments are pointers, those may be iterators for some container 1862 depending on implementation details of the container. Specifically, any 1863 Array_<T2>::iterator or const_iterator is an ordinary pointer. 1864 1865 @param[in] first A pointer to the first source element to be copied. 1866 @param[in] last1 A pointer to one element past the last source element. 1867 1868 @par Complexity: 1869 For non-owner arrays, n=last1-first must equal the current size() in which 1870 case there will be exactly size() calls to the T=T2 assignment operator. 1871 For owner arrays, say the array initially has capacity c, and the 1872 source provides n new elements. If type T has a destructor, it will be called 1873 exactly size() times. Reallocation will then occur if c < n and may occur if 1874 c >> n to avoid leaving a lot of unused space. Then the constructor T(T2) will 1875 be called exactly n times. **/ 1876 template <class T2> 1877 void 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 1889 /** Assign this array from a range [first,last1) given by non-pointer 1890 iterators. See the assign(first,last1) method with pointer arguments for a 1891 relevant discussion. 1892 1893 @remarks 1894 - For a non-owner array this is only allowed if we can calculate the number of 1895 source elements, and if that number is exactly the same as the current 1896 size(). 1897 - See Complexity discussion below for behavior for the different kinds of 1898 iterators that might be supplied. 1899 - It is not permitted for any of the source elements to overlap in memory 1900 with the initial contents of the array. 1901 1902 @param[in] first 1903 An iterator pointing to the first source element to be copied. 1904 @param[in] last1 1905 A iterator pointing one element past the last source element. 1906 1907 @pre last1-first <= max_size() 1908 @pre for non-owner array, last1-first == size() 1909 @par Complexity: 1910 For a non-owner array, this is only allowed if n=last1-first equals the 1911 current size(), in which case we'll perform exactly n calls to the appropriate 1912 assignment operator of element type T. For owner arrays, if we can determine 1913 how many elements n=last1-first the source contains in advance, we'll do only 1914 a single allocation here and call one of T's constructors exactly n times after 1915 just size() destructor calls needed to erase the original data. If the 1916 iterators are random access iterators, calculating n is a fast constant-time 1917 operation. For forward or bidirectional iterators, we have to advance through 1918 the iterators once to count the source elements prior to allocating space, 1919 adding an O(n) cost. For input iterators, we can't count them in advance so 1920 we just have to add elements as we find them using push_back() meaning we may 1921 need to reallocate log(n) times, calling the destructor and copy constructor 1922 each time to move the elements around. 1923 @see assign(T2* first, T2* last1) **/ 1924 template <class Iter> 1925 void 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 1930 /** Copy assignment operator destructs the current contents of this array and 1931 then makes it a copy of the source array by repeated calls to the element 1932 type's copy constructor. At most one reallocation of heap space occurs that 1933 may result in this array having a larger or smaller capacity, although of 1934 course it will be at least as large as the source. **/ 1935 Array_& operator=(const Array_& src) { 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 1943 /** Move assignment operator swaps the contents of this Array_ with the 1944 source Array_. **/ 1945 Array_& operator=(Array_&& src) { 1946 swap(src); 1947 return *this; 1948 } 1949 1950 /** This is assignment from a source array whose element type T2 and/or index 1951 type X2 are different from this array's T and X. This will work as long as 1952 this array can accommodate all the elements in the source and T2 is assignment 1953 compatible with T. See discussion for the copy assignment operator for more 1954 information. */ 1955 template <class T2, class X2> 1956 Array_& operator=(const Array_<T2,X2>& src) { 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 1964 /** This is assignment from a source std::vector<T2>. This will work as long as 1965 this array can accommodate all the elements in the source and T2 is assignment 1966 compatible with T. See discussion for the copy assignment operator for more 1967 information. */ 1968 template <class T2, class A> 1969 Array_& 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 1976 /** This is a specialized algorithm providing constant time exchange of data 1977 with another array that has identical element and index types. This is \e much 1978 faster than using the default std::swap() algorithm on the arrays since that 1979 would involve O(n) copying operations; we provide a specialization for 1980 std::swap() that uses the method here instead. This method makes no calls to any 1981 constructors or destructors. This is allowable even for non-owner arrays; the 1982 non-owner attribute will follow the non-owned data. **/ 1983 void 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 1989 /** This dangerous extension allows you to supply your own already-allocated 1990 heap space for use by this array, which then becomes the owner of the supplied 1991 heap space. Any memory currently associated with the array is deallocated; 1992 see deallocate() for more information. 1993 @see deallocate(), shareData() **/ 1994 Array_& 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 } 2014 /** A variant of adoptData() that assumes the capacity is the same as the 2015 current size. @see adoptData(data,size,capacity) **/ 2016 Array_& adoptData(T* newData, size_type dataSize) 2017 { return adoptData(newData, dataSize, dataSize); } 2018 2019 2020 /** This dangerous extension allows you to make this array handle refer to 2021 someone else's data without copying it. Any memory currently associated 2022 with the array is deallocated; see deallocate() for more information. This 2023 method makes the array a fixed-size, non-owner array that cannot be 2024 reallocated, and no element destruction nor heap deallocation will occur when 2025 the handle is subsequently destructed or deallocated. 2026 @note 2027 - A null (0) pointer is allowed for the pointer as long as \a dataSize==0, 2028 however in that case the array handle ends up deallocated (that is, 2029 indistinguishable from a default-constructed array) so is resizeable. 2030 - This is implemented by setting the nAllocated data member to zero while 2031 the nUsed data member is set to the given \a dataSize. 2032 @see deallocate(), adoptData() **/ 2033 Array_& 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 2048 /** Same as shareData(data,size) but uses a pointer range [first,last1) to 2049 identify the data to be referenced. **/ 2050 Array_& 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 2059 /*@} End of assignment. **/ 2060 2061 2062 //------------------------------------------------------------------------------ 2063 /** @name Size and capacity 2064 2065 These methods examine and alter the number of elements (size) or the amount of 2066 allocated heap space (capacity) or both. **/ 2067 /*@{*/ 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 2074 /** Return the current number of elements stored in this array. **/ 2075 SimTK_FORCE_INLINE size_type size() const {return this->CBase::size();} 2076 /** Return the maximum allowable size for this array. **/ 2077 size_type max_size() const {return this->CBase::max_size();} 2078 /** Return true if there are no elements currently stored in this array. This 2079 is equivalent to the tests begin() == end() or size()==0. **/ 2080 bool empty() const {return this->CBase::empty();} 2081 /** Return the number of elements this array can currently hold without 2082 requiring reallocation. The value returned by capacity() is always greater 2083 than or equal to size(), even if the data is not owned by this array in 2084 which case we have capacity() == size() and the array is not reallocatable. **/ 2085 size_type capacity() const {return this->CBase::capacity();} 2086 2087 /** Change the size of this Array, preserving all the elements that will still 2088 fit, and default constructing any new elements that are added. This is not 2089 allowed for non-owner arrays unless the requested size is the same as the 2090 current size. **/ 2091 void 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 2109 /** Change the size of this array, preserving all the elements that will still 2110 fit, and initializing any new elements that are added by repeatedly copy- 2111 constructing from the supplied value. This is not allowed for non-owner arrays 2112 unless the requested size is the same as the current size. **/ 2113 void 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 2130 /** Ensure that this array has enough allocated capacity to hold the indicated 2131 number of elements. No heap reallocation will occur after this until the array 2132 is grown beyond this capacity, meaning that adding elements will not invalidate 2133 any iterators or element addresses until that point. This method will never 2134 reduce the capacity of the array. It is OK to call this on a non-owner array 2135 as long as you are not asking for an increase in capacity. **/ 2136 void reserve(size_type n) { 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 2152 /** Request that the capacity of this array be reduced to the minimum necessary 2153 to hold the number of elements currently in use. In practice no shrinkage will 2154 occur if the current size is just slightly too big, unless the current size is 2155 exactly zero in which case we guarantee to deallocate all heap space associated 2156 with this array leaving a null data pointer and begin()==end()==0, exactly as 2157 though the array had just been default-constructed. Otherwise you can check 2158 capacity() afterwards to see what happened. If the capacity() is reduced by 2159 this method, then all the elements will have been moved to new locations so 2160 existing iterators and references into the array will become invalid. 2161 2162 @note 2163 - This method matches the C++11 std::vector method, except for 2164 the guaranteed behavior for a zero-size container. 2165 - It is OK to call this on a non-owner array but it has no effect since 2166 capacity()==size() already in that case. 2167 2168 @par Complexity: 2169 If the capacity is reduced, there will be one call to T's move constructor 2170 and destructor (if any) for each element currently in the array. Otherwise 2171 this is very fast. **/ 2172 void shrink_to_fit() { 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 2184 /** Return the amount of heap space owned by this array; this is the same 2185 as capacity() for owner arrays but is zero for non-owners. 2186 @note There is no equivalent of this method for std::vector. **/ 2187 size_type allocated() const 2188 { return this->CBase::allocated(); } 2189 /** Does this array own the data to which it refers? If not, it can't be 2190 resized, and the destructor will not free any heap space nor call any element 2191 destructors. If the array does not refer to \e any data it is considered to be 2192 an owner and it is resizeable. 2193 @note There is no equivalent of this method for std::vector. **/ 2194 bool isOwner() const {return this->CBase::isOwner();} 2195 /*@} End of size and capacity. **/ 2196 2197 2198 //------------------------------------------------------------------------------ 2199 /** @name Iterators 2200 2201 These methods deal in iterators, which are STL generalized pointers. For this 2202 class, iterators are just ordinary pointers to T, and you may depend on that. 2203 By necessity, reverse iterators can't be just pointers; however, they contain 2204 an ordinary iterator (i.e. a pointer) that can be obtained by calling the 2205 reverse iterator's base() method. **/ 2206 /*@{*/ 2207 2208 /** Return a const pointer to the first element of this array if any, otherwise 2209 cend(), which may be null (0) in that case but does not have to be. This method 2210 is from the C++11 standard; there is also an overloaded begin() from 2211 the original standard that returns a const pointer. **/ 2212 SimTK_FORCE_INLINE const T* cbegin() const {return this->CBase::cbegin();} 2213 /** The const version of begin() is the same as cbegin(). **/ 2214 SimTK_FORCE_INLINE const T* begin() const {return this->CBase::cbegin();} 2215 /** Return a writable pointer to the first element of this array if any, 2216 otherwise end(). If the array is empty, this \e may return null (0) but does 2217 not have to -- the only thing you can be sure of is that begin() == end() for 2218 an empty array. **/ 2219 SimTK_FORCE_INLINE T* begin() {return this->Base::begin();} 2220 2221 /** Return a const pointer to what would be the element just after the last one 2222 in the array; this may be null (0) if there are no elements but doesn't have to 2223 be. This method is from the C++11 standard; there is also an 2224 overloaded end() from the original standard that returns a const pointer. **/ 2225 SimTK_FORCE_INLINE const T* cend() const {return this->CBase::cend();} 2226 /** The const version of end() is the same as cend(). **/ 2227 SimTK_FORCE_INLINE const T* end() const {return this->CBase::cend();} 2228 /** Return a writable pointer to what would be the element just after the last 2229 one in this array. If the array is empty, this \e may return null (0) but does 2230 not have to -- the only thing you can be sure of is that begin()==end() for an 2231 empty array. **/ 2232 SimTK_FORCE_INLINE T* end() {return this->Base::end();} 2233 2234 /** Return a const reverse iterator pointing to the last element in the array 2235 or crend() if the array is empty. **/ 2236 const_reverse_iterator crbegin() const 2237 { return this->CBase::crbegin(); } 2238 /** The const version of rbegin() is the same as crbegin(). **/ 2239 const_reverse_iterator rbegin() const 2240 { return this->CBase::crbegin(); } 2241 /** Return a writable reverse iterator pointing to the last element in the 2242 array or rend() if the array is empty. **/ 2243 reverse_iterator rbegin() {return this->Base::rbegin();} 2244 2245 /** Return the past-the-end reverse iterator that tests equal to a reverse 2246 iterator that has been incremented past the front of the array. You cannot 2247 dereference this iterator. **/ 2248 const_reverse_iterator crend() const 2249 { return this->CBase::crend(); } 2250 /** The const version of rend() is the same as crend(). **/ 2251 const_reverse_iterator rend() const 2252 { return this->CBase::crend(); } 2253 /** Return a writable past-the-end reverse iterator that tests equal to a 2254 reverse iterator that has been incremented past the front of the array. You 2255 cannot dereference this iterator. **/ 2256 reverse_iterator rend() {return this->Base::rend();} 2257 2258 /** Return a const pointer to the first element of the array, or possibly 2259 (but not necessarily) null (0) if the array is empty. 2260 @note 2261 cdata() is not in the C++11 standard although it would seem 2262 obvious in view of the cbegin() and cend() methods that had to be added. 2263 The C++11 overloaded const data() method is also available. **/ 2264 SimTK_FORCE_INLINE const T* cdata() const {return this->CBase::cdata();} 2265 /** The const version of the data() method is identical to cdata(). 2266 @note This method is from the C++11 std::vector. **/ 2267 SimTK_FORCE_INLINE const T* data() const {return this->CBase::cdata();} 2268 /** Return a writable pointer to the first allocated element of the array, or 2269 a null pointer if no space is associated with the array. 2270 @note This method is from the C++11 std::vector. **/ 2271 SimTK_FORCE_INLINE T* data() {return this->Base::data();} 2272 /*@}*/ 2273 2274 /** @name Element access 2275 2276 These methods provide read and write access to individual elements, or groups 2277 of elements, that are currently present in the array. **/ 2278 /*@{*/ 2279 2280 /** Select an element by its index, returning a const reference. Note that only 2281 a value of the Array's templatized index type is allowed (default is unsigned). 2282 This will be range-checked in a Debug build but not in Release. 2283 @pre 0 <= \a i < size() 2284 @par Complexity: 2285 Constant time. **/ 2286 SimTK_FORCE_INLINE const T& operator[](index_type i) const 2287 { return this->CBase::operator[](i); } 2288 2289 /** Select an element by its index, returning a writable (lvalue) reference. 2290 Note that only a value of the Array's templatized index type is allowed 2291 (default is unsigned). This will be range-checked in a Debug build but not 2292 in Release. 2293 @pre 0 <= \a i < size() 2294 @par Complexity: 2295 Constant time. **/ 2296 SimTK_FORCE_INLINE T& operator[](index_type i) {return this->Base::operator[](i);} 2297 2298 /** Same as operator[] but always range-checked, even in a Release build. 2299 @pre 0 <= \a i < size() 2300 @par Complexity: 2301 Constant time. **/ 2302 const T& at(index_type i) const {return this->CBase::at(i);} 2303 2304 /** Same as operator[] but always range-checked, even in a Release build. 2305 @pre 0 <= \a i < size() 2306 @par Complexity: 2307 Constant time. **/ 2308 T& at(index_type i) {return const_cast<T&>(this->Base::at(i));} 2309 2310 /** Same as the const form of operator[]; exists to provide a non-operator 2311 method for element access in case that's needed. **/ 2312 SimTK_FORCE_INLINE const T& getElt(index_type i) const 2313 { return this->CBase::getElt(i); } 2314 /** Same as the non-const form of operator[]; exists to provide a non-operator 2315 method for element access in case that's needed. **/ 2316 SimTK_FORCE_INLINE T& updElt(index_type i) {return this->Base::updElt(i);} 2317 2318 /** Return a const reference to the first element in this array, which must 2319 not be empty. 2320 @pre The array is not empty. 2321 @par Complexity: 2322 Constant time. **/ 2323 SimTK_FORCE_INLINE const T& front() const {return this->CBase::front();} 2324 2325 /** Return a writable reference to the first element in this array, which must 2326 not be empty. 2327 @pre The array is not empty. 2328 @par Complexity: 2329 Constant time. **/ 2330 SimTK_FORCE_INLINE T& front() {return const_cast<T&>(this->Base::front());} 2331 2332 /** Return a const reference to the last element in this array, which must 2333 not be empty. 2334 @pre The array is not empty. 2335 @par Complexity: 2336 Constant time. **/ 2337 SimTK_FORCE_INLINE const T& back() const {return this->CBase::back();} 2338 2339 /** Return a writable reference to the last element in this array, which must 2340 not be empty. 2341 @pre The array is not empty. 2342 @par Complexity: 2343 Constant time. **/ 2344 SimTK_FORCE_INLINE T& back() {return const_cast<T&>(this->Base::back());} 2345 2346 /** Select a subrange of this const array by starting index and length, and 2347 return a ArrayViewConst_ referencing that data without copying it. **/ 2348 ArrayViewConst_<T,X> operator()(index_type index, size_type length) const 2349 { return CBase::operator()(index,length); } 2350 /** Same as const form of operator()(index,length); exists to provide 2351 non-operator access to that functionality in case it is needed. **/ 2352 ArrayViewConst_<T,X> getSubArray(index_type index, size_type length) const 2353 { return CBase::getSubArray(index,length); } 2354 2355 /** Select a subrange of this array by starting index and length, and 2356 return an ArrayView_ referencing that data without copying it. **/ 2357 ArrayView_<T,X> operator()(index_type index, size_type length) 2358 { return Base::operator()(index,length); } 2359 /** Same as non-const operator()(index,length); exists to provide non-operator 2360 access to that functionality in case it is needed. **/ 2361 ArrayView_<T,X> updSubArray(index_type index, size_type length) 2362 { return Base::updSubArray(index,length); } 2363 /*@} End of element access. **/ 2364 2365 2366 //------------------------------------------------------------------------------ 2367 /**@name Element insertion and removal 2368 2369 These are methods that change the number of elements in the array by insertion 2370 or erasure. **/ 2371 /*@{*/ 2372 2373 /** This method increases the size of the Array by one element at the end and 2374 initializes that element by copy constructing it from the given value. If 2375 capacity() > size(), that's all that will happen. If capacity()==size(), there 2376 is no room for another element so we'll allocate more space and move all the 2377 elements there. A reference to the just-inserted element can be obtained using 2378 the back() method after the call to push_back(). 2379 @param[in] value 2380 An object of type T from which the new element is copy-constructed. 2381 2382 @remarks 2383 - If you are appending a default-constructed object of type T, consider using 2384 the alternate non-standard but safe push_back() method rather than 2385 push_back(T()). The non-standard method default-constructs the new element 2386 internally. That avoids a call to the copy constructor which can be 2387 expensive for some objects, and nonexistent for others. 2388 - If you are constructing the source object with a non-default constructor, 2389 and the object is expensive or impossible to default-construct and/or 2390 copy-construct, consider using the non-standard and dangerous method 2391 raw_push_back() which enables you to construct the new element in place. 2392 2393 @par Complexity: 2394 Constant time if no reallocation is required; otherwise the current 2395 contents of the array must be moved to new space, costing one call to T's 2396 move constructor and destructor (if any) for each element currently in the 2397 array. Either way there is also one call to T's copy constructor to 2398 construct the new element from the supplied value. **/ 2399 void 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 2406 /** This is the move form of push_back(), taking an rvalue reference rather 2407 than an lvalue reference. See the other signature for information, with 2408 move-construction instead of copy-construction (reallocation is the same 2409 in either case). **/ 2410 void 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 2417 /** This is similar to push_back() but rather than copying, it constructs the 2418 element in place at the end of the array. To do that it invokes the constructor 2419 of T whose signature matches the supplied argument pack. This has the same 2420 effect as `push_back(T(Args...))` would have but avoids the extra copy that 2421 would be required. Reallocation is handled the same as for push_back(). 2422 2423 @note This method should be preferred to the nonstandard raw_push_back() 2424 method. **/ 2425 template<class... Args> 2426 void 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 2433 /** (Deprecated, use emplace_back() instead) This is a non-standard version of 2434 push_back() that increases the size of the array by one default-constructed 2435 element at the end. This avoids having to default-construct the argument to the 2436 standard push_back(value) method which then has to copy-construct or 2437 move-construct it into the array. By carefully avoiding reallocation and using 2438 this form of push_back() you can use the Array_<T> class to hold objects of type 2439 T even if T has no copy or move constructor, which is prohibited by the standard 2440 std::vector<T> definition. 2441 2442 @note Since C++11 added emplace_back() you can accomplish the same thing 2443 by calling emplace_back() with no arguments. 2444 2445 @par Complexity: 2446 Same as the standard push_back(value) method except without the final 2447 call to T's copy constructor. 2448 @see emplace_back(), push_back(value) 2449 **/ 2450 void push_back() { 2451 if (pallocated() == psize()) 2452 growAtEnd(1,"Array_<T>::push_back()"); 2453 defaultConstruct(end()); 2454 incrSize(); 2455 } 2456 2457 /** (Deprecated, use emplace_back() instead) This dangerous non-standard method 2458 increases the Array's size by one element at the end but doesn't perform any 2459 construction so the memory is filled with garbage. You must immediately 2460 construct into this space, using code like: 2461 @code 2462 new(a.raw_push_back()) MyConstructor(args...); 2463 @endcode 2464 This is a substantial performance improvement when the element type is something 2465 complicated since the constructor is called once and not copied; it can also be 2466 used for objects that have neither default nor copy constructors. 2467 @return 2468 An iterator (pointer) pointing at the unconstructed element. 2469 2470 @note Since C++11 added emplace_back() you can accomplish the same thing safely 2471 by calling emplace_back(args...) with the constructor arguments. 2472 2473 @par Complexity: 2474 Same as ordinary push_back(). 2475 @see emplace_back(), push_back(value) 2476 **/ 2477 T* raw_push_back() { 2478 if (pallocated() == psize()) 2479 growAtEnd(1,"Array_<T>::raw_push_back()"); 2480 T* const p = end(); 2481 incrSize(); 2482 return p; 2483 } 2484 2485 /** Remove the last element from this array, which must not be empty. The 2486 element is destructed, not returned. The array's size() is reduced by one. **/ 2487 void pop_back() { 2488 SimTK_ERRCHK(!empty(), "Array_<T>::pop_back()", "Array was empty."); 2489 destruct(&back()); 2490 decrSize(); 2491 } 2492 2493 /** Erase elements in range [first,last1), packing in any later elements into 2494 the newly-available space and reducing the array's size by the number of 2495 elements erased. Capacity is unchanged. If the range is empty nothing happens. 2496 2497 @pre begin() <= \a first <= \a last1 <= end() 2498 @param first 2499 Points to the first element that will be erased. 2500 @param last1 2501 Points one element past the last element to be erased. 2502 @return 2503 An iterator pointing to the new location of the element immediately 2504 following the erased ones, or end() if there are none. Either way, this is 2505 the same memory address as the passed-in \a first argument since there can 2506 be no reallocation here. 2507 @par Complexity: 2508 Calls T's destructor once for each erased element and calls T's move 2509 constructor and destructor once for each element that has to be moved. **/ 2510 T* 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 2526 /** Erase just one element, moving all subsequent elements down one slot and 2527 reducing the array's size by one. This is equivalent to erase(p,p+1) but faster; 2528 that means \a p cannot be end() because end()+1 is not defined. Capacity is 2529 unchanged. 2530 2531 @note If you don't mind the elements being reordered, you can erase an element 2532 in constant time using the non-standard extension eraseFast(). 2533 2534 @param p 2535 Points to the element that will be erased; \a p cannot be end(). 2536 @return 2537 A pointer to the element that replaced the one at \a p, or end() if \a p 2538 was the last element. Either way, this is the same memory address as the 2539 erased element had since there can be no reallocation here. 2540 @pre begin() <= \a p < end() 2541 @par Complexity: 2542 Calls T's destructor once for the erased element and calls T's move 2543 constructor and destructor once for each element that has to be moved. 2544 @see eraseFast() **/ 2545 T* 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 2558 /** Be careful with this non-standard extension; it erases one element and 2559 then moves the last one in its place which changes the element order 2560 from what it was before (unlike the standard erase() method). This avoids 2561 having to compress the elements so this runs in constant time: 2562 the element is destructed; then if it wasn't the last element the 2563 move constructor is used to move the last element into the vacated 2564 space, and the destructor is called to clear the last element. The 2565 size is reduced by 1 but the capacity does not change. 2566 2567 @param p 2568 Points to the element that will be erased; \a p cannot be end(). 2569 @return 2570 A pointer to the element that replaced the one at \a p, or end() if \a p 2571 was the last element. Either way, this is the same memory address as the 2572 erased element had since there can be no reallocation here. 2573 @pre begin() <= \a p < end() 2574 @par Complexity: 2575 Calls T's destructor once for the erased element and calls T's move 2576 constructor and destructor once for each element that has to be moved. 2577 @see erase() **/ 2578 T* 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 2591 /** Erase all the elements currently in this array without changing the 2592 capacity; equivalent to erase(begin(),end()) but a little faster. Size is 2593 zero after this call. T's destructor is called exactly once for each element 2594 in the array. 2595 2596 @par Complexity: 2597 O(n) if T has a destructor; constant time otherwise. **/ 2598 void 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 2606 /** Insert \a n copies of a given value at a particular location within this 2607 array, moving all following elements up by \a n positions. 2608 2609 @param[in] p 2610 Where to insert the new elements. This must be an iterator (pointer) that 2611 is valid for this array, that is, begin() <= \a p <= end(). 2612 @param[in] n 2613 How many copies of the given \a value to insert. Nothing happens if 2614 \a n is zero. 2615 @param[in] value 2616 A value of the element type that is copied into the newly-created elements 2617 using T's copy constructor. 2618 @return 2619 A pointer to the first of the newly-created elements in the array. This 2620 will be different from \a p if reallocation occurred, otherwise it is the 2621 same as \a p was on entry. 2622 2623 @pre begin() <= \a p <= end() 2624 @par Complexity: 2625 If size() + \a n > capacity() then the array must be reallocated, resulting 2626 in size() move constructor/destructor call pairs to move the old data to 2627 the new location. Otherwise, the m=(end()-\a p) elements above the insertion 2628 point must be moved up \a n positions resulting in m move/destruct pairs. 2629 Then there are n copy constructor calls to construct the new elements from 2630 the given value. 2631 **/ 2632 T* 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 2640 /** Insert a new element at a given location within this array, initializing 2641 it to a copy of a given value and moving all following elements up one 2642 position. This is identical to insert(\a p,1,\a value) but slightly faster; see 2643 that method for full documentation. **/ 2644 T* 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 2652 /** Insert a new element at a given location within this array, by invoking 2653 T's constructor whose signature matches the supplied arguments. All following 2654 elements are moved up one position. This is identical in effect to 2655 `insert(p,T(Args...))` but avoids the extra copy that would be required in that 2656 case. **/ 2657 template <class... Args> 2658 T* 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 2666 /** Insert elements in a range [first,last1) into this array at a given position 2667 \a p, moving all following elements up by n=(last1-first) positions. This 2668 variant of insert() takes iterators which are ordinary pointers, although the 2669 source elements do not have to be of type T as long as there is a constructor 2670 T(T2) that works. 2671 2672 @param[in] p 2673 Where to insert the new elements. This must be an iterator (pointer) that 2674 is valid for this array, that is, begin() <= \a p <= end(). 2675 @param[in] first 2676 This is a pointer to the first element of the source to be copied. 2677 @param[in] last1 2678 This points one element past the last element of the source to be copied. 2679 @return 2680 A pointer to the first of the newly-created elements in the array. This 2681 will be different from \a p if reallocation occurred, otherwise it is the 2682 same as \a p was on entry. 2683 2684 @pre begin() <= \a p <= end() 2685 @pre first <= last1 2686 @pre The range [first,last1) does not include any of the current contents 2687 of this array. 2688 @par Complexity: 2689 If capacity() < size()+n then the array must be reallocated, resulting in 2690 size() calls to T's move constructor and destructor (if any) to move the old 2691 data to the new location. Otherwise, the m=(end()-\a p) elements above the 2692 insertion point must be moved up n positions resulting in m move/destruct 2693 pairs. Then there are n T(T2) constructor calls to construct the new 2694 elements from the given value. **/ 2695 template <class T2> 2696 T* 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 2708 /** Insert elements in a range [first,last1) where the range is given by 2709 non-pointer iterators. **/ 2710 template <class Iter> 2711 T* insert(T* p, const Iter& first, const Iter& last1) { 2712 return insertDispatch(p, first, last1, 2713 typename IsIntegralType<Iter>::Result(), 2714 "Array_<T>::insert(T* p, Iter first, Iter last1)"); 2715 } 2716 /*@} End of insertion and erase. **/ 2717 2718 2719 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. 2739 T* 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. 2768 void 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. 2787 size_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. 2811 T* 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. 2853 template <class IntegralType> void 2854 ctorDispatch(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. 2866 template <class InputIterator> void 2867 ctorDispatch(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. 2878 template <class InputIterator> void 2879 ctorIteratorDispatch(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. 2906 template <class ForwardIterator> void 2907 ctorIteratorDispatch(const ForwardIterator& first, const ForwardIterator& last1, 2908 std::forward_iterator_tag) 2909 { 2910 typedef typename std::iterator_traits<ForwardIterator>::difference_type 2911 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. 2938 template <class IntegralType> 2939 T* 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. 2946 template <class InputIterator> 2947 T* 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. 2956 template <class InputIterator> 2957 T* 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. 2980 template <class ForwardIterator> 2981 T* 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 2987 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. 3012 template <class IntegralType> 3013 void 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. 3020 template <class InputIterator> 3021 void 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. 3030 template <class InputIterator> 3031 void 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. 3062 template <class ForwardIterator> 3063 void 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. 3119 void reallocateIfAdvisable(size_type n) { 3120 if (allocated() < n || allocated()/2 > std::max(minAlloc(), n)) 3121 reallocateNoDestructOrConstruct(n); 3122 } 3123 3124 3125 void allocateNoConstruct(size_type n) 3126 { setData(allocN(n)); setAllocated(n); } // size() left unchanged 3127 void deallocateNoDestruct() 3128 { freeN(data()); setData(0); setAllocated(0); } // size() left unchanged 3129 void reallocateNoDestructOrConstruct(size_type n) 3130 { deallocateNoDestruct(); allocateNoConstruct(n); } 3131 3132 // This sets the smallest allocation we'll do when growing. 3133 size_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. 3139 static 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. 3152 static void freeN(T* p) { 3153 delete[] reinterpret_cast<char*>(p); 3154 } 3155 3156 // default construct one element 3157 static void defaultConstruct(T* p) {new(p) T();} 3158 // default construct range [b,e) 3159 static 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 3163 static 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 3167 static void copyConstruct(T* p, const T& v) {new(p) T(v);} 3168 // move construct one element from a given value 3169 static void moveConstruct(T* p, T&& v) {new(p) T(std::move(v));} 3170 3171 // copy construct range [b,e) from sequence of source values 3172 static 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 3175 static 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. 3180 template <class InputIterator> 3181 static 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. 3188 static 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. 3195 static 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. 3202 void 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. 3212 void 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. 3221 void 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 3231 static void destruct(T* p) {p->~T();} 3232 // destruct range [b,e) 3233 static 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. 3238 template <class S> 3239 bool 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. 3249 packed_size_type psize() const {return this->CBase::psize();} 3250 packed_size_type pallocated() const {return this->CBase::pallocated();} 3251 3252 void setData(const T* p) {this->CBase::setData(p);} 3253 void setSize(size_type n) {this->CBase::setSize(n);} 3254 void incrSize() {this->CBase::incrSize();} 3255 void decrSize() {this->CBase::decrSize();} 3256 void 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. 3259 unsigned long long ullSize() const 3260 { return this->CBase::ullSize(); } 3261 unsigned long long ullCapacity() const 3262 { return this->CBase::ullCapacity(); } 3263 unsigned 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. 3267 const 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. 3279 template <class T, class X> static inline 3280 std::istream& readArrayFromStreamHelper 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 3460 /**@name Array_<T> serialization and I/O 3461 These methods are at namespace scope but are logically part of the Array 3462 classes. These deal with reading and writing Arrays from and to streams, 3463 which places an additional requirement on the element type T: the element 3464 must support the same operation you are trying to do on the Array as a 3465 whole. **/ 3466 /*@{*/ 3467 3468 /** Specialize writeUnformatted() for Array_<E,X> to delegate to element type 3469 E, with spaces separating the elements. 3470 @relates SimTK::Array_ **/ 3471 template <class T, class X> inline void 3472 writeUnformatted(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 3480 /** Specialize writeFormatted() for Array_<E,X> to delegate to element type 3481 E, with surrounding parentheses and commas separating the elements. 3482 @relates SimTK::Array_ **/ 3483 template <class T, class X> inline void 3484 writeFormatted(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 3493 /** Output a human readable representation of an array to an std::ostream 3494 (like std::cout). The format is ( \e elements ) where \e elements is a 3495 comma-separated list of the Array's contents output by invoking the "<<" 3496 operator on the elements. This function will not compile if the element type 3497 does not support the "<<" operator. No newline is issued before 3498 or after the output. @relates Array_ **/ 3499 template <class T, class X> inline 3500 std::ostream& 3501 operator<<(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 3514 /** Specialization of readUnformatted() for variable-length Array_<T,X>; 3515 continues reading whitespace-separated tokens until error or eof. 3516 @relates Array_ **/ 3517 template <class T, class X> inline bool 3518 readUnformatted(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 3527 /** Specialization of readUnformatted() for fixed-length ArrayView_<T,X>; reads 3528 whitespace-separated tokens until the expected number have been read. If fewer 3529 are available we fail. 3530 @relates ArrayView_ **/ 3531 template <class T, class X> inline bool 3532 readUnformatted(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 3539 /** Specialization of readFormatted() for variable-length Array_<T,X>; 3540 uses readArrayFromStream() to consume an appropriately-formatted array 3541 until error, closing parenthesis or bracket, or eof. 3542 @see readArrayFromStream() for details 3543 @relates Array_ **/ 3544 template <class T, class X> inline bool 3545 readFormatted(std::istream& in, Array_<T,X>& v) { 3546 return !readArrayFromStream(in,v).fail(); 3547 } 3548 3549 /** Specialization of readFormatted() for fixed-length ArrayView_<T,X>; uses 3550 fillArrayViewFromStream() to consume an appropriately-formatted fixed-size 3551 array. 3552 @see fillArrayViewFromStream() for details 3553 @relates ArrayView_ **/ 3554 template <class T, class X> inline bool 3555 readFormatted(std::istream& in, ArrayView_<T,X>& v) { 3556 return !fillArrayViewFromStream(in,v).fail(); 3557 } 3558 3559 /** Read in an Array_<T> from a stream, as a sequence of space-separated or 3560 comma-separated values optionally surrounded by parentheses (), square 3561 brackets [], or curly braces {}. We will continue to read elements of 3562 type T from the stream until we find a reason to stop, using type T's stream 3563 extraction operator>>() to read in each element and resizing the Array as 3564 necessary. If the data is bracketed, we'll read until we hit the closing 3565 bracket. If it is not bracketed, we'll read until we hit eof() or get an error 3566 such as the element extractor setting the stream's fail bit due to bad 3567 formatting. On successful return, the stream will be positioned right after 3568 the final read-in element or terminating bracket, and the stream's status will 3569 be good() or eof(). We will not consume trailing whitespace after bracketed 3570 elements; that means the stream might actually be empty even if we don't 3571 return eof(). If you want to know whether there is anything else in the 3572 stream, follow this call with the STL whitespace skipper std::ws() like this: 3573 @code 3574 if (readArrayFromStream(in,array) && !in.eof()) 3575 std::ws(in); // might take us to eof 3576 if (in.fail()) {...} // probably a formatting error 3577 else { 3578 // Here if the stream is good() then there is more to read; if the 3579 // stream got used up the status is guaranteed to be eof(). 3580 } 3581 @endcode 3582 A compilation error will occur if you try to use this method on an Array_<T> 3583 for a type T for which there is no stream extraction operator>>(). 3584 @note If you want to fill an owner Array_<T> with a fixed amount of data from 3585 the stream, resize() the array to the appropriate length and then use 3586 fillArrayFromStream() instead. @see fillArrayFromStream() 3587 @relates Array_ **/ 3588 template <class T, class X> static inline 3589 std::istream& readArrayFromStream(std::istream& in, Array_<T,X>& out) 3590 { return readArrayFromStreamHelper<T,X>(in, false /*variable sizez*/, out); } 3591 3592 3593 3594 /** Read in a fixed number of elements from a stream into an Array. We expect 3595 to read in exactly size() elements of type T, using type T's stream extraction 3596 operator>>(). This will stop reading when we've read size() elements, or set 3597 the fail bit in the stream if we run out of elements or if any element's 3598 extract operator sets the fail bit. On successful return, all size() elements 3599 will have been set, the stream will be positioned right after the final 3600 read-in element or terminating bracket, and the stream's status will be good() 3601 or eof(). We will not consume trailing whitespace after reading all the 3602 elements; that means the stream might actually be empty even if we don't 3603 return eof(). If you want to know whether there is anything else in the 3604 stream, follow this call with std::ws() like this: 3605 @code 3606 if (fillArrayFromStream(in,array)) 3607 if (!in.eof()) std::ws(in); // might take us to eof 3608 if (in.fail()) {...} // deal with I/O or formatting error 3609 // Here if the stream is good() then there is more to read; if the 3610 // stream got used up the status is guaranteed to be eof(). 3611 @endcode 3612 A compilation error will occur if you try to use this method on an Array_<T> 3613 for a type T for which there is no stream extraction operator>>(). 3614 @note If you want to read in a variable number of elements and have the 3615 Array_<T> resized as needed, use readArrayFromStream() instead. 3616 @see readArrayFromStream() 3617 @relates Array_ **/ 3618 template <class T, class X> static inline 3619 std::istream& fillArrayFromStream(std::istream& in, Array_<T,X>& out) 3620 { return readArrayFromStreamHelper<T,X>(in, true /*fixed size*/, out); } 3621 3622 /** Read in a fixed number of elements from a stream into an ArrayView. See 3623 fillArrayFromStream() for more information; this works the same way. 3624 @see fillArrayFromStream() 3625 @relates ArrayView_ **/ 3626 template <class T, class X> static inline 3627 std::istream& fillArrayViewFromStream(std::istream& in, ArrayView_<T,X>& out) 3628 { return readArrayFromStreamHelper<T,X>(in, true /*fixed size*/, out); } 3629 3630 3631 3632 3633 /** Read an Array_<T> from a stream as a sequence of space- or comma-separated 3634 values of type T, optionally delimited by parentheses, brackets, or braces. 3635 The Array_<T> may be an owner (variable size) or a view (fixed size n). In 3636 the case of an owner, we'll read all the elements in brackets or until eof if 3637 there are no brackets. In the case of a view, there must be exactly n elements 3638 in brackets, or if there are no brackets we'll consume exactly n elements and 3639 then stop. Each element is read in with its own operator ">>" so this won't 3640 work if no such operator is defined for type T. 3641 @relates Array_ **/ 3642 template <class T, class X> inline 3643 std::istream& operator>>(std::istream& in, Array_<T,X>& out) 3644 { return readArrayFromStream<T,X>(in, out); } 3645 3646 /** Read a (fixed size n) ArrayView_<T> from a stream as a sequence of space- 3647 or comma-separated values of type T, optionally delimited by parentheses, 3648 square brackets, or curly braces. If there are no delimiters then we will read 3649 size() values and then stop. Otherwise, there must be exactly size() values 3650 within the brackets. Each element is read in with its own operator ">>" so 3651 this won't work if no such operator is defined for type T. 3652 @relates ArrayView_ **/ 3653 template <class T, class X> inline 3654 std::istream& operator>>(std::istream& in, ArrayView_<T,X>& out) 3655 { return fillArrayViewFromStream<T,X>(in, out); } 3656 3657 /*@} End of Array serialization. **/ 3658 3659 3660 3661 /**@name Comparison operators 3662 These operators permit lexicographical comparisons between two comparable 3663 Array_ objects, possibly with differing element and index types, and between 3664 an Array_ object and a comparable std::vector object. @relates Array_ **/ 3665 /*@{*/ 3666 3667 /** Two Array_ objects are equal if and only if they are the same size() and 3668 each element compares equal using an operator T1==T2. @relates Array_ **/ 3669 template <class T1, class X1, class T2, class X2> inline bool 3670 operator==(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2) { 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 } 3681 /** The not equal operator is implemented using the equal operator. 3682 @relates Array_ **/ 3683 template <class T1, class X1, class T2, class X2> inline bool 3684 operator!=(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2) 3685 { return !(a1 == a2); } 3686 3687 /** Array_ objects are ordered lexicographically; that is, by first differing 3688 element or by length if there are no differing elements up to the length of the 3689 shorter array (in which case the shorter one is "less than" the longer). 3690 This depends on T1==T2 and T1<T2 operators working. @relates Array_ **/ 3691 template <class T1, class X1, class T2, class X2> inline bool 3692 operator<(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2) { 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 } 3704 /** The greater than or equal operator is implemented using the less than 3705 operator. @relates Array_ **/ 3706 template <class T1, class X1, class T2, class X2> inline bool 3707 operator>=(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2) 3708 { return !(a1 < a2); } 3709 /** The greater than operator is implemented by using less than with the 3710 arguments reversed, meaning the elements must have working comparison 3711 operators of the form T2==T1 and T2<T1. @relates Array_ **/ 3712 template <class T1, class X1, class T2, class X2> inline bool 3713 operator>(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2) 3714 { return a2 < a1; } 3715 /** The less than or equal operator is implemented using the greater than 3716 operator. @relates Array_ **/ 3717 template <class T1, class X1, class T2, class X2> inline bool 3718 operator<=(const ArrayViewConst_<T1,X1>& a1, const ArrayViewConst_<T2,X2>& a2) 3719 { return !(a1 > a2); } 3720 3721 /** An Array_<T1> and an std::vector<T2> are equal if and only if they are the 3722 same size() and each element compares equal using an operator T1==T2. 3723 @relates Array_ **/ 3724 template <class T1, class X1, class T2, class A2> inline bool 3725 operator==(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2) 3726 { return a1 == ArrayViewConst_<T2,size_t>(v2); } 3727 3728 /** An std::vector<T1> and an Array_<T2> are equal if and only if they are the 3729 same size() and each element compares equal using an operator T2==T1. 3730 @relates Array_ **/ 3731 template <class T1, class A1, class T2, class X2> inline bool 3732 operator==(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2) 3733 { return a2 == v1; } 3734 3735 /** The not equal operator is implemented using the equal operator. 3736 @relates Array_ **/ 3737 template <class T1, class X1, class T2, class A2> inline bool 3738 operator!=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2) 3739 { return !(a1 == v2); } 3740 /** The not equal operator is implemented using the equal operator. 3741 @relates Array_ **/ 3742 template <class T1, class A1, class T2, class X2> inline bool 3743 operator!=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2) 3744 { return !(a2 == v1); } 3745 3746 /** An Array_<T1> and std::vector<T2> are ordered lexicographically; that is, 3747 by first differing element or by length if there are no differing elements up 3748 to the length of the shorter container (in which case the shorter one is 3749 "less than" the longer). This depends on having working element operators 3750 T1==T2 and T1<T2. @relates Array_ **/ 3751 template <class T1, class X1, class T2, class A2> inline bool 3752 operator<(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2) 3753 { return a1 < ArrayViewConst_<T2,size_t>(v2); } 3754 3755 /** An std::vector<T1> and Array_<T2> are ordered lexicographically; that is, 3756 by first differing element or by length if there are no differing elements up 3757 to the length of the shorter container (in which case the shorter one is 3758 "less than" the longer). This depends on having working element operators 3759 T1==T2 and T1<T2. @relates Array_ **/ 3760 template <class T1, class A1, class T2, class X2> inline bool 3761 operator<(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2) 3762 { return ArrayViewConst_<T1,size_t>(v1) < a2; } 3763 3764 /** The greater than or equal operator is implemented using the less than 3765 operator. @relates Array_ **/ 3766 template <class T1, class X1, class T2, class A2> inline bool 3767 operator>=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2) 3768 { return !(a1 < v2); } 3769 /** The greater than or equal operator is implemented using the less than 3770 operator. @relates Array_ **/ 3771 template <class T1, class A1, class T2, class X2> inline bool 3772 operator>=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2) 3773 { return !(v1 < a2); } 3774 3775 /** The greater than operator is implemented by using less than with the 3776 arguments reversed, meaning the elements must have working comparison 3777 operators of the form T2==T1 and T2<T1. @relates Array_ **/ 3778 template <class T1, class X1, class T2, class A2> inline bool 3779 operator>(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2) 3780 { return v2 < a1; } 3781 /** The greater than operator is implemented by using less than with the 3782 arguments reversed, meaning the elements must have working comparison 3783 operators of the form T2==T1 and T2<T1. @relates Array_ **/ 3784 template <class T1, class A1, class T2, class X2> inline bool 3785 operator>(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2) 3786 { return a2 < v1; } 3787 3788 /** The less than or equal operator is implemented using the greater than 3789 operator. @relates Array_ **/ 3790 template <class T1, class X1, class T2, class A2> inline bool 3791 operator<=(const ArrayViewConst_<T1,X1>& a1, const std::vector<T2,A2>& v2) 3792 { return !(a1 > v2); } 3793 /** The less than or equal operator is implemented using the greater than 3794 operator. @relates Array_ **/ 3795 template <class T1, class A1, class T2, class X2> inline bool 3796 operator<=(const std::vector<T1,A1>& v1, const ArrayViewConst_<T2,X2>& a2) 3797 { return !(v1 > a2); } 3798 3799 /*@}*/ 3800 3801 } // namespace SimTK 3802 3803 namespace std { 3804 /** This is a specialization of the STL std::swap() algorithm which uses the 3805 constant time built-in swap() member of the Array_ class. 3806 @relates SimTK::Array_ **/ 3807 template <class T, class X> inline void 3808 swap(SimTK::Array_<T,X>& a1, SimTK::Array_<T,X>& a2) { 3809 a1.swap(a2); 3810 } 3811 3812 } // namespace std 3813 3814 #endif // SimTK_SimTKCOMMON_ARRAY_H_ 3815