mirror of
https://github.com/appgurueu/modlib.git
synced 2024-11-22 07:13:45 +01:00
Add Lua log files
This commit is contained in:
parent
fc683ce28c
commit
f516cc6bb8
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
# generated by B3D test
|
# generated by B3D test
|
||||||
character.b3d.lua
|
character.b3d.lua
|
||||||
|
# generated by Lua logfile test
|
||||||
|
logfile.test.lua
|
17
Readme.md
17
Readme.md
@ -10,6 +10,23 @@ No dependencies. Licensed under the MIT License. Written by Lars Mueller aka LMD
|
|||||||
|
|
||||||
Mostly self-documenting code. Mod namespace is `modlib` or `_ml`, containing all variables & functions.
|
Mostly self-documenting code. Mod namespace is `modlib` or `_ml`, containing all variables & functions.
|
||||||
|
|
||||||
|
### Persistence
|
||||||
|
|
||||||
|
#### Lua Log Files
|
||||||
|
|
||||||
|
A data log file based on Lua statements. **Experimental.** High performance. Example from `test.lua`:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local logfile = persistence.lua_log_file.new(mod.get_resource"logfile.test.lua", {})
|
||||||
|
logfile:init()
|
||||||
|
logfile.root = {}
|
||||||
|
logfile:rewrite()
|
||||||
|
logfile:set_root({a = 1}, {b = 2, c = 3})
|
||||||
|
logfile:close()
|
||||||
|
logfile:init()
|
||||||
|
assert(table.equals(logfile.root, {[{a = 1}] = {b = 2, c = 3}}))
|
||||||
|
```
|
||||||
|
|
||||||
### Bluon
|
### Bluon
|
||||||
|
|
||||||
Binary Lua object notation. **Experimental.** Handling of subnormal numbers (very small floats) may be broken.
|
Binary Lua object notation. **Experimental.** Handling of subnormal numbers (very small floats) may be broken.
|
||||||
|
5
init.lua
5
init.lua
@ -50,7 +50,8 @@ for _, file in pairs{
|
|||||||
"ranked_set",
|
"ranked_set",
|
||||||
"binary",
|
"binary",
|
||||||
"b3d",
|
"b3d",
|
||||||
"bluon"
|
"bluon",
|
||||||
|
"persistence"
|
||||||
} do
|
} do
|
||||||
modules[file] = file
|
modules[file] = file
|
||||||
end
|
end
|
||||||
@ -77,7 +78,7 @@ end
|
|||||||
local load_module, get_resource, loadfile_exports
|
local load_module, get_resource, loadfile_exports
|
||||||
modlib = setmetatable({
|
modlib = setmetatable({
|
||||||
-- TODO bump on release
|
-- TODO bump on release
|
||||||
version = 62,
|
version = 63,
|
||||||
modname = minetest and minetest.get_current_modname(),
|
modname = minetest and minetest.get_current_modname(),
|
||||||
dir_delim = rawget(_G, "DIR_DELIM") or "/",
|
dir_delim = rawget(_G, "DIR_DELIM") or "/",
|
||||||
_RG = setmetatable({}, {
|
_RG = setmetatable({}, {
|
||||||
|
140
persistence.lua
Normal file
140
persistence.lua
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
lua_log_file = {}
|
||||||
|
local files = {}
|
||||||
|
local metatable = {__index = lua_log_file}
|
||||||
|
|
||||||
|
-- TODO register on shutdown
|
||||||
|
|
||||||
|
function lua_log_file.new(file_path, root)
|
||||||
|
local self = setmetatable({file_path = assert(file_path), root = root}, metatable)
|
||||||
|
files[self] = true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function lua_log_file:load()
|
||||||
|
-- Bytecode is blocked by the engine
|
||||||
|
local read = assert(loadfile(self.file_path))
|
||||||
|
local env = {}
|
||||||
|
setfenv(read, env)
|
||||||
|
read()
|
||||||
|
env.R = env.R or {{}}
|
||||||
|
self.reference_count = #env.R
|
||||||
|
self.root = env.R[1]
|
||||||
|
self.references = modlib.table.flip(env.R)
|
||||||
|
end
|
||||||
|
|
||||||
|
function lua_log_file:open()
|
||||||
|
self.file = io.open(self.file_path, "a+")
|
||||||
|
end
|
||||||
|
|
||||||
|
function lua_log_file:init()
|
||||||
|
if modlib.file.exists(self.file_path) then
|
||||||
|
self:load()
|
||||||
|
self:_rewrite()
|
||||||
|
self:open()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self:open()
|
||||||
|
self.root = {}
|
||||||
|
self:_write()
|
||||||
|
end
|
||||||
|
|
||||||
|
function lua_log_file:log(statement)
|
||||||
|
self.file:write(statement)
|
||||||
|
self.file:write"\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
function lua_log_file:flush()
|
||||||
|
self.file:flush()
|
||||||
|
end
|
||||||
|
|
||||||
|
function lua_log_file:close()
|
||||||
|
self.file:close()
|
||||||
|
self.file = nil
|
||||||
|
files[self] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_on_shutdown(function()
|
||||||
|
for self in pairs(files) do
|
||||||
|
self.file:close()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- TODO use shorthand notations
|
||||||
|
function lua_log_file:dump(value)
|
||||||
|
if value == nil then
|
||||||
|
return "nil"
|
||||||
|
end
|
||||||
|
if value == true then
|
||||||
|
return "true"
|
||||||
|
end
|
||||||
|
if value == false then
|
||||||
|
return "false"
|
||||||
|
end
|
||||||
|
if value ~= value then
|
||||||
|
-- nan
|
||||||
|
return "0/0"
|
||||||
|
end
|
||||||
|
local _type = type(value)
|
||||||
|
if _type == "number" then
|
||||||
|
return ("%.17g"):format(value)
|
||||||
|
end
|
||||||
|
if self.references[value] then
|
||||||
|
return "R[" .. self.references[value] .. "]"
|
||||||
|
end
|
||||||
|
self.reference_count = self.reference_count + 1
|
||||||
|
local reference = self.reference_count
|
||||||
|
self.references[value] = reference
|
||||||
|
local formatted
|
||||||
|
if _type == "string" then
|
||||||
|
formatted = ("%q"):format(value)
|
||||||
|
elseif _type == "table" then
|
||||||
|
local entries = {}
|
||||||
|
for _, value in ipairs(value) do
|
||||||
|
table.insert(entries, self:dump(value))
|
||||||
|
end
|
||||||
|
for key, value in pairs(value) do
|
||||||
|
if type(key) ~= "number" or key % 1 ~= 0 or key < 1 or key > #value then
|
||||||
|
table.insert(entries, "[" .. self:dump(key) .. "]=" .. self:dump(value))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
formatted = "{" .. table.concat(entries, ";") .. "}"
|
||||||
|
else
|
||||||
|
error("unsupported type: " .. _type)
|
||||||
|
end
|
||||||
|
local key = "R[" .. reference .."]"
|
||||||
|
self:log(key .. "=" .. formatted)
|
||||||
|
return key
|
||||||
|
end
|
||||||
|
|
||||||
|
function lua_log_file:set(table, key, value)
|
||||||
|
table[key] = value
|
||||||
|
if not self.references[table] then
|
||||||
|
error"orphan table"
|
||||||
|
end
|
||||||
|
self:log(self:dump(table) .. "[" .. self:dump(key) .. "]=" .. self:dump(value))
|
||||||
|
end
|
||||||
|
|
||||||
|
function lua_log_file:set_root(key, value)
|
||||||
|
return self:set(self.root, key, value)
|
||||||
|
end
|
||||||
|
|
||||||
|
function lua_log_file:_write()
|
||||||
|
self.references = {}
|
||||||
|
self.reference_count = 0
|
||||||
|
self:log"R={}"
|
||||||
|
self:dump(self.root)
|
||||||
|
end
|
||||||
|
|
||||||
|
function lua_log_file:_rewrite()
|
||||||
|
self.file = io.open(self.file_path, "w+")
|
||||||
|
self:_write()
|
||||||
|
self.file:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function lua_log_file:rewrite()
|
||||||
|
if self.file then
|
||||||
|
self.file:close()
|
||||||
|
end
|
||||||
|
self:_rewrite()
|
||||||
|
self.file = io.open(self.file_path, "a+")
|
||||||
|
end
|
9
test.lua
9
test.lua
@ -192,6 +192,15 @@ test_from_string("#333", 0x333333FF)
|
|||||||
test_from_string("#694269", 0x694269FF)
|
test_from_string("#694269", 0x694269FF)
|
||||||
test_from_string("#11223344", 0x11223344)
|
test_from_string("#11223344", 0x11223344)
|
||||||
|
|
||||||
|
local logfile = persistence.lua_log_file.new(mod.get_resource"logfile.test.lua", {})
|
||||||
|
logfile:init()
|
||||||
|
logfile.root = {}
|
||||||
|
logfile:rewrite()
|
||||||
|
logfile:set_root({a = 1}, {b = 2, c = 3})
|
||||||
|
logfile:close()
|
||||||
|
logfile:init()
|
||||||
|
assert(table.equals(logfile.root, {[{a = 1}] = {b = 2, c = 3}}))
|
||||||
|
|
||||||
-- in-game tests & b3d testing
|
-- in-game tests & b3d testing
|
||||||
local tests = {
|
local tests = {
|
||||||
-- depends on player_api
|
-- depends on player_api
|
||||||
|
Loading…
Reference in New Issue
Block a user