(LibretroDB) Update

This commit is contained in:
twinaphex 2015-01-23 05:59:47 +01:00
parent fb5384feab
commit fc82bd4d9d
19 changed files with 690 additions and 305 deletions

View File

@ -173,7 +173,7 @@ OBJ += frontend/frontend.o \
ifeq ($(HAVE_LIBRETRODB), 1)
OBJ += libretrodb/bintree.o \
libretrodb/rarchdb.o \
libretrodb/libretrodb.o \
libretrodb/query.o \
libretrodb/rmsgpack.o \
libretrodb/rmsgpack_dom.o

View File

@ -810,7 +810,7 @@ XML
============================================================ */
#ifdef HAVE_LIBRETRODB
#include "../libretrodb/bintree.c"
#include "../libretrodb/rarchdb.c"
#include "../libretrodb/libretrodb.c"
#include "../libretrodb/rmsgpack.c"
#include "../libretrodb/rmsgpack_dom.c"
#include "../libretrodb/query.c"

View File

@ -4,7 +4,7 @@ INCFLAGS = -I. -I../libretro-sdk/include
LUA_CONVERTER_OBJ = rmsgpack.o \
rmsgpack_dom.o \
lua_common.o \
rarchdb.o \
libretrodb.o \
bintree.o \
query.o \
lua_converter.o \
@ -13,10 +13,10 @@ LUA_CONVERTER_OBJ = rmsgpack.o \
RARCHDB_TOOL_OBJ = rmsgpack.o \
rmsgpack_dom.o \
rarchdb_tool.o \
libretrodb_tool.o \
bintree.o \
query.o \
rarchdb.o \
libretrodb.o \
compat_fnmatch.c \
$(NULL)
@ -24,7 +24,7 @@ TESTLIB_C = testlib.c \
lua_common.c \
query.c \
compat_fnmatch.c \
rarchdb.c \
libretrodb.c \
bintree.c \
rmsgpack.c \
rmsgpack_dom.c \
@ -35,7 +35,7 @@ TESTLIB_FLAGS = ${CFLAGS} ${LUA_FLAGS} -shared -fpic
.PHONY: all clean check
all: rmsgpack_test rarchdb_tool lua_converter
all: rmsgpack_test libretrodb_tool lua_converter
%.o: %.c
${CC} $(INCFLAGS) $< -c ${CFLAGS} -o $@
@ -43,7 +43,7 @@ all: rmsgpack_test rarchdb_tool lua_converter
lua_converter: ${LUA_CONVERTER_OBJ}
${CC} $(INCFLAGS) ${LUA_CONVERTER_OBJ} ${LUA_FLAGS} -o $@
rarchdb_tool: ${RARCHDB_TOOL_OBJ}
libretrodb_tool: ${RARCHDB_TOOL_OBJ}
${CC} $(INCFLAGS) ${RARCHDB_TOOL_OBJ} -o $@
rmsgpack_test:
@ -56,4 +56,4 @@ check: testlib.so tests.lua
lua ./tests.lua
clean:
rm -rf *.o rmsgpack_test lua_converter rarchdb_tool testlib.so
rm -rf *.o rmsgpack_test lua_converter libretrodb_tool testlib.so

View File

@ -1,13 +1,13 @@
# rarchdb
# libretrodb
A small read only database
Mainly to be used by retroarch
# Usage
Files specified later in the chain **will override** earlier ones if the same key exists multiple times.
To list out the content of a db `rarchdb_tool <db file> list`
To create an index `rarchdb_tool <db file> create-index <index name> <field name>`
To find an entry with an index `rarchdb_tool <db file> find <index name> <value>`
To list out the content of a db `libretrodb_tool <db file> list`
To create an index `libretrodb_tool <db file> create-index <index name> <field name>`
To find an entry with an index `libretrodb_tool <db file> find <index name> <value>`
# lua converters
In order to write you own converter you must have a lua file that implements the following functions:
@ -54,15 +54,15 @@ dat_converter snes.rdb rom.crc snes1.dat snes2.dat
~~~
# Query examples
Some examples of queries you can use with rarchdbtool:
Some examples of queries you can use with libretrodbtool:
1) Glob pattern matching
Usecase : Search for all games starting with 'Street Fighter' in the 'name' field (glob pattern matching)
`rarchdb_tool <db file> find "{'name':glob('Street Fighter*')}"`
`libretrodb_tool <db file> find "{'name':glob('Street Fighter*')}"`
2) Combined number matching query
Usecase: Search for all games released on October 1995.
`rarchdb_tool <db file> find "{'releasemonth':10,'releaseyear':1995}"`
`libretrodb_tool <db file> find "{'releasemonth':10,'releaseyear':1995}"`

291
libretrodb/dat_converter.c Normal file
View File

@ -0,0 +1,291 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "rarchdb.h"
#include "db_parser.h"
#define MAX_TOKEN 256
static char *strndup_(const char *s, size_t n)
{
char* buff = calloc(n, sizeof(char));
if (!buff)
return 0;
strncpy(buff, s, n);
return buff;
}
static struct rmsgpack_dom_value *get_map_value(const struct rmsgpack_dom_value *m, char* key)
{
struct rmsgpack_dom_value v;
v.type = RDT_STRING;
v.string.len = strlen(key);
v.string.buff = key;
return rmsgpack_dom_value_map_value(m, &v);
}
static int load_string(int fd, struct rmsgpack_dom_value *out)
{
char tok[MAX_TOKEN];
ssize_t tok_size;
if ((tok_size = get_token(fd, tok, MAX_TOKEN)) < 0)
return tok_size;
out->type = RDT_STRING;
out->string.len = tok_size;
out->string.buff = strndup_(tok, tok_size);
return 0;
}
static int load_uint(int fd, struct rmsgpack_dom_value *out)
{
char tok[MAX_TOKEN], *c;
ssize_t tok_size;
uint64_t value = 0;
if ((tok_size = get_token(fd, tok, MAX_TOKEN)) < 0)
return tok_size;
for (c = tok; c < tok + tok_size; c++)
{
value *= 10;
value += *c - '0';
}
out->type = RDT_UINT;
out->uint_ = value;
return 0;
}
static int load_bin(int fd, struct rmsgpack_dom_value *out)
{
char tok[MAX_TOKEN];
ssize_t tok_size;
uint8_t h;
uint8_t l;
int i;
if ((tok_size = get_token(fd, tok, MAX_TOKEN)) < 0)
return tok_size;
out->type = RDT_BINARY;
out->binary.len = tok_size / 2;
for (i = 0; i < tok_size; i += 2)
{
if (tok[i] <= '9')
h = tok[i] - '0';
else
h = (tok[i] - 'A') + 10;
if (tok[i+1] <= '9')
l = tok[i+1] - '0';
else
l = (tok[i+1] - 'A') + 10;
tok[i/2] = h * 16 + l;
}
out->binary.buff = malloc(out->binary.len);
memcpy(out->binary.buff, tok, out->binary.len);
return 0;
}
static int dat_value_provider(void *ctx, struct rmsgpack_dom_value *out)
{
int rv, i;
static const int field_count = 22;
int fd = *((int*)ctx);
char* key;
out->type = RDT_MAP;
out->map.len = field_count;
out->map.items = calloc(field_count, sizeof(struct rmsgpack_dom_pair));
if (find_token(fd, "game") < 0)
return 1;
for (i = 0; i < field_count; i++)
{
if ((rv = load_string(fd, &out->map.items[i].key)) < 0)
goto failed;
key = out->map.items[i].key.string.buff;
if (strncmp(key, "name", sizeof("name")) == 0)
{
if ((rv = load_string(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "description", sizeof("description")) == 0)
{
if ((rv = load_string(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "users", sizeof("users")) == 0)
{
if ((rv = load_uint(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "releasemonth", sizeof("releasemonth")) == 0)
{
if ((rv = load_uint(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "releaseyear", sizeof("releaseyear")) == 0)
{
if ((rv = load_uint(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "rumble", sizeof("rumble")) == 0)
{
if ((rv = load_uint(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "analog", sizeof("analog")) == 0)
{
if ((rv = load_uint(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "serial", sizeof("serial")) == 0)
{
if ((rv = load_string(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "esrb_rating", sizeof("esrb_rating")) == 0)
{
if ((rv = load_string(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "elspa_rating", sizeof("elspa_rating")) == 0)
{
if ((rv = load_string(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "pegi_rating", sizeof("pegi_rating")) == 0)
{
if ((rv = load_string(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "cero_rating", sizeof("cero_rating")) == 0)
{
if ((rv = load_string(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "developers", sizeof("developers")) == 0)
{
if ((rv = load_string(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "publisher", sizeof("publisher")) == 0)
{
if ((rv = load_string(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "origin", sizeof("origin")) == 0)
{
if ((rv = load_string(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "rom", sizeof("rom")) == 0)
{
if (find_token(fd, "name") < 0)
goto failed;
if ((rv = load_string(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "size", sizeof("size")) == 0)
{
if ((rv = load_uint(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "sha1", sizeof("sha1")) == 0)
{
if ((rv = load_bin(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "crc", sizeof("crc")) == 0)
{
if ((rv = load_bin(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "md5", sizeof("md5")) == 0)
{
if ((rv = load_bin(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, "serial", sizeof("serial")) == 0)
{
if ((rv = load_string(fd, &out->map.items[i].value)) < 0)
goto failed;
}
else if (strncmp(key, ")", sizeof(")")) == 0)
{
rmsgpack_dom_value_free(&out->map.items[i].key);
out->map.len = i;
printf("Couldn't find all fields for item\n");
break;
}
else
{
rmsgpack_dom_value_free(&out->map.items[i].key);
i--;
}
}
printf("Inserting '%s' (%02X%02X%02X%02X)...\n",
get_map_value(out, "name")->string.buff,
(unsigned char)get_map_value(out, "crc")->binary.buff[0],
(unsigned char)get_map_value(out, "crc")->binary.buff[1],
(unsigned char)get_map_value(out, "crc")->binary.buff[2],
(unsigned char)get_map_value(out, "crc")->binary.buff[3]
);
return 0;
failed:
rmsgpack_dom_value_free(out);
out->type = RDT_NULL;
return rv;
}
int main(int argc, char **argv)
{
int rv = 0;
int src = -1;
int dst = -1;
if (argc != 3)
printf("Usage: %s <dat file> <output file>\n", argv[0]);
src = open(argv[1], O_RDONLY);
if (src == -1)
{
printf("Could not open source file '%s': %s\n", argv[1], strerror(errno));
rv = errno;
goto clean;
}
dst = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (dst == -1)
{
printf("Could not open destination file '%s': %s\n", argv[1], strerror(errno));
rv = errno;
goto clean;
}
rv = rarchdb_create(dst, &dat_value_provider, &src);
clean:
if (src != -1)
close(src);
if (dst != -1)
close(dst);
return rv;
}

80
libretrodb/db_parser.c Normal file
View File

@ -0,0 +1,80 @@
#include "db_parser.h"
#include <errno.h>
#include <string.h>
#include <stdlib.h>
ssize_t get_token(int fd, char *token, size_t max_len)
{
char *c = token;
int rv;
ssize_t len = 0;
int in_string = 0;
while (1)
{
rv = read(fd, c, 1);
if (rv == 0)
return 0;
else if (rv < 1)
{
switch (errno)
{
case EINTR:
case EAGAIN:
continue;
default:
return -errno;
}
}
switch (*c)
{
case ' ':
case '\t':
case '\r':
case '\n':
if (c == token)
continue;
if (!in_string)
{
*c = '\0';
return len;
}
break;
case '\"':
if (c == token)
{
in_string = 1;
continue;
}
*c = '\0';
return len;
}
len++;
c++;
if (len == (ssize_t)max_len)
{
*c = '\0';
return len;
}
}
}
int find_token(int fd, const char *token)
{
int tmp_len = strlen(token);
char *tmp_token = (char*)calloc(tmp_len, 1);
if (!tmp_token)
return -1;
while (strncmp(tmp_token, token, tmp_len) != 0)
{
if (get_token(fd, tmp_token, tmp_len) <= 0)
return -1;
}
return 0;
}

View File

@ -1,4 +1,4 @@
#include "rarchdb.h"
#include "libretrodb.h"
#include <sys/types.h>
#ifdef _WIN32
@ -17,43 +17,26 @@
#include "rmsgpack_dom.h"
#include "rmsgpack.h"
#include "bintree.h"
#include "rarchdb_endian.h"
#include "libretrodb_endian.h"
#include "query.h"
#define MAGIC_NUMBER "RARCHDB"
struct rarchdb_header {
char magic_number[sizeof(MAGIC_NUMBER)-1];
uint64_t metadata_offset;
};
struct rarchdb_metadata {
uint64_t count;
};
struct rarchdb_index {
char name[50];
uint64_t key_size;
uint64_t next;
};
struct node_iter_ctx {
struct rarchdb * db;
struct rarchdb_index * idx;
libretrodb_t *db;
libretrodb_index_t *idx;
};
static struct rmsgpack_dom_value sentinal;
static int rarchdb_read_metadata(
static int libretrodb_read_metadata(
int fd,
struct rarchdb_metadata * md
libretrodb_metadata_t *md
){
return rmsgpack_dom_read_into(fd, "count", &md->count, NULL);
}
static int rarchdb_write_metadata(
static int libretrodb_write_metadata(
int fd,
struct rarchdb_metadata * md
libretrodb_metadata_t *md
){
rmsgpack_write_map_header(fd, 1);
rmsgpack_write_string(fd, "count", strlen("count"));
@ -93,24 +76,26 @@ static int validate_document(const struct rmsgpack_dom_value * doc) {
return rv;
}
int rarchdb_create(
int libretrodb_create(
int fd,
rarchdb_value_provider value_provider,
libretrodb_value_provider value_provider,
void * ctx
){
int rv;
struct rarchdb_metadata md;
off_t root;
off_t root;
uint64_t item_count = 0;
libretrodb_metadata_t md;
struct rmsgpack_dom_value item = {};
struct rarchdb_header header = {};
libretrodb_header_t header = {};
memcpy(header.magic_number, MAGIC_NUMBER, sizeof(MAGIC_NUMBER)-1);
root = lseek(fd, 0, SEEK_CUR);
// We write the header in the end because we need to know the size of
// the db first
lseek(fd, sizeof(struct rarchdb_header), SEEK_CUR);
/* We write the header in the end because we need to know the size of
* the db first */
lseek(fd, sizeof(libretrodb_header_t), SEEK_CUR);
while ((rv = value_provider(ctx, &item)) == 0) {
if ((rv = validate_document(&item)) < 0)
@ -130,7 +115,7 @@ int rarchdb_create(
header.metadata_offset = httobe64(lseek(fd, 0, SEEK_CUR));
md.count = item_count;
rarchdb_write_metadata(fd, &md);
libretrodb_write_metadata(fd, &md);
lseek(fd, root, SEEK_SET);
write(fd, &header, sizeof(header));
clean:
@ -138,10 +123,9 @@ clean:
return rv;
}
static int rarchdb_read_index_header(
int fd,
struct rarchdb_index * idx
){
static int libretrodb_read_index_header(
int fd, libretrodb_index_t *idx)
{
uint64_t name_len = 50;
return rmsgpack_dom_read_into(
fd,
@ -152,10 +136,9 @@ static int rarchdb_read_index_header(
);
}
static void rarchdb_write_index_header(
int fd,
struct rarchdb_index * idx
){
static void libretrodb_write_index_header(
int fd, libretrodb_index_t * idx)
{
rmsgpack_write_map_header(fd, 3);
rmsgpack_write_string(fd, "name", strlen("name"));
rmsgpack_write_string(fd, idx->name, strlen(idx->name));
@ -165,20 +148,22 @@ static void rarchdb_write_index_header(
rmsgpack_write_uint(fd, idx->next);
}
void rarchdb_close(struct rarchdb * db)
void libretrodb_close(libretrodb_t * db)
{
close(db->fd);
db->fd = -1;
}
int rarchdb_open(
int libretrodb_open(
const char * path,
struct rarchdb * db
){
struct rarchdb_header header;
struct rarchdb_metadata md;
libretrodb_t * db
)
{
libretrodb_header_t header;
libretrodb_metadata_t md;
int rv;
int fd = open(path, O_RDWR);
if (fd == -1)
return -errno;
@ -195,7 +180,7 @@ int rarchdb_open(
header.metadata_offset = betoht64(header.metadata_offset);
lseek(fd, header.metadata_offset, SEEK_SET);
if (rarchdb_read_metadata(fd, &md) < 0) {
if (libretrodb_read_metadata(fd, &md) < 0) {
rv = -EINVAL;
goto error;
}
@ -208,19 +193,22 @@ error:
return rv;
}
static int rarchdb_find_index(
struct rarchdb * db,
const char * index_name,
struct rarchdb_index * idx
static int libretrodb_find_index(
libretrodb_t *db,
const char *index_name,
libretrodb_index_t *idx
){
off_t eof = lseek(db->fd, 0, SEEK_END);
off_t offset = lseek(db->fd, db->first_index_offset, SEEK_SET);
while (offset < eof) {
rarchdb_read_index_header(db->fd, idx);
if (strncmp(index_name, idx->name, strlen(idx->name)) == 0)
return 0;
offset = lseek(db->fd, idx->next, SEEK_CUR);
}
while (offset < eof)
{
libretrodb_read_index_header(db->fd, idx);
if (strncmp(index_name, idx->name, strlen(idx->name)) == 0)
return 0;
offset = lseek(db->fd, idx->next, SEEK_CUR);
}
return -1;
}
@ -255,21 +243,20 @@ static int binsearch(
return binsearch(current + item_size, item, count - mid, field_size, offset);
}
int rarchdb_find_entry(
struct rarchdb * db,
const char * index_name,
const void * key,
int libretrodb_find_entry(
libretrodb_t *db,
const char *index_name,
const void *key,
struct rmsgpack_dom_value * out
) {
struct rarchdb_index idx;
libretrodb_index_t idx;
int rv;
void * buff;
uint64_t offset;
ssize_t bufflen, nread = 0;
if (rarchdb_find_index(db, index_name, &idx) < 0) {
if (libretrodb_find_index(db, index_name, &idx) < 0)
return -1;
}
bufflen = idx.next;
buff = malloc(bufflen);
@ -302,25 +289,25 @@ int rarchdb_find_entry(
}
/**
* rarchdb_cursor_reset:
* libretrodb_cursor_reset:
* @cursor : Handle to database cursor.
*
* Resets cursor.
*
* Returns: ???.
**/
int rarchdb_cursor_reset(struct rarchdb_cursor * cursor)
int libretrodb_cursor_reset(libretrodb_cursor_t *cursor)
{
cursor->eof = 0;
return lseek(
cursor->fd,
cursor->db->root + sizeof(struct rarchdb_header),
cursor->db->root + sizeof(libretrodb_header_t),
SEEK_SET
);
}
int rarchdb_cursor_read_item(
struct rarchdb_cursor * cursor,
int libretrodb_cursor_read_item(
libretrodb_cursor_t *cursor,
struct rmsgpack_dom_value * out
) {
int rv;
@ -338,7 +325,7 @@ retry:
}
if (cursor->query) {
if (!rarchdb_query_filter(cursor->query, out)) {
if (!libretrodb_query_filter(cursor->query, out)) {
goto retry;
}
}
@ -347,12 +334,12 @@ retry:
}
/**
* rarchdb_cursor_close:
* libretrodb_cursor_close:
* @cursor : Handle to database cursor.
*
* Closes cursor and frees up allocated memory.
**/
void rarchdb_cursor_close(struct rarchdb_cursor * cursor)
void libretrodb_cursor_close(libretrodb_cursor_t *cursor)
{
close(cursor->fd);
cursor->is_valid = 0;
@ -360,12 +347,12 @@ void rarchdb_cursor_close(struct rarchdb_cursor * cursor)
cursor->eof = 1;
cursor->db = NULL;
if (cursor->query)
rarchdb_query_free(cursor->query);
libretrodb_query_free(cursor->query);
cursor->query = NULL;
}
/**
* rarchdb_cursor_open:
* libretrodb_cursor_open:
* @db : Handle to database.
* @cursor : Handle to database cursor.
* @q : Query to execute.
@ -374,10 +361,10 @@ void rarchdb_cursor_close(struct rarchdb_cursor * cursor)
*
* Returns: 0 if successful, otherwise negative.
**/
int rarchdb_cursor_open(
struct rarchdb * db,
struct rarchdb_cursor * cursor,
rarchdb_query * q
int libretrodb_cursor_open(
libretrodb_t *db,
libretrodb_cursor_t *cursor,
libretrodb_query_t *q
)
{
cursor->fd = dup(db->fd);
@ -387,11 +374,11 @@ int rarchdb_cursor_open(
cursor->db = db;
cursor->is_valid = 1;
rarchdb_cursor_reset(cursor);
libretrodb_cursor_reset(cursor);
cursor->query = q;
if (q)
rarchdb_query_inc_ref(q);
libretrodb_query_inc_ref(q);
return 0;
}
@ -406,41 +393,41 @@ static int node_iter(void * value, void * ctx)
return -1;
}
static uint64_t rarchdb_tell(struct rarchdb * db)
static uint64_t libretrodb_tell(libretrodb_t *db)
{
return lseek(db->fd, 0, SEEK_CUR);
}
int rarchdb_create_index(
struct rarchdb * db,
const char * name,
const char * field_name
int libretrodb_create_index(
libretrodb_t *db,
const char *name,
const char *field_name
){
int rv;
struct node_iter_ctx nictx;
struct rmsgpack_dom_value key;
struct rarchdb_index idx;
libretrodb_index_t idx;
struct rmsgpack_dom_value item;
struct rmsgpack_dom_value * field;
struct bintree tree;
libretrodb_cursor_t cur;
void * buff = NULL;
uint64_t * buff_u64 = NULL;
uint8_t field_size = 0;
struct bintree tree;
uint64_t item_loc = rarchdb_tell(db);
uint64_t idx_header_offset;
struct rarchdb_cursor cur;
uint64_t item_loc = libretrodb_tell(db);
bintree_new(&tree, node_compare, &field_size);
if (rarchdb_cursor_open(db, &cur, NULL) != 0) {
if (libretrodb_cursor_open(db, &cur, NULL) != 0) {
rv = -1;
goto clean;
}
key.type = RDT_STRING;
key.string.len = strlen(field_name);
// We know we aren't going to change it
/* We know we aren't going to change it */
key.string.buff = (char *) field_name;
while (rarchdb_cursor_read_item(&cur, &item) == 0) {
while (libretrodb_cursor_read_item(&cur, &item) == 0) {
if (item.type != RDT_MAP) {
rv = -EINVAL;
printf("Only map keys are supported\n");
@ -491,7 +478,7 @@ int rarchdb_create_index(
}
buff = NULL;
rmsgpack_dom_value_free(&item);
item_loc = rarchdb_tell(db);
item_loc = libretrodb_tell(db);
}
(void)rv;
@ -503,7 +490,7 @@ int rarchdb_create_index(
idx.name[49] = '\0';
idx.key_size = field_size;
idx.next = db->count * (field_size + sizeof(uint64_t));
rarchdb_write_index_header(db->fd, &idx);
libretrodb_write_index_header(db->fd, &idx);
nictx.db = db;
nictx.idx = &idx;
@ -514,7 +501,7 @@ clean:
if (buff)
free(buff);
if (cur.is_valid) {
rarchdb_cursor_close(&cur);
libretrodb_cursor_close(&cur);
}
return 0;
}

129
libretrodb/libretrodb.h Normal file
View File

@ -0,0 +1,129 @@
#ifndef __LIBRETRODB_H__
#define __LIBRETRODB_H__
#include <stdint.h>
#ifdef _WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif
#include "rmsgpack_dom.h"
#define MAGIC_NUMBER "RARCHDB"
typedef struct libretrodb_query libretrodb_query_t;
typedef struct libretrodb
{
int fd;
uint64_t root;
uint64_t count;
uint64_t first_index_offset;
} libretrodb_t;
typedef struct libretrodb_index
{
char name[50];
uint64_t key_size;
uint64_t next;
} libretrodb_index_t;
typedef struct libretrodb_metadata
{
uint64_t count;
} libretrodb_metadata_t;
typedef struct libretrodb_header
{
char magic_number[sizeof(MAGIC_NUMBER)-1];
uint64_t metadata_offset;
} libretrodb_header_t;
typedef struct libretrodb_cursor
{
int is_valid;
int fd;
int eof;
libretrodb_query_t * query;
libretrodb_t * db;
} libretrodb_cursor_t;
typedef int (* libretrodb_value_provider)(
void * ctx,
struct rmsgpack_dom_value * out
);
int libretrodb_create(
int fd,
libretrodb_value_provider value_provider,
void * ctx
);
void libretrodb_close(libretrodb_t * db);
int libretrodb_open(
const char * path,
libretrodb_t * db
);
int libretrodb_create_index(
libretrodb_t * db,
const char * name,
const char * field_name
);
int libretrodb_find_entry(
libretrodb_t * db,
const char * index_name,
const void * key,
struct rmsgpack_dom_value * out
);
/**
* libretrodb_cursor_open:
* @db : Handle to database.
* @cursor : Handle to database cursor.
* @q : Query to execute.
*
* Opens cursor to database based on query @q.
*
* Returns: 0 if successful, otherwise negative.
**/
int libretrodb_cursor_open(
libretrodb_t *db,
libretrodb_cursor_t *cursor,
libretrodb_query_t *query
);
/**
* libretrodb_cursor_reset:
* @cursor : Handle to database cursor.
*
* Resets cursor.
*
* Returns: ???.
**/
int libretrodb_cursor_reset(libretrodb_cursor_t * cursor);
/**
* libretrodb_cursor_close:
* @cursor : Handle to database cursor.
*
* Closes cursor and frees up allocated memory.
**/
void libretrodb_cursor_close(libretrodb_cursor_t * cursor);
void *libretrodb_query_compile(
libretrodb_t * db,
const char * query,
size_t buff_len,
const char ** error
);
void libretrodb_query_free(void *q);
int libretrodb_cursor_read_item(
libretrodb_cursor_t * cursor,
struct rmsgpack_dom_value * out
);
#endif

View File

@ -1,5 +1,5 @@
#ifndef __RARCHDB_MSGPACK_ENDIAN_H
#define __RARCHDB_MSGPACK_ENDIAN_H
#ifndef __LIBRETRODB_MSGPACK_ENDIAN_H
#define __LIBRETRODB_MSGPACK_ENDIAN_H
#include <stdint.h>
#include <retro_endianness.h>

View File

@ -1,7 +1,7 @@
#include <stdio.h>
#include <string.h>
#include "rarchdb.h"
#include "libretrodb.h"
#include "rmsgpack_dom.h"
int main(
@ -9,9 +9,12 @@ int main(
char ** argv
){
int rv;
struct rarchdb db;
struct rarchdb_cursor cur;
libretrodb_t db;
libretrodb_cursor_t cur;
libretrodb_query_t *q;
struct rmsgpack_dom_value item;
const char *command, *path, *query_exp, *error;
if (argc < 3) {
printf("Usage: %s <db file> <command> [extra args...]\n", argv[0]);
printf("Available Commands:\n");
@ -21,14 +24,14 @@ int main(
return 1;
}
const char * command = argv[2];
const char * path = argv[1];
command = argv[2];
path = argv[1];
if ((rv = rarchdb_open(path, &db)) != 0) {
if ((rv = libretrodb_open(path, &db)) != 0) {
printf("Could not open db file '%s': %s\n", path, strerror(-rv));
return 1;
} else if (strcmp(command, "list") == 0) {
if ((rv = rarchdb_cursor_open(&db, &cur, NULL)) != 0) {
if ((rv = libretrodb_cursor_open(&db, &cur, NULL)) != 0) {
printf("Could not open cursor: %s\n", strerror(-rv));
return 1;
}
@ -37,7 +40,7 @@ int main(
printf("Usage: %s <db file> list\n", argv[0]);
return 1;
}
while (rarchdb_cursor_read_item(&cur, &item) == 0) {
while (libretrodb_cursor_read_item(&cur, &item) == 0) {
rmsgpack_dom_value_print(&item);
printf("\n");
rmsgpack_dom_value_free(&item);
@ -47,20 +50,23 @@ int main(
printf("Usage: %s <db file> find <query expression>\n", argv[0]);
return 1;
}
const char * query_exp = argv[3];
const char * error = NULL;
rarchdb_query * q = rarchdb_query_compile(&db, query_exp, strlen(query_exp), &error);
query_exp = argv[3];
error = NULL;
q = libretrodb_query_compile(&db, query_exp, strlen(query_exp), &error);
if (error) {
printf("%s\n", error);
return 1;
}
if ((rv = rarchdb_cursor_open(&db, &cur, q)) != 0) {
if ((rv = libretrodb_cursor_open(&db, &cur, q)) != 0)
{
printf("Could not open cursor: %s\n", strerror(-rv));
return 1;
}
while (rarchdb_cursor_read_item(&cur, &item) == 0) {
while (libretrodb_cursor_read_item(&cur, &item) == 0)
{
rmsgpack_dom_value_print(&item);
printf("\n");
rmsgpack_dom_value_free(&item);
@ -76,10 +82,10 @@ int main(
index_name = argv[3];
field_name = argv[4];
rarchdb_create_index(&db, index_name, field_name);
libretrodb_create_index(&db, index_name, field_name);
} else {
printf("Unkonwn command %s\n", argv[2]);
return 1;
}
rarchdb_close(&db);
libretrodb_close(&db);
}

View File

@ -3,7 +3,7 @@
#include <stdlib.h>
#include <string.h>
int rarchdb_lua_to_rmsgpack_value(
int libretrodb_lua_to_rmsgpack_value(
lua_State * L,
int index,
struct rmsgpack_dom_value * out

View File

@ -7,7 +7,7 @@
#include "rmsgpack_dom.h"
int rarchdb_lua_to_rmsgpack_value(
int libretrodb_lua_to_rmsgpack_value(
lua_State * L,
int index,
struct rmsgpack_dom_value * out

View File

@ -10,7 +10,7 @@
#include <lualib.h>
#include <lauxlib.h>
#include "rarchdb.h"
#include "libretrodb.h"
#include "lua_common.h"
int master_key = 1;
@ -62,7 +62,7 @@ static int value_provider(
if (lua_isnil(L, -1)) {
rv = 1;
} else if (lua_istable(L, -1)) {
rv = rarchdb_lua_to_rmsgpack_value(L, -1, out);
rv = libretrodb_lua_to_rmsgpack_value(L, -1, out);
} else {
printf("function `get_value' must return a table or nil\n");
}
@ -108,7 +108,7 @@ int main(
goto clean;
}
rv = rarchdb_create(dst, &value_provider, L);
rv = libretrodb_create(dst, &value_provider, L);
clean:
lua_close(L);
if (dst != -1) {

View File

@ -8,7 +8,7 @@
#include <ctype.h>
#include <string.h>
#include "rarchdb.h"
#include "libretrodb.h"
#include "rmsgpack_dom.h"
#include <compat/fnmatch.h>
@ -870,31 +870,30 @@ success:
}
void rarchdb_query_free(rarchdb_query * q) {
void libretrodb_query_free(void *q)
{
unsigned i;
struct query * real_q = (struct query*)q;
real_q->ref_count--;
if (real_q->ref_count > 0) {
if (real_q->ref_count > 0)
return;
}
for (i = 0; i < real_q->root.argc; i++) {
for (i = 0; i < real_q->root.argc; i++)
argument_free(&real_q->root.argv[i]);
}
}
rarchdb_query * rarchdb_query_compile(
struct rarchdb * db,
void *libretrodb_query_compile(
libretrodb_t * db,
const char * query,
size_t buff_len,
const char ** error
) {
)
{
struct buffer buff;
struct query *q = (struct query*)malloc(sizeof(struct query));
if (!q) {
if (!q)
goto clean;
}
memset(q, 0, sizeof(struct query));
q->ref_count = 1;
buff.data = query;
@ -914,9 +913,8 @@ rarchdb_query * rarchdb_query_compile(
}
buff = expect_eof(buff, error);
if (*error) {
if (*error)
goto clean;
}
if (q->root.func == NULL) {
raise_unexpected_eof(buff.offset, error);
@ -924,20 +922,20 @@ rarchdb_query * rarchdb_query_compile(
}
goto success;
clean:
if (q) {
rarchdb_query_free(q);
}
if (q)
libretrodb_query_free(q);
success:
return q;
}
void rarchdb_query_inc_ref(rarchdb_query * q) {
void libretrodb_query_inc_ref(libretrodb_query_t *q)
{
struct query * rq = (struct query*)q;
rq->ref_count += 1;
}
int rarchdb_query_filter(
rarchdb_query * q,
int libretrodb_query_filter(
libretrodb_query_t * q,
struct rmsgpack_dom_value * v
) {
struct invocation inv = ((struct query *)q)->root;

View File

@ -1,12 +1,14 @@
#ifndef __RARCHDB_QUERY_H__
#define __RARCHDB_QUERY_H__
#ifndef __LIBRETRODB_QUERY_H__
#define __LIBRETRODB_QUERY_H__
#include "rarchdb.h"
#include "libretrodb.h"
void rarchdb_query_inc_ref(rarchdb_query * q);
void rarchdb_query_dec_ref(rarchdb_query * q);
int rarchdb_query_filter(
rarchdb_query * q,
void libretrodb_query_inc_ref(libretrodb_query_t *q);
void libretrodb_query_dec_ref(libretrodb_query_t *q);
int libretrodb_query_filter(
libretrodb_query_t *q,
struct rmsgpack_dom_value * v
);

View File

@ -1,108 +0,0 @@
#ifndef __RARCHDB_H__
#define __RARCHDB_H__
#include <stdint.h>
#ifdef _WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif
#include "rmsgpack_dom.h"
typedef void rarchdb_query;
struct rarchdb
{
int fd;
uint64_t root;
uint64_t count;
uint64_t first_index_offset;
};
struct rarchdb_cursor
{
int is_valid;
int fd;
int eof;
rarchdb_query * query;
struct rarchdb * db;
};
typedef int (* rarchdb_value_provider)(
void * ctx,
struct rmsgpack_dom_value * out
);
int rarchdb_create(
int fd,
rarchdb_value_provider value_provider,
void * ctx
);
void rarchdb_close(struct rarchdb * db);
int rarchdb_open(
const char * path,
struct rarchdb * db
);
int rarchdb_create_index(
struct rarchdb * db,
const char * name,
const char * field_name
);
int rarchdb_find_entry(
struct rarchdb * db,
const char * index_name,
const void * key,
struct rmsgpack_dom_value * out
);
/**
* rarchdb_cursor_open:
* @db : Handle to database.
* @cursor : Handle to database cursor.
* @q : Query to execute.
*
* Opens cursor to database based on query @q.
*
* Returns: 0 if successful, otherwise negative.
**/
int rarchdb_cursor_open(
struct rarchdb * db,
struct rarchdb_cursor * cursor,
rarchdb_query * query
);
/**
* rarchdb_cursor_reset:
* @cursor : Handle to database cursor.
*
* Resets cursor.
*
* Returns: ???.
**/
int rarchdb_cursor_reset(struct rarchdb_cursor * cursor);
/**
* rarchdb_cursor_close:
* @cursor : Handle to database cursor.
*
* Closes cursor and frees up allocated memory.
**/
void rarchdb_cursor_close(struct rarchdb_cursor * cursor);
rarchdb_query * rarchdb_query_compile(
struct rarchdb * db,
const char * query,
size_t buff_len,
const char ** error
);
void rarchdb_query_free(rarchdb_query * q);
int rarchdb_cursor_read_item(
struct rarchdb_cursor * cursor,
struct rmsgpack_dom_value * out
);
#endif

View File

@ -21,7 +21,7 @@
#include <stdint.h>
#include <string.h>
#include "rarchdb_endian.h"
#include "libretrodb_endian.h"
static const uint8_t MPF_FIXMAP = 0x80;
static const uint8_t MPF_MAP16 = 0xde;

View File

@ -10,7 +10,7 @@
#include "lua.h"
#include "lauxlib.h"
#include "rarchdb.h"
#include "libretrodb.h"
#include "lua_common.h"
static int create_db (lua_State * L);
@ -36,7 +36,7 @@ static const struct luaL_Reg cursor_mt [] = {
{NULL, NULL}
};
static const struct luaL_Reg rarchdb_mt [] = {
static const struct luaL_Reg libretrodb_mt [] = {
{"__gc", db_close},
{"list_all", db_cursor_open},
{"query", db_query},
@ -49,7 +49,7 @@ LUALIB_API int luaopen_testlib (lua_State * L) {
lua_pushstring(L, "__index");
lua_pushvalue(L, -2);
lua_settable(L, -3);
luaL_openlib(L, NULL, rarchdb_mt, 0);
luaL_openlib(L, NULL, libretrodb_mt, 0);
luaL_newmetatable(L, "RarchDB.Cursor");
lua_pushstring(L, "__index");
@ -61,13 +61,13 @@ LUALIB_API int luaopen_testlib (lua_State * L) {
return 1;
}
static struct rarchdb_cursor * checkcursor(lua_State * L) {
static libretrodb_cursor * checkcursor(lua_State * L) {
void * ud = luaL_checkudata(L, 1, "RarchDB.Cursor");
luaL_argcheck(L, ud != NULL, 1, "`RarchDB.Cursor' expected");
return ud;
}
static struct rarchdb * checkdb(lua_State * L) {
static libretrodb * checkdb(lua_State * L) {
void * ud = luaL_checkudata(L, 1, "RarchDB.DB");
luaL_argcheck(L, ud != NULL, 1, "`RarchDB.DB' expected");
return ud;
@ -92,7 +92,7 @@ static int value_provider(
if (lua_isnil(L, -1)) {
rv = 1;
} else if (lua_istable(L, -1)) {
rv = rarchdb_lua_to_rmsgpack_value(L, -1, out);
rv = libretrodb_lua_to_rmsgpack_value(L, -1, out);
} else {
printf("function `get_value' must return a table or nil\n");
}
@ -117,18 +117,18 @@ static int create_db (lua_State * L) {
lua_error(L);
}
rv = rarchdb_create(dst, &value_provider, L);
rv = libretrodb_create(dst, &value_provider, L);
close(dst);
return 0;
}
static int db_new (lua_State * L) {
struct rarchdb * db = NULL;
libretrodb_t * db = NULL;
const char * db_file = NULL;
int rv;
db_file = luaL_checkstring(L, -1);
db = lua_newuserdata(L, sizeof(struct rarchdb));
if ((rv = rarchdb_open(db_file, db)) == 0) {
db = lua_newuserdata(L, sizeof(libretrodb_t));
if ((rv = libretrodb_open(db_file, db)) == 0) {
luaL_getmetatable(L, "RarchDB.DB");
lua_setmetatable(L, -2);
lua_pushnil(L);
@ -141,18 +141,18 @@ static int db_new (lua_State * L) {
}
static int db_close (lua_State * L) {
struct rarchdb * db = checkdb(L);
rarchdb_close(db);
libretrodb_t *db = checkdb(L);
libretrodb_close(db);
return 0;
}
static int db_query (lua_State * L) {
int rv;
struct rarchdb_cursor * cursor = NULL;
struct rarchdb * db = checkdb(L);
libretrodb_cursor_t *cursor = NULL;
libretrodb_t *db = checkdb(L);
const char * query = luaL_checkstring(L, -1);
const char * error = NULL;
rarchdb_query * q = rarchdb_query_compile(
libretrodb_query_t *q = libretrodb_query_compile(
db,
query,
strlen(query),
@ -162,8 +162,8 @@ static int db_query (lua_State * L) {
lua_pushnil(L);
lua_pushstring(L, error);
} else {
cursor = lua_newuserdata(L, sizeof(struct rarchdb));
if ((rv = rarchdb_cursor_open(db, cursor, q)) == 0) {
cursor = lua_newuserdata(L, sizeof(libretrodb_t));
if ((rv = libretrodb_cursor_open(db, cursor, q)) == 0) {
luaL_getmetatable(L, "RarchDB.Cursor");
lua_setmetatable(L, -2);
lua_pushnil(L);
@ -172,16 +172,16 @@ static int db_query (lua_State * L) {
lua_pushnil(L);
lua_pushstring(L, strerror(-rv));
}
rarchdb_query_free(q);
libretrodb_query_free(q);
}
return 2;
}
static int db_cursor_open (lua_State * L) {
int rv;
struct rarchdb_cursor * cursor = NULL;
struct rarchdb * db = checkdb(L);
cursor = lua_newuserdata(L, sizeof(struct rarchdb));
if ((rv = rarchdb_cursor_open(db, cursor, NULL)) == 0) {
libretrodb_cursor_t *cursor = NULL;
libretrodb_t *db = checkdb(L);
cursor = lua_newuserdata(L, sizeof(libretrodb_t));
if ((rv = libretrodb_cursor_open(db, cursor, NULL)) == 0) {
luaL_getmetatable(L, "RarchDB.Cursor");
lua_setmetatable(L, -2);
lua_pushnil(L);
@ -193,8 +193,8 @@ static int db_cursor_open (lua_State * L) {
return 2;
}
static int cursor_close (lua_State * L) {
struct rarchdb_cursor * cursor = checkcursor(L);
rarchdb_cursor_close(cursor);
libretrodb_cursor_t *cursor = checkcursor(L);
libretrodb_cursor_close(cursor);
return 0;
}
@ -272,9 +272,9 @@ static void push_rmsgpack_value(
}
static int cursor_read (lua_State * L) {
struct rarchdb_cursor * cursor = checkcursor(L);
libretrodb_cursor_t *cursor = checkcursor(L);
struct rmsgpack_dom_value value;
if (rarchdb_cursor_read_item(cursor, &value) == 0) {
if (libretrodb_cursor_read_item(cursor, &value) == 0) {
push_rmsgpack_value(L, &value);
} else {
lua_pushnil(L);
@ -283,7 +283,7 @@ static int cursor_read (lua_State * L) {
}
static int cursor_iter (lua_State * L) {
struct rarchdb_cursor * cursor = checkcursor(L);
libretrodb_cursor_t * cursor = checkcursor(L);
luaL_getmetafield(L, -1, "read");
lua_pushvalue(L, -2);
return 2;

View File

@ -33,7 +33,7 @@
#endif
#ifdef HAVE_LIBRETRODB
#include "../libretrodb/rarchdb.h"
#include "../libretrodb/libretrodb.h"
#endif
#include "../input/input_remapping.h"
@ -1596,8 +1596,8 @@ static int deferred_push_database_manager_list_deferred(void *data, void *userda
{
#ifdef HAVE_LIBRETRODB
int rv;
struct rarchdb db;
struct rarchdb_cursor cur;
libretrodb_t db;
libretrodb_cursor_t cur;
struct rmsgpack_dom_value item;
#endif
unsigned i;
@ -1611,13 +1611,13 @@ static int deferred_push_database_manager_list_deferred(void *data, void *userda
menu_list_clear(list);
#ifdef HAVE_LIBRETRODB
if ((rv = rarchdb_open(path, &db)) != 0)
if ((rv = libretrodb_open(path, &db)) != 0)
return -1;
if ((rv = rarchdb_cursor_open(&db, &cur, NULL)) != 0)
if ((rv = libretrodb_cursor_open(&db, &cur, NULL)) != 0)
return -1;
while (rarchdb_cursor_read_item(&cur, &item) == 0)
while (libretrodb_cursor_read_item(&cur, &item) == 0)
{
if (item.type != RDT_MAP)
continue;
@ -1636,8 +1636,8 @@ static int deferred_push_database_manager_list_deferred(void *data, void *userda
}
}
rarchdb_cursor_close(&cur);
rarchdb_close(&db);
libretrodb_cursor_close(&cur);
libretrodb_close(&db);
#endif
menu_list_sort_on_alt(list);
driver.menu->scroll_indices_size = 0;