Current section
Files
Jump to
Current section
Files
lib/ini.ex
defmodule Ini do
def decode(data) do
# Filter out the garbage rows ; \n ""
data = String.split(data, ~r/[\r\n]+/)
|> Enum.filter fn line ->
!Regex.match?(~r/^\s*[;]/, line) and line != ""
end
# Parse the remaining lines with that sick ini regex
ini_regex = ~r/^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i
data = Enum.map data, fn line ->
hd(Regex.scan ini_regex, line)
end
# This mess parses the actual INI file
output = Enum.reduce data, %{}, fn line, output ->
case length(line) do
x when x == 2 ->
# This is a new field that isn't a list
key = tl(line)
|> hd
|> String.to_atom
{_, output} = get_and_update_in(output[:current], &{&1, &1 = key})
{_, output} = get_and_update_in(output[key], &{&1, &1 = %{} })
x when x > 3 ->
# This is either a list or a regular value
key = String.strip(Enum.at(line, 2))
value = String.strip(Enum.at(line, 4))
if String.slice(key, -2..-1) == "[]" do
# Handle the case that we have a list
key = String.slice(key, 0..-3)
|> String.to_atom
if !is_nil(output[output[:current]][key]) do
{_, output} = get_and_update_in(output[output[:current]][key], &{&1, &1 ++ [value] })
else
{_, output} = get_and_update_in(output[output[:current]][key], &{&1, &1 = [value] })
end
else
# This isn't an array it's just a normal key
key = String.to_atom(key)
# if there is no current we just pump out key value pairs
if is_nil(output[:current]) do
{_, output} = get_and_update_in(output[key], &{&1, &1 = value})
else
{_, output} = get_and_update_in(output[output[:current]][key], &{&1, &1 = value})
end
end
_ ->
output
end
output
end
Map.delete(output, :current)
end
end