Log In  


I made a simple ini parsing/dumping function. load_ini() converts an ini string to a table, and dump_ini() converts a lua table to an ini string.

This could be useful for projects that have a configuration file. Using an ini might be better for user configs since ini supports comments.

The ini format is simple. Section headings are marked with [section] and items are stored as key=value. Subsections are separated with a dot. Inline comments are not supported, but comments at the start of the line are.

Strings don't have to be quoted, but you should quote them.

Example:

[heading]
a=1
b=2

[heading.sub]
c="hello"
d="world"

[heading.array]
1=4
2=5
3=6

This will convert to:

{
  heading = {
    a = 1,
    b = 2,
    sub = {
      c = "hello",
      d = "world"
    },
    array = { 4, 5, 6 }
  }
}

With the way I wrote it, it can handle anything that can be parsed with unpod(). This may be useful for writing some things (such as arrays) more compactly. The following is equivalent to the above example:

[heading]
a=1
b=2
sub={c="hello",d="world"}
array={4,5,6}

Code under the cut

https://gist.github.com/Rayquaza01/e2cedb3ab53d166fdcd2c1a9cc950b1e

--- Loads an ini string into a lua table
--- @param ini_text string
---   @Return table
function load_ini(ini_text)
    local tbl = {}
    local lines = split(ini_text, "\n", false)

    local current_head = tbl
    local header = ""

    for l in all(lines) do
        -- if line is not comment
        if not (l == "" or l:find("^%s*;") or l:find("^%s*%-%-") or l:find("^%s*#") or l:find("^%s*//")) then
            if l:find("%[.+%]") then
                current_head = tbl
                header = l:sub(2, #l - 1)
                for h in all(split(header, ".", false)) do
                    if (current_head[h]) == nil then
                        current_head[h] = {}
                    end

                    current_head = current_head[h]
                end
            elseif l:find("%w+=.+") then
                local equals_pos = l:find("=", 1, true)
                local key = l:sub(1, equals_pos - 1)
                local value = l:sub(equals_pos + 1, #l)

                if tonum(key) ~= nil then
                    key = tonum(key)
                end

                if tonum(value) ~= nil then
                    value = tonum(value)
                elseif value == "true" or value == "false" then
                    value = unpod(value)
                else
                    value = unpod(value) or value
                end

                current_head[key] = value
            end
        end
    end

    return tbl
end

--- Dumps a lua table into an ini string
--- @param tbl table
--- @param header_prefix? string
---   @Return string
function dump_ini(tbl, header_prefix)
    if header_prefix == nil or type(header_prefix) ~= "string" then
        header_prefix = ""
    end

    local text = {}

    -- first pass add any values
    for key, value in pairs(tbl) do
        if type(value) ~= "table" then
            add(text, ("%s=%s"):format(tostr(key), pod(value)))
        end
    end

    -- second pass add nested tables
    for key, value in pairs(tbl) do
        if type(value) == "table" then
            add(text, ("[%s%s]"):format(header_prefix, key))
            add(text, dump_ini(value, ("%s%s."):format(header_prefix, key)))
        end
    end

    return table.concat(text, "\n")
end

1



[Please log in to post a comment]