mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-12-27 21:29:42 +00:00
210 lines
6.0 KiB
C
210 lines
6.0 KiB
C
/*
|
|
* 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<tokCount; i++) {
|
|
fprintf(stderr, "%s", "type:");
|
|
switch(parsedData.jsonTokens[i].type) {
|
|
case JSMN_PRIMITIVE:
|
|
fprintf(stderr, "%s", "PRIMITIVE ");
|
|
break;
|
|
case JSMN_OBJECT:
|
|
fprintf(stderr, "%s", "OBJECT ");
|
|
break;
|
|
case JSMN_ARRAY:
|
|
fprintf(stderr, "%s", "ARRAY ");
|
|
break;
|
|
case JSMN_STRING:
|
|
fprintf(stderr, "%s", "STRING ");
|
|
break;
|
|
default:
|
|
fprintf(stderr, "%s", "UNKNOWN ");
|
|
break;
|
|
}
|
|
int start = parsedData.jsonTokens[i].start;
|
|
int end = parsedData.jsonTokens[i].end;
|
|
fprintf(stderr, "start:%6d end:%6d size:%6d parent:%3d", start, end, parsedData.jsonTokens[i].size, parsedData.jsonTokens[i].parent);
|
|
if (parsedData.jsonTokens[i].type == JSMN_STRING) {
|
|
char lastChar = parsedData.jsonString[end];
|
|
parsedData.jsonString[end] = '\0';
|
|
fprintf(stderr, " VALUE:%s", &parsedData.jsonString[start]);
|
|
parsedData.jsonString[end] = lastChar;
|
|
}
|
|
fprintf(stderr, "%s", "\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|