Skip to content

Instantly share code, notes, and snippets.

@skwerlman
Last active August 29, 2015 14:14
Show Gist options
  • Save skwerlman/46e4033c755c1396bc89 to your computer and use it in GitHub Desktop.
Save skwerlman/46e4033c755c1396bc89 to your computer and use it in GitHub Desktop.
convert .dec's to .cod's
#!/usr/bin/env lua5.2
-- this must be run under 5.2 or 5.3 with 5.2 compat
-- this converter goes one way; i will not provide a way to go back to dec as that would involve discarding data
--[[
local bDebug = true
--]]
--
-- Really ugly constant definitions and handling of args
--
-- args from user
local T_USR_ARGS = {...}
-- where the .dec is
local S_DEC_LOC = T_USR_ARGS[1]
table.remove(T_USR_ARGS, 1)
-- where we will put the .cod (same as S_DEC_LOC, but ends in .cod instead of .dec)
local S_COD_LOC = S_DEC_LOC:sub( 1, #S_DEC_LOC - 3 ) .. 'cod'
-- pretty-print name of deck
local S_COD_DECKNAME = ""
for _, v in ipairs(T_USR_ARGS) do
S_COD_DECKNAME = S_COD_DECKNAME .. ' ' .. v
end
S_COD_DECKNAME = S_COD_DECKNAME:sub( 2 )
-- header info required by .cod
local S_COD_PREFIX = string.format( [[<?xml version="1.0" encoding="UTF-8"?>
<!--
automatically generated by dec-to-cod.lua
-->
<cockatrice_deck version="1">
<deckname>%s</deckname>
<comments>Converted from DEC</comments>
<zone name="main">
]], S_COD_DECKNAME )
-- closes all open tags
local S_COD_SUFFIX = [[ </zone>
</cockatrice_deck>
]]
--
-- Function definitions
--
--
-- DEBUG: write to console if bDebug is true
--
local function write (sStr)
if bDebug then
io.write( sStr )
end
return sStr -- allow data to be passed through (kinda like a pipe)
end
--
-- Check whether file exists
--
local function fileExists (sPath)
assert( type( sPath ) == 'string', 'bad argument #1: expected string, got ' .. type( sPath ) )
local hFile = io.open( sPath, "r" )
if hFile == nil then
return false
else
hFile:close()
return true
end
end
--
-- Reads a file storing each line in a table
-- We read it into memory all at once to relinquish the handle as fast as possible
--
local function fileToTable (sPath)
assert( fileExists( sPath ), sPath .. ' does not exist or is a directory' )
local tLines = {}
local lines = io.lines( sPath ) -- this closes itself
for line in lines do
if line ~= '' then
tLines[#tLines + 1] = line
end
end
return tLines
end
--
-- Remove all leading whitespace from a string
--
local function stripLeadingWhitespace (sStr)
assert( type( sStr ) == 'string', 'bad argument #1: expected string, got ' .. type( sStr ) )
if #sStr >= 1 then
while true do
if sStr:sub( 1, 1 ) ~= ' ' and sStr:sub( 1, 1 ) ~= '\t' then
break
end
sStr = sStr:sub( 2 )
end
end
return sStr
end
--
-- Break sStr into two sections, using sDelim as the delimeter
--
local function tokenize (sStr, sDelim, nLine)
assert( type( sStr ) == 'string', 'bad argument #1: expected string, got ' .. type( sStr ) )
assert( type( sDelim ) == 'string' or type( sDelim ) == 'nil', 'bad argument #2: expected string or nil, got ' .. type( sDelim ) )
assert( type( nLine ) == 'number' or type( nLine ) == 'nil', 'bad argument #2: expected number or nil, got ' .. type( nLine ) )
sDelim = sDelim or ' '
nLine = nLine or 'unknown'
local tTokens = {}
-- break sStr into two segments and store in table, splitting at first sDelim
nDelimLoc = sStr:find( sDelim )
assert( nDelimLoc, "malformed entry in " .. S_DEC_LOC .. " near line " .. nLine )
tTokens[1] = stripLeadingWhitespace( sStr:sub( 1, nDelimLoc - 1 ) )
tTokens[2] = stripLeadingWhitespace( sStr:sub( nDelimLoc + 1 ) )
return tTokens
end
--
-- Wraps a .dec entry in the xml required by .cod
-- We set price to 0 because we don't know the current value; cockatrice can update it later
-- We need to pass the line number within the .dec so it can be used in error messages
--
local function encodeEntry (sEntry, nLine)
assert( type( sEntry ) == 'string', 'bad argument #1: expected string, got' .. type( sEntry ) )
assert( type( nLine ) == 'number' or type( nLine ) == 'nil', 'bad argument #2: expected number or nil, got ' .. type( nLine ) )
nLine = nLine or 'unknown'
local tParts = tokenize( stripLeadingWhitespace( sEntry ), ' ', nLine )
assert( #tParts == 2, "malformed entry in " .. S_DEC_LOC .. " near line " .. nLine ) -- not certain this can be triggered
return string.format( " <card number=\"%s\" price=\"0\" name=\"%s\"/>\n", tParts[1], tParts[2] )
end
--
-- Write a string to a file, replacing anything already there
-- We use this to write the .cod after bulding it in memory. This minimizes the amount of time we spend with the handle open
--
local function writeStringToFile (sStr, sPath)
assert( type( sStr ) == 'string', 'bad argument #1: expected string, got ' .. type( sStr ) )
assert( type( sPath ) == 'string', 'bad argument #2: expected string, got ' .. type( sPath ) )
local hFile = io.open( sPath, 'w+' )
assert( hFile, 'failed to open file for write; do you have the correct permissions?' )
io.write( 'Writing to ' .. S_COD_LOC .. '...')
hFile:write( sStr )
hFile:flush()
hFile:close()
io.write( ' Done.\n')
end
--
-- this is where the party's at
--
-- load the .dec into a table
local tDEC = fileToTable( S_DEC_LOC )
-- prefill sCOD with .cod header info
local sCOD = write( S_COD_PREFIX )
-- iterate over the .dec table, encoding each nonempty entry
for i, sEntry in ipairs( tDEC ) do
sCOD = sCOD .. write( encodeEntry( sEntry, i ) )
end
-- append closing tags
sCOD = sCOD .. write( S_COD_SUFFIX )
-- now that we've generated the .cod, we can write it to disk
writeStringToFile( sCOD, S_COD_LOC )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment