summaryrefslogtreecommitdiff
path: root/messagelog.lua
blob: 9f05ab4c92b212cb21d6592d2240fe8724913ac2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
local function esc(x)
    local res = ""
    for i=1, #x do
        local c = x:sub(i,i)
        if c == "\\" then
            res = res .. "\\\\"
        elseif c == "\01" then
            res = res .. "\\a"
        elseif c == "\02" then
            res = res .. "\\b"
        elseif c == "|" then
            res = res .. "\\p"
        else
            res = res .. c
        end
    end
    return res
end

local function unesc(x)
    local res = ""
    local i = 1
    while i <= #x do
        local c = x:sub(i,i)
        if c == "\\" then
            local c2 = x:sub(i+1,i+1)
            if c2 == "\\" then res = res .. "\\" end
            if c2 == "a" then res = res .. "\01" end
            if c2 == "b" then res = res .. "\01" end
            if c2 == "p" then res = res .. "|" end
            i = i + 1
        else
            res = res .. c
        end
        i = i + 1
    end
    return res
end

local function genmsg(msg)
    return "\01|"..msg.timestamp.."|"..esc(msg.sender).."|"..esc(msg.content).."|"..(msg.parent or "").."|"
end

local function parsemsg(readable)
    if readable:read(1) ~= "\01" or readable:read(1) ~= "|" then
        return false
    end
    local section = 0
    local timestamp = ""
    local sender = ""
    local content = ""
    local parent = ""
    while true do
        local c = readable:read(1)
        if c == nil then
            return false
        end
        if c == "|" then
            section = section + 1
            if section == 4 then return {timestamp=timestamp, sender=unesc(sender), content=unesc(content), parent=parent=="" and nil or tonumber(parent)} end
        elseif section == 0 then
            timestamp = timestamp .. c
        elseif section == 1 then
            sender = sender .. c
        elseif section == 2 then
            content = content .. c
        else
            parent = parent .. c
        end
    end
end

local function appendmsg(filename,msg)
    local f = io.open(filename,"ab")
    local res = f:seek("cur",0)
    f:write(genmsg(msg))
    f:close()
    return res
end

local function getmsg(filename,id)
    local f = io.open(filename,"rb")
    f:seek("set",id)
    local msg = parsemsg(f)
    msg.id = id
    f:close()
    return msg
end

local function last_n(filename,n,id)
    local res = {}
    local f = io.open(filename,"rb")
    local i = id or 0
    while true do
        i = i - 1
        local pos = f:seek(id and "set" or "end",i)
        local c = f:read(1)
        if not c then
            local res2 = {}
            for i=#res,1,-1 do
                table.insert(res2,res[i])
            end
            return res2
        end
        if c == "\01" then table.insert(res, getmsg(filename,pos)) end
        if #res >= n or pos == 0 then
            local res2 = {}
            for i=#res,1,-1 do
                table.insert(res2,res[i])
            end
            return res2
        end
    end
end

return {last_n = last_n, getmsg = getmsg, appendmsg = appendmsg}