Author: Armin Rigo <ar...@tunes.org> Branch: ffi-backend Changeset: r56482:41e915635f62 Date: 2012-07-26 21:34 +0200 http://bitbucket.org/pypy/pypy/changeset/41e915635f62/
Log: wchar_t: in-progress diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -74,6 +74,9 @@ def str(self): return self.ctype.str(self) + def unicode(self): + return self.ctype.unicode(self) + def _make_comparison(name): op = getattr(operator, name) requires_ordering = name not in ('eq', 'ne') @@ -316,7 +319,7 @@ __float__ = interp2app(W_CData.float), __len__ = interp2app(W_CData.len), __str__ = interp2app(W_CData.str), - #XXX WCHAR __unicode__ = + __unicode__ = interp2app(W_CData.unicode), __lt__ = interp2app(W_CData.lt), __le__ = interp2app(W_CData.le), __eq__ = interp2app(W_CData.eq), diff --git a/pypy/module/_cffi_backend/ctypearray.py b/pypy/module/_cffi_backend/ctypearray.py --- a/pypy/module/_cffi_backend/ctypearray.py +++ b/pypy/module/_cffi_backend/ctypearray.py @@ -12,6 +12,7 @@ from pypy.module._cffi_backend.ctypeobj import W_CType 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 @@ -31,6 +32,14 @@ return self.space.wrap(s) return W_CTypePtrOrArray.str(self, cdataobj) + def unicode(self, cdataobj): + if isinstance(self.ctitem, W_CTypePrimitiveUniChar): + XXX + s = rffi.charp2strn(cdataobj._cdata, cdataobj.get_array_length()) + keepalive_until_here(cdataobj) + return self.space.wrap(s) + return W_CTypePtrOrArray.unicode(self, cdataobj) + def _alignof(self): return self.ctitem.alignof() @@ -42,7 +51,7 @@ 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): + 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 else: @@ -109,7 +118,24 @@ cdata[i] = s[i] if n != self.length: cdata[n] = '\x00' - #XXX WCHAR + elif isinstance(self.ctitem, W_CTypePrimitiveUniChar): + try: + s = space.unicode_w(w_ob) + except OperationError, e: + if not e.match(space, space.w_TypeError): + raise + raise self._convert_error("unicode or list or tuple", w_ob) + n = len(s) + if self.length >= 0 and n > self.length: + raise operationerrfmt(space.w_IndexError, + "initializer unicode string is too long for '%s'" + " (got %d characters)", + self.name, n) + unichardata = rffi.cast(rffi.CWCHARP, cdata) + for i in range(n): + unichardata[i] = s[i] + if n != self.length: + unichardata[n] = u'\x00' else: raise self._convert_error("list or tuple", w_ob) diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py --- a/pypy/module/_cffi_backend/ctypefunc.py +++ b/pypy/module/_cffi_backend/ctypefunc.py @@ -296,7 +296,7 @@ elif size == 4: return _settype(ctype, clibffi.ffi_type_sint32) elif size == 8: return _settype(ctype, clibffi.ffi_type_sint64) - elif (isinstance(ctype, ctypeprim.W_CTypePrimitiveChar) or + elif (isinstance(ctype, ctypeprim.W_CTypePrimitiveCharOrWChar) or isinstance(ctype, ctypeprim.W_CTypePrimitiveUnsigned)): if size == 1: return _settype(ctype, clibffi.ffi_type_uint8) elif size == 2: return _settype(ctype, clibffi.ffi_type_uint16) diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py --- a/pypy/module/_cffi_backend/ctypeobj.py +++ b/pypy/module/_cffi_backend/ctypeobj.py @@ -13,6 +13,7 @@ #_immutable_ = True XXX newtype.complete_struct_or_union()? cast_anything = False is_char_ptr_or_array = False + is_unichar_ptr_or_array = False def __init__(self, space, size, name, name_position): self.space = space @@ -85,6 +86,9 @@ def str(self, cdataobj): return cdataobj.repr() + def unicode(self, cdataobj): + XXX + def add(self, cdata, i): space = self.space raise operationerrfmt(space.w_TypeError, diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py --- a/pypy/module/_cffi_backend/ctypeprim.py +++ b/pypy/module/_cffi_backend/ctypeprim.py @@ -58,9 +58,12 @@ "integer %s does not fit '%s'", s, self.name) -class W_CTypePrimitiveChar(W_CTypePrimitive): +class W_CTypePrimitiveCharOrUniChar(W_CTypePrimitive): + pass + + +class W_CTypePrimitiveChar(W_CTypePrimitiveCharOrUniChar): cast_anything = True - #XXX WCHAR class PrimitiveUniChar def int(self, cdata): return self.space.wrap(ord(cdata[0])) @@ -90,6 +93,38 @@ cdata[0] = value +class W_CTypePrimitiveUniChar(W_CTypePrimitiveCharOrUniChar): + + def int(self, cdata): + XXX + + def convert_to_object(self, cdata): + unichardata = rffi.cast(rffi.CWCHARP, cdata) + s = rffi.wcharpsize2unicode(unichardata, 1) + return self.space.wrap(s) + + def unicode(self, cdataobj): + w_res = self.convert_to_object(cdataobj._cdata) + keepalive_until_here(cdataobj) + return w_res + + def _convert_to_unichar(self, w_ob): + space = self.space + if space.isinstance_w(w_ob, space.w_unicode): + s = space.unicode_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_CTypePrimitiveUniChar)): + return rffi.cast(rffi.CWCHARP, ob._cdata)[0] + raise self._convert_error("unicode string of length 1", w_ob) + + def convert_from_object(self, cdata, w_ob): + value = self._convert_to_unichar(w_ob) + rffi.cast(rffi.CWCHARP, cdata)[0] = value + + class W_CTypePrimitiveSigned(W_CTypePrimitive): def __init__(self, *args): diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py --- a/pypy/module/_cffi_backend/ctypeptr.py +++ b/pypy/module/_cffi_backend/ctypeptr.py @@ -15,6 +15,7 @@ def __init__(self, space, size, extra, extra_position, ctitem, could_cast_anything=True): from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveChar + from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveUniChar from pypy.module._cffi_backend.ctypestruct import W_CTypeStructOrUnion name, name_position = ctitem.insert_name(extra, extra_position) W_CType.__init__(self, space, size, name, name_position) @@ -25,6 +26,7 @@ self.ctitem = ctitem self.can_cast_anything = could_cast_anything and ctitem.cast_anything self.is_char_ptr_or_array = isinstance(ctitem, W_CTypePrimitiveChar) + self.is_unichar_ptr_or_array=isinstance(ctitem,W_CTypePrimitiveUniChar) self.is_struct_ptr = isinstance(ctitem, W_CTypeStructOrUnion) def cast(self, w_ob): @@ -98,6 +100,9 @@ return self.space.wrap(s) return W_CTypePtrOrArray.str(self, cdataobj) + def unicode(self, cdataobj): + XXX + def newp(self, w_init): from pypy.module._cffi_backend import ctypeprim space = self.space @@ -116,7 +121,7 @@ cdatastruct._cdata, self, cdatastruct) else: - if self.is_char_ptr_or_array: + if self.is_char_ptr_or_array or self.is_unichar_ptr_or_array: datasize *= 2 # forcefully add a null character cdata = cdataobj.W_CDataNewOwning(space, datasize, self) # diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py --- a/pypy/module/_cffi_backend/ctypestruct.py +++ b/pypy/module/_cffi_backend/ctypestruct.py @@ -183,7 +183,7 @@ # if isinstance(ctype, ctypeprim.W_CTypePrimitiveUnsigned): value_fits_long = ctype.value_fits_long - elif isinstance(ctype, ctypeprim.W_CTypePrimitiveChar): + elif isinstance(ctype, ctypeprim.W_CTypePrimitiveCharOrUniChar): value_fits_long = True else: raise NotImplementedError diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py --- a/pypy/module/_cffi_backend/newtype.py +++ b/pypy/module/_cffi_backend/newtype.py @@ -24,6 +24,7 @@ PRIMITIVE_TYPES[name] = ctypecls, rffi.sizeof(TYPE), alignment(TYPE) eptype("char", lltype.Char, ctypeprim.W_CTypePrimitiveChar) +eptype("wchar_t", lltype.UniChar, ctypeprim.W_CTypePrimitiveUniChar) eptype("signed char", rffi.SIGNEDCHAR, ctypeprim.W_CTypePrimitiveSigned) eptype("short", rffi.SHORT, ctypeprim.W_CTypePrimitiveSigned) eptype("int", rffi.INT, ctypeprim.W_CTypePrimitiveSigned) @@ -36,7 +37,6 @@ eptype("unsigned long long", rffi.LONGLONG, ctypeprim.W_CTypePrimitiveUnsigned) eptype("float", rffi.FLOAT, ctypeprim.W_CTypePrimitiveFloat) eptype("double", rffi.DOUBLE, ctypeprim.W_CTypePrimitiveFloat) -#XXX WCHAR @unwrap_spec(name=str) def new_primitive_type(space, name): @@ -148,8 +148,9 @@ custom_field_pos |= (offset != foffset) offset = foffset # - if fbitsize < 0 or (fbitsize == 8 * ftype.size and not - isinstance(ftype, ctypeprim.W_CTypePrimitiveChar)): + if fbitsize < 0 or ( + fbitsize == 8 * ftype.size and not + isinstance(ftype, ctypeprim.W_CTypePrimitiveCharOrUniChar)): fbitsize = -1 bitshift = -1 prev_bit_position = 0 @@ -159,7 +160,6 @@ isinstance(ftype, ctypeprim.W_CTypePrimitiveChar)) or fbitsize == 0 or fbitsize > 8 * ftype.size): - #XXX WCHAR: reach here if ftype is PrimitiveUniChar raise operationerrfmt(space.w_TypeError, "invalid bit field '%s'", fname) if prev_bit_position > 0: _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit