~ubuntu-branches/ubuntu/karmic/pypy/karmic

« back to all changes in this revision

Viewing changes to pypy/rpython/rctypes/rarray.py

  • Committer: Bazaar Package Importer
  • Author(s): Alexandre Fayolle
  • Date: 2007-04-13 09:33:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070413093309-yoojh4jcoocu2krz
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from ctypes import ARRAY, c_int
 
2
from pypy.rpython.error import TyperError
 
3
from pypy.rpython.lltypesystem.rstr import string_repr, emptystr
 
4
from pypy.rpython.rmodel import IntegerRepr, inputconst
 
5
from pypy.rpython.rslice import AbstractSliceRepr
 
6
from pypy.rpython.lltypesystem import lltype
 
7
from pypy.annotation.pairtype import pairtype
 
8
from pypy.rpython.rctypes.rmodel import CTypesRefRepr, CTypesValueRepr
 
9
from pypy.rpython.rctypes.rmodel import genreccopy_arrayitem, reccopy, C_ZERO
 
10
from pypy.rpython.rctypes.rprimitive import PrimitiveRepr
 
11
from pypy.rpython.rctypes.rpointer import PointerRepr
 
12
from pypy.rpython.rctypes.aarray import VarSizedArrayType
 
13
from pypy.annotation.model import SomeCTypesObject
 
14
from pypy.objspace.flow.model import Constant
 
15
 
 
16
ArrayType = type(ARRAY(c_int, 10))
 
17
 
 
18
 
 
19
class ArrayRepr(CTypesRefRepr):
 
20
    def __init__(self, rtyper, s_array):
 
21
        array_ctype = s_array.knowntype
 
22
        
 
23
        item_ctype = array_ctype._type_
 
24
        if isinstance(array_ctype, VarSizedArrayType):
 
25
            self.length = None
 
26
        else:
 
27
            self.length = array_ctype._length_
 
28
        
 
29
        # Find the repr and low-level type of items from their ctype
 
30
        self.r_item = rtyper.getrepr(SomeCTypesObject(item_ctype,
 
31
                                                      ownsmemory=False))
 
32
 
 
33
        # Here, self.c_data_type == self.ll_type
 
34
        if self.length is not None:
 
35
            c_data_type = lltype.FixedSizeArray(self.r_item.ll_type,
 
36
                                                self.length)
 
37
        else:
 
38
            c_data_type = lltype.Array(self.r_item.ll_type,
 
39
                                       hints={'nolength': True})
 
40
 
 
41
        super(ArrayRepr, self).__init__(rtyper, s_array, c_data_type)
 
42
 
 
43
    def get_content_keepalive_type(self):
 
44
        "An extra array of keepalives, one per item."
 
45
        item_keepalive_type = self.r_item.get_content_keepalive_type()
 
46
        if not item_keepalive_type:
 
47
            return None
 
48
        elif self.length is not None:
 
49
            return lltype.FixedSizeArray(item_keepalive_type, self.length)
 
50
        else:
 
51
            raise NotImplementedError("XXX not supported yet: "
 
52
                                      "var-sized arrays of pointers")
 
53
 
 
54
    def initialize_const(self, p, value):
 
55
        for i in range(self.length):
 
56
            llitem = self.r_item.convert_const(value[i])
 
57
            if isinstance(self.r_item, CTypesRefRepr):
 
58
                # ByRef case
 
59
                reccopy(llitem.c_data, p.c_data[i])
 
60
            else:
 
61
                # ByValue case
 
62
                p.c_data[i] = llitem.c_data[0]
 
63
 
 
64
    def rtype_getattr(self, hop):
 
65
        s_attr = hop.args_s[1]
 
66
        assert s_attr.is_constant()
 
67
        assert s_attr.const == 'value'
 
68
        assert self.r_item.ll_type == lltype.Char  # .value: char arrays only
 
69
        hop.exception_cannot_occur()
 
70
        if self.length == 0:
 
71
            return hop.inputconst(lltype.typeOf(emptystr), emptystr)
 
72
        else:
 
73
            v_box = hop.inputarg(self, 0)
 
74
            return hop.gendirectcall(ll_chararrayvalue, v_box)
 
75
 
 
76
    def get_c_data_of_item(self, llops, v_array, v_index):
 
77
        v_c_array = self.get_c_data(llops, v_array)
 
78
        if isinstance(self.r_item, CTypesRefRepr):
 
79
            # ByRef case
 
80
            return llops.genop('getarraysubstruct', [v_c_array, v_index],
 
81
                               lltype.Ptr(self.r_item.c_data_type))
 
82
        else:
 
83
            # ByValue case
 
84
            P = lltype.Ptr(lltype.FixedSizeArray(self.r_item.ll_type, 1))
 
85
            v_items = llops.genop('direct_arrayitems', [v_c_array],
 
86
                                  resulttype = P)
 
87
            if isinstance(v_index, Constant) and v_index.value == 0:
 
88
                pass   # skip direct_ptradd
 
89
            else:
 
90
                v_items = llops.genop('direct_ptradd', [v_items, v_index],
 
91
                                      resulttype = P)
 
92
            return v_items
 
93
 
 
94
    def get_item_value(self, llops, v_array, v_index):
 
95
        # ByValue case only
 
96
        assert isinstance(self.r_item, CTypesValueRepr)
 
97
        v_c_array = self.get_c_data(llops, v_array)
 
98
        return llops.genop('getarrayitem', [v_c_array, v_index],
 
99
                           resulttype = self.r_item.ll_type)
 
100
 
 
101
##    def set_item_value(self, llops, v_array, v_index, v_newvalue):
 
102
##        # ByValue case only
 
103
##        assert isinstance(self.r_item, CTypesValueRepr)
 
104
##        v_c_array = self.get_c_data(llops, v_array)
 
105
##        llops.genop('setarrayitem', [v_c_array, v_index, v_newvalue])
 
106
 
 
107
    def setitem(self, llops, v_array, v_index, v_item):
 
108
        v_newvalue = self.r_item.get_c_data_or_value(llops, v_item)
 
109
        # copy the new value (which might be a whole structure)
 
110
        v_c_array = self.get_c_data(llops, v_array)
 
111
        genreccopy_arrayitem(llops, v_newvalue, v_c_array, v_index)
 
112
        # copy the keepalive information too
 
113
        v_keepalive_array = self.getkeepalive(llops, v_array)
 
114
        if v_keepalive_array is not None:
 
115
            v_newkeepalive = self.r_item.getkeepalive(llops, v_item)
 
116
            genreccopy_arrayitem(llops, v_newkeepalive,
 
117
                                 v_keepalive_array, v_index)
 
118
 
 
119
    def initializeitems(self, llops, v_array, items_v):
 
120
        for i, v_item in enumerate(items_v):
 
121
            c_index = inputconst(lltype.Signed, i)
 
122
            self.setitem(llops, v_array, c_index, v_item)
 
123
 
 
124
 
 
125
class __extend__(pairtype(ArrayRepr, IntegerRepr)):
 
126
    def rtype_getitem((r_array, r_int), hop):
 
127
        v_array, v_index = hop.inputargs(r_array, lltype.Signed)
 
128
        hop.exception_cannot_occur()
 
129
        if isinstance(r_array.r_item, PrimitiveRepr):
 
130
            # primitive case (optimization; the below also works in this case)
 
131
            # NB. this optimization is invalid for PointerReprs!  See for
 
132
            # example:  a[0].contents = ...  to change the first pointer of
 
133
            # an array of pointers.
 
134
            v_value = r_array.get_item_value(hop.llops, v_array, v_index)
 
135
            return r_array.r_item.return_value(hop.llops, v_value)
 
136
        else:
 
137
            # ByRef case
 
138
            v_c_data = r_array.get_c_data_of_item(hop.llops, v_array, v_index)
 
139
            return r_array.r_item.return_c_data(hop.llops, v_c_data)
 
140
 
 
141
    def rtype_setitem((r_array, r_int), hop):
 
142
        v_array, v_index, v_item = hop.inputargs(r_array, lltype.Signed,
 
143
                                                 r_array.r_item)
 
144
        hop.exception_cannot_occur()
 
145
        r_array.setitem(hop.llops, v_array, v_index, v_item)
 
146
 
 
147
 
 
148
class __extend__(pairtype(ArrayRepr, AbstractSliceRepr)):
 
149
    def rtype_getitem((r_array, r_slic), hop):
 
150
        rs = hop.rtyper.type_system.rslice
 
151
        hop.exception_cannot_occur()
 
152
        if r_slic == rs.startstop_slice_repr:
 
153
            # slicing: char array only
 
154
            assert r_array.r_item.ll_type == lltype.Char
 
155
            if r_array.length == 0:
 
156
                return hop.inputconst(lltype.typeOf(emptystr), emptystr)
 
157
            v_array, v_slice = hop.inputargs(r_array, rs.startstop_slice_repr)
 
158
            return hop.gendirectcall(ll_chararrayslice, v_array, v_slice)
 
159
        raise TyperError('getitem does not support slices with %r' % (r_slic,))
 
160
 
 
161
 
 
162
class __extend__(pairtype(ArrayRepr, PointerRepr)):
 
163
    def convert_from_to((r_from, r_to), v, llops):
 
164
        # XXX keepalives
 
165
        r_temp = r_to.r_memoryowner
 
166
        v_owned_box = r_temp.allocate_instance(llops)
 
167
        v_c_array = r_from.get_c_data_of_item(llops, v, C_ZERO)
 
168
        r_temp.setvalue(llops, v_owned_box, v_c_array)
 
169
        return llops.convertvar(v_owned_box, r_temp, r_to)
 
170
 
 
171
 
 
172
def ll_chararrayvalue(box):
 
173
    from pypy.rpython.rctypes import rchar_p
 
174
    p = box.c_data
 
175
    length = rchar_p.ll_strnlen(lltype.direct_arrayitems(p), len(p))
 
176
    newstr = lltype.malloc(string_repr.lowleveltype.TO, length)
 
177
    newstr.hash = 0
 
178
    for i in range(length):
 
179
        newstr.chars[i] = p[i]
 
180
    return newstr
 
181
 
 
182
def ll_chararrayslice(box, slice):
 
183
    from pypy.rpython.rctypes import rchar_p
 
184
    p = box.c_data
 
185
    start = slice.start
 
186
    stop = slice.stop
 
187
    length = stop - start
 
188
    assert length >= 0
 
189
    newstr = lltype.malloc(string_repr.lowleveltype.TO, length)
 
190
    newstr.hash = 0
 
191
    for i in range(length):
 
192
        newstr.chars[i] = p[start+i]
 
193
    return newstr