1 #ifndef _ArrayPtrs_h_
2 #define _ArrayPtrs_h_
3 /* -------------------------------------------------------------------------- *
4  *                           OpenSim:  ArrayPtrs.h                            *
5  * -------------------------------------------------------------------------- *
6  * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
7  * See http://opensim.stanford.edu and the NOTICE file for more information.  *
8  * OpenSim is developed at Stanford University and supported by the US        *
9  * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
10  * through the Warrior Web program.                                           *
11  *                                                                            *
12  * Copyright (c) 2005-2017 Stanford University and the Authors                *
13  * Author(s): Frank C. Anderson                                               *
14  *                                                                            *
15  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
16  * not use this file except in compliance with the License. You may obtain a  *
17  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
18  *                                                                            *
19  * Unless required by applicable law or agreed to in writing, software        *
20  * distributed under the License is distributed on an "AS IS" BASIS,          *
21  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
22  * See the License for the specific language governing permissions and        *
23  * limitations under the License.                                             *
24  * -------------------------------------------------------------------------- */
25 
26 /* Note: This code was originally developed by Realistic Dynamics Inc.
27  * Author: Frank C. Anderson
28  */
29 
30 
31 #include "osimCommonDLL.h"
32 #include <iostream>
33 #include "Exception.h"
34 
35 
36 //=============================================================================
37 //=============================================================================
38 /**
39  * A class for storing an array of pointers to objects of type T.
40  *
41  * In contrast to class Array<T>, when an object is added to this array
42  * a copy is not made.  Rather, a pointer to the added object is
43  * stored in the array.
44  *
45  * When an ArrayPtrs object falls out of scope or is deleted, all objects
46  * pointed to by the pointers in the array are deleted unless the array
47  * is set not to own the memory associated with the objects to which its
48  * array points.
49  *
50  * The capacity of the class grows as needed.  To use this template for a
51  * class of type T, class T should implement the following methods:
52  * default constructor, copy constructor, T* clone(),
53  * assignment operator (=), equality operator (==), less than
54  * operator (<), and the output operator (<<).
55  *
56  * @version 1.0
57  * @author Frank C. Anderson
58  */
59 namespace OpenSim {
60 
61 template<class T> class ArrayPtrs
62 {
63 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
64 // DATA
65 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
66 protected:
67     /** Flag indicating whether this ArrayPtrs object is responsible for
68     (owns) the memory associated with the pointers in its array and therefore
69     should issue deletes for the pointers upon destruction.  By default,
70     _memoryOwner = true. */
71     bool _memoryOwner;
72     /** Size of the array.  Also the index of the first empty array element. */
73     int _size;
74     /** Current capacity of the array. */
75     int _capacity;
76     /** Increment by which the current capacity is increased when the capacity
77     of this array is reached.  If negative, capacity doubles. */
78     int _capacityIncrement;
79     /** Array of pointers to objects of type T. */
80     T **_array;
81 
82 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
83 // METHODS
84 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
85 //=============================================================================
86 // CONSTRUCTION
87 //=============================================================================
88 public:
89 
90 // This typedef is used to avoid "duplicate const" errors with SWIG.
91 typedef typename std::add_const<T>::type ConstT;
92 
93 //_____________________________________________________________________________
94 /**
95  * Destructor.
96  *
97  * When the array is deleted, if this array is the memory owner, pointers
98  * held by this array are also deleted.
99  *
100  * @see setMemoryOwner()
101  */
~ArrayPtrs()102 virtual ~ArrayPtrs()
103 {
104     if(_memoryOwner) clearAndDestroy();
105 
106     // ARRAY
107     delete[] _array;
108     _array = NULL;
109 }
110 //_____________________________________________________________________________
111 /**
112  * Default constructor.
113  *
114  * @param aCapacity Initial capacity of the array.  The capacity
115  * must be 1 or greater.
116  */
117 explicit ArrayPtrs(int aCapacity=1)
118 {
119     setNull();
120 
121     // CAPACITY
122     if(aCapacity<1)  aCapacity = 1;
123     ensureCapacity(aCapacity);
124 
125 }
126 //_____________________________________________________________________________
127 /**
128  * Copy constructor.
129  *
130  * @param aArray Array to be copied.
131  */
ArrayPtrs(const ArrayPtrs<T> & aArray)132 ArrayPtrs(const ArrayPtrs<T> &aArray)
133 {
134     setNull();
135     *this = aArray;
136 }
137 
138 
139 private:
140 //_____________________________________________________________________________
141 /**
142  * %Set all member variables to their null or default values.
143  */
setNull()144 void setNull()
145 {
146     _memoryOwner = true;
147     _size = 0;
148     _capacityIncrement = -1;
149     _capacity = 0;
150     _array = NULL;
151 }
152 
153 public:
154 //_____________________________________________________________________________
155 /**
156  * Destroy all objects pointed to by this array and set the size of the
157  * array to zero.  When this method is called, the objects pointed to by
158  * this array are destroyed (deleted) even if this array is not set as
159  * the memory owner.
160  *
161  * @see setMemoryOwner()
162  */
clearAndDestroy()163 void clearAndDestroy()
164 {
165     if(_array==NULL) return;
166 
167     int i;
168     for(i=0;i<_size;i++) {
169         delete _array[i];  _array[i]=NULL;
170     }
171 
172     _size = 0;
173 }
174 
175 
176 //=============================================================================
177 // OPERATORS
178 //=============================================================================
179 public:
180 //-----------------------------------------------------------------------------
181 // ASSIGNMENT (=)
182 //-----------------------------------------------------------------------------
183 //_____________________________________________________________________________
184 /**
185  * Assign this array to a specified array.
186  * This operator makes a complete copy of the specified array; all member
187  * variables and objects in the array are copied.  Because all objects are
188  * copied, this object takes ownership of the newly allocated objects (i.e.,
189  * _memoryOwner is set to true. So, the result is two independent,
190  * identical arrays, with the possible exception of the _memoryOwner flag.
191  *
192  * @param aArray Array to be copied.
193  * @return Reference to this array.
194  */
195 #ifndef SWIG
196 ArrayPtrs<T>& operator=(const ArrayPtrs<T> &aArray)
197 {
198     // DELETE OLD ARRAY
199     if(_memoryOwner) clearAndDestroy();
200 
201     // COPY MEMBER VARIABLES
202     _size = aArray._size;
203     _capacity = aArray._capacity;
204     _capacityIncrement = aArray._capacityIncrement;
205 
206     // ARRAY
207     int i;
208     if(_array!=NULL) delete[] _array;
209     _array = new T*[_capacity];
210     for(i=0;i<_size;i++) {
211         if(aArray._array[i]!=NULL)  _array[i] = aArray._array[i]->clone();
212     }
213 
214     // TAKE OWNERSHIP OF MEMORY
215     _memoryOwner = true;
216 
217     return(*this);
218 }
219 
220 //-----------------------------------------------------------------------------
221 // EQUALITY (==)
222 //-----------------------------------------------------------------------------
223 //_____________________________________________________________________________
224 /**
225  * Determine if two arrays are equal.
226  *
227  * Two arrays are equal if their contents are equal.  That is, each array
228  * must be the same length and their corresponding array elements must be
229  * equal.
230  *
231  * @param aArray Array to be tested as equal.
232  * @return True if equal, false if not equal.
233  */
234 bool operator==(const ArrayPtrs<T> &aArray) const
235 {
236     if(_size != aArray._size) return(false);
237 
238     int i;
239     for(i=0;i<_size;i++) {
240         if( !(_array[i]==aArray._array[i]) ) return(false);
241     }
242 
243     return(true);
244 }
245 
246 //-----------------------------------------------------------------------------
247 // BRACKETS ([])
248 //-----------------------------------------------------------------------------
249 //_____________________________________________________________________________
250 /**
251  * Get a pointer to the array object at a specified index.
252  *
253  * This operator is intended for accessing array elements with as little
254  * overhead as possible, so no error checking is performed.
255  * The caller must make sure the specified index is within the bounds of
256  * the array.  If error checking is desired, use ArrayPtrs::get().
257  *
258  * @param aIndex Index of the desired element (0 <= aIndex < _size).
259  * @return Reference to the array element.
260  * @throws Exception if a NULL pointer is encountered.
261  * @see get().
262  */
263 T* operator[](int aIndex) const
264 {
265     return( _array[aIndex] );
266 }
267 //_____________________________________________________________________________
268 //-----------------------------------------------------------------------------
269 // OUTPUT (<<)
270 //-----------------------------------------------------------------------------
271 //_____________________________________________________________________________
272 /**
273  * Implementation of the output operator.
274  * The output for an array looks like the following:\n\n
275  *
276  * ArrayPtrs[size] = T[0] T[1] T[2] ... T[size-1].
277  *
278  * @param aOut Output stream.
279  * @param aArray Array to be output.
280  * @return Reference to the output stream.
281  */
282 friend std::ostream& operator<<(std::ostream &aOut,const ArrayPtrs<T> &aArray)
283 {
284     aOut << "ArrayPtrs[" << aArray.getSize() <<"] =";
285 
286     int i;
287     T* obj;
288     for(i=0;i<aArray.getSize();i++)  {
289         aOut << " ";
290         obj = aArray[i];
291         if(obj==NULL) {
292             aOut << "NULL";
293         } else {
294             // The following line is having trouble compiling on IRIX.
295             //aOut << *obj;
296         }
297     }
298 
299     return(aOut);
300 }
301 
302 
303 //=============================================================================
304 // MEMORY OWNERSHIP
305 //=============================================================================
306 //_____________________________________________________________________________
307 /**
308  * %Set whether or not this array owns the memory pointed to by the pointers
309  * in its array.
310  *
311  * @param aTrueFalse If true, all the memory associated with each of the
312  * pointers in this array are deleted upon the array's destruction.  If
313  * false, deletes are not issued for each of the pointers.
314  */
setMemoryOwner(bool aTrueFalse)315 void setMemoryOwner(bool aTrueFalse)
316 {
317     _memoryOwner = aTrueFalse;
318 }
319 //_____________________________________________________________________________
320 /**
321  * Get whether or not this array owns the memory pointed to by the pointers
322  * in its array.
323  *
324  * If the array is set to own the memory pointed to by its pointers, this
325  * array issues deletes for all these pointers upon the array's destruction.
326  * If not, this array does not issue deletes.
327  *
328  * @return True if this array owns the memory; false otherwise.
329  */
getMemoryOwner()330 bool getMemoryOwner() const
331 {
332     return(_memoryOwner);
333 }
334 
335 
336 //=============================================================================
337 // CAPACITY
338 //=============================================================================
339 //_____________________________________________________________________________
340 /**
341  * Compute a new capacity that is at least as large as a specified minimum
342  * capacity; this method does not change the capacity, it simply computes
343  * a new recommended capacity.
344  *
345  * If the capacity increment is negative, the current capacity is
346  * doubled until the computed capacity is greater than or equal to the
347  * specified minimum capacity.  If the capacity increment is positive, the
348  * current capacity increments by this amount until the computed capacity is
349  * greater than or equal to the specified minimum capacity.  If the capacity
350  * increment is zero, the computed capacity is set to the current capacity
351  * and false is returned.
352  *
353  * @param rNewCapacity New computed capacity.
354  * @param aMinCapacity Minimum new computed capacity.  The computed capacity
355  * is incremented until it is at least as large as aMinCapacity, assuming
356  * the capacity increment is not zero.
357  * @return True if the new capacity was increased, false otherwise (i.e.,
358  * if the capacity increment is set to 0).
359  * @see setCapacityIncrement()
360  */
computeNewCapacity(int aMinCapacity,int & rNewCapacity)361 bool computeNewCapacity(int aMinCapacity,int &rNewCapacity)
362 {
363     rNewCapacity = _capacity;
364     if(rNewCapacity < 1) rNewCapacity = 1;
365 
366     // CHECK FOR ZERO INCREMENT
367     if(_capacityIncrement == 0) {
368         std::cout << "ArrayPtrs.computeNewCapacity: WARN- capacity is set";
369         std::cout << " not to increase (i.e., _capacityIncrement==0).\n";
370         return(false);
371     }
372 
373     // INCREMENT UNTIL LARGER THAN THE MINIMUM SIZE
374     while(rNewCapacity < aMinCapacity) {
375         if(_capacityIncrement < 0) {
376             rNewCapacity = 2 * rNewCapacity;
377         } else {
378             rNewCapacity = rNewCapacity + _capacityIncrement;
379         }
380     }
381 
382     return(true);
383 }
384 //_____________________________________________________________________________
385 /**
386  * Ensure that the capacity of this array is at least the specified amount.
387  * The newly allocated array elements are initialized to NULL.
388  *
389  * @param aCapacity Desired capacity.
390  * @return true if the capacity was successfully obtained, false otherwise.
391  */
ensureCapacity(int aCapacity)392 bool ensureCapacity(int aCapacity)
393 {
394     // CHECK REQUESTED CAPACITY
395     if(aCapacity < 1) aCapacity = 1;
396     if(_capacity>=aCapacity) return(true);
397 
398     // ALLOCATE THE NEW ARRAY
399     int i;
400     T **newArray = new T*[aCapacity];
401     if(newArray==NULL) {
402         std::cout << "ArrayPtrs.ensureCapacity: ERR- failed to increase capacity.\n";
403         return(false);
404     }
405 
406     // COPY CURRENT ARRAY
407     if(_array!=NULL) {
408         for(i=0;i<_size;i++) newArray[i] = _array[i];
409         for(i=_size;i<aCapacity;i++) newArray[i] = NULL;
410         delete[] _array;
411     } else {
412         for(i=0;i<aCapacity;i++) newArray[i] = NULL;
413     }
414 
415     // REASSIGN
416     _capacity = aCapacity;
417     _array = newArray;
418 
419     return(true);
420 }
421 
422 //_____________________________________________________________________________
423 /**
424  * Trim the capacity of this array so that it is one larger than the size
425  * of this array.  This is useful for reducing the amount of memory used
426  * by this array.  This capacity is kept at one larger than the size so
427  * that, for example, an array of characters can be treated as a NULL
428  * terminated string.
429  */
trim()430 void trim()
431 {
432     // COMPUTE NEW CAPACITY
433     int newCapacity = _size + 1;
434     if(newCapacity>=_capacity) return;
435     if(newCapacity<1) newCapacity = 1;
436 
437     // TEMPORARY ARRAY
438     T **array = _array;
439 
440     // ALLOCATE NEW ARRAY
441     _array = new T*[newCapacity];
442     if(_array==NULL) {
443         std::cout << "ArrayPtrs.trim: ERR- unable to allocate array.\n";
444         return;
445     }
446 
447     // RESET PREVIOUS VALUES
448     int i;
449     for(i=0;i<_size;i++) _array[i] = array[i];
450     _array[_size] = NULL;
451 
452     // SET CORRECT CAPACITY
453     _capacity = newCapacity;
454 
455     // DELETE OLD ARRAY
456     delete[] array;
457 }
458 //_____________________________________________________________________________
459 /**
460  * Get the capacity of this storage instance.
461  */
getCapacity()462 int getCapacity() const
463 {
464     return(_capacity);
465 }
466 
467 //-----------------------------------------------------------------------------
468 // CAPACITY INCREMENT
469 //-----------------------------------------------------------------------------
470 //_____________________________________________________________________________
471 /**
472  * %Set the amount by which the capacity is increased when the capacity of
473  * of the array in exceeded.
474  * If the specified increment is negative or this method
475  * is called with no argument, the capacity is set to double whenever
476  * the capacity is exceeded.
477  *
478  * @param aIncrement Desired capacity increment.
479  */
setCapacityIncrement(int aIncrement)480 void setCapacityIncrement(int aIncrement)
481 {
482     _capacityIncrement = aIncrement;
483 }
484 //_____________________________________________________________________________
485 /**
486  * Get the amount by which the capacity is increased.
487  */
getCapacityIncrement()488 int getCapacityIncrement() const
489 {
490     return(_capacityIncrement);
491 }
492 #endif
493 //=============================================================================
494 // STORAGE OPERATIONS
495 //=============================================================================
496 //-----------------------------------------------------------------------------
497 // SIZE
498 //-----------------------------------------------------------------------------
499 //_____________________________________________________________________________
500 /**
501  * %Set the size of the array.  This method can be used only to decrease
502  * the size of the array.  If the size of an array is decreased, all objects
503  * in the array that become invalid as a result of the decrease are
504  * deleted.
505  *
506  * Note that the size of an array is different than its capacity.  The size
507  * indicates how many valid elements are stored in an array.  The capacity
508  * indicates how much the size of the array can be increased without
509  * allocated more memory.  At all times size <= capacity.
510  *
511  * @param aSize Desired size of the array.  The size must be greater than
512  * or equal to zero and less than or equal to the current size of the
513  * array.
514  * @return True if the requested size change was carried out, false
515  * otherwise.
516  */
setSize(int aSize)517 bool setSize(int aSize)
518 {
519     if(aSize==_size) return(true);
520     if(aSize>_size) return(false);
521     if(aSize<0) aSize = 0;
522     if(aSize<_size) {
523         int i;
524         for(i=(_size-1);i>=aSize;i--) {
525             if(_array[i]!=NULL) {
526                 if(getMemoryOwner()) { delete _array[i]; }
527                 _array[i] = NULL;
528             }
529         }
530         _size = aSize;
531     }
532 
533     return(true);
534 }
535 //_____________________________________________________________________________
536 /**
537  * Get the size of the array.
538  *
539  * @return Size of the array.
540  */
getSize()541 int getSize() const
542 {
543     return(_size);
544 }
545 
546 /** Alternate name for getSize(). **/
size()547 int size() const {return getSize();}
548 
549 //-----------------------------------------------------------------------------
550 // INDEX
551 //-----------------------------------------------------------------------------
552 //_____________________________________________________________________________
553 /**
554  * Get the index of an object by specifying its name.
555  *
556  * @param aObject Address of the object whose index is sought.
557  * @param aStartIndex Index at which to start searching.  If the object is
558  * not found at or following aStartIndex, the array is searched from
559  * its beginning.
560  * @return Index of the object with the address aObject.  If no such object
561  * exists in the array, -1 is returned.
562  */
563 int getIndex(ConstT *aObject,int aStartIndex=0) const
564 {
565     if(aStartIndex<0) aStartIndex=0;
566     if(aStartIndex>=getSize()) aStartIndex=0;
567 
568     // SEARCH STARTING FROM aStartIndex
569     int i;
570     for(i=aStartIndex;i<getSize();i++) {
571         if(_array[i] == aObject) return(i);
572     }
573 
574     // SEARCH FROM BEGINNING
575     for(i=0;i<aStartIndex;i++) {
576         if(_array[i] == aObject) return(i);
577     }
578 
579     return(-1);
580 }
581 //_____________________________________________________________________________
582 /**
583  * Get the index of an object by specifying its name.
584  *
585  * @param aName Name of the object whose index is sought.
586  * @param aStartIndex Index at which to start searching.  If the object is
587  * not found at or following aStartIndex, the array is searched from
588  * its beginning.
589  * @return Index of the object named aName.  If no such object exists in
590  * the array, -1 is returned.
591  */
592 int getIndex(const std::string &aName,int aStartIndex=0) const
593 {
594     if(aStartIndex<0) aStartIndex=0;
595     if(aStartIndex>=getSize()) aStartIndex=0;
596 
597     // SEARCH STARTING FROM aStartIndex
598     int i;
599     for(i=aStartIndex;i<getSize();i++) {
600         if(_array[i]->getName() == aName) return(i);
601     }
602 
603     // SEARCH FROM BEGINNING
604     for(i=0;i<aStartIndex;i++) {
605         if(_array[i]->getName() == aName) return(i);
606     }
607 
608     return(-1);
609 }
610 
611 //-----------------------------------------------------------------------------
612 // APPEND
613 //-----------------------------------------------------------------------------
614 //_____________________________________________________________________________
615 /**
616  * Append to the array.  A copy of the specified object is NOT made.
617  *
618  * @param aObject Object to be appended.
619  * @return True if the append was successful, false otherwise.
620  */
append(T * aObject)621 bool append(T *aObject)
622 {
623     if(aObject==NULL) {
624         std::cout<<"ArrayPtrs.append: ERR- NULL pointer."<<std::endl;
625         return(false);
626     }
627 
628     // ENSURE CAPACITY
629     if((_size+1)>=_capacity) {
630         int newCapacity;
631         bool success;
632         success = computeNewCapacity(_size+1,newCapacity);
633         if(!success) return(success);
634         success = ensureCapacity(newCapacity);
635         if(!success) return(success);
636     }
637 
638     // SET
639     _array[_size] = aObject;
640     _size++;
641 
642     return(true);
643 }
644 //_____________________________________________________________________________
645 /**
646  * Append an array of objects.  Copies of the objects are NOT made
647  *
648  * @param aArray Array of objects to be appended.
649  * @return True if the append was successful, false otherwise.
650  */
append(ArrayPtrs<T> & aArray)651 bool append(ArrayPtrs<T> &aArray)
652 {
653     // LOOP THROUGH THE ELEMENTS
654     bool success;
655     int i,n=aArray.getSize();
656     for(i=0;i<n;i++) {
657         success = append(aArray[i]);
658         if(!success) return(success);
659     }
660 
661     return(true);
662 }
663 
664 //-----------------------------------------------------------------------------
665 // INSERT
666 //-----------------------------------------------------------------------------
667 //_____________________________________________________________________________
668 /**
669  * Insert an object into the array at a specified index.  A copy of the
670  * specified object is NOT made.
671  *
672  * This method is relatively computationally costly since many of the array
673  * elements may need to be shifted.
674  *
675  * @param aObject Object to be inserted.
676  * @param aIndex Index at which to insert the new object.  All current elements
677  * from aIndex to the end of the array are shifted one place in the direction
678  * of the end of the array.  The specified index must be less than or
679  * equal to the size of the array.  Note that if aIndex is equal to the
680  * size of the array, the insertion is equivalent to an append.
681  * @return True if the insertion was successful, false otherwise.
682  */
insert(int aIndex,T * aObject)683 bool insert(int aIndex,T *aObject)
684 {
685     // NULL POINTER
686     if(aObject==NULL) {
687         std::cout<<"ArrayPtrs.insert: ERR- NULL pointer."<<std::endl;
688         return(false);
689     }
690 
691     // NEGATIVE INDEX
692     if(aIndex<0) {
693         std::cout << "ArrayPtrs.insert: ERR- aIndex was less than 0.\n";
694         return(false);
695     }
696 
697     // INDEX PAST END OF ARRAY
698     if(aIndex>_size) {
699         return(false);
700     }
701 
702     // ENSURE CAPACITY
703     if((_size+1)>=_capacity) {
704         int newCapacity;
705         bool success;
706         success = computeNewCapacity(_size+1,newCapacity);
707         if(!success) return(success);
708         success = ensureCapacity(newCapacity);
709         if(!success) return(success);
710     }
711 
712     // SHIFT ARRAY
713     int i;
714     for(i=_size;i>aIndex;i--) {
715         _array[i] = _array[i-1];
716     }
717 
718     // SET
719     _array[aIndex] = aObject;
720     _size++;
721 
722     return(true);
723 }
724 
725 //-----------------------------------------------------------------------------
726 // REMOVE
727 //-----------------------------------------------------------------------------
728 //_____________________________________________________________________________
729 /**
730  * Remove an object from the array at a specified index.
731  * The object is deleted when it is removed.
732  *
733  * This method is relatively computationally costly since many of the array
734  * elements may need to be shifted.
735  *
736  * @param aIndex Index of the value to remove.  All elements from aIndex to
737  * the end of the array are shifted one place toward the beginning of
738  * the array.  If aIndex is less than 0 or greater than or equal to the
739  * current size of the array, no element is removed.
740  * @return True if the removal was successful, false otherwise.
741  */
remove(int aIndex)742 bool remove(int aIndex)
743 {
744     if(aIndex<0) {
745         return(false);
746     }
747     if(aIndex>=_size) {
748         return(false);
749     }
750 
751     // DELETE CURRENT OBJECT
752     if(getMemoryOwner()&&(_array[aIndex]!=NULL)) delete _array[aIndex];
753 
754     // SHIFT ARRAY
755     int i;
756     _size--;
757     for(i=aIndex;i<_size;i++) {
758         _array[i] = _array[i+1];
759     }
760     _array[_size] = NULL;
761 
762     return(true);
763 }
764 //_____________________________________________________________________________
765 /**
766  * Remove an object from the array by specifying its address.
767  * If this array is set as the memory owner, the object is deleted when it
768  * is removed.
769  *
770  * This method is relatively computationally costly since many of the array
771  * elements may need to be shifted.
772  *
773  * @param aObject Pointer to the object to be removed.  If an object with the
774  * specified address is not found, no action is taken.
775  * @return True if the removal was successful, false otherwise.
776  */
remove(ConstT * aObject)777 bool remove(ConstT* aObject)
778 {
779     int index = getIndex(aObject);
780     return( remove(index) );
781 }
782 
783 
784 //-----------------------------------------------------------------------------
785 // SET AND GET
786 //-----------------------------------------------------------------------------
787 //_____________________________________________________________________________
788 /**
789  * %Set the object at a specified index.  A copy of the object is NOT made.
790  *
791  * If the set method is successful and the array is set as the memory
792  * owner, the previous object stored at the specified index is deleted.
793  *
794  * @param aIndex Index of the array element to be set.  aIndex must be
795  * greater than zero and less than or equal to the size of the array.  Note
796  * that if aIndex is equal to the size of the array, the set is equivalent
797  * to an append.
798  * @param aObject Object to be set.
799  * @return True if the set was successful, false otherwise.
800  * @see setMemoryOwner()
801  */
set(int aIndex,T * aObject)802 bool set(int aIndex,T *aObject)
803 {
804     if(aIndex<0) return(false);
805     if(aIndex>_size) return(false);
806 
807     // APPEND
808     if(aIndex==_size) {
809         bool success;
810         success = append(aObject);
811         return(success);
812     }
813 
814     // SET
815     if(getMemoryOwner() && (_array[aIndex]!=NULL)) delete _array[aIndex];
816     _array[aIndex] = aObject;
817 
818     return(true);
819 }
820 //_____________________________________________________________________________
821 /**
822  * Get the object at a specified array index.
823  *
824  * If the index is negative or passed the end of the array, an exception
825  * is thrown.
826  *
827  * For faster execution, the array elements can be accessed through the
828  * overloaded operator[], which does no bounds checking.
829  *
830  * @param aIndex Array index of the desired object.
831  * @return Pointer to the desired object.
832  * @throws Exception if (aIndex<0)||(aIndex>=_size) or if the pointer
833  * at aIndex is NULL.
834  * @see operator[].
835  */
get(int aIndex)836 T* get(int aIndex)
837 {
838     if((aIndex<0)||(aIndex>=_size)) {
839         throw(Exception("ArrayPtrs.get: Array index out of bounds."));
840     }
841     if(_array[aIndex]==NULL) {
842         throw(Exception("ArrayPtrs.get: NULL pointer.",
843             __FILE__,__LINE__));
844     }
845 
846     return(_array[aIndex]);
847 }
848 //_____________________________________________________________________________
849 /**
850  * Get the object at a specified array index.
851  *
852  * If the index is negative or passed the end of the array, an exception
853  * is thrown.
854  *
855  * For faster execution, the array elements can be accessed through the
856  * overloaded operator[], which does no bounds checking.
857  *
858  * @param aIndex Array index of the desired object.
859  * @return Pointer to the desired object.
860  * @throws Exception if (aIndex<0)||(aIndex>=_size) or if the pointer
861  * at aIndex is NULL.
862  * @see operator[].
863  */
864 #ifndef SWIG
get(int aIndex)865 const T* get(int aIndex) const
866 {
867     if((aIndex<0)||(aIndex>=_size)) {
868         throw(Exception("ArrayPtrs.get: Array index out of bounds."));
869     }
870     if(_array[aIndex]==NULL) {
871         throw(Exception("ArrayPtrs.get: NULL pointer.",
872             __FILE__,__LINE__));
873     }
874 
875     return(_array[aIndex]);
876 }
877 #endif
878 //_____________________________________________________________________________
879 /**
880  * Get the first object that has a specified name.
881  *
882  * If the array doesn't contain an object of the specified name, an
883  * exception is thrown.
884  *
885  * @param aName Name of the desired object.
886  * @return Pointer to the object.
887  * @throws Exception if no such object exists.
888  * @see getIndex()
889  */
get(const std::string & aName)890 T* get(const std::string &aName)
891 {
892     int index = getIndex(aName);
893     if(index==-1) {
894         std::string msg = "ArrayPtrs.get(aName): No object with name ";
895         msg += aName;
896         throw( Exception(msg,__FILE__,__LINE__) );
897     }
898     return(_array[index]);
899 }
900 //_____________________________________________________________________________
901 /**
902  * Get the first object that has a specified name.
903  *
904  * If the array doesn't contain an object of the specified name, an
905  * exception is thrown.
906  *
907  * @param aName Name of the desired object.
908  * @return Pointer to the object.
909  * @throws Exception if no such object exists.
910  * @see getIndex()
911  */
912 #ifndef SWIG
get(const std::string & aName)913 const T* get(const std::string &aName) const
914 {
915     int index = getIndex(aName);
916     if(index==-1) {
917         std::string msg = "ArrayPtrs.get(aName): No object with name ";
918         msg += aName;
919         throw( Exception(msg,__FILE__,__LINE__) );
920     }
921     return(_array[index]);
922 }
923 #endif
924 //_____________________________________________________________________________
925 /**
926  * Get the last value in the array.
927  *
928  * @return Last value in the array.
929  * @throws Exception if the array is empty.
930  */
getLast()931 T* getLast() const
932 {
933     if(_size<=0) {
934         throw(Exception("Array is empty."));
935     }
936     return(_array[_size-1]);
937 }
938 
939 
940 //=============================================================================
941 // SEARCH
942 //=============================================================================
943 //_____________________________________________________________________________
944 /**
945  * Search for the largest value in the array that is less than or
946  * equal to a specified value.  If there is more than one element with this
947  * largest value, the index of the first of these elements can optionally be
948  * found, but this can be up to twice as costly.
949  *
950  * This method assumes that the array element values monotonically
951  * increase as the array index increases.  Note that monotonically
952  * increase means never decrease, so it is permissible for adjacent elements
953  * to have the same value.
954  *
955  * A binary search is performed (i.e., the array is repeatedly subdivided
956  * into two bins one of which must contain the specified until the
957  * appropriate element is identified), so the performance of this method
958  * is approximately ln(n), where n is the size of the array.
959  *
960  * @param aValue Value to which the array elements are compared.
961  * @param aFindFirst If true, find the first element that satisfies
962  * the search.  If false, the index of any element that satisfies the
963  * search can be returned- which index will be returned depends on the
964  * length of the array and is therefore somewhat arbitrary. By default,
965  * this flag is false.
966  * @param aLo Lowest array index to consider in the search.
967  * @param aHi Highest array index to consider in the search.
968  * @return Index of the array element that has the largest value that is less
969  * than or equal to aValue.  If there is more than one such elements with the
970  * same value and aFindFirst is set to true, the index of the first of
971  * these elements is returned.  If an error is encountered (e.g., the array
972  * is empty), or the array contains no element that is less than or equal
973  * to aValue, -1 is returned.
974  */
975 int searchBinary(ConstT& aObject,bool aFindFirst=false,
976                       int aLo=-1,int aHi=-1) const
977 {
978     if(_size<=0) return(-1);
979     int lo = aLo;  if(lo<0) lo = 0;
980     int hi = aHi;  if((hi<0)||(hi>=_size)) hi = _size - 1;
981     int mid = -1;
982 
983     // CHECK lo AND hi
984     if(lo>hi) return(-1);
985 
986     // SEARCH
987     while(lo <= hi) {
988         mid = (lo + hi) / 2;
989         if(aObject < *_array[mid]) {
990             hi = mid - 1;
991         } else if(*_array[mid] < aObject) {
992             lo = mid + 1;
993         } else {
994             break;
995         }
996     }
997 
998     // MAKE SURE LESS THAN
999     if(aObject < *_array[mid]) mid--;
1000     if(mid<=0) {
1001         return(mid);
1002     }
1003 
1004     // FIND FIRST
1005     if(aFindFirst) {
1006         if(*_array[mid-1]<*_array[mid]) {
1007             return(mid);
1008         }
1009         lo = aLo;  if(lo<0) lo = 0;
1010         hi = mid;
1011         int mid2 = mid;
1012         T *obj2 = _array[mid];
1013         while(lo <= hi) {
1014             mid2 = (lo + hi) / 2;
1015             if(*_array[mid2] == *obj2) {
1016                 hi = mid2 - 1;
1017             } else if(*_array[mid2] < *obj2) {
1018                 lo = mid2 + 1;
1019             }
1020         }
1021         if(*_array[mid2] < *obj2) mid2++;
1022         if(mid2<mid) mid = mid2;
1023     }
1024 
1025     return(mid);
1026 }
1027 
1028 //=============================================================================
1029 };  // END of class ArrayPtrs
1030 
1031 }; //namespace
1032 //=============================================================================
1033 //=============================================================================
1034 
1035 
1036 #endif //__ArrayPtrs_h__
1037