StableArray.h
Go to the documentation of this file.00001 #ifndef SimTK_SimTKCOMMON_STABLEARRAY_H_
00002 #define SimTK_SimTKCOMMON_STABLEARRAY_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "SimTKcommon/internal/common.h"
00036 #include "SimTKcommon/internal/Array.h"
00037
00038 #include <cstddef>
00039 #include <cassert>
00040
00041 namespace SimTK {
00042
00062 template <class T> class StableArray {
00063 public:
00064 StableArray() : nOccupiedSlots(0) { }
00065
00066
00067 explicit StableArray(size_t z, const T& ival=T()) : stuff(z), nOccupiedSlots(z) {
00068 for (size_t i=0; i<z; ++i) stuff[i] = new T(ival);
00069 }
00070
00071
00072 StableArray(const StableArray& s) : stuff(s.size(),0), nOccupiedSlots(0) {
00073 for (size_t i=0; i<s.size(); ++i)
00074 if (!s.empty(i)) initializeEmptyElement(i, s[i]);
00075 assert(nItems() == s.nItems());
00076 }
00077
00078
00079 StableArray& operator=(const StableArray& s) {
00080 clear();
00081 stuff.resize(s.size(),0);
00082 for (size_t i=0; i<s.size(); ++i)
00083 if (!s.empty(i)) initializeEmptyElement(i, s[i]);
00084 assert(nItems() == s.nItems());
00085 return *this;
00086 }
00087
00088 ~StableArray() { clear(); }
00089
00090 bool empty() const { return stuff.size()==0; }
00091 bool empty(size_t i) const {
00092 assert(i < stuff.size());
00093 return stuff[i] == 0;
00094 }
00095 size_t size() const {return stuff.size();}
00096 size_t nItems() const {return nOccupiedSlots;}
00097
00098
00099
00100
00101
00102 void resize(size_t newz, const T& ival=T()) {
00103 const size_t oldz = stuff.size();
00104
00105 for (size_t i=newz; i < oldz; ++i)
00106 eraseElementIfNecessary(i);
00107 stuff.resize(newz,0);
00108
00109 for (size_t i=0; i < newz; ++i)
00110 initializeElementIfNecessary(i,ival);
00111 assert(nItems() == newz);
00112 }
00113
00114 void clear() {
00115 for (size_t i=0; i < stuff.size(); ++i)
00116 eraseElementIfNecessary(i);
00117 stuff.resize(0);
00118 assert(nItems()==0);
00119 }
00120
00121
00122
00123 void push_back(const T& t) {
00124 stuff.push_back(new T(t));
00125 ++nOccupiedSlots;
00126 }
00127
00128
00129
00130
00131
00132 void pop_back() {
00133 assert(!empty() && stuff.back());
00134 eraseOccupiedElement(stuff.size()-1);
00135
00136
00137 do { stuff.pop_back(); } while (!stuff.empty() && !stuff.back());
00138 }
00139
00140 void insertAt(size_t i, const T& t) {
00141 assert(i <= stuff.size());
00142 if (i == size()) push_back(t);
00143 else initializeEmptyElement(i,t);
00144 }
00145
00146 size_t findFreeSlot() const {
00147 if (nItems() == size())
00148 return size();
00149 for (size_t i=0; i<size(); ++i)
00150 if (empty(i)) return i;
00151 assert(false);
00152 return size_t(-1);
00153 }
00154
00155
00156
00157
00158
00159 size_t findNextItem(size_t i) {
00160 assert(i < stuff.size());
00161 for (; i < stuff.size() && !stuff[i]; ++i);
00162 return i;
00163 }
00164
00165
00166
00167
00168 size_t insert(const T& t) {
00169 const size_t free = findFreeSlot();
00170 insertAt(free, t);
00171 return free;
00172 }
00173
00174
00175
00176
00177
00178
00179
00180 void erase(size_t i) {
00181 if (i == stuff.size()-1) pop_back();
00182 else eraseElementIfNecessary(i);
00183 }
00184
00185
00186 const T& front() const {
00187 const size_t firstItem = findNextItem(0);
00188 assert(firstItem < stuff.size());
00189 return *stuff[firstItem];
00190 }
00191 T& front() {
00192 const size_t firstItem = findNextItem(0);
00193 assert(firstItem < stuff.size());
00194 return *stuff[firstItem];
00195 }
00196
00197
00198
00199 const T& back() const {assert(!empty() && stuff.back()); return *stuff.back();}
00200 T& back() {assert(!empty() && stuff.back()); return *stuff.back();}
00201
00202 const T& operator[](size_t i) const {
00203 assert(i < stuff.size() && stuff[i]);
00204 return *stuff[i];
00205 }
00206 T& operator[](size_t i) {
00207 assert(i < stuff.size() && stuff[i]);
00208 return *stuff[i];
00209 }
00210
00211 private:
00212 size_t nOccupiedSlots;
00213 Array_<T*> stuff;
00214
00215
00216
00217
00218 void eraseOccupiedElement(size_t i) {
00219 assert(i < stuff.size() && stuff[i]);
00220 delete stuff[i]; stuff[i]=0; --nOccupiedSlots;
00221 }
00222
00223 void initializeEmptyElement(size_t i, const T& t) {
00224 assert(i < stuff.size() && !stuff[i]);
00225 stuff[i] = new T(t); ++nOccupiedSlots;
00226 }
00227
00228 void eraseElementIfNecessary(size_t i) {
00229 assert(i < stuff.size());
00230 if (stuff[i]) eraseOccupiedElement(i);
00231 }
00232
00233 void initializeElementIfNecessary(size_t i, const T& t) {
00234 assert(i < stuff.size());
00235 if (!stuff[i]) initializeEmptyElement(i,t);
00236 }
00237
00238 };
00239
00240 }
00241
00242 #endif // SimTK_SimTKCOMMON_STABLEARRAY_H_