summaryrefslogtreecommitdiff
path: root/target/linux/ramips/base-files/usr/lib/lua/shuci.lua
blob: 1b0109f53ebdab20b11d395eb5f6542d6205bed5 (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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/usr/bin/env lua

--[[
 * A pure lua library to translate between:
 *     lua table <--> uci config
 *
 * For UCI: http://wiki.openwrt.org/doc/techref/uci
 *          http://wiki.openwrt.org/doc/uci
 *
 * Copyright (C) 2015 Hua Shao <nossiac@163.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
]]


local shuci = {}

function shuci.decode(path)
    function file_exists(name)
       local f=io.open(name,"r")
       if f~=nil then io.close(f) return true else return false end
    end
    local function linebreaker(str)
        local i,_ = string.find(str, "([^%s])")
        if not i then return nil end
        if string.find(str, "config%s+%w+") then
            local i,j,k,v = string.find(str, "config%s+([%w-_]+)%s*['\"]*([^%s\'\"]*)")
            return "section", k, v
        elseif string.find(str, "option%s+%w+") then
            local i,j,k,v = string.find(str, "option%s+([%w-_]+)%s*['\"]([^'\"]+)['\"]")
            if not k or not v then
                i,j,k,v = string.find(str, "option%s+([%w-_]+)%s*['\"]*([^%s\'\"]*)")
            end
            return "option", k, v
        elseif string.find(str, "list%s+%w+") then
            local i,j,k,v = string.find(str, "list%s+([%w-_]+)%s*['\"]([^'\"]+)['\"]")
            if not k or not v then
                i,j,k,v = string.find(str, "list%s+([%w-_]+)%s*['\"]*([^%s\'\"]*)")
            end
            return "list", k, v
        end
    end

    if not file_exists(path) then
        return
    end

    local _sect_ = nil
    local t = {}
    for line in io.lines(path) do
        local _type, _name, _value = linebreaker(line)
        if _type == "section" then
            if not t[_name] then
                t[_name] = {}
                _sect_ = t[_name]
                if _value then
                    _sect_[".name"] = _value
                end
            else
                if t[_name][1] then -- already a list
                else -- upgrade from dict to array
                    local _t = t[_name]
                    t[_name] = {}
                    t[_name][1] = _t
                end
                t[_name][#t[_name]+1] = {}
                _sect_ = t[_name][#t[_name]]
                if _value then
                    _sect_[".name"] = _value
                end
            end
        end
        if _type == "option" then
            if _name and _value then
                _sect_[_name] = _value
            end
        end
        if _type == "list" and _name and _value then
            local idx
            if not _sect_[_name] then
                _sect_[_name] = {}
                _sect_[_name][1] = _value
            else
                idx = #_sect_[_name]
                _sect_[_name][idx+1] = _value
            end
        end
    end

    return t
end


function shuci.encode(t, path)
    local dump = io.write
    if path then
        local fp = io.open(path, "w")
        dump = function(str) fp:write(str) end
    end
    for stype,ss in pairs(t) do
        if #ss > 0 then
            for _,s in ipairs(ss) do
                dump(string.format("config\t%s\t'%s'\n", stype, s[".name"] or ""))
                for k,v in pairs(s) do
                    if type(v) == "table" then
                        for _,vv in ipairs(v) do
                            dump(string.format("\tlist\t%s\t'%s'\n",k,vv))
                        end
                    elseif type(v) == "string" and k ~= ".name" then
                        dump(string.format("\toption\t%s\t'%s'\n",k,v))
                    elseif type(v) == "number" and k ~= ".name" then
                        dump(string.format("\toption\t%s\t'%s'\n",k,tonumber(v)))
                    end
                end
            dump("\n")
            end
        else
            dump(string.format("config\t%s\t'%s'\n", stype, ss[".name"] or ""))
            for k,v in pairs(ss) do
                if type(v) == "table" then
                    for _,vv in ipairs(v) do
                        dump(string.format("\tlist\t%s\t'%s'\n",k,vv))
                    end
                elseif type(v) == "string" and k ~= ".name" then
                    dump(string.format("\toption\t%s\t'%s'\n",k,v))
                elseif type(v) == "number" and k ~= ".name" then
                    dump(string.format("\toption\t%s\t'%s'\n",k,tonumber(v)))
                end
            end
        end
    end
end

return shuci