Last active
August 29, 2015 14:14
-
-
Save skwerlman/46e4033c755c1396bc89 to your computer and use it in GitHub Desktop.
convert .dec's to .cod's
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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