mirror of
https://github.com/sigmasternchen/libargo
synced 2025-03-15 05:08:54 +00:00
better memory management and cleanup on malloc fail
This commit is contained in:
parent
4b3ce34e2b
commit
a1cf81a8ee
3 changed files with 269 additions and 56 deletions
188
src/base.c
188
src/base.c
|
@ -51,12 +51,16 @@ jsonValue_t* json_value() {
|
|||
|
||||
jsonValue_t* json_null() {
|
||||
jsonValue_t* value = json_value();
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
value->type = JSON_NULL;
|
||||
return value;
|
||||
}
|
||||
|
||||
jsonValue_t* json_double(double d) {
|
||||
jsonValue_t* value = json_value();
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
value->type = JSON_DOUBLE;
|
||||
value->value.real = d;
|
||||
return value;
|
||||
|
@ -64,6 +68,8 @@ jsonValue_t* json_double(double d) {
|
|||
|
||||
jsonValue_t* json_long(long l) {
|
||||
jsonValue_t* value = json_value();
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
value->type = JSON_LONG;
|
||||
value->value.integer = l;
|
||||
return value;
|
||||
|
@ -71,6 +77,8 @@ jsonValue_t* json_long(long l) {
|
|||
|
||||
jsonValue_t* json_bool(bool b) {
|
||||
jsonValue_t* value = json_value();
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
value->type = JSON_BOOL;
|
||||
value->value.boolean = b;
|
||||
return value;
|
||||
|
@ -78,75 +86,166 @@ jsonValue_t* json_bool(bool b) {
|
|||
|
||||
jsonValue_t* json_string(const char* s) {
|
||||
jsonValue_t* value = json_value();
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
value->type = JSON_STRING;
|
||||
value->value.string = strdup(s);
|
||||
if (value->value.string == NULL) {
|
||||
free(value);
|
||||
return NULL;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
jsonValue_t* json_array(bool freeAfterwards, size_t size, ...) {
|
||||
jsonValue_t* value = json_value();
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
value->type = JSON_ARRAY;
|
||||
value->value.array.size = size;
|
||||
value->value.array.entries = malloc(sizeof(jsonValue_t) * size);
|
||||
if (value->value.array.entries == NULL) {
|
||||
free(value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool abort = false;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, size);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
jsonValue_t* entry = va_arg(ap, jsonValue_t*);
|
||||
if (entry == NULL) {
|
||||
abort = true;
|
||||
if (freeAfterwards) {
|
||||
// we need to free each argument
|
||||
// this one is null -> don't free
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if aborted this does nothing
|
||||
value->value.array.entries[i] = *entry;
|
||||
|
||||
if (freeAfterwards) {
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
if (abort) {
|
||||
free(value->value.array.entries);
|
||||
free(value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
jsonValue_t* json_array_direct(bool freeAfterwards, size_t size, jsonValue_t* values[]) {
|
||||
jsonValue_t* value = json_value();
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
value->type = JSON_ARRAY;
|
||||
value->value.array.size = size;
|
||||
value->value.array.entries = malloc(sizeof(jsonValue_t) * size);
|
||||
if (value->value.array.entries == NULL) {
|
||||
free(value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool abort = false;
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
value->value.array.entries[i] = *values[i];
|
||||
if ((values[i]) == NULL) {
|
||||
abort = true;
|
||||
if (freeAfterwards) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if aborted this does nothing
|
||||
value->value.array.entries[i] = *(values[i]);
|
||||
|
||||
if (freeAfterwards) {
|
||||
free(values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (abort) {
|
||||
free(value->value.array.entries);
|
||||
free(value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
jsonValue_t* json_object(bool freeAfterwards, size_t size, ...) {
|
||||
jsonValue_t* value = json_value();
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
value->type = JSON_OBJECT;
|
||||
value->value.object.size = size;
|
||||
value->value.object.entries = malloc(sizeof(jsonObjectEntry_t) * size);
|
||||
|
||||
// using calloc so the memory is set to 0
|
||||
value->value.object.entries = calloc(size, sizeof(jsonObjectEntry_t));
|
||||
if (value->value.object.entries == NULL) {
|
||||
free(value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool abort = false;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, size);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
const char* key = va_arg(ap, const char*);
|
||||
jsonValue_t* entry = va_arg(ap, jsonValue_t*);
|
||||
value->value.object.entries[i].key = strdup(key);
|
||||
value->value.object.entries[i].value = *entry;
|
||||
|
||||
if (key == NULL) {
|
||||
abort = true;
|
||||
if (!freeAfterwards) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (entry == NULL) {
|
||||
abort = true;
|
||||
if (freeAfterwards) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!abort) {
|
||||
value->value.object.entries[i].key = strdup(key);
|
||||
value->value.object.entries[i].value = *entry;
|
||||
}
|
||||
if (freeAfterwards) {
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
if (abort) {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (value->value.object.entries[i].key != NULL) {
|
||||
free(value->value.object.entries[i].key);
|
||||
}
|
||||
}
|
||||
free(value->value.object.entries);
|
||||
free(value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void print_repeat(int i, char c) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
printf("%c", c);
|
||||
|
@ -197,58 +296,81 @@ void json_print(jsonValue_t* value) {
|
|||
json_print_r(value, 0);
|
||||
}
|
||||
|
||||
jsonValue_t json_clone_r(jsonValue_t value) {
|
||||
jsonValue_t clone = value;
|
||||
int json_clone_r(jsonValue_t* value, jsonValue_t* clone) {
|
||||
*clone = *value;
|
||||
|
||||
switch(value.type) {
|
||||
switch(value->type) {
|
||||
case JSON_STRING:
|
||||
clone.value.string = strdup(value.value.string);
|
||||
clone->value.string = strdup(value->value.string);
|
||||
if (clone->value.string == NULL) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case JSON_ARRAY:
|
||||
clone.value.array.size = value.value.array.size;
|
||||
clone.value.array.entries = malloc(sizeof(jsonValue_t) * clone.value.array.size);
|
||||
clone->value.array.size = value->value.array.size;
|
||||
clone->value.array.entries = malloc(sizeof(jsonValue_t) * clone->value.array.size);
|
||||
|
||||
if (clone.value.array.entries == NULL) {
|
||||
fprintf(stderr, "fuu\n");
|
||||
exit(1);
|
||||
if (clone->value.array.entries == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < clone.value.array.size; i++) {
|
||||
clone.value.array.entries[i] = json_clone_r(value.value.array.entries[i]);
|
||||
for (size_t i = 0; i < clone->value.array.size; i++) {
|
||||
if (json_clone_r(&(value->value.array.entries[i]), &(clone->value.array.entries[i])) < 0) {
|
||||
free(clone->value.array.entries);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case JSON_OBJECT:
|
||||
clone.value.object.size = value.value.object.size;
|
||||
clone.value.object.entries = malloc(sizeof(jsonObjectEntry_t) * clone.value.object.size);
|
||||
clone->value.object.size = value->value.object.size;
|
||||
clone->value.object.entries = malloc(sizeof(jsonObjectEntry_t) * clone->value.object.size);
|
||||
|
||||
if (clone.value.object.entries == NULL) {
|
||||
fprintf(stderr, "fuu\n");
|
||||
exit(1);
|
||||
if (clone->value.object.entries == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < clone.value.object.size; i++) {
|
||||
clone.value.object.entries[i].key = strdup(value.value.object.entries[i].key);
|
||||
clone.value.object.entries[i].value = json_clone_r(value.value.object.entries[i].value);
|
||||
for (size_t i = 0; i < clone->value.object.size; i++) {
|
||||
bool okay = true;
|
||||
|
||||
clone->value.object.entries[i].key = strdup(value->value.object.entries[i].key);
|
||||
if (clone->value.object.entries[i].key == NULL) {
|
||||
okay = false;
|
||||
} else if (json_clone_r(&(value->value.object.entries[i].value), &(clone->value.object.entries[i].value)) < 0) {
|
||||
free(clone->value.object.entries[i].key);
|
||||
okay = false;
|
||||
}
|
||||
|
||||
if (!okay) {
|
||||
for (size_t j = 0; j < i; j++) {
|
||||
free(clone->value.object.entries[j].key);
|
||||
json_free_r(&(clone->value.object.entries[j].value));
|
||||
}
|
||||
free(clone->value.object.entries);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// non dynamic members already copied
|
||||
break;
|
||||
}
|
||||
|
||||
return clone;
|
||||
return 0;
|
||||
}
|
||||
|
||||
jsonValue_t* json_clone(jsonValue_t* value) {
|
||||
jsonValue_t* clone = malloc(sizeof(jsonValue_t));
|
||||
if (clone == NULL) {
|
||||
fprintf(stderr, "fuu\n");
|
||||
exit(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*clone = json_clone_r(*value);
|
||||
if (json_clone_r(value, clone) < 0) {
|
||||
free(clone);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
|
134
src/parse.c
134
src/parse.c
|
@ -16,12 +16,20 @@ struct parserToken {
|
|||
|
||||
#define PARSER_TOKEN_CHUNK_SIZE (1024)
|
||||
|
||||
void addToParserToken(struct parserToken* token, char c) {
|
||||
int addToParserToken(struct parserToken* token, char c) {
|
||||
if (token->length % PARSER_TOKEN_CHUNK_SIZE == 0) {
|
||||
token->token = realloc(token->token, sizeof(char) * (token->length / PARSER_TOKEN_CHUNK_SIZE + 1) * PARSER_TOKEN_CHUNK_SIZE);
|
||||
char* tmp = realloc(token->token, sizeof(char) * (token->length / PARSER_TOKEN_CHUNK_SIZE + 1) * PARSER_TOKEN_CHUNK_SIZE);
|
||||
if (tmp == NULL) {
|
||||
free(token->token);
|
||||
token->token = NULL;
|
||||
return -1;
|
||||
}
|
||||
token->token = tmp;
|
||||
}
|
||||
|
||||
token->token[token->length++] = c;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void freeParserToken(struct parserToken* token) {
|
||||
|
@ -51,7 +59,10 @@ typedef struct {
|
|||
#define JSON_PARSER_STATE_DOUBLE (50)
|
||||
|
||||
jsonParsedValue_t json_parse_long(jsonParsedValue_t value, struct parserToken token) {
|
||||
addToParserToken(&token, '\0');
|
||||
if (addToParserToken(&token, '\0') < 0) {
|
||||
value.errorFormat = "internal error while parsing numgber";
|
||||
return value;
|
||||
}
|
||||
|
||||
char* endptr;
|
||||
long long l = strtoll(token.token, &endptr, 10);
|
||||
|
@ -68,7 +79,10 @@ jsonParsedValue_t json_parse_long(jsonParsedValue_t value, struct parserToken to
|
|||
}
|
||||
|
||||
jsonParsedValue_t json_parse_double(jsonParsedValue_t value, struct parserToken token) {
|
||||
addToParserToken(&token, '\0');
|
||||
if (addToParserToken(&token, '\0') < 0) {
|
||||
value.errorFormat = "internal error while parsing numgber";
|
||||
return value;
|
||||
}
|
||||
|
||||
char* endptr;
|
||||
double d = strtod(token.token, &endptr);
|
||||
|
@ -138,7 +152,10 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
case '8':
|
||||
case '9':
|
||||
case '-':
|
||||
addToParserToken(&token, c);
|
||||
if (addToParserToken(&token, c) < 0) {
|
||||
value.errorFormat = "internal error in line %ld";
|
||||
return value;
|
||||
}
|
||||
state = JSON_PARSER_STATE_LONG;
|
||||
break;
|
||||
default:
|
||||
|
@ -161,56 +178,77 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
value.errorFormat = "illegal character in line %d: '%c'";
|
||||
}
|
||||
|
||||
freeParserToken(&token);
|
||||
|
||||
return value;
|
||||
}
|
||||
break;
|
||||
case JSON_PARSER_STATE_STRING:
|
||||
if (!escaped && c == '"') {
|
||||
addToParserToken(&token, '\0');
|
||||
value.okay = true;
|
||||
if (addToParserToken(&token, '\0') < 0) {
|
||||
value.errorFormat = "internal error while parsing string";
|
||||
return value;
|
||||
}
|
||||
value.index = index + 1;
|
||||
value.value.value.string = strdup(token.token);
|
||||
freeParserToken(&token);
|
||||
if (value.value.value.string == NULL) {
|
||||
value.errorFormat = "couldn't strdup while parsing string";
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
|
||||
value.okay = true;
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
if (!escaped && c == '\\') {
|
||||
escaped = true;
|
||||
break;
|
||||
} else if (escaped) {
|
||||
int tmp = 0;
|
||||
switch(c) {
|
||||
case 'b':
|
||||
addToParserToken(&token, '\b');
|
||||
tmp = addToParserToken(&token, '\b');
|
||||
break;
|
||||
case 'f':
|
||||
addToParserToken(&token, '\f');
|
||||
tmp = addToParserToken(&token, '\f');
|
||||
break;
|
||||
case 'n':
|
||||
addToParserToken(&token, '\n');
|
||||
tmp = addToParserToken(&token, '\n');
|
||||
break;
|
||||
case 'r':
|
||||
addToParserToken(&token, '\r');
|
||||
tmp = addToParserToken(&token, '\r');
|
||||
break;
|
||||
case 't':
|
||||
addToParserToken(&token, '\t');
|
||||
tmp = addToParserToken(&token, '\t');
|
||||
break;
|
||||
case 'u':
|
||||
value.okay = false;
|
||||
value.index = index;
|
||||
value.errorFormat = "line %ld: \\u-syntax is not supported";
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
|
||||
case '"':
|
||||
case '\\':
|
||||
case '/':
|
||||
addToParserToken(&token, c);
|
||||
tmp = addToParserToken(&token, c);
|
||||
break;
|
||||
|
||||
default:
|
||||
addToParserToken(&token, '\\');
|
||||
addToParserToken(&token, c);
|
||||
tmp = addToParserToken(&token, '\\');
|
||||
tmp = addToParserToken(&token, c);
|
||||
break;
|
||||
}
|
||||
if (tmp < 0) {
|
||||
value.errorFormat = "internal error while parsing string escape sequence";
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
|
||||
escaped = false;
|
||||
} else {
|
||||
switch(c) {
|
||||
|
@ -222,32 +260,56 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
value.okay = false;
|
||||
value.index = index;
|
||||
value.errorFormat = "line %ld: control characters are not allowed in json strings";
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
default:
|
||||
addToParserToken(&token, c);
|
||||
if (addToParserToken(&token, c) < 0) {
|
||||
value.errorFormat = "internal error while parsing string";
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case JSON_PARSER_STATE_LONG:
|
||||
if (c >= '0' && c <= '9') {
|
||||
addToParserToken(&token, c);
|
||||
if (addToParserToken(&token, c) < 0) {
|
||||
value.errorFormat = "internal error while parsing number";
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
} else if (c == '.' || c == 'e') {
|
||||
addToParserToken(&token, c);
|
||||
if (addToParserToken(&token, c) < 0) {
|
||||
value.errorFormat = "internal error while parsing number";
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
state = JSON_PARSER_STATE_DOUBLE;
|
||||
} else {
|
||||
value.index = index;
|
||||
value = json_parse_long(value, token);
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
break;
|
||||
case JSON_PARSER_STATE_DOUBLE:
|
||||
if ((c >= '0' && c <= '9') || c == '.' || c == '+' || c == '-' || c == 'e') {
|
||||
addToParserToken(&token, c);
|
||||
if (addToParserToken(&token, c) < 0) {
|
||||
value.errorFormat = "internal error while parsing number";
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
} else {
|
||||
value.index = index;
|
||||
value = json_parse_double(value, token);
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
|
@ -265,6 +327,8 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
|
||||
value.errorFormat = "line %ld: unexpected '%c'";
|
||||
value.index = index;
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -286,6 +350,7 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
if (!entry.okay) {
|
||||
json_free_r(&value.value);
|
||||
|
||||
freeParserToken(&token);
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
@ -295,6 +360,8 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
json_free_r(&value.value);
|
||||
|
||||
value.errorFormat = "allocation for array failed";
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -328,6 +395,8 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
|
||||
value.errorFormat = "line %ld: unexpected ','; ':' expected";
|
||||
value.index = index;
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -342,6 +411,8 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
|
||||
value.errorFormat = "line %ld: unexpected character ':'";
|
||||
value.index = index;
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -350,6 +421,8 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
|
||||
value.errorFormat = "line %ld: unexpected ':'; key is missing";
|
||||
value.index = index;
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -363,6 +436,8 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
|
||||
value.errorFormat = "line %ld: unexpected '%c'; ',' or '}' expected";
|
||||
value.index = index;
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -371,6 +446,7 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
if (!entry.okay) {
|
||||
json_free_r(&value.value);
|
||||
|
||||
freeParserToken(&token);
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
@ -379,9 +455,10 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
json_free_r(&value.value);
|
||||
json_free_r(&entry.value);
|
||||
|
||||
|
||||
value.errorFormat = "line %ld: key is missing";
|
||||
value.index = index;
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -394,6 +471,8 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
json_free_r(&value.value);
|
||||
|
||||
value.errorFormat = "allocation for object failed";
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -414,6 +493,8 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
default:
|
||||
value.index = index;
|
||||
value.errorFormat = "illegal state in line %ld";
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
@ -421,21 +502,22 @@ jsonParsedValue_t json_parse_r(const char* string, size_t index, size_t line, si
|
|||
if (state == JSON_PARSER_STATE_LONG) {
|
||||
value.index = index;
|
||||
value = json_parse_long(value, token);
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
if (state == JSON_PARSER_STATE_DOUBLE) {
|
||||
value.index = index;
|
||||
value = json_parse_double(value, token);
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
|
||||
freeParserToken(&token);
|
||||
|
||||
value.index = index - 1;
|
||||
value.errorFormat = "unexpected end of input on line %ld";
|
||||
|
||||
freeParserToken(&token);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -445,6 +527,7 @@ jsonValue_t* json_parse(const char* string) {
|
|||
jsonParsedValue_t parsedValue = json_parse_r(string, 0, 1, length);
|
||||
|
||||
if (!parsedValue.okay) {
|
||||
// TODO put in extern global instead
|
||||
printf("%ld\n", parsedValue.index);
|
||||
printf(parsedValue.errorFormat, parsedValue.line, string[parsedValue.index]);
|
||||
printf("\n");
|
||||
|
@ -457,6 +540,11 @@ jsonValue_t* json_parse(const char* string) {
|
|||
}
|
||||
|
||||
jsonValue_t* value = malloc(sizeof(jsonValue_t));
|
||||
if (value == NULL) {
|
||||
json_free_r(&(parsedValue.value));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*value = parsedValue.value;
|
||||
|
||||
return value;
|
||||
|
|
|
@ -34,6 +34,9 @@ jsonValue_t* json_query(jsonValue_t* value, const char* query) {
|
|||
char buffer[JSON_QUERY_BUFFER_SIZE];
|
||||
|
||||
value = json_clone(value);
|
||||
if (value == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while(true) {
|
||||
if (query[0] == '\0')
|
||||
|
|
Loading…
Reference in a new issue