mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-23 16:09:47 +00:00
parse new lobby room listing with JSON
This commit is contained in:
parent
21fe0c8499
commit
0d81b2005f
@ -1195,7 +1195,8 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
network/netplay/netplay_io.o \
|
||||
network/netplay/netplay_sync.o \
|
||||
network/netplay/netplay_discovery.o \
|
||||
network/netplay/netplay_buf.o
|
||||
network/netplay/netplay_buf.o \
|
||||
network/netplay/netplay_room_parse.o
|
||||
|
||||
# Retro Achievements (also depends on threads)
|
||||
|
||||
|
@ -3418,7 +3418,6 @@ finish:
|
||||
int j = 0;
|
||||
int k = 0;
|
||||
int lan_room_count = 0;
|
||||
static struct string_list *room_data = NULL;
|
||||
struct netplay_host_list *lan_hosts = NULL;
|
||||
file_list_t *file_list = menu_entries_get_selection_buf_ptr(0);
|
||||
|
||||
@ -3428,7 +3427,7 @@ finish:
|
||||
if (lan_hosts)
|
||||
lan_room_count = lan_hosts->size;
|
||||
|
||||
room_data = string_split(buf, "\n");
|
||||
netplay_rooms_parse(buf);
|
||||
|
||||
if (netplay_room_list)
|
||||
free(netplay_room_list);
|
||||
@ -3437,20 +3436,11 @@ finish:
|
||||
* in the same list. If both entries are available, we want to show only
|
||||
* the LAN one. */
|
||||
|
||||
netplay_room_count = (int)(room_data->size / 8);
|
||||
netplay_room_count = netplay_rooms_get_count();
|
||||
netplay_room_list = (struct netplay_room*)
|
||||
calloc(netplay_room_count + lan_room_count,
|
||||
sizeof(struct netplay_room));
|
||||
|
||||
#if 0
|
||||
for (int i = 0; i < room_data->size; i++)
|
||||
{
|
||||
strlcpy(tmp,
|
||||
room_data->elems[i].data, sizeof(tmp));
|
||||
RARCH_LOG("tmp %s\n", tmp);
|
||||
|
||||
}
|
||||
#endif
|
||||
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, file_list);
|
||||
menu_entries_append_enum(file_list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_ENABLE_HOST),
|
||||
@ -3469,7 +3459,9 @@ finish:
|
||||
|
||||
for (i = 0; i < netplay_room_count; i++)
|
||||
{
|
||||
strlcpy(netplay_room_list[i].nickname,
|
||||
memcpy(&netplay_room_list[i], netplay_room_get(i), sizeof(netplay_room_list[i]));
|
||||
|
||||
/*strlcpy(netplay_room_list[i].nickname,
|
||||
room_data->elems[j + 0].data,
|
||||
sizeof(netplay_room_list[i].nickname));
|
||||
strlcpy(netplay_room_list[i].address,
|
||||
@ -3487,7 +3479,7 @@ finish:
|
||||
|
||||
netplay_room_list[i].port = atoi(room_data->elems[j + 2].data);
|
||||
netplay_room_list[i].gamecrc = atoi(room_data->elems[j + 6].data);
|
||||
netplay_room_list[i].timestamp = atoi(room_data->elems[j + 7].data);
|
||||
netplay_room_list[i].timestamp = atoi(room_data->elems[j + 7].data);*/
|
||||
|
||||
/* Uncomment this to debug mismatched room parameters*/
|
||||
#if 0
|
||||
@ -3521,6 +3513,8 @@ finish:
|
||||
MENU_ENUM_LABEL_CONNECT_NETPLAY_ROOM,
|
||||
MENU_ROOM, 0, 0);
|
||||
}
|
||||
|
||||
netplay_rooms_free();
|
||||
}
|
||||
|
||||
if (lan_room_count != 0)
|
||||
@ -3587,7 +3581,7 @@ finish:
|
||||
static int action_ok_push_netplay_refresh_rooms(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
char url [2048] = "http://lobby.libretro.com/raw/";
|
||||
char url [2048] = "http://newlobby.libretro.com/list/";
|
||||
task_push_netplay_lan_scan();
|
||||
task_push_http_transfer(url, true, NULL, netplay_refresh_rooms_cb, NULL);
|
||||
return 0;
|
||||
|
@ -79,4 +79,12 @@ void deinit_netplay(void);
|
||||
|
||||
bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data);
|
||||
|
||||
int netplay_rooms_parse(const char *buf);
|
||||
|
||||
struct netplay_room* netplay_room_get(int index);
|
||||
|
||||
int netplay_rooms_get_count();
|
||||
|
||||
void netplay_rooms_free();
|
||||
|
||||
#endif
|
||||
|
@ -60,6 +60,10 @@ struct netplay_room
|
||||
char gamename [PATH_MAX_LENGTH];
|
||||
int gamecrc;
|
||||
int timestamp;
|
||||
bool has_password;
|
||||
bool has_spectate_password;
|
||||
bool fixed;
|
||||
struct netplay_room *next;
|
||||
};
|
||||
|
||||
extern struct netplay_room *netplay_room_list;
|
||||
|
@ -521,7 +521,7 @@ static void netplay_announce_cb(void *task_data, void *user_data, const char *er
|
||||
static void netplay_announce(void)
|
||||
{
|
||||
char buf [2048];
|
||||
char url [2048] = "http://lobby.libretro.com/raw/?";
|
||||
char url [2048] = "http://newlobby.libretro.com/add/";
|
||||
rarch_system_info_t *system = NULL;
|
||||
settings_t *settings = config_get_ptr();
|
||||
uint32_t *content_crc_ptr = NULL;
|
||||
@ -532,14 +532,13 @@ static void netplay_announce(void)
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
snprintf(buf, sizeof(buf), "%susername=%s&corename=%s&coreversion=%s&"
|
||||
"gamename=%s&gamecrc=%d&port=%d",
|
||||
url, settings->username, system->info.library_name,
|
||||
system->info.library_version,
|
||||
!string_is_empty(path_basename(path_get(RARCH_PATH_BASENAME))) ? path_basename(path_get(RARCH_PATH_BASENAME)) : "N/A",*content_crc_ptr,
|
||||
settings->netplay.port);
|
||||
snprintf(buf, sizeof(buf), "username=%s&core_name=%s&core_version=%s&"
|
||||
"game_name=%s&game_crc=%d&port=%d&has_password=%d&has_spectate_password=%d",
|
||||
settings->username, system->info.library_name, system->info.library_version,
|
||||
!string_is_empty(path_basename(path_get(RARCH_PATH_BASENAME))) ? path_basename(path_get(RARCH_PATH_BASENAME)) : "N/A", *content_crc_ptr,
|
||||
settings->netplay.port, settings->netplay.password ? 1 : 0, settings->netplay.spectate_password ? 1 : 0);
|
||||
|
||||
task_push_http_transfer(buf, true, NULL, netplay_announce_cb, NULL);
|
||||
task_push_http_post_transfer(url, buf, true, NULL, netplay_announce_cb, NULL);
|
||||
}
|
||||
|
||||
int16_t input_state_net(unsigned port, unsigned device,
|
||||
|
466
network/netplay/netplay_room_parse.c
Normal file
466
network/netplay/netplay_room_parse.c
Normal file
@ -0,0 +1,466 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2017 - Daniel De Matteis
|
||||
* Copyright (C) 2016-2017 - Gregor Richards
|
||||
* Copyright (C) 2017 - Brad Parker
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <string/stdstring.h>
|
||||
#include <compat/strl.h>
|
||||
#include <formats/jsonsax_full.h>
|
||||
#include "netplay_discovery.h"
|
||||
#include "../../verbosity.h"
|
||||
|
||||
enum parse_state
|
||||
{
|
||||
STATE_START = 0,
|
||||
STATE_ARRAY_START,
|
||||
STATE_OBJECT_START,
|
||||
STATE_FIELDS_START,
|
||||
STATE_FIELDS_OBJECT_START,
|
||||
STATE_END
|
||||
};
|
||||
|
||||
struct netplay_rooms
|
||||
{
|
||||
struct netplay_room *head;
|
||||
struct netplay_room *cur;
|
||||
};
|
||||
|
||||
typedef struct tag_Context
|
||||
{
|
||||
JSON_Parser parser;
|
||||
int inEmptyContainer;
|
||||
enum parse_state state;
|
||||
char *cur_field;
|
||||
void *cur_member;
|
||||
size_t cur_member_size;
|
||||
} Context;
|
||||
|
||||
static struct netplay_rooms *rooms;
|
||||
|
||||
static void parse_context_init(Context* pCtx)
|
||||
{
|
||||
pCtx->parser = NULL;
|
||||
pCtx->inEmptyContainer = 0;
|
||||
}
|
||||
|
||||
static void parse_context_free(Context* pCtx)
|
||||
{
|
||||
if (pCtx->cur_field)
|
||||
free(pCtx->cur_field);
|
||||
|
||||
pCtx->cur_field = NULL;
|
||||
|
||||
JSON_Parser_Free(pCtx->parser);
|
||||
}
|
||||
|
||||
static JSON_Parser_HandlerResult JSON_CALL EncodingDetectedHandler(JSON_Parser parser)
|
||||
{
|
||||
(void)parser;
|
||||
return JSON_Parser_Continue;
|
||||
}
|
||||
|
||||
static JSON_Parser_HandlerResult JSON_CALL NullHandler(JSON_Parser parser)
|
||||
{
|
||||
Context* pCtx = (Context*)JSON_Parser_GetUserData(parser);
|
||||
(void)parser;
|
||||
pCtx->inEmptyContainer = 0;
|
||||
return JSON_Parser_Continue;
|
||||
}
|
||||
|
||||
static JSON_Parser_HandlerResult JSON_CALL BooleanHandler(JSON_Parser parser, JSON_Boolean value)
|
||||
{
|
||||
Context* pCtx = (Context*)JSON_Parser_GetUserData(parser);
|
||||
(void)parser;
|
||||
pCtx->inEmptyContainer = 0;
|
||||
|
||||
if (pCtx->state == STATE_FIELDS_OBJECT_START)
|
||||
{
|
||||
RARCH_LOG("found boolean: %d\n", value);
|
||||
|
||||
if (pCtx->cur_field)
|
||||
*((bool*)pCtx->cur_member) = value;
|
||||
}
|
||||
|
||||
return JSON_Parser_Continue;
|
||||
}
|
||||
|
||||
static JSON_Parser_HandlerResult JSON_CALL StringHandler(JSON_Parser parser, char* pValue, size_t length, JSON_StringAttributes attributes)
|
||||
{
|
||||
Context* pCtx = (Context*)JSON_Parser_GetUserData(parser);
|
||||
(void)parser;
|
||||
(void)attributes;
|
||||
pCtx->inEmptyContainer = 0;
|
||||
|
||||
if (pCtx->state == STATE_FIELDS_OBJECT_START)
|
||||
{
|
||||
RARCH_LOG("found string: %s\n", pValue);
|
||||
|
||||
if (pValue && length)
|
||||
{
|
||||
if (pCtx->cur_field && string_is_equal(pCtx->cur_field, "game_crc"))
|
||||
{
|
||||
/* CRC comes in as a string but it is stored as an int */
|
||||
*((int*)pCtx->cur_member) = strtoul(pValue, NULL, 16);
|
||||
}
|
||||
else if (pCtx->cur_field)
|
||||
strlcpy((char*)pCtx->cur_member, pValue, PATH_MAX_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
return JSON_Parser_Continue;
|
||||
}
|
||||
|
||||
static JSON_Parser_HandlerResult JSON_CALL NumberHandler(JSON_Parser parser, char* pValue, size_t length, JSON_NumberAttributes attributes)
|
||||
{
|
||||
Context* pCtx = (Context*)JSON_Parser_GetUserData(parser);
|
||||
(void)parser;
|
||||
(void)attributes;
|
||||
pCtx->inEmptyContainer = 0;
|
||||
|
||||
if (pCtx->state == STATE_FIELDS_OBJECT_START)
|
||||
{
|
||||
RARCH_LOG("found number string: %s\n", pValue);
|
||||
|
||||
if (pValue && length)
|
||||
if (pCtx->cur_field)
|
||||
*((int*)pCtx->cur_member) = strtol(pValue, NULL, 10);
|
||||
}
|
||||
|
||||
return JSON_Parser_Continue;
|
||||
}
|
||||
|
||||
static JSON_Parser_HandlerResult JSON_CALL SpecialNumberHandler(JSON_Parser parser, JSON_SpecialNumber value)
|
||||
{
|
||||
Context* pCtx = (Context*)JSON_Parser_GetUserData(parser);
|
||||
(void)parser;
|
||||
pCtx->inEmptyContainer = 0;
|
||||
return JSON_Parser_Continue;
|
||||
}
|
||||
|
||||
static JSON_Parser_HandlerResult JSON_CALL StartObjectHandler(JSON_Parser parser)
|
||||
{
|
||||
Context* pCtx = (Context*)JSON_Parser_GetUserData(parser);
|
||||
(void)parser;
|
||||
pCtx->inEmptyContainer = 1;
|
||||
RARCH_LOG("object start\n");
|
||||
|
||||
if (pCtx->state == STATE_FIELDS_START)
|
||||
{
|
||||
pCtx->state = STATE_FIELDS_OBJECT_START;
|
||||
|
||||
if (!rooms->head)
|
||||
{
|
||||
rooms->head = (struct netplay_room*)calloc(1, sizeof(*rooms->head));
|
||||
rooms->cur = rooms->head;
|
||||
}
|
||||
else if (!rooms->cur->next)
|
||||
{
|
||||
rooms->cur->next = (struct netplay_room*)calloc(1, sizeof(*rooms->cur->next));
|
||||
rooms->cur = rooms->cur->next;
|
||||
}
|
||||
}
|
||||
else if (pCtx->state == STATE_ARRAY_START)
|
||||
pCtx->state = STATE_OBJECT_START;
|
||||
|
||||
return JSON_Parser_Continue;
|
||||
}
|
||||
|
||||
static JSON_Parser_HandlerResult JSON_CALL EndObjectHandler(JSON_Parser parser)
|
||||
{
|
||||
Context* pCtx = (Context*)JSON_Parser_GetUserData(parser);
|
||||
if (!pCtx->inEmptyContainer)
|
||||
{
|
||||
/* indent */
|
||||
}
|
||||
pCtx->inEmptyContainer = 0;
|
||||
RARCH_LOG("object end\n");
|
||||
|
||||
if (pCtx->state == STATE_FIELDS_OBJECT_START)
|
||||
pCtx->state = STATE_ARRAY_START;
|
||||
|
||||
return JSON_Parser_Continue;
|
||||
}
|
||||
|
||||
static JSON_Parser_HandlerResult JSON_CALL ObjectMemberHandler(JSON_Parser parser, char* pValue, size_t length, JSON_StringAttributes attributes)
|
||||
{
|
||||
Context* pCtx = (Context*)JSON_Parser_GetUserData(parser);
|
||||
(void)parser;
|
||||
(void)attributes;
|
||||
if (!pCtx->inEmptyContainer)
|
||||
RARCH_LOG("object member comma\n");
|
||||
RARCH_LOG("object member %I64u: %s\n", length, pValue);
|
||||
|
||||
if (!pValue || !length)
|
||||
return JSON_Parser_Continue;
|
||||
|
||||
if (pCtx->state == STATE_OBJECT_START && string_is_equal(pValue, "fields"))
|
||||
pCtx->state = STATE_FIELDS_START;
|
||||
|
||||
if (pCtx->state == STATE_FIELDS_OBJECT_START)
|
||||
{
|
||||
RARCH_LOG("got field %s\n", pValue);
|
||||
|
||||
if (pCtx->cur_field)
|
||||
free(pCtx->cur_field);
|
||||
|
||||
pCtx->cur_field = strdup(pValue);
|
||||
|
||||
if (string_is_equal(pValue, "username"))
|
||||
{
|
||||
pCtx->cur_member = &rooms->cur->nickname;
|
||||
pCtx->cur_member_size = sizeof(rooms->cur->nickname);
|
||||
}
|
||||
else if (string_is_equal(pValue, "game_name"))
|
||||
{
|
||||
pCtx->cur_member = &rooms->cur->gamename;
|
||||
pCtx->cur_member_size = sizeof(rooms->cur->gamename);
|
||||
}
|
||||
else if (string_is_equal(pValue, "core_name"))
|
||||
{
|
||||
pCtx->cur_member = &rooms->cur->corename;
|
||||
pCtx->cur_member_size = sizeof(rooms->cur->corename);
|
||||
}
|
||||
else if (string_is_equal(pValue, "ip"))
|
||||
{
|
||||
pCtx->cur_member = &rooms->cur->address;
|
||||
pCtx->cur_member_size = sizeof(rooms->cur->address);
|
||||
}
|
||||
else if (string_is_equal(pValue, "port"))
|
||||
pCtx->cur_member = &rooms->cur->port;
|
||||
else if (string_is_equal(pValue, "game_crc"))
|
||||
pCtx->cur_member = &rooms->cur->gamecrc;
|
||||
else if (string_is_equal(pValue, "core_version"))
|
||||
{
|
||||
pCtx->cur_member = &rooms->cur->coreversion;
|
||||
pCtx->cur_member_size = sizeof(rooms->cur->coreversion);
|
||||
}
|
||||
else if (string_is_equal(pValue, "has_password"))
|
||||
pCtx->cur_member = &rooms->cur->has_password;
|
||||
else if (string_is_equal(pValue, "has_spectate_password"))
|
||||
pCtx->cur_member = &rooms->cur->has_spectate_password;
|
||||
else if (string_is_equal(pValue, "fixed"))
|
||||
pCtx->cur_member = &rooms->cur->fixed;
|
||||
else
|
||||
{
|
||||
/* unknown field, ignore it */
|
||||
free(pCtx->cur_field);
|
||||
pCtx->cur_field = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
pCtx->inEmptyContainer = 0;
|
||||
/* indent, string, space, colon, space */
|
||||
return JSON_Parser_Continue;
|
||||
}
|
||||
|
||||
static JSON_Parser_HandlerResult JSON_CALL StartArrayHandler(JSON_Parser parser)
|
||||
{
|
||||
Context* pCtx = (Context*)JSON_Parser_GetUserData(parser);
|
||||
(void)parser;
|
||||
pCtx->inEmptyContainer = 1;
|
||||
RARCH_LOG("array start\n");
|
||||
|
||||
if (pCtx->state == STATE_START)
|
||||
pCtx->state = STATE_ARRAY_START;
|
||||
|
||||
return JSON_Parser_Continue;
|
||||
}
|
||||
|
||||
static JSON_Parser_HandlerResult JSON_CALL EndArrayHandler(JSON_Parser parser)
|
||||
{
|
||||
Context* pCtx = (Context*)JSON_Parser_GetUserData(parser);
|
||||
(void)parser;
|
||||
if (!pCtx->inEmptyContainer)
|
||||
{
|
||||
/* indent */
|
||||
}
|
||||
pCtx->inEmptyContainer = 0;
|
||||
RARCH_LOG("array end\n");
|
||||
return JSON_Parser_Continue;
|
||||
}
|
||||
|
||||
static JSON_Parser_HandlerResult JSON_CALL ArrayItemHandler(JSON_Parser parser)
|
||||
{
|
||||
Context* pCtx = (Context*)JSON_Parser_GetUserData(parser);
|
||||
(void)parser;
|
||||
if (!pCtx->inEmptyContainer)
|
||||
{
|
||||
RARCH_LOG("array comma\n");
|
||||
}
|
||||
pCtx->inEmptyContainer = 0;
|
||||
/* indent */
|
||||
return JSON_Parser_Continue;
|
||||
}
|
||||
|
||||
static int parse_context_setup(Context* pCtx)
|
||||
{
|
||||
/*JSON_Parser_SetTrackObjectMembers(pCtx->parser, JSON_True);
|
||||
JSON_Parser_SetAllowBOM(pCtx->parser, JSON_True);
|
||||
JSON_Parser_SetAllowComments(pCtx->parser, JSON_True);
|
||||
JSON_Parser_SetAllowSpecialNumbers(pCtx->parser, JSON_True);
|
||||
JSON_Parser_SetAllowHexNumbers(pCtx->parser, JSON_True);
|
||||
JSON_Parser_SetAllowUnescapedControlCharacters(pCtx->parser, JSON_True);
|
||||
JSON_Parser_SetReplaceInvalidEncodingSequences(pCtx->parser, JSON_True);
|
||||
JSON_Parser_SetTrackObjectMembers(pCtx->parser, JSON_False);*/
|
||||
|
||||
if (JSON_Parser_GetInputEncoding(pCtx->parser) == JSON_UnknownEncoding)
|
||||
{
|
||||
JSON_Parser_SetEncodingDetectedHandler(pCtx->parser, &EncodingDetectedHandler);
|
||||
}
|
||||
|
||||
JSON_Parser_SetNullHandler(pCtx->parser, &NullHandler);
|
||||
JSON_Parser_SetBooleanHandler(pCtx->parser, &BooleanHandler);
|
||||
JSON_Parser_SetStringHandler(pCtx->parser, &StringHandler);
|
||||
JSON_Parser_SetNumberHandler(pCtx->parser, &NumberHandler);
|
||||
JSON_Parser_SetSpecialNumberHandler(pCtx->parser, &SpecialNumberHandler);
|
||||
JSON_Parser_SetStartObjectHandler(pCtx->parser, &StartObjectHandler);
|
||||
JSON_Parser_SetEndObjectHandler(pCtx->parser, &EndObjectHandler);
|
||||
JSON_Parser_SetObjectMemberHandler(pCtx->parser, &ObjectMemberHandler);
|
||||
JSON_Parser_SetStartArrayHandler(pCtx->parser, &StartArrayHandler);
|
||||
JSON_Parser_SetEndArrayHandler(pCtx->parser, &EndArrayHandler);
|
||||
JSON_Parser_SetArrayItemHandler(pCtx->parser, &ArrayItemHandler);
|
||||
JSON_Parser_SetUserData(pCtx->parser, pCtx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void parse_context_error(Context* pCtx)
|
||||
{
|
||||
if (JSON_Parser_GetError(pCtx->parser) != JSON_Error_AbortedByHandler)
|
||||
{
|
||||
JSON_Error error = JSON_Parser_GetError(pCtx->parser);
|
||||
JSON_Location errorLocation = {0, 0, 0};
|
||||
(void)JSON_Parser_GetErrorLocation(pCtx->parser, &errorLocation);
|
||||
RARCH_ERR("invalid JSON at line %d, column %d (input byte %d) - %s.\n",
|
||||
(int)errorLocation.line + 1,
|
||||
(int)errorLocation.column + 1,
|
||||
(int)errorLocation.byte,
|
||||
JSON_ErrorString(error));
|
||||
}
|
||||
}
|
||||
|
||||
static int json_parse(Context* pCtx, const char *buf)
|
||||
{
|
||||
if (!JSON_Parser_Parse(pCtx->parser, buf, strlen(buf), JSON_True))
|
||||
{
|
||||
parse_context_error(pCtx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void netplay_rooms_free()
|
||||
{
|
||||
if (rooms)
|
||||
{
|
||||
struct netplay_room *room = rooms->head;
|
||||
|
||||
if (room)
|
||||
{
|
||||
while (room != NULL)
|
||||
{
|
||||
struct netplay_room *next = room->next;
|
||||
|
||||
free(room);
|
||||
|
||||
room = next;
|
||||
}
|
||||
|
||||
free(rooms);
|
||||
}
|
||||
else
|
||||
free(rooms);
|
||||
|
||||
rooms = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int netplay_rooms_parse(const char *buf)
|
||||
{
|
||||
Context ctx;
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
|
||||
ctx.state = STATE_START;
|
||||
|
||||
/* delete any previous rooms */
|
||||
netplay_rooms_free();
|
||||
|
||||
rooms = (struct netplay_rooms*)calloc(1, sizeof(*rooms));
|
||||
|
||||
parse_context_init(&ctx);
|
||||
|
||||
ctx.parser = JSON_Parser_Create(NULL);
|
||||
|
||||
if (!ctx.parser)
|
||||
{
|
||||
RARCH_ERR("could not allocate memory for JSON parser.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
parse_context_setup(&ctx);
|
||||
json_parse(&ctx, buf);
|
||||
parse_context_free(&ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct netplay_room* netplay_room_get(int index)
|
||||
{
|
||||
int cur = 0;
|
||||
struct netplay_room *room = rooms->head;
|
||||
|
||||
if (index < 0)
|
||||
return NULL;
|
||||
|
||||
while (room != NULL)
|
||||
{
|
||||
if (cur == index)
|
||||
break;
|
||||
|
||||
room = room->next;
|
||||
cur++;
|
||||
}
|
||||
|
||||
return room;
|
||||
}
|
||||
|
||||
int netplay_rooms_get_count()
|
||||
{
|
||||
int count = 0;
|
||||
struct netplay_room *room;
|
||||
|
||||
if (!rooms)
|
||||
return count;
|
||||
|
||||
room = rooms->head;
|
||||
|
||||
if (!room)
|
||||
return count;
|
||||
|
||||
while(room != NULL)
|
||||
{
|
||||
count++;
|
||||
|
||||
room = room->next;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
Loading…
Reference in New Issue
Block a user