Skip to content

Commit

Permalink
INI: Switch to using LPEG for unpack
Browse files Browse the repository at this point in the history
Issue: #99

Switching to LPEG should make it easier to properly support the file
format.  In particular, double quoted lists are now handled properly.
Additionally, fewer assumptions regarding values are made.

For unquoted values, everything until the EOL is now returned.  Within
the game files there are cases where trailing comments are not removed.
There are cases where they are.  How are we supposed to know?

For quoted values, both single and double, the quotes are no longer
removed.  There are cases where some values must be double quoted.
Others must be singled quoted.  Again, how are we supposed to know?

So we make less assumptions, and let the user decide.
  • Loading branch information
nvs committed Jul 5, 2022
1 parent 2d7dc1e commit d7c03a2
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 45 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
### Fixed
- Trigger Strings (`wts`):
- Nested bracket support restored.
- INI (`txt`):
- Properly handle quoted lists.

### Added
- Trigger Strings (`wts`):
Expand All @@ -20,6 +22,9 @@

- Objects (`w3a`, `w3b`, `w3d`, `w3h`, `w3q`, `w3u`, `w3t`):
- Unpacked format has changed.
- INI (`txt`):
- Quotes are no longer removed from values.
- Trailing comments are no longer removed from values.

## [0.10.1] - 2020-01-05
### Fixed
Expand Down
82 changes: 37 additions & 45 deletions file/ini.lua
Original file line number Diff line number Diff line change
@@ -1,68 +1,60 @@
local INI = {}

function INI.unpack (input)
assert (type (input) == 'string')
local LPeg = require ('lpeg')
local Re = require ('re')

local output = {}
local current
local INI = {}

if input:sub (1, 3) == '\239\187\191' then
input = input:sub (4)
end
local grammar
do
local P = LPeg.P

for line in input:gmatch ('[^\r\n]+') do
line = line:find ('^%s*//') and '' or line
local section = line:match ('^%[([^%]]+)%]$')
local definitions = {
eol = P ('\r\n') + P ('\n'),
bom = P ('\xEF\xBB\xBF'),
set = rawset
}

if section then
current = output [section] or {}
output [section] = current
grammar = Re.compile ([[
INI <- bom? ({||} contents*) ~> set eof {}
contents <- eol / comment / section / skip
elseif not current then -- luacheck: ignore 542
-- Do nothing. All key/value pairs must be in a section.
section <- {: header ({||} body*) ~> set :}
header <- '[' name ']'
name <- { (!']' !eol .)+ }
body <- eol / comment / pair
else
local index = line:find ('=', 1, true)
pair <- {: key '=' value :}
key <- { (!'=' !eol .)+ }
value <- quoted / unquoted
if index then
local key = line:sub (1, index - 1)
local value = line:sub (index + 1)
quoted <- { singles / doubles } skip*
unquoted <- { (!eol .)* }
-- Double quotes only apply if the first character of the
-- value (i.e. that immediately after the equals sign) is
-- one. If so, the value is considered to be that which
-- extends to the first closing double quote or the end of
-- the line, whichever comes first.
if value:sub (1, 1) == '"' then
value = value:match ('^"([^"]*)"?')
singles <- single (',' single)*
single <- "'" (!"'" !eol .)* "'"
-- Otherwise, we remove any trailing comments.
else
value = value:match ('^(.-)//') or value
end
doubles <- double (',' double)*
double <- '"' (!'"' !eol .)* '"'
current [key] = value
end
end
end
comment <- '//' (!eol . )*
skip <- !eol .
bom <- %bom
eol <- %eol
eof <- !.
]], definitions)
end

return output
function INI.unpack (input, position)
return grammar:match (input, position)
end

function INI.pack (input)
assert (type (input) == 'table')

local output = {}

for section, contents in pairs (input) do
output [#output + 1] = '[' .. section .. ']'

for key, value in pairs (contents) do
-- Remove trailing comments. If the user wishes to include `//`
-- in their value, then they should use double quotes.
value = value:match ('^(.-)//') or value

output [#output + 1] = key .. '=' .. value .. ''
output [#output + 1] = key .. '=' .. value
end

output [#output + 1] = ''
Expand Down

0 comments on commit d7c03a2

Please sign in to comment.