translated the lua converter to plain c

This commit is contained in:
Andre Leiradella 2015-10-06 23:16:54 -03:00
parent 5fce3f4138
commit bdd98d3ea3
7 changed files with 0 additions and 458 deletions

View File

@ -1,216 +0,0 @@
local dat_obj = {}
local match_key = nil
local function dat_lexer(f, fname)
local line, err = f:read("*l")
local location = {line_no = 1, column = 1, fname = fname}
return function()
local tok = nil
while not tok do
if not line then
return nil
end
pre_space, tok, line = string.match(line, "^(%s*)(..-)([()]*%s.*)")
if tok and string.match(tok, "^\"") then
tok, line = string.match(tok..line, "^\"([^\"]-)\"(.*)")
elseif tok and string.match(tok, "^[()]") then
line = tok:sub(2) .. line
tok = tok:sub(1,1)
end
location.column = location.column + #(pre_space or "")
tok_loc = {
line_no = location.line_no,
column = location.column,
fname = location.fname
}
if not line then
line = f:read("*l")
location.line_no = location.line_no + 1
location.column = 1
else
location.column = location.column + #tok
end
end
-- print(tok)
return tok, tok_loc
end
end
local function dat_parse_table(lexer, start_loc)
local res = {}
local state = "key"
local key = nil
for tok, loc in lexer do
if state == "key" then
if tok == ")" then
return res
elseif tok == "(" then
error(string.format(
"%s:%d:%d: fatal error: Unexpected '(' instead of key",
loc.fname,
loc.line_no,
loc.column
))
else
key = tok
state = "value"
end
else
if tok == "(" then
res[key] = dat_parse_table(lexer, loc)
elseif tok == ")" then
error(string.format(
"%s:%d:%d: fatal error: Unexpected ')' instead of value",
loc.fname,
loc.line_no,
loc.column
))
else
res[key] = tok
end
state = "key"
end
end
error(string.format(
"%s:%d:%d: fatal error: Missing ')' for '('",
start_loc.fname,
start_loc.line_no,
start_loc.column
))
end
local function dat_parser(lexer)
local res = {}
local state = "key"
local key = nil
local skip = true
for tok, loc in lexer do
if state == "key" then
if tok == "game" then
skip = false
end
state = "value"
else
if tok == "(" then
local v = dat_parse_table(lexer, loc)
if not skip then
table.insert(res, v)
skip = true
end
else
error(string.format(
"%s:%d:%d: fatal error: Expected '(' found '%s'",
loc.fname,
loc.line_no,
loc.column,
tok
))
end
state = "key"
end
end
return res
end
local function unhex(s)
if not s then return nil end
return (s:gsub('..', function (c)
return string.char(tonumber(c, 16))
end))
end
local function get_match_key(mk, t)
for p in string.gmatch(mk, "(%w+)[.]?") do
if p == nil or t == nil then
error("Invalid match key '"..mk.."'")
end
t = t[p]
end
return t
end
table.update = function(a, b)
for k,v in pairs(b) do
a[k] = v
end
end
function init(...)
local args = {...}
table.remove(args, 1)
if #args == 0 then
assert(dat_path, "dat file argument is missing")
end
if #args > 1 then
match_key = table.remove(args, 1)
end
local dat_hash = {}
for _, dat_path in ipairs(args) do
local dat_file, err = io.open(dat_path, "r")
if err then
error("could not open dat file '" .. dat_path .. "':" .. err)
end
print("Parsing dat file '" .. dat_path .. "'...")
local objs = dat_parser(dat_lexer(dat_file, dat_path))
dat_file:close()
for _, obj in pairs(objs) do
if match_key then
local mk = get_match_key(match_key, obj)
if mk == nil then
error("missing match key '" .. match_key .. "' in one of the entries")
end
if dat_hash[mk] == nil then
dat_hash[mk] = {}
table.insert(dat_obj, dat_hash[mk])
end
table.update(dat_hash[mk], obj)
else
table.insert(dat_obj, obj)
end
end
end
end
function get_value()
local t = table.remove(dat_obj)
if not t then
return
else
return {
name = t.name,
description = t.description,
rom_name = t.rom.name,
size = uint(tonumber(t.rom.size)),
users = uint(tonumber(t.users)),
releasemonth = uint(tonumber(t.releasemonth)),
releaseyear = uint(tonumber(t.releaseyear)),
rumble = uint(tonumber(t.rumble)),
analog = uint(tonumber(t.analog)),
famitsu_rating = uint(tonumber(t.famitsu_rating)),
edge_rating = uint(tonumber(t.edge_rating)),
edge_issue = uint(tonumber(t.edge_issue)),
edge_review = t.edge_review,
enhancement_hw = t.enhancement_hw,
barcode = t.barcode,
esrb_rating = t.esrb_rating,
elspa_rating = t.elspa_rating,
pegi_rating = t.pegi_rating,
cero_rating = t.cero_rating,
franchise = t.franchise,
developer = t.developer,
publisher = t.publisher,
origin = t.origin,
crc = binary(unhex(t.rom.crc)),
md5 = binary(unhex(t.rom.md5)),
sha1 = binary(unhex(t.rom.sha1)),
serial = binary(t.serial or t.rom.serial),
}
end
end

View File

@ -1,12 +0,0 @@
unsigned djb2( const char* str, unsigned len )
{
const unsigned char* aux = (const unsigned char*)str;
unsigned hash = 5381;
while ( len-- )
{
hash = ( hash << 5 ) + hash + *aux++;
}
return hash;
}

View File

@ -1,6 +0,0 @@
#ifndef DJB2_H
#define DJB2_H
unsigned djb2( const char* str, unsigned len );
#endif /* DJB2_H */

