|
#ifndef RLIZA_H
|
|
#define RLIZA_H
|
|
#include "rbuffer.h"
|
|
#include "rmalloc.h"
|
|
#include "rstring.h"
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
typedef enum rliza_type_t {
|
|
RLIZA_STRING = 's',
|
|
RLIZA_BOOLEAN = 'b',
|
|
RLIZA_NUMBER = 'n',
|
|
RLIZA_OBJECT = 'o',
|
|
RLIZA_ARRAY = 'a',
|
|
RLIZA_NULL = 0,
|
|
RLIZA_KEY = 'k',
|
|
RLIZA_INTEGER = 'i'
|
|
} rliza_type_t;
|
|
|
|
typedef struct rliza_t {
|
|
rliza_type_t type;
|
|
struct rliza_t *value;
|
|
char *key;
|
|
union {
|
|
char *string;
|
|
bool boolean;
|
|
double number;
|
|
struct rliza_t **map;
|
|
long long integer;
|
|
} content;
|
|
unsigned int count;
|
|
char *(*get_string)(struct rliza_t *, char *);
|
|
long long (*get_integer)(struct rliza_t *, char *);
|
|
double (*get_number)(struct rliza_t *, char *);
|
|
bool (*get_boolean)(struct rliza_t *, char *);
|
|
struct rliza_t *(*get_array)(struct rliza_t *, char *);
|
|
struct rliza_t *(*get_object)(struct rliza_t *, char *);
|
|
void (*set_string)(struct rliza_t *, char *, char *);
|
|
void (*set_integer)(struct rliza_t *, char *, long long);
|
|
void (*set_number)(struct rliza_t *, char *, double);
|
|
void (*set_boolean)(struct rliza_t *, char *, bool);
|
|
void (*set_array)(struct rliza_t *self, char *key, struct rliza_t *array);
|
|
void (*set_object)(struct rliza_t *self, char *key, struct rliza_t *object);
|
|
} rliza_t;
|
|
|
|
void rliza_free(rliza_t *rliza) {
|
|
if (rliza->key) {
|
|
free(rliza->key);
|
|
rliza->key = NULL;
|
|
}
|
|
if (rliza->value) {
|
|
rliza_free(rliza->value);
|
|
rliza->value = NULL;
|
|
}
|
|
// if (rliza->content.array) {
|
|
// printf("JAAAA\n");
|
|
// }
|
|
// if (rliza->content.object) {
|
|
// rliza_free(rliza->content.object);
|
|
// rliza->content.object = NULL;
|
|
//}
|
|
if (rliza->type == RLIZA_STRING) {
|
|
if (rliza->content.string) {
|
|
free(rliza->content.string);
|
|
rliza->content.string = NULL;
|
|
// else if (rliza->type == RLIZA_NUMBER) {
|
|
// printf("STDring freed\n");
|
|
}
|
|
} else if (rliza->type == RLIZA_OBJECT || rliza->type == RLIZA_ARRAY) {
|
|
|
|
if (rliza->content.map) {
|
|
for (unsigned int i = 0; i < rliza->count; i++) {
|
|
rliza_free(rliza->content.map[i]);
|
|
}
|
|
free(rliza->content.map);
|
|
}
|
|
}
|
|
// free(rliza->content.array);
|
|
//}
|
|
|
|
free(rliza);
|
|
}
|
|
|
|
rliza_t *rliza_new(rliza_type_t type);
|
|
rliza_t *rliza_new_string(char *string);
|
|
rliza_t *rliza_new_null();
|
|
rliza_t *rliza_new_boolean(bool value);
|
|
rliza_t *rliza_new_number(double value);
|
|
rliza_t *rliza_new_integer(long long value);
|
|
rliza_t *rliza_new_key_value(char *key, rliza_t *value);
|
|
rliza_t *rliza_new_key_string(char *key, char *string);
|
|
rliza_t *rliza_new_key_bool(char *key, bool value);
|
|
rliza_t *rliza_new_key_number(char *key, double value);
|
|
void rliza_push(rliza_t *self, rliza_t *obj);
|
|
void rliza_push_object(rliza_t *self, rliza_t *object);
|
|
void rliza_set_object(rliza_t *self, char *key, rliza_t *object);
|
|
void rliza_set_string(rliza_t *self, char *key, char *string);
|
|
void rliza_set_boolean(rliza_t *self, char *key, bool value);
|
|
void rliza_set_number(rliza_t *self, char *key, double value);
|
|
void rliza_set_integer(rliza_t *self, char *key, long long value);
|
|
char *rliza_get_string(rliza_t *self, char *key);
|
|
long long rliza_get_integer(rliza_t *self, char *key);
|
|
double rliza_get_number(rliza_t *self, char *key);
|
|
bool rliza_get_boolean(rliza_t *self, char *key);
|
|
rliza_t *rliza_get_array(rliza_t *self, char *key);
|
|
rliza_t *rliza_get_object(rliza_t *self, char *key);
|
|
void rliza_set_array(rliza_t *self, char *key, rliza_t *array);
|
|
|
|
char *rliza_dumps(rliza_t *rliza);
|
|
rliza_t *rliza_loads(char **content);
|
|
rliza_t *_rliza_loads(char **content);
|
|
|
|
char *rliza_get_string(rliza_t *self, char *key) {
|
|
for (unsigned int i = 0; i < self->count; i++) {
|
|
if (self->content.map[i]->key != NULL && strcmp(self->content.map[i]->key, key) == 0) {
|
|
if (self->content.map[i]->type == RLIZA_STRING || self->content.map[i]->type == RLIZA_NULL) {
|
|
return self->content.map[i]->content.string;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
long long rliza_get_integer(rliza_t *self, char *key) {
|
|
for (unsigned int i = 0; i < self->count; i++) {
|
|
if (self->content.map[i]->key != NULL && strcmp(self->content.map[i]->key, key) == 0) {
|
|
if (self->content.map[i]->type == RLIZA_INTEGER || self->content.map[i]->type == RLIZA_NULL) {
|
|
return self->content.map[i]->content.integer;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
double rliza_get_number(rliza_t *self, char *key) {
|
|
for (unsigned int i = 0; i < self->count; i++) {
|
|
if (self->content.map[i]->key != NULL && strcmp(self->content.map[i]->key, key) == 0) {
|
|
if (self->content.map[i]->type == RLIZA_NUMBER || self->content.map[i]->type == RLIZA_NULL) {
|
|
return self->content.map[i]->content.number;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool rliza_get_boolean(rliza_t *self, char *key) {
|
|
for (unsigned int i = 0; i < self->count; i++) {
|
|
if (self->content.map[i]->key != NULL && strcmp(self->content.map[i]->key, key) == 0) {
|
|
if (self->content.map[i]->type == RLIZA_BOOLEAN || self->content.map[i]->type == RLIZA_NULL) {
|
|
return self->content.map[i]->content.boolean;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
rliza_t *rliza_get_object(rliza_t *self, char *key) {
|
|
for (unsigned int i = 0; i < self->count; i++) {
|
|
if (self->content.map[i]->key != NULL && strcmp(self->content.map[i]->key, key) == 0) {
|
|
return self->content.map[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
rliza_t *rliza_get_array(rliza_t *self, char *key) {
|
|
for (unsigned int i = 0; i < self->count; i++) {
|
|
if (self->content.map[i]->key != NULL && strcmp(self->content.map[i]->key, key) == 0) {
|
|
if (self->content.map[i]->type == RLIZA_ARRAY || self->content.map[i]->type == RLIZA_NULL) {
|
|
return self->content.map[i];
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
rliza_t *rliza_new_null() {
|
|
rliza_t *rliza = rliza_new(RLIZA_NULL);
|
|
return rliza;
|
|
}
|
|
rliza_t *rliza_new_string(char *string) {
|
|
rliza_t *rliza = rliza_new(RLIZA_STRING);
|
|
if (string == NULL) {
|
|
rliza->type = RLIZA_NULL;
|
|
rliza->content.string = NULL;
|
|
return rliza;
|
|
} else {
|
|
rliza->content.string = strdup(string);
|
|
}
|
|
return rliza;
|
|
}
|
|
rliza_t *rliza_new_boolean(bool value) {
|
|
rliza_t *rliza = rliza_new(RLIZA_BOOLEAN);
|
|
rliza->content.boolean = value;
|
|
return rliza;
|
|
}
|
|
|
|
rliza_t *rliza_new_number(double value) {
|
|
rliza_t *rliza = rliza_new(RLIZA_NUMBER);
|
|
rliza->content.number = value;
|
|
return rliza;
|
|
}
|
|
|
|
rliza_t *rliza_new_integer(long long value) {
|
|
rliza_t *rliza = rliza_new(RLIZA_INTEGER);
|
|
rliza->content.integer = value;
|
|
return rliza;
|
|
}
|
|
rliza_t *rliza_new_key_array(char *key) {
|
|
rliza_t *rliza = rliza_new(RLIZA_ARRAY);
|
|
rliza->key = strdup(key);
|
|
return rliza;
|
|
}
|
|
|
|
rliza_t *rliza_new_key_value(char *key, rliza_t *value) {
|
|
rliza_t *rliza = rliza_new(RLIZA_OBJECT);
|
|
if (key) {
|
|
rliza->key = strdup(key);
|
|
}
|
|
rliza->value = value;
|
|
return rliza;
|
|
}
|
|
|
|
rliza_t *rliza_new_key_string(char *key, char *string) {
|
|
rliza_t *rliza = rliza_new_key_value(key, rliza_new_string(string));
|
|
return rliza;
|
|
}
|
|
rliza_t *rliza_new_key_bool(char *key, bool value) {
|
|
rliza_t *rliza = rliza_new_key_value(key, rliza_new_boolean(value));
|
|
return rliza;
|
|
}
|
|
rliza_t *rliza_new_key_number(char *key, double value) {
|
|
rliza_t *rliza = rliza_new_key_value(key, rliza_new_number(value));
|
|
return rliza;
|
|
}
|
|
|
|
void rliza_set_null(rliza_t *self, char *key) {
|
|
rliza_t *obj = rliza_get_object(self, key);
|
|
if (!obj) {
|
|
obj = rliza_new_null();
|
|
obj->key = strdup(key);
|
|
rliza_push_object(self, obj);
|
|
}
|
|
if (obj->type == RLIZA_OBJECT) {
|
|
|
|
rliza_free(obj->value);
|
|
obj->value = NULL;
|
|
} else if (obj->type == RLIZA_STRING) {
|
|
if (obj->content.string)
|
|
free(obj->content.string);
|
|
obj->content.string = NULL;
|
|
} else if (obj->type == RLIZA_ARRAY) {
|
|
for (unsigned int i = 0; i < obj->count; i++) {
|
|
rliza_free(obj->content.map[i]);
|
|
}
|
|
} else if (obj->type == RLIZA_NUMBER) {
|
|
obj->content.number = 0;
|
|
} else if (obj->type == RLIZA_INTEGER) {
|
|
obj->content.integer = 0;
|
|
}
|
|
obj->type = RLIZA_NULL;
|
|
}
|
|
|
|
rliza_t *rliza_duplicate(rliza_t *rliza) {
|
|
if (!rliza)
|
|
return NULL;
|
|
char *str = rliza_dumps(rliza);
|
|
char *strp = str;
|
|
rliza_t *obj = rliza_loads(&strp);
|
|
free(str);
|
|
return obj;
|
|
}
|
|
|
|
rliza_t *rliza_new_object(rliza_t *obj) {
|
|
rliza_t *rliza = rliza_new(RLIZA_OBJECT);
|
|
rliza->value = obj;
|
|
return rliza;
|
|
}
|
|
void rliza_set_object(rliza_t *self, char *key, rliza_t *value) {
|
|
rliza_t *obj = rliza_duplicate(value);
|
|
obj->key = strdup(key);
|
|
obj->type = RLIZA_OBJECT;
|
|
rliza_push(self, obj);
|
|
}
|
|
|
|
void rliza_set_string(rliza_t *self, char *key, char *string) {
|
|
rliza_t *obj = rliza_get_object(self, key);
|
|
|
|
if (!obj) {
|
|
obj = rliza_new_string(string);
|
|
obj->key = strdup(key);
|
|
obj->type = RLIZA_STRING;
|
|
rliza_push_object(self, obj);
|
|
} else {
|
|
obj->content.string = strdup(string);
|
|
}
|
|
}
|
|
|
|
void rliza_set_array(rliza_t *self, char *key, rliza_t *array) {
|
|
rliza_t *obj = rliza_get_object(self, key);
|
|
if (obj)
|
|
rliza_free(obj);
|
|
if (array->key) {
|
|
free(array->key);
|
|
array->key = strdup(key);
|
|
}
|
|
rliza_push_object(self, array);
|
|
}
|
|
|
|
void rliza_set_number(rliza_t *self, char *key, double value) {
|
|
rliza_t *obj = rliza_get_object(self, key);
|
|
if (!obj) {
|
|
obj = rliza_new_number(value);
|
|
obj->key = strdup(key);
|
|
obj->type = RLIZA_NUMBER;
|
|
rliza_push_object(self, obj);
|
|
} else {
|
|
obj->content.number = value;
|
|
}
|
|
}
|
|
|
|
void rliza_push_object(rliza_t *self, rliza_t *object) {
|
|
self->content.map = realloc(self->content.map, (sizeof(rliza_t **)) * (self->count + 1));
|
|
self->content.map[self->count] = object;
|
|
self->count++;
|
|
}
|
|
void rliza_set_integer(rliza_t *self, char *key, long long value) {
|
|
rliza_t *obj = rliza_get_object(self, key);
|
|
if (!obj) {
|
|
obj = rliza_new_integer(value);
|
|
obj->key = strdup(key);
|
|
obj->type = RLIZA_INTEGER;
|
|
rliza_push_object(self, obj);
|
|
} else {
|
|
obj->content.integer = value;
|
|
}
|
|
}
|
|
|
|
void rliza_set_boolean(rliza_t *self, char *key, bool value) {
|
|
rliza_t *obj = rliza_get_object(self, key);
|
|
if (!obj) {
|
|
obj = rliza_new_boolean(value);
|
|
obj->key = strdup(key);
|
|
obj->type = RLIZA_BOOLEAN;
|
|
|
|
rliza_push_object(self, obj);
|
|
} else {
|
|
obj->content.boolean = value;
|
|
}
|
|
}
|
|
|
|
rliza_t *rliza_new(rliza_type_t type) {
|
|
rliza_t *rliza = (rliza_t *)calloc(1, sizeof(rliza_t));
|
|
rliza->type = type;
|
|
rliza->get_boolean = rliza_get_boolean;
|
|
rliza->get_integer = rliza_get_integer;
|
|
rliza->get_number = rliza_get_number;
|
|
rliza->get_string = rliza_get_string;
|
|
rliza->get_array = rliza_get_array;
|
|
rliza->get_object = rliza_get_object;
|
|
rliza->set_string = rliza_set_string;
|
|
rliza->set_number = rliza_set_number;
|
|
rliza->set_boolean = rliza_set_boolean;
|
|
rliza->set_integer = rliza_set_integer;
|
|
rliza->set_array = rliza_set_array;
|
|
rliza->set_object = rliza_set_object;
|
|
|
|
return rliza;
|
|
}
|
|
|
|
void *rliza_coalesce(void *result, void *default_value) {
|
|
if (result == NULL)
|
|
return default_value;
|
|
return result;
|
|
}
|
|
|
|
char *rliza_seek_string(char **content, char **options) {
|
|
|
|
while (**content == ' ' || **content == '\n' || **content == '\t' || **content == '\r') {
|
|
(*content)++;
|
|
}
|
|
if (**content == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
char *option = NULL;
|
|
unsigned int option_index = 0;
|
|
|
|
while (true) {
|
|
option = options[option_index];
|
|
if (option == NULL)
|
|
break;
|
|
option_index++;
|
|
if (option[0] == 'd') {
|
|
if (**content >= '0' && **content <= '9') {
|
|
return (char *)*content;
|
|
}
|
|
} else if (!strncmp(option, *content, strlen(option))) {
|
|
return (char *)*content;
|
|
}
|
|
}
|
|
return *content;
|
|
}
|
|
|
|
char *rliza_extract_quotes(char **content) {
|
|
rbuffer_t *buffer = rbuffer_new(NULL, 0);
|
|
assert(**content == '"');
|
|
char previous = 0;
|
|
while (true) {
|
|
|
|
(*content)++;
|
|
if (!**content) {
|
|
rbuffer_free(buffer);
|
|
return NULL;
|
|
}
|
|
|
|
if (**content == '"' && previous != '\\') {
|
|
break;
|
|
}
|
|
rbuffer_push(buffer, **content);
|
|
previous = **content;
|
|
}
|
|
assert(**content == '"');
|
|
(*content)++;
|
|
rbuffer_push(buffer, 0);
|
|
char *result = (char *)rbuffer_to_string(buffer);
|
|
return result;
|
|
}
|
|
|
|
rliza_t *_rliza_loads(char **content) {
|
|
static char *seek_for1[] = {"[", "{", "\"", "d", "true", "false", "null", NULL};
|
|
char *token = (char *)rliza_seek_string(content, seek_for1);
|
|
if (!token)
|
|
return NULL;
|
|
rliza_t *rliza = rliza_new(RLIZA_NULL);
|
|
if (**content == '"') {
|
|
char *extracted = rliza_extract_quotes(content);
|
|
if (!extracted) {
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
// char *extracted_with_slashes = (char *)malloc(strlen((char *)extracted) * 2 + 1);
|
|
// rstraddslashes(extracted, extracted_with_slashes);
|
|
rliza->type = RLIZA_STRING;
|
|
rliza->content.string = extracted; // extracted_with_slashes; // extracted_without_slashes;
|
|
// free(extracted);
|
|
return rliza;
|
|
} else if (**content == '{') {
|
|
rliza->type = RLIZA_OBJECT;
|
|
(*content)++;
|
|
char *result = NULL;
|
|
static char *seek_for2[] = {"\"", ",", "}", NULL};
|
|
while ((result = (char *)rliza_seek_string(content, seek_for2)) != NULL && *result) {
|
|
|
|
if (!**content) {
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
if (**content == ',') {
|
|
(*content)++;
|
|
if (!**content) {
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
continue;
|
|
}
|
|
char *key = NULL;
|
|
if (**content == '"') {
|
|
key = rliza_extract_quotes((char **)content);
|
|
if (!key || !*key) {
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
char *escaped_key = (char *)malloc(strlen((char *)key) * 2 + 1);
|
|
rstrstripslashes((char *)key, escaped_key);
|
|
static char *seek_for3[] = {":", NULL};
|
|
char *devider = rliza_seek_string(content, seek_for3);
|
|
|
|
if (!devider || !*devider) {
|
|
free(escaped_key);
|
|
free(key);
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
(*content)++;
|
|
if (!**content) {
|
|
free(key);
|
|
free(escaped_key);
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
rliza_t *value = _rliza_loads(content);
|
|
if (!value) {
|
|
free(key);
|
|
free(escaped_key);
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
if (value->key)
|
|
free(value->key);
|
|
value->key = escaped_key;
|
|
free(key);
|
|
rliza_push_object(rliza, value);
|
|
} else if (**content == '}') {
|
|
break;
|
|
} else {
|
|
// Parse error
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
};
|
|
if ((**content != '}')) {
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
(*content)++;
|
|
return rliza;
|
|
} else if (**content == '[') {
|
|
rliza->type = RLIZA_ARRAY;
|
|
(*content)++;
|
|
char *result;
|
|
static char *seek_for4[] = {"[", "{", "\"", "d", ",", "]", "null", "true", "false", NULL};
|
|
while ((result = (char *)rliza_seek_string(content, seek_for4)) != NULL && *result) {
|
|
if (**content == ',') {
|
|
(*content)++;
|
|
|
|
} else if (**content == ']') {
|
|
break;
|
|
}
|
|
rliza_t *obj = _rliza_loads(content);
|
|
if (!obj) {
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
rliza_push(rliza, obj);
|
|
if (!**content) {
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
}
|
|
if (**content != ']') {
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
(*content)++;
|
|
return rliza;
|
|
} else if (**content >= '0' && **content <= '9') {
|
|
char *ptr = *content;
|
|
bool is_decimal = false;
|
|
|
|
while (**content) {
|
|
if (**content == '.') {
|
|
is_decimal = true;
|
|
} else if (!isdigit(**content)) {
|
|
break;
|
|
}
|
|
(*content)++;
|
|
}
|
|
if (*(*content - 1) == '.') {
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
if (!**content) {
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
if (is_decimal) {
|
|
rliza->type = RLIZA_NUMBER;
|
|
rliza->content.number = strtod(ptr, NULL);
|
|
} else {
|
|
rliza->type = RLIZA_INTEGER;
|
|
rliza->content.integer = strtoll(ptr, NULL, 10);
|
|
}
|
|
return rliza;
|
|
} else if (!strncmp(*content, "true", 4)) {
|
|
rliza->type = RLIZA_BOOLEAN;
|
|
rliza->content.boolean = true;
|
|
*content += 4;
|
|
|
|
return rliza;
|
|
} else if (!strncmp(*content, "false", 5)) {
|
|
rliza->type = RLIZA_BOOLEAN;
|
|
rliza->content.boolean = false;
|
|
*content += 5;
|
|
|
|
return rliza;
|
|
} else if (!strncmp(*content, "null", 4)) {
|
|
rliza->type = RLIZA_NULL;
|
|
*content += 4;
|
|
|
|
return rliza;
|
|
}
|
|
// Parsing error
|
|
rliza_free(rliza);
|
|
return NULL;
|
|
}
|
|
rliza_t *rliza_loads(char **content) {
|
|
if (!content || !**content) {
|
|
return NULL;
|
|
}
|
|
char *original_content = *content;
|
|
rliza_t *result = _rliza_loads(content);
|
|
if (!result) {
|
|
*content = original_content;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
char *rliza_dumps(rliza_t *rliza) {
|
|
size_t size = 4096;
|
|
char *content = (char *)calloc(size, sizeof(char));
|
|
content[0] = 0;
|
|
if (rliza->type == RLIZA_INTEGER) {
|
|
if (rliza->key) {
|
|
sprintf(content, "\"%s\":%lld", rliza->key, rliza->content.integer);
|
|
} else {
|
|
sprintf(content, "%lld", rliza->content.integer);
|
|
}
|
|
} else if (rliza->type == RLIZA_STRING) {
|
|
|
|
// char *escaped_string = (char *)calloc(strlen((char *)rliza->content.string) * 2 + 1024,sizeof(char));
|
|
char *escaped_string = rliza->content.string;
|
|
// rstrstripslashes((char *)rliza->content.string, escaped_string);
|
|
size_t min_size = strlen((char *)escaped_string) + (rliza->key ? strlen(rliza->key) : 0) + 1024;
|
|
if (size < min_size) {
|
|
size = min_size + 1;
|
|
content = realloc(content, size);
|
|
}
|
|
if (rliza->key) {
|
|
char *escaped_key = (char *)malloc(strlen((char *)rliza->key) * 2 + 20);
|
|
rstrstripslashes((char *)rliza->key, escaped_key);
|
|
if (strlen(content) > size) {
|
|
size = size + strlen(escaped_string) + 20;
|
|
content = realloc(content, size);
|
|
}
|
|
sprintf(content, "\"%s\":\"%s\"", escaped_key, escaped_string);
|
|
free(escaped_key);
|
|
} else {
|
|
size = size + strlen(escaped_string) + 20;
|
|
content = realloc(content, size);
|
|
sprintf(content, "\"%s\"", escaped_string);
|
|
}
|
|
// free(escaped_string);
|
|
} else if (rliza->type == RLIZA_NUMBER) {
|
|
if (rliza->key) {
|
|
sprintf(content, "\"%s\":%f", rliza->key, rliza->content.number);
|
|
} else {
|
|
sprintf(content, "%f", rliza->content.number);
|
|
}
|
|
int last_zero = 0;
|
|
bool beyond_dot = false;
|
|
for (size_t i = 0; i < strlen(content); i++) {
|
|
if (content[i] == '.') {
|
|
beyond_dot = true;
|
|
} else if (beyond_dot == true) {
|
|
if (content[i - 1] != '.') {
|
|
if (content[i] == '0') {
|
|
if (!last_zero)
|
|
last_zero = i;
|
|
} else {
|
|
last_zero = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (last_zero != 0) {
|
|
content[last_zero] = 0;
|
|
}
|
|
} else if (rliza->type == RLIZA_BOOLEAN) {
|
|
if (rliza->key) {
|
|
sprintf(content, "\"%s\":%s", rliza->key, rliza->content.boolean ? "true" : "false");
|
|
} else {
|
|
sprintf(content, "%s", rliza->content.boolean ? "true" : "false");
|
|
}
|
|
} else if (rliza->type == RLIZA_OBJECT) {
|
|
|
|
strcat(content, "{");
|
|
if (rliza->key) {
|
|
strcat(content, "\"");
|
|
strcat(content, rliza->key);
|
|
strcat(content, "\":{");
|
|
}
|
|
// bool add_braces = false;
|
|
for (unsigned i = 0; i < rliza->count; i++) {
|
|
char *content_chunk = rliza_dumps(rliza->content.map[i]);
|
|
char *content_chunk_stripped = content_chunk;
|
|
if (*content_chunk_stripped == '{') {
|
|
content_chunk_stripped++;
|
|
content_chunk_stripped[strlen(content_chunk_stripped) - 1] = 0;
|
|
}
|
|
if (strlen(content_chunk_stripped) + strlen(content) > size) {
|
|
size += strlen(content_chunk_stripped) + 20;
|
|
content = realloc(content, size);
|
|
}
|
|
strcat(content, content_chunk_stripped);
|
|
free(content_chunk);
|
|
|
|
strcat(content, ",");
|
|
}
|
|
if (content[strlen(content) - 1] == ',') {
|
|
content[strlen(content) - 1] = '\0';
|
|
|
|
if (rliza->key) {
|
|
strcat(content, "}");
|
|
}
|
|
}
|
|
strcat(content, "}");
|
|
} else if (rliza->type == RLIZA_ARRAY) {
|
|
if (rliza->key) {
|
|
char *escaped_key = (char *)malloc(strlen((char *)rliza->key) * 2 + 1);
|
|
rstraddslashes((char *)rliza->key, escaped_key);
|
|
if (strlen(escaped_key) > size) {
|
|
size = strlen(escaped_key) + 10;
|
|
content = realloc(content, size);
|
|
}
|
|
sprintf(content, "\"%s\":[", escaped_key);
|
|
free(escaped_key);
|
|
} else
|
|
strcpy(content, "[");
|
|
for (unsigned i = 0; i < rliza->count; i++) {
|
|
char *content_chunk = rliza_dumps(rliza->content.map[i]);
|
|
char *content_chunk_stripped = content_chunk;
|
|
if (*content_chunk_stripped == '{') {
|
|
// content_chunk_stripped++;
|
|
// content_chunk_stripped[strlen(content_chunk_stripped) - 1] = 0;
|
|
}
|
|
if (strlen(content_chunk_stripped) + strlen(content) > size) {
|
|
size += strlen(content_chunk_stripped) + 20;
|
|
content = realloc(content, size);
|
|
}
|
|
strcat(content, content_chunk_stripped);
|
|
free(content_chunk);
|
|
strcat(content, ",");
|
|
}
|
|
if (content[strlen(content) - 1] != '[')
|
|
content[strlen(content) - 1] = 0;
|
|
strcat(content, "]");
|
|
} else if (rliza->type == RLIZA_NULL) {
|
|
|
|
if (rliza->key) {
|
|
char *escaped_key = (char *)malloc(strlen((char *)rliza->key) * 2 + 1);
|
|
rstraddslashes((char *)rliza->key, escaped_key);
|
|
sprintf(content, "\"%s\":null", escaped_key);
|
|
free(escaped_key);
|
|
} else
|
|
strcpy(content, "null");
|
|
}
|
|
return content;
|
|
}
|
|
|
|
void rliza_dumpss(rliza_t *rliza) {
|
|
char *output = rliza_dumps(rliza);
|
|
printf("%s\n", output);
|
|
free(output);
|
|
}
|
|
|
|
void rliza_push(rliza_t *self, rliza_t *obj) { rliza_push_object(self, obj); }
|
|
|
|
int rliza_validate(char *json_content) {
|
|
if (!json_content || !*json_content) {
|
|
return false;
|
|
}
|
|
char *json_contentp = json_content;
|
|
rliza_t *to_object = _rliza_loads(&json_contentp);
|
|
if (to_object) {
|
|
rliza_free(to_object);
|
|
return json_contentp - json_content;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#endif
|