/* * It parse a JSON string and convert it to MessagePack format, this packer is * useful when a complete JSON message exists, otherwise it will fail until * the message is complete. * * This routine do not keep a state in the parser, do not use it for big * JSON messages. */ int flb_pack_json(char *js, size_t len, char **buffer, int *size) { int ret; int out; char *buf; struct flb_pack_state state; ret = flb_pack_state_init(&state); if (ret != 0) { return -1; } ret = json_tokenise(js, len, &state); if (ret != 0) { return ret; } buf = tokens_to_msgpack(js, state.tokens, state.tokens_count, &out); if (!buf) { return -1; } *size = out; *buffer = buf; return 0; }
/* * It parse a JSON string and convert it to MessagePack format. The main * difference of this function and the previous flb_pack_json() is that it * keeps a parser and tokens state, allowing to process big messages and * resume the parsing process instead of start from zero. */ int flb_pack_json_state(char *js, size_t len, char **buffer, int *size, struct flb_pack_state *state) { int ret; int out; char *buf; ret = json_tokenise(js, len, state); if (ret != 0) { return ret; } buf = tokens_to_msgpack(js, state->tokens, state->tokens_count, &out); free(state->tokens); if (!buf) { return -1; } *size = out; *buffer = buf; return 0; }
int main() { int rc; char token[86] = "a"; char query[512]; struct songitem songarray[300]; // 10 = count in query below rc = getToken(token); check(rc == OK, "Could not get token"); /* printf("Token: %s\n", token); */ rc = snprintf(query, sizeof(query), "https://api.vk.com/method/audio.get?count=300&access_token=%s", token); check( ((rc > 0) && (rc < (int)sizeof(query))), "Could not create query"); char *js = jsonFetch(query); jsmntok_t *tokens = json_tokenise(js); typedef enum { START, KEY, STOP, RESPONSE, ARRAY, SONG, TITLE, URL} parse_state; // state is the current state of parser parse_state state = START; // stack is the state we return to when reaching end of an object parse_state stack = STOP; // counters to keep track of how far through parsing we are size_t object_tokens = 0; size_t songs = 0; size_t song_tokens = 0; size_t song_id = 0; for (size_t i = 0, j = 1; j > 0; i++, j--) { jsmntok_t *t = &tokens[i]; // should never reach uninitialized tokens check((t->start != -1 && t->end != -1), "Have reached uninitialized tokens"); if (t->type == JSMN_ARRAY || t->type == JSMN_OBJECT) j += t->size; switch (state) { case START: if (t->type != JSMN_OBJECT) sentinel("Invalid response: root element must be an object."); state = KEY; object_tokens = t->size; if (object_tokens == 0) state = STOP; if (object_tokens % 2 != 0) sentinel("Invalid response: object must have even number of children."); break; case KEY: object_tokens--; if (t->type != JSMN_STRING) sentinel("Invalid response: object keys must be strings."); if (json_token_streq(js, t, "response")) state = RESPONSE; if (object_tokens == 0) state = STOP; break; case RESPONSE: /* printf("songs t->type: %d\n", t->type); */ if (t->type != JSMN_ARRAY) sentinel("Unknown RESPONSE value, expected array of songs."); songs = t->size; state = ARRAY; stack = ARRAY; if (songs == 0) state = STOP; break; case ARRAY: songs--; /* printf("Q_SONGS = %ld\n", songs); */ song_tokens = t->size; state = SONG; /* if (song_tokens != 0) */ /* printf("%ld - song tokens\n", song_tokens); */ if (song_tokens == 0) state = STOP; if (songs == 0) stack = STOP; break; case SONG: case TITLE: case URL: song_tokens--; // Keys are odd numbered tokens within the object if (song_tokens % 2 == 1) { if (t->type == JSMN_STRING && json_token_streq(js, t, "title")) { state = TITLE; } else if (t->type == JSMN_STRING && json_token_streq(js, t, "url")) { state = URL; } } // Values in the TITLE state else if (state == TITLE) { if (t->type != JSMN_STRING) sentinel("Invalid title name."); char *str = json_token_tostr(js, t); /* printf("%s\n", str); */ songarray[song_id].id = song_id+1; snprintf(songarray[song_id].title, sizeof(songarray[song_id].title), "%s", str); state = SONG; } else if (state == URL) { if (t->type != JSMN_STRING) sentinel("Invalid url name."); // token to string char *p_url = json_token_tostr(js, t); // concatanate rubish after 'mp3' char *pch = strstr(p_url, ".mp3"); if (!pch) { sentinel("The links format does not seem to be correct, please try again"); } pch += 4; *pch = '\0'; // stupid procedure to remove '\' while ( (pch = strstr(p_url, "\\")) ) { int idx = (pch-p_url); memmove(&p_url[idx], &p_url[idx+1], strlen(p_url) - (idx)); } /* printf("%s\n", p_url); */ snprintf(songarray[song_id].url, sizeof(songarray[song_id].url), "%s", p_url); /* play_url(p_url); */ song_id++; state = SONG; } if (song_tokens == 0) state = stack; break; case STOP: printf("STOP\n"); break; default: sentinel("Invalid state %u", state); } } // end of for loop int i; pthread_t thread1; int ret1; for (i = 0; i < (int)sizeof(songarray)/(int)sizeof(songitem); i++) { printf("%d - %s\n", songarray[i].id, songarray[i].title); ret1 = pthread_create(&thread1, NULL, play_url2, (void *) songarray[i].url); pthread_join(thread1, NULL); sleep(1); /* play_url(songarray[i].url); */ } cleanup(); return 0; error: return 1; }
/** *[{"uid":"3863fccf9a1a48af99c8bfcbf01c6b7f","timestamp":1401902872564,"command":{"id":"machine.TurnOn","params":{"Light":false}}}] * * * @return resultcode if negative value or number of tokens */ mqtt_data_t json_deserialize(char* payload) { mqtt_data_t data_t; jsmntok_t * tokens = json_tokenise(payload); char* temp_uid = json_token_tostr(payload, &tokens[2]); char* uid = BS_MEM_ALLOC(strlen(temp_uid) + 1); memcpy(uid, temp_uid, strlen(temp_uid) + 1); char* temp_data = json_token_tostr(payload, &tokens[6]); char* data = BS_MEM_ALLOC(strlen(temp_data) + 1); memcpy(data, temp_data, strlen(temp_data) + 1); if(strcmp(data, "command") == 0) { //data_t = json_deserialize_command(tokens, payload, data_t); char* temp_name = json_token_tostr(payload, &tokens[9]); char* name = BS_MEM_ALLOC(strlen(temp_name) + 1); memcpy(name, temp_name, strlen(temp_name) + 1); //data_t->ticketId = uid; int max = (&tokens[11])->size; printf("Command: %s (%d params)\r\n", name, max / 2); int index = 0; char** keys = BS_MEM_ALLOC(max / 2); int key_index = 0; for(index = 0; index < max; index+=2, key_index++) { char* temp_pname = json_token_tostr(payload, &tokens[12 + index]); keys[key_index] = BS_MEM_ALLOC(strlen(temp_pname) + 1); memcpy(keys[key_index], temp_pname, strlen(temp_pname) + 1); char* temp = json_token_tostr(payload, &tokens[12 + index + 1]); char* param_value = BS_MEM_ALLOC(strlen(temp) + 1); memcpy(param_value, temp, strlen(temp) + 1); printf("%s: %s\r\n", keys[key_index], param_value); //x.fieldname = param_name; bsd_data_t x; if(strcmp(param_value, "true") == 0) { printf("param bool @ true\r\n"); x.kind = BSD_BOOL; x.content.boolean = true; } else if(strcmp(param_value, "false") == 0) { printf("param bool @ false\r\n"); x.kind = BSD_BOOL; x.content.boolean = false; } else { // Not supported // x.content.string.length = strlen(param_value); // x.content.string.data = param_value; } data_t.values[key_index] = BS_MEM_ALLOC(sizeof(x)); memcpy(data_t.values[key_index], &x, sizeof(x)); } data_t.path = name; data_t.nbofvalues = max / 2; data_t.keys = keys; } free(tokens); free(uid); free(data); return data_t; }
int main(void) { //char *js = json_fetch(URL); /*char js[] = "{" "\"following_url\": \"https://api.github.com/users/alisdair/following{/other_user}\"," "\"name\": \"Alisdair McDiarmid\"," "\"location\": \"Glasgow\"," "\"hireable\": true," "\"public_repos\": 49," "\"created_at\": \"2009-03-31T12:36:07Z\"," "\"updated_at\": \"2015-04-15T09:39:22Z\"" "}";*/ char *js = json_fetch_file("test_json.txt"); char token[64]; char name[64]; char location[64]; char hireable[64]; char following_url[64]; int public_repos; double public_gists; char *str; jsmntok_t *tokens = json_tokenise(js); typedef enum { START, KEY, PRINT, SKIP, STOP } parse_state; parse_state state = START; size_t object_tokens = 0; for (size_t i = 0, j = 1; j > 0; i++, j--) { jsmntok_t *t = &tokens[i]; if (t->type == JSMN_ARRAY || t->type == JSMN_OBJECT) j += t->size; switch (state) { case START: state = KEY; object_tokens = t->size; if (object_tokens == 0) state = STOP; break; case KEY: object_tokens--; state = SKIP; for (size_t i = 0; i < sizeof(KEYS)/sizeof(char *); i++) { if (json_token_streq(js, t, KEYS[i])) { printf("%s: ", KEYS[i]); strcpy(token, KEYS[i]); state = PRINT; break; } } break; case SKIP: object_tokens--; state = KEY; if (object_tokens == 0) state = STOP; break; case PRINT: str = json_token_tostr(js, t); puts(str); if(strcmp("name", token) == 0) // token = string { strcpy(name, str); } if(strcmp("location", token) == 0) // token = string { strcpy(location, str); } if(strcmp("public_repos", token) == 0) // token = int { public_repos = atoi(str); } if(strcmp("hireable", token) == 0) // token = string { strcpy(hireable, str); } if(strcmp("following_url", token) == 0) // token = string { strcpy(following_url, str); } if(strcmp("public_gists", token) == 0) // token = double { public_gists = atof(str); } object_tokens--; state = KEY; if (object_tokens == 0) state = STOP; break; case STOP: break; default: break; } } return 0; }
int parse_json_request(Reader& reader, const char* const keys[], const jsmntype_t types[], unsigned count) { char* js = reader.fetch_as_string(); if (!js) return -1; jsmntok_t *tokens = json_tokenise(js); enum parse_state { START, KEY, VALUE, SKIP, STOP }; parse_state state = START; jsmntype_t expected_type = JSMN_OBJECT; int result = 0; int key = -1; for (size_t i = 0, j = 1; j > 0; i++, j--) { jsmntok_t *t = &tokens[i]; if (t->type == JSMN_ARRAY || t->type == JSMN_OBJECT) j += t->size * 2; switch (state) { case START: state = KEY; break; case KEY: state = VALUE; key = -1; for (size_t i = 0; i < count; i++) { if (json_token_streq(js, t, keys[i])) { expected_type = types[i]; if (parsed_key(i)) { key = i; JSON_DEBUG( ( "key: %s %d %d\n", keys[i], i, (int)expected_type ) ); } } } if (key==-1) { JSON_DEBUG( ( "unknown key: %s\n", json_token_tostr(js, t) ) ); result = -1; } break; case VALUE: if (key!=-1) { if (t->type != expected_type) { result = -1; JSON_DEBUG( ( "type mismatch\n" ) ); } else { char *str = json_token_tostr(js, t); if (!parsed_value(key, t, str)) result = -1; } } state = KEY; break; case STOP: // Just consume the tokens break; default: result = -1; } } free(js); return result; }
int read_leap_dump(void) { // printf("%s\n", "Reaadding???"); lock(); int count = 1; char* js = 0; long length; FILE * f = fopen ("../src/leap_data.json", "rb"); if (f) { // printf("%s\n", "File Found"); fseek (f, 0, SEEK_END); length = ftell (f); fseek (f, 0, SEEK_SET); js = malloc (length); if (js) { // printf("%s\n", "File non trivial"); fread (js, 1, length, f); *(js + length) = '\0'; } fclose (f); } jsmntok_t *tokens = json_tokenise(js); /* The GitHub user API response is a single object. States required to * parse this are simple: start of the object, keys, values we want to * print, values we want to skip, and then a marker state for the end. */ typedef enum { START, KEY, PRINT, SKIP, STOP } parse_state; parse_state state = START; size_t object_tokens = 0; size_t i; size_t j; for (i = 0, j = 1; j > 0; i++, j--) { jsmntok_t *t = &tokens[i]; // Should never reach uninitialized tokens log_assert(t->start != -1 && t->end != -1); if (t->type == JSMN_ARRAY || t->type == JSMN_OBJECT) j += t->size; switch (state) { case START: if (t->type != JSMN_OBJECT) log_die("Invalid response: root element must be an object."); state = KEY; object_tokens = t->size; if (object_tokens == 0) state = STOP; if (object_tokens % 2 != 0) log_die("Invalid response: object must have even number of children."); break; case KEY: object_tokens--; if (t->type != JSMN_STRING) log_die("Invalid response: object keys must be strings."); state = SKIP; size_t i; for (i = 0; i < sizeof(KEYS)/sizeof(char *); i++) { if (json_token_streq(js, t, KEYS[i])) { printf("%s: ", KEYS[i]); state = PRINT; break; } } break; case SKIP: if (t->type != JSMN_STRING && t->type != JSMN_PRIMITIVE) log_die("Invalid response: object values must be strings or primitives."); object_tokens--; state = KEY; if (object_tokens == 0) state = STOP; break; case PRINT: if (t->type != JSMN_STRING && t->type != JSMN_PRIMITIVE) log_die("Invalid response: object values must be strings or primitives."); char *str = json_token_tostr(js, t); puts(str); char * pch; printf ("Splitting string \"%s\" into tokens:\n",str); pch = strtok (str,":"); while (pch != NULL) { printf ("%s\n",pch); if (count == 1) { py1 = atof(pch); } if (count == 2) { pz1 = atof(pch); } if (count == 3){ px1 = atof(pch); } pch = strtok (NULL, " "); } object_tokens--; state = KEY; count++; if (object_tokens == 0) state = STOP; break; case STOP: // Just consume the tokens break; default: log_die("Invalid state %u", state); } } unlock(); return 0; }
/* It parse a JSON string and convert it to MessagePack format */ char *flb_pack_json(char *js, size_t len, int *size) { int i; int flen; int arr_size; char *p; char *buf; jsmntok_t *t; jsmntok_t *tokens; msgpack_packer pck; msgpack_sbuffer sbuf; if (!js) { return NULL; } tokens = json_tokenise(js, len, &arr_size); if (!tokens) { return NULL; } flb_debug("JSON to pack: '%s'", js); /* initialize buffers */ msgpack_sbuffer_init(&sbuf); msgpack_packer_init(&pck, &sbuf, msgpack_sbuffer_write); for (i = 0; i < arr_size ; i++) { t = &tokens[i]; if (t->start == -1 || t->end == -1 || (t->start == 0 && t->end == 0)) { break; } flen = (t->end - t->start); switch (t->type) { case JSMN_OBJECT: flb_debug("json_pack: token=%i is OBJECT (size=%i)", i, t->size); msgpack_pack_map(&pck, t->size); break; case JSMN_ARRAY: flb_debug("json_pack: token=%i is ARRAY (size=%i)", i, t->size); msgpack_pack_array(&pck, t->size); break; case JSMN_STRING: flb_debug("json_pack: token=%i is STRING (len=%i)\n", i, flen); msgpack_pack_bin(&pck, flen); msgpack_pack_bin_body(&pck, js + t->start, flen); break; case JSMN_PRIMITIVE: p = js + t->start; if (strncmp(p, "false", 5) == 0) { flb_debug("json_pack: token=%i is FALSE", i); msgpack_pack_false(&pck); } else if (strncmp(p, "true", 4) == 0) { flb_debug("json_pack: token=%i is TRUE", i); msgpack_pack_true(&pck); } else if (strncmp(p, "null", 4) == 0) { flb_debug("json_pack: token=%i is NULL", i); msgpack_pack_nil(&pck); } else { flb_debug("json_pack: token=%i is INT64", i); msgpack_pack_int64(&pck, atol(p)); } break; } } /* dump data back to a new buffer */ *size = sbuf.size; buf = malloc(sbuf.size); memcpy(buf, sbuf.data, sbuf.size); msgpack_sbuffer_destroy(&sbuf); free(tokens); return buf; }