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]