RetroArch/libretro-db/lua/lua_common.c
2016-01-26 09:32:49 +01:00

156 lines
4.4 KiB
C

#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);
}
#if 1
/* re-order to avoid random output each run */
struct rmsgpack_dom_pair* ordered_pairs = calloc(out->val.map.len, sizeof(struct rmsgpack_dom_pair));
struct rmsgpack_dom_pair* ordered_pairs_outp = ordered_pairs;
const char* ordered_keys[] =
{
"name",
"description",
"rom_name",
"size",
"users",
"releasemonth",
"releaseyear",
"rumble",
"analog",
"famitsu_rating",
"edge_rating",
"edge_issue",
"edge_review",
"enhancement_hw",
"barcode",
"esrb_rating",
"elspa_rating",
"pegi_rating",
"cero_rating",
"franchise",
"developer",
"publisher",
"origin",
"crc",
"md5",
"sha1",
"serial"
};
for(i = 0; i < (sizeof(ordered_keys)/sizeof(char*)); i++)
{
int j;
for(j = 0; j < out->val.map.len; j++)
{
if(!strcmp(ordered_keys[i], out->val.map.items[j].key.val.string.buff))
{
*ordered_pairs_outp++ = out->val.map.items[j];
break;
}
}
}
free(out->val.map.items);
out->val.map.items = ordered_pairs;
out->val.map.len = ordered_pairs_outp - ordered_pairs;
#endif
rv = 0;
return rv;
}