/* * Apple // emulator for *ix * * This software package is subject to the GNU General Public License * version 3 or later (your choice) as published by the Free Software * Foundation. * * Copyright 2013-2015 Aaron Culliney * */ #include "json_parse.h" #define JSON_LENGTH 16 #define DEFAULT_NUMTOK 16 int json_createFromFile(const char *filePath, INOUT JSON_s *parsedData) { int fd = -1; jsmnerr_t errCount = JSMN_ERROR_NOMEM; ssize_t jsonIdx = 0; ssize_t jsonLen = 0; char *jsonString = NULL; jsmntok_t *jsonTokens = NULL; do { if (!parsedData) { break; } parsedData->jsonString = NULL; parsedData->jsonTokens = NULL; TEMP_FAILURE_RETRY(fd = open(filePath, O_RDONLY)); if (fd < 0) { ERRLOG("Error opening file : %s", strerror(errno)); break; } jsonLen = JSON_LENGTH*2; jsonString = malloc(jsonLen); if (jsonString == NULL) { ERRLOG("WHOA : %s", strerror(errno)); break; } ssize_t bytesRead = 0; do { TEMP_FAILURE_RETRY(bytesRead = read(fd, jsonString+jsonIdx, JSON_LENGTH)); if (bytesRead < 0) { ERRLOG("Error reading file : %s", strerror(errno)); break; } if (bytesRead) { jsonIdx += bytesRead; if (jsonLen - jsonIdx < JSON_LENGTH) { //LOG("reallocating json string ..."); jsonLen <<= 1; char *newString = realloc(jsonString, jsonLen); if (!newString) { ERRLOG("WHOA2 : %s", strerror(errno)); bytesRead = -1; break; } jsonString = newString; } } } while (bytesRead); if (bytesRead < 0) { break; } jsonLen = jsonIdx; TEMP_FAILURE_RETRY(close(fd)); fd = 0; // now parse the string jsmn_parser parser = { 0 }; unsigned int numTokens = DEFAULT_NUMTOK; do { if (!jsonTokens) { jsonTokens = calloc(numTokens, sizeof(jsmntok_t)); if (!jsonTokens) { ERRLOG("WHOA3 : %s", strerror(errno)); break; } } else { //LOG("reallocating json tokens ..."); numTokens <<= 1; jsmntok_t *newTokens = realloc(jsonTokens, numTokens * sizeof(jsmntok_t)); memset(newTokens, '\0', numTokens * sizeof(jsmntok_t)); if (!newTokens) { ERRLOG("WHOA4 : %s", strerror(errno)); break; } jsonTokens = newTokens; } jsmn_init(&parser); errCount = jsmn_parse(&parser, jsonString, jsonLen, jsonTokens, numTokens-(numTokens/2)); } while (errCount == JSMN_ERROR_NOMEM); if (errCount == JSMN_ERROR_NOMEM) { break; } if (errCount < 0) { ERRLOG("%s", "OOPS error parsing JSON : "); switch (errCount) { case JSMN_ERROR_NOMEM: assert(0 && "should not happen"); break; case JSMN_ERROR_INVAL: ERRLOG("%s", "Invalid character inside JSON string"); break; case JSMN_ERROR_PART: ERRLOG("%s", "String is not a complete JSON packet, moar bytes expected"); break; default: ERRLOG("UNKNOWN errCount : %d", errCount); break; } break; } parsedData->jsonString = jsonString; parsedData->jsonTokens = jsonTokens; } while (0); if (fd > 0) { TEMP_FAILURE_RETRY(close(fd)); fd = 0; } if (errCount < 0) { if (jsonString) { FREE(jsonString); } if (jsonTokens) { FREE(jsonTokens); } } return errCount; } void json_destroy(JSON_s *parsedData) { FREE(parsedData->jsonString); FREE(parsedData->jsonTokens); } #if TEST_JSON bool do_logging = true; FILE *error_log = NULL; // Runs jsmn against an arbitrary a test_file.json int main(int argc, char **argv) { error_log = stderr; if (argc < 2) { fprintf(stderr, "Please specify a JSON file to parse on CLI, e.g. : %s path/to/some_file.json\n", argv[0]); exit(1); } JSON_s parsedData = { 0 }; int tokCount = json_createFromFile(argv[1], &parsedData); if (tokCount < 0) { return 1; } fprintf(stderr, "TOK COUNT:%d\n", tokCount); for (int i=0; i