[pypy-commit] pypy ffi-backend: Refactoring: split ctypeobj.py.
arigo
noreply at buildbot.pypy.org
Tue Jun 26 16:57:08 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: ffi-backend
Changeset: r55833:953c16a08cfc
Date: 2012-06-26 16:56 +0200
http://bitbucket.org/pypy/pypy/changeset/953c16a08cfc/
Log: Refactoring: split ctypeobj.py.
diff --git a/pypy/module/_ffi_backend/cdataobj.py b/pypy/module/_ffi_backend/cdataobj.py
--- a/pypy/module/_ffi_backend/cdataobj.py
+++ b/pypy/module/_ffi_backend/cdataobj.py
@@ -15,9 +15,9 @@
cdata = lltype.nullptr(rffi.CCHARP.TO)
def __init__(self, space, cdata, ctype):
- from pypy.module._ffi_backend import ctypeobj
+ from pypy.module._ffi_backend import ctypeprim
assert lltype.typeOf(cdata) == rffi.CCHARP
- assert isinstance(ctype, ctypeobj.W_CType)
+ assert isinstance(ctype, ctypeprim.W_CType)
self.space = space
self._cdata = cdata # don't forget keepalive_until_here!
self.ctype = ctype
@@ -48,9 +48,9 @@
return w_result
def len(self):
- from pypy.module._ffi_backend import ctypeobj
+ from pypy.module._ffi_backend import ctypearray
space = self.space
- if isinstance(self.ctype, ctypeobj.W_CTypeArray):
+ if isinstance(self.ctype, ctypearray.W_CTypeArray):
return space.wrap(self.get_array_length())
raise operationerrfmt(space.w_TypeError,
"cdata of type '%s' has no len()",
@@ -110,13 +110,13 @@
space = self.space
ob = space.interpclass_w(w_other)
if isinstance(ob, W_CData):
- from pypy.module._ffi_backend import ctypeobj
+ from pypy.module._ffi_backend import ctypeptr, ctypearray
ct = ob.ctype
- if isinstance(ct, ctypeobj.W_CTypeArray):
+ if isinstance(ct, ctypearray.W_CTypeArray):
ct = ct.ctptr
#
if (ct is not self.ctype or
- not isinstance(ct, ctypeobj.W_CTypePointer) or
+ not isinstance(ct, ctypeptr.W_CTypePointer) or
ct.ctitem.size <= 0):
raise operationerrfmt(space.w_TypeError,
"cannot subtract cdata '%s' and cdata '%s'",
@@ -129,13 +129,13 @@
return self._add_or_sub(w_other, -1)
def getcfield(self, w_attr):
- from pypy.module._ffi_backend import ctypeobj
+ from pypy.module._ffi_backend import ctypeptr, ctypestruct
space = self.space
ctype = self.ctype
attr = space.str_w(w_attr)
- if isinstance(ctype, ctypeobj.W_CTypePointer):
+ if isinstance(ctype, ctypeptr.W_CTypePointer):
ctype = ctype.ctitem
- if (isinstance(ctype, ctypeobj.W_CTypeStructOrUnion) and
+ if (isinstance(ctype, ctypestruct.W_CTypeStructOrUnion) and
ctype.fields_dict is not None):
try:
return ctype.fields_dict[attr]
@@ -183,9 +183,9 @@
return w_obj
def get_array_length(self):
- from pypy.module._ffi_backend import ctypeobj
+ from pypy.module._ffi_backend import ctypearray
ctype = self.ctype
- assert isinstance(ctype, ctypeobj.W_CTypeArray)
+ assert isinstance(ctype, ctypearray.W_CTypeArray)
length = ctype.length
assert length >= 0
return length
diff --git a/pypy/module/_ffi_backend/ctypearray.py b/pypy/module/_ffi_backend/ctypearray.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi_backend/ctypearray.py
@@ -0,0 +1,116 @@
+"""
+Arrays.
+"""
+
+from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.rpython.lltypesystem import rffi
+from pypy.rlib.objectmodel import keepalive_until_here
+from pypy.rlib.rarithmetic import ovfcheck
+
+from pypy.module._ffi_backend.ctypeobj import W_CType
+from pypy.module._ffi_backend.ctypeprim import W_CTypePrimitiveChar
+from pypy.module._ffi_backend.ctypeptr import W_CTypePtrOrArray
+from pypy.module._ffi_backend import cdataobj
+
+
+class W_CTypeArray(W_CTypePtrOrArray):
+
+ def __init__(self, space, ctptr, length, arraysize, extra):
+ W_CTypePtrOrArray.__init__(self, space, arraysize, extra, 0,
+ ctptr.ctitem)
+ self.length = length
+ self.ctptr = ctptr
+
+ def str(self, cdataobj):
+ if isinstance(self.ctitem, W_CTypePrimitiveChar):
+ s = rffi.charp2strn(cdataobj._cdata, cdataobj.get_array_length())
+ keepalive_until_here(cdataobj)
+ return self.space.wrap(s)
+ return W_CTypePtrOrArray.str(self, cdataobj)
+
+ def _alignof(self):
+ return self.ctitem.alignof()
+
+ def newp(self, w_init):
+ space = self.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_str):
+ # from a string, we add the null terminator
+ length = space.int_w(space.len(w_init)) + 1
+ else:
+ 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
+ #
+ try:
+ 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_CDataOwnLength(space, datasize, self, length)
+ #
+ else:
+ cdata = cdataobj.W_CDataOwn(space, datasize, self)
+ #
+ if not space.is_w(w_init, space.w_None):
+ self.convert_from_object(cdata._cdata, w_init)
+ keepalive_until_here(cdata)
+ return cdata
+
+ def _check_subscript_index(self, w_cdata, i):
+ space = self.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)",
+ self.name, i, w_cdata.get_array_length())
+
+ def convert_from_object(self, cdata, w_ob):
+ space = self.space
+ if (space.isinstance_w(w_ob, space.w_list) or
+ space.isinstance_w(w_ob, space.w_tuple)):
+ lst_w = space.listview(w_ob)
+ if self.length >= 0 and len(lst_w) > self.length:
+ raise operationerrfmt(space.w_IndexError,
+ "too many initializers for '%s' (got %d)",
+ self.name, len(lst_w))
+ ctitem = self.ctitem
+ for i in range(len(lst_w)):
+ ctitem.convert_from_object(cdata, lst_w[i])
+ cdata = rffi.ptradd(cdata, ctitem.size)
+ elif isinstance(self.ctitem, W_CTypePrimitiveChar):
+ try:
+ s = space.str_w(w_ob)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ raise self._convert_error("str or list or tuple", w_ob)
+ n = len(s)
+ if self.length >= 0 and n > self.length:
+ raise operationerrfmt(space.w_IndexError,
+ "initializer string is too long for '%s'"
+ " (got %d characters)",
+ self.name, n)
+ for i in range(n):
+ cdata[i] = s[i]
+ if n != self.length:
+ cdata[n] = '\x00'
+ else:
+ raise self._convert_error("list or tuple", w_ob)
+
+ def convert_to_object(self, cdata):
+ return cdataobj.W_CData(self.space, cdata, self)
+
+ def add(self, cdata, i):
+ p = rffi.ptradd(cdata, i * self.ctitem.size)
+ return cdataobj.W_CData(self.space, p, self.ctptr)
diff --git a/pypy/module/_ffi_backend/ctypeenum.py b/pypy/module/_ffi_backend/ctypeenum.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi_backend/ctypeenum.py
@@ -0,0 +1,83 @@
+"""
+Enums.
+"""
+
+from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.rlib.objectmodel import keepalive_until_here
+
+from pypy.module._ffi_backend.ctypeprim import W_CTypePrimitiveSigned
+from pypy.module._ffi_backend import misc
+
+
+class W_CTypeEnum(W_CTypePrimitiveSigned):
+
+ def __init__(self, space, name, enumerators, enumvalues):
+ from pypy.module._ffi_backend.newtype import alignment
+ name = "enum " + name
+ size = rffi.sizeof(rffi.INT)
+ align = alignment(rffi.INT)
+ W_CTypePrimitiveSigned.__init__(self, space, size,
+ name, len(name), align)
+ self.enumerators2values = {} # str -> int
+ self.enumvalues2erators = {} # int -> str
+ for i in range(len(enumerators)):
+ self.enumerators2values[enumerators[i]] = enumvalues[i]
+ self.enumvalues2erators[enumvalues[i]] = enumerators[i]
+
+ def _getfields(self):
+ space = self.space
+ lst = []
+ for enumerator in self.enumerators2values:
+ enumvalue = self.enumerators2values[enumerator]
+ lst.append(space.newtuple([space.wrap(enumvalue),
+ space.wrap(enumerator)]))
+ w_lst = space.newlist(lst)
+ space.call_method(w_lst, 'sort')
+ return w_lst
+
+ def str(self, cdataobj):
+ w_res = self.convert_to_object(cdataobj._cdata)
+ keepalive_until_here(cdataobj)
+ return w_res
+
+ def convert_to_object(self, cdata):
+ value = intmask(misc.read_raw_signed_data(cdata, self.size))
+ try:
+ enumerator = self.enumvalues2erators[value]
+ except KeyError:
+ enumerator = '#%d' % (value,)
+ return self.space.wrap(enumerator)
+
+ def convert_from_object(self, cdata, w_ob):
+ space = self.space
+ try:
+ return W_CTypePrimitiveSigned.convert_from_object(self, cdata,
+ w_ob)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ if space.isinstance_w(w_ob, space.w_str):
+ value = self.convert_enum_string_to_int(space.str_w(w_ob))
+ misc.write_raw_integer_data(cdata, value, self.size)
+ else:
+ raise self._convert_error("str or int", w_ob)
+
+ def cast_str(self, w_ob):
+ space = self.space
+ return self.convert_enum_string_to_int(space.str_w(w_ob))
+
+ def convert_enum_string_to_int(self, s):
+ space = self.space
+ if s.startswith('#'):
+ try:
+ return int(s[1:]) # xxx is it RPython?
+ except ValueError:
+ raise OperationError(space.w_ValueError,
+ space.wrap("invalid literal after '#'"))
+ else:
+ try:
+ return self.enumerators2values[s]
+ except KeyError:
+ raise operationerrfmt(space.w_ValueError,
+ "'%s' is not an enumerator for %s",
+ s, self.name)
diff --git a/pypy/module/_ffi_backend/ctypeobj.py b/pypy/module/_ffi_backend/ctypeobj.py
--- a/pypy/module/_ffi_backend/ctypeobj.py
+++ b/pypy/module/_ffi_backend/ctypeobj.py
@@ -1,13 +1,12 @@
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.typedef import TypeDef, interp_attrproperty
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.typedef import make_weakref_descr
from pypy.rpython.lltypesystem import lltype, llmemory, rffi
-from pypy.rlib.rarithmetic import intmask, ovfcheck, r_ulonglong
-from pypy.rlib.objectmodel import keepalive_until_here, we_are_translated
+from pypy.rlib.objectmodel import we_are_translated
-from pypy.module._ffi_backend import cdataobj, misc
+from pypy.module._ffi_backend import cdataobj
class W_CType(Wrappable):
@@ -115,606 +114,9 @@
return None
-class W_CTypePtrOrArray(W_CType):
-
- def __init__(self, space, size, extra, extra_position, ctitem):
- name, name_position = ctitem.insert_name(extra, extra_position)
- W_CType.__init__(self, space, size, name, name_position)
- self.ctitem = ctitem
-
-
-class W_CTypePointer(W_CTypePtrOrArray):
-
- def __init__(self, space, ctitem):
- size = rffi.sizeof(rffi.VOIDP)
- if isinstance(ctitem, W_CTypeArray):
- extra = "(*)" # obscure case: see test_array_add
- else:
- extra = " *"
- W_CTypePtrOrArray.__init__(self, space, size, extra, 2, ctitem)
-
- def str(self, cdataobj):
- if isinstance(self.ctitem, W_CTypePrimitiveChar):
- if not cdataobj._cdata:
- space = self.space
- raise operationerrfmt(space.w_RuntimeError,
- "cannot use str() on %s",
- space.str_w(cdataobj.repr()))
- s = rffi.charp2str(cdataobj._cdata)
- keepalive_until_here(cdataobj)
- return self.space.wrap(s)
- return W_CTypePtrOrArray.str(self, cdataobj)
-
- def cast(self, w_ob):
- space = self.space
- ob = space.interpclass_w(w_ob)
- if (isinstance(ob, cdataobj.W_CData) and
- isinstance(ob.ctype, W_CTypePtrOrArray)):
- value = ob._cdata
- else:
- value = misc.as_unsigned_long_long(space, w_ob, strict=False)
- value = rffi.cast(rffi.CCHARP, value)
- return cdataobj.W_CData(space, value, self)
-
- def newp(self, w_init):
- space = self.space
- ctitem = self.ctitem
- datasize = ctitem.size
- if datasize < 0:
- raise operationerrfmt(space.w_TypeError,
- "cannot instantiate ctype '%s' of unknown size",
- self.name)
- if isinstance(ctitem, W_CTypePrimitiveChar):
- datasize *= 2 # forcefully add a null character
- cdata = cdataobj.W_CDataOwn(space, datasize, self)
- if not space.is_w(w_init, space.w_None):
- ctitem.convert_from_object(cdata._cdata, w_init)
- keepalive_until_here(cdata)
- return cdata
-
- def _check_subscript_index(self, w_cdata, i):
- if isinstance(w_cdata, cdataobj.W_CDataOwn) and i != 0:
- space = self.space
- raise operationerrfmt(space.w_IndexError,
- "cdata '%s' can only be indexed by 0",
- self.name)
-
- def add(self, cdata, i):
- space = self.space
- ctitem = self.ctitem
- if ctitem.size < 0:
- raise operationerrfmt(space.w_TypeError,
- "ctype '%s' points to items of unknown size",
- self.name)
- p = rffi.ptradd(cdata, i * self.ctitem.size)
- return cdataobj.W_CData(space, p, self)
-
- def _alignof(self):
- from pypy.module._ffi_backend import newtype
- return newtype.alignment_of_pointer
-
- def convert_to_object(self, cdata):
- ptrdata = rffi.cast(rffi.CCHARPP, cdata)[0]
- return cdataobj.W_CData(self.space, ptrdata, self)
-
- def convert_from_object(self, cdata, w_ob):
- space = self.space
- ob = space.interpclass_w(w_ob)
- if not isinstance(ob, cdataobj.W_CData):
- raise self._convert_error("compatible pointer", w_ob)
- otherctype = ob.ctype
- if (isinstance(otherctype, W_CTypePtrOrArray) and
- (self.ctitem.cast_anything or
- otherctype.ctitem.cast_anything or
- self.ctitem is otherctype.ctitem)):
- pass # compatible types
- else:
- raise self._convert_error("compatible pointer", w_ob)
-
- rffi.cast(rffi.CCHARPP, cdata)[0] = ob._cdata
-
-
-class W_CTypeArray(W_CTypePtrOrArray):
-
- def __init__(self, space, ctptr, length, arraysize, extra):
- W_CTypePtrOrArray.__init__(self, space, arraysize, extra, 0,
- ctptr.ctitem)
- self.length = length
- self.ctptr = ctptr
-
- def str(self, cdataobj):
- if isinstance(self.ctitem, W_CTypePrimitiveChar):
- s = rffi.charp2strn(cdataobj._cdata, cdataobj.get_array_length())
- keepalive_until_here(cdataobj)
- return self.space.wrap(s)
- return W_CTypePtrOrArray.str(self, cdataobj)
-
- def _alignof(self):
- return self.ctitem.alignof()
-
- def newp(self, w_init):
- space = self.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_str):
- # from a string, we add the null terminator
- length = space.int_w(space.len(w_init)) + 1
- else:
- 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
- #
- try:
- 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_CDataOwnLength(space, datasize, self, length)
- #
- else:
- cdata = cdataobj.W_CDataOwn(space, datasize, self)
- #
- if not space.is_w(w_init, space.w_None):
- self.convert_from_object(cdata._cdata, w_init)
- keepalive_until_here(cdata)
- return cdata
-
- def _check_subscript_index(self, w_cdata, i):
- space = self.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)",
- self.name, i, w_cdata.get_array_length())
-
- def convert_from_object(self, cdata, w_ob):
- space = self.space
- if (space.isinstance_w(w_ob, space.w_list) or
- space.isinstance_w(w_ob, space.w_tuple)):
- lst_w = space.listview(w_ob)
- if self.length >= 0 and len(lst_w) > self.length:
- raise operationerrfmt(space.w_IndexError,
- "too many initializers for '%s' (got %d)",
- self.name, len(lst_w))
- ctitem = self.ctitem
- for i in range(len(lst_w)):
- ctitem.convert_from_object(cdata, lst_w[i])
- cdata = rffi.ptradd(cdata, ctitem.size)
- elif isinstance(self.ctitem, W_CTypePrimitiveChar):
- try:
- s = space.str_w(w_ob)
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
- raise self._convert_error("str or list or tuple", w_ob)
- n = len(s)
- if self.length >= 0 and n > self.length:
- raise operationerrfmt(space.w_IndexError,
- "initializer string is too long for '%s'"
- " (got %d characters)",
- self.name, n)
- for i in range(n):
- cdata[i] = s[i]
- if n != self.length:
- cdata[n] = '\x00'
- else:
- raise self._convert_error("list or tuple", w_ob)
-
- def convert_to_object(self, cdata):
- return cdataobj.W_CData(self.space, cdata, self)
-
- def add(self, cdata, i):
- p = rffi.ptradd(cdata, i * self.ctitem.size)
- return cdataobj.W_CData(self.space, p, self.ctptr)
-
-
-class W_CTypePrimitive(W_CType):
-
- def __init__(self, space, size, name, name_position, align):
- W_CType.__init__(self, space, size, name, name_position)
- self.align = align
-
- def extra_repr(self, cdata):
- w_ob = self.convert_to_object(cdata)
- return self.space.str_w(self.space.repr(w_ob))
-
- def _alignof(self):
- return self.align
-
- def cast_str(self, w_ob):
- space = self.space
- s = space.str_w(w_ob)
- if len(s) != 1:
- raise operationerrfmt(space.w_TypeError,
- "cannot cast string of length %d to ctype '%s'",
- len(s), self.name)
- return ord(s[0])
-
- def cast(self, w_ob):
- space = self.space
- ob = space.interpclass_w(w_ob)
- if (isinstance(ob, cdataobj.W_CData) and
- isinstance(ob.ctype, W_CTypePtrOrArray)):
- value = rffi.cast(lltype.Signed, ob._cdata)
- elif space.isinstance_w(w_ob, space.w_str):
- value = self.cast_str(w_ob)
- else:
- value = misc.as_unsigned_long_long(space, w_ob, strict=False)
- w_cdata = cdataobj.W_CDataOwnFromCasted(space, self.size, self)
- w_cdata.write_raw_integer_data(value)
- return w_cdata
-
- def _overflow(self, w_ob):
- space = self.space
- s = space.str_w(space.str(w_ob))
- raise operationerrfmt(space.w_OverflowError,
- "integer %s does not fit '%s'", s, self.name)
-
-
-class W_CTypePrimitiveChar(W_CTypePrimitive):
- cast_anything = True
-
- def int(self, cdata):
- return self.space.wrap(ord(cdata[0]))
-
- def convert_to_object(self, cdata):
- return self.space.wrap(cdata[0])
-
- def str(self, cdataobj):
- w_res = self.convert_to_object(cdataobj._cdata)
- keepalive_until_here(cdataobj)
- return w_res
-
- def _convert_to_char(self, w_ob):
- space = self.space
- if space.isinstance_w(w_ob, space.w_str):
- s = space.str_w(w_ob)
- if len(s) == 1:
- return s[0]
- ob = space.interpclass_w(w_ob)
- if (isinstance(ob, cdataobj.W_CData) and
- isinstance(ob.ctype, W_CTypePrimitiveChar)):
- return ob._cdata[0]
- raise self._convert_error("string of length 1", w_ob)
-
- def convert_from_object(self, cdata, w_ob):
- value = self._convert_to_char(w_ob)
- cdata[0] = value
-
-
-class W_CTypePrimitiveSigned(W_CTypePrimitive):
-
- def __init__(self, *args):
- W_CTypePrimitive.__init__(self, *args)
- self.value_fits_long = self.size <= rffi.sizeof(lltype.Signed)
- if self.size < rffi.sizeof(lltype.SignedLongLong):
- sh = self.size * 8
- self.vmin = r_ulonglong(-1) << (sh - 1)
- self.vrangemax = (r_ulonglong(1) << sh) - 1
-
- def int(self, cdata):
- if self.value_fits_long:
- # this case is to handle enums, but also serves as a slight
- # performance improvement for some other primitive types
- value = intmask(misc.read_raw_signed_data(cdata, self.size))
- return self.space.wrap(value)
- else:
- return self.convert_to_object(cdata)
-
- def convert_to_object(self, cdata):
- value = misc.read_raw_signed_data(cdata, self.size)
- if self.value_fits_long:
- return self.space.wrap(intmask(value))
- else:
- return self.space.wrap(value) # r_longlong => on 32-bit, 'long'
-
- def convert_from_object(self, cdata, w_ob):
- value = misc.as_long_long(self.space, w_ob)
- if self.size < rffi.sizeof(lltype.SignedLongLong):
- if r_ulonglong(value) - self.vmin > self.vrangemax:
- self._overflow(w_ob)
- misc.write_raw_integer_data(cdata, value, self.size)
-
-
-class W_CTypePrimitiveUnsigned(W_CTypePrimitive):
-
- def __init__(self, *args):
- W_CTypePrimitive.__init__(self, *args)
- self.value_fits_long = self.size < rffi.sizeof(lltype.Signed)
- if self.size < rffi.sizeof(lltype.SignedLongLong):
- sh = self.size * 8
- self.vrangemax = (r_ulonglong(1) << sh) - 1
-
- def int(self, cdata):
- return self.convert_to_object(cdata)
-
- def convert_from_object(self, cdata, w_ob):
- value = misc.as_unsigned_long_long(self.space, w_ob, strict=True)
- if self.size < rffi.sizeof(lltype.SignedLongLong):
- if value > self.vrangemax:
- self._overflow(w_ob)
- misc.write_raw_integer_data(cdata, value, self.size)
-
- def convert_to_object(self, cdata):
- value = misc.read_raw_unsigned_data(cdata, self.size)
- if self.value_fits_long:
- return self.space.wrap(intmask(value))
- else:
- return self.space.wrap(value) # r_ulonglong => 'long' object
-
-
-class W_CTypePrimitiveFloat(W_CTypePrimitive):
-
- def cast(self, w_ob):
- space = self.space
- ob = space.interpclass_w(w_ob)
- if isinstance(ob, cdataobj.W_CData):
- if not isinstance(ob.ctype, W_CTypePrimitive):
- raise operationerrfmt(space.w_TypeError,
- "cannot cast ctype '%s' to ctype '%s'",
- ob.ctype.name, self.name)
- w_ob = ob.convert_to_object()
- #
- if space.isinstance_w(w_ob, space.w_str):
- value = self.cast_str(w_ob)
- else:
- value = space.float_w(w_ob)
- w_cdata = cdataobj.W_CDataOwnFromCasted(space, self.size, self)
- w_cdata.write_raw_float_data(value)
- return w_cdata
-
- def int(self, cdata):
- w_value = self.float(cdata)
- return self.space.int(w_value)
-
- def float(self, cdata):
- return self.convert_to_object(cdata)
-
- def convert_to_object(self, cdata):
- value = misc.read_raw_float_data(cdata, self.size)
- return self.space.wrap(value)
-
- def convert_from_object(self, cdata, w_ob):
- space = self.space
- value = space.float_w(space.float(w_ob))
- misc.write_raw_float_data(cdata, value, self.size)
-
-
-class W_CTypeEnum(W_CTypePrimitiveSigned):
-
- def __init__(self, space, name, enumerators, enumvalues):
- from pypy.module._ffi_backend.newtype import alignment
- name = "enum " + name
- size = rffi.sizeof(rffi.INT)
- align = alignment(rffi.INT)
- W_CTypePrimitiveSigned.__init__(self, space, size,
- name, len(name), align)
- self.enumerators2values = {} # str -> int
- self.enumvalues2erators = {} # int -> str
- for i in range(len(enumerators)):
- self.enumerators2values[enumerators[i]] = enumvalues[i]
- self.enumvalues2erators[enumvalues[i]] = enumerators[i]
-
- def _getfields(self):
- space = self.space
- lst = []
- for enumerator in self.enumerators2values:
- enumvalue = self.enumerators2values[enumerator]
- lst.append(space.newtuple([space.wrap(enumvalue),
- space.wrap(enumerator)]))
- w_lst = space.newlist(lst)
- space.call_method(w_lst, 'sort')
- return w_lst
-
- def str(self, cdataobj):
- w_res = self.convert_to_object(cdataobj._cdata)
- keepalive_until_here(cdataobj)
- return w_res
-
- def convert_to_object(self, cdata):
- value = intmask(misc.read_raw_signed_data(cdata, self.size))
- try:
- enumerator = self.enumvalues2erators[value]
- except KeyError:
- enumerator = '#%d' % (value,)
- return self.space.wrap(enumerator)
-
- def convert_from_object(self, cdata, w_ob):
- space = self.space
- try:
- return W_CTypePrimitiveSigned.convert_from_object(self, cdata,
- w_ob)
- except OperationError, e:
- if not e.match(space, space.w_TypeError):
- raise
- if space.isinstance_w(w_ob, space.w_str):
- value = self.convert_enum_string_to_int(space.str_w(w_ob))
- misc.write_raw_integer_data(cdata, value, self.size)
- else:
- raise self._convert_error("str or int", w_ob)
-
- def cast_str(self, w_ob):
- space = self.space
- return self.convert_enum_string_to_int(space.str_w(w_ob))
-
- def convert_enum_string_to_int(self, s):
- space = self.space
- if s.startswith('#'):
- try:
- return int(s[1:]) # xxx is it RPython?
- except ValueError:
- raise OperationError(space.w_ValueError,
- space.wrap("invalid literal after '#'"))
- else:
- try:
- return self.enumerators2values[s]
- except KeyError:
- raise operationerrfmt(space.w_ValueError,
- "'%s' is not an enumerator for %s",
- s, self.name)
-
-
-class W_CTypeStructOrUnion(W_CType):
- # fields added by complete_struct_or_union():
- alignment = -1
- fields_list = None
- fields_dict = None
-
- def __init__(self, space, name):
- name = '%s %s' % (self.kind, name)
- W_CType.__init__(self, space, -1, name, len(name))
-
- def check_complete(self):
- if self.fields_dict is None:
- space = self.space
- raise operationerrfmt(space.w_TypeError,
- "'%s' is not completed yet", self.name)
-
- def _alignof(self):
- self.check_complete()
- return self.alignment
-
- def _getfields(self):
- if self.size < 0:
- return None
- space = self.space
- result = [None] * len(self.fields_list)
- for fname, field in self.fields_dict.iteritems():
- i = self.fields_list.index(field)
- result[i] = space.newtuple([space.wrap(fname),
- space.wrap(field)])
- return space.newlist(result)
-
- def convert_to_object(self, cdata):
- space = self.space
- self.check_complete()
- return cdataobj.W_CData(space, cdata, self)
-
- def offsetof(self, fieldname):
- self.check_complete()
- try:
- cfield = self.fields_dict[fieldname]
- except KeyError:
- space = self.space
- raise OperationError(space.w_KeyError, space.wrap(fieldname))
- return cfield.offset
-
- def _copy_from_same(self, cdata, w_ob):
- space = self.space
- ob = space.interpclass_w(w_ob)
- if isinstance(ob, cdataobj.W_CData):
- if ob.ctype is self and self.size >= 0:
- # push push push at the llmemory interface (with hacks that
- # are all removed after translation)
- zero = llmemory.itemoffsetof(rffi.CCHARP.TO, 0)
- llmemory.raw_memcopy(
- llmemory.cast_ptr_to_adr(ob._cdata) + zero,
- llmemory.cast_ptr_to_adr(cdata) + zero,
- self.size * llmemory.sizeof(lltype.Char))
- keepalive_until_here(ob)
- return True
- return False
-
-
-class W_CTypeStruct(W_CTypeStructOrUnion):
- kind = "struct"
-
- def convert_from_object(self, cdata, w_ob):
- space = self.space
- if self._copy_from_same(cdata, w_ob):
- return
-
- if (space.isinstance_w(w_ob, space.w_list) or
- space.isinstance_w(w_ob, space.w_tuple)):
- lst_w = space.listview(w_ob)
- if len(lst_w) > len(self.fields_list):
- raise operationerrfmt(space.w_ValueError,
- "too many initializers for '%s' (got %d)",
- self.name, len(lst_w))
- for i in range(len(lst_w)):
- self.fields_list[i].write(cdata, lst_w[i])
-
- elif space.isinstance_w(w_ob, space.w_dict):
- lst_w = space.fixedview(w_ob)
- for i in range(len(lst_w)):
- w_key = lst_w[i]
- key = space.str_w(w_key)
- try:
- cf = self.fields_dict[key]
- except KeyError:
- space.raise_key_error(w_key)
- assert 0
- cf.write(cdata, space.getitem(w_ob, w_key))
-
- else:
- raise self._convert_error("list or tuple or dict or struct-cdata",
- w_ob)
-
-
-class W_CTypeUnion(W_CTypeStructOrUnion):
- kind = "union"
-
- def convert_from_object(self, cdata, w_ob):
- space = self.space
- if self._copy_from_same(cdata, w_ob):
- return
- if not self.fields_list:
- raise OperationError(space.w_ValueError,
- space.wrap("empty union"))
- self.fields_list[0].write(cdata, w_ob)
-
-
-class W_CTypeVoid(W_CType):
- cast_anything = True
-
- def __init__(self, space):
- W_CType.__init__(self, space, -1, "void", len("void"))
-
-
-class W_CField(Wrappable):
- _immutable_ = True
- def __init__(self, ctype, offset, bitshift, bitsize):
- self.ctype = ctype
- self.offset = offset
- self.bitshift = bitshift
- self.bitsize = bitsize
-
- def read(self, cdata):
- cdata = rffi.ptradd(cdata, self.offset)
- if self.bitshift >= 0:
- xxx
- else:
- return self.ctype.convert_to_object(cdata)
-
- def write(self, cdata, w_ob):
- cdata = rffi.ptradd(cdata, self.offset)
- if self.bitshift >= 0:
- xxx
- else:
- self.ctype.convert_from_object(cdata, w_ob)
-
-
W_CType.typedef = TypeDef(
'_ffi_backend.CTypeDescr',
__repr__ = interp2app(W_CType.repr),
__weakref__ = make_weakref_descr(W_CType),
)
W_CType.typedef.acceptable_as_base_class = False
-
-W_CField.typedef = TypeDef(
- '_ffi_backend.CField',
- type = interp_attrproperty('ctype', W_CField),
- offset = interp_attrproperty('offset', W_CField),
- bitshift = interp_attrproperty('bitshift', W_CField),
- bitsize = interp_attrproperty('bitsize', W_CField),
- )
-W_CField.typedef.acceptable_as_base_class = False
diff --git a/pypy/module/_ffi_backend/ctypeprim.py b/pypy/module/_ffi_backend/ctypeprim.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi_backend/ctypeprim.py
@@ -0,0 +1,184 @@
+"""
+Primitives.
+"""
+
+from pypy.interpreter.error import operationerrfmt
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rlib.rarithmetic import intmask, r_ulonglong
+from pypy.rlib.objectmodel import keepalive_until_here
+
+from pypy.module._ffi_backend.ctypeobj import W_CType
+from pypy.module._ffi_backend import cdataobj, misc
+
+
+class W_CTypePrimitive(W_CType):
+
+ def __init__(self, space, size, name, name_position, align):
+ W_CType.__init__(self, space, size, name, name_position)
+ self.align = align
+
+ def extra_repr(self, cdata):
+ w_ob = self.convert_to_object(cdata)
+ return self.space.str_w(self.space.repr(w_ob))
+
+ def _alignof(self):
+ return self.align
+
+ def cast_str(self, w_ob):
+ space = self.space
+ s = space.str_w(w_ob)
+ if len(s) != 1:
+ raise operationerrfmt(space.w_TypeError,
+ "cannot cast string of length %d to ctype '%s'",
+ len(s), self.name)
+ return ord(s[0])
+
+ def cast(self, w_ob):
+ from pypy.module._ffi_backend import ctypeptr
+ space = self.space
+ ob = space.interpclass_w(w_ob)
+ if (isinstance(ob, cdataobj.W_CData) and
+ isinstance(ob.ctype, ctypeptr.W_CTypePtrOrArray)):
+ value = rffi.cast(lltype.Signed, ob._cdata)
+ elif space.isinstance_w(w_ob, space.w_str):
+ value = self.cast_str(w_ob)
+ else:
+ value = misc.as_unsigned_long_long(space, w_ob, strict=False)
+ w_cdata = cdataobj.W_CDataOwnFromCasted(space, self.size, self)
+ w_cdata.write_raw_integer_data(value)
+ return w_cdata
+
+ def _overflow(self, w_ob):
+ space = self.space
+ s = space.str_w(space.str(w_ob))
+ raise operationerrfmt(space.w_OverflowError,
+ "integer %s does not fit '%s'", s, self.name)
+
+
+class W_CTypePrimitiveChar(W_CTypePrimitive):
+ cast_anything = True
+
+ def int(self, cdata):
+ return self.space.wrap(ord(cdata[0]))
+
+ def convert_to_object(self, cdata):
+ return self.space.wrap(cdata[0])
+
+ def str(self, cdataobj):
+ w_res = self.convert_to_object(cdataobj._cdata)
+ keepalive_until_here(cdataobj)
+ return w_res
+
+ def _convert_to_char(self, w_ob):
+ space = self.space
+ if space.isinstance_w(w_ob, space.w_str):
+ s = space.str_w(w_ob)
+ if len(s) == 1:
+ return s[0]
+ ob = space.interpclass_w(w_ob)
+ if (isinstance(ob, cdataobj.W_CData) and
+ isinstance(ob.ctype, W_CTypePrimitiveChar)):
+ return ob._cdata[0]
+ raise self._convert_error("string of length 1", w_ob)
+
+ def convert_from_object(self, cdata, w_ob):
+ value = self._convert_to_char(w_ob)
+ cdata[0] = value
+
+
+class W_CTypePrimitiveSigned(W_CTypePrimitive):
+
+ def __init__(self, *args):
+ W_CTypePrimitive.__init__(self, *args)
+ self.value_fits_long = self.size <= rffi.sizeof(lltype.Signed)
+ if self.size < rffi.sizeof(lltype.SignedLongLong):
+ sh = self.size * 8
+ self.vmin = r_ulonglong(-1) << (sh - 1)
+ self.vrangemax = (r_ulonglong(1) << sh) - 1
+
+ def int(self, cdata):
+ if self.value_fits_long:
+ # this case is to handle enums, but also serves as a slight
+ # performance improvement for some other primitive types
+ value = intmask(misc.read_raw_signed_data(cdata, self.size))
+ return self.space.wrap(value)
+ else:
+ return self.convert_to_object(cdata)
+
+ def convert_to_object(self, cdata):
+ value = misc.read_raw_signed_data(cdata, self.size)
+ if self.value_fits_long:
+ return self.space.wrap(intmask(value))
+ else:
+ return self.space.wrap(value) # r_longlong => on 32-bit, 'long'
+
+ def convert_from_object(self, cdata, w_ob):
+ value = misc.as_long_long(self.space, w_ob)
+ if self.size < rffi.sizeof(lltype.SignedLongLong):
+ if r_ulonglong(value) - self.vmin > self.vrangemax:
+ self._overflow(w_ob)
+ misc.write_raw_integer_data(cdata, value, self.size)
+
+
+class W_CTypePrimitiveUnsigned(W_CTypePrimitive):
+
+ def __init__(self, *args):
+ W_CTypePrimitive.__init__(self, *args)
+ self.value_fits_long = self.size < rffi.sizeof(lltype.Signed)
+ if self.size < rffi.sizeof(lltype.SignedLongLong):
+ sh = self.size * 8
+ self.vrangemax = (r_ulonglong(1) << sh) - 1
+
+ def int(self, cdata):
+ return self.convert_to_object(cdata)
+
+ def convert_from_object(self, cdata, w_ob):
+ value = misc.as_unsigned_long_long(self.space, w_ob, strict=True)
+ if self.size < rffi.sizeof(lltype.SignedLongLong):
+ if value > self.vrangemax:
+ self._overflow(w_ob)
+ misc.write_raw_integer_data(cdata, value, self.size)
+
+ def convert_to_object(self, cdata):
+ value = misc.read_raw_unsigned_data(cdata, self.size)
+ if self.value_fits_long:
+ return self.space.wrap(intmask(value))
+ else:
+ return self.space.wrap(value) # r_ulonglong => 'long' object
+
+
+class W_CTypePrimitiveFloat(W_CTypePrimitive):
+
+ def cast(self, w_ob):
+ space = self.space
+ ob = space.interpclass_w(w_ob)
+ if isinstance(ob, cdataobj.W_CData):
+ if not isinstance(ob.ctype, W_CTypePrimitive):
+ raise operationerrfmt(space.w_TypeError,
+ "cannot cast ctype '%s' to ctype '%s'",
+ ob.ctype.name, self.name)
+ w_ob = ob.convert_to_object()
+ #
+ if space.isinstance_w(w_ob, space.w_str):
+ value = self.cast_str(w_ob)
+ else:
+ value = space.float_w(w_ob)
+ w_cdata = cdataobj.W_CDataOwnFromCasted(space, self.size, self)
+ w_cdata.write_raw_float_data(value)
+ return w_cdata
+
+ def int(self, cdata):
+ w_value = self.float(cdata)
+ return self.space.int(w_value)
+
+ def float(self, cdata):
+ return self.convert_to_object(cdata)
+
+ def convert_to_object(self, cdata):
+ value = misc.read_raw_float_data(cdata, self.size)
+ return self.space.wrap(value)
+
+ def convert_from_object(self, cdata, w_ob):
+ space = self.space
+ value = space.float_w(space.float(w_ob))
+ misc.write_raw_float_data(cdata, value, self.size)
diff --git a/pypy/module/_ffi_backend/ctypeptr.py b/pypy/module/_ffi_backend/ctypeptr.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi_backend/ctypeptr.py
@@ -0,0 +1,112 @@
+"""
+Pointers.
+"""
+
+from pypy.interpreter.error import operationerrfmt
+from pypy.rpython.lltypesystem import rffi
+from pypy.rlib.objectmodel import keepalive_until_here
+
+from pypy.module._ffi_backend.ctypeobj import W_CType
+from pypy.module._ffi_backend.ctypeprim import W_CTypePrimitiveChar
+from pypy.module._ffi_backend import cdataobj, misc
+
+
+class W_CTypePtrOrArray(W_CType):
+
+ def __init__(self, space, size, extra, extra_position, ctitem):
+ name, name_position = ctitem.insert_name(extra, extra_position)
+ W_CType.__init__(self, space, size, name, name_position)
+ self.ctitem = ctitem
+
+
+class W_CTypePointer(W_CTypePtrOrArray):
+
+ def __init__(self, space, ctitem):
+ size = rffi.sizeof(rffi.VOIDP)
+ from pypy.module._ffi_backend import ctypearray
+ if isinstance(ctitem, ctypearray.W_CTypeArray):
+ extra = "(*)" # obscure case: see test_array_add
+ else:
+ extra = " *"
+ W_CTypePtrOrArray.__init__(self, space, size, extra, 2, ctitem)
+
+ def str(self, cdataobj):
+ if isinstance(self.ctitem, W_CTypePrimitiveChar):
+ if not cdataobj._cdata:
+ space = self.space
+ raise operationerrfmt(space.w_RuntimeError,
+ "cannot use str() on %s",
+ space.str_w(cdataobj.repr()))
+ s = rffi.charp2str(cdataobj._cdata)
+ keepalive_until_here(cdataobj)
+ return self.space.wrap(s)
+ return W_CTypePtrOrArray.str(self, cdataobj)
+
+ def cast(self, w_ob):
+ space = self.space
+ ob = space.interpclass_w(w_ob)
+ if (isinstance(ob, cdataobj.W_CData) and
+ isinstance(ob.ctype, W_CTypePtrOrArray)):
+ value = ob._cdata
+ else:
+ value = misc.as_unsigned_long_long(space, w_ob, strict=False)
+ value = rffi.cast(rffi.CCHARP, value)
+ return cdataobj.W_CData(space, value, self)
+
+ def newp(self, w_init):
+ from pypy.module._ffi_backend import ctypeprim
+ space = self.space
+ ctitem = self.ctitem
+ datasize = ctitem.size
+ if datasize < 0:
+ raise operationerrfmt(space.w_TypeError,
+ "cannot instantiate ctype '%s' of unknown size",
+ self.name)
+ if isinstance(ctitem, W_CTypePrimitiveChar):
+ datasize *= 2 # forcefully add a null character
+ cdata = cdataobj.W_CDataOwn(space, datasize, self)
+ if not space.is_w(w_init, space.w_None):
+ ctitem.convert_from_object(cdata._cdata, w_init)
+ keepalive_until_here(cdata)
+ return cdata
+
+ def _check_subscript_index(self, w_cdata, i):
+ if isinstance(w_cdata, cdataobj.W_CDataOwn) and i != 0:
+ space = self.space
+ raise operationerrfmt(space.w_IndexError,
+ "cdata '%s' can only be indexed by 0",
+ self.name)
+
+ def add(self, cdata, i):
+ space = self.space
+ ctitem = self.ctitem
+ if ctitem.size < 0:
+ raise operationerrfmt(space.w_TypeError,
+ "ctype '%s' points to items of unknown size",
+ self.name)
+ p = rffi.ptradd(cdata, i * self.ctitem.size)
+ return cdataobj.W_CData(space, p, self)
+
+ def _alignof(self):
+ from pypy.module._ffi_backend import newtype
+ return newtype.alignment_of_pointer
+
+ def convert_to_object(self, cdata):
+ ptrdata = rffi.cast(rffi.CCHARPP, cdata)[0]
+ return cdataobj.W_CData(self.space, ptrdata, self)
+
+ def convert_from_object(self, cdata, w_ob):
+ space = self.space
+ ob = space.interpclass_w(w_ob)
+ if not isinstance(ob, cdataobj.W_CData):
+ raise self._convert_error("compatible pointer", w_ob)
+ otherctype = ob.ctype
+ if (isinstance(otherctype, W_CTypePtrOrArray) and
+ (self.ctitem.cast_anything or
+ otherctype.ctitem.cast_anything or
+ self.ctitem is otherctype.ctitem)):
+ pass # compatible types
+ else:
+ raise self._convert_error("compatible pointer", w_ob)
+
+ rffi.cast(rffi.CCHARPP, cdata)[0] = ob._cdata
diff --git a/pypy/module/_ffi_backend/ctypestruct.py b/pypy/module/_ffi_backend/ctypestruct.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi_backend/ctypestruct.py
@@ -0,0 +1,157 @@
+"""
+Struct and unions.
+"""
+
+from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.typedef import TypeDef, interp_attrproperty
+from pypy.rlib.objectmodel import keepalive_until_here
+
+from pypy.module._ffi_backend.ctypeobj import W_CType
+from pypy.module._ffi_backend import cdataobj
+
+
+class W_CTypeStructOrUnion(W_CType):
+ # fields added by complete_struct_or_union():
+ alignment = -1
+ fields_list = None
+ fields_dict = None
+
+ def __init__(self, space, name):
+ name = '%s %s' % (self.kind, name)
+ W_CType.__init__(self, space, -1, name, len(name))
+
+ def check_complete(self):
+ if self.fields_dict is None:
+ space = self.space
+ raise operationerrfmt(space.w_TypeError,
+ "'%s' is not completed yet", self.name)
+
+ def _alignof(self):
+ self.check_complete()
+ return self.alignment
+
+ def _getfields(self):
+ if self.size < 0:
+ return None
+ space = self.space
+ result = [None] * len(self.fields_list)
+ for fname, field in self.fields_dict.iteritems():
+ i = self.fields_list.index(field)
+ result[i] = space.newtuple([space.wrap(fname),
+ space.wrap(field)])
+ return space.newlist(result)
+
+ def convert_to_object(self, cdata):
+ space = self.space
+ self.check_complete()
+ return cdataobj.W_CData(space, cdata, self)
+
+ def offsetof(self, fieldname):
+ self.check_complete()
+ try:
+ cfield = self.fields_dict[fieldname]
+ except KeyError:
+ space = self.space
+ raise OperationError(space.w_KeyError, space.wrap(fieldname))
+ return cfield.offset
+
+ def _copy_from_same(self, cdata, w_ob):
+ space = self.space
+ ob = space.interpclass_w(w_ob)
+ if isinstance(ob, cdataobj.W_CData):
+ if ob.ctype is self and self.size >= 0:
+ # push push push at the llmemory interface (with hacks that
+ # are all removed after translation)
+ zero = llmemory.itemoffsetof(rffi.CCHARP.TO, 0)
+ llmemory.raw_memcopy(
+ llmemory.cast_ptr_to_adr(ob._cdata) + zero,
+ llmemory.cast_ptr_to_adr(cdata) + zero,
+ self.size * llmemory.sizeof(lltype.Char))
+ keepalive_until_here(ob)
+ return True
+ return False
+
+
+class W_CTypeStruct(W_CTypeStructOrUnion):
+ kind = "struct"
+
+ def convert_from_object(self, cdata, w_ob):
+ space = self.space
+ if self._copy_from_same(cdata, w_ob):
+ return
+
+ if (space.isinstance_w(w_ob, space.w_list) or
+ space.isinstance_w(w_ob, space.w_tuple)):
+ lst_w = space.listview(w_ob)
+ if len(lst_w) > len(self.fields_list):
+ raise operationerrfmt(space.w_ValueError,
+ "too many initializers for '%s' (got %d)",
+ self.name, len(lst_w))
+ for i in range(len(lst_w)):
+ self.fields_list[i].write(cdata, lst_w[i])
+
+ elif space.isinstance_w(w_ob, space.w_dict):
+ lst_w = space.fixedview(w_ob)
+ for i in range(len(lst_w)):
+ w_key = lst_w[i]
+ key = space.str_w(w_key)
+ try:
+ cf = self.fields_dict[key]
+ except KeyError:
+ space.raise_key_error(w_key)
+ assert 0
+ cf.write(cdata, space.getitem(w_ob, w_key))
+
+ else:
+ raise self._convert_error("list or tuple or dict or struct-cdata",
+ w_ob)
+
+
+class W_CTypeUnion(W_CTypeStructOrUnion):
+ kind = "union"
+
+ def convert_from_object(self, cdata, w_ob):
+ space = self.space
+ if self._copy_from_same(cdata, w_ob):
+ return
+ if not self.fields_list:
+ raise OperationError(space.w_ValueError,
+ space.wrap("empty union"))
+ self.fields_list[0].write(cdata, w_ob)
+
+
+
+class W_CField(Wrappable):
+ _immutable_ = True
+ def __init__(self, ctype, offset, bitshift, bitsize):
+ self.ctype = ctype
+ self.offset = offset
+ self.bitshift = bitshift
+ self.bitsize = bitsize
+
+ def read(self, cdata):
+ cdata = rffi.ptradd(cdata, self.offset)
+ if self.bitshift >= 0:
+ xxx
+ else:
+ return self.ctype.convert_to_object(cdata)
+
+ def write(self, cdata, w_ob):
+ cdata = rffi.ptradd(cdata, self.offset)
+ if self.bitshift >= 0:
+ xxx
+ else:
+ self.ctype.convert_from_object(cdata, w_ob)
+
+
+
+W_CField.typedef = TypeDef(
+ '_ffi_backend.CField',
+ type = interp_attrproperty('ctype', W_CField),
+ offset = interp_attrproperty('offset', W_CField),
+ bitshift = interp_attrproperty('bitshift', W_CField),
+ bitsize = interp_attrproperty('bitsize', W_CField),
+ )
+W_CField.typedef.acceptable_as_base_class = False
diff --git a/pypy/module/_ffi_backend/ctypevoid.py b/pypy/module/_ffi_backend/ctypevoid.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_ffi_backend/ctypevoid.py
@@ -0,0 +1,12 @@
+"""
+Void.
+"""
+
+from pypy.module._ffi_backend.ctypeobj import W_CType
+
+
+class W_CTypeVoid(W_CType):
+ cast_anything = True
+
+ def __init__(self, space):
+ W_CType.__init__(self, space, -1, "void", len("void"))
diff --git a/pypy/module/_ffi_backend/newtype.py b/pypy/module/_ffi_backend/newtype.py
--- a/pypy/module/_ffi_backend/newtype.py
+++ b/pypy/module/_ffi_backend/newtype.py
@@ -3,7 +3,8 @@
from pypy.rpython.lltypesystem import lltype, rffi
from pypy.rlib.rarithmetic import ovfcheck
-from pypy.module._ffi_backend import ctypeobj
+from pypy.module._ffi_backend import ctypeobj, ctypeprim, ctypeptr, ctypearray
+from pypy.module._ffi_backend import ctypestruct, ctypevoid, ctypeenum
def alignment(TYPE):
@@ -20,19 +21,19 @@
def eptype(name, TYPE, ctypecls):
PRIMITIVE_TYPES[name] = ctypecls, rffi.sizeof(TYPE), alignment(TYPE)
-eptype("char", lltype.Char, ctypeobj.W_CTypePrimitiveChar)
-eptype("signed char", rffi.SIGNEDCHAR, ctypeobj.W_CTypePrimitiveSigned)
-eptype("short", rffi.SHORT, ctypeobj.W_CTypePrimitiveSigned)
-eptype("int", rffi.INT, ctypeobj.W_CTypePrimitiveSigned)
-eptype("long", rffi.LONG, ctypeobj.W_CTypePrimitiveSigned)
-eptype("long long", rffi.LONGLONG, ctypeobj.W_CTypePrimitiveSigned)
-eptype("unsigned char", rffi.UCHAR, ctypeobj.W_CTypePrimitiveUnsigned)
-eptype("unsigned short", rffi.SHORT, ctypeobj.W_CTypePrimitiveUnsigned)
-eptype("unsigned int", rffi.INT, ctypeobj.W_CTypePrimitiveUnsigned)
-eptype("unsigned long", rffi.LONG, ctypeobj.W_CTypePrimitiveUnsigned)
-eptype("unsigned long long", rffi.LONGLONG, ctypeobj.W_CTypePrimitiveUnsigned)
-eptype("float", rffi.FLOAT, ctypeobj.W_CTypePrimitiveFloat)
-eptype("double", rffi.DOUBLE, ctypeobj.W_CTypePrimitiveFloat)
+eptype("char", lltype.Char, ctypeprim.W_CTypePrimitiveChar)
+eptype("signed char", rffi.SIGNEDCHAR, ctypeprim.W_CTypePrimitiveSigned)
+eptype("short", rffi.SHORT, ctypeprim.W_CTypePrimitiveSigned)
+eptype("int", rffi.INT, ctypeprim.W_CTypePrimitiveSigned)
+eptype("long", rffi.LONG, ctypeprim.W_CTypePrimitiveSigned)
+eptype("long long", rffi.LONGLONG, ctypeprim.W_CTypePrimitiveSigned)
+eptype("unsigned char", rffi.UCHAR, ctypeprim.W_CTypePrimitiveUnsigned)
+eptype("unsigned short", rffi.SHORT, ctypeprim.W_CTypePrimitiveUnsigned)
+eptype("unsigned int", rffi.INT, ctypeprim.W_CTypePrimitiveUnsigned)
+eptype("unsigned long", rffi.LONG, ctypeprim.W_CTypePrimitiveUnsigned)
+eptype("unsigned long long", rffi.LONGLONG, ctypeprim.W_CTypePrimitiveUnsigned)
+eptype("float", rffi.FLOAT, ctypeprim.W_CTypePrimitiveFloat)
+eptype("double", rffi.DOUBLE, ctypeprim.W_CTypePrimitiveFloat)
@unwrap_spec(name=str)
def new_primitive_type(space, name):
@@ -47,14 +48,14 @@
@unwrap_spec(ctype=ctypeobj.W_CType)
def new_pointer_type(space, ctype):
- ctypeptr = ctypeobj.W_CTypePointer(space, ctype)
- return ctypeptr
+ ctypepointer = ctypeptr.W_CTypePointer(space, ctype)
+ return ctypepointer
# ____________________________________________________________
@unwrap_spec(ctptr=ctypeobj.W_CType)
def new_array_type(space, ctptr, w_length):
- if not isinstance(ctptr, ctypeobj.W_CTypePointer):
+ if not isinstance(ctptr, ctypeptr.W_CTypePointer):
raise OperationError(space.w_TypeError,
space.wrap("first arg must be a pointer ctype"))
ctitem = ctptr.ctitem
@@ -78,29 +79,29 @@
space.wrap("array size would overflow a ssize_t"))
extra = '[%d]' % length
#
- ctypeptr = ctypeobj.W_CTypeArray(space, ctptr, length, arraysize, extra)
- return ctypeptr
+ ctype = ctypearray.W_CTypeArray(space, ctptr, length, arraysize, extra)
+ return ctype
# ____________________________________________________________
@unwrap_spec(name=str)
def new_struct_type(space, name):
- return ctypeobj.W_CTypeStruct(space, name)
+ return ctypestruct.W_CTypeStruct(space, name)
@unwrap_spec(name=str)
def new_union_type(space, name):
- return ctypeobj.W_CTypeUnion(space, name)
+ return ctypestruct.W_CTypeUnion(space, name)
@unwrap_spec(ctype=ctypeobj.W_CType, totalsize=int, totalalignment=int)
def complete_struct_or_union(space, ctype, w_fields, w_ignored=None,
totalsize=-1, totalalignment=-1):
- if (not isinstance(ctype, ctypeobj.W_CTypeStructOrUnion)
+ if (not isinstance(ctype, ctypestruct.W_CTypeStructOrUnion)
or ctype.size >= 0):
raise OperationError(space.w_TypeError,
space.wrap("first arg must be a non-initialized"
" struct or union ctype"))
- is_union = isinstance(ctype, ctypeobj.W_CTypeUnion)
+ is_union = isinstance(ctype, ctypestruct.W_CTypeUnion)
maxsize = 1
alignment = 1
offset = 0
@@ -149,7 +150,7 @@
else:
xxx
#
- fld = ctypeobj.W_CField(ftype, offset, bitshift, fbitsize)
+ fld = ctypestruct.W_CField(ftype, offset, bitshift, fbitsize)
fields_list.append(fld)
fields_dict[fname] = fld
#
@@ -183,7 +184,7 @@
# ____________________________________________________________
def new_void_type(space):
- ctype = ctypeobj.W_CTypeVoid(space)
+ ctype = ctypevoid.W_CTypeVoid(space)
return ctype
# ____________________________________________________________
@@ -197,5 +198,5 @@
space.wrap("tuple args must have the same size"))
enumerators = [space.str_w(w) for w in enumerators_w]
enumvalues = [space.int_w(w) for w in enumvalues_w]
- ctype = ctypeobj.W_CTypeEnum(space, name, enumerators, enumvalues)
+ ctype = ctypeenum.W_CTypeEnum(space, name, enumerators, enumvalues)
return ctype
More information about the pypy-commit
mailing list