00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef XRD_CLIIDXVEC_H
00020 #define XRD_CLIIDXVEC_H
00021
00022 #include <stdlib.h>
00023 #include <string.h>
00024
00025 #include "XrdSys/XrdSysHeaders.hh"
00026
00027
00028 #define IDXVEC_MINCAPACITY 128
00029
00030 template<class T>
00031 class XrdClientVector {
00032
00033
00034 private:
00035
00036
00037 int sizeof_t;
00038
00039 char *rawdata;
00040
00041 struct myindex {
00042 long offs;
00043 bool notempty;
00044 } *index;
00045
00046
00047
00048 int holecount;
00049
00050 long size, mincap;
00051 long capacity, maxsize;
00052
00053
00054
00055
00056 int BufRealloc(int newsize);
00057
00058 inline void Init(int cap = -1) {
00059 if (rawdata) free(rawdata);
00060 if (index) free(index);
00061
00062 mincap = (cap > 0) ? cap : IDXVEC_MINCAPACITY;
00063
00064 rawdata = static_cast<char *>(malloc(mincap * sizeof_t));
00065
00066 index = static_cast<myindex *>(malloc(mincap * sizeof(myindex)));
00067
00068 if (!rawdata || !index) {
00069 std::cerr << "XrdClientIdxVector::Init .... out of memory. sizeof_t=" << sizeof_t <<
00070 " sizeof(myindex)=" << sizeof(myindex) << " capacity=" << mincap << std::endl;
00071 abort();
00072 }
00073
00074
00075 memset(index, 0, mincap * sizeof(myindex));
00076
00077 holecount = 0;
00078
00079 size = 0;
00080 maxsize = capacity = mincap;
00081 }
00082
00083
00084
00085
00086 void DestroyElem(myindex *el) {
00087 reinterpret_cast<T*>(rawdata+el->offs)->~T();
00088
00089 }
00090
00091 void put(T& item, long pos) {
00092
00093
00094
00095 if (size+holecount >= capacity) {
00096 std::cerr << "XrdClientIdxVector::put .... internal error." << std::endl;
00097 abort();
00098 }
00099
00100 T *p;
00101 long offs = (size+holecount)*sizeof_t;
00102
00103 if (index[pos].notempty) {
00104 offs = index[pos].offs;
00105
00106
00107 holecount--;
00108 }
00109
00110 p = new(rawdata + offs) T(item);
00111
00112 if (p) {
00113 index[pos].offs = offs;
00114 index[pos].notempty = true;
00115 }
00116 else {
00117 std::cerr << "XrdClientIdxVector::put .... out of memory." << std::endl;
00118 abort();
00119 }
00120
00121 }
00122
00123 public:
00124
00125 inline int GetSize() const { return size; }
00126
00127 void Clear() {
00128 for (long i = 0; i < size; i++)
00129 if (index[i].notempty) DestroyElem(&index[i]);
00130
00131 Init(mincap);
00132 }
00133
00134 XrdClientVector(int cap = -1):
00135 sizeof_t(0), rawdata(0), index(0)
00136 {
00137
00138 sizeof_t = (sizeof(T) + 3) >> 2 << 2;
00139 Init(cap);
00140 }
00141
00142 XrdClientVector(XrdClientVector &v):
00143 rawdata(0), index(0) {
00144
00145 sizeof_t = (sizeof(T) + 3) >> 2 << 2;
00146
00147 Init(v.capacity);
00148 BufRealloc(v.size);
00149
00150 for (int i = 0; i < v.size; i++)
00151 Push_back( v[i] );
00152 }
00153
00154 ~XrdClientVector() {
00155 for (long i = 0; i < size; i++)
00156 if (index[i].notempty) DestroyElem(&index[i]);
00157
00158 if (rawdata) free(rawdata);
00159 if (index) free(index);
00160 }
00161
00162 void Resize(int newsize) {
00163 long oldsize = size;
00164
00165 if (newsize > oldsize) {
00166 BufRealloc(newsize);
00167 T *item = new T;
00168
00169 for (long i = oldsize; i < newsize; i++) {
00170 put(*item, size++);
00171 }
00172 }
00173 else {
00174 for (long i = oldsize; i > newsize; i--)
00175 Erase(i-1, false);
00176 }
00177 }
00178
00179 void Push_back(T& item) {
00180
00181 if ( BufRealloc(size+1) )
00182 put(item, size++);
00183
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 void Insert(T& item, int pos) {
00207
00208 if (pos >= size) {
00209 Push_back(item);
00210 return;
00211 }
00212
00213 if ( BufRealloc(size+1) ) {
00214
00215 if (holecount > 0) {
00216 struct myindex tmpi = index[size];
00217 memmove(&index[pos+1], &index[pos], (size-pos) * sizeof(myindex));
00218 index[pos] = tmpi;
00219 } else {
00220 memmove(&index[pos+1], &index[pos], (size-pos) * sizeof(myindex));
00221 index[pos].notempty = false;
00222 }
00223
00224 size++;
00225 put(item, pos);
00226 }
00227
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 void Erase(unsigned int pos, bool dontrealloc=true) {
00249
00250 DestroyElem(index + pos);
00251
00252 struct myindex tmpi = index[pos];
00253 holecount++;
00254
00255 memmove(&index[pos], &index[pos+1], (size-pos-1) * sizeof(myindex));
00256
00257 size--;
00258 index[size] = tmpi;
00259 if (!dontrealloc)
00260 BufRealloc(size);
00261
00262 }
00263
00264 T Pop_back() {
00265 T r( At(size-1) );
00266
00267 DestroyElem(index+size-1);
00268
00269 holecount++;
00270 size--;
00271
00272
00273 return (r);
00274 }
00275
00276 T Pop_front() {
00277 T res;
00278
00279 res = At(0);
00280
00281 Erase(0);
00282 return (res);
00283 }
00284
00285
00286 inline T &At(int pos) {
00287
00288
00289
00290 return *( reinterpret_cast<T*>(rawdata + index[pos].offs));
00291 }
00292
00293 inline T &operator[] (int pos) {
00294 return At(pos);
00295 }
00296
00297 };
00298
00299
00300
00301
00302 template <class T>
00303 int XrdClientVector<T>::BufRealloc(int newsize) {
00304
00305
00306
00307 if ((size+holecount >= capacity-2) && (holecount > 4*size))
00308 while (size+holecount >= capacity-2) {
00309 long lastempty = size+holecount-1;
00310
00311
00312
00313
00314
00315
00316
00317 memmove(rawdata + index[lastempty].offs, rawdata + index[lastempty].offs + sizeof_t,
00318 (size+holecount)*sizeof_t - index[lastempty].offs );
00319
00320
00321 index[lastempty].notempty = false;
00322 holecount--;
00323
00324
00325 for (long i = 0; i < size+holecount; i++)
00326 if (index[i].notempty && (index[i].offs > index[lastempty].offs))
00327 index[i].offs -= sizeof_t;
00328
00329 }
00330
00331 if (newsize > maxsize) maxsize = newsize;
00332
00333 while (newsize+holecount > capacity*2/3) {
00334
00335
00336
00337 capacity *= 2;
00338
00339 rawdata = static_cast<char *>(realloc(rawdata, capacity*sizeof_t));
00340 if (!rawdata) {
00341 std::cerr << "XrdClientIdxVector::BufRealloc .... out of memory." << std::endl;
00342 abort();
00343 }
00344
00345 index = static_cast<myindex *>(realloc(index, capacity*sizeof(myindex)));
00346 memset(index+capacity/2, 0, capacity*sizeof(myindex)/2);
00347
00348 }
00349
00350 while ((newsize+holecount < capacity/3) && (capacity > 2*mincap)) {
00351
00352
00353
00354
00355 capacity /= 2;
00356
00357 rawdata = static_cast<char *>(realloc(rawdata, capacity*sizeof_t));
00358 if (!rawdata) {
00359 std::cerr << "XrdClientIdxVector::BufRealloc .... out of memory." << std::endl;
00360 abort();
00361 }
00362
00363 index = static_cast<myindex *>(realloc(index, capacity*sizeof(myindex)));
00364
00365 }
00366
00367 return 1;
00368
00369 }
00370
00371
00372 #endif