Ejemplo n.º 1
0
void rmsgpack_dom_value_free(struct rmsgpack_dom_value *v)
{
   unsigned i;

   switch (v->type)
   {
      case RDT_STRING:
         free(v->val.string.buff);
         break;
      case RDT_BINARY:
         free(v->val.binary.buff);
         break;
      case RDT_MAP:
         for (i = 0; i < v->val.map.len; i++)
         {
            rmsgpack_dom_value_free(&v->val.map.items[i].key);
            rmsgpack_dom_value_free(&v->val.map.items[i].value);
         }
         free(v->val.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);
         break;
      case RDT_NULL:
      case RDT_INT:
      case RDT_BOOL:
      case RDT_UINT:
         /* Do nothing */
         break;
   }
}
Ejemplo n.º 2
0
int libretrodb_cursor_read_item(libretrodb_cursor_t *cursor,
      struct rmsgpack_dom_value *out)
{
   int rv;

   if (cursor->eof)
      return EOF;

retry:
   rv = rmsgpack_dom_read(cursor->fd, out);
   if (rv < 0)
      return rv;

   if (out->type == RDT_NULL)
   {
      cursor->eof = 1;
      return EOF;
   }

   if (cursor->query)
   {
      if (!libretrodb_query_filter(cursor->query, out))
      {
         rmsgpack_dom_value_free(out);
         goto retry;
      }
   }

   return 0;
}
Ejemplo n.º 3
0
int libretrodb_create(RFILE *fd, libretrodb_value_provider value_provider,
      void *ctx)
{
   int rv;
   libretrodb_metadata_t md;
   struct rmsgpack_dom_value item;
   uint64_t item_count        = 0;
   libretrodb_header_t header = {{0}};
   ssize_t root = filestream_seek(fd, 0, SEEK_CUR);

   memcpy(header.magic_number, MAGIC_NUMBER, sizeof(MAGIC_NUMBER)-1);

   /* We write the header in the end because we need to know the size of
    * the db first */

   filestream_seek(fd, sizeof(libretrodb_header_t), SEEK_CUR);

   item.type = RDT_NULL;
   while ((rv = value_provider(ctx, &item)) == 0)
   {
      if ((rv = libretrodb_validate_document(&item)) < 0)
         goto clean;

      if ((rv = rmsgpack_dom_write(fd, &item)) < 0)
         goto clean;

      rmsgpack_dom_value_free(&item);
      item.type = RDT_NULL;
      item_count++;
   }

   if (rv < 0)
      goto clean;

   if ((rv = rmsgpack_dom_write(fd, &sentinal)) < 0)
      goto clean;

   header.metadata_offset = swap_if_little64(filestream_seek(fd, 0, SEEK_CUR));
   md.count = item_count;
   libretrodb_write_metadata(fd, &md);
   filestream_seek(fd, root, SEEK_SET);
   filestream_write(fd, &header, sizeof(header));
clean:
   rmsgpack_dom_value_free(&item);
   return rv;
}
Ejemplo n.º 4
0
static void argument_free(struct argument *arg)
{
   unsigned i;

   if (arg->type != AT_FUNCTION)
   {
      rmsgpack_dom_value_free(&arg->a.value);
      return;
   }

   for (i = 0; i < arg->a.invocation.argc; i++)
      argument_free(&arg->a.invocation.argv[i]);
}
Ejemplo n.º 5
0
int rmsgpack_dom_read(FILE *fp, struct rmsgpack_dom_value *out)
{
   struct dom_reader_state s = {0};
   int rv                    = 0;

   s.stack[0] = out;

   rv = rmsgpack_read(fp, &dom_reader_callbacks, &s);

   if (rv < 0)
      rmsgpack_dom_value_free(out);

   return rv;
}
Ejemplo n.º 6
0
int libretrodb_create(int fd, libretrodb_value_provider value_provider,
        void * ctx)
{
   int rv;
   off_t root;
   libretrodb_metadata_t md;
   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 = lseek(fd, 0, SEEK_CUR);

   /* We write the header in the end because we need to know the size of
    * the db first */

   lseek(fd, sizeof(libretrodb_header_t), SEEK_CUR);

   while ((rv = value_provider(ctx, &item)) == 0)
   {
      if ((rv = validate_document(&item)) < 0)
         goto clean;

      if ((rv = rmsgpack_dom_write(fd, &item)) < 0)
         goto clean;

      item_count++;
   }

   if (rv < 0)
      goto clean;

   if ((rv = rmsgpack_dom_write(fd, &sentinal)) < 0)
      goto clean;

   header.metadata_offset = httobe64(lseek(fd, 0, SEEK_CUR));
   md.count = item_count;
   libretrodb_write_metadata(fd, &md);
   lseek(fd, root, SEEK_SET);
   write(fd, &header, sizeof(header));
clean:
   rmsgpack_dom_value_free(&item);
   return rv;
}
Ejemplo n.º 7
0
int main(int argc, char ** argv)
{
   int rv;
   libretrodb_t db;
   libretrodb_cursor_t cur;
   libretrodb_query_t *q;
   struct rmsgpack_dom_value item;
   const char *command, *path, *query_exp, *error;

   if (argc < 3)
   {
      printf("Usage: %s <db file> <command> [extra args...]\n", argv[0]);
      printf("Available Commands:\n");
      printf("\tlist\n");
      printf("\tcreate-index <index name> <field name>\n");
      printf("\tfind <query expression>\n");
      return 1;
   }

   command = argv[2];
   path    = argv[1];

   if ((rv = libretrodb_open(path, &db)) != 0)
   {
      printf("Could not open db file '%s': %s\n", path, strerror(-rv));
      return 1;
   }
   else if (strcmp(command, "list") == 0)
   {
      if ((rv = libretrodb_cursor_open(&db, &cur, NULL)) != 0)
      {
         printf("Could not open cursor: %s\n", strerror(-rv));
         return 1;
      }

      if (argc != 3)
      {
         printf("Usage: %s <db file> list\n", argv[0]);
         return 1;
      }

      while (libretrodb_cursor_read_item(&cur, &item) == 0)
      {
         rmsgpack_dom_value_print(&item);
         printf("\n");
         rmsgpack_dom_value_free(&item);
      }
   }
   else if (strcmp(command, "find") == 0)
   {
      if (argc != 4)
      {
         printf("Usage: %s <db file> find <query expression>\n", argv[0]);
         return 1;
      }

      query_exp = argv[3];
      error = NULL;
      q = libretrodb_query_compile(&db, query_exp, strlen(query_exp), &error);

      if (error)
      {
         printf("%s\n", error);
         return 1;
      }

      if ((rv = libretrodb_cursor_open(&db, &cur, q)) != 0)
      {
         printf("Could not open cursor: %s\n", strerror(-rv));
         return 1;
      }

      while (libretrodb_cursor_read_item(&cur, &item) == 0)
      {
         rmsgpack_dom_value_print(&item);
         printf("\n");
         rmsgpack_dom_value_free(&item);
      }
   }
   else if (strcmp(command, "create-index") == 0)
   {
      const char * index_name, * field_name;

      if (argc != 5)
      {
         printf("Usage: %s <db file> create-index <index name> <field name>\n", argv[0]);
         return 1;
      }

      index_name = argv[3];
      field_name = argv[4];

      libretrodb_create_index(&db, index_name, field_name);
   }
   else
   {
      printf("Unknown command %s\n", argv[2]);
      return 1;
   }

   libretrodb_close(&db);
   return 1;
}
Ejemplo n.º 8
0
int rmsgpack_dom_read_into(RFILE *fd, ...)
{
   va_list ap;
   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;
   int value_type = 0;

   va_start(ap, fd);

   rv = rmsgpack_dom_read(fd, &map);

   (void)value_type;

   if (rv < 0)
   {
      va_end(ap);
      return rv;
   }

   if (map.type != RDT_MAP)
      goto clean;

   while (1)
   {
      key_name = va_arg(ap, const char *);

      if (!key_name)
         goto clean;

      key.type            = RDT_STRING;
      key.val.string.len  = (uint32_t)strlen(key_name);
      key.val.string.buff = (char *) key_name;

      value = rmsgpack_dom_value_map_value(&map, &key);

      switch (value->type)
      {
         case RDT_INT:
            int_value   = va_arg(ap, int64_t *);
            *int_value  = value->val.int_;
            break;
         case RDT_BOOL:
            bool_value  = va_arg(ap, int *);
            *bool_value = value->val.bool_;
            break;
         case RDT_UINT:
            uint_value  = va_arg(ap, uint64_t *);
            *uint_value = value->val.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;

            memcpy(buff_value, value->val.binary.buff, (size_t)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;
            *uint_value = min_len;

            memcpy(buff_value, value->val.string.buff, (size_t)min_len);
            break;
         default:
            goto clean;
      }
   }

clean:
   va_end(ap);
   rmsgpack_dom_value_free(&map);
   return 0;
}
Ejemplo n.º 9
0
static int database_cursor_iterate(libretrodb_cursor_t *cur,
      database_info_t *db_info)
{
   unsigned i;
   struct rmsgpack_dom_value item;
   const char* str                = NULL;

   if (libretrodb_cursor_read_item(cur, &item) != 0)
      return -1;

   if (item.type != RDT_MAP)
   {
      rmsgpack_dom_value_free(&item);
      return 1;
   }

   db_info->analog_supported       = -1;
   db_info->rumble_supported       = -1;
   db_info->coop_supported         = -1;

   for (i = 0; i < item.val.map.len; i++)
   {
      struct rmsgpack_dom_value *key = &item.val.map.items[i].key;
      struct rmsgpack_dom_value *val = &item.val.map.items[i].value;
      const char *val_string         = NULL;

      if (!key || !val)
         continue;

      val_string                     = val->val.string.buff;
      str                            = key->val.string.buff;

      if (string_is_equal(str, "publisher"))
      {
         if (!string_is_empty(val_string))
            db_info->publisher = strdup(val_string);
      }
      else if (string_is_equal(str, "developer"))
      {
         if (!string_is_empty(val_string))
            db_info->developer = string_split(val_string, "|");
      }
      else if (string_is_equal(str, "serial"))
      {
         if (!string_is_empty(val_string))
            db_info->serial = strdup(val_string);
      }
      else if (string_is_equal(str, "rom_name"))
      {
         if (!string_is_empty(val_string))
            db_info->rom_name = strdup(val_string);
      }
      else if (string_is_equal(str, "name"))
      {
         if (!string_is_empty(val_string))
            db_info->name = strdup(val_string);
      }
      else if (string_is_equal(str, "description"))
      {
         if (!string_is_empty(val_string))
            db_info->description = strdup(val_string);
      }
      else if (string_is_equal(str, "genre"))
      {
         if (!string_is_empty(val_string))
            db_info->genre = strdup(val_string);
      }
      else if (string_is_equal(str, "origin"))
      {
         if (!string_is_empty(val_string))
            db_info->origin = strdup(val_string);
      }
      else if (string_is_equal(str, "franchise"))
      {
         if (!string_is_empty(val_string))
            db_info->franchise = strdup(val_string);
      }
      else if (string_is_equal(str, "bbfc_rating"))
      {
         if (!string_is_empty(val_string))
            db_info->bbfc_rating = strdup(val_string);
      }
      else if (string_is_equal(str, "esrb_rating"))
      {
         if (!string_is_empty(val_string))
            db_info->esrb_rating = strdup(val_string);
      }
      else if (string_is_equal(str, "elspa_rating"))
      {
         if (!string_is_empty(val_string))
            db_info->elspa_rating = strdup(val_string);
      }
      else if (string_is_equal(str, "cero_rating"))
      {
         if (!string_is_empty(val_string))
            db_info->cero_rating          = strdup(val_string);
      }
      else if (string_is_equal(str, "pegi_rating"))
      {
         if (!string_is_empty(val_string))
            db_info->pegi_rating          = strdup(val_string);
      }
      else if (string_is_equal(str, "enhancement_hw"))
      {
         if (!string_is_empty(val_string))
            db_info->enhancement_hw       = strdup(val_string);
      }
      else if (string_is_equal(str, "edge_review"))
      {
         if (!string_is_empty(val_string))
            db_info->edge_magazine_review = strdup(val_string);
      }
      else if (string_is_equal(str, "edge_rating"))
         db_info->edge_magazine_rating    = (unsigned)val->val.uint_;
      else if (string_is_equal(str, "edge_issue"))
         db_info->edge_magazine_issue     = (unsigned)val->val.uint_;
      else if (string_is_equal(str, "famitsu_rating"))
         db_info->famitsu_magazine_rating = (unsigned)val->val.uint_;
      else if (string_is_equal(str, "tgdb_rating"))
         db_info->tgdb_rating             = (unsigned)val->val.uint_;
      else if (string_is_equal(str, "users"))
         db_info->max_users               = (unsigned)val->val.uint_;
      else if (string_is_equal(str, "releasemonth"))
         db_info->releasemonth            = (unsigned)val->val.uint_;
      else if (string_is_equal(str, "releaseyear"))
         db_info->releaseyear             = (unsigned)val->val.uint_;
      else if (string_is_equal(str, "rumble"))
         db_info->rumble_supported        = (int)val->val.uint_;
      else if (string_is_equal(str, "coop"))
         db_info->coop_supported          = (int)val->val.uint_;
      else if (string_is_equal(str, "analog"))
         db_info->analog_supported        = (int)val->val.uint_;
      else if (string_is_equal(str, "size"))
         db_info->size                    = (unsigned)val->val.uint_;
      else if (string_is_equal(str, "crc"))
         db_info->crc32 = swap_if_little32(
               *(uint32_t*)val->val.binary.buff);
      else if (string_is_equal(str, "sha1"))
         db_info->sha1 = bin_to_hex_alloc(
               (uint8_t*)val->val.binary.buff, val->val.binary.len);
      else if (string_is_equal(str, "md5"))
         db_info->md5 = bin_to_hex_alloc(
               (uint8_t*)val->val.binary.buff, val->val.binary.len);
      else
      {
         RARCH_LOG("Unknown key: %s\n", str);
      }
   }

   rmsgpack_dom_value_free(&item);

   return 0;
}
Ejemplo n.º 10
0
int libretrodb_create_index(libretrodb_t *db,
      const char *name, const char *field_name)
{
	int rv;
	struct node_iter_ctx nictx;
	struct rmsgpack_dom_value key;
	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);

	if (libretrodb_cursor_open(db, &cur, NULL) != 0)
   {
		rv = -1;
		goto clean;
	}

	key.type = RDT_STRING;
	key.string.len = strlen(field_name);

	/* We know we aren't going to change it */
	key.string.buff = (char *) field_name;

	while (libretrodb_cursor_read_item(&cur, &item) == 0)
   {
		if (item.type != RDT_MAP)
      {
			rv = -EINVAL;
			printf("Only map keys are supported\n");
			goto clean;
		}

		field = rmsgpack_dom_value_map_value(&item, &key);

		if (!field)
      {
			rv = -EINVAL;
			printf("field not found in item\n");
			goto clean;
		}

		if (field->type != RDT_BINARY)
      {
			rv = -EINVAL;
			printf("field is not binary\n");
			goto clean;
		}

		if (field->binary.len == 0)
      {
			rv = -EINVAL;
			printf("field is empty\n");
			goto clean;
		}

		if (field_size == 0)
			field_size = field->binary.len;
		else if (field->binary.len != field_size)
      {
			rv = -EINVAL;
			printf("field is not of correct size\n");
			goto clean;
		}

		buff = malloc(field_size + sizeof(uint64_t));
		if (!buff)
      {
			rv = -ENOMEM;
			goto clean;
		}

		memcpy(buff, field->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)
      {
			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;
}
Ejemplo n.º 11
0
static int database_cursor_iterate(libretrodb_cursor_t *cur,
      database_info_t *db_info)
{
   unsigned i;
   struct rmsgpack_dom_value item;
   const char* str                = NULL;

   if (libretrodb_cursor_read_item(cur, &item) != 0)
      return -1;

   if (item.type != RDT_MAP)
   {
      rmsgpack_dom_value_free(&item);
      return 1;
   }

   db_info->analog_supported       = -1;
   db_info->rumble_supported       = -1;
   db_info->coop_supported         = -1;

   for (i = 0; i < item.val.map.len; i++)
   {
      uint32_t                 value = 0;
      struct rmsgpack_dom_value *key = &item.val.map.items[i].key;
      struct rmsgpack_dom_value *val = &item.val.map.items[i].value;

      if (!key || !val)
         continue;

      str   = key->val.string.buff;
      value = msg_hash_calculate(str);

      switch (value)
      {
         case DB_CURSOR_SERIAL:
            db_info->serial = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_ROM_NAME:
            db_info->rom_name = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_NAME:
            db_info->name = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_DESCRIPTION:
            db_info->description = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_GENRE:
            db_info->genre = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_PUBLISHER:
            db_info->publisher = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_DEVELOPER:
            db_info->developer = string_split(val->val.string.buff, "|");
            break;
         case DB_CURSOR_ORIGIN:
            db_info->origin = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_FRANCHISE:
            db_info->franchise = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_BBFC_RATING:
            db_info->bbfc_rating = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_ESRB_RATING:
            db_info->esrb_rating = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_ELSPA_RATING:
            db_info->elspa_rating = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_CERO_RATING:
            db_info->cero_rating = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_PEGI_RATING:
            db_info->pegi_rating = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_ENHANCEMENT_HW:
            db_info->enhancement_hw = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_EDGE_MAGAZINE_REVIEW:
            db_info->edge_magazine_review = strdup(val->val.string.buff);
            break;
         case DB_CURSOR_EDGE_MAGAZINE_RATING:
            db_info->edge_magazine_rating = val->val.uint_;
            break;
         case DB_CURSOR_EDGE_MAGAZINE_ISSUE:
            db_info->edge_magazine_issue = val->val.uint_;
            break;
         case DB_CURSOR_FAMITSU_MAGAZINE_RATING:
            db_info->famitsu_magazine_rating = val->val.uint_;
            break;
         case DB_CURSOR_TGDB_RATING:
            db_info->tgdb_rating = val->val.uint_;
            break;
         case DB_CURSOR_MAX_USERS:
            db_info->max_users = val->val.uint_;
            break;
         case DB_CURSOR_RELEASEDATE_MONTH:
            db_info->releasemonth = val->val.uint_;
            break;
         case DB_CURSOR_RELEASEDATE_YEAR:
            db_info->releaseyear = val->val.uint_;
            break;
         case DB_CURSOR_RUMBLE_SUPPORTED:
            db_info->rumble_supported = val->val.uint_;
            break;
         case DB_CURSOR_COOP_SUPPORTED:
            db_info->coop_supported = val->val.uint_;
            break;
         case DB_CURSOR_ANALOG_SUPPORTED:
            db_info->analog_supported = val->val.uint_;
            break;
         case DB_CURSOR_SIZE:
            db_info->size = val->val.uint_;
            break;
         case DB_CURSOR_CHECKSUM_CRC32:
            db_info->crc32 = swap_if_little32(*(uint32_t*)val->val.binary.buff);
            break;
         case DB_CURSOR_CHECKSUM_SHA1:
            db_info->sha1 = bin_to_hex_alloc((uint8_t*)val->val.binary.buff, val->val.binary.len);
            break;
         case DB_CURSOR_CHECKSUM_MD5:
            db_info->md5 = bin_to_hex_alloc((uint8_t*)val->val.binary.buff, val->val.binary.len);
            break;
         default:
            RARCH_LOG("Unknown key: %s\n", str);
            break;
      }
   }

   rmsgpack_dom_value_free(&item);

   return 0;
}