Commits

Armin Rigo committed 41e9156

wchar_t: in-progress

Comments (0)

Files changed (8)

pypy/module/_cffi_backend/cdataobj.py

     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')
     __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),

pypy/module/_cffi_backend/ctypearray.py

 
 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
 
             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()
 
             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:
                 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)
 

pypy/module/_cffi_backend/ctypefunc.py

             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)

pypy/module/_cffi_backend/ctypeobj.py

     #_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
     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,

pypy/module/_cffi_backend/ctypeprim.py

                               "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]))
         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):

pypy/module/_cffi_backend/ctypeptr.py

     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)
         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):
             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
                                                        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)
         #

pypy/module/_cffi_backend/ctypestruct.py

         #
         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

pypy/module/_cffi_backend/newtype.py

     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)
 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):
             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
                      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: