src/List.h
author Asher Baker <asherkin@gmail.com>
Mon Jun 10 15:52:44 2013 +0100 (2013-06-10)
changeset 265 3a903b89a514
parent 251 ca99a81745fe
permissions -rw-r--r--
Fixed type checking for multidimensional arrays.
     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_sp2_list_h_
    20 #define _include_sp2_list_h_
    21 
    22 #include "Objects.h"
    23 #include "FixedArray.h"
    24 #include "Zone.h"
    25 #include "Heap-inl.h"
    26 #include "Handles-inl.h"
    27 
    28 namespace ke {
    29 
    30 template <typename T>
    31 class List : public Object
    32 {
    33   public:
    34     static List *New(Zone *zone, Heap::Tenure tenure = Heap::Tenure_Default) {
    35         Local<List> list(zone, List::cast(zone->allocate(MapKind_List, sizeof(List), tenure)));
    36         if (!list)
    37             return NULL;
    38 
    39         list->length_ = 0;
    40         list->array_ = NULL;
    41 
    42         return list;
    43     }
    44 
    45     bool append(Zone *zone, Handle<T> obj) {
    46         Local<List> list(zone, this);
    47         if (!Grow(zone, list, 1))
    48             return false;
    49 
    50         list->array_->set(zone, list->length_, obj);
    51         list->length_++;
    52         return true;
    53     }
    54 
    55     T *at(unsigned i) {
    56         return T::cast(array_->at(i));
    57     }
    58 
    59     unsigned length() {
    60         return length_;
    61     }
    62 
    63   private:
    64     static bool Grow(Zone *zone, Handle<List> list, unsigned amount) {
    65         if (!IsUint32AddSafe(list->length(), amount)) {
    66             zone->reportAllocationOverflow();
    67             return false;
    68         }
    69 
    70         unsigned newlen = list->length() + amount;
    71         if (list->array_ && newlen < list->array_->length())
    72             return true;
    73 
    74         unsigned maxsize = list->array_ ? list->array_->length() : 8;
    75         if (!IsUint32AddSafe(maxsize, amount)) {
    76             zone->reportAllocationOverflow();
    77             return false;
    78         }
    79 
    80         while (newlen > maxsize) {
    81             if (!IsUint32MultiplySafe(maxsize, 2)) {
    82                 zone->reportAllocationOverflow();
    83                 return false;
    84             }
    85             maxsize *= 2;
    86         }
    87 
    88         Local<FixedArray> array(zone, FixedArray::New(zone, maxsize, Heap::Tenure_Default));
    89         if (!array)
    90             return false;
    91 
    92         for (unsigned i = 0; i < list->length_; i++)
    93             array->set(zone, i, list->array_->at(i));
    94 
    95         list->array_ = array;
    96         return true;
    97     }
    98 
    99   public:
   100 
   101     // Begin GC descriptor.
   102     static inline size_t offsetOfArray() {
   103         return OFFSETOF(List, array_);
   104     }
   105     // End GC descriptor.
   106 
   107     static inline List *cast(Object *obj) {
   108         assert(!obj || obj->is(MapKind_List));
   109         return reinterpret_cast<List *>(obj);
   110     }
   111 
   112   private:
   113     unsigned length_;
   114     FixedArray *array_;
   115 };
   116 
   117 } // namespace ke
   118 
   119 #endif // _include_sp2_list_h_