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