mirror of
https://github.com/libretro/RetroArch
synced 2025-02-20 15:40:44 +00:00
Revert to last working version of libretro-db
This commit is contained in:
parent
d65cc5fd2f
commit
b32b17f4ae
@ -22,52 +22,46 @@
|
||||
|
||||
struct node_iter_ctx
|
||||
{
|
||||
libretrodb_t *db;
|
||||
libretrodb_index_t *idx;
|
||||
libretrodb_t *db;
|
||||
libretrodb_index_t *idx;
|
||||
};
|
||||
|
||||
static struct rmsgpack_dom_value sentinal;
|
||||
|
||||
static INLINE off_t flseek(FILE *fp, int offset, int whence)
|
||||
static int libretrodb_read_metadata(int fd, libretrodb_metadata_t *md)
|
||||
{
|
||||
if (fseek(fp, offset, whence) != 0)
|
||||
return (off_t)-1;
|
||||
return (off_t)ftell(fp);
|
||||
return rmsgpack_dom_read_into(fd, "count", &md->count, NULL);
|
||||
}
|
||||
|
||||
static int libretrodb_read_metadata(FILE *fp, libretrodb_metadata_t *md)
|
||||
static int libretrodb_write_metadata(int fd, libretrodb_metadata_t *md)
|
||||
{
|
||||
return rmsgpack_dom_read_into(fp, "count", &md->count, NULL);
|
||||
}
|
||||
|
||||
static int libretrodb_write_metadata(FILE *fp, libretrodb_metadata_t *md)
|
||||
{
|
||||
rmsgpack_write_map_header(fp, 1);
|
||||
rmsgpack_write_string(fp, "count", strlen("count"));
|
||||
return rmsgpack_write_uint(fp, md->count);
|
||||
rmsgpack_write_map_header(fd, 1);
|
||||
rmsgpack_write_string(fd, "count", strlen("count"));
|
||||
return rmsgpack_write_uint(fd, md->count);
|
||||
}
|
||||
|
||||
static int validate_document(const struct rmsgpack_dom_value * doc)
|
||||
{
|
||||
unsigned i;
|
||||
struct rmsgpack_dom_value key, value;
|
||||
struct rmsgpack_dom_value key;
|
||||
struct rmsgpack_dom_value value;
|
||||
int rv = 0;
|
||||
|
||||
if (doc->type != RDT_MAP)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < doc->val.map.len; i++)
|
||||
for (i = 0; i < doc->map.len; i++)
|
||||
{
|
||||
key = doc->val.map.items[i].key;
|
||||
value = doc->val.map.items[i].value;
|
||||
key = doc->map.items[i].key;
|
||||
value = doc->map.items[i].value;
|
||||
|
||||
if (key.type != RDT_STRING)
|
||||
return -EINVAL;
|
||||
|
||||
if (key.val.string.len <= 0)
|
||||
if (key.string.len <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (key.val.string.buff[0] == '$')
|
||||
if (key.string.buff[0] == '$')
|
||||
return -EINVAL;
|
||||
|
||||
if (value.type != RDT_MAP)
|
||||
@ -80,95 +74,91 @@ static int validate_document(const struct rmsgpack_dom_value * doc)
|
||||
return rv;
|
||||
}
|
||||
|
||||
int libretrodb_create(FILE *fp, libretrodb_value_provider value_provider,
|
||||
void * ctx)
|
||||
int libretrodb_create(int fd, libretrodb_value_provider value_provider,
|
||||
void * ctx)
|
||||
{
|
||||
int rv;
|
||||
off_t root;
|
||||
libretrodb_metadata_t md;
|
||||
struct rmsgpack_dom_value item;
|
||||
uint64_t item_count = 0;
|
||||
libretrodb_header_t header = {{0}};
|
||||
uint64_t item_count = 0;
|
||||
struct rmsgpack_dom_value item = {};
|
||||
libretrodb_header_t header = {};
|
||||
|
||||
memcpy(header.magic_number, MAGIC_NUMBER, sizeof(MAGIC_NUMBER)-1);
|
||||
root = flseek(fp, 0, SEEK_CUR);
|
||||
root = lseek(fd, 0, SEEK_CUR);
|
||||
|
||||
/* We write the header in the end because we need to know the size of
|
||||
* the db first */
|
||||
|
||||
flseek(fp, sizeof(libretrodb_header_t), SEEK_CUR);
|
||||
lseek(fd, sizeof(libretrodb_header_t), SEEK_CUR);
|
||||
|
||||
while ((rv = value_provider(ctx, &item)) == 0)
|
||||
{
|
||||
if ((rv = validate_document(&item)) < 0)
|
||||
goto error;
|
||||
goto clean;
|
||||
|
||||
if ((rv = rmsgpack_dom_write(fp, &item)) < 0)
|
||||
goto error;
|
||||
if ((rv = rmsgpack_dom_write(fd, &item)) < 0)
|
||||
goto clean;
|
||||
|
||||
item_count++;
|
||||
}
|
||||
|
||||
if (rv < 0)
|
||||
goto error;
|
||||
goto clean;
|
||||
|
||||
if ((rv = rmsgpack_dom_write(fp, &sentinal)) < 0)
|
||||
goto error;
|
||||
if ((rv = rmsgpack_dom_write(fd, &sentinal)) < 0)
|
||||
goto clean;
|
||||
|
||||
header.metadata_offset = httobe64(flseek(fp, 0, SEEK_CUR));
|
||||
header.metadata_offset = httobe64(lseek(fd, 0, SEEK_CUR));
|
||||
md.count = item_count;
|
||||
libretrodb_write_metadata(fp, &md);
|
||||
flseek(fp, root, SEEK_SET);
|
||||
fwrite(&header, 1, sizeof(header), fp);
|
||||
|
||||
error:
|
||||
libretrodb_write_metadata(fd, &md);
|
||||
lseek(fd, root, SEEK_SET);
|
||||
write(fd, &header, sizeof(header));
|
||||
clean:
|
||||
rmsgpack_dom_value_free(&item);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int libretrodb_read_index_header(FILE *fp, libretrodb_index_t *idx)
|
||||
static int libretrodb_read_index_header(int fd, libretrodb_index_t *idx)
|
||||
{
|
||||
uint64_t name_len = 50;
|
||||
return rmsgpack_dom_read_into(fp,
|
||||
return rmsgpack_dom_read_into(fd,
|
||||
"name", idx->name, &name_len,
|
||||
"key_size", &idx->key_size,
|
||||
"next", &idx->next, NULL);
|
||||
}
|
||||
|
||||
static void libretrodb_write_index_header(FILE *fp, libretrodb_index_t * idx)
|
||||
static void libretrodb_write_index_header(int fd, libretrodb_index_t * idx)
|
||||
{
|
||||
rmsgpack_write_map_header(fp, 3);
|
||||
rmsgpack_write_string(fp, "name", strlen("name"));
|
||||
rmsgpack_write_string(fp, idx->name, strlen(idx->name));
|
||||
rmsgpack_write_string(fp, "key_size", strlen("key_size"));
|
||||
rmsgpack_write_uint(fp, idx->key_size);
|
||||
rmsgpack_write_string(fp, "next", strlen("next"));
|
||||
rmsgpack_write_uint(fp, idx->next);
|
||||
rmsgpack_write_map_header(fd, 3);
|
||||
rmsgpack_write_string(fd, "name", strlen("name"));
|
||||
rmsgpack_write_string(fd, idx->name, strlen(idx->name));
|
||||
rmsgpack_write_string(fd, "key_size", strlen("key_size"));
|
||||
rmsgpack_write_uint(fd, idx->key_size);
|
||||
rmsgpack_write_string(fd, "next", strlen("next"));
|
||||
rmsgpack_write_uint(fd, idx->next);
|
||||
}
|
||||
|
||||
void libretrodb_close(libretrodb_t *db)
|
||||
{
|
||||
if (!db)
|
||||
return;
|
||||
|
||||
fclose(db->fp);
|
||||
db->fp = NULL;
|
||||
close(db->fd);
|
||||
db->fd = -1;
|
||||
}
|
||||
|
||||
int libretrodb_open(const char *path, libretrodb_t *db)
|
||||
{
|
||||
int rv;
|
||||
libretrodb_header_t header;
|
||||
libretrodb_metadata_t md;
|
||||
FILE *fp = fopen(path, "rb");
|
||||
int rv;
|
||||
int fd = open(path, O_RDWR);
|
||||
|
||||
if (fp == NULL)
|
||||
if (fd == -1)
|
||||
return -errno;
|
||||
|
||||
strcpy(db->path, path);
|
||||
db->root = flseek(fp, 0, SEEK_CUR);
|
||||
db->root = lseek(fd, 0, SEEK_CUR);
|
||||
|
||||
if ((rv = fread(&header, 1, sizeof(header), fp)) != sizeof(header))
|
||||
if ((rv = read(fd, &header, sizeof(header))) == -1)
|
||||
{
|
||||
rv = -errno;
|
||||
goto error;
|
||||
@ -181,37 +171,37 @@ int libretrodb_open(const char *path, libretrodb_t *db)
|
||||
}
|
||||
|
||||
header.metadata_offset = betoht64(header.metadata_offset);
|
||||
flseek(fp, (int)header.metadata_offset, SEEK_SET);
|
||||
lseek(fd, header.metadata_offset, SEEK_SET);
|
||||
|
||||
if (libretrodb_read_metadata(fp, &md) < 0)
|
||||
if (libretrodb_read_metadata(fd, &md) < 0)
|
||||
{
|
||||
rv = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
db->count = md.count;
|
||||
db->first_index_offset = flseek(fp, 0, SEEK_CUR);
|
||||
db->fp = fp;
|
||||
db->count = md.count;
|
||||
db->first_index_offset = lseek(fd, 0, SEEK_CUR);
|
||||
db->fd = fd;
|
||||
return 0;
|
||||
error:
|
||||
fclose(fp);
|
||||
close(fd);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int libretrodb_find_index(libretrodb_t *db, const char *index_name,
|
||||
libretrodb_index_t *idx)
|
||||
{
|
||||
off_t eof = flseek(db->fp, 0, SEEK_END);
|
||||
off_t offset = flseek(db->fp, (int)db->first_index_offset, SEEK_SET);
|
||||
off_t eof = lseek(db->fd, 0, SEEK_END);
|
||||
off_t offset = lseek(db->fd, db->first_index_offset, SEEK_SET);
|
||||
|
||||
while (offset < eof)
|
||||
{
|
||||
libretrodb_read_index_header(db->fp, idx);
|
||||
libretrodb_read_index_header(db->fd, idx);
|
||||
|
||||
if (strncmp(index_name, idx->name, strlen(idx->name)) == 0)
|
||||
return 0;
|
||||
|
||||
offset = flseek(db->fp, (int)idx->next, SEEK_CUR);
|
||||
offset = lseek(db->fd, idx->next, SEEK_CUR);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@ -247,27 +237,27 @@ static int binsearch(const void * buff, const void * item,
|
||||
}
|
||||
|
||||
int libretrodb_find_entry(libretrodb_t *db, const char *index_name,
|
||||
const void *key, struct rmsgpack_dom_value *out)
|
||||
const void *key, struct rmsgpack_dom_value *out)
|
||||
{
|
||||
libretrodb_index_t idx;
|
||||
int rv;
|
||||
void * buff;
|
||||
uint64_t offset;
|
||||
void *buff = NULL;
|
||||
ssize_t bufflen, nread = 0;
|
||||
|
||||
if (libretrodb_find_index(db, index_name, &idx) < 0)
|
||||
return -1;
|
||||
|
||||
bufflen = idx.next;
|
||||
buff = malloc(bufflen);
|
||||
buff = malloc(bufflen);
|
||||
|
||||
if (!buff)
|
||||
return -ENOMEM;
|
||||
|
||||
while (nread < bufflen)
|
||||
{
|
||||
void *buff_ = (uint64_t *)buff + nread;
|
||||
rv = fread(buff_, 1, bufflen - nread, db->fp);
|
||||
void * buff_ = (uint64_t *)buff + nread;
|
||||
rv = read(db->fd, buff_, bufflen - nread);
|
||||
|
||||
if (rv <= 0)
|
||||
{
|
||||
@ -277,13 +267,18 @@ int libretrodb_find_entry(libretrodb_t *db, const char *index_name,
|
||||
nread += rv;
|
||||
}
|
||||
|
||||
rv = binsearch(buff, key, db->count, (uint8_t)idx.key_size, &offset);
|
||||
rv = binsearch(buff, key, db->count, idx.key_size, &offset);
|
||||
free(buff);
|
||||
|
||||
if (rv == 0)
|
||||
flseek(db->fp, (int)offset, SEEK_SET);
|
||||
lseek(db->fd, offset, SEEK_SET);
|
||||
|
||||
return rmsgpack_dom_read(db->fp, out);
|
||||
rv = rmsgpack_dom_read(db->fd, out);
|
||||
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -296,9 +291,9 @@ int libretrodb_find_entry(libretrodb_t *db, const char *index_name,
|
||||
**/
|
||||
int libretrodb_cursor_reset(libretrodb_cursor_t *cursor)
|
||||
{
|
||||
cursor->eof = 0;
|
||||
return flseek(cursor->fp,
|
||||
(int)cursor->db->root + sizeof(libretrodb_header_t),
|
||||
cursor->eof = 0;
|
||||
return lseek(cursor->fd,
|
||||
cursor->db->root + sizeof(libretrodb_header_t),
|
||||
SEEK_SET);
|
||||
}
|
||||
|
||||
@ -311,7 +306,7 @@ int libretrodb_cursor_read_item(libretrodb_cursor_t *cursor,
|
||||
return EOF;
|
||||
|
||||
retry:
|
||||
rv = rmsgpack_dom_read(cursor->fp, out);
|
||||
rv = rmsgpack_dom_read(cursor->fd, out);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
@ -324,10 +319,7 @@ retry:
|
||||
if (cursor->query)
|
||||
{
|
||||
if (!libretrodb_query_filter(cursor->query, out))
|
||||
{
|
||||
rmsgpack_dom_value_free(out);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -344,16 +336,16 @@ void libretrodb_cursor_close(libretrodb_cursor_t *cursor)
|
||||
if (!cursor)
|
||||
return;
|
||||
|
||||
fclose(cursor->fp);
|
||||
close(cursor->fd);
|
||||
cursor->is_valid = 0;
|
||||
cursor->fd = -1;
|
||||
cursor->eof = 1;
|
||||
cursor->db = NULL;
|
||||
|
||||
if (cursor->query)
|
||||
libretrodb_query_free(cursor->query);
|
||||
if (cursor->query)
|
||||
libretrodb_query_free(cursor->query);
|
||||
|
||||
cursor->is_valid = 0;
|
||||
cursor->fp = NULL;
|
||||
cursor->eof = 1;
|
||||
cursor->db = NULL;
|
||||
cursor->query = NULL;
|
||||
cursor->query = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -369,17 +361,15 @@ void libretrodb_cursor_close(libretrodb_cursor_t *cursor)
|
||||
int libretrodb_cursor_open(libretrodb_t *db, libretrodb_cursor_t *cursor,
|
||||
libretrodb_query_t *q)
|
||||
{
|
||||
cursor->fp = fopen(db->path, "rb");
|
||||
cursor->fd = dup(db->fd);
|
||||
|
||||
if (cursor->fp == NULL)
|
||||
if (cursor->fd == -1)
|
||||
return -errno;
|
||||
|
||||
cursor->db = db;
|
||||
cursor->db = db;
|
||||
cursor->is_valid = 1;
|
||||
|
||||
libretrodb_cursor_reset(cursor);
|
||||
|
||||
cursor->query = q;
|
||||
cursor->query = q;
|
||||
|
||||
if (q)
|
||||
libretrodb_query_inc_ref(q);
|
||||
@ -389,124 +379,138 @@ int libretrodb_cursor_open(libretrodb_t *db, libretrodb_cursor_t *cursor,
|
||||
|
||||
static int node_iter(void * value, void * ctx)
|
||||
{
|
||||
struct node_iter_ctx *nictx = (struct node_iter_ctx*)ctx;
|
||||
size_t size = nictx->idx->key_size + sizeof(uint64_t);
|
||||
struct node_iter_ctx *nictx = (struct node_iter_ctx*)ctx;
|
||||
|
||||
if (fwrite(value, 1, size, nictx->db->fp) == size)
|
||||
return 0;
|
||||
if (write(nictx->db->fd, value,
|
||||
nictx->idx->key_size + sizeof(uint64_t)) > 0)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint64_t libretrodb_tell(libretrodb_t *db)
|
||||
{
|
||||
return (uint64_t)ftell(db->fp);
|
||||
return lseek(db->fd, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
int libretrodb_create_index(libretrodb_t *db,
|
||||
const char *name, const char *field_name)
|
||||
{
|
||||
struct node_iter_ctx nictx;
|
||||
struct rmsgpack_dom_value key;
|
||||
libretrodb_index_t idx;
|
||||
struct rmsgpack_dom_value item;
|
||||
struct rmsgpack_dom_value *field;
|
||||
struct bintree tree;
|
||||
libretrodb_cursor_t cur = {0};
|
||||
void *buff = NULL;
|
||||
uint64_t *buff_u64 = NULL;
|
||||
uint64_t idx_header_offset = 0;
|
||||
uint8_t field_size = 0;
|
||||
uint64_t item_loc = libretrodb_tell(db);
|
||||
int rv;
|
||||
struct node_iter_ctx nictx;
|
||||
struct rmsgpack_dom_value key;
|
||||
libretrodb_index_t idx;
|
||||
struct rmsgpack_dom_value item;
|
||||
struct rmsgpack_dom_value * field;
|
||||
struct bintree tree;
|
||||
libretrodb_cursor_t cur;
|
||||
uint64_t idx_header_offset;
|
||||
void * buff = NULL;
|
||||
uint64_t * buff_u64 = NULL;
|
||||
uint8_t field_size = 0;
|
||||
uint64_t item_loc = libretrodb_tell(db);
|
||||
|
||||
bintree_new(&tree, node_compare, &field_size);
|
||||
bintree_new(&tree, node_compare, &field_size);
|
||||
|
||||
if (libretrodb_cursor_open(db, &cur, NULL) != 0)
|
||||
goto error;
|
||||
|
||||
key.type = RDT_STRING;
|
||||
key.val.string.len = strlen(field_name);
|
||||
|
||||
/* We know we aren't going to change it */
|
||||
key.val.string.buff = (char*)field_name;
|
||||
|
||||
while (libretrodb_cursor_read_item(&cur, &item) == 0)
|
||||
if (libretrodb_cursor_open(db, &cur, NULL) != 0)
|
||||
{
|
||||
if (item.type != RDT_MAP)
|
||||
rv = -1;
|
||||
goto clean;
|
||||
}
|
||||
|
||||
key.type = RDT_STRING;
|
||||
key.string.len = strlen(field_name);
|
||||
|
||||
/* We know we aren't going to change it */
|
||||
key.string.buff = (char *) field_name;
|
||||
|
||||
while (libretrodb_cursor_read_item(&cur, &item) == 0)
|
||||
{
|
||||
if (item.type != RDT_MAP)
|
||||
{
|
||||
printf("Only map keys are supported\n");
|
||||
goto error;
|
||||
}
|
||||
rv = -EINVAL;
|
||||
printf("Only map keys are supported\n");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
field = rmsgpack_dom_value_map_value(&item, &key);
|
||||
field = rmsgpack_dom_value_map_value(&item, &key);
|
||||
|
||||
if (!field)
|
||||
if (!field)
|
||||
{
|
||||
printf("field not found in item\n");
|
||||
goto error;
|
||||
}
|
||||
rv = -EINVAL;
|
||||
printf("field not found in item\n");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
if (field->type != RDT_BINARY)
|
||||
if (field->type != RDT_BINARY)
|
||||
{
|
||||
printf("field is not binary\n");
|
||||
goto error;
|
||||
}
|
||||
rv = -EINVAL;
|
||||
printf("field is not binary\n");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
if (field->val.binary.len == 0)
|
||||
if (field->binary.len == 0)
|
||||
{
|
||||
printf("field is empty\n");
|
||||
goto error;
|
||||
}
|
||||
rv = -EINVAL;
|
||||
printf("field is empty\n");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
if (field_size == 0)
|
||||
field_size = field->val.binary.len;
|
||||
else if (field->val.binary.len != field_size)
|
||||
if (field_size == 0)
|
||||
field_size = field->binary.len;
|
||||
else if (field->binary.len != field_size)
|
||||
{
|
||||
printf("field is not of correct size\n");
|
||||
goto error;
|
||||
}
|
||||
rv = -EINVAL;
|
||||
printf("field is not of correct size\n");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
buff = malloc(field_size + sizeof(uint64_t));
|
||||
if (!buff)
|
||||
goto error;
|
||||
|
||||
memcpy(buff, field->val.binary.buff, field_size);
|
||||
|
||||
buff_u64 = (uint64_t *)buff + field_size;
|
||||
|
||||
memcpy(buff_u64, &item_loc, sizeof(uint64_t));
|
||||
|
||||
if (bintree_insert(&tree, buff) != 0)
|
||||
buff = malloc(field_size + sizeof(uint64_t));
|
||||
if (!buff)
|
||||
{
|
||||
printf("Value is not unique: ");
|
||||
rmsgpack_dom_value_print(field);
|
||||
printf("\n");
|
||||
goto error;
|
||||
}
|
||||
buff = NULL;
|
||||
rmsgpack_dom_value_free(&item);
|
||||
item_loc = libretrodb_tell(db);
|
||||
}
|
||||
rv = -ENOMEM;
|
||||
goto clean;
|
||||
}
|
||||
|
||||
idx_header_offset = flseek(db->fp, 0, SEEK_END);
|
||||
(void)idx_header_offset;
|
||||
strncpy(idx.name, name, 50);
|
||||
memcpy(buff, field->binary.buff, field_size);
|
||||
|
||||
idx.name[49] = '\0';
|
||||
idx.key_size = field_size;
|
||||
idx.next = db->count * (field_size + sizeof(uint64_t));
|
||||
libretrodb_write_index_header(db->fp, &idx);
|
||||
buff_u64 = (uint64_t *)buff + field_size;
|
||||
|
||||
nictx.db = db;
|
||||
nictx.idx = &idx;
|
||||
bintree_iterate(&tree, node_iter, &nictx);
|
||||
bintree_free(&tree);
|
||||
memcpy(buff_u64, &item_loc, sizeof(uint64_t));
|
||||
|
||||
error:
|
||||
rmsgpack_dom_value_free(&item);
|
||||
if (buff)
|
||||
free(buff);
|
||||
if (cur.is_valid)
|
||||
libretrodb_cursor_close(&cur);
|
||||
return 0;
|
||||
if (bintree_insert(&tree, buff) != 0)
|
||||
{
|
||||
printf("Value is not unique: ");
|
||||
rmsgpack_dom_value_print(field);
|
||||
printf("\n");
|
||||
rv = -EINVAL;
|
||||
goto clean;
|
||||
}
|
||||
buff = NULL;
|
||||
rmsgpack_dom_value_free(&item);
|
||||
item_loc = libretrodb_tell(db);
|
||||
}
|
||||
|
||||
(void)rv;
|
||||
(void)idx_header_offset;
|
||||
|
||||
idx_header_offset = lseek(db->fd, 0, SEEK_END);
|
||||
strncpy(idx.name, name, 50);
|
||||
|
||||
idx.name[49] = '\0';
|
||||
idx.key_size = field_size;
|
||||
idx.next = db->count * (field_size + sizeof(uint64_t));
|
||||
libretrodb_write_index_header(db->fd, &idx);
|
||||
|
||||
nictx.db = db;
|
||||
nictx.idx = &idx;
|
||||
bintree_iterate(&tree, node_iter, &nictx);
|
||||
bintree_free(&tree);
|
||||
clean:
|
||||
rmsgpack_dom_value_free(&item);
|
||||
if (buff)
|
||||
free(buff);
|
||||
if (cur.is_valid)
|
||||
libretrodb_cursor_close(&cur);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
#ifndef __LIBRETRODB_H__
|
||||
#define __LIBRETRODB_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
@ -20,7 +19,7 @@ typedef struct libretrodb_query libretrodb_query_t;
|
||||
|
||||
typedef struct libretrodb
|
||||
{
|
||||
FILE *fp;
|
||||
int fd;
|
||||
uint64_t root;
|
||||
uint64_t count;
|
||||
uint64_t first_index_offset;
|
||||
@ -48,7 +47,7 @@ typedef struct libretrodb_header
|
||||
typedef struct libretrodb_cursor
|
||||
{
|
||||
int is_valid;
|
||||
FILE *fp;
|
||||
int fd;
|
||||
int eof;
|
||||
libretrodb_query_t * query;
|
||||
libretrodb_t * db;
|
||||
@ -57,7 +56,7 @@ typedef struct libretrodb_cursor
|
||||
typedef int (* libretrodb_value_provider)(void * ctx,
|
||||
struct rmsgpack_dom_value * out);
|
||||
|
||||
int libretrodb_create(FILE *fp, libretrodb_value_provider value_provider,
|
||||
int libretrodb_create(int fd, libretrodb_value_provider value_provider,
|
||||
void * ctx);
|
||||
|
||||
void libretrodb_close(libretrodb_t * db);
|
||||
|
@ -31,7 +31,7 @@ int main(int argc, char ** argv)
|
||||
printf("Could not open db file '%s': %s\n", path, strerror(-rv));
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(command, "list"))
|
||||
else if (strcmp(command, "list") == 0)
|
||||
{
|
||||
if ((rv = libretrodb_cursor_open(&db, &cur, NULL)) != 0)
|
||||
{
|
||||
@ -52,7 +52,7 @@ int main(int argc, char ** argv)
|
||||
rmsgpack_dom_value_free(&item);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(command, "find"))
|
||||
else if (strcmp(command, "find") == 0)
|
||||
{
|
||||
if (argc != 4)
|
||||
{
|
||||
@ -83,7 +83,7 @@ int main(int argc, char ** argv)
|
||||
rmsgpack_dom_value_free(&item);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(command, "create-index"))
|
||||
else if (strcmp(command, "create-index") == 0)
|
||||
{
|
||||
const char * index_name, * field_name;
|
||||
|
||||
|
@ -3,97 +3,91 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int libretrodb_lua_to_rmsgpack_value(lua_State * L, int index, struct rmsgpack_dom_value * out)
|
||||
{
|
||||
lua_Number tmp_num;
|
||||
size_t tmp_len;
|
||||
int i, rv = -1;
|
||||
const char * tmp_string = NULL;
|
||||
char * tmp_buff = NULL;
|
||||
struct rmsgpack_dom_value * tmp_value;
|
||||
const int key_idx = -2;
|
||||
const int value_idx = -1;
|
||||
const int MAX_FIELDS = 100;
|
||||
int libretrodb_lua_to_rmsgpack_value(
|
||||
lua_State * L,
|
||||
int index,
|
||||
struct rmsgpack_dom_value * out
|
||||
) {
|
||||
|
||||
out->type = RDT_MAP;
|
||||
out->val.map.len = 0;
|
||||
out->val.map.items = calloc(MAX_FIELDS, sizeof(struct rmsgpack_dom_pair));
|
||||
lua_pushnil(L);
|
||||
int rv = -1;
|
||||
int i;
|
||||
const char * tmp_string = NULL;
|
||||
char * tmp_buff = NULL;
|
||||
struct rmsgpack_dom_value * tmp_value;
|
||||
const int key_idx = -2;
|
||||
const int value_idx = -1;
|
||||
const int MAX_FIELDS = 100;
|
||||
size_t tmp_len;
|
||||
lua_Number tmp_num;
|
||||
|
||||
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;
|
||||
out->type = RDT_MAP;
|
||||
out->map.len = 0;
|
||||
out->map.items = calloc(MAX_FIELDS, sizeof(struct rmsgpack_dom_pair));
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, index - 1) != 0) {
|
||||
if (out->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->map.len;
|
||||
tmp_buff = strdup(lua_tostring(L, key_idx));
|
||||
out->map.items[i].key.type = RDT_STRING;
|
||||
out->map.items[i].key.string.len = strlen(tmp_buff);
|
||||
out->map.items[i].key.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:
|
||||
tmp_value = &out->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->int_ = tmp_num;
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
tmp_value->type = RDT_BOOL;
|
||||
tmp_value->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->string.len = strlen(tmp_buff);
|
||||
tmp_value->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->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->binary.len = tmp_len;
|
||||
tmp_value->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;
|
||||
tmp_value->type = RDT_NULL;
|
||||
}
|
||||
out->map.len++;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
rv = 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -20,100 +20,94 @@ 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;
|
||||
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]);
|
||||
}
|
||||
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)
|
||||
);
|
||||
}
|
||||
if (lua_pcall(L, argc, 0, 0) != 0)
|
||||
{
|
||||
printf(
|
||||
"error running function `init': %s\n",
|
||||
lua_tostring(L, -1)
|
||||
);
|
||||
}
|
||||
|
||||
return rv;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int value_provider(
|
||||
void * ctx,
|
||||
struct rmsgpack_dom_value * out
|
||||
) {
|
||||
int rv;
|
||||
lua_State * L = ctx;
|
||||
static int value_provider(void * ctx, struct rmsgpack_dom_value *out)
|
||||
{
|
||||
int rv;
|
||||
lua_State * L = ctx;
|
||||
|
||||
lua_getglobal(L, "get_value");
|
||||
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_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;
|
||||
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
|
||||
){
|
||||
const char * db_file;
|
||||
const char * lua_file;
|
||||
int dst = -1;
|
||||
int rv = 0;
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
const char * db_file;
|
||||
const char * lua_file;
|
||||
int dst = -1;
|
||||
int rv = 0;
|
||||
|
||||
if (argc < 3) {
|
||||
printf("usage:\n%s <db file> <lua file> [args ...]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
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];
|
||||
db_file = argv[1];
|
||||
lua_file = argv[2];
|
||||
|
||||
lua_State * L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
luaL_dostring(L, LUA_COMMON);
|
||||
lua_State * L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
luaL_dostring(L, LUA_COMMON);
|
||||
|
||||
if (luaL_dofile(L, lua_file) != 0) {
|
||||
return 1;
|
||||
}
|
||||
if (luaL_dofile(L, lua_file) != 0)
|
||||
return 1;
|
||||
|
||||
call_init(L, argc - 2, (const char **) argv + 2);
|
||||
call_init(L, argc - 2, (const char **) argv + 2);
|
||||
|
||||
dst = open(db_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
if (dst == -1) {
|
||||
printf(
|
||||
"Could not open destination file '%s': %s\n",
|
||||
db_file,
|
||||
strerror(errno)
|
||||
);
|
||||
rv = errno;
|
||||
goto clean;
|
||||
}
|
||||
dst = open(db_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
if (dst == -1)
|
||||
{
|
||||
printf(
|
||||
"Could not open destination file '%s': %s\n",
|
||||
db_file,
|
||||
strerror(errno)
|
||||
);
|
||||
rv = errno;
|
||||
goto clean;
|
||||
}
|
||||
|
||||
rv = libretrodb_create(dst, &value_provider, L);
|
||||
|
||||
rv = libretrodb_create(dst, &value_provider, L);
|
||||
clean:
|
||||
lua_close(L);
|
||||
if (dst != -1) {
|
||||
close(dst);
|
||||
}
|
||||
return rv;
|
||||
lua_close(L);
|
||||
if (dst != -1)
|
||||
close(dst);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -8,32 +8,30 @@
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <compat/fnmatch.h>
|
||||
#include <compat/strl.h>
|
||||
|
||||
#include "libretrodb.h"
|
||||
#include "query.h"
|
||||
|
||||
#include "rmsgpack_dom.h"
|
||||
#include <compat/fnmatch.h>
|
||||
|
||||
#define MAX_ERROR_LEN 256
|
||||
#undef MAX_ARGS
|
||||
#define MAX_ARGS 50
|
||||
|
||||
static char tmp_error_buff [MAX_ERROR_LEN] = {0};
|
||||
static char tmp_error_buff [MAX_ERROR_LEN] = {};
|
||||
|
||||
struct buffer
|
||||
{
|
||||
const char *data;
|
||||
size_t len;
|
||||
off_t offset;
|
||||
const char *data;
|
||||
size_t len;
|
||||
off_t offset;
|
||||
};
|
||||
|
||||
/* Errors */
|
||||
static void raise_too_many_arguments(const char **error)
|
||||
{
|
||||
strlcpy(tmp_error_buff,
|
||||
"Too many arguments in function call.", sizeof(tmp_error_buff));
|
||||
*error = tmp_error_buff;
|
||||
snprintf(tmp_error_buff, MAX_ERROR_LEN,
|
||||
"Too many arguments in function call.");
|
||||
*error = tmp_error_buff;
|
||||
}
|
||||
|
||||
static void raise_expected_number(off_t where, const char **error)
|
||||
@ -75,12 +73,12 @@ static void raise_unexpected_eof(off_t where, const char ** error)
|
||||
|
||||
static void raise_enomem(const char **error)
|
||||
{
|
||||
strlcpy(tmp_error_buff, "Out of memory", sizeof(tmp_error_buff));
|
||||
snprintf(tmp_error_buff, MAX_ERROR_LEN, "Out of memory");
|
||||
*error = tmp_error_buff;
|
||||
}
|
||||
|
||||
static void raise_unknown_function(off_t where, const char *name,
|
||||
ssize_t len, const char **error)
|
||||
size_t len, const char **error)
|
||||
{
|
||||
int n = snprintf(tmp_error_buff, MAX_ERROR_LEN,
|
||||
#ifdef _WIN32
|
||||
@ -133,26 +131,26 @@ enum argument_type
|
||||
struct argument;
|
||||
|
||||
typedef struct rmsgpack_dom_value (*rarch_query_func)(
|
||||
struct rmsgpack_dom_value input,
|
||||
unsigned argc,
|
||||
const struct argument *argv
|
||||
);
|
||||
struct rmsgpack_dom_value input,
|
||||
unsigned argc,
|
||||
const struct argument *argv
|
||||
);
|
||||
|
||||
struct invocation
|
||||
{
|
||||
rarch_query_func func;
|
||||
unsigned argc;
|
||||
struct argument *argv;
|
||||
rarch_query_func func;
|
||||
unsigned argc;
|
||||
struct argument *argv;
|
||||
};
|
||||
|
||||
struct argument
|
||||
{
|
||||
enum argument_type type;
|
||||
union
|
||||
enum argument_type type;
|
||||
union
|
||||
{
|
||||
struct rmsgpack_dom_value value;
|
||||
struct invocation invocation;
|
||||
} a;
|
||||
struct rmsgpack_dom_value value;
|
||||
struct invocation invocation;
|
||||
};
|
||||
};
|
||||
|
||||
static void argument_free(struct argument *arg)
|
||||
@ -161,85 +159,82 @@ static void argument_free(struct argument *arg)
|
||||
|
||||
if (arg->type != AT_FUNCTION)
|
||||
{
|
||||
rmsgpack_dom_value_free(&arg->a.value);
|
||||
rmsgpack_dom_value_free(&arg->value);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < arg->a.invocation.argc; i++)
|
||||
argument_free(&arg->a.invocation.argv[i]);
|
||||
for (i = 0; i < arg->invocation.argc; i++)
|
||||
argument_free(&arg->invocation.argv[i]);
|
||||
}
|
||||
|
||||
struct query
|
||||
{
|
||||
unsigned ref_count;
|
||||
struct invocation root;
|
||||
unsigned ref_count;
|
||||
struct invocation root;
|
||||
};
|
||||
|
||||
struct registered_func
|
||||
{
|
||||
const char *name;
|
||||
rarch_query_func func;
|
||||
const char *name;
|
||||
rarch_query_func func;
|
||||
};
|
||||
|
||||
static struct buffer parse_argument(struct buffer buff, struct argument *arg,
|
||||
const char **error);
|
||||
|
||||
static struct rmsgpack_dom_value is_true(struct rmsgpack_dom_value input,
|
||||
unsigned argc, const struct argument *argv)
|
||||
unsigned argc, const struct argument *argv)
|
||||
{
|
||||
struct rmsgpack_dom_value res;
|
||||
memset(&res, 0, sizeof(res));
|
||||
|
||||
res.type = RDT_BOOL;
|
||||
res.val.bool_ = 0;
|
||||
res.type = RDT_BOOL;
|
||||
res.bool_ = 0;
|
||||
|
||||
if (argc > 0 || input.type != RDT_BOOL)
|
||||
res.val.bool_ = 0;
|
||||
res.bool_ = 0;
|
||||
else
|
||||
res.val.bool_ = input.val.bool_;
|
||||
res.bool_ = input.bool_;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct rmsgpack_dom_value equals(struct rmsgpack_dom_value input,
|
||||
unsigned argc, const struct argument * argv)
|
||||
unsigned argc, const struct argument * argv)
|
||||
{
|
||||
struct argument arg;
|
||||
struct rmsgpack_dom_value res;
|
||||
memset(&res, 0, sizeof(res));
|
||||
struct argument arg;
|
||||
|
||||
res.type = RDT_BOOL;
|
||||
|
||||
if (argc != 1)
|
||||
res.val.bool_ = 0;
|
||||
res.bool_ = 0;
|
||||
else
|
||||
{
|
||||
arg = argv[0];
|
||||
|
||||
if (arg.type != AT_VALUE)
|
||||
res.val.bool_ = 0;
|
||||
res.bool_ = 0;
|
||||
else
|
||||
{
|
||||
if (input.type == RDT_UINT && arg.a.value.type == RDT_INT)
|
||||
if (input.type == RDT_UINT && arg.value.type == RDT_INT)
|
||||
{
|
||||
arg.a.value.type = RDT_UINT;
|
||||
arg.a.value.val.uint_ = arg.a.value.val.int_;
|
||||
arg.value.type = RDT_UINT;
|
||||
arg.value.uint_ = arg.value.int_;
|
||||
}
|
||||
res.val.bool_ = (rmsgpack_dom_value_cmp(&input, &arg.a.value) == 0);
|
||||
res.bool_ = (rmsgpack_dom_value_cmp(&input, &arg.value) == 0);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct rmsgpack_dom_value operator_or(struct rmsgpack_dom_value input,
|
||||
unsigned argc, const struct argument * argv)
|
||||
unsigned argc, const struct argument * argv)
|
||||
{
|
||||
unsigned i;
|
||||
struct rmsgpack_dom_value res;
|
||||
memset(&res, 0, sizeof(res));
|
||||
unsigned i;
|
||||
|
||||
res.type = RDT_BOOL;
|
||||
res.val.bool_ = 0;
|
||||
res.bool_ = 0;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
@ -247,13 +242,13 @@ static struct rmsgpack_dom_value operator_or(struct rmsgpack_dom_value input,
|
||||
res = equals(input, 1, &argv[i]);
|
||||
else
|
||||
{
|
||||
res = is_true(argv[i].a.invocation.func(input,
|
||||
argv[i].a.invocation.argc,
|
||||
argv[i].a.invocation.argv
|
||||
res = is_true(argv[i].invocation.func(input,
|
||||
argv[i].invocation.argc,
|
||||
argv[i].invocation.argv
|
||||
), 0, NULL);
|
||||
}
|
||||
|
||||
if (res.val.bool_)
|
||||
if (res.bool_)
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -264,12 +259,10 @@ static struct rmsgpack_dom_value between(struct rmsgpack_dom_value input,
|
||||
unsigned argc, const struct argument * argv)
|
||||
{
|
||||
struct rmsgpack_dom_value res;
|
||||
unsigned i = 0;
|
||||
|
||||
memset(&res, 0, sizeof(res));
|
||||
unsigned i = 0;
|
||||
|
||||
res.type = RDT_BOOL;
|
||||
res.val.bool_ = 0;
|
||||
res.bool_ = 0;
|
||||
|
||||
(void)i;
|
||||
|
||||
@ -277,16 +270,16 @@ static struct rmsgpack_dom_value between(struct rmsgpack_dom_value input,
|
||||
return res;
|
||||
if (argv[0].type != AT_VALUE || argv[1].type != AT_VALUE)
|
||||
return res;
|
||||
if (argv[0].a.value.type != RDT_INT || argv[1].a.value.type != RDT_INT)
|
||||
if (argv[0].value.type != RDT_INT || argv[1].value.type != RDT_INT)
|
||||
return res;
|
||||
|
||||
switch (input.type)
|
||||
{
|
||||
case RDT_INT:
|
||||
res.val.bool_ = ((input.val.int_ >= argv[0].a.value.val.int_) && (input.val.int_ <= argv[1].a.value.val.int_));
|
||||
res.bool_ = input.int_ >= argv[0].value.int_ && input.int_ <= argv[1].value.int_;
|
||||
break;
|
||||
case RDT_UINT:
|
||||
res.val.bool_ = (((unsigned)input.val.int_ >= argv[0].a.value.val.uint_) && (input.val.int_ <= argv[1].a.value.val.int_));
|
||||
res.bool_ = input.int_ >= argv[0].value.uint_ && input.int_ <= argv[1].value.int_;
|
||||
break;
|
||||
default:
|
||||
return res;
|
||||
@ -298,12 +291,11 @@ static struct rmsgpack_dom_value between(struct rmsgpack_dom_value input,
|
||||
static struct rmsgpack_dom_value operator_and(struct rmsgpack_dom_value input,
|
||||
unsigned argc, const struct argument * argv)
|
||||
{
|
||||
unsigned i;
|
||||
struct rmsgpack_dom_value res;
|
||||
memset(&res, 0, sizeof(res));
|
||||
unsigned i;
|
||||
|
||||
res.type = RDT_BOOL;
|
||||
res.val.bool_ = 0;
|
||||
res.bool_ = 0;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
@ -312,14 +304,14 @@ static struct rmsgpack_dom_value operator_and(struct rmsgpack_dom_value input,
|
||||
else
|
||||
{
|
||||
res = is_true(
|
||||
argv[i].a.invocation.func(input,
|
||||
argv[i].a.invocation.argc,
|
||||
argv[i].a.invocation.argv
|
||||
argv[i].invocation.func(input,
|
||||
argv[i].invocation.argc,
|
||||
argv[i].invocation.argv
|
||||
),
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
if (!res.val.bool_)
|
||||
if (!res.bool_)
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
@ -330,22 +322,21 @@ static struct rmsgpack_dom_value q_glob(struct rmsgpack_dom_value input,
|
||||
{
|
||||
struct rmsgpack_dom_value res;
|
||||
unsigned i = 0;
|
||||
memset(&res, 0, sizeof(res));
|
||||
|
||||
res.type = RDT_BOOL;
|
||||
res.val.bool_ = 0;
|
||||
res.bool_ = 0;
|
||||
|
||||
(void)i;
|
||||
|
||||
if (argc != 1)
|
||||
return res;
|
||||
if (argv[0].type != AT_VALUE || argv[0].a.value.type != RDT_STRING)
|
||||
if (argv[0].type != AT_VALUE || argv[0].value.type != RDT_STRING)
|
||||
return res;
|
||||
if (input.type != RDT_STRING)
|
||||
return res;
|
||||
res.val.bool_ = rl_fnmatch(
|
||||
argv[0].a.value.val.string.buff,
|
||||
input.val.string.buff,
|
||||
res.bool_ = rl_fnmatch(
|
||||
argv[0].value.string.buff,
|
||||
input.string.buff,
|
||||
0
|
||||
) == 0;
|
||||
return res;
|
||||
@ -354,20 +345,19 @@ static struct rmsgpack_dom_value q_glob(struct rmsgpack_dom_value input,
|
||||
static struct rmsgpack_dom_value all_map(struct rmsgpack_dom_value input,
|
||||
unsigned argc, const struct argument *argv)
|
||||
{
|
||||
unsigned i;
|
||||
struct argument arg;
|
||||
struct rmsgpack_dom_value res;
|
||||
struct rmsgpack_dom_value nil_value;
|
||||
struct rmsgpack_dom_value *value = NULL;
|
||||
memset(&res, 0, sizeof(res));
|
||||
struct argument arg;
|
||||
struct rmsgpack_dom_value nil_value;
|
||||
unsigned i;
|
||||
|
||||
nil_value.type = RDT_NULL;
|
||||
res.type = RDT_BOOL;
|
||||
res.val.bool_ = 1;
|
||||
res.bool_ = 1;
|
||||
|
||||
if (argc % 2 != 0)
|
||||
{
|
||||
res.val.bool_ = 0;
|
||||
res.bool_ = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -379,10 +369,10 @@ static struct rmsgpack_dom_value all_map(struct rmsgpack_dom_value input,
|
||||
arg = argv[i];
|
||||
if (arg.type != AT_VALUE)
|
||||
{
|
||||
res.val.bool_ = 0;
|
||||
res.bool_ = 0;
|
||||
goto clean;
|
||||
}
|
||||
value = rmsgpack_dom_value_map_value(&input, &arg.a.value);
|
||||
value = rmsgpack_dom_value_map_value(&input, &arg.value);
|
||||
if (!value) /* All missing fields are nil */
|
||||
value = &nil_value;
|
||||
arg = argv[i + 1];
|
||||
@ -390,14 +380,14 @@ static struct rmsgpack_dom_value all_map(struct rmsgpack_dom_value input,
|
||||
res = equals(*value, 1, &arg);
|
||||
else
|
||||
{
|
||||
res = is_true(arg.a.invocation.func(
|
||||
res = is_true(arg.invocation.func(
|
||||
*value,
|
||||
arg.a.invocation.argc,
|
||||
arg.a.invocation.argv
|
||||
arg.invocation.argc,
|
||||
arg.invocation.argv
|
||||
), 0, NULL);
|
||||
value = NULL;
|
||||
}
|
||||
if (!res.val.bool_)
|
||||
if (!res.bool_)
|
||||
break;
|
||||
}
|
||||
clean:
|
||||
@ -405,24 +395,26 @@ clean:
|
||||
}
|
||||
|
||||
struct registered_func registered_functions[100] = {
|
||||
{"is_true", is_true},
|
||||
{"or", operator_or},
|
||||
{"and", operator_and},
|
||||
{"between", between},
|
||||
{"glob", q_glob},
|
||||
{NULL, NULL}
|
||||
{"is_true", is_true},
|
||||
{"or", operator_or},
|
||||
{"and", operator_and},
|
||||
{"between", between},
|
||||
{"glob", q_glob},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static struct buffer chomp(struct buffer buff)
|
||||
{
|
||||
for (; (unsigned)buff.offset < buff.len && isspace((int)buff.data[buff.offset]); buff.offset++);
|
||||
off_t i = 0;
|
||||
(void)i;
|
||||
for (; buff.offset < buff.len && isspace(buff.data[buff.offset]); buff.offset++);
|
||||
return buff;
|
||||
}
|
||||
|
||||
static struct buffer expect_char(struct buffer buff,
|
||||
char c, const char ** error)
|
||||
{
|
||||
if ((unsigned)buff.offset >= buff.len)
|
||||
if (buff.offset >= buff.len)
|
||||
raise_unexpected_eof(buff.offset, error);
|
||||
else if (buff.data[buff.offset] != c)
|
||||
raise_unexpected_char(
|
||||
@ -435,7 +427,7 @@ static struct buffer expect_char(struct buffer buff,
|
||||
static struct buffer expect_eof(struct buffer buff, const char ** error)
|
||||
{
|
||||
buff = chomp(buff);
|
||||
if ((unsigned)buff.offset < buff.len)
|
||||
if (buff.offset < buff.len)
|
||||
raise_expected_eof(buff.offset, buff.data[buff.offset], error);
|
||||
return buff;
|
||||
}
|
||||
@ -453,7 +445,7 @@ static int peek(struct buffer buff, const char * data)
|
||||
|
||||
static int is_eot(struct buffer buff)
|
||||
{
|
||||
return ((unsigned)buff.offset >= buff.len);
|
||||
return (buff.offset >= buff.len);
|
||||
}
|
||||
|
||||
static void peek_char(struct buffer buff, char *c, const char **error)
|
||||
@ -470,23 +462,22 @@ static void peek_char(struct buffer buff, char *c, const char **error)
|
||||
static struct buffer get_char(struct buffer buff, char * c,
|
||||
const char ** error)
|
||||
{
|
||||
if (is_eot(buff))
|
||||
if (is_eot(buff))
|
||||
{
|
||||
raise_unexpected_eof(buff.offset, error);
|
||||
return buff;
|
||||
}
|
||||
*c = buff.data[buff.offset];
|
||||
buff.offset++;
|
||||
return buff;
|
||||
raise_unexpected_eof(buff.offset, error);
|
||||
return buff;
|
||||
}
|
||||
*c = buff.data[buff.offset];
|
||||
buff.offset++;
|
||||
return buff;
|
||||
}
|
||||
|
||||
static struct buffer parse_string(struct buffer buff,
|
||||
struct rmsgpack_dom_value *value, const char **error)
|
||||
{
|
||||
const char * str_start = NULL;
|
||||
char terminator = '\0';
|
||||
char c = '\0';
|
||||
int is_binstr = 0;
|
||||
const char * str_start;
|
||||
char terminator = '\0';
|
||||
char c = '\0';
|
||||
|
||||
(void)c;
|
||||
|
||||
@ -495,12 +486,6 @@ static struct buffer parse_string(struct buffer buff,
|
||||
if (*error)
|
||||
return buff;
|
||||
|
||||
if (terminator == 'b')
|
||||
{
|
||||
is_binstr = 1;
|
||||
buff = get_char(buff, &terminator, error);
|
||||
}
|
||||
|
||||
if (terminator != '"' && terminator != '\'')
|
||||
{
|
||||
buff.offset--;
|
||||
@ -519,44 +504,18 @@ static struct buffer parse_string(struct buffer buff,
|
||||
|
||||
if (!*error)
|
||||
{
|
||||
size_t count;
|
||||
value->type = is_binstr ? RDT_BINARY : RDT_STRING;
|
||||
value->val.string.len = (buff.data + buff.offset) - str_start - 1;
|
||||
value->type = RDT_STRING;
|
||||
value->string.len = (buff.data + buff.offset) - str_start - 1;
|
||||
value->string.buff = (char*)calloc(value->string.len + 1, sizeof(char));
|
||||
|
||||
count = is_binstr ? (value->val.string.len + 1) / 2 : (value->val.string.len + 1);
|
||||
value->val.string.buff = (char*)calloc(count, sizeof(char));
|
||||
|
||||
if (!value->val.string.buff)
|
||||
if (!value->string.buff)
|
||||
raise_enomem(error);
|
||||
else if (is_binstr)
|
||||
{
|
||||
unsigned i;
|
||||
const char *tok = str_start;
|
||||
unsigned j = 0;
|
||||
|
||||
for (i = 0; i < value->val.string.len; i += 2)
|
||||
{
|
||||
uint8_t hi, lo;
|
||||
char hic = tok[i];
|
||||
char loc = tok[i + 1];
|
||||
|
||||
if (hic <= '9')
|
||||
hi = hic - '0';
|
||||
else
|
||||
hi = (hic - 'A') + 10;
|
||||
|
||||
if (loc <= '9')
|
||||
lo = loc - '0';
|
||||
else
|
||||
lo = (loc - 'A') + 10;
|
||||
|
||||
value->val.string.buff[j++] = hi * 16 + lo;
|
||||
}
|
||||
|
||||
value->val.string.len = j;
|
||||
}
|
||||
else
|
||||
memcpy(value->val.string.buff, str_start, value->val.string.len);
|
||||
memcpy(
|
||||
value->string.buff,
|
||||
str_start,
|
||||
value->string.len
|
||||
);
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
@ -572,11 +531,11 @@ static struct buffer parse_integer(struct buffer buff,
|
||||
#else
|
||||
"%lld",
|
||||
#endif
|
||||
(signed long long*)&value->val.int_) == 0)
|
||||
(signed long long*)&value->int_) == 0)
|
||||
raise_expected_number(buff.offset, error);
|
||||
else
|
||||
{
|
||||
while (isdigit((int)buff.data[buff.offset]))
|
||||
while (isdigit(buff.data[buff.offset]))
|
||||
buff.offset++;
|
||||
}
|
||||
return buff;
|
||||
@ -596,17 +555,17 @@ static struct buffer parse_value(struct buffer buff,
|
||||
{
|
||||
buff.offset += strlen("true");
|
||||
value->type = RDT_BOOL;
|
||||
value->val.bool_ = 1;
|
||||
value->bool_ = 1;
|
||||
}
|
||||
else if (peek(buff, "false"))
|
||||
{
|
||||
buff.offset += strlen("false");
|
||||
value->type = RDT_BOOL;
|
||||
value->val.bool_ = 0;
|
||||
value->bool_ = 0;
|
||||
}
|
||||
else if (peek(buff, "b") || peek(buff, "\"") || peek(buff, "'"))
|
||||
else if (peek(buff, "\"") || peek(buff, "'"))
|
||||
buff = parse_string(buff, value, error);
|
||||
else if (isdigit((int)buff.data[buff.offset]))
|
||||
else if (isdigit(buff.data[buff.offset]))
|
||||
buff = parse_integer(buff, value, error);
|
||||
return buff;
|
||||
}
|
||||
@ -617,28 +576,28 @@ static struct buffer get_ident(struct buffer buff,
|
||||
{
|
||||
char c = '\0';
|
||||
|
||||
if (is_eot(buff))
|
||||
if (is_eot(buff))
|
||||
{
|
||||
raise_unexpected_eof(buff.offset, error);
|
||||
return buff;
|
||||
}
|
||||
|
||||
*ident = buff.data + buff.offset;
|
||||
*len = 0;
|
||||
peek_char(buff, &c, error);
|
||||
*ident = buff.data + buff.offset;
|
||||
*len = 0;
|
||||
peek_char(buff, &c, error);
|
||||
|
||||
if (*error)
|
||||
goto clean;
|
||||
if (!isalpha((int)c))
|
||||
return buff;
|
||||
if (*error)
|
||||
goto clean;
|
||||
if (!isalpha(c))
|
||||
return buff;
|
||||
|
||||
buff.offset++;
|
||||
*len = *len + 1;
|
||||
peek_char(buff, &c, error);
|
||||
buff.offset++;
|
||||
*len = *len + 1;
|
||||
peek_char(buff, &c, error);
|
||||
|
||||
while (!*error)
|
||||
while (!*error)
|
||||
{
|
||||
if (!(isalpha((int)c) || isdigit((int)c) || c == '_'))
|
||||
if (!(isalpha(c) || isdigit(c) || c == '_'))
|
||||
break;
|
||||
buff.offset++;
|
||||
*len = *len + 1;
|
||||
@ -646,18 +605,18 @@ static struct buffer get_ident(struct buffer buff,
|
||||
}
|
||||
|
||||
clean:
|
||||
return buff;
|
||||
return buff;
|
||||
}
|
||||
|
||||
static struct buffer parse_method_call(struct buffer buff,
|
||||
struct invocation *invocation, const char **error)
|
||||
{
|
||||
const char *func_name;
|
||||
size_t func_name_len;
|
||||
unsigned i;
|
||||
struct argument args[MAX_ARGS];
|
||||
unsigned argi = 0;
|
||||
const char *func_name = NULL;
|
||||
struct registered_func *rf = registered_functions;
|
||||
struct registered_func * rf = registered_functions;
|
||||
|
||||
invocation->func = NULL;
|
||||
|
||||
@ -740,12 +699,14 @@ success:
|
||||
static struct buffer parse_table(struct buffer buff,
|
||||
struct invocation *invocation, const char **error)
|
||||
{
|
||||
unsigned i;
|
||||
size_t ident_len;
|
||||
struct argument args[MAX_ARGS];
|
||||
const char *ident_name = NULL;
|
||||
unsigned i;
|
||||
const char *ident_name;
|
||||
size_t ident_len;
|
||||
unsigned argi = 0;
|
||||
|
||||
memset(args, 0, sizeof(struct argument) * MAX_ARGS);
|
||||
|
||||
buff = chomp(buff);
|
||||
buff = expect_char(buff, '{', error);
|
||||
|
||||
@ -762,31 +723,31 @@ static struct buffer parse_table(struct buffer buff,
|
||||
goto clean;
|
||||
}
|
||||
|
||||
if (isalpha((int)buff.data[buff.offset]))
|
||||
if (isalpha(buff.data[buff.offset]))
|
||||
{
|
||||
buff = get_ident(buff, &ident_name, &ident_len, error);
|
||||
|
||||
if (!*error)
|
||||
{
|
||||
args[argi].a.value.type = RDT_STRING;
|
||||
args[argi].a.value.val.string.len = ident_len;
|
||||
args[argi].a.value.val.string.buff = (char*)calloc(
|
||||
args[argi].value.type = RDT_STRING;
|
||||
args[argi].value.string.len = ident_len;
|
||||
args[argi].value.string.buff = (char*)calloc(
|
||||
ident_len + 1,
|
||||
sizeof(char)
|
||||
);
|
||||
|
||||
if (!args[argi].a.value.val.string.buff)
|
||||
if (!args[argi].value.string.buff)
|
||||
goto clean;
|
||||
|
||||
strncpy(
|
||||
args[argi].a.value.val.string.buff,
|
||||
args[argi].value.string.buff,
|
||||
ident_name,
|
||||
ident_len
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
buff = parse_string(buff, &args[argi].a.value, error);
|
||||
buff = parse_string(buff, &args[argi].value, error);
|
||||
|
||||
if (*error)
|
||||
goto clean;
|
||||
@ -855,65 +816,63 @@ static struct buffer parse_argument(struct buffer buff,
|
||||
buff = chomp(buff);
|
||||
|
||||
if (
|
||||
isalpha((int)buff.data[buff.offset])
|
||||
isalpha(buff.data[buff.offset])
|
||||
&& !(
|
||||
peek(buff, "nil")
|
||||
|| peek(buff, "true")
|
||||
|| peek(buff, "false")
|
||||
|| peek(buff, "b\"") || peek(buff, "b'") /* bin string prefix*/
|
||||
)
|
||||
)
|
||||
{
|
||||
arg->type = AT_FUNCTION;
|
||||
buff = parse_method_call(buff, &arg->a.invocation, error);
|
||||
buff = parse_method_call(buff, &arg->invocation, error);
|
||||
}
|
||||
else if (peek(buff, "{"))
|
||||
{
|
||||
arg->type = AT_FUNCTION;
|
||||
buff = parse_table(buff, &arg->a.invocation, error);
|
||||
buff = parse_table(buff, &arg->invocation, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg->type = AT_VALUE;
|
||||
buff = parse_value(buff, &arg->a.value, error);
|
||||
buff = parse_value(buff, &arg->value, error);
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void libretrodb_query_free(void *q)
|
||||
{
|
||||
unsigned i;
|
||||
struct query *real_q = (struct query*)q;
|
||||
unsigned i;
|
||||
struct query * real_q = (struct query*)q;
|
||||
|
||||
real_q->ref_count--;
|
||||
if (real_q->ref_count > 0)
|
||||
return;
|
||||
real_q->ref_count--;
|
||||
if (real_q->ref_count > 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < real_q->root.argc; i++)
|
||||
argument_free(&real_q->root.argv[i]);
|
||||
|
||||
free(real_q->root.argv);
|
||||
real_q->root.argv = NULL;
|
||||
real_q->root.argc = 0;
|
||||
free(real_q);
|
||||
for (i = 0; i < real_q->root.argc; i++)
|
||||
argument_free(&real_q->root.argv[i]);
|
||||
}
|
||||
|
||||
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*)calloc(1, sizeof(*q));
|
||||
struct query *q = (struct query*)malloc(sizeof(struct query));
|
||||
|
||||
if (!q)
|
||||
goto clean;
|
||||
|
||||
memset(q, 0, sizeof(struct query));
|
||||
|
||||
q->ref_count = 1;
|
||||
buff.data = query;
|
||||
buff.len = buff_len;
|
||||
buff.offset = 0;
|
||||
*error = NULL;
|
||||
|
||||
buff = chomp(buff);
|
||||
buff = chomp(buff);
|
||||
|
||||
if (peek(buff, "{"))
|
||||
{
|
||||
@ -921,7 +880,7 @@ void *libretrodb_query_compile(libretrodb_t *db,
|
||||
if (*error)
|
||||
goto clean;
|
||||
}
|
||||
else if (isalpha((int)buff.data[buff.offset]))
|
||||
else if (isalpha(buff.data[buff.offset]))
|
||||
buff = parse_method_call(buff, &q->root, error);
|
||||
|
||||
buff = expect_eof(buff, error);
|
||||
@ -953,5 +912,5 @@ int libretrodb_query_filter(libretrodb_query_t *q,
|
||||
{
|
||||
struct invocation inv = ((struct query *)q)->root;
|
||||
struct rmsgpack_dom_value res = inv.func(*v, inv.argc, inv.argv);
|
||||
return (res.type == RDT_BOOL && res.val.bool_);
|
||||
return (res.type == RDT_BOOL && res.bool_);
|
||||
}
|
||||
|
@ -55,18 +55,7 @@ static const uint8_t MPF_UINT64 = 0xcf;
|
||||
|
||||
static const uint8_t MPF_NIL = 0xc0;
|
||||
|
||||
static INLINE ssize_t fpwrite(FILE *fp, const void *buf, size_t count)
|
||||
{
|
||||
return (fwrite(buf, 1, count, fp) != count) ? -1 : (ssize_t)count;
|
||||
}
|
||||
|
||||
static INLINE ssize_t fpread(FILE *fp, void *buf, size_t count)
|
||||
{
|
||||
size_t num_read = fread(buf, 1, count, fp);
|
||||
return num_read != count && ferror(fp) ? -1 : (ssize_t)num_read;
|
||||
}
|
||||
|
||||
int rmsgpack_write_array_header(FILE *fp, uint32_t size)
|
||||
int rmsgpack_write_array_header(int fd, uint32_t size)
|
||||
{
|
||||
uint16_t tmp_i16;
|
||||
uint32_t tmp_i32;
|
||||
@ -74,29 +63,29 @@ int rmsgpack_write_array_header(FILE *fp, uint32_t size)
|
||||
if (size < 16)
|
||||
{
|
||||
size = (size | MPF_FIXARRAY);
|
||||
if (fpwrite(fp, &size, sizeof(int8_t)) == -1)
|
||||
if (write(fd, &size, sizeof(int8_t)) == -1)
|
||||
return -errno;
|
||||
return sizeof(int8_t);
|
||||
}
|
||||
else if (size == (uint16_t)size)
|
||||
{
|
||||
if (fpwrite(fp, &MPF_ARRAY16, sizeof(MPF_ARRAY16)) == -1)
|
||||
if (write(fd, &MPF_ARRAY16, sizeof(MPF_ARRAY16)) == -1)
|
||||
return -errno;
|
||||
tmp_i16 = httobe16(size);
|
||||
if (fpwrite(fp, (void *)(&tmp_i16), sizeof(uint16_t)) == -1)
|
||||
if (write(fd, (void *)(&tmp_i16), sizeof(uint16_t)) == -1)
|
||||
return -errno;
|
||||
return sizeof(int8_t) + sizeof(uint16_t);
|
||||
}
|
||||
|
||||
if (fpwrite(fp, &MPF_ARRAY32, sizeof(MPF_ARRAY32)) == -1)
|
||||
if (write(fd, &MPF_ARRAY32, sizeof(MPF_ARRAY32)) == -1)
|
||||
return -errno;
|
||||
tmp_i32 = httobe32(size);
|
||||
if (fpwrite(fp, (void *)(&tmp_i32), sizeof(uint32_t)) == -1)
|
||||
if (write(fd, (void *)(&tmp_i32), sizeof(uint32_t)) == -1)
|
||||
return -errno;
|
||||
return sizeof(int8_t) + sizeof(uint32_t);
|
||||
}
|
||||
|
||||
int rmsgpack_write_map_header(FILE *fp, uint32_t size)
|
||||
int rmsgpack_write_map_header(int fd, uint32_t size)
|
||||
{
|
||||
uint16_t tmp_i16;
|
||||
uint32_t tmp_i32;
|
||||
@ -104,29 +93,29 @@ int rmsgpack_write_map_header(FILE *fp, uint32_t size)
|
||||
if (size < 16)
|
||||
{
|
||||
size = (size | MPF_FIXMAP);
|
||||
if (fpwrite(fp, &size, sizeof(int8_t)) == -1)
|
||||
if (write(fd, &size, sizeof(int8_t)) == -1)
|
||||
return -errno;
|
||||
return sizeof(int8_t);
|
||||
}
|
||||
else if (size < (uint16_t)size)
|
||||
{
|
||||
if (fpwrite(fp, &MPF_MAP16, sizeof(MPF_MAP16)) == -1)
|
||||
if (write(fd, &MPF_MAP16, sizeof(MPF_MAP16)) == -1)
|
||||
return -errno;
|
||||
tmp_i16 = httobe16(size);
|
||||
if (fpwrite(fp, (void *)(&tmp_i16), sizeof(uint16_t)) == -1)
|
||||
if (write(fd, (void *)(&tmp_i16), sizeof(uint16_t)) == -1)
|
||||
return -errno;
|
||||
return sizeof(uint8_t) + sizeof(uint16_t);
|
||||
}
|
||||
|
||||
tmp_i32 = httobe32(size);
|
||||
if (fpwrite(fp, &MPF_MAP32, sizeof(MPF_MAP32)) == -1)
|
||||
if (write(fd, &MPF_MAP32, sizeof(MPF_MAP32)) == -1)
|
||||
return -errno;
|
||||
if (fpwrite(fp, (void *)(&tmp_i32), sizeof(uint32_t)) == -1)
|
||||
if (write(fd, (void *)(&tmp_i32), sizeof(uint32_t)) == -1)
|
||||
return -errno;
|
||||
return sizeof(int8_t) + sizeof(uint32_t);
|
||||
}
|
||||
|
||||
int rmsgpack_write_string(FILE *fp, const char *s, uint32_t len)
|
||||
int rmsgpack_write_string(int fd, const char *s, uint32_t len)
|
||||
{
|
||||
int8_t fixlen = 0;
|
||||
uint16_t tmp_i16;
|
||||
@ -136,43 +125,43 @@ int rmsgpack_write_string(FILE *fp, const char *s, uint32_t len)
|
||||
if (len < 32)
|
||||
{
|
||||
fixlen = len | MPF_FIXSTR;
|
||||
if (fpwrite(fp, &fixlen, sizeof(int8_t)) == -1)
|
||||
if (write(fd, &fixlen, sizeof(int8_t)) == -1)
|
||||
return -errno;
|
||||
}
|
||||
else if (len < (1 << 8))
|
||||
{
|
||||
if (fpwrite(fp, &MPF_STR8, sizeof(MPF_STR8)) == -1)
|
||||
if (write(fd, &MPF_STR8, sizeof(MPF_STR8)) == -1)
|
||||
return -errno;
|
||||
if (fpwrite(fp, &len, sizeof(uint8_t)) == -1)
|
||||
if (write(fd, &len, sizeof(uint8_t)) == -1)
|
||||
return -errno;
|
||||
written += sizeof(uint8_t);
|
||||
}
|
||||
else if (len < (1 << 16))
|
||||
{
|
||||
if (fpwrite(fp, &MPF_STR16, sizeof(MPF_STR16)) == -1)
|
||||
if (write(fd, &MPF_STR16, sizeof(MPF_STR16)) == -1)
|
||||
return -errno;
|
||||
tmp_i16 = httobe16(len);
|
||||
if (fpwrite(fp, &tmp_i16, sizeof(uint16_t)) == -1)
|
||||
if (write(fd, &tmp_i16, sizeof(uint16_t)) == -1)
|
||||
return -errno;
|
||||
written += sizeof(uint16_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fpwrite(fp, &MPF_STR32, sizeof(MPF_STR32)) == -1)
|
||||
if (write(fd, &MPF_STR32, sizeof(MPF_STR32)) == -1)
|
||||
return -errno;
|
||||
tmp_i32 = httobe32(len);
|
||||
if (fpwrite(fp, &tmp_i32, sizeof(uint32_t)) == -1)
|
||||
if (write(fd, &tmp_i32, sizeof(uint32_t)) == -1)
|
||||
return -errno;
|
||||
written += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
if (fpwrite(fp, s, len) == -1)
|
||||
if (write(fd, s, len) == -1)
|
||||
return -errno;
|
||||
written += len;
|
||||
return written;
|
||||
}
|
||||
|
||||
int rmsgpack_write_bin(FILE *fp, const void *s, uint32_t len)
|
||||
int rmsgpack_write_bin(int fd, const void *s, uint32_t len)
|
||||
{
|
||||
uint16_t tmp_i16;
|
||||
uint32_t tmp_i32;
|
||||
@ -180,58 +169,58 @@ int rmsgpack_write_bin(FILE *fp, const void *s, uint32_t len)
|
||||
|
||||
if (len == (uint8_t)len)
|
||||
{
|
||||
if (fpwrite(fp, &MPF_BIN8, sizeof(MPF_BIN8)) == -1)
|
||||
if (write(fd, &MPF_BIN8, sizeof(MPF_BIN8)) == -1)
|
||||
return -errno;
|
||||
if (fpwrite(fp, &len, sizeof(uint8_t)) == -1)
|
||||
if (write(fd, &len, sizeof(uint8_t)) == -1)
|
||||
return -errno;
|
||||
written += sizeof(uint8_t);
|
||||
}
|
||||
else if (len == (uint16_t)len)
|
||||
{
|
||||
if (fpwrite(fp, &MPF_BIN16, sizeof(MPF_BIN16)) == -1)
|
||||
if (write(fd, &MPF_BIN16, sizeof(MPF_BIN16)) == -1)
|
||||
return -errno;
|
||||
tmp_i16 = httobe16(len);
|
||||
if (fpwrite(fp, &tmp_i16, sizeof(uint16_t)) == -1)
|
||||
if (write(fd, &tmp_i16, sizeof(uint16_t)) == -1)
|
||||
return -errno;
|
||||
written += sizeof(uint16_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fpwrite(fp, &MPF_BIN32, sizeof(MPF_BIN32)) == -1)
|
||||
if (write(fd, &MPF_BIN32, sizeof(MPF_BIN32)) == -1)
|
||||
return -errno;
|
||||
tmp_i32 = httobe32(len);
|
||||
if (fpwrite(fp, &tmp_i32, sizeof(uint32_t)) == -1)
|
||||
if (write(fd, &tmp_i32, sizeof(uint32_t)) == -1)
|
||||
return -errno;
|
||||
written += sizeof(uint32_t);
|
||||
}
|
||||
if (fpwrite(fp, s, len) == -1)
|
||||
if (write(fd, s, len) == -1)
|
||||
return -errno;
|
||||
written += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rmsgpack_write_nil(FILE *fp)
|
||||
int rmsgpack_write_nil(int fd)
|
||||
{
|
||||
if (fpwrite(fp, &MPF_NIL, sizeof(MPF_NIL)) == -1)
|
||||
if (write(fd, &MPF_NIL, sizeof(MPF_NIL)) == -1)
|
||||
return -errno;
|
||||
return sizeof(uint8_t);
|
||||
}
|
||||
|
||||
int rmsgpack_write_bool(FILE *fp, int value)
|
||||
int rmsgpack_write_bool(int fd, int value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
if (fpwrite(fp, &MPF_TRUE, sizeof(MPF_TRUE)) == -1)
|
||||
if (write(fd, &MPF_TRUE, sizeof(MPF_TRUE)) == -1)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (fpwrite(fp, &MPF_FALSE, sizeof(MPF_FALSE)) == -1)
|
||||
if (write(fd, &MPF_FALSE, sizeof(MPF_FALSE)) == -1)
|
||||
return -errno;
|
||||
|
||||
return sizeof(uint8_t);
|
||||
}
|
||||
|
||||
int rmsgpack_write_int(FILE *fp, int64_t value)
|
||||
int rmsgpack_write_int(int fd, int64_t value)
|
||||
{
|
||||
int16_t tmp_i16;
|
||||
int32_t tmp_i32;
|
||||
@ -240,58 +229,58 @@ int rmsgpack_write_int(FILE *fp, int64_t value)
|
||||
|
||||
if (value >=0 && value < 128)
|
||||
{
|
||||
if (fpwrite(fp, &value, sizeof(int8_t)) == -1)
|
||||
if (write(fd, &value, sizeof(int8_t)) == -1)
|
||||
return -errno;
|
||||
}
|
||||
else if (value < 0 && value > -32)
|
||||
{
|
||||
tmpval = (value) | 0xe0;
|
||||
if (fpwrite(fp, &tmpval, sizeof(uint8_t)) == -1)
|
||||
if (write(fd, &tmpval, sizeof(uint8_t)) == -1)
|
||||
return -errno;
|
||||
}
|
||||
else if (value == (int8_t)value)
|
||||
{
|
||||
if (fpwrite(fp, &MPF_INT8, sizeof(MPF_INT8)) == -1)
|
||||
if (write(fd, &MPF_INT8, sizeof(MPF_INT8)) == -1)
|
||||
return -errno;
|
||||
|
||||
if (fpwrite(fp, &value, sizeof(int8_t)) == -1)
|
||||
if (write(fd, &value, sizeof(int8_t)) == -1)
|
||||
return -errno;
|
||||
written += sizeof(int8_t);
|
||||
}
|
||||
else if (value == (int16_t)value)
|
||||
{
|
||||
if (fpwrite(fp, &MPF_INT16, sizeof(MPF_INT16)) == -1)
|
||||
if (write(fd, &MPF_INT16, sizeof(MPF_INT16)) == -1)
|
||||
return -errno;
|
||||
|
||||
tmp_i16 = httobe16(value);
|
||||
if (fpwrite(fp, &tmp_i16, sizeof(int16_t)) == -1)
|
||||
if (write(fd, &tmp_i16, sizeof(int16_t)) == -1)
|
||||
return -errno;
|
||||
written += sizeof(int16_t);
|
||||
}
|
||||
else if (value == (int32_t)value)
|
||||
{
|
||||
if (fpwrite(fp, &MPF_INT32, sizeof(MPF_INT32)) == -1)
|
||||
if (write(fd, &MPF_INT32, sizeof(MPF_INT32)) == -1)
|
||||
return -errno;
|
||||
|
||||
tmp_i32 = httobe32(value);
|
||||
if (fpwrite(fp, &tmp_i32, sizeof(int32_t)) == -1)
|
||||
if (write(fd, &tmp_i32, sizeof(int32_t)) == -1)
|
||||
return -errno;
|
||||
written += sizeof(int32_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fpwrite(fp, &MPF_INT64, sizeof(MPF_INT64)) == -1)
|
||||
if (write(fd, &MPF_INT64, sizeof(MPF_INT64)) == -1)
|
||||
return -errno;
|
||||
|
||||
value = httobe64(value);
|
||||
if (fpwrite(fp, &value, sizeof(int64_t)) == -1)
|
||||
if (write(fd, &value, sizeof(int64_t)) == -1)
|
||||
return -errno;
|
||||
written += sizeof(int64_t);
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
int rmsgpack_write_uint(FILE *fp, uint64_t value)
|
||||
int rmsgpack_write_uint(int fd, uint64_t value)
|
||||
{
|
||||
uint16_t tmp_i16;
|
||||
uint32_t tmp_i32;
|
||||
@ -299,51 +288,51 @@ int rmsgpack_write_uint(FILE *fp, uint64_t value)
|
||||
|
||||
if (value == (uint8_t)value)
|
||||
{
|
||||
if (fpwrite(fp, &MPF_UINT8, sizeof(MPF_UINT8)) == -1)
|
||||
if (write(fd, &MPF_UINT8, sizeof(MPF_UINT8)) == -1)
|
||||
return -errno;
|
||||
|
||||
if (fpwrite(fp, &value, sizeof(uint8_t)) == -1)
|
||||
if (write(fd, &value, sizeof(uint8_t)) == -1)
|
||||
return -errno;
|
||||
written += sizeof(uint8_t);
|
||||
}
|
||||
else if (value == (uint16_t)value)
|
||||
{
|
||||
if (fpwrite(fp, &MPF_UINT16, sizeof(MPF_UINT16)) == -1)
|
||||
if (write(fd, &MPF_UINT16, sizeof(MPF_UINT16)) == -1)
|
||||
return -errno;
|
||||
|
||||
tmp_i16 = httobe16(value);
|
||||
if (fpwrite(fp, &tmp_i16, sizeof(uint16_t)) == -1)
|
||||
if (write(fd, &tmp_i16, sizeof(uint16_t)) == -1)
|
||||
return -errno;
|
||||
written += sizeof(uint16_t);
|
||||
}
|
||||
else if (value == (uint32_t)value)
|
||||
{
|
||||
if (fpwrite(fp, &MPF_UINT32, sizeof(MPF_UINT32)) == -1)
|
||||
if (write(fd, &MPF_UINT32, sizeof(MPF_UINT32)) == -1)
|
||||
return -errno;
|
||||
|
||||
tmp_i32 = httobe32(value);
|
||||
if (fpwrite(fp, &tmp_i32, sizeof(uint32_t)) == -1)
|
||||
if (write(fd, &tmp_i32, sizeof(uint32_t)) == -1)
|
||||
return -errno;
|
||||
written += sizeof(uint32_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fpwrite(fp, &MPF_UINT64, sizeof(MPF_UINT64)) == -1)
|
||||
if (write(fd, &MPF_UINT64, sizeof(MPF_UINT64)) == -1)
|
||||
return -errno;
|
||||
|
||||
value = httobe64(value);
|
||||
if (fpwrite(fp, &value, sizeof(uint64_t)) == -1)
|
||||
if (write(fd, &value, sizeof(uint64_t)) == -1)
|
||||
return -errno;
|
||||
written += sizeof(uint64_t);
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
static int read_uint(FILE *fp, uint64_t *out, size_t size)
|
||||
static int read_uint(int fd, uint64_t *out, size_t size)
|
||||
{
|
||||
uint64_t tmp;
|
||||
|
||||
if (fpread(fp, &tmp, size) == -1)
|
||||
if (read(fd, &tmp, size) == -1)
|
||||
return -errno;
|
||||
|
||||
switch (size)
|
||||
@ -364,15 +353,18 @@ static int read_uint(FILE *fp, uint64_t *out, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_int(FILE *fp, int64_t *out, size_t size)
|
||||
static int read_int(int fd, int64_t *out, size_t size)
|
||||
{
|
||||
uint8_t tmp8 = 0;
|
||||
uint16_t tmp16;
|
||||
uint32_t tmp32;
|
||||
uint64_t tmp64;
|
||||
|
||||
if (fpread(fp, &tmp64, size) == -1)
|
||||
if (read(fd, &tmp64, size) == -1)
|
||||
return -errno;
|
||||
|
||||
(void)tmp8;
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 1:
|
||||
@ -391,34 +383,30 @@ static int read_int(FILE *fp, int64_t *out, size_t size)
|
||||
*out = *((int64_t *)(&tmp64));
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_buff(FILE *fp, size_t size, char **pbuff, uint64_t *len)
|
||||
static int read_buff(int fd, size_t size, char **pbuff, uint64_t *len)
|
||||
{
|
||||
uint64_t tmp_len = 0;
|
||||
|
||||
if (read_uint(fp, &tmp_len, size) == -1)
|
||||
goto error;
|
||||
if (read_uint(fd, &tmp_len, size) == -1)
|
||||
return -errno;
|
||||
|
||||
*pbuff = (char *)calloc((size_t)tmp_len + 1, sizeof(char));
|
||||
*pbuff = (char *)calloc(tmp_len + 1, sizeof(char));
|
||||
|
||||
if (fpread(fp, *pbuff, (size_t)tmp_len) == -1)
|
||||
goto error;
|
||||
if (read(fd, *pbuff, tmp_len) == -1)
|
||||
{
|
||||
free(*pbuff);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
*len = tmp_len;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (*pbuff)
|
||||
free(*pbuff);
|
||||
return -errno;
|
||||
|
||||
}
|
||||
|
||||
static int read_map(FILE *fp, uint32_t len,
|
||||
struct rmsgpack_read_callbacks *callbacks, void *data)
|
||||
static int read_map(int fd, uint32_t len,
|
||||
struct rmsgpack_read_callbacks *callbacks, void *data)
|
||||
{
|
||||
int rv;
|
||||
unsigned i;
|
||||
@ -429,16 +417,16 @@ static int read_map(FILE *fp, uint32_t len,
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if ((rv = rmsgpack_read(fp, callbacks, data)) < 0)
|
||||
if ((rv = rmsgpack_read(fd, callbacks, data)) < 0)
|
||||
return rv;
|
||||
if ((rv = rmsgpack_read(fp, callbacks, data)) < 0)
|
||||
if ((rv = rmsgpack_read(fd, callbacks, data)) < 0)
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_array(FILE *fp, uint32_t len,
|
||||
static int read_array(int fd, uint32_t len,
|
||||
struct rmsgpack_read_callbacks *callbacks, void *data)
|
||||
{
|
||||
int rv;
|
||||
@ -450,14 +438,14 @@ static int read_array(FILE *fp, uint32_t len,
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if ((rv = rmsgpack_read(fp, callbacks, data)) < 0)
|
||||
if ((rv = rmsgpack_read(fd, callbacks, data)) < 0)
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rmsgpack_read(FILE *fp,
|
||||
int rmsgpack_read(int fd,
|
||||
struct rmsgpack_read_callbacks *callbacks, void *data)
|
||||
{
|
||||
int rv;
|
||||
@ -467,7 +455,7 @@ int rmsgpack_read(FILE *fp,
|
||||
uint8_t type = 0;
|
||||
char *buff = NULL;
|
||||
|
||||
if (fpread(fp, &type, sizeof(uint8_t)) == -1)
|
||||
if (read(fd, &type, sizeof(uint8_t)) == -1)
|
||||
return -errno;
|
||||
|
||||
if (type < MPF_FIXMAP)
|
||||
@ -479,20 +467,20 @@ int rmsgpack_read(FILE *fp,
|
||||
else if (type < MPF_FIXARRAY)
|
||||
{
|
||||
tmp_len = type - MPF_FIXMAP;
|
||||
return read_map(fp, (uint32_t)tmp_len, callbacks, data);
|
||||
return read_map(fd, tmp_len, callbacks, data);
|
||||
}
|
||||
else if (type < MPF_FIXSTR)
|
||||
{
|
||||
tmp_len = type - MPF_FIXARRAY;
|
||||
return read_array(fp, (size_t)tmp_len, callbacks, data);
|
||||
return read_array(fd, tmp_len, callbacks, data);
|
||||
}
|
||||
else if (type < MPF_NIL)
|
||||
{
|
||||
tmp_len = type - MPF_FIXSTR;
|
||||
buff = (char *)calloc((size_t)tmp_len + 1, sizeof(char));
|
||||
buff = (char *)calloc(tmp_len + 1, sizeof(char));
|
||||
if (!buff)
|
||||
return -ENOMEM;
|
||||
if (fpread(fp, buff, (size_t)tmp_len) == -1)
|
||||
if (read(fd, buff, tmp_len) == -1)
|
||||
{
|
||||
free(buff);
|
||||
return -errno;
|
||||
@ -503,7 +491,7 @@ int rmsgpack_read(FILE *fp,
|
||||
free(buff);
|
||||
return 0;
|
||||
}
|
||||
return callbacks->read_string(buff, (size_t)tmp_len, data);
|
||||
return callbacks->read_string(buff, tmp_len, data);
|
||||
}
|
||||
else if (type > MPF_MAP32)
|
||||
{
|
||||
@ -529,20 +517,20 @@ int rmsgpack_read(FILE *fp,
|
||||
case 0xc4:
|
||||
case 0xc5:
|
||||
case 0xc6:
|
||||
if ((rv = read_buff(fp, 1<<(type - 0xc4),
|
||||
if ((rv = read_buff(fd, 1<<(type - 0xc4),
|
||||
&buff, &tmp_len)) < 0)
|
||||
return rv;
|
||||
|
||||
if (callbacks->read_bin)
|
||||
return callbacks->read_bin(buff, (size_t)tmp_len, data);
|
||||
return callbacks->read_bin(buff, tmp_len, data);
|
||||
break;
|
||||
case 0xcc:
|
||||
case 0xcd:
|
||||
case 0xce:
|
||||
case 0xcf:
|
||||
tmp_len = UINT32_C(1) << (type - 0xcc);
|
||||
tmp_len = 1ULL << (type - 0xcc);
|
||||
tmp_uint = 0;
|
||||
if (read_uint(fp, &tmp_uint, (size_t)tmp_len) == -1)
|
||||
if (read_uint(fd, &tmp_uint, tmp_len) == -1)
|
||||
return -errno;
|
||||
|
||||
if (callbacks->read_uint)
|
||||
@ -552,9 +540,9 @@ int rmsgpack_read(FILE *fp,
|
||||
case 0xd1:
|
||||
case 0xd2:
|
||||
case 0xd3:
|
||||
tmp_len = UINT32_C(1) << (type - 0xd0);
|
||||
tmp_len = 1ULL << (type - 0xd0);
|
||||
tmp_int = 0;
|
||||
if (read_int(fp, &tmp_int, (size_t)tmp_len) == -1)
|
||||
if (read_int(fd, &tmp_int, tmp_len) == -1)
|
||||
return -errno;
|
||||
|
||||
if (callbacks->read_int)
|
||||
@ -563,24 +551,24 @@ int rmsgpack_read(FILE *fp,
|
||||
case 0xd9:
|
||||
case 0xda:
|
||||
case 0xdb:
|
||||
if ((rv = read_buff(fp, 1<<(type - 0xd9), &buff, &tmp_len)) < 0)
|
||||
if ((rv = read_buff(fd, 1<<(type - 0xd9), &buff, &tmp_len)) < 0)
|
||||
return rv;
|
||||
|
||||
if (callbacks->read_string)
|
||||
return callbacks->read_string(buff, (size_t)tmp_len, data);
|
||||
return callbacks->read_string(buff, tmp_len, data);
|
||||
break;
|
||||
case 0xdc:
|
||||
case 0xdd:
|
||||
if (read_uint(fp, &tmp_len, 2<<(type - 0xdc)) == -1)
|
||||
if (read_uint(fd, &tmp_len, 2<<(type - 0xdc)) == -1)
|
||||
return -errno;
|
||||
|
||||
return read_array(fp, (size_t)tmp_len, callbacks, data);
|
||||
return read_array(fd, tmp_len, callbacks, data);
|
||||
case 0xde:
|
||||
case 0xdf:
|
||||
if (read_uint(fp, &tmp_len, 2<<(type - 0xde)) == -1)
|
||||
if (read_uint(fd, &tmp_len, 2<<(type - 0xde)) == -1)
|
||||
return -errno;
|
||||
|
||||
return read_map(fp, (size_t)tmp_len, callbacks, data);
|
||||
return read_map(fd, tmp_len, callbacks, data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1,7 +1,6 @@
|
||||
#ifndef __RARCHDB_MSGPACK_H__
|
||||
#define __RARCHDB_MSGPACK_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct rmsgpack_read_callbacks {
|
||||
@ -40,39 +39,39 @@ struct rmsgpack_read_callbacks {
|
||||
|
||||
|
||||
int rmsgpack_write_array_header(
|
||||
FILE *fp,
|
||||
int fd,
|
||||
uint32_t size
|
||||
);
|
||||
int rmsgpack_write_map_header(
|
||||
FILE *fp,
|
||||
int fd,
|
||||
uint32_t size
|
||||
);
|
||||
int rmsgpack_write_string(
|
||||
FILE *fp,
|
||||
int fd,
|
||||
const char * s,
|
||||
uint32_t len
|
||||
);
|
||||
int rmsgpack_write_bin(
|
||||
FILE *fp,
|
||||
int fd,
|
||||
const void * s,
|
||||
uint32_t len
|
||||
);
|
||||
int rmsgpack_write_nil(FILE *fp);
|
||||
int rmsgpack_write_nil(int fd);
|
||||
int rmsgpack_write_bool(
|
||||
FILE *fp,
|
||||
int fd,
|
||||
int value
|
||||
);
|
||||
int rmsgpack_write_int(
|
||||
FILE *fp,
|
||||
int fd,
|
||||
int64_t value
|
||||
);
|
||||
int rmsgpack_write_uint(
|
||||
FILE *fp,
|
||||
int fd,
|
||||
uint64_t value
|
||||
);
|
||||
|
||||
int rmsgpack_read(
|
||||
FILE *fp,
|
||||
int fd,
|
||||
struct rmsgpack_read_callbacks * callbacks,
|
||||
void * data
|
||||
);
|
||||
|
@ -13,74 +13,24 @@
|
||||
|
||||
struct dom_reader_state
|
||||
{
|
||||
int i;
|
||||
struct rmsgpack_dom_value *stack[MAX_DEPTH];
|
||||
int i;
|
||||
struct rmsgpack_dom_value *stack[MAX_DEPTH];
|
||||
};
|
||||
|
||||
static struct rmsgpack_dom_value *dom_reader_state_pop(
|
||||
struct dom_reader_state *s)
|
||||
static struct rmsgpack_dom_value *dom_reader_state_pop(struct dom_reader_state *s)
|
||||
{
|
||||
struct rmsgpack_dom_value *v = s->stack[s->i];
|
||||
s->i--;
|
||||
return v;
|
||||
struct rmsgpack_dom_value *v = s->stack[s->i];
|
||||
s->i--;
|
||||
return v;
|
||||
}
|
||||
|
||||
static void puts_i64(int64_t dec)
|
||||
static int dom_reader_state_push(struct dom_reader_state *s, struct rmsgpack_dom_value *v)
|
||||
{
|
||||
unsigned i;
|
||||
signed j;
|
||||
signed char digits[19 + 1] = {0}; /* max i64: 9,223,372,036,854,775,807 */
|
||||
uint64_t decimal = (dec < 0) ? (uint64_t)-dec : (uint64_t)+dec;
|
||||
|
||||
digits[19] = '\0';
|
||||
|
||||
for (j = sizeof(digits) - 2; j >= 0; j--)
|
||||
{
|
||||
digits[j] = decimal % 10;
|
||||
decimal /= 10;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(digits) - 1; i++)
|
||||
digits[i] += '0';
|
||||
|
||||
for (i = 0; i < sizeof(digits) - 2; i++)
|
||||
if (digits[i] != '0')
|
||||
break; /* Don't print leading zeros to the console. */
|
||||
|
||||
if (dec < 0)
|
||||
putchar('-');
|
||||
fputs((char *)&digits[i], stdout);
|
||||
}
|
||||
|
||||
static void puts_u64(uint64_t decimal)
|
||||
{
|
||||
signed j;
|
||||
unsigned i;
|
||||
char digits[20 + 1] = {0}; /* max u64: 18,446,744,073,709,551,616 */
|
||||
|
||||
for (j = sizeof(digits) - 2; j >= 0; j--)
|
||||
{
|
||||
digits[j] = decimal % 10;
|
||||
decimal /= 10;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(digits) - 1; i++)
|
||||
digits[i] += '0';
|
||||
for (i = 0; i < sizeof(digits) - 2; i++)
|
||||
if (digits[i] != '0')
|
||||
break; /* Don't print leading zeros to the console. */
|
||||
|
||||
fputs(&digits[i], stdout);
|
||||
}
|
||||
|
||||
static int dom_reader_state_push(struct dom_reader_state *s,
|
||||
struct rmsgpack_dom_value *v)
|
||||
{
|
||||
if ((s->i + 1) == MAX_DEPTH)
|
||||
return -ENOMEM;
|
||||
s->i++;
|
||||
s->stack[s->i] = v;
|
||||
return 0;
|
||||
if ((s->i + 1) == MAX_DEPTH)
|
||||
return -ENOMEM;
|
||||
s->i++;
|
||||
s->stack[s->i] = v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dom_read_nil(void *data)
|
||||
@ -99,7 +49,7 @@ static int dom_read_bool(int value, void *data)
|
||||
(struct rmsgpack_dom_value*)dom_reader_state_pop(dom_state);
|
||||
|
||||
v->type = RDT_BOOL;
|
||||
v->val.bool_ = value;
|
||||
v->bool_ = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -110,7 +60,7 @@ static int dom_read_int(int64_t value, void *data)
|
||||
(struct rmsgpack_dom_value*)dom_reader_state_pop(dom_state);
|
||||
|
||||
v->type = RDT_INT;
|
||||
v->val.int_ = value;
|
||||
v->int_ = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -121,7 +71,7 @@ static int dom_read_uint(uint64_t value, void *data)
|
||||
(struct rmsgpack_dom_value*)dom_reader_state_pop(dom_state);
|
||||
|
||||
v->type = RDT_UINT;
|
||||
v->val.uint_ = value;
|
||||
v->uint_ = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -132,8 +82,8 @@ static int dom_read_string(char *value, uint32_t len, void *data)
|
||||
(struct rmsgpack_dom_value*)dom_reader_state_pop(dom_state);
|
||||
|
||||
v->type = RDT_STRING;
|
||||
v->val.string.len = len;
|
||||
v->val.string.buff = value;
|
||||
v->string.len = len;
|
||||
v->string.buff = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -142,10 +92,10 @@ static int dom_read_bin(void *value, uint32_t len, void *data)
|
||||
struct dom_reader_state *dom_state = (struct dom_reader_state *)data;
|
||||
struct rmsgpack_dom_value *v =
|
||||
(struct rmsgpack_dom_value*)dom_reader_state_pop(dom_state);
|
||||
|
||||
|
||||
v->type = RDT_BINARY;
|
||||
v->val.binary.len = len;
|
||||
v->val.binary.buff = (char *)value;
|
||||
v->binary.len = len;
|
||||
v->binary.buff = (char *)value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -157,8 +107,8 @@ static int dom_read_map_start(uint32_t len, void *data)
|
||||
struct rmsgpack_dom_value *v = dom_reader_state_pop(dom_state);
|
||||
|
||||
v->type = RDT_MAP;
|
||||
v->val.map.len = len;
|
||||
v->val.map.items = NULL;
|
||||
v->map.len = len;
|
||||
v->map.items = NULL;
|
||||
|
||||
items = (struct rmsgpack_dom_pair *)calloc(len,
|
||||
sizeof(struct rmsgpack_dom_pair));
|
||||
@ -166,7 +116,7 @@ static int dom_read_map_start(uint32_t len, void *data)
|
||||
if (!items)
|
||||
return -ENOMEM;
|
||||
|
||||
v->val.map.items = items;
|
||||
v->map.items = items;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
@ -181,40 +131,40 @@ static int dom_read_map_start(uint32_t len, void *data)
|
||||
|
||||
static int dom_read_array_start(uint32_t len, void *data)
|
||||
{
|
||||
unsigned i;
|
||||
struct dom_reader_state *dom_state = (struct dom_reader_state *)data;
|
||||
struct rmsgpack_dom_value *v = dom_reader_state_pop(dom_state);
|
||||
struct rmsgpack_dom_value *items = NULL;
|
||||
unsigned i;
|
||||
struct dom_reader_state *dom_state = (struct dom_reader_state *)data;
|
||||
struct rmsgpack_dom_value *v = dom_reader_state_pop(dom_state);
|
||||
struct rmsgpack_dom_value *items = NULL;
|
||||
|
||||
v->type = RDT_ARRAY;
|
||||
v->val.array.len = len;
|
||||
v->val.array.items = NULL;
|
||||
v->type = RDT_ARRAY;
|
||||
v->array.len = len;
|
||||
v->array.items = NULL;
|
||||
|
||||
items = (struct rmsgpack_dom_value *)calloc(len, sizeof(struct rmsgpack_dom_pair));
|
||||
items = (struct rmsgpack_dom_value *)calloc(len, sizeof(struct rmsgpack_dom_pair));
|
||||
|
||||
if (!items)
|
||||
return -ENOMEM;
|
||||
if (!items)
|
||||
return -ENOMEM;
|
||||
|
||||
v->val.array.items = items;
|
||||
v->array.items = items;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (dom_reader_state_push(dom_state, &items[i]) < 0)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rmsgpack_read_callbacks dom_reader_callbacks = {
|
||||
dom_read_nil,
|
||||
dom_read_bool,
|
||||
dom_read_int,
|
||||
dom_read_uint,
|
||||
dom_read_string,
|
||||
dom_read_bin,
|
||||
dom_read_map_start,
|
||||
dom_read_array_start
|
||||
dom_read_nil,
|
||||
dom_read_bool,
|
||||
dom_read_int,
|
||||
dom_read_uint,
|
||||
dom_read_string,
|
||||
dom_read_bin,
|
||||
dom_read_map_start,
|
||||
dom_read_array_start
|
||||
};
|
||||
|
||||
void rmsgpack_dom_value_free(struct rmsgpack_dom_value *v)
|
||||
@ -224,33 +174,29 @@ void rmsgpack_dom_value_free(struct rmsgpack_dom_value *v)
|
||||
switch (v->type)
|
||||
{
|
||||
case RDT_STRING:
|
||||
free(v->val.string.buff);
|
||||
v->val.string.buff = NULL;
|
||||
free(v->string.buff);
|
||||
break;
|
||||
case RDT_BINARY:
|
||||
free(v->val.binary.buff);
|
||||
v->val.binary.buff = NULL;
|
||||
free(v->binary.buff);
|
||||
break;
|
||||
case RDT_MAP:
|
||||
for (i = 0; i < v->val.map.len; i++)
|
||||
for (i = 0; i < v->map.len; i++)
|
||||
{
|
||||
rmsgpack_dom_value_free(&v->val.map.items[i].key);
|
||||
rmsgpack_dom_value_free(&v->val.map.items[i].value);
|
||||
rmsgpack_dom_value_free(&v->map.items[i].key);
|
||||
rmsgpack_dom_value_free(&v->map.items[i].value);
|
||||
}
|
||||
free(v->val.map.items);
|
||||
v->val.map.items = NULL;
|
||||
free(v->map.items);
|
||||
break;
|
||||
case RDT_ARRAY:
|
||||
for (i = 0; i < v->val.array.len; i++)
|
||||
rmsgpack_dom_value_free(&v->val.array.items[i]);
|
||||
free(v->val.array.items);
|
||||
v->val.array.items = NULL;
|
||||
for (i = 0; i < v->array.len; i++)
|
||||
rmsgpack_dom_value_free(&v->array.items[i]);
|
||||
free(v->array.items);
|
||||
break;
|
||||
case RDT_NULL:
|
||||
case RDT_INT:
|
||||
case RDT_BOOL:
|
||||
case RDT_UINT:
|
||||
/* Do nothing */
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -263,10 +209,10 @@ struct rmsgpack_dom_value *rmsgpack_dom_value_map_value(
|
||||
if (map->type != RDT_MAP)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < map->val.map.len; i++)
|
||||
for (i = 0; i < map->map.len; i++)
|
||||
{
|
||||
if (rmsgpack_dom_value_cmp(key, &map->val.map.items[i].key) == 0)
|
||||
return &map->val.map.items[i].value;
|
||||
if (rmsgpack_dom_value_cmp(key, &map->map.items[i].key) == 0)
|
||||
return &map->map.items[i].value;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -274,7 +220,7 @@ struct rmsgpack_dom_value *rmsgpack_dom_value_map_value(
|
||||
int rmsgpack_dom_value_cmp(
|
||||
const struct rmsgpack_dom_value *a,
|
||||
const struct rmsgpack_dom_value *b
|
||||
)
|
||||
)
|
||||
{
|
||||
int rv;
|
||||
unsigned i;
|
||||
@ -290,39 +236,39 @@ int rmsgpack_dom_value_cmp(
|
||||
case RDT_NULL:
|
||||
return 0;
|
||||
case RDT_BOOL:
|
||||
return (a->val.bool_ == b->val.bool_) ? 0 : 1;
|
||||
return a->bool_ == b->bool_ ? 0 : 1;
|
||||
case RDT_INT:
|
||||
return (a->val.int_ == b->val.int_) ? 0 : 1;
|
||||
return a->int_ == b->int_ ? 0 : 1;
|
||||
case RDT_UINT:
|
||||
return (a->val.uint_ == b->val.uint_) ? 0 : 1;
|
||||
return a->uint_ == b->uint_ ? 0 : 1;
|
||||
case RDT_STRING:
|
||||
if (a->val.string.len != b->val.string.len)
|
||||
if (a->string.len != b->string.len)
|
||||
return 1;
|
||||
return strncmp(a->val.string.buff, b->val.string.buff, a->val.string.len);
|
||||
return strncmp(a->string.buff, b->string.buff, a->string.len);
|
||||
case RDT_BINARY:
|
||||
if (a->val.binary.len != b->val.binary.len)
|
||||
if (a->binary.len != b->binary.len)
|
||||
return 1;
|
||||
return memcmp(a->val.binary.buff, b->val.binary.buff, a->val.binary.len);
|
||||
return memcmp(a->binary.buff, b->binary.buff, a->binary.len);
|
||||
case RDT_MAP:
|
||||
if (a->val.map.len != b->val.map.len)
|
||||
if (a->map.len != b->map.len)
|
||||
return 1;
|
||||
for (i = 0; i < a->val.map.len; i++)
|
||||
for (i = 0; i < a->map.len; i++)
|
||||
{
|
||||
if ((rv = rmsgpack_dom_value_cmp(&a->val.map.items[i].key,
|
||||
&b->val.map.items[i].key)) != 0)
|
||||
if ((rv = rmsgpack_dom_value_cmp(&a->map.items[i].key,
|
||||
&b->map.items[i].key)) != 0)
|
||||
return rv;
|
||||
if ((rv = rmsgpack_dom_value_cmp(&a->val.map.items[i].value,
|
||||
&b->val.map.items[i].value)) != 0)
|
||||
if ((rv = rmsgpack_dom_value_cmp(&a->map.items[i].value,
|
||||
&b->map.items[i].value)) != 0)
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
case RDT_ARRAY:
|
||||
if (a->val.array.len != b->val.array.len)
|
||||
if (a->array.len != b->array.len)
|
||||
return 1;
|
||||
for (i = 0; i < a->val.array.len; i++)
|
||||
for (i = 0; i < a->array.len; i++)
|
||||
{
|
||||
if ((rv = rmsgpack_dom_value_cmp(&a->val.array.items[i],
|
||||
&b->val.array.items[i])) != 0)
|
||||
if ((rv = rmsgpack_dom_value_cmp(&a->array.items[i],
|
||||
&b->array.items[i])) != 0)
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
@ -341,91 +287,100 @@ void rmsgpack_dom_value_print(struct rmsgpack_dom_value *obj)
|
||||
printf("nil");
|
||||
break;
|
||||
case RDT_BOOL:
|
||||
if (obj->val.bool_)
|
||||
if (obj->bool_)
|
||||
printf("true");
|
||||
else
|
||||
printf("false");
|
||||
break;
|
||||
case RDT_INT:
|
||||
puts_i64(obj->val.int_);
|
||||
#ifdef _WIN32
|
||||
printf("%I64d", (signed long long)obj->int_);
|
||||
#else
|
||||
printf("%lld", (signed long long)obj->int_);
|
||||
#endif
|
||||
break;
|
||||
case RDT_UINT:
|
||||
puts_u64(obj->val.uint_);
|
||||
#ifdef _WIN32
|
||||
printf("%I64u", (unsigned long long)obj->uint_);
|
||||
#else
|
||||
printf("%llu", (unsigned long long)obj->uint_);
|
||||
#endif
|
||||
break;
|
||||
case RDT_STRING:
|
||||
printf("\"%s\"", obj->val.string.buff);
|
||||
break; case RDT_BINARY:
|
||||
printf("\"%s\"", obj->string.buff);
|
||||
break;
|
||||
case RDT_BINARY:
|
||||
printf("\"");
|
||||
for (i = 0; i < obj->val.binary.len; i++)
|
||||
printf("%02X", (unsigned char) obj->val.binary.buff[i]);
|
||||
for (i = 0; i < obj->binary.len; i++)
|
||||
printf("%02X", (unsigned char) obj->binary.buff[i]);
|
||||
printf("\"");
|
||||
break;
|
||||
case RDT_MAP:
|
||||
printf("{");
|
||||
for (i = 0; i < obj->val.map.len; i++)
|
||||
for (i = 0; i < obj->map.len; i++)
|
||||
{
|
||||
rmsgpack_dom_value_print(&obj->val.map.items[i].key);
|
||||
rmsgpack_dom_value_print(&obj->map.items[i].key);
|
||||
printf(": ");
|
||||
rmsgpack_dom_value_print(&obj->val.map.items[i].value);
|
||||
if (i < (obj->val.map.len - 1))
|
||||
rmsgpack_dom_value_print(&obj->map.items[i].value);
|
||||
if (i < (obj->map.len - 1))
|
||||
printf(", ");
|
||||
}
|
||||
printf("}");
|
||||
break;
|
||||
case RDT_ARRAY:
|
||||
printf("[");
|
||||
for (i = 0; i < obj->val.array.len; i++)
|
||||
for (i = 0; i < obj->array.len; i++)
|
||||
{
|
||||
rmsgpack_dom_value_print(&obj->val.array.items[i]);
|
||||
if (i < (obj->val.array.len - 1))
|
||||
rmsgpack_dom_value_print(&obj->array.items[i]);
|
||||
if (i < (obj->array.len - 1))
|
||||
printf(", ");
|
||||
}
|
||||
printf("]");
|
||||
}
|
||||
}
|
||||
int rmsgpack_dom_write(FILE *fp, const struct rmsgpack_dom_value *obj)
|
||||
int rmsgpack_dom_write(int fd, const struct rmsgpack_dom_value *obj)
|
||||
{
|
||||
unsigned i;
|
||||
int rv = 0;
|
||||
int rv = 0;
|
||||
int written = 0;
|
||||
|
||||
switch (obj->type)
|
||||
{
|
||||
case RDT_NULL:
|
||||
return rmsgpack_write_nil(fp);
|
||||
return rmsgpack_write_nil(fd);
|
||||
case RDT_BOOL:
|
||||
return rmsgpack_write_bool(fp, obj->val.bool_);
|
||||
return rmsgpack_write_bool(fd, obj->bool_);
|
||||
case RDT_INT:
|
||||
return rmsgpack_write_int(fp, obj->val.int_);
|
||||
return rmsgpack_write_int(fd, obj->int_);
|
||||
case RDT_UINT:
|
||||
return rmsgpack_write_uint(fp, obj->val.uint_);
|
||||
return rmsgpack_write_uint(fd, obj->uint_);
|
||||
case RDT_STRING:
|
||||
return rmsgpack_write_string(fp, obj->val.string.buff, obj->val.string.len);
|
||||
return rmsgpack_write_string(fd, obj->string.buff, obj->string.len);
|
||||
case RDT_BINARY:
|
||||
return rmsgpack_write_bin(fp, obj->val.binary.buff, obj->val.binary.len);
|
||||
return rmsgpack_write_bin(fd, obj->binary.buff, obj->binary.len);
|
||||
case RDT_MAP:
|
||||
if ((rv = rmsgpack_write_map_header(fp, obj->val.map.len)) < 0)
|
||||
if ((rv = rmsgpack_write_map_header(fd, obj->map.len)) < 0)
|
||||
return rv;
|
||||
written += rv;
|
||||
|
||||
for (i = 0; i < obj->val.map.len; i++)
|
||||
for (i = 0; i < obj->map.len; i++)
|
||||
{
|
||||
if ((rv = rmsgpack_dom_write(fp, &obj->val.map.items[i].key)) < 0)
|
||||
if ((rv = rmsgpack_dom_write(fd, &obj->map.items[i].key)) < 0)
|
||||
return rv;
|
||||
written += rv;
|
||||
if ((rv = rmsgpack_dom_write(fp, &obj->val.map.items[i].value)) < 0)
|
||||
if ((rv = rmsgpack_dom_write(fd, &obj->map.items[i].value)) < 0)
|
||||
return rv;
|
||||
written += rv;
|
||||
}
|
||||
break;
|
||||
case RDT_ARRAY:
|
||||
if ((rv = rmsgpack_write_array_header(fp, obj->val.array.len)) < 0)
|
||||
if ((rv = rmsgpack_write_array_header(fd, obj->array.len)) < 0)
|
||||
return rv;
|
||||
written += rv;
|
||||
|
||||
for (i = 0; i < obj->val.array.len; i++)
|
||||
for (i = 0; i < obj->array.len; i++)
|
||||
{
|
||||
if ((rv = rmsgpack_dom_write(fp, &obj->val.array.items[i])) < 0)
|
||||
if ((rv = rmsgpack_dom_write(fd, &obj->array.items[i])) < 0)
|
||||
return rv;
|
||||
written += rv;
|
||||
}
|
||||
@ -433,14 +388,15 @@ int rmsgpack_dom_write(FILE *fp, const struct rmsgpack_dom_value *obj)
|
||||
return written;
|
||||
}
|
||||
|
||||
int rmsgpack_dom_read(FILE *fp, struct rmsgpack_dom_value *out)
|
||||
int rmsgpack_dom_read(int fd, struct rmsgpack_dom_value *out)
|
||||
{
|
||||
struct dom_reader_state s = {0};
|
||||
int rv = 0;
|
||||
struct dom_reader_state s;
|
||||
int rv = 0;
|
||||
|
||||
s.i = 0;
|
||||
s.stack[0] = out;
|
||||
|
||||
rv = rmsgpack_read(fp, &dom_reader_callbacks, &s);
|
||||
rv = rmsgpack_read(fd, &dom_reader_callbacks, &s);
|
||||
|
||||
if (rv < 0)
|
||||
rmsgpack_dom_value_free(out);
|
||||
@ -448,23 +404,26 @@ int rmsgpack_dom_read(FILE *fp, struct rmsgpack_dom_value *out)
|
||||
return rv;
|
||||
}
|
||||
|
||||
int rmsgpack_dom_read_into(FILE *fp, ...)
|
||||
int rmsgpack_dom_read_into(int fd, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int rv;
|
||||
struct rmsgpack_dom_value map;
|
||||
int rv;
|
||||
const char *key_name;
|
||||
struct rmsgpack_dom_value key;
|
||||
struct rmsgpack_dom_value *value;
|
||||
int64_t *int_value;
|
||||
uint64_t *uint_value;
|
||||
int *bool_value;
|
||||
char *buff_value;
|
||||
uint64_t min_len;
|
||||
char *buff_value = NULL;
|
||||
const char *key_name = NULL;
|
||||
int value_type = 0;
|
||||
|
||||
va_start(ap, fp);
|
||||
va_start(ap, fd);
|
||||
|
||||
rv = rmsgpack_dom_read(fp, &map);
|
||||
rv = rmsgpack_dom_read(fd, &map);
|
||||
|
||||
(void)value_type;
|
||||
|
||||
if (rv < 0)
|
||||
{
|
||||
@ -473,18 +432,24 @@ int rmsgpack_dom_read_into(FILE *fp, ...)
|
||||
}
|
||||
|
||||
if (map.type != RDT_MAP)
|
||||
goto error;
|
||||
{
|
||||
rv = -EINVAL;
|
||||
goto clean;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
key_name = va_arg(ap, const char *);
|
||||
|
||||
if (!key_name)
|
||||
goto error;
|
||||
{
|
||||
rv = 0;
|
||||
goto clean;
|
||||
}
|
||||
|
||||
key.type = RDT_STRING;
|
||||
key.val.string.len = strlen(key_name);
|
||||
key.val.string.buff = (char *) key_name;
|
||||
key.string.len = strlen(key_name);
|
||||
key.string.buff = (char *) key_name;
|
||||
|
||||
value = rmsgpack_dom_value_map_value(&map, &key);
|
||||
|
||||
@ -492,40 +457,41 @@ int rmsgpack_dom_read_into(FILE *fp, ...)
|
||||
{
|
||||
case RDT_INT:
|
||||
int_value = va_arg(ap, int64_t *);
|
||||
*int_value = value->val.int_;
|
||||
*int_value = value->int_;
|
||||
break;
|
||||
case RDT_BOOL:
|
||||
bool_value = va_arg(ap, int *);
|
||||
*bool_value = value->val.bool_;
|
||||
*bool_value = value->bool_;
|
||||
break;
|
||||
case RDT_UINT:
|
||||
uint_value = va_arg(ap, uint64_t *);
|
||||
*uint_value = value->val.uint_;
|
||||
*uint_value = value->uint_;
|
||||
break;
|
||||
case RDT_BINARY:
|
||||
buff_value = va_arg(ap, char *);
|
||||
uint_value = va_arg(ap, uint64_t *);
|
||||
*uint_value = value->val.binary.len;
|
||||
min_len = (value->val.binary.len > *uint_value) ?
|
||||
*uint_value : value->val.binary.len;
|
||||
*uint_value = value->binary.len;
|
||||
min_len = (value->binary.len > *uint_value) ?
|
||||
*uint_value : value->binary.len;
|
||||
|
||||
memcpy(buff_value, value->val.binary.buff, (size_t)min_len);
|
||||
memcpy(buff_value, value->binary.buff, min_len);
|
||||
break;
|
||||
case RDT_STRING:
|
||||
buff_value = va_arg(ap, char *);
|
||||
uint_value = va_arg(ap, uint64_t *);
|
||||
min_len = (value->val.string.len + 1 > *uint_value) ?
|
||||
*uint_value : value->val.string.len + 1;
|
||||
min_len = (value->string.len + 1 > *uint_value) ?
|
||||
*uint_value : value->string.len + 1;
|
||||
*uint_value = min_len;
|
||||
|
||||
memcpy(buff_value, value->val.string.buff, (size_t)min_len);
|
||||
memcpy(buff_value, value->string.buff, min_len);
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
rv = -1;
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
clean:
|
||||
va_end(ap);
|
||||
rmsgpack_dom_value_free(&map);
|
||||
return 0;
|
||||
|
@ -1,7 +1,6 @@
|
||||
#ifndef __RARCHDB_MSGPACK_DOM_H__
|
||||
#define __RARCHDB_MSGPACK_DOM_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -24,32 +23,24 @@ struct rmsgpack_dom_value {
|
||||
union {
|
||||
uint64_t uint_;
|
||||
int64_t int_;
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint32_t len;
|
||||
char * buff;
|
||||
} string;
|
||||
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint32_t len;
|
||||
char * buff;
|
||||
} binary;
|
||||
|
||||
int bool_;
|
||||
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint32_t len;
|
||||
struct rmsgpack_dom_pair * items;
|
||||
} map;
|
||||
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
uint32_t len;
|
||||
struct rmsgpack_dom_value * items;
|
||||
} array;
|
||||
} val;
|
||||
};
|
||||
};
|
||||
|
||||
struct rmsgpack_dom_pair {
|
||||
@ -70,15 +61,15 @@ struct rmsgpack_dom_value * rmsgpack_dom_value_map_value(
|
||||
);
|
||||
|
||||
int rmsgpack_dom_read(
|
||||
FILE *fp,
|
||||
int fd,
|
||||
struct rmsgpack_dom_value * out
|
||||
);
|
||||
int rmsgpack_dom_write(
|
||||
FILE *fp,
|
||||
int fd,
|
||||
const struct rmsgpack_dom_value * obj
|
||||
);
|
||||
|
||||
int rmsgpack_dom_read_into(FILE *fp, ...);
|
||||
int rmsgpack_dom_read_into(int fd, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -162,17 +162,42 @@ static struct rmsgpack_read_callbacks stub_callbacks = {
|
||||
|
||||
int main(void)
|
||||
{
|
||||
FILE *fp;
|
||||
int fd;
|
||||
/*
|
||||
int fd = open("test.msgpack", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
int rv = 0;
|
||||
if (fd == -1)
|
||||
{
|
||||
printf("Could not open file: %s", strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
rmsgpack_write_map_header(fd, 2);
|
||||
rmsgpack_write_string(fd, "compact", strlen("compact"));
|
||||
rmsgpack_write_bool(fd, 1);
|
||||
rmsgpack_write_string(fd, "schema", strlen("schema"));
|
||||
rmsgpack_write_array_header(fd, 10);
|
||||
rmsgpack_write_string(fd, "schema", strlen("schema"));
|
||||
rmsgpack_write_uint(fd, 1<<17);
|
||||
rmsgpack_write_int(fd, (1<<17) + 1);
|
||||
rmsgpack_write_int(fd, 4);
|
||||
rmsgpack_write_int(fd, -3);
|
||||
rmsgpack_write_int(fd, -22);
|
||||
rmsgpack_write_int(fd, -35);
|
||||
rmsgpack_write_int(fd, -421421412);
|
||||
rmsgpack_write_int(fd, 4214);
|
||||
rmsgpack_write_int(fd, -4214);
|
||||
rmsgpack_write_uint(fd, 1<<17);
|
||||
close(fd);
|
||||
*/
|
||||
|
||||
struct stub_state state;
|
||||
|
||||
state.i = 0;
|
||||
state.stack[0] = 0;
|
||||
|
||||
fp = fopen("test.msgpack", "rb");
|
||||
rmsgpack_read(fp, &stub_callbacks, &state);
|
||||
|
||||
fd = open("test.msgpack", O_RDONLY);
|
||||
rmsgpack_read(fd, &stub_callbacks, &state);
|
||||
printf("\n");
|
||||
fclose(fp);
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user