pypy / pypy / module / _cffi_backend /

Full commit

from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.gateway import interp2app
from pypy.interpreter.typedef import TypeDef
from pypy.rpython.lltypesystem import rffi
from pypy.rlib.objectmodel import keepalive_until_here
from pypy.rlib.rarithmetic import ovfcheck

from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveChar
from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveUniChar
from pypy.module._cffi_backend.ctypeptr import W_CTypePtrOrArray
from pypy.module._cffi_backend import cdataobj

class W_CTypeArray(W_CTypePtrOrArray):
    _attrs_            = ['ctptr']
    _immutable_fields_ = ['ctptr']

    def __init__(self, space, ctptr, length, arraysize, extra):
        W_CTypePtrOrArray.__init__(self, space, arraysize, extra, 0,
        self.length = length
        self.ctptr = ctptr

    def _alignof(self):
        return self.ctitem.alignof()

    def newp(self, w_init):
        space =
        datasize = self.size
        if datasize < 0:
            if (space.isinstance_w(w_init, space.w_list) or
                space.isinstance_w(w_init, space.w_tuple)):
                length = space.int_w(space.len(w_init))
            elif space.isinstance_w(w_init, space.w_basestring):
                # from a string, we add the null terminator
                length = space.int_w(space.len(w_init)) + 1
                length = space.getindex_w(w_init, space.w_OverflowError)
                if length < 0:
                    raise OperationError(space.w_ValueError,
                                         space.wrap("negative array length"))
                w_init = space.w_None
                datasize = ovfcheck(length * self.ctitem.size)
            except OverflowError:
                raise OperationError(space.w_OverflowError,
                    space.wrap("array size would overflow a ssize_t"))
            cdata = cdataobj.W_CDataNewOwningLength(space, datasize,
                                                    self, length)
            cdata = cdataobj.W_CDataNewOwning(space, datasize, self)
        if not space.is_w(w_init, space.w_None):
            self.convert_from_object(cdata._cdata, w_init)
        return cdata

    def _check_subscript_index(self, w_cdata, i):
        space =
        if i < 0:
            raise OperationError(space.w_IndexError,
                                 space.wrap("negative index not supported"))
        if i >= w_cdata.get_array_length():
            raise operationerrfmt(space.w_IndexError,
                "index too large for cdata '%s' (expected %d < %d)",
      , i, w_cdata.get_array_length())
        return self

    def convert_from_object(self, cdata, w_ob):
        self.convert_array_from_object(cdata, w_ob)

    def convert_to_object(self, cdata):
        if self.length < 0:
            # we can't return a <cdata 'int[]'> here, because we don't
            # know the length to give it.  As a compromize, returns
            # <cdata 'int *'> in this case.
            self = self.ctptr
        return cdataobj.W_CData(, cdata, self)

    def add(self, cdata, i):
        p = rffi.ptradd(cdata, i * self.ctitem.size)
        return cdataobj.W_CData(, p, self.ctptr)

    def iter(self, cdata):
        return W_CDataIter(, self.ctitem, cdata)

    def get_vararg_type(self):
        return self.ctptr

class W_CDataIter(Wrappable):
    _immutable_fields_ = ['ctitem', 'cdata', '_stop']    # but not '_next'

    def __init__(self, space, ctitem, cdata): = space
        self.ctitem = ctitem
        self.cdata = cdata
        length = cdata.get_array_length()
        self._next = cdata._cdata
        self._stop = rffi.ptradd(cdata._cdata, length * ctitem.size)

    def iter_w(self):

    def next_w(self):
        result = self._next
        if result == self._stop:
            raise OperationError(,
        self._next = rffi.ptradd(result, self.ctitem.size)
        return self.ctitem.convert_to_object(result)

W_CDataIter.typedef = TypeDef(
    __module__ = '_cffi_backend',
    __iter__ = interp2app(W_CDataIter.iter_w),
    next = interp2app(W_CDataIter.next_w),
W_CDataIter.typedef.acceptable_as_base_class = False