src/Vector.h
author David Anderson <dvander@alliedmods.net>
Sat Nov 17 20:03:57 2012 -0800 (2012-11-17)
changeset 204 ff89b2640fba
parent 195 c1ba166f3fc4
child 251 ca99a81745fe
permissions -rw-r--r--
Added missing tests.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of SourcePawn.
     6  *
     7  * SourcePawn is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * SourcePawn. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #ifndef _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_
    20 #define _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_
    21 
    22 #include <new>
    23 #include <stdlib.h>
    24 #include "AllocatorPolicies.h"
    25 #include "Utility.h"
    26 
    27 namespace ke {
    28 
    29 template <typename T, typename AllocPolicy = ZoneAllocatorPolicy>
    30 class Vector : public AllocPolicy
    31 {
    32   public:
    33     Vector(AllocPolicy = AllocPolicy())
    34       : data(NULL),
    35         nitems(0),
    36         maxsize(0)
    37     { }
    38     ~Vector() {
    39         for (size_t i = 0; i < nitems; i++)
    40             data[i].~T();
    41         this->free(data);
    42     }
    43     bool append(const T& item) {
    44         if (!GrowIfNeeded(1))
    45             return false;
    46         new (&data[nitems]) T(item);
    47         nitems++;
    48         return true;
    49     }
    50     void infallibleAppend(const T &item) {
    51         assert(GrowIfNeeded(1));
    52         new (&data[nitems]) T(item);
    53         nitems++;
    54     }
    55     T popCopy() {
    56         T t = at(length() - 1);
    57         pop();
    58         return t;
    59     }
    60     void pop() {
    61         assert(nitems);
    62         data[nitems - 1].~T();
    63         nitems--;
    64     }
    65     bool empty() const {
    66         return length() == 0;
    67     }
    68     size_t length() const {
    69         return nitems;
    70     }
    71     T& at(size_t i) {
    72         assert(i < length());
    73         return data[i];
    74     }
    75     const T& at(size_t i) const {
    76         assert(i < length());
    77         return data[i];
    78     }
    79     T& operator [](size_t i) {
    80         return at(i);
    81     }
    82     const T& operator [](size_t i) const {
    83         return at(i);
    84     }
    85     void clear() {
    86         nitems = 0;
    87     }
    88 
    89     T *buffer() const {
    90         return data;
    91     }
    92 
    93     bool ensure(size_t desired) {
    94         if (desired <= length())
    95             return true;
    96 
    97         return GrowIfNeeded(desired - length());
    98     }
    99 
   100   private:
   101     bool GrowIfNeeded(size_t needed)
   102     {
   103         if (!IsUintPtrAddSafe(nitems, needed)) {
   104             this->reportAllocationOverflow();
   105             return false;
   106         }
   107         if (maxsize == 0)
   108             maxsize = 8;
   109         while (nitems + needed > maxsize)
   110         {
   111             if (!IsUintPtrMultiplySafe(maxsize, 2)) {
   112                 this->reportAllocationOverflow();
   113                 return false;
   114             }
   115             maxsize *= 2;
   116         }
   117         T* newdata = (T*)this->malloc(sizeof(T) * maxsize);
   118         if (newdata == NULL)
   119             return false;
   120         for (size_t i = 0; i < nitems; i++)
   121         {
   122             new (&newdata[i]) T(data[i]);
   123             data[i].~T();
   124         }
   125         this->free(data);
   126         data = newdata;
   127         return true;
   128     }
   129 
   130   private:
   131     T* data;
   132     size_t nitems;
   133     size_t maxsize;
   134 };
   135 
   136 }
   137 
   138 #endif /* _INCLUDE_KEIMA_TPL_CPP_VECTOR_H_ */
   139