View File

@ -1,100 +0,0 @@
#include "lua_common.h"
#include <stdlib.h>
#include <string.h>
int libretrodb_lua_to_rmsgpack_value(lua_State *L, int index,
struct rmsgpack_dom_value * out)
{
size_t tmp_len;
lua_Number tmp_num;
struct rmsgpack_dom_value * tmp_value;
int i, rv = -1;
const char * tmp_string = NULL;
char * tmp_buff = NULL;
const int key_idx = -2;
const int value_idx = -1;
const int MAX_FIELDS = 100;
out->type = RDT_MAP;
out->val.map.len = 0;
out->val.map.items = calloc(MAX_FIELDS, sizeof(struct rmsgpack_dom_pair));
lua_pushnil(L);
while (lua_next(L, index - 1) != 0)
{
if (out->val.map.len > MAX_FIELDS)
printf("skipping due to too many keys\n");
else if (!lua_isstring(L, key_idx))
printf("skipping non string key\n");
else if (lua_isnil(L, value_idx))
{
/* Skipping nil value fields to save disk space */
}
else
{
i = out->val.map.len;
tmp_buff = strdup(lua_tostring(L, key_idx));
out->val.map.items[i].key.type = RDT_STRING;
out->val.map.items[i].key.val.string.len = strlen(tmp_buff);
out->val.map.items[i].key.val.string.buff = tmp_buff;
tmp_value = &out->val.map.items[i].value;
switch (lua_type(L, value_idx))
{
case LUA_TNUMBER:
tmp_num = lua_tonumber(L, value_idx);
tmp_value->type = RDT_INT;
tmp_value->val.int_ = tmp_num;
break;
case LUA_TBOOLEAN:
tmp_value->type = RDT_BOOL;
tmp_value->val.bool_ = lua_toboolean(L, value_idx);
break;
case LUA_TSTRING:
tmp_buff = strdup(lua_tostring(L, value_idx));
tmp_value->type = RDT_STRING;
tmp_value->val.string.len = strlen(tmp_buff);
tmp_value->val.string.buff = tmp_buff;
break;
case LUA_TTABLE:
lua_getfield(L, value_idx, "binary");
if (!lua_isstring(L, -1))
{
lua_pop(L, 1);
lua_getfield(L, value_idx, "uint");
if (!lua_isnumber(L, -1))
{
lua_pop(L, 1);
goto set_nil;
}
else
{
tmp_num = lua_tonumber(L, -1);
tmp_value->type = RDT_UINT;
tmp_value->val.uint_ = tmp_num;
lua_pop(L, 1);
}
}
else
{
tmp_string = lua_tolstring(L, -1, &tmp_len);
tmp_buff = malloc(tmp_len);
memcpy(tmp_buff, tmp_string, tmp_len);
tmp_value->type = RDT_BINARY;
tmp_value->val.binary.len = tmp_len;
tmp_value->val.binary.buff = tmp_buff;
lua_pop(L, 1);
}
break;
default:
set_nil:
tmp_value->type = RDT_NULL;
}
out->val.map.len++;
}
lua_pop(L, 1);
}
rv = 0;
return rv;
}

View File

@ -1,12 +0,0 @@
#ifndef __RARCHDB_LUA_COMMON_H__
#define __RARCHDB_LUA_COMMON_H__
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "rmsgpack_dom.h"
int libretrodb_lua_to_rmsgpack_value(lua_State *L, int index, struct rmsgpack_dom_value *out);
#endif

View File

@ -1,112 +0,0 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "libretrodb.h"
#include "lua_common.h"
int master_key = 1;
const char * LUA_COMMON = " \
function binary(s) if s ~= nil then return {binary = s} else return nil end end \
function uint(s) if s ~= nil then return {uint = s} else return nil end end \
";
static int call_init(lua_State * L, int argc, const char ** argv)
{
int rv = -1;
int i;
lua_getglobal(L, "init");
for (i = 0; i < argc; i++)
lua_pushstring(L, argv[i]);
if (lua_pcall(L, argc, 0, 0) != 0)
{
printf(
"error running function `init': %s\n",
lua_tostring(L, -1)
);
}
return rv;
}
static int value_provider(void * ctx, struct rmsgpack_dom_value *out)
{
int rv = 0;
lua_State * L = ctx;
lua_getglobal(L, "get_value");
if (lua_pcall(L, 0, 1, 0) != 0)
{
printf(
"error running function `get_value': %s\n",
lua_tostring(L, -1)
);
}
if (lua_isnil(L, -1))
rv = 1;
else if (lua_istable(L, -1))
rv = libretrodb_lua_to_rmsgpack_value(L, -1, out);
else
printf("function `get_value' must return a table or nil\n");
lua_pop(L, 1);
return rv;
}
int main(int argc, char ** argv)
{
lua_State *L;
const char *db_file;
const char *lua_file;
RFILE *dst;
int rv = 0;
if (argc < 3)
{
printf("usage:\n%s <db file> <lua file> [args ...]\n", argv[0]);
return 1;
}
db_file = argv[1];
lua_file = argv[2];
L = luaL_newstate();
luaL_openlibs(L);
luaL_dostring(L, LUA_COMMON);
if (luaL_dofile(L, lua_file) != 0)
return 1;
call_init(L, argc - 2, (const char **) argv + 2);
dst = retro_fopen(db_file, RFILE_MODE_WRITE, -1);
if (!dst)
{
printf(
"Could not open destination file '%s': %s\n",
db_file,
strerror(errno)
);
rv = errno;
goto clean;
}
rv = libretrodb_create(dst, &value_provider, L);
clean:
lua_close(L);
retro_fclose(dst);
return rv;
}