Operating system for OpenComputers
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

172 lignes
3.9KB

  1. buffer = {}
  2. local metatable = {
  3. __index = buffer,
  4. __metatable = "file",
  5. __close = buffer.close
  6. }
  7. function buffer.new(mode, stream)
  8. local result = {
  9. closed = false,
  10. tty = false,
  11. mode = {},
  12. stream = stream,
  13. bufferRead = "",
  14. bufferWrite = "",
  15. bufferSize = math.max(512, math.min(8 * 1024, computer.freeMemory() / 8)),
  16. bufferMode = "full",
  17. readTimeout = math.huge,
  18. }
  19. mode = mode or "r"
  20. for i = 1, mode:len() do
  21. result.mode[mode:sub(i, i)] = true
  22. end
  23. -- when stream closes, result should close first
  24. -- when result closes, stream should close after
  25. -- when stream closes, it is removed from the proc
  26. stream.close = setmetatable({close = stream.close,parent = result},{__call = buffer.close})
  27. return setmetatable(result, metatable)
  28. end
  29. function buffer:close()
  30. -- self is either the buffer, or the stream.close callable
  31. local meta = getmetatable(self)
  32. if meta == metatable.__metatable then
  33. return self.stream:close()
  34. end
  35. local parent = self.parent
  36. if parent.mode.w or parent.mode.a then
  37. parent:flush()
  38. end
  39. parent.closed = true
  40. return self.close(parent.stream)
  41. end
  42. function buffer:flush()
  43. if #self.bufferWrite > 0 then
  44. local tmp = self.bufferWrite
  45. self.bufferWrite = ""
  46. local result, reason = self.stream:write(tmp)
  47. if not result then
  48. return nil, reason or "bad file descriptor"
  49. end
  50. end
  51. return self
  52. end
  53. function buffer:lines(...)
  54. local args = table.pack(...)
  55. return function()
  56. local result = table.pack(self:read(table.unpack(args, 1, args.n)))
  57. if not result[1] and result[2] then
  58. error(result[2])
  59. end
  60. return table.unpack(result, 1, result.n)
  61. end
  62. end
  63. local function readChunk(self)
  64. if computer.uptime() > self.timeout then
  65. error("timeout")
  66. end
  67. local result, reason = self.stream:read(math.max(1,self.bufferSize))
  68. if result then
  69. self.bufferRead = self.bufferRead .. result
  70. return self
  71. else -- error or eof
  72. return result, reason
  73. end
  74. end
  75. function buffer:readLine(chop, timeout)
  76. self.timeout = timeout or (computer.uptime() + self.readTimeout)
  77. local start = 1
  78. while true do
  79. local buf = self.bufferRead
  80. local i = buf:find("[\r\n]", start)
  81. local c = i and buf:sub(i,i)
  82. local is_cr = c == "\r"
  83. if i and (not is_cr or i < #buf) then
  84. local n = buf:sub(i+1,i+1)
  85. if is_cr and n == "\n" then
  86. c = c .. n
  87. end
  88. local result = buf:sub(1, i - 1) .. (chop and "" or c)
  89. self.bufferRead = buf:sub(i + #c)
  90. return result
  91. else
  92. start = #self.bufferRead - (is_cr and 1 or 0)
  93. local result, reason = readChunk(self)
  94. if not result then
  95. if reason then
  96. return result, reason
  97. else -- eof
  98. result = #self.bufferRead > 0 and self.bufferRead or nil
  99. self.bufferRead = ""
  100. return result
  101. end
  102. end
  103. end
  104. coroutine.yield()
  105. end
  106. end
  107. function buffer:read(...)
  108. if not self.mode.r then
  109. return nil, "read mode was not enabled for this stream"
  110. end
  111. if self.mode.w or self.mode.a then
  112. self:flush()
  113. end
  114. if select("#", ...) == 0 then
  115. return self:readLine(true)
  116. end
  117. return self:formatted_read(readChunk, ...)
  118. end
  119. function buffer:setvbuf(mode, size)
  120. mode = mode or self.bufferMode
  121. size = size or self.bufferSize
  122. assert(mode == "no" or mode == "full" or mode == "line",
  123. "bad argument #1 (no, full or line expected, got " .. tostring(mode) .. ")")
  124. assert(mode == "no" or type(size) == "number",
  125. "bad argument #2 (number expected, got " .. type(size) .. ")")
  126. self.bufferMode = mode
  127. self.bufferSize = size
  128. return self.bufferMode, self.bufferSize
  129. end
  130. function buffer:write(...)
  131. if self.closed then
  132. return nil, "bad file descriptor"
  133. end
  134. if not self.mode.w and not self.mode.a then
  135. return nil, "write mode was not enabled for this stream"
  136. end
  137. local args = table.pack(...)
  138. for i = 1, args.n do
  139. if type(args[i]) == "number" then
  140. args[i] = tostring(args[i])
  141. end
  142. checkArg(i, args[i], "string")
  143. end
  144. for i = 1, args.n do
  145. local arg = args[i]
  146. local result, reason
  147. result, reason = self.stream:write(arg)
  148. if not result then
  149. return nil, reason
  150. end
  151. end
  152. return self
  153. end