DKL9 GitList
Repositories
DKL9 home
memoire
Code
Commits
Branches
Tags
Search
Tree:
613c575
Branches
Tags
master
memoire
recrw.lua
Optimise Recfile output generation
John Smith
commited
613c575
at 2022-214 13:37:56
recrw.lua
Blame
History
Raw
--[[ a Recfile is (to simplify) a sequence of records a record is a sequence of fields a field is a label-value pair a label is an identifier a value is a string ]] --[[ converts text from a Recfile into a sequence of records returns (on success) a table of tables of pairs of labels and value-lists returns (on failure) nil ]] local function text2recs(str) local ret = {} local cr = {} local cl = nil local cv = nil -- Rec is line-based for line in str:gmatch "([^\n]*)\n" do -- continuation lines if cv and cv:sub(-1) == "\\" then cv = cv:sub(1, -2) .. line elseif line:sub(1, 1) == "+" then cv = cv .. "\n" .. line:gsub("^%+ ?", "") -- blank lines separate records elseif line:match "^%s*$" then -- add field to record if non-empty if cl then if cr[cl] then table.insert(cr[cl], cv) else cr[cl] = { cv } end end cl = nil cv = nil -- add record to return value if non-empty if next(cr) then table.insert(ret, cr) end cr = {} -- lines starting with # are comments elseif line:sub(1, 1) == "#" then if cl then if cr[cl] then table.insert(cr[cl], cv) else cr[cl] = { cv } end end cl = nil cv = nil -- new field else if cl then if cr[cl] then table.insert(cr[cl], cv) else cr[cl] = { cv } end end cl, cv = line:match "^([%a%%][%w_]*):%s(.*)" -- no match? bad field if not cl then return nil end end end if cl then if cr[cl] then table.insert(cr[cl], cv) else cr[cl] = { cv } end end if next(cr) then table.insert(ret, cr) end return ret end --[[ converts a sequence of records into text for a Recfile returns (on success) a string returns (on failure) nil ]] local function recs2text(recs, si, ei) local ret = "" si = si or 1 ei = ei or #recs --[[ use recursive (binary-splitting) string building this makes stuff way more efficient ]] if si == ei then for label, vl in pairs(recs[si]) do for j, value in ipairs(vl) do ret = ret .. string.format("\n%s: %s", label, tostring(value):gsub("\n", "\n+ ")) end end return ret .. "\n" else return recs2text(recs, si, (si + ei) // 2) .. recs2text(recs, (si + ei) // 2 + 1, ei) end end return { read = text2recs, write = recs2text }