Expands on Recfile read/write library
John Smith

John Smith commited on 2021-309 23:32:01
Showing 1 changed files, with 43 additions and 9 deletions.


`recparse.lua` has been moved to `recrw.lua` to better reflect its function:
it implements conversion from an internal representation to Rec,
not just the other way around.

The internal representation has changed from lists of label-value pairs
to lists pairing labels with lists of values,
to accommodate the duplication allowed in Rec.
... ...
@@ -8,7 +8,7 @@
8 8
 
9 9
 --[[
10 10
     maps text from a Recfile into a sequence of records
11
-    returns (on success) a table of tables of tables of two strings (label and value)
11
+    returns (on success) a table of tables of label-value-list pairs
12 12
     returns (on failure) nil
13 13
 ]]
14 14
 local function text2recs(str)
... ...
@@ -27,7 +27,11 @@ local function text2recs(str)
27 27
         elseif line:match "^%s*$" then
28 28
             -- add field to record if non-empty
29 29
             if cl then
30
-                table.insert(cr, { k = cl, v = cv })
30
+                if cr[cl] then
31
+                    table.insert(cr[cl], cv)
32
+                else
33
+                    cr[cl] = { cv }
34
+                end
31 35
             end
32 36
             cl = nil
33 37
             cv = nil
... ...
@@ -39,24 +43,34 @@ local function text2recs(str)
39 43
         -- lines starting with # are comments
40 44
         elseif line:sub(1, 1) == "#" then
41 45
             if cl then
42
-                table.insert(cr, { k = cl, v = cv })
46
+                if cr[cl] then
47
+                    table.insert(cr[cl], cv)
48
+                else
49
+                    cr[cl] = { cv }
50
+                end
43 51
             end
44 52
             cl = nil
45 53
             cv = nil
46 54
         -- new field
47 55
         else
48 56
             if cl then
49
-                table.insert(cr, { k = cl, v = cv })
57
+                if cr[cl] then
58
+                    table.insert(cr[cl], cv)
59
+                else
60
+                    cr[cl] = { cv }
61
+                end
50 62
             end
51 63
             cl, cv = line:match "^([%a%%][%w_]*):%s(.*)"
52 64
             -- no match? bad field
53
-            if not cl then
54
-                return nil
55
-            end
65
+            if not cl then return nil end
56 66
         end
57 67
     end
58 68
     if cl then
59
-        table.insert(cr, { k = cl, v = cv })
69
+        if cr[cl] then
70
+            table.insert(cr[cl], cv)
71
+        else
72
+            cr[cl] = { cv }
73
+        end
60 74
     end
61 75
     if next(cr) then
62 76
         table.insert(ret, cr)
... ...
@@ -64,4 +78,24 @@ local function text2recs(str)
64 78
     return ret
65 79
 end
66 80
 
67
-return text2recs
81
+--[[
82
+    maps a sequence of records into text for a Recfile
83
+    returns (on success) a string
84
+    returns (on failure) nil
85
+]]
86
+local function recs2text(recs)
87
+    local ret = ""
88
+    -- go through records
89
+    for i, rec in ipairs(recs) do
90
+        for label, vl in pairs(rec) do
91
+            for j, value in ipairs(vl) do
92
+                ret = ret .. string.format("\n%s: %s", label, value:gsub("\n", "\n+ "))
93
+            end
94
+        end
95
+        ret = ret .. "\n"
96
+    end
97
+    return ret
98
+end
99
+
100
+
101
+return { read = text2recs, write = recs2text }
68 102