This file is indexed.

/usr/share/lua/5.1/lgi/component.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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
------------------------------------------------------------------------------
--
--  LGI Basic repo type component implementation
--
--  Copyright (c) 2010, 2011, 2012, 2013 Pavel Holejsovsky
--  Licensed under the MIT license:
--  http://www.opensource.org/licenses/mit-license.php
--
------------------------------------------------------------------------------

local assert, pcall, setmetatable, getmetatable, pairs, next, rawget, rawset,
type, select, error
   = assert, pcall, setmetatable, getmetatable, pairs, next, rawget, rawset,
type, select, error

local table = require 'table'
local string = require 'string'
local core = require 'lgi.core'

-- Generic component metatable.  Component is any entity in the repo,
-- e.g. record, object, enum, etc.
local component = { mt = {} }

-- Creates new component table by cloning all contents and setting
-- Gets table for category of compound (i.e. _field of struct or _property
-- for class etc).  Installs metatable which performs on-demand lookup of
-- symbols.
function component.get_category(children, xform_value,
				xform_name, xform_name_reverse)
   -- Either none or both transform methods must be provided.
   assert(not xform_name or xform_name_reverse)

   -- Early shortcircuit; no elements, no table needed at all.
   if #children == 0 then return nil end

   -- Index contains array of indices which were still not retrieved
   -- from 'children' table, and table part contains name->index
   -- mapping.
   local index, mt = {}, {}
   for i = 1, #children do index[i] = i end

   -- Fully resolves the category (i.e. loads everything remaining to
   -- be loaded in given category) and disconnects on-demand loading
   -- metatable.
   local function resolve(category)
      -- Load al values from unknown indices.
      local ei, en, val
      local function xvalue(arg)
	 if not xform_value then return arg end
	 if arg then
	    local ok, res = pcall(xform_value, arg)
	    return ok and res
	 end
      end
      while #index > 0 do
	 ei = children[table.remove(index)]
	 val = xvalue(ei)
	 if val then
	    en = ei.name
	    en = not xform_name_reverse and en or xform_name_reverse(en)
	    if en then category[en] = val end
	 end
      end

      -- Load all known indices.
      for en, idx in pairs(index) do
	 val = xvalue(children[idx])
	 en = not xform_name_reverse and en or xform_name_reverse(en)
	 if en then category[en] = val end
      end

      -- Metatable is no longer needed, disconnect it.
      return setmetatable(category, nil)
   end

   function mt:__index(requested_name)
      -- Check if closure for fully resolving the category is needed.
      if requested_name == '_resolve' then return resolve end

      -- Transform name by transform function.
      local name = not xform_name and requested_name
	 or xform_name(requested_name)
      if not name then return end

      -- Check, whether we already know its index.
      local idx, val = index[name]
      if idx then
	 -- We know at least the index, so get info directly.
	 val = children[idx]
	 index[name] = nil
      else
	 -- Not yet, go through unknown indices and try to find the
	 -- name.
	 while #index > 0 do
	    idx = table.remove(index)
	    val = children[idx]
	    local en = val.name
	    if en == name then break end
	    val = nil
	    index[en] = idx
	 end
      end

      -- If there is nothing in the index, we can disconnect
      -- metatable, because everything is already loaded.
      if not next(index) then
	 setmetatable(self, nil)
      end

      -- Transform found value and store it into the category (self)
      -- table.
      if not val then return nil end
      if xform_value then val = xform_value(val) end
      if not val then return nil end
      self[requested_name] = val
      return val
   end
   return setmetatable({}, mt)
end

-- Creates new component table by cloning all contents and setting
-- categories table.
function component.mt:clone(type, categories)
   local new_component = {}
   for key, value in pairs(self) do new_component[key] = value end
   new_component._type = type
   if categories then
      table.insert(categories, 1, '_attribute')
      new_component._categories = categories
   end
   return new_component
end

-- __call implementation, uses _new method to create new instance of
-- component type.
function component.mt:__call(...)
   return self:_new(...)
end

-- Fully resolves the whole typetable, i.e. load all symbols normally
-- loaded on-demand at once.  Returns self, so that resolve can be
-- easily chained for the caller.
function component.mt:_resolve()
   local categories = self._categories or {}
   for i = 1, #categories do
      -- Invoke '_resolve' function for all category tables, if they have it.
      local category = rawget(self, categories[i])
      local resolve = type(category) == 'table' and category._resolve
      if resolve then resolve(category) end
   end
   return self
end

-- Implementation of _access method, which is called by _core when
-- repo instance is accessed for reading or writing.
function component.mt:_access(instance, symbol, ...)
   -- Invoke _element, which converts symbol to element and category.
   local element, category = self:_element(instance, symbol)
   if not element then
      error(("%s: no `%s'"):format(self._name, tostring(symbol)), 3)
   end

   -- Get category handler to be used, and invoke it.
   if category then
      local handler = self['_access' .. category]
      if handler then return handler(self, instance, element, ...) end
   end

   -- If specific accessor does not exist, consider the element to be
   -- 'static const' attribute of the class.  This works well for
   -- methods, constants and assorted other elements added manually
   -- into the class by overrides.
   if select('#', ...) > 0 then
      error(("%s: `%s' is not writable"):format(self._name, symbol), 4)
   end
   return element
end

-- Keyword translation dictionary.  Used for translating Lua keywords
-- which might appear as symbols in typelibs into Lua-neutral identifiers.
local keyword_dictionary = {
   _end = 'end', _do = 'do', _then = 'then', _elseif = 'elseif', _in = 'in',
   _local = 'local', _function = 'function', _nil = 'nil', _false = 'false',
   _true = 'true', _and = 'and', _or = 'or', _not = 'not',
}

-- Retrieves (element, category) pair from given componenttable and
-- instance for given symbol.
function component.mt:_element(instance, symbol, origin)
   -- This generic version can work only with strings.  Refuse
   -- everything other, hoping that some more specialized _element
   -- implementation will handle it.
   if type(symbol) ~= 'string' then return end

   -- Check keyword translation dictionary.  If the symbol can be
   -- found there, try to lookup translated symbol.
   symbol = keyword_dictionary[symbol] or symbol

   -- Check whether symbol is directly accessible in the component.
   local element = rawget(self, symbol)
   if element then return element end

   -- Check whether symbol is accessible in cached directory of the
   -- component, packed as element value and category
   local cached = rawget(self, '_cached')
   if cached then
      element = cached[symbol]
      if element then return element[1], element[2] end
   end

   -- Decompose symbol name, in case that it contains category prefix
   -- (e.g. '_field_name' when requesting explicitely field called
   -- name).
   local category, name = string.match(symbol, '^(_.-)_(.*)$')
   if category and name and category ~= '_access' then
      -- Check requested category.
      local cat = rawget(self, category)
      element = cat and cat[name]
   elseif string.sub(symbol, 1, 1) ~= '_' then
      -- Check all available categories.
      local categories = self._categories or {}
      for i = 1, #categories do
	 category = categories[i]
	 local cat = rawget(self, category)
	 element = cat and cat[symbol]
	 if element then break end
      end
   end
   if element then
      -- Make sure that table-based attributes have symbol name, so
      -- that potential errors contain the name of referenced
      -- attribute.
      if type(element) == 'table' and category == '_attribute' then
	 element._name = element._name or symbol
      end

      -- If possible, cache the element in root table.
      if not category or not (origin or self)['_access' .. category] then
	 -- No category or no special category handler is present,
	 -- store it directly, which results in fastest access.  This
	 -- is most typical for methods.
	 self[symbol] = element
      else
	 -- Store into _cached table, because we have to preserve the
	 -- category.
	 if not cached then
	    cached = {}
	    self._cached = cached
	 end
	 cached[symbol] = { element, category }
      end

      return element, category
   end
end

-- __index implementation, uses _element method to perform lookup.
function component.mt:__index(key)
   -- First try to invoke our own _element method.
   local _element, mt = rawget(self, '_element')
   if not _element then
      mt = getmetatable(self)
      _element = rawget(mt, '_element')
   end
   local value, category = _element(self, nil, key)
   if value then
      if category then
	 -- Mangle the result by type-specific '_index_<category>'
	 -- method, if present.
	 local index_name = '_index' .. category
	 local index = rawget(self, index_name)
	 if not index then
	    if not mt then mt = getmetatable(self) end
	    if mt then index = rawget(mt, index_name) end
	 end
	 if index then value = index(self, value) end
      end
      return value
   end

   -- If not found as object element, examine the metatable itself.
   return rawget(mt or getmetatable(self), key)
end

-- Implementation of attribute accessor.  Attribute is either function
-- to be directly invoked, or table containing set and get functions.
function component.mt:_access_attribute(instance, element, ...)
   -- If element is a table, assume that this table contains 'get' and
   -- 'set' methods.  Dispatch to them, and error out if they are
   -- missing.
   if type(element) == 'table' then
      local mode = select('#', ...) == 0 and 'get' or 'set'
      if not element[mode] then
	 error(("%s: cannot %s `%s'"):format(
		  self._name, mode == 'get' and 'read' or 'write',
		  element._name or '<unknown>'), 5)
      end
      element = element[mode]
   end

   -- Invoke attribute access function.
   return element(instance, ...)
end

-- Pretty prints type name
function component.mt:__tostring()
   return self._name
end

-- Creates new component and sets up common parts according to given
-- info.
function component.create(info, mt, name)
   local gtype
   if core.gi.isinfo(info) then
      gtype = info.gtype
      name = info.fullname
   else
      gtype = info and core.gtype(info)
   end

   -- Fill in meta of the compound.
   local component = { _name = name }
   if gtype then
      -- Bind component in repo, make the relation using GType.
      component._gtype = gtype
      core.index[gtype] = component
   end
   return setmetatable(component, mt)
end

return component