Home | History | Annotate | Download | only in include
      1 /*
      2     Copyright 2010 Google Inc.
      3 
      4     Licensed under the Apache License, Version 2.0 (the "License");
      5     you may not use this file except in compliance with the License.
      6     You may obtain a copy of the License at
      7 
      8          http://www.apache.org/licenses/LICENSE-2.0
      9 
     10     Unless required by applicable law or agreed to in writing, software
     11     distributed under the License is distributed on an "AS IS" BASIS,
     12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13     See the License for the specific language governing permissions and
     14     limitations under the License.
     15  */
     16 
     17 
     18 #ifndef GrTArray_DEFINED
     19 #define GrTArray_DEFINED
     20 
     21 #include <new>
     22 #include "GrTypes.h"
     23 #include "GrTemplates.h"
     24 
     25 // DATA_TYPE indicates that T has a trivial cons, destructor
     26 // and can be shallow-copied
     27 template <typename T, bool DATA_TYPE = false> class GrTArray {
     28 public:
     29     GrTArray() {
     30         fCount = 0;
     31         fReserveCount = MIN_ALLOC_COUNT;
     32         fAllocCount = 0;
     33         fMemArray = NULL;
     34         fPreAllocMemArray = NULL;
     35     }
     36 
     37     explicit GrTArray(int reserveCount) {
     38         GrAssert(reserveCount >= 0);
     39         fCount = 0;
     40         fReserveCount = reserveCount > MIN_ALLOC_COUNT ? reserveCount :
     41                                                          MIN_ALLOC_COUNT;
     42         fAllocCount = fReserveCount;
     43         fMemArray = GrMalloc(sizeof(T) * fReserveCount);
     44         fPreAllocMemArray = NULL;
     45     }
     46 
     47     template <int N>
     48     GrTArray(GrAlignedSTStorage<N,T>* storage) {
     49         GrAssert(N > 0);
     50         fCount              = 0;
     51         fReserveCount       = N;
     52         fAllocCount         = N;
     53         fMemArray           = storage->get();
     54         fPreAllocMemArray   = storage->get();
     55     }
     56 
     57     GrTArray(void* preAllocStorage, int preAllocCount) {
     58         GrAssert(preAllocCount >= 0);
     59         // we allow NULL,0 args and revert to the default cons. behavior
     60         // this makes it possible for a owner-object to use same constructor
     61         // to get either prealloc or nonprealloc behavior based using same line
     62         GrAssert((NULL == preAllocStorage) == !preAllocCount);
     63 
     64         fCount              = 0;
     65         fReserveCount       = preAllocCount > 0 ? preAllocCount :
     66                                                   MIN_ALLOC_COUNT;
     67         fAllocCount         = preAllocCount;
     68         fMemArray           = preAllocStorage;
     69         fPreAllocMemArray   = preAllocStorage;
     70     }
     71 
     72     explicit GrTArray(const GrTArray& array) {
     73         fCount              = array.count();
     74         fReserveCount       = MIN_ALLOC_COUNT;
     75         fAllocCount         = GrMax(fReserveCount, fCount);
     76         fMemArray           = GrMalloc(sizeof(T) * fAllocCount);
     77         fPreAllocMemArray   = NULL;
     78 
     79         if (DATA_TYPE) {
     80             memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
     81         } else {
     82             for (int i = 0; i < fCount; ++i) {
     83                 new (fItemArray + i) T(array[i]);
     84             }
     85         }
     86     }
     87 
     88     GrTArray(const T* array, int count) {
     89         GrAssert(count >= 0);
     90         fCount              = count;
     91         fReserveCount       = MIN_ALLOC_COUNT;
     92         fAllocCount         = GrMax(fReserveCount, fCount);
     93         fMemArray           = GrMalloc(sizeof(T) * fAllocCount);
     94         fPreAllocMemArray   = NULL;
     95         if (DATA_TYPE) {
     96             memcpy(fMemArray, array, sizeof(T) * fCount);
     97         } else {
     98             for (int i = 0; i < fCount; ++i) {
     99                 new (fItemArray + i) T(array[i]);
    100             }
    101         }
    102     }
    103 
    104     GrTArray(const GrTArray& array,
    105              void* preAllocStorage, int preAllocCount) {
    106 
    107         GrAssert(preAllocCount >= 0);
    108 
    109         // for same reason as non-copying cons we allow NULL, 0 for prealloc
    110         GrAssert((NULL == preAllocStorage) == !preAllocCount);
    111 
    112         fCount              = array.count();
    113         fReserveCount       = preAllocCount > 0 ? preAllocCount :
    114                                                   MIN_ALLOC_COUNT;
    115         fPreAllocMemArray   = preAllocStorage;
    116 
    117         if (fReserveCount >= fCount && preAllocCount) {
    118             fAllocCount = fReserveCount;
    119             fMemArray = preAllocStorage;
    120         } else {
    121             fAllocCount = GrMax(fCount, fReserveCount);
    122             fMemArray = GrMalloc(fAllocCount * sizeof(T));
    123         }
    124 
    125         if (DATA_TYPE) {
    126             memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
    127         } else {
    128             for (int i = 0; i < fCount; ++i) {
    129                 new (fItemArray + i) T(array[i]);
    130             }
    131         }
    132     }
    133 
    134     GrTArray(const T* array, int count,
    135              void* preAllocStorage, int preAllocCount) {
    136 
    137         GrAssert(count >= 0);
    138         GrAssert(preAllocCount >= 0);
    139 
    140         // for same reason as non-copying cons we allow NULL, 0 for prealloc
    141         GrAssert((NULL == preAllocStorage) == !preAllocCount);
    142 
    143         fCount              = count;
    144         fReserveCount       = (preAllocCount > 0) ? preAllocCount :
    145                                                     MIN_ALLOC_COUNT;
    146         fPreAllocMemArray   = preAllocStorage;
    147 
    148         if (fReserveCount >= fCount && preAllocCount) {
    149             fAllocCount = fReserveCount;
    150             fMemArray = preAllocStorage;
    151         } else {
    152             fAllocCount = GrMax(fCount, fReserveCount);
    153             fMemArray = GrMalloc(fAllocCount * sizeof(T));
    154         }
    155 
    156         if (DATA_TYPE) {
    157             memcpy(fMemArray, array, sizeof(T) * fCount);
    158         } else {
    159             for (int i = 0; i < fCount; ++i) {
    160                 new (fItemArray + i) T(array[i]);
    161             }
    162         }
    163     }
    164 
    165     GrTArray& operator =(const GrTArray& array) {
    166         for (int i = 0; i < fCount; ++i) {
    167             fItemArray[i].~T();
    168         }
    169         fCount = 0;
    170         checkRealloc((int)array.count());
    171         fCount = array.count();
    172         if (DATA_TYPE) {
    173             memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
    174         } else {
    175             for (int i = 0; i < fCount; ++i) {
    176                 new (fItemArray + i) T(array[i]);
    177             }
    178         }
    179         return *this;
    180     }
    181 
    182     ~GrTArray() {
    183         for (int i = 0; i < fCount; ++i) {
    184             fItemArray[i].~T();
    185         }
    186         if (fMemArray != fPreAllocMemArray) {
    187             GrFree(fMemArray);
    188         }
    189     }
    190 
    191     void reset() { this->pop_back_n(fCount); }
    192 
    193     int count() const { return fCount; }
    194 
    195     bool empty() const { return !fCount; }
    196 
    197     T& push_back() {
    198         checkRealloc(1);
    199         new ((char*)fMemArray+sizeof(T)*fCount) T;
    200         ++fCount;
    201         return fItemArray[fCount-1];
    202     }
    203 
    204     void push_back_n(int n) {
    205         GrAssert(n >= 0);
    206         checkRealloc(n);
    207         for (int i = 0; i < n; ++i) {
    208             new (fItemArray + fCount + i) T;
    209         }
    210         fCount += n;
    211     }
    212 
    213     void pop_back() {
    214         GrAssert(fCount > 0);
    215         --fCount;
    216         fItemArray[fCount].~T();
    217         checkRealloc(0);
    218     }
    219 
    220     void pop_back_n(int n) {
    221         GrAssert(n >= 0);
    222         GrAssert(fCount >= n);
    223         fCount -= n;
    224         for (int i = 0; i < n; ++i) {
    225             fItemArray[i].~T();
    226         }
    227         checkRealloc(0);
    228     }
    229 
    230     // pushes or pops from the back to resize
    231     void resize_back(int newCount) {
    232         GrAssert(newCount >= 0);
    233 
    234         if (newCount > fCount) {
    235             push_back_n(newCount - fCount);
    236         } else if (newCount < fCount) {
    237             pop_back_n(fCount - newCount);
    238         }
    239     }
    240 
    241     T& operator[] (int i) {
    242         GrAssert(i < fCount);
    243         GrAssert(i >= 0);
    244         return fItemArray[i];
    245     }
    246 
    247     const T& operator[] (int i) const {
    248         GrAssert(i < fCount);
    249         GrAssert(i >= 0);
    250         return fItemArray[i];
    251     }
    252 
    253     T& front() { GrAssert(fCount > 0); return fItemArray[0];}
    254 
    255     const T& front() const { GrAssert(fCount > 0); return fItemArray[0];}
    256 
    257     T& back() { GrAssert(fCount); return fItemArray[fCount - 1];}
    258 
    259     const T& back() const { GrAssert(fCount > 0); return fItemArray[fCount - 1];}
    260 
    261     T& fromBack(int i) {
    262         GrAssert(i >= 0);
    263         GrAssert(i < fCount);
    264         return fItemArray[fCount - i - 1];
    265     }
    266 
    267     const T& fromBack(int i) const {
    268         GrAssert(i >= 0);
    269         GrAssert(i < fCount);
    270         return fItemArray[fCount - i - 1];
    271     }
    272 
    273 private:
    274 
    275     static const int MIN_ALLOC_COUNT = 8;
    276 
    277     inline void checkRealloc(int delta) {
    278         GrAssert(fCount >= 0);
    279         GrAssert(fAllocCount >= 0);
    280 
    281         GrAssert(-delta <= fCount);
    282 
    283         int newCount = fCount + delta;
    284         int fNewAllocCount = fAllocCount;
    285 
    286         if (newCount > fAllocCount) {
    287             fNewAllocCount = GrMax(newCount + ((newCount + 1) >> 1),
    288                                    fReserveCount);
    289         } else if (newCount < fAllocCount / 3) {
    290             fNewAllocCount = GrMax(fAllocCount / 2, fReserveCount);
    291         }
    292 
    293         if (fNewAllocCount != fAllocCount) {
    294 
    295             fAllocCount = fNewAllocCount;
    296             char* fNewMemArray;
    297 
    298             if (fAllocCount == fReserveCount && NULL != fPreAllocMemArray) {
    299                 fNewMemArray = (char*) fPreAllocMemArray;
    300             } else {
    301                 fNewMemArray = (char*) GrMalloc(fAllocCount*sizeof(T));
    302             }
    303 
    304             if (DATA_TYPE) {
    305                 memcpy(fNewMemArray, fMemArray, fCount * sizeof(T));
    306             } else {
    307                 for (int i = 0; i < fCount; ++i) {
    308                     new (fNewMemArray + sizeof(T) * i) T(fItemArray[i]);
    309                     fItemArray[i].~T();
    310                 }
    311             }
    312 
    313             if (fMemArray != fPreAllocMemArray) {
    314                 GrFree(fMemArray);
    315             }
    316             fMemArray = fNewMemArray;
    317         }
    318     }
    319 
    320     int fReserveCount;
    321     int fCount;
    322     int fAllocCount;
    323     void*    fPreAllocMemArray;
    324     union {
    325         T*       fItemArray;
    326         void*    fMemArray;
    327     };
    328 };
    329 
    330 #endif
    331 
    332