src/Array.cpp
author David Anderson <dvander@alliedmods.net>
Sun Aug 05 00:31:20 2012 -0700 (2012-08-05)
changeset 154 a85a0303bcb8
parent 91 5f4402180204
child 169 0456a16c2a63
permissions -rw-r--r--
Refactory array maps to allow arrays of structs.
     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 #include <string.h>
    20 #include "Array.h"
    21 #include "Heap.h"
    22 #include "Zone.h"
    23 #include "Structures.h"
    24 #include "Heap-inl.h"
    25 
    26 using namespace ke;
    27 
    28 ArrayMap *
    29 ArrayMap::New(Zone *zone, Handle<Type> type)
    30 {
    31     Local<Map> obj(zone, zone->allocateMap(MapKind_Array, sizeof(ArrayMap), MapKind_MetaArray));
    32     if (!obj)
    33         return NULL;
    34 
    35     Local<ArrayMap> map(zone, ArrayMap::cast(obj));
    36     map->type_ = type;
    37     return map;
    38 }
    39 
    40 static inline size_t
    41 SizeFor(Type *type, unsigned elements)
    42 {
    43     if (type->contained()->isTraceable())
    44         return sizeof(Array) + elements * sizeof(ke::Object *);
    45     if (type->contained()->isInt32())
    46         return sizeof(Array) + elements * sizeof(int);
    47     if (type->contained()->primitive() == PrimitiveType_Char)
    48         return sizeof(Array) + elements * sizeof(char);
    49     assert(type->contained()->isFloat());
    50     return elements * sizeof(float);
    51 }
    52 
    53 Array *
    54 Array::New(Zone *zone, Handle<ArrayMap> map, uint32 elements, Heap::Tenure tenure)
    55 {
    56     size_t elementBytes = SizeFor(map->type(), elements);
    57     size_t bytes = sizeof(Array) + elementBytes;
    58     Local<Array> array(zone, Array::cast(zone->allocate(map, bytes, tenure)));
    59     if (!array)
    60         return NULL;
    61 
    62     array->nelements_ = elements;
    63     array->elements_ = (Array *)array + 1;
    64 
    65     if (map->type()->contained()->isArray()) {
    66         Local<ArrayMap> childMap(zone, ArrayMap::cast(map->type()->contained()->newMap()));
    67         Local<Array> child(zone);
    68         for (unsigned i = 0; i < elements; i++) {
    69             child = Array::New(zone, childMap, map->type()->contained()->elements(), tenure);
    70             if (!child)
    71                 return NULL;
    72 
    73             array->writeObject(zone, i, child);
    74         }
    75     } else if (map->type()->contained()->isStruct()) {
    76         Local<StructMap> childMap(zone, StructMap::cast(map->type()->contained()->newMap()));
    77         Local<Struct> child(zone);
    78         for (unsigned i = 0; i < elements; i++) {
    79             child = Struct::New(zone, childMap, tenure);
    80             if (!child)
    81                 return NULL;
    82 
    83             array->writeObject(zone, i, child);
    84         }
    85     } else {
    86         memset(array->elements_, 0, elementBytes);
    87     }
    88     return array;
    89 }
    90 
    91 Array *
    92 Array::NewExternal(Zone *zone, Handle<ArrayMap> map, uint32 nelements, void *buffer,
    93                    Heap::Tenure tenure)
    94 {
    95     Local<Array> array(zone, Array::cast(zone->allocate(map, sizeof(Array), tenure)));
    96     if (!array)
    97         return NULL;
    98 
    99     array->nelements_ = nelements;
   100     array->elements_ = buffer;
   101     return array;
   102 }
   103