cffi / cffi / model.py

class BaseType(object):

    def __repr__(self):
        return '<%s>' % (self.get_c_name(),)

    def __eq__(self, other):
        return (self.__class__ == other.__class__ and
                self._get_items() == other._get_items())

    def __ne__(self, other):
        return not self == other

    def _get_items(self):
        return [(name, getattr(self, name)) for name in self._attrs_]

    def __hash__(self):
        return hash((self.__class__, tuple(self._get_items())))

    def prepare_backend_type(self, ffi):
        pass

    def finish_backend_type(self, ffi, *args):
        try:
            return ffi._cached_btypes[self]
        except KeyError:
            return self.new_backend_type(ffi, *args)

    def verifier_declare_typedef(self, verifier, name):
        verifier.write('__sametype__(%s, %s)' % (
            self.get_c_name('** result'), name))


class VoidType(BaseType):
    _attrs_ = ()

    def get_c_name(self, replace_with=''):
        return 'void' + replace_with

    def new_backend_type(self, ffi):
        return ffi._backend.new_void_type()

void_type = VoidType()

class PrimitiveType(BaseType):
    _attrs_ = ('name',)

    def __init__(self, name):
        self.name = name

    def get_c_name(self, replace_with=''):
        return self.name + replace_with

    def new_backend_type(self, ffi):
        return ffi._backend.new_primitive_type(self.name)

class FunctionType(BaseType):
    _attrs_ = ('args', 'result', 'ellipsis')

    def __init__(self, args, result, ellipsis):
        self.args = args
        self.result = result
        self.ellipsis = ellipsis

    def get_c_name(self, replace_with=''):
        reprargs = [arg.get_c_name() for arg in self.args]
        if self.ellipsis:
            reprargs.append('...')
        reprargs = reprargs or ['void']
        replace_with = '(*%s)(%s)' % (replace_with, ', '.join(reprargs))
        return self.result.get_c_name(replace_with)

    def prepare_backend_type(self, ffi):
        args = [ffi._get_cached_btype(self.result)]
        for tp in self.args:
            args.append(ffi._get_cached_btype(tp))
        return args

    def new_backend_type(self, ffi, result, *args):
        return ffi._backend.new_function_type(args, result, self.ellipsis)

    def verifier_declare_function(self, verifier, name):
        verifier.write('{ %s = %s; }' % (
            self.get_c_name('result'), name))


class PointerType(BaseType):
    _attrs_ = ('totype',)
    
    def __init__(self, totype):
        self.totype = totype

    def get_c_name(self, replace_with=''):
        return self.totype.get_c_name('* ' + replace_with)

    def prepare_backend_type(self, ffi):
        return (ffi._get_cached_btype(self.totype),)

    def new_backend_type(self, ffi, BItem):
        return ffi._backend.new_pointer_type(BItem)

class ConstPointerType(PointerType):

    def get_c_name(self, replace_with=''):
        return self.totype.get_c_name(' const * ' + replace_with)

    def prepare_backend_type(self, ffi):
        return (ffi._get_cached_btype(PointerType(self.totype)),)

    def new_backend_type(self, ffi, BPtr):
        return BPtr


class ArrayType(BaseType):
    _attrs_ = ('item', 'length')

    def __init__(self, item, length):
        self.item = item
        self.length = length

    def get_c_name(self, replace_with=''):
        if self.length is None:
            brackets = '[]'
        else:
            brackets = '[%d]' % self.length
        return self.item.get_c_name(replace_with + brackets)

    def prepare_backend_type(self, ffi):
        return (ffi._get_cached_btype(PointerType(self.item)),)

    def new_backend_type(self, ffi, BPtrItem):
        return ffi._backend.new_array_type(BPtrItem, self.length)

class StructOrUnion(BaseType):
    _attrs_ = ('name',)
        
    def __init__(self, name, fldnames, fldtypes, fldbitsize):
        self.name = name
        self.fldnames = fldnames
        self.fldtypes = fldtypes
        self.fldbitsize = fldbitsize

    def get_c_name(self, replace_with=''):
        return '%s %s%s' % (self.kind, self.name, replace_with)

    def prepare_backend_type(self, ffi):
        BType = self.get_btype(ffi)
        ffi._cached_btypes[self] = BType
        args = [BType]
        for tp in self.fldtypes:
            args.append(ffi._get_cached_btype(tp))
        return args

    def finish_backend_type(self, ffi, BType, *fldtypes):
        lst = zip(self.fldnames, fldtypes, self.fldbitsize)
        ffi._backend.complete_struct_or_union(BType, lst, self)
        return BType

class StructType(StructOrUnion):
    kind = 'struct'
    partial = False

    def check_not_partial(self):
        if self.partial:
            from . import ffiplatform
            raise ffiplatform.VerificationMissing(self.get_c_name())

    def get_btype(self, ffi):
        self.check_not_partial()
        return ffi._backend.new_struct_type(self.name)

    def verifier_declare_struct(self, verifier, name):
        assert name == self.name
        if self.partial:
            self.verifier_decl_partial(verifier)
        else:
            self.verifier_decl_notpartial(verifier)

    def verifier_decl_notpartial(self, verifier):
        if self.fldnames is None:    # not partial, but fully opaque:
            return                   # cannot really test even for existence
        struct = verifier.ffi._get_cached_btype(self)
        verifier.write('{')
        verifier.write('struct __aligncheck__ { char x; struct %s y; };' %
                       self.name)
        verifier.write(
            '__sameconstant__(sizeof(struct %s), %d)' % (
            self.name, verifier.ffi.sizeof(struct)))
        verifier.write(
            '__sameconstant__(offsetof(struct __aligncheck__, y), %d)' % (
            verifier.ffi.alignof(struct),))
        for fname, ftype, fbitsize in zip(self.fldnames, self.fldtypes,
                                          self.fldbitsize):
            if fbitsize >= 0:
                assert 0, "XXX: bitfield"
            verifier.write('__sameconstant__(offsetof(struct %s, %s), %d)' % (
                self.name, fname, verifier.ffi.offsetof(struct, fname)))
            # XXX gcc only!
            verifier.write('__sametype__(%s, typeof(((struct %s *)0)->%s))' % (
                ftype.get_c_name('** result'), self.name, fname))
        verifier.write('}')

    def verifier_decl_partial(self, verifier):
        assert self.fldnames is not None
        verifier.write('{')
        verifier.write('struct __aligncheck__ { char x; struct %s y; };' %
                       self.name)
        verifier.write('struct %s __test__;' % self.name)
        verifier.write_printf('BEGIN struct %s' % self.name)
        verifier.write_printf('SIZE %ld %ld',
                              '(long)sizeof(struct %s)' % self.name,
                              '(long)offsetof(struct __aligncheck__, y)')
        for fname, ftype, fbitsize in zip(self.fldnames, self.fldtypes,
                                          self.fldbitsize):
            if fbitsize < 0:
                verifier.write_printf('FIELD ' + fname + ' %ld %ld',
                                      '(long)offsetof(struct %s, %s)' %
                                      (self.name, fname),
                                      '(long)sizeof(__test__.%s)' % fname)
            else:
                assert 0, "XXX: bitfield"
        verifier.write_printf('END')
        verifier.write('}')

class UnionType(StructOrUnion):
    kind = 'union'

    def get_btype(self, ffi):
        return ffi._backend.new_union_type(self.name)
    
class EnumType(BaseType):
    _attrs_ = ('name',)

    def __init__(self, name, enumerators, enumvalues):
        self.name = name
        self.enumerators = enumerators
        self.enumvalues = enumvalues

    def get_c_name(self, replace_with=''):
        return 'enum %s%s' % (self.name, replace_with)

    def new_backend_type(self, ffi):
        return ffi._backend.new_enum_type(self.name, self.enumerators,
                                          self.enumvalues)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.