/** * Iterate over the given JSON array, passing elements of it to the given iteration function. * If the iteration function ever returns STOP, return the array element passed to it which caused it to first return STOP. * If the iteration function returns CONTINUE for each and every array element, return NULL. * The iteration function is not guaranteed to be called for each and every element in the given array. */ static struct json_object * json_array_find(keystone_context_t *context, struct json_object *array, item_callback_func_t callback, void *callback_arg) { struct json_object *item; unsigned int i; assert(context != NULL); assert(array != NULL); assert(callback != NULL); i = json_array_length(context, array); while (i--) { item_callback_return_t ret; item = json_array_get(context, array, i); ret = callback(context, item, callback_arg); switch (ret) { case CONTINUE: break; case STOP: return item; default: assert(0); break; } } return NULL; }
END_TEST START_TEST (test_valid_3) { char *s = "[{\"key1\":2 , \"key2\":\"val\"}, 45, null]"; struct json_object *j_ar = json_parser_parse(s); fail_unless(json_type(j_ar) == json_type_array, "bad type"); fail_unless(json_array_length(j_ar) == 3, "bad length"); struct json_object *j_obj = json_array_get(j_ar, 0); struct json_object *j_int1 = json_array_get(j_ar, 1); struct json_object *j_null = json_array_get(j_ar, 2); fail_unless(json_type(j_obj) == json_type_object, "bad type"); fail_unless(json_type(j_int1) == json_type_int, "bad type"); fail_unless(json_type(j_null) == json_type_null, "bad type"); struct json_object *j_int2 = json_object_get(j_obj, "key1"); struct json_object *j_str = json_object_get(j_obj, "key2"); fail_unless(json_int_get(j_int1) == 45, "bad value"); fail_unless(json_int_get(j_int2) == 2, "bad value"); fail_unless(strcmp(json_string_get(j_str), "val") == 0, "bad value"); json_ref_put(j_ar); }
/* Returns: -1: group object is corrupted 0: didn't find datastream 1: found datastream */ int osd_group_has_photostream(json_object_t g, int id) { json_object_t a = json_object_get(g, "photostreams"); if (!json_isarray(a)) return -1; int len = json_array_length(a); for (int i = 0; i < len; i++) { json_object_t d = json_array_get(a, i); if (!json_isobject(d)) return -1; int x = osd_object_get_id(d); if (x == -1) return -1; if (x == id) return 1; } return 0; }
END_TEST START_TEST (test_valid_2) { char *s = "[2 , 3]"; struct json_object *obj = json_parser_parse(s); fail_unless(json_type(obj) == json_type_array, "bad type"); fail_unless(json_array_length(obj) == 2, "bad length"); struct json_object *j_int0 = json_array_get(obj, 0); struct json_object *j_int1 = json_array_get(obj, 1); fail_unless(json_type(j_int0) == json_type_int, "bad type"); fail_unless(json_type(j_int1) == json_type_int, "bad type"); fail_unless(json_int_get(j_int0) == 2, "bad value"); fail_unless(json_int_get(j_int1) == 3, "bad value"); json_ref_put(obj); }
/** * Return the index'th element of the given JSON array. */ static struct json_object * json_array_get(keystone_context_t *context, struct json_object *array, unsigned int index) { struct json_object *item; assert(context != NULL); assert(array != NULL); if (json_object_is_type(array, json_type_array)) { if (index < json_array_length(context, array)) { item = json_object_array_get_idx(array, index); if (NULL == item) { context->keystone_error("failed to index into JSON array", KSERR_PARSE); } } else { context->keystone_error("JSON array index out of bound", KSERR_PARSE); item = NULL; } } else { context->keystone_error("JSON object is not an array", KSERR_PARSE); item = NULL; } return item; }
END_TEST START_TEST (test_valid_4_utf) { char *s = "[\"Элементы\", 5, \"массива\"]"; struct json_object *j_ar = json_parser_parse(s); fail_unless(json_type(j_ar) == json_type_array, "bad type"); fail_unless(json_array_length(j_ar) == 3, "bad length"); struct json_object *j_str_1 = json_array_get(j_ar, 0); struct json_object *j_int = json_array_get(j_ar, 1); struct json_object *j_str_2 = json_array_get(j_ar, 2); fail_unless(json_type(j_str_1) == json_type_string, "bad type"); fail_unless(json_type(j_str_2) == json_type_string, "bad type"); fail_unless(json_type(j_int) == json_type_int, "bad type"); fail_unless(json_int_get(j_int) == 5, "bad value_int"); fail_unless(strcmp(json_string_get(j_str_1), "Элементы") == 0, "bad value_str_1"); fail_unless(strcmp(json_string_get(j_str_2), "массива") == 0, "bad value_str_2"); json_ref_put(j_ar); }
void CServerBrowser::LoadDDNet() { // reset servers / countries m_NumDDNetCountries = 0; m_NumDDNetTypes = 0; // load ddnet server list IStorageTW *pStorage = Kernel()->RequestInterface<IStorageTW>(); IOHANDLE File = pStorage->OpenFile("tmp/cache/ddnet-servers.json", IOFLAG_READ, IStorageTW::TYPE_ALL); if(File) { char aBuf[4096*4]; mem_zero(aBuf, sizeof(aBuf)); io_read(File, aBuf, sizeof(aBuf)); io_close(File); // parse JSON json_value *pCountries = json_parse(aBuf); if (pCountries && pCountries->type == json_array) { for (int i = 0; i < json_array_length(pCountries) && m_NumDDNetCountries < MAX_DDNET_COUNTRIES; i++) { // pSrv - { name, flagId, servers } const json_value *pSrv = json_array_get(pCountries, i); const json_value *pTypes = json_object_get(pSrv, "servers"); const json_value *pName = json_object_get(pSrv, "name"); const json_value *pFlagID = json_object_get(pSrv, "flagId"); if (pSrv->type != json_object || pTypes->type != json_object || pName->type != json_string || pFlagID->type != json_integer) { dbg_msg("client_srvbrowse", "invalid attributes"); continue; } // build structure CDDNetCountry *pCntr = &m_aDDNetCountries[m_NumDDNetCountries]; pCntr->Reset(); str_copy(pCntr->m_aName, json_string_get(pName), sizeof(pCntr->m_aName)); pCntr->m_FlagID = json_int_get(pFlagID); // add country for (unsigned int t = 0; t < pTypes->u.object.length; t++) { const char *pType = pTypes->u.object.values[t].name; const json_value *pAddrs = pTypes->u.object.values[t].value; // add type if(json_array_length(pAddrs) > 0 && m_NumDDNetTypes < MAX_DDNET_TYPES) { int pos; for(pos = 0; pos < m_NumDDNetTypes; pos++) { if(!str_comp(m_aDDNetTypes[pos], pType)) break; } if(pos == m_NumDDNetTypes) { str_copy(m_aDDNetTypes[m_NumDDNetTypes], pType, sizeof(m_aDDNetTypes[m_NumDDNetTypes])); m_NumDDNetTypes++; } } // add addresses for (int g = 0; g < json_array_length(pAddrs); g++, pCntr->m_NumServers++) { const json_value *pAddr = json_array_get(pAddrs, g); const char* pStr = json_string_get(pAddr); net_addr_from_str(&pCntr->m_aServers[pCntr->m_NumServers], pStr); str_copy(pCntr->m_aTypes[pCntr->m_NumServers], pType, sizeof(pCntr->m_aTypes[pCntr->m_NumServers])); } } m_NumDDNetCountries++; } } if (pCountries) json_value_free(pCountries); } }