src/Array.cpp
author David Anderson <dvander@alliedmods.net>
Sat Aug 11 12:11:39 2012 -0700 (2012-08-11)
changeset 170 5e4570966ece
parent 169 0456a16c2a63
child 184 387d76b1e981
permissions -rw-r--r--
Parser support for public variables.
dvander@154
     1
/* vim: set ts=4 sw=4 tw=99 et:
dvander@154
     2
 *
dvander@12
     3
 * Copyright (C) 2012 David Anderson
dvander@12
     4
 *
dvander@154
     5
 * This file is part of SourcePawn.
dvander@12
     6
 *
dvander@154
     7
 * SourcePawn is free software: you can redistribute it and/or modify it under
dvander@12
     8
 * the terms of the GNU General Public License as published by the Free
dvander@12
     9
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@12
    10
 * any later version.
dvander@12
    11
 * 
dvander@154
    12
 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@12
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@12
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@12
    15
 *
dvander@12
    16
 * You should have received a copy of the GNU General Public License along with
dvander@154
    17
 * SourcePawn. If not, see http://www.gnu.org/licenses/.
dvander@12
    18
 */
danderson@91
    19
#include <string.h>
dvander@12
    20
#include "Array.h"
dvander@12
    21
#include "Heap.h"
dvander@12
    22
#include "Zone.h"
dvander@154
    23
#include "Structures.h"
dvander@12
    24
#include "Heap-inl.h"
dvander@12
    25
dvander@59
    26
using namespace ke;
dvander@12
    27
dvander@12
    28
ArrayMap *
dvander@154
    29
ArrayMap::New(Zone *zone, Handle<Type> type)
dvander@12
    30
{
dvander@31
    31
    Local<Map> obj(zone, zone->allocateMap(MapKind_Array, sizeof(ArrayMap), MapKind_MetaArray));
dvander@12
    32
    if (!obj)
dvander@12
    33
        return NULL;
dvander@12
    34
dvander@31
    35
    Local<ArrayMap> map(zone, ArrayMap::cast(obj));
dvander@13
    36
    map->type_ = type;
dvander@12
    37
    return map;
dvander@12
    38
}
dvander@12
    39
dvander@169
    40
ArrayMap *
dvander@169
    41
ArrayMap::Attach(Zone *zone, Handle<Type> type)
dvander@169
    42
{
dvander@169
    43
    if (type->newMap())
dvander@169
    44
        return ArrayMap::cast(type->newMap());
dvander@169
    45
dvander@169
    46
    Local<ArrayMap> map(zone, ArrayMap::New(zone, type));
dvander@169
    47
    if (!map)
dvander@169
    48
        return NULL;
dvander@169
    49
dvander@169
    50
    // Ensure the inner type has an ArrayMap if needed.
dvander@169
    51
    if (type->contained()->isArray()) {
dvander@169
    52
        Local<Type> contained(zone, type->contained());
dvander@169
    53
        if (!ArrayMap::Attach(zone, contained))
dvander@169
    54
            return NULL;
dvander@169
    55
    }
dvander@169
    56
dvander@169
    57
    type->setNewMap(map);
dvander@169
    58
    return map;
dvander@169
    59
}
dvander@169
    60
dvander@12
    61
static inline size_t
dvander@12
    62
SizeFor(Type *type, unsigned elements)
dvander@12
    63
{
dvander@154
    64
    if (type->contained()->isTraceable())
dvander@59
    65
        return sizeof(Array) + elements * sizeof(ke::Object *);
dvander@20
    66
    if (type->contained()->isInt32())
dvander@12
    67
        return sizeof(Array) + elements * sizeof(int);
dvander@21
    68
    if (type->contained()->primitive() == PrimitiveType_Char)
dvander@21
    69
        return sizeof(Array) + elements * sizeof(char);
dvander@12
    70
    assert(type->contained()->isFloat());
dvander@53
    71
    return elements * sizeof(float);
dvander@12
    72
}
dvander@12
    73
dvander@12
    74
Array *
dvander@27
    75
Array::New(Zone *zone, Handle<ArrayMap> map, uint32 elements, Heap::Tenure tenure)
dvander@12
    76
{
dvander@53
    77
    size_t elementBytes = SizeFor(map->type(), elements);
dvander@53
    78
    size_t bytes = sizeof(Array) + elementBytes;
dvander@31
    79
    Local<Array> array(zone, Array::cast(zone->allocate(map, bytes, tenure)));
dvander@31
    80
    if (!array)
dvander@12
    81
        return NULL;
dvander@12
    82
dvander@13
    83
    array->nelements_ = elements;
dvander@66
    84
    array->elements_ = (Array *)array + 1;
dvander@154
    85
dvander@154
    86
    if (map->type()->contained()->isArray()) {
dvander@154
    87
        Local<ArrayMap> childMap(zone, ArrayMap::cast(map->type()->contained()->newMap()));
dvander@154
    88
        Local<Array> child(zone);
dvander@154
    89
        for (unsigned i = 0; i < elements; i++) {
dvander@154
    90
            child = Array::New(zone, childMap, map->type()->contained()->elements(), tenure);
dvander@154
    91
            if (!child)
dvander@154
    92
                return NULL;
dvander@154
    93
dvander@154
    94
            array->writeObject(zone, i, child);
dvander@154
    95
        }
dvander@154
    96
    } else if (map->type()->contained()->isStruct()) {
dvander@154
    97
        Local<StructMap> childMap(zone, StructMap::cast(map->type()->contained()->newMap()));
dvander@154
    98
        Local<Struct> child(zone);
dvander@154
    99
        for (unsigned i = 0; i < elements; i++) {
dvander@154
   100
            child = Struct::New(zone, childMap, tenure);
dvander@154
   101
            if (!child)
dvander@154
   102
                return NULL;
dvander@154
   103
dvander@154
   104
            array->writeObject(zone, i, child);
dvander@154
   105
        }
dvander@154
   106
    } else {
dvander@154
   107
        memset(array->elements_, 0, elementBytes);
dvander@154
   108
    }
dvander@31
   109
    return array;
dvander@12
   110
}
dvander@31
   111
dvander@65
   112
Array *
dvander@169
   113
Array::NewString(Zone *zone, Handle<ArrayMap> map, Address buffer, size_t length, Heap::Tenure tenure)
dvander@169
   114
{
dvander@169
   115
    Local<Array> array(zone, Array::New(zone, map, length, tenure));
dvander@169
   116
    if (!array)
dvander@169
   117
        return NULL;
dvander@169
   118
dvander@169
   119
    assert(array->length() >= length);
dvander@169
   120
    memcpy(array->chars(), buffer, length);
dvander@169
   121
    return array;
dvander@169
   122
}
dvander@169
   123
dvander@169
   124
Array *
dvander@65
   125
Array::NewExternal(Zone *zone, Handle<ArrayMap> map, uint32 nelements, void *buffer,
dvander@65
   126
                   Heap::Tenure tenure)
dvander@65
   127
{
dvander@65
   128
    Local<Array> array(zone, Array::cast(zone->allocate(map, sizeof(Array), tenure)));
dvander@65
   129
    if (!array)
dvander@65
   130
        return NULL;
dvander@65
   131
dvander@65
   132
    array->nelements_ = nelements;
dvander@65
   133
    array->elements_ = buffer;
dvander@65
   134
    return array;
dvander@65
   135
}
dvander@154
   136