Operating system for OpenComputers
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

146 рядки
4.6KB

  1. -- serialization lib borrowed from OpenOS
  2. local serialization = {}
  3. -- delay loaded tables fail to deserialize cross [C] boundaries (such as when having to read files that cause yields)
  4. local local_pairs = function(tbl)
  5. local mt = getmetatable(tbl)
  6. return (mt and mt.__pairs or pairs)(tbl)
  7. end
  8. -- Important: pretty formatting will allow presenting non-serializable values
  9. -- but may generate output that cannot be unserialized back.
  10. function serialization.serialize(value, pretty) -- serialize *value* into a string, optionally in a nicely formatted manner when *pretty* is set
  11. local kw = {["and"]=true, ["break"]=true, ["do"]=true, ["else"]=true,
  12. ["elseif"]=true, ["end"]=true, ["false"]=true, ["for"]=true,
  13. ["function"]=true, ["goto"]=true, ["if"]=true, ["in"]=true,
  14. ["local"]=true, ["nil"]=true, ["not"]=true, ["or"]=true,
  15. ["repeat"]=true, ["return"]=true, ["then"]=true, ["true"]=true,
  16. ["until"]=true, ["while"]=true}
  17. local id = "^[%a_][%w_]*$"
  18. local ts = {}
  19. local result_pack = {}
  20. local function recurse(current_value, depth)
  21. local t = type(current_value)
  22. if t == "number" then
  23. if current_value ~= current_value then
  24. table.insert(result_pack, "0/0")
  25. elseif current_value == math.huge then
  26. table.insert(result_pack, "math.huge")
  27. elseif current_value == -math.huge then
  28. table.insert(result_pack, "-math.huge")
  29. else
  30. table.insert(result_pack, tostring(current_value))
  31. end
  32. elseif t == "string" then
  33. table.insert(result_pack, (string.format("%q", current_value):gsub("\\\n","\\n")))
  34. elseif
  35. t == "nil" or
  36. t == "boolean" or
  37. pretty and (t ~= "table" or (getmetatable(current_value) or {}).__tostring) then
  38. table.insert(result_pack, tostring(current_value))
  39. elseif t == "table" then
  40. if ts[current_value] then
  41. if pretty then
  42. table.insert(result_pack, "recursion")
  43. return
  44. else
  45. error("tables with cycles are not supported")
  46. end
  47. end
  48. ts[current_value] = true
  49. local f
  50. if pretty then
  51. local ks, sks, oks = {}, {}, {}
  52. for k in local_pairs(current_value) do
  53. if type(k) == "number" then
  54. table.insert(ks, k)
  55. elseif type(k) == "string" then
  56. table.insert(sks, k)
  57. else
  58. table.insert(oks, k)
  59. end
  60. end
  61. table.sort(ks)
  62. table.sort(sks)
  63. for _, k in ipairs(sks) do
  64. table.insert(ks, k)
  65. end
  66. for _, k in ipairs(oks) do
  67. table.insert(ks, k)
  68. end
  69. local n = 0
  70. f = table.pack(function()
  71. n = n + 1
  72. local k = ks[n]
  73. if k ~= nil then
  74. return k, current_value[k]
  75. else
  76. return nil
  77. end
  78. end)
  79. else
  80. f = table.pack(local_pairs(current_value))
  81. end
  82. local i = 1
  83. local first = true
  84. table.insert(result_pack, "{")
  85. for k, v in table.unpack(f) do
  86. if not first then
  87. table.insert(result_pack, ",")
  88. if pretty then
  89. table.insert(result_pack, "\n" .. string.rep(" ", depth))
  90. end
  91. end
  92. first = nil
  93. local tk = type(k)
  94. if tk == "number" and k == i then
  95. i = i + 1
  96. recurse(v, depth + 1)
  97. else
  98. if tk == "string" and not kw[k] and string.match(k, id) then
  99. table.insert(result_pack, k)
  100. else
  101. table.insert(result_pack, "[")
  102. recurse(k, depth + 1)
  103. table.insert(result_pack, "]")
  104. end
  105. table.insert(result_pack, "=")
  106. recurse(v, depth + 1)
  107. end
  108. end
  109. ts[current_value] = nil -- allow writing same table more than once
  110. table.insert(result_pack, "}")
  111. else
  112. error("unsupported type: " .. t)
  113. end
  114. end
  115. recurse(value, 1)
  116. local result = table.concat(result_pack)
  117. if pretty then
  118. local limit = type(pretty) == "number" and pretty or 10
  119. local truncate = 0
  120. while limit > 0 and truncate do
  121. truncate = string.find(result, "\n", truncate + 1, true)
  122. limit = limit - 1
  123. end
  124. if truncate then
  125. return result:sub(1, truncate) .. "..."
  126. end
  127. end
  128. return result
  129. end
  130. function serialization.unserialize(data) -- returns the data contained in serialized string *data*
  131. local result, reason = load("return " .. data, "=data", nil, {math={huge=math.huge}})
  132. if not result then
  133. return nil, reason
  134. end
  135. local ok, output = pcall(result)
  136. if not ok then
  137. return nil, output
  138. end
  139. return output
  140. end
  141. return serialization