file_lfs.lua 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. local FILE_READ_CHUNK = 1024
  2. local _file = file
  3. local file_exists, file_open, file_getcontents, file_rename, file_stat, file_putcontents, file_close, file_list =
  4. _file.exists, _file.open, _file.getcontents, _file.rename, _file.stat, _file.putcontents, _file.close, _file.list
  5. local node_LFS_resource = node.LFS.resource or function(filename) if filename then return else return {} end end -- luacheck: ignore
  6. local file_lfs = {}
  7. local current_file_lfs
  8. local function file_lfs_create (filename)
  9. local content = node_LFS_resource(filename)
  10. local pos = 1
  11. local read = function (_, n_or_char)
  12. local p1, p2
  13. n_or_char = n_or_char or FILE_READ_CHUNK
  14. if type(n_or_char) == "number" then
  15. p1, p2 = pos, pos + n_or_char - 1
  16. elseif type(n_or_char) == "string" and #n_or_char == 1 then
  17. p1 = pos
  18. local _
  19. _, p2 = content:find(n_or_char, p1, true)
  20. if not p2 then p2 = p1 + FILE_READ_CHUNK - 1 end
  21. else
  22. error("invalid parameter")
  23. end
  24. if p2 - p1 > FILE_READ_CHUNK then p2 = pos + FILE_READ_CHUNK - 1 end
  25. if p1>#content then return end
  26. pos = p2+1
  27. return content:sub(p1, p2)
  28. end
  29. local seek = function (_, whence, offset)
  30. offset = offset or 0
  31. local len = #content + 1 -- position starts at 1
  32. if whence == "set" then
  33. pos = offset + 1 -- 0 offset means position 1
  34. elseif whence == "cur" then
  35. pos = pos + offset
  36. elseif whence == "end" then
  37. pos = len + offset
  38. elseif whence then -- not nil not one of above
  39. return -- on error return nil
  40. end
  41. local pos_ok = true
  42. if pos < 1 then pos = 1; pos_ok = false end
  43. if pos > len then pos = len; pos_ok = false end
  44. return pos_ok and pos - 1 or nil
  45. end
  46. local obj = {}
  47. obj.read = read
  48. obj.readline = function(self) return read(self, "\n") end
  49. obj.seek = seek
  50. obj.close = function() current_file_lfs = nil end
  51. setmetatable(obj, {
  52. __index = function (_, k)
  53. return function () --...)
  54. error (("LFS file unsupported function '%s'") % tostring(k))
  55. --return _file[k](...)
  56. end
  57. end
  58. })
  59. return obj
  60. end
  61. file_lfs.exists = function (filename)
  62. return (node_LFS_resource(filename) ~= nil) or file_exists(filename)
  63. end
  64. file_lfs.open = function (filename, mode)
  65. mode = mode or "r"
  66. if file_exists(filename) then
  67. return file_open(filename, mode)
  68. elseif node_LFS_resource(filename) then
  69. if mode ~= "r" and mode:find("^[rwa]%+?$") then
  70. -- file does not exist in SPIFFS but exists in LFS -> copy to SPIFFS
  71. file_putcontents(filename, node_LFS_resource(filename))
  72. return file_open(filename, mode)
  73. else -- "r" or anything else
  74. current_file_lfs = file_lfs_create (filename)
  75. return current_file_lfs
  76. end
  77. else
  78. return file_open(filename, mode)
  79. end
  80. end
  81. file_lfs.close = function (...)
  82. current_file_lfs = nil
  83. return file_close(...)
  84. end
  85. file_lfs.getcontents = function(filename)
  86. if file_exists(filename) then
  87. return file_getcontents(filename)
  88. else
  89. return node_LFS_resource(filename) or file_getcontents(filename)
  90. end
  91. end
  92. file_lfs.rename = function(oldname, newname)
  93. if node_LFS_resource(oldname) ~= nil and not file_exists(oldname) then
  94. -- error "LFS file cannot be renamed"
  95. return false
  96. else
  97. return file_rename(oldname, newname)
  98. end
  99. end
  100. file_lfs.stat = function(filename)
  101. if node_LFS_resource(filename) ~= nil and not file_exists(filename) then
  102. return {
  103. name = filename,
  104. size = #node_LFS_resource(filename),
  105. time = {day = 1, hour = 0, min = 0, year = 1970, sec = 0, mon = 1},
  106. is_hidden = false, is_rdonly = true, is_dir = false, is_arch = false, is_sys = false, is_LFS = true
  107. }
  108. else
  109. return file_stat(filename)
  110. end
  111. end
  112. file_lfs.list = function (pattern, SPIFFs_only)
  113. local filelist = file_list(pattern)
  114. if not SPIFFs_only then
  115. local fl = node_LFS_resource()
  116. if fl then
  117. for _, f in ipairs(fl) do
  118. if not(filelist[f]) and (not pattern or f:match(pattern)) then
  119. filelist[f] = #node_LFS_resource(f)
  120. end
  121. end
  122. end
  123. end
  124. return filelist
  125. end
  126. setmetatable(file_lfs, {
  127. __index = function (_, k)
  128. return function (...)
  129. local t = ...
  130. if type(t) == "table" then
  131. return t[k](...)
  132. elseif not t and current_file_lfs then
  133. return current_file_lfs[k](...)
  134. else
  135. return _file[k](...)
  136. end
  137. end
  138. end
  139. })
  140. print ("[file_lfs] LFS file routines loaded")
  141. return file_lfs