/usr/share/lua/5.1/lgi/ffi.lua is in lua-lgi 0.9.0.20151101.git.885af4-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | ------------------------------------------------------------------------------
--
-- LGI Helpers for custom FFI definitions
--
-- Copyright (c) 2012 Pavel Holejsovsky
-- Licensed under the MIT license:
-- http://www.opensource.org/licenses/mit-license.php
--
------------------------------------------------------------------------------
local pairs, ipairs, setmetatable, getmetatable
= pairs, ipairs, setmetatable, getmetatable
local math = require 'math'
local core = require 'lgi.core'
local gi = core.gi
local component = require 'lgi.component'
local enum = require 'lgi.enum'
local record = require 'lgi.record'
local ffi = {}
local gobject = gi.require('GObject')
local glib = gi.require('GLib')
-- Gather all basic types. We have to 'steal' them from well-known
-- declarations, because girepository API does not allow synthesizing
-- GIBaseInfo instances from the air.
ffi.types = {
void = gobject.Callback.return_type,
boolean = glib.Variant.methods.get_boolean.return_type,
int8 = gobject.ParamSpecChar.fields.minimum.typeinfo,
uint8 = gobject.ParamSpecUChar.fields.minimum.typeinfo,
int16 = glib.Variant.methods.get_int16.return_type,
uint16 = glib.Variant.methods.get_uint16.return_type,
int32 = glib.Variant.methods.get_int32.return_type,
uint32 = glib.Variant.methods.get_uint32.return_type,
int64 = glib.Variant.methods.get_int64.return_type,
uint64 = glib.Variant.methods.get_uint64.return_type,
int = gobject.ParamSpecEnum.fields.default_value.typeinfo,
uint = gobject.ParamSpecFlags.fields.default_value.typeinfo,
long = gobject.ParamSpecLong.fields.default_value.typeinfo,
ulong = gobject.ParamSpecULong.fields.default_value.typeinfo,
float = gobject.ParamSpecFloat.fields.default_value.typeinfo,
double = gobject.ParamSpecDouble.fields.default_value.typeinfo,
utf8 = gobject.ParamSpecString.fields.default_value.typeinfo,
filename = glib.file_get_contents.args[1].typeinfo,
GType = gobject.ParamSpecGType.fields.is_a_type.typeinfo,
GStrv = glib.KeyFile.methods.get_groups.return_type,
GDestroyNotify = glib.Hook.fields.destroy.typeinfo,
ptr = glib.CompareDataFunc.args[1].typeinfo,
}
for name, alias in pairs {
char = 'int8', uchar = 'uint8', short = 'int16', ushort = 'uint16'
} do
ffi.types[name] = ffi.types[alias]
end
-- Gets gtype from specified resolved and _get_type function name.
function ffi.load_gtype(resolver, get_type_name)
local addr = resolver[get_type_name]
if not addr then return nil, ("`%s' not found"):format(get_type_name) end
local get_gtype = core.callable.new(
{ name = get_type_name, addr = addr, ret = ffi.types.GType })
return get_gtype()
end
-- Creates new enum/flags table with all values from specified gtype.
function ffi.load_enum(gtype, name)
local GObject = core.repo.GObject
local is_flags = GObject.Type.is_a(gtype, GObject.Type.FLAGS)
local enum_component = component.create(
gtype, is_flags and enum.bitflags_mt or enum.enum_mt, name)
local type_class = GObject.TypeClass.ref(gtype)
local enum_class = core.record.cast(
type_class, is_flags and GObject.FlagsClass or GObject.EnumClass)
for i = 0, enum_class.n_values - 1 do
local val = core.record.fromarray(enum_class.values, i)
enum_component[core.upcase(val.value_nick):gsub('%-', '_')] = val.value
end
type_class:unref()
return enum_component
end
-- Aligns offset to specified alignment.
local function align(offset, align)
return math.modf((offset + align - 1) / align) * align
end
-- Creates record from the table of the field definitions.
function ffi.load_fields(rec, defs)
rec._field = {}
local offset = 0
local max_align = 1
local max_size = 0
for _, def in ipairs(defs) do
local field = {}
-- Get size and alignment of this field.
local size, alignment
if gi.isinfo(def[2]) then
field[2] = 0
if def[2].tag == 'interface' then
local ii = def[2].interface
if ii.type == 'enum' or ii.type == 'flags' then
size, alignment = core.marshal.typeinfo(ii.typeinfo)
elseif ii.type == 'struct' or ii.type == 'union' then
size, alignment = core.marshal.typeinfo(ffi.types.ptr)
if not ii.is_pointer then
-- Alignment is tricky; ideally we should go through
-- the record and find alignment according to the
-- largest alignments of the fields, but now we just
-- punt and use 'ptr' as alignment. But this might
-- be incorrect in case that doubles are used on 32b
-- platform.
-- Get size from the record descriptor.
size = core.repotype(ii)._size
end
end
else
-- Basic type.
size, alignment = core.marshal.typeinfo(def[2])
end
else
-- Either record or enum, decide according to repotable.
local repotype = getmetatable(def[2])._type
if repotype == 'struct' or repotype == 'union' then
field[2] = 1
size, alignment = core.marshal.typeinfo(ffi.types.ptr)
if not def.ptr then
field[2] = 2
size = def[2]._size
end
elseif repotype == 'enum' or repotype == 'flags' then
field[2] = 3
field[4] = def.type or ffi.types.int
size, alignment = core.marshal.typeinfo(field[4])
end
end
-- Adjust offset according to the alignment.
offset = align(offset, alignment)
max_align = math.max(max_align, alignment)
-- Create and add field definition.
field[1] = offset
field[3] = def[2]
rec._field[def[1]] = field
if getmetatable(rec)._type == 'union' then
-- Remember largest size as the size of the union.
max_size = math.max(max_size, align(size, alignment))
else
-- Move offset after the field.
offset = offset + size
end
end
-- Store the total size of the record.
rec._size = ((getmetatable(rec)._type == 'union') and max_size
or align(offset, max_align))
end
return ffi
|