I_M_CODER

vdevice.lua

Nov 12th, 2016
96
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local component = require("component");
  2.  
  3. local vdevice_lib = {};
  4. vdevice_lib.VOnly = 2; --только виртуальные компоненты
  5. vdevice_lib.ROnly = 1; --только реальные компоненты
  6.  
  7. local VDEVICE = {};
  8. local TYPES   = {};
  9. local MAX     = 1;
  10.  
  11. local function _IF(f,a,b)
  12.  if f then return a; end; return b;
  13. end;
  14.  
  15. --переопределение метода list, параметр av определяет фильтр
  16. --виртуальные|не виртуальные|оба типа(если значение не равно не одной из констант)
  17. local _list = component.list;
  18. component.list = function(ttype,f,av)
  19.  local inc = _list(ttype,f);
  20.  local i = 0;
  21.  return function()
  22.   local adrs,name = nil,nil;
  23.   if i == 0 and av ~= 2 then
  24.    adrs,name = inc();
  25.    if not(adrs) or not(name) then i = 1; end;
  26.   end;
  27.   if i > 0 and i <= MAX and av ~= 1 then
  28.    while true do
  29.     if VDEVICE[i] and (type(ttype) ~= "string" or VDEVICE[i].type:sub(1,ttype:len()) == ttype) then
  30.      adrs = '#'..i; name = VDEVICE[i].type; i = i + 1; break;
  31.     end;
  32.     i = i + 1;
  33.     if i > MAX then i = -1; break; end;
  34.    end;
  35.   end;
  36.   return adrs,name;
  37.  end;
  38. end;
  39.  
  40. --переопределеие метода invoke
  41. local _invoke = component.invoke;
  42. component.invoke = function(adrs,op,...)
  43.  checkArg(1,adrs,"string");
  44.  checkArg(2,op  ,"string");
  45.  if adrs:sub(1,1) == '#' then
  46.   local vd = VDEVICE[tonumber(adrs:sub(2,adrs:len()))];
  47.   if vd == nil then error("no such virtual component"); end;
  48.   if type(vd.methods[op]) ~= "function" then error("no such virtual method"); end;
  49.   return vd.methods[op](...);
  50.  end;
  51.  return _invoke(adrs,op,...);
  52. end;
  53.  
  54. --переопределение метода proxy
  55. local _proxy = component.proxy;
  56. component.proxy = function(adrs)
  57.  checkArg(1,adrs,"string");
  58.  if adrs:sub(1,1) == '#' then
  59.   local vd = VDEVICE[tonumber(adrs:sub(2,adrs:len()))];
  60.   return setmetatable({},{__index = vd.methods});
  61.  end;
  62.  return _proxy(adrs);
  63. end;
  64.  
  65. --переопределение метода type
  66. local _type = component.type;
  67. component.type = function(adrs)
  68.  checkArg(1,adrs,"string");
  69.  if adrs:sub(1,1) == '#' then
  70.   local vd = VDEVICE[tonumber(adrs:sub(2,adrs:len()))];
  71.   return vd.type;
  72.  end;
  73.  return _type(adrs);
  74. end;
  75.  
  76. --метод для добавление нового виртуального устройства,
  77. --в качестве параметров требудет тип и теблицу с методами
  78. --табица должна содержать поля в виде function с ключами string
  79. --в случаи удачного добавления возвращает адресс устройства
  80. --в случаи неудачи - nil и причину
  81. function vdevice_lib.addVDevice(ttype,tmethods)
  82.  checkArg(1,ttype   ,"string");
  83.  checkArg(2,tmethods, "table");
  84.  for k,d in pairs(tmethods) do
  85.   if type(k) ~= "string" or type(d) ~= "function" then return nil,"invalid methods"; end;
  86.   os.sleep(0.005);
  87.  end;
  88.  local i = 0;
  89.  while true do
  90.   os.sleep(0.005);
  91.   i = i + 1;
  92.   if VDEVICE[i] == nil then break; end;
  93.  end;
  94.  VDEVICE[i] = {
  95.   methods = tmethods,
  96.   type    = ttype;
  97.  };
  98.  if TYPES[ttype] == nil then TYPES[ttype] = {}; end;
  99.  table.insert(TYPES[ttype],i);
  100.  if i > MAX then MAX = i; end;
  101.  return '#'..i;
  102. end;
  103.  
  104. --метод для удаления виртуального устройства,
  105. --в качестве параметра требуется адресс устройства
  106. --в случаи удачного удаления вернет true
  107. --в случаи неудачи вернет nil
  108. function vdevice_lib.delVDevice(adrs)
  109.  checkArg(1,adrs,"string");
  110.  if adrs:sub(1,1) ~= '#' then return nil,"invalid address"; end;
  111.  local ind = tonumber(adrs:sub(2,adrs:len()));
  112.  local vd = VDEVICE[ind];
  113.  if vd == nil then return nil,"no such virtual component"; end;
  114.  --в данном цикле нет прерывания ОС, так-как это может негативно сказатся на результате операции
  115.  for i = 1, #(TYPES[vd.type]) do
  116.   if TYPES[vd.type][i] == ind then table.remove(TYPES[vd.type],i); break; end;
  117.  end;
  118.  VDEVICE[ind] = nil;
  119.  local i = MAX;
  120.  while true do
  121.   if VDEVICE[i] or i == 1 then break; end;
  122.   i = i + 1;
  123.  end;
  124.  MAX = i;
  125.  return true;
  126. end;
  127.  
  128. return vdevice_lib;
RAW Paste Data