Host driver/HAL to build a LoRa Picocell Gateway which communicates through USB with a concentrator board based on Semtech SX1308 multi-channel modem and SX1257/SX1255 RF transceivers.

Committer:
dgabino
Date:
Wed Apr 11 14:38:42 2018 +0000
Revision:
0:102b50f941d0
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dgabino 0:102b50f941d0 1 /*
dgabino 0:102b50f941d0 2 Parson ( http://kgabis.github.com/parson/ )
dgabino 0:102b50f941d0 3 Copyright (c) 2012 - 2016 Krzysztof Gabis
dgabino 0:102b50f941d0 4
dgabino 0:102b50f941d0 5 Permission is hereby granted, free of charge, to any person obtaining a copy
dgabino 0:102b50f941d0 6 of this software and associated documentation files (the "Software"), to deal
dgabino 0:102b50f941d0 7 in the Software without restriction, including without limitation the rights
dgabino 0:102b50f941d0 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
dgabino 0:102b50f941d0 9 copies of the Software, and to permit persons to whom the Software is
dgabino 0:102b50f941d0 10 furnished to do so, subject to the following conditions:
dgabino 0:102b50f941d0 11
dgabino 0:102b50f941d0 12 The above copyright notice and this permission notice shall be included in
dgabino 0:102b50f941d0 13 all copies or substantial portions of the Software.
dgabino 0:102b50f941d0 14
dgabino 0:102b50f941d0 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
dgabino 0:102b50f941d0 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
dgabino 0:102b50f941d0 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
dgabino 0:102b50f941d0 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
dgabino 0:102b50f941d0 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
dgabino 0:102b50f941d0 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
dgabino 0:102b50f941d0 21 THE SOFTWARE.
dgabino 0:102b50f941d0 22 */
dgabino 0:102b50f941d0 23 #ifdef _MSC_VER
dgabino 0:102b50f941d0 24 #define _CRT_SECURE_NO_WARNINGS
dgabino 0:102b50f941d0 25 #endif
dgabino 0:102b50f941d0 26
dgabino 0:102b50f941d0 27 #include "parson.h"
dgabino 0:102b50f941d0 28
dgabino 0:102b50f941d0 29 #include <stdio.h>
dgabino 0:102b50f941d0 30 #include <stdlib.h>
dgabino 0:102b50f941d0 31 #include <string.h>
dgabino 0:102b50f941d0 32 #include <ctype.h>
dgabino 0:102b50f941d0 33 #include <math.h>
dgabino 0:102b50f941d0 34
dgabino 0:102b50f941d0 35 #define STARTING_CAPACITY 15
dgabino 0:102b50f941d0 36 #define ARRAY_MAX_CAPACITY 122880 /* 15*(2^13) */
dgabino 0:102b50f941d0 37 #define OBJECT_MAX_CAPACITY 960 /* 15*(2^6) */
dgabino 0:102b50f941d0 38 #define MAX_NESTING 19
dgabino 0:102b50f941d0 39 #define DOUBLE_SERIALIZATION_FORMAT "%f"
dgabino 0:102b50f941d0 40
dgabino 0:102b50f941d0 41 #define SIZEOF_TOKEN(a) (sizeof(a) - 1)
dgabino 0:102b50f941d0 42 #define SKIP_CHAR(str) ((*str)++)
dgabino 0:102b50f941d0 43 #define SKIP_WHITESPACES(str) while (isspace(**str)) { SKIP_CHAR(str); }
dgabino 0:102b50f941d0 44 #define MAX(a, b) ((a) > (b) ? (a) : (b))
dgabino 0:102b50f941d0 45
dgabino 0:102b50f941d0 46 #undef malloc
dgabino 0:102b50f941d0 47 #undef free
dgabino 0:102b50f941d0 48
dgabino 0:102b50f941d0 49 static JSON_Malloc_Function parson_malloc = malloc;
dgabino 0:102b50f941d0 50 static JSON_Free_Function parson_free = free;
dgabino 0:102b50f941d0 51
dgabino 0:102b50f941d0 52 #define IS_CONT(b) (((unsigned char)(b) & 0xC0) == 0x80) /* is utf-8 continuation byte */
dgabino 0:102b50f941d0 53
dgabino 0:102b50f941d0 54 /* Type definitions */
dgabino 0:102b50f941d0 55 typedef union json_value_value {
dgabino 0:102b50f941d0 56 char *string;
dgabino 0:102b50f941d0 57 double number;
dgabino 0:102b50f941d0 58 JSON_Object *object;
dgabino 0:102b50f941d0 59 JSON_Array *array;
dgabino 0:102b50f941d0 60 int boolean;
dgabino 0:102b50f941d0 61 int null;
dgabino 0:102b50f941d0 62 } JSON_Value_Value;
dgabino 0:102b50f941d0 63
dgabino 0:102b50f941d0 64 struct json_value_t {
dgabino 0:102b50f941d0 65 JSON_Value_Type type;
dgabino 0:102b50f941d0 66 JSON_Value_Value value;
dgabino 0:102b50f941d0 67 };
dgabino 0:102b50f941d0 68
dgabino 0:102b50f941d0 69 struct json_object_t {
dgabino 0:102b50f941d0 70 char **names;
dgabino 0:102b50f941d0 71 JSON_Value **values;
dgabino 0:102b50f941d0 72 size_t count;
dgabino 0:102b50f941d0 73 size_t capacity;
dgabino 0:102b50f941d0 74 };
dgabino 0:102b50f941d0 75
dgabino 0:102b50f941d0 76 struct json_array_t {
dgabino 0:102b50f941d0 77 JSON_Value **items;
dgabino 0:102b50f941d0 78 size_t count;
dgabino 0:102b50f941d0 79 size_t capacity;
dgabino 0:102b50f941d0 80 };
dgabino 0:102b50f941d0 81
dgabino 0:102b50f941d0 82 /* Various */
dgabino 0:102b50f941d0 83 static char * read_file(const char *filename);
dgabino 0:102b50f941d0 84 static void remove_comments(char *string, const char *start_token, const char *end_token);
dgabino 0:102b50f941d0 85 static char * parson_strndup(const char *string, size_t n);
dgabino 0:102b50f941d0 86 static char * parson_strdup(const char *string);
dgabino 0:102b50f941d0 87 static int is_utf16_hex(const unsigned char *string);
dgabino 0:102b50f941d0 88 static int num_bytes_in_utf8_sequence(unsigned char c);
dgabino 0:102b50f941d0 89 static int verify_utf8_sequence(const unsigned char *string, int *len);
dgabino 0:102b50f941d0 90 static int is_valid_utf8(const char *string, size_t string_len);
dgabino 0:102b50f941d0 91 static int is_decimal(const char *string, size_t length);
dgabino 0:102b50f941d0 92
dgabino 0:102b50f941d0 93 /* JSON Object */
dgabino 0:102b50f941d0 94 static JSON_Object * json_object_init(void);
dgabino 0:102b50f941d0 95 static JSON_Status json_object_add(JSON_Object *object, const char *name, JSON_Value *value);
dgabino 0:102b50f941d0 96 static JSON_Status json_object_resize(JSON_Object *object, size_t new_capacity);
dgabino 0:102b50f941d0 97 static JSON_Value * json_object_nget_value(const JSON_Object *object, const char *name, size_t n);
dgabino 0:102b50f941d0 98 static void json_object_free(JSON_Object *object);
dgabino 0:102b50f941d0 99
dgabino 0:102b50f941d0 100 /* JSON Array */
dgabino 0:102b50f941d0 101 static JSON_Array * json_array_init(void);
dgabino 0:102b50f941d0 102 static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value);
dgabino 0:102b50f941d0 103 static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity);
dgabino 0:102b50f941d0 104 static void json_array_free(JSON_Array *array);
dgabino 0:102b50f941d0 105
dgabino 0:102b50f941d0 106 /* JSON Value */
dgabino 0:102b50f941d0 107 static JSON_Value * json_value_init_string_no_copy(char *string);
dgabino 0:102b50f941d0 108
dgabino 0:102b50f941d0 109 /* Parser */
dgabino 0:102b50f941d0 110 static void skip_quotes(const char **string);
dgabino 0:102b50f941d0 111 static int parse_utf_16(const char **unprocessed, char **processed);
dgabino 0:102b50f941d0 112 static char * process_string(const char *input, size_t len);
dgabino 0:102b50f941d0 113 static char * get_quoted_string(const char **string);
dgabino 0:102b50f941d0 114 static JSON_Value * parse_object_value(const char **string, size_t nesting);
dgabino 0:102b50f941d0 115 static JSON_Value * parse_array_value(const char **string, size_t nesting);
dgabino 0:102b50f941d0 116 static JSON_Value * parse_string_value(const char **string);
dgabino 0:102b50f941d0 117 static JSON_Value * parse_boolean_value(const char **string);
dgabino 0:102b50f941d0 118 static JSON_Value * parse_number_value(const char **string);
dgabino 0:102b50f941d0 119 static JSON_Value * parse_null_value(const char **string);
dgabino 0:102b50f941d0 120 static JSON_Value * parse_value(const char **string, size_t nesting);
dgabino 0:102b50f941d0 121
dgabino 0:102b50f941d0 122 /* Serialization */
dgabino 0:102b50f941d0 123 static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf);
dgabino 0:102b50f941d0 124 static int json_serialize_string(const char *string, char *buf);
dgabino 0:102b50f941d0 125 static int append_indent(char *buf, int level);
dgabino 0:102b50f941d0 126 static int append_string(char *buf, const char *string);
dgabino 0:102b50f941d0 127
dgabino 0:102b50f941d0 128 /* Various */
dgabino 0:102b50f941d0 129 static char * parson_strndup(const char *string, size_t n) {
dgabino 0:102b50f941d0 130 char *output_string = (char*)parson_malloc(n + 1);
dgabino 0:102b50f941d0 131 if (!output_string) {
dgabino 0:102b50f941d0 132 return NULL;
dgabino 0:102b50f941d0 133 }
dgabino 0:102b50f941d0 134 output_string[n] = '\0';
dgabino 0:102b50f941d0 135 strncpy(output_string, string, n);
dgabino 0:102b50f941d0 136 return output_string;
dgabino 0:102b50f941d0 137 }
dgabino 0:102b50f941d0 138
dgabino 0:102b50f941d0 139 static char * parson_strdup(const char *string) {
dgabino 0:102b50f941d0 140 return parson_strndup(string, strlen(string));
dgabino 0:102b50f941d0 141 }
dgabino 0:102b50f941d0 142
dgabino 0:102b50f941d0 143 static int is_utf16_hex(const unsigned char *s) {
dgabino 0:102b50f941d0 144 return isxdigit(s[0]) && isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]);
dgabino 0:102b50f941d0 145 }
dgabino 0:102b50f941d0 146
dgabino 0:102b50f941d0 147 static int num_bytes_in_utf8_sequence(unsigned char c) {
dgabino 0:102b50f941d0 148 if (c == 0xC0 || c == 0xC1 || c > 0xF4 || IS_CONT(c)) {
dgabino 0:102b50f941d0 149 return 0;
dgabino 0:102b50f941d0 150 } else if ((c & 0x80) == 0) { /* 0xxxxxxx */
dgabino 0:102b50f941d0 151 return 1;
dgabino 0:102b50f941d0 152 } else if ((c & 0xE0) == 0xC0) { /* 110xxxxx */
dgabino 0:102b50f941d0 153 return 2;
dgabino 0:102b50f941d0 154 } else if ((c & 0xF0) == 0xE0) { /* 1110xxxx */
dgabino 0:102b50f941d0 155 return 3;
dgabino 0:102b50f941d0 156 } else if ((c & 0xF8) == 0xF0) { /* 11110xxx */
dgabino 0:102b50f941d0 157 return 4;
dgabino 0:102b50f941d0 158 }
dgabino 0:102b50f941d0 159 return 0; /* won't happen */
dgabino 0:102b50f941d0 160 }
dgabino 0:102b50f941d0 161
dgabino 0:102b50f941d0 162 static int verify_utf8_sequence(const unsigned char *string, int *len) {
dgabino 0:102b50f941d0 163 unsigned int cp = 0;
dgabino 0:102b50f941d0 164 *len = num_bytes_in_utf8_sequence(string[0]);
dgabino 0:102b50f941d0 165
dgabino 0:102b50f941d0 166 if (*len == 1) {
dgabino 0:102b50f941d0 167 cp = string[0];
dgabino 0:102b50f941d0 168 } else if (*len == 2 && IS_CONT(string[1])) {
dgabino 0:102b50f941d0 169 cp = string[0] & 0x1F;
dgabino 0:102b50f941d0 170 cp = (cp << 6) | (string[1] & 0x3F);
dgabino 0:102b50f941d0 171 } else if (*len == 3 && IS_CONT(string[1]) && IS_CONT(string[2])) {
dgabino 0:102b50f941d0 172 cp = ((unsigned char)string[0]) & 0xF;
dgabino 0:102b50f941d0 173 cp = (cp << 6) | (string[1] & 0x3F);
dgabino 0:102b50f941d0 174 cp = (cp << 6) | (string[2] & 0x3F);
dgabino 0:102b50f941d0 175 } else if (*len == 4 && IS_CONT(string[1]) && IS_CONT(string[2]) && IS_CONT(string[3])) {
dgabino 0:102b50f941d0 176 cp = string[0] & 0x7;
dgabino 0:102b50f941d0 177 cp = (cp << 6) | (string[1] & 0x3F);
dgabino 0:102b50f941d0 178 cp = (cp << 6) | (string[2] & 0x3F);
dgabino 0:102b50f941d0 179 cp = (cp << 6) | (string[3] & 0x3F);
dgabino 0:102b50f941d0 180 } else {
dgabino 0:102b50f941d0 181 return 0;
dgabino 0:102b50f941d0 182 }
dgabino 0:102b50f941d0 183
dgabino 0:102b50f941d0 184 /* overlong encodings */
dgabino 0:102b50f941d0 185 if ((cp < 0x80 && *len > 1) ||
dgabino 0:102b50f941d0 186 (cp < 0x800 && *len > 2) ||
dgabino 0:102b50f941d0 187 (cp < 0x10000 && *len > 3)) {
dgabino 0:102b50f941d0 188 return 0;
dgabino 0:102b50f941d0 189 }
dgabino 0:102b50f941d0 190
dgabino 0:102b50f941d0 191 /* invalid unicode */
dgabino 0:102b50f941d0 192 if (cp > 0x10FFFF) {
dgabino 0:102b50f941d0 193 return 0;
dgabino 0:102b50f941d0 194 }
dgabino 0:102b50f941d0 195
dgabino 0:102b50f941d0 196 /* surrogate halves */
dgabino 0:102b50f941d0 197 if (cp >= 0xD800 && cp <= 0xDFFF) {
dgabino 0:102b50f941d0 198 return 0;
dgabino 0:102b50f941d0 199 }
dgabino 0:102b50f941d0 200
dgabino 0:102b50f941d0 201 return 1;
dgabino 0:102b50f941d0 202 }
dgabino 0:102b50f941d0 203
dgabino 0:102b50f941d0 204 static int is_valid_utf8(const char *string, size_t string_len) {
dgabino 0:102b50f941d0 205 int len = 0;
dgabino 0:102b50f941d0 206 const char *string_end = string + string_len;
dgabino 0:102b50f941d0 207 while (string < string_end) {
dgabino 0:102b50f941d0 208 if (!verify_utf8_sequence((const unsigned char*)string, &len)) {
dgabino 0:102b50f941d0 209 return 0;
dgabino 0:102b50f941d0 210 }
dgabino 0:102b50f941d0 211 string += len;
dgabino 0:102b50f941d0 212 }
dgabino 0:102b50f941d0 213 return 1;
dgabino 0:102b50f941d0 214 }
dgabino 0:102b50f941d0 215
dgabino 0:102b50f941d0 216 static int is_decimal(const char *string, size_t length) {
dgabino 0:102b50f941d0 217 if (length > 1 && string[0] == '0' && string[1] != '.') {
dgabino 0:102b50f941d0 218 return 0;
dgabino 0:102b50f941d0 219 }
dgabino 0:102b50f941d0 220 if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.') {
dgabino 0:102b50f941d0 221 return 0;
dgabino 0:102b50f941d0 222 }
dgabino 0:102b50f941d0 223 while (length--)
dgabino 0:102b50f941d0 224 if (strchr("xX", string[length])) {
dgabino 0:102b50f941d0 225 return 0;
dgabino 0:102b50f941d0 226 }
dgabino 0:102b50f941d0 227 return 1;
dgabino 0:102b50f941d0 228 }
dgabino 0:102b50f941d0 229
dgabino 0:102b50f941d0 230 static char * read_file(const char * filename) {
dgabino 0:102b50f941d0 231 FILE *fp = fopen(filename, "r");
dgabino 0:102b50f941d0 232 size_t file_size;
dgabino 0:102b50f941d0 233 long pos;
dgabino 0:102b50f941d0 234 char *file_contents;
dgabino 0:102b50f941d0 235 if (!fp) {
dgabino 0:102b50f941d0 236 return NULL;
dgabino 0:102b50f941d0 237 }
dgabino 0:102b50f941d0 238 fseek(fp, 0L, SEEK_END);
dgabino 0:102b50f941d0 239 pos = ftell(fp);
dgabino 0:102b50f941d0 240 if (pos < 0) {
dgabino 0:102b50f941d0 241 fclose(fp);
dgabino 0:102b50f941d0 242 return NULL;
dgabino 0:102b50f941d0 243 }
dgabino 0:102b50f941d0 244 file_size = pos;
dgabino 0:102b50f941d0 245 rewind(fp);
dgabino 0:102b50f941d0 246 file_contents = (char*)parson_malloc(sizeof(char) * (file_size + 1));
dgabino 0:102b50f941d0 247 if (!file_contents) {
dgabino 0:102b50f941d0 248 fclose(fp);
dgabino 0:102b50f941d0 249 return NULL;
dgabino 0:102b50f941d0 250 }
dgabino 0:102b50f941d0 251 if (fread(file_contents, file_size, 1, fp) < 1) {
dgabino 0:102b50f941d0 252 if (ferror(fp)) {
dgabino 0:102b50f941d0 253 fclose(fp);
dgabino 0:102b50f941d0 254 parson_free(file_contents);
dgabino 0:102b50f941d0 255 return NULL;
dgabino 0:102b50f941d0 256 }
dgabino 0:102b50f941d0 257 }
dgabino 0:102b50f941d0 258 fclose(fp);
dgabino 0:102b50f941d0 259 file_contents[file_size] = '\0';
dgabino 0:102b50f941d0 260 return file_contents;
dgabino 0:102b50f941d0 261 }
dgabino 0:102b50f941d0 262
dgabino 0:102b50f941d0 263 static void remove_comments(char *string, const char *start_token, const char *end_token) {
dgabino 0:102b50f941d0 264 int in_string = 0, escaped = 0;
dgabino 0:102b50f941d0 265 size_t i;
dgabino 0:102b50f941d0 266 char *ptr = NULL, current_char;
dgabino 0:102b50f941d0 267 size_t start_token_len = strlen(start_token);
dgabino 0:102b50f941d0 268 size_t end_token_len = strlen(end_token);
dgabino 0:102b50f941d0 269 if (start_token_len == 0 || end_token_len == 0) {
dgabino 0:102b50f941d0 270 return;
dgabino 0:102b50f941d0 271 }
dgabino 0:102b50f941d0 272 while ((current_char = *string) != '\0') {
dgabino 0:102b50f941d0 273 if (current_char == '\\' && !escaped) {
dgabino 0:102b50f941d0 274 escaped = 1;
dgabino 0:102b50f941d0 275 string++;
dgabino 0:102b50f941d0 276 continue;
dgabino 0:102b50f941d0 277 } else if (current_char == '\"' && !escaped) {
dgabino 0:102b50f941d0 278 in_string = !in_string;
dgabino 0:102b50f941d0 279 } else if (!in_string && strncmp(string, start_token, start_token_len) == 0) {
dgabino 0:102b50f941d0 280 for(i = 0; i < start_token_len; i++) {
dgabino 0:102b50f941d0 281 string[i] = ' ';
dgabino 0:102b50f941d0 282 }
dgabino 0:102b50f941d0 283 string = string + start_token_len;
dgabino 0:102b50f941d0 284 ptr = strstr(string, end_token);
dgabino 0:102b50f941d0 285 if (!ptr) {
dgabino 0:102b50f941d0 286 return;
dgabino 0:102b50f941d0 287 }
dgabino 0:102b50f941d0 288 for (i = 0; i < (ptr - string) + end_token_len; i++) {
dgabino 0:102b50f941d0 289 string[i] = ' ';
dgabino 0:102b50f941d0 290 }
dgabino 0:102b50f941d0 291 string = ptr + end_token_len - 1;
dgabino 0:102b50f941d0 292 }
dgabino 0:102b50f941d0 293 escaped = 0;
dgabino 0:102b50f941d0 294 string++;
dgabino 0:102b50f941d0 295 }
dgabino 0:102b50f941d0 296 }
dgabino 0:102b50f941d0 297
dgabino 0:102b50f941d0 298 /* JSON Object */
dgabino 0:102b50f941d0 299 static JSON_Object * json_object_init(void) {
dgabino 0:102b50f941d0 300 JSON_Object *new_obj = (JSON_Object*)parson_malloc(sizeof(JSON_Object));
dgabino 0:102b50f941d0 301 if (!new_obj) {
dgabino 0:102b50f941d0 302 return NULL;
dgabino 0:102b50f941d0 303 }
dgabino 0:102b50f941d0 304 new_obj->names = (char**)NULL;
dgabino 0:102b50f941d0 305 new_obj->values = (JSON_Value**)NULL;
dgabino 0:102b50f941d0 306 new_obj->capacity = 0;
dgabino 0:102b50f941d0 307 new_obj->count = 0;
dgabino 0:102b50f941d0 308 return new_obj;
dgabino 0:102b50f941d0 309 }
dgabino 0:102b50f941d0 310
dgabino 0:102b50f941d0 311 static JSON_Status json_object_add(JSON_Object *object, const char *name, JSON_Value *value) {
dgabino 0:102b50f941d0 312 size_t index = 0;
dgabino 0:102b50f941d0 313 if (object == NULL || name == NULL || value == NULL) {
dgabino 0:102b50f941d0 314 return JSONFailure;
dgabino 0:102b50f941d0 315 }
dgabino 0:102b50f941d0 316 if (object->count >= object->capacity) {
dgabino 0:102b50f941d0 317 size_t new_capacity = MAX(object->capacity * 2, STARTING_CAPACITY);
dgabino 0:102b50f941d0 318 if (new_capacity > OBJECT_MAX_CAPACITY) {
dgabino 0:102b50f941d0 319 return JSONFailure;
dgabino 0:102b50f941d0 320 }
dgabino 0:102b50f941d0 321 if (json_object_resize(object, new_capacity) == JSONFailure) {
dgabino 0:102b50f941d0 322 return JSONFailure;
dgabino 0:102b50f941d0 323 }
dgabino 0:102b50f941d0 324 }
dgabino 0:102b50f941d0 325 if (json_object_get_value(object, name) != NULL) {
dgabino 0:102b50f941d0 326 return JSONFailure;
dgabino 0:102b50f941d0 327 }
dgabino 0:102b50f941d0 328 index = object->count;
dgabino 0:102b50f941d0 329 object->names[index] = parson_strdup(name);
dgabino 0:102b50f941d0 330 if (object->names[index] == NULL) {
dgabino 0:102b50f941d0 331 return JSONFailure;
dgabino 0:102b50f941d0 332 }
dgabino 0:102b50f941d0 333 object->values[index] = value;
dgabino 0:102b50f941d0 334 object->count++;
dgabino 0:102b50f941d0 335 return JSONSuccess;
dgabino 0:102b50f941d0 336 }
dgabino 0:102b50f941d0 337
dgabino 0:102b50f941d0 338 static JSON_Status json_object_resize(JSON_Object *object, size_t new_capacity) {
dgabino 0:102b50f941d0 339 char **temp_names = NULL;
dgabino 0:102b50f941d0 340 JSON_Value **temp_values = NULL;
dgabino 0:102b50f941d0 341
dgabino 0:102b50f941d0 342 if ((object->names == NULL && object->values != NULL) ||
dgabino 0:102b50f941d0 343 (object->names != NULL && object->values == NULL) ||
dgabino 0:102b50f941d0 344 new_capacity == 0) {
dgabino 0:102b50f941d0 345 return JSONFailure; /* Shouldn't happen */
dgabino 0:102b50f941d0 346 }
dgabino 0:102b50f941d0 347
dgabino 0:102b50f941d0 348 temp_names = (char**)parson_malloc(new_capacity * sizeof(char*));
dgabino 0:102b50f941d0 349 if (temp_names == NULL) {
dgabino 0:102b50f941d0 350 return JSONFailure;
dgabino 0:102b50f941d0 351 }
dgabino 0:102b50f941d0 352
dgabino 0:102b50f941d0 353 temp_values = (JSON_Value**)parson_malloc(new_capacity * sizeof(JSON_Value*));
dgabino 0:102b50f941d0 354 if (temp_values == NULL) {
dgabino 0:102b50f941d0 355 parson_free(temp_names);
dgabino 0:102b50f941d0 356 return JSONFailure;
dgabino 0:102b50f941d0 357 }
dgabino 0:102b50f941d0 358
dgabino 0:102b50f941d0 359 if (object->names != NULL && object->values != NULL && object->count > 0) {
dgabino 0:102b50f941d0 360 memcpy(temp_names, object->names, object->count * sizeof(char*));
dgabino 0:102b50f941d0 361 memcpy(temp_values, object->values, object->count * sizeof(JSON_Value*));
dgabino 0:102b50f941d0 362 }
dgabino 0:102b50f941d0 363 parson_free(object->names);
dgabino 0:102b50f941d0 364 parson_free(object->values);
dgabino 0:102b50f941d0 365 object->names = temp_names;
dgabino 0:102b50f941d0 366 object->values = temp_values;
dgabino 0:102b50f941d0 367 object->capacity = new_capacity;
dgabino 0:102b50f941d0 368 return JSONSuccess;
dgabino 0:102b50f941d0 369 }
dgabino 0:102b50f941d0 370
dgabino 0:102b50f941d0 371 static JSON_Value * json_object_nget_value(const JSON_Object *object, const char *name, size_t n) {
dgabino 0:102b50f941d0 372 size_t i, name_length;
dgabino 0:102b50f941d0 373 for (i = 0; i < json_object_get_count(object); i++) {
dgabino 0:102b50f941d0 374 name_length = strlen(object->names[i]);
dgabino 0:102b50f941d0 375 if (name_length != n) {
dgabino 0:102b50f941d0 376 continue;
dgabino 0:102b50f941d0 377 }
dgabino 0:102b50f941d0 378 if (strncmp(object->names[i], name, n) == 0) {
dgabino 0:102b50f941d0 379 return object->values[i];
dgabino 0:102b50f941d0 380 }
dgabino 0:102b50f941d0 381 }
dgabino 0:102b50f941d0 382 return NULL;
dgabino 0:102b50f941d0 383 }
dgabino 0:102b50f941d0 384
dgabino 0:102b50f941d0 385 static void json_object_free(JSON_Object *object) {
dgabino 0:102b50f941d0 386 while(object->count--) {
dgabino 0:102b50f941d0 387 parson_free(object->names[object->count]);
dgabino 0:102b50f941d0 388 json_value_free(object->values[object->count]);
dgabino 0:102b50f941d0 389 }
dgabino 0:102b50f941d0 390 parson_free(object->names);
dgabino 0:102b50f941d0 391 parson_free(object->values);
dgabino 0:102b50f941d0 392 parson_free(object);
dgabino 0:102b50f941d0 393 }
dgabino 0:102b50f941d0 394
dgabino 0:102b50f941d0 395 /* JSON Array */
dgabino 0:102b50f941d0 396 static JSON_Array * json_array_init(void) {
dgabino 0:102b50f941d0 397 JSON_Array *new_array = (JSON_Array*)parson_malloc(sizeof(JSON_Array));
dgabino 0:102b50f941d0 398 if (!new_array) {
dgabino 0:102b50f941d0 399 return NULL;
dgabino 0:102b50f941d0 400 }
dgabino 0:102b50f941d0 401 new_array->items = (JSON_Value**)NULL;
dgabino 0:102b50f941d0 402 new_array->capacity = 0;
dgabino 0:102b50f941d0 403 new_array->count = 0;
dgabino 0:102b50f941d0 404 return new_array;
dgabino 0:102b50f941d0 405 }
dgabino 0:102b50f941d0 406
dgabino 0:102b50f941d0 407 static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value) {
dgabino 0:102b50f941d0 408 if (array->count >= array->capacity) {
dgabino 0:102b50f941d0 409 size_t new_capacity = MAX(array->capacity * 2, STARTING_CAPACITY);
dgabino 0:102b50f941d0 410 if (new_capacity > ARRAY_MAX_CAPACITY) {
dgabino 0:102b50f941d0 411 return JSONFailure;
dgabino 0:102b50f941d0 412 }
dgabino 0:102b50f941d0 413 if (json_array_resize(array, new_capacity) == JSONFailure) {
dgabino 0:102b50f941d0 414 return JSONFailure;
dgabino 0:102b50f941d0 415 }
dgabino 0:102b50f941d0 416 }
dgabino 0:102b50f941d0 417 array->items[array->count] = value;
dgabino 0:102b50f941d0 418 array->count++;
dgabino 0:102b50f941d0 419 return JSONSuccess;
dgabino 0:102b50f941d0 420 }
dgabino 0:102b50f941d0 421
dgabino 0:102b50f941d0 422 static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity) {
dgabino 0:102b50f941d0 423 JSON_Value **new_items = NULL;
dgabino 0:102b50f941d0 424 if (new_capacity == 0) {
dgabino 0:102b50f941d0 425 return JSONFailure;
dgabino 0:102b50f941d0 426 }
dgabino 0:102b50f941d0 427 new_items = (JSON_Value**)parson_malloc(new_capacity * sizeof(JSON_Value*));
dgabino 0:102b50f941d0 428 if (new_items == NULL) {
dgabino 0:102b50f941d0 429 return JSONFailure;
dgabino 0:102b50f941d0 430 }
dgabino 0:102b50f941d0 431 if (array->items != NULL && array->count > 0) {
dgabino 0:102b50f941d0 432 memcpy(new_items, array->items, array->count * sizeof(JSON_Value*));
dgabino 0:102b50f941d0 433 }
dgabino 0:102b50f941d0 434 parson_free(array->items);
dgabino 0:102b50f941d0 435 array->items = new_items;
dgabino 0:102b50f941d0 436 array->capacity = new_capacity;
dgabino 0:102b50f941d0 437 return JSONSuccess;
dgabino 0:102b50f941d0 438 }
dgabino 0:102b50f941d0 439
dgabino 0:102b50f941d0 440 static void json_array_free(JSON_Array *array) {
dgabino 0:102b50f941d0 441 while (array->count--) {
dgabino 0:102b50f941d0 442 json_value_free(array->items[array->count]);
dgabino 0:102b50f941d0 443 }
dgabino 0:102b50f941d0 444 parson_free(array->items);
dgabino 0:102b50f941d0 445 parson_free(array);
dgabino 0:102b50f941d0 446 }
dgabino 0:102b50f941d0 447
dgabino 0:102b50f941d0 448 /* JSON Value */
dgabino 0:102b50f941d0 449 static JSON_Value * json_value_init_string_no_copy(char *string) {
dgabino 0:102b50f941d0 450 JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
dgabino 0:102b50f941d0 451 if (!new_value) {
dgabino 0:102b50f941d0 452 return NULL;
dgabino 0:102b50f941d0 453 }
dgabino 0:102b50f941d0 454 new_value->type = JSONString;
dgabino 0:102b50f941d0 455 new_value->value.string = string;
dgabino 0:102b50f941d0 456 return new_value;
dgabino 0:102b50f941d0 457 }
dgabino 0:102b50f941d0 458
dgabino 0:102b50f941d0 459 /* Parser */
dgabino 0:102b50f941d0 460 static void skip_quotes(const char **string) {
dgabino 0:102b50f941d0 461 SKIP_CHAR(string);
dgabino 0:102b50f941d0 462 while (**string != '\"') {
dgabino 0:102b50f941d0 463 if (**string == '\0') {
dgabino 0:102b50f941d0 464 return;
dgabino 0:102b50f941d0 465 }
dgabino 0:102b50f941d0 466 if (**string == '\\') {
dgabino 0:102b50f941d0 467 SKIP_CHAR(string);
dgabino 0:102b50f941d0 468 if (**string == '\0') {
dgabino 0:102b50f941d0 469 return;
dgabino 0:102b50f941d0 470 }
dgabino 0:102b50f941d0 471 }
dgabino 0:102b50f941d0 472 SKIP_CHAR(string);
dgabino 0:102b50f941d0 473 }
dgabino 0:102b50f941d0 474 SKIP_CHAR(string);
dgabino 0:102b50f941d0 475 }
dgabino 0:102b50f941d0 476
dgabino 0:102b50f941d0 477 static int parse_utf_16(const char **unprocessed, char **processed) {
dgabino 0:102b50f941d0 478 unsigned int cp, lead, trail;
dgabino 0:102b50f941d0 479 char *processed_ptr = *processed;
dgabino 0:102b50f941d0 480 const char *unprocessed_ptr = *unprocessed;
dgabino 0:102b50f941d0 481 unprocessed_ptr++; /* skips u */
dgabino 0:102b50f941d0 482 if (!is_utf16_hex((const unsigned char*)unprocessed_ptr) || sscanf(unprocessed_ptr, "%4x", &cp) == EOF) {
dgabino 0:102b50f941d0 483 return JSONFailure;
dgabino 0:102b50f941d0 484 }
dgabino 0:102b50f941d0 485 if (cp < 0x80) {
dgabino 0:102b50f941d0 486 *processed_ptr = cp; /* 0xxxxxxx */
dgabino 0:102b50f941d0 487 } else if (cp < 0x800) {
dgabino 0:102b50f941d0 488 *processed_ptr++ = ((cp >> 6) & 0x1F) | 0xC0; /* 110xxxxx */
dgabino 0:102b50f941d0 489 *processed_ptr = ((cp ) & 0x3F) | 0x80; /* 10xxxxxx */
dgabino 0:102b50f941d0 490 } else if (cp < 0xD800 || cp > 0xDFFF) {
dgabino 0:102b50f941d0 491 *processed_ptr++ = ((cp >> 12) & 0x0F) | 0xE0; /* 1110xxxx */
dgabino 0:102b50f941d0 492 *processed_ptr++ = ((cp >> 6) & 0x3F) | 0x80; /* 10xxxxxx */
dgabino 0:102b50f941d0 493 *processed_ptr = ((cp ) & 0x3F) | 0x80; /* 10xxxxxx */
dgabino 0:102b50f941d0 494 } else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */
dgabino 0:102b50f941d0 495 lead = cp;
dgabino 0:102b50f941d0 496 unprocessed_ptr += 4; /* should always be within the buffer, otherwise previous sscanf would fail */
dgabino 0:102b50f941d0 497 if (*unprocessed_ptr++ != '\\' || *unprocessed_ptr++ != 'u' || /* starts with \u? */
dgabino 0:102b50f941d0 498 !is_utf16_hex((const unsigned char*)unprocessed_ptr) ||
dgabino 0:102b50f941d0 499 sscanf(unprocessed_ptr, "%4x", &trail) == EOF ||
dgabino 0:102b50f941d0 500 trail < 0xDC00 || trail > 0xDFFF) { /* valid trail surrogate? (0xDC00..0xDFFF) */
dgabino 0:102b50f941d0 501 return JSONFailure;
dgabino 0:102b50f941d0 502 }
dgabino 0:102b50f941d0 503 cp = ((((lead - 0xD800) & 0x3FF) << 10) | ((trail - 0xDC00) & 0x3FF)) + 0x010000;
dgabino 0:102b50f941d0 504 *processed_ptr++ = (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */
dgabino 0:102b50f941d0 505 *processed_ptr++ = (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */
dgabino 0:102b50f941d0 506 *processed_ptr++ = (((cp >> 6) & 0x3F) | 0x80); /* 10xxxxxx */
dgabino 0:102b50f941d0 507 *processed_ptr = (((cp ) & 0x3F) | 0x80); /* 10xxxxxx */
dgabino 0:102b50f941d0 508 } else { /* trail surrogate before lead surrogate */
dgabino 0:102b50f941d0 509 return JSONFailure;
dgabino 0:102b50f941d0 510 }
dgabino 0:102b50f941d0 511 unprocessed_ptr += 3;
dgabino 0:102b50f941d0 512 *processed = processed_ptr;
dgabino 0:102b50f941d0 513 *unprocessed = unprocessed_ptr;
dgabino 0:102b50f941d0 514 return JSONSuccess;
dgabino 0:102b50f941d0 515 }
dgabino 0:102b50f941d0 516
dgabino 0:102b50f941d0 517
dgabino 0:102b50f941d0 518 /* Copies and processes passed string up to supplied length.
dgabino 0:102b50f941d0 519 Example: "\u006Corem ipsum" -> lorem ipsum */
dgabino 0:102b50f941d0 520 static char* process_string(const char *input, size_t len) {
dgabino 0:102b50f941d0 521 const char *input_ptr = input;
dgabino 0:102b50f941d0 522 size_t initial_size = (len + 1) * sizeof(char);
dgabino 0:102b50f941d0 523 size_t final_size = 0;
dgabino 0:102b50f941d0 524 char *output = (char*)parson_malloc(initial_size);
dgabino 0:102b50f941d0 525 char *output_ptr = output;
dgabino 0:102b50f941d0 526 char *resized_output = NULL;
dgabino 0:102b50f941d0 527 while ((*input_ptr != '\0') && (size_t)(input_ptr - input) < len) {
dgabino 0:102b50f941d0 528 if (*input_ptr == '\\') {
dgabino 0:102b50f941d0 529 input_ptr++;
dgabino 0:102b50f941d0 530 switch (*input_ptr) {
dgabino 0:102b50f941d0 531 case '\"':
dgabino 0:102b50f941d0 532 *output_ptr = '\"';
dgabino 0:102b50f941d0 533 break;
dgabino 0:102b50f941d0 534 case '\\':
dgabino 0:102b50f941d0 535 *output_ptr = '\\';
dgabino 0:102b50f941d0 536 break;
dgabino 0:102b50f941d0 537 case '/':
dgabino 0:102b50f941d0 538 *output_ptr = '/';
dgabino 0:102b50f941d0 539 break;
dgabino 0:102b50f941d0 540 case 'b':
dgabino 0:102b50f941d0 541 *output_ptr = '\b';
dgabino 0:102b50f941d0 542 break;
dgabino 0:102b50f941d0 543 case 'f':
dgabino 0:102b50f941d0 544 *output_ptr = '\f';
dgabino 0:102b50f941d0 545 break;
dgabino 0:102b50f941d0 546 case 'n':
dgabino 0:102b50f941d0 547 *output_ptr = '\n';
dgabino 0:102b50f941d0 548 break;
dgabino 0:102b50f941d0 549 case 'r':
dgabino 0:102b50f941d0 550 *output_ptr = '\r';
dgabino 0:102b50f941d0 551 break;
dgabino 0:102b50f941d0 552 case 't':
dgabino 0:102b50f941d0 553 *output_ptr = '\t';
dgabino 0:102b50f941d0 554 break;
dgabino 0:102b50f941d0 555 case 'u':
dgabino 0:102b50f941d0 556 if (parse_utf_16(&input_ptr, &output_ptr) == JSONFailure) {
dgabino 0:102b50f941d0 557 goto error;
dgabino 0:102b50f941d0 558 }
dgabino 0:102b50f941d0 559 break;
dgabino 0:102b50f941d0 560 default:
dgabino 0:102b50f941d0 561 goto error;
dgabino 0:102b50f941d0 562 }
dgabino 0:102b50f941d0 563 } else if ((unsigned char)*input_ptr < 0x20) {
dgabino 0:102b50f941d0 564 goto error; /* 0x00-0x19 are invalid characters for json string (http://www.ietf.org/rfc/rfc4627.txt) */
dgabino 0:102b50f941d0 565 } else {
dgabino 0:102b50f941d0 566 *output_ptr = *input_ptr;
dgabino 0:102b50f941d0 567 }
dgabino 0:102b50f941d0 568 output_ptr++;
dgabino 0:102b50f941d0 569 input_ptr++;
dgabino 0:102b50f941d0 570 }
dgabino 0:102b50f941d0 571 *output_ptr = '\0';
dgabino 0:102b50f941d0 572 /* resize to new length */
dgabino 0:102b50f941d0 573 final_size = (size_t)(output_ptr - output) + 1;
dgabino 0:102b50f941d0 574 resized_output = (char*)parson_malloc(final_size);
dgabino 0:102b50f941d0 575 if (resized_output == NULL) {
dgabino 0:102b50f941d0 576 goto error;
dgabino 0:102b50f941d0 577 }
dgabino 0:102b50f941d0 578 memcpy(resized_output, output, final_size);
dgabino 0:102b50f941d0 579 parson_free(output);
dgabino 0:102b50f941d0 580 return resized_output;
dgabino 0:102b50f941d0 581 error:
dgabino 0:102b50f941d0 582 parson_free(output);
dgabino 0:102b50f941d0 583 return NULL;
dgabino 0:102b50f941d0 584 }
dgabino 0:102b50f941d0 585
dgabino 0:102b50f941d0 586 /* Return processed contents of a string between quotes and
dgabino 0:102b50f941d0 587 skips passed argument to a matching quote. */
dgabino 0:102b50f941d0 588 static char * get_quoted_string(const char **string) {
dgabino 0:102b50f941d0 589 const char *string_start = *string;
dgabino 0:102b50f941d0 590 size_t string_len = 0;
dgabino 0:102b50f941d0 591 skip_quotes(string);
dgabino 0:102b50f941d0 592 if (**string == '\0') {
dgabino 0:102b50f941d0 593 return NULL;
dgabino 0:102b50f941d0 594 }
dgabino 0:102b50f941d0 595 string_len = *string - string_start - 2; /* length without quotes */
dgabino 0:102b50f941d0 596 return process_string(string_start + 1, string_len);
dgabino 0:102b50f941d0 597 }
dgabino 0:102b50f941d0 598
dgabino 0:102b50f941d0 599 static JSON_Value * parse_value(const char **string, size_t nesting) {
dgabino 0:102b50f941d0 600 if (nesting > MAX_NESTING) {
dgabino 0:102b50f941d0 601 return NULL;
dgabino 0:102b50f941d0 602 }
dgabino 0:102b50f941d0 603 SKIP_WHITESPACES(string);
dgabino 0:102b50f941d0 604 switch (**string) {
dgabino 0:102b50f941d0 605 case '{':
dgabino 0:102b50f941d0 606 return parse_object_value(string, nesting + 1);
dgabino 0:102b50f941d0 607 case '[':
dgabino 0:102b50f941d0 608 return parse_array_value(string, nesting + 1);
dgabino 0:102b50f941d0 609 case '\"':
dgabino 0:102b50f941d0 610 return parse_string_value(string);
dgabino 0:102b50f941d0 611 case 'f':
dgabino 0:102b50f941d0 612 case 't':
dgabino 0:102b50f941d0 613 return parse_boolean_value(string);
dgabino 0:102b50f941d0 614 case '-':
dgabino 0:102b50f941d0 615 case '0':
dgabino 0:102b50f941d0 616 case '1':
dgabino 0:102b50f941d0 617 case '2':
dgabino 0:102b50f941d0 618 case '3':
dgabino 0:102b50f941d0 619 case '4':
dgabino 0:102b50f941d0 620 case '5':
dgabino 0:102b50f941d0 621 case '6':
dgabino 0:102b50f941d0 622 case '7':
dgabino 0:102b50f941d0 623 case '8':
dgabino 0:102b50f941d0 624 case '9':
dgabino 0:102b50f941d0 625 return parse_number_value(string);
dgabino 0:102b50f941d0 626 case 'n':
dgabino 0:102b50f941d0 627 return parse_null_value(string);
dgabino 0:102b50f941d0 628 default:
dgabino 0:102b50f941d0 629 return NULL;
dgabino 0:102b50f941d0 630 }
dgabino 0:102b50f941d0 631 }
dgabino 0:102b50f941d0 632
dgabino 0:102b50f941d0 633 static JSON_Value * parse_object_value(const char **string, size_t nesting) {
dgabino 0:102b50f941d0 634 JSON_Value *output_value = json_value_init_object(), *new_value = NULL;
dgabino 0:102b50f941d0 635 JSON_Object *output_object = json_value_get_object(output_value);
dgabino 0:102b50f941d0 636 char *new_key = NULL;
dgabino 0:102b50f941d0 637 if (output_value == NULL) {
dgabino 0:102b50f941d0 638 return NULL;
dgabino 0:102b50f941d0 639 }
dgabino 0:102b50f941d0 640 SKIP_CHAR(string);
dgabino 0:102b50f941d0 641 SKIP_WHITESPACES(string);
dgabino 0:102b50f941d0 642 if (**string == '}') { /* empty object */
dgabino 0:102b50f941d0 643 SKIP_CHAR(string);
dgabino 0:102b50f941d0 644 return output_value;
dgabino 0:102b50f941d0 645 }
dgabino 0:102b50f941d0 646 while (**string != '\0') {
dgabino 0:102b50f941d0 647 new_key = get_quoted_string(string);
dgabino 0:102b50f941d0 648 SKIP_WHITESPACES(string);
dgabino 0:102b50f941d0 649 if (new_key == NULL || **string != ':') {
dgabino 0:102b50f941d0 650 json_value_free(output_value);
dgabino 0:102b50f941d0 651 return NULL;
dgabino 0:102b50f941d0 652 }
dgabino 0:102b50f941d0 653 SKIP_CHAR(string);
dgabino 0:102b50f941d0 654 new_value = parse_value(string, nesting);
dgabino 0:102b50f941d0 655 if (new_value == NULL) {
dgabino 0:102b50f941d0 656 parson_free(new_key);
dgabino 0:102b50f941d0 657 json_value_free(output_value);
dgabino 0:102b50f941d0 658 return NULL;
dgabino 0:102b50f941d0 659 }
dgabino 0:102b50f941d0 660 if(json_object_add(output_object, new_key, new_value) == JSONFailure) {
dgabino 0:102b50f941d0 661 parson_free(new_key);
dgabino 0:102b50f941d0 662 parson_free(new_value);
dgabino 0:102b50f941d0 663 json_value_free(output_value);
dgabino 0:102b50f941d0 664 return NULL;
dgabino 0:102b50f941d0 665 }
dgabino 0:102b50f941d0 666 parson_free(new_key);
dgabino 0:102b50f941d0 667 SKIP_WHITESPACES(string);
dgabino 0:102b50f941d0 668 if (**string != ',') {
dgabino 0:102b50f941d0 669 break;
dgabino 0:102b50f941d0 670 }
dgabino 0:102b50f941d0 671 SKIP_CHAR(string);
dgabino 0:102b50f941d0 672 SKIP_WHITESPACES(string);
dgabino 0:102b50f941d0 673 }
dgabino 0:102b50f941d0 674 SKIP_WHITESPACES(string);
dgabino 0:102b50f941d0 675 if (**string != '}' || /* Trim object after parsing is over */
dgabino 0:102b50f941d0 676 json_object_resize(output_object, json_object_get_count(output_object)) == JSONFailure) {
dgabino 0:102b50f941d0 677 json_value_free(output_value);
dgabino 0:102b50f941d0 678 return NULL;
dgabino 0:102b50f941d0 679 }
dgabino 0:102b50f941d0 680 SKIP_CHAR(string);
dgabino 0:102b50f941d0 681 return output_value;
dgabino 0:102b50f941d0 682 }
dgabino 0:102b50f941d0 683
dgabino 0:102b50f941d0 684 static JSON_Value * parse_array_value(const char **string, size_t nesting) {
dgabino 0:102b50f941d0 685 JSON_Value *output_value = json_value_init_array(), *new_array_value = NULL;
dgabino 0:102b50f941d0 686 JSON_Array *output_array = json_value_get_array(output_value);
dgabino 0:102b50f941d0 687 if (!output_value) {
dgabino 0:102b50f941d0 688 return NULL;
dgabino 0:102b50f941d0 689 }
dgabino 0:102b50f941d0 690 SKIP_CHAR(string);
dgabino 0:102b50f941d0 691 SKIP_WHITESPACES(string);
dgabino 0:102b50f941d0 692 if (**string == ']') { /* empty array */
dgabino 0:102b50f941d0 693 SKIP_CHAR(string);
dgabino 0:102b50f941d0 694 return output_value;
dgabino 0:102b50f941d0 695 }
dgabino 0:102b50f941d0 696 while (**string != '\0') {
dgabino 0:102b50f941d0 697 new_array_value = parse_value(string, nesting);
dgabino 0:102b50f941d0 698 if (!new_array_value) {
dgabino 0:102b50f941d0 699 json_value_free(output_value);
dgabino 0:102b50f941d0 700 return NULL;
dgabino 0:102b50f941d0 701 }
dgabino 0:102b50f941d0 702 if(json_array_add(output_array, new_array_value) == JSONFailure) {
dgabino 0:102b50f941d0 703 parson_free(new_array_value);
dgabino 0:102b50f941d0 704 json_value_free(output_value);
dgabino 0:102b50f941d0 705 return NULL;
dgabino 0:102b50f941d0 706 }
dgabino 0:102b50f941d0 707 SKIP_WHITESPACES(string);
dgabino 0:102b50f941d0 708 if (**string != ',') {
dgabino 0:102b50f941d0 709 break;
dgabino 0:102b50f941d0 710 }
dgabino 0:102b50f941d0 711 SKIP_CHAR(string);
dgabino 0:102b50f941d0 712 SKIP_WHITESPACES(string);
dgabino 0:102b50f941d0 713 }
dgabino 0:102b50f941d0 714 SKIP_WHITESPACES(string);
dgabino 0:102b50f941d0 715 if (**string != ']' || /* Trim array after parsing is over */
dgabino 0:102b50f941d0 716 json_array_resize(output_array, json_array_get_count(output_array)) == JSONFailure) {
dgabino 0:102b50f941d0 717 json_value_free(output_value);
dgabino 0:102b50f941d0 718 return NULL;
dgabino 0:102b50f941d0 719 }
dgabino 0:102b50f941d0 720 SKIP_CHAR(string);
dgabino 0:102b50f941d0 721 return output_value;
dgabino 0:102b50f941d0 722 }
dgabino 0:102b50f941d0 723
dgabino 0:102b50f941d0 724 static JSON_Value * parse_string_value(const char **string) {
dgabino 0:102b50f941d0 725 JSON_Value *value = NULL;
dgabino 0:102b50f941d0 726 char *new_string = get_quoted_string(string);
dgabino 0:102b50f941d0 727 if (new_string == NULL) {
dgabino 0:102b50f941d0 728 return NULL;
dgabino 0:102b50f941d0 729 }
dgabino 0:102b50f941d0 730 value = json_value_init_string_no_copy(new_string);
dgabino 0:102b50f941d0 731 if (value == NULL) {
dgabino 0:102b50f941d0 732 parson_free(new_string);
dgabino 0:102b50f941d0 733 return NULL;
dgabino 0:102b50f941d0 734 }
dgabino 0:102b50f941d0 735 return value;
dgabino 0:102b50f941d0 736 }
dgabino 0:102b50f941d0 737
dgabino 0:102b50f941d0 738 static JSON_Value * parse_boolean_value(const char **string) {
dgabino 0:102b50f941d0 739 size_t true_token_size = SIZEOF_TOKEN("true");
dgabino 0:102b50f941d0 740 size_t false_token_size = SIZEOF_TOKEN("false");
dgabino 0:102b50f941d0 741 if (strncmp("true", *string, true_token_size) == 0) {
dgabino 0:102b50f941d0 742 *string += true_token_size;
dgabino 0:102b50f941d0 743 return json_value_init_boolean(1);
dgabino 0:102b50f941d0 744 } else if (strncmp("false", *string, false_token_size) == 0) {
dgabino 0:102b50f941d0 745 *string += false_token_size;
dgabino 0:102b50f941d0 746 return json_value_init_boolean(0);
dgabino 0:102b50f941d0 747 }
dgabino 0:102b50f941d0 748 return NULL;
dgabino 0:102b50f941d0 749 }
dgabino 0:102b50f941d0 750
dgabino 0:102b50f941d0 751 static JSON_Value * parse_number_value(const char **string) {
dgabino 0:102b50f941d0 752 char *end;
dgabino 0:102b50f941d0 753 double number = strtod(*string, &end);
dgabino 0:102b50f941d0 754 JSON_Value *output_value;
dgabino 0:102b50f941d0 755 if (is_decimal(*string, end - *string)) {
dgabino 0:102b50f941d0 756 *string = end;
dgabino 0:102b50f941d0 757 output_value = json_value_init_number(number);
dgabino 0:102b50f941d0 758 } else {
dgabino 0:102b50f941d0 759 output_value = NULL;
dgabino 0:102b50f941d0 760 }
dgabino 0:102b50f941d0 761 return output_value;
dgabino 0:102b50f941d0 762 }
dgabino 0:102b50f941d0 763
dgabino 0:102b50f941d0 764 static JSON_Value * parse_null_value(const char **string) {
dgabino 0:102b50f941d0 765 size_t token_size = SIZEOF_TOKEN("null");
dgabino 0:102b50f941d0 766 if (strncmp("null", *string, token_size) == 0) {
dgabino 0:102b50f941d0 767 *string += token_size;
dgabino 0:102b50f941d0 768 return json_value_init_null();
dgabino 0:102b50f941d0 769 }
dgabino 0:102b50f941d0 770 return NULL;
dgabino 0:102b50f941d0 771 }
dgabino 0:102b50f941d0 772
dgabino 0:102b50f941d0 773 /* Serialization */
dgabino 0:102b50f941d0 774 #define APPEND_STRING(str) do { written = append_string(buf, (str)); \
dgabino 0:102b50f941d0 775 if (written < 0) { return -1; } \
dgabino 0:102b50f941d0 776 if (buf != NULL) { buf += written; } \
dgabino 0:102b50f941d0 777 written_total += written; } while(0)
dgabino 0:102b50f941d0 778
dgabino 0:102b50f941d0 779 #define APPEND_INDENT(level) do { written = append_indent(buf, (level)); \
dgabino 0:102b50f941d0 780 if (written < 0) { return -1; } \
dgabino 0:102b50f941d0 781 if (buf != NULL) { buf += written; } \
dgabino 0:102b50f941d0 782 written_total += written; } while(0)
dgabino 0:102b50f941d0 783
dgabino 0:102b50f941d0 784 static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, int is_pretty, char *num_buf) {
dgabino 0:102b50f941d0 785 const char *key = NULL, *string = NULL;
dgabino 0:102b50f941d0 786 JSON_Value *temp_value = NULL;
dgabino 0:102b50f941d0 787 JSON_Array *array = NULL;
dgabino 0:102b50f941d0 788 JSON_Object *object = NULL;
dgabino 0:102b50f941d0 789 size_t i = 0, count = 0;
dgabino 0:102b50f941d0 790 double num = 0.0;
dgabino 0:102b50f941d0 791 int written = -1, written_total = 0;
dgabino 0:102b50f941d0 792
dgabino 0:102b50f941d0 793 switch (json_value_get_type(value)) {
dgabino 0:102b50f941d0 794 case JSONArray:
dgabino 0:102b50f941d0 795 array = json_value_get_array(value);
dgabino 0:102b50f941d0 796 count = json_array_get_count(array);
dgabino 0:102b50f941d0 797 APPEND_STRING("[");
dgabino 0:102b50f941d0 798 if (count > 0 && is_pretty) {
dgabino 0:102b50f941d0 799 APPEND_STRING("\n");
dgabino 0:102b50f941d0 800 }
dgabino 0:102b50f941d0 801 for (i = 0; i < count; i++) {
dgabino 0:102b50f941d0 802 if (is_pretty) {
dgabino 0:102b50f941d0 803 APPEND_INDENT(level + 1);
dgabino 0:102b50f941d0 804 }
dgabino 0:102b50f941d0 805 temp_value = json_array_get_value(array, i);
dgabino 0:102b50f941d0 806 written = json_serialize_to_buffer_r(temp_value, buf, level + 1, is_pretty, num_buf);
dgabino 0:102b50f941d0 807 if (written < 0) {
dgabino 0:102b50f941d0 808 return -1;
dgabino 0:102b50f941d0 809 }
dgabino 0:102b50f941d0 810 if (buf != NULL) {
dgabino 0:102b50f941d0 811 buf += written;
dgabino 0:102b50f941d0 812 }
dgabino 0:102b50f941d0 813 written_total += written;
dgabino 0:102b50f941d0 814 if (i < (count - 1)) {
dgabino 0:102b50f941d0 815 APPEND_STRING(",");
dgabino 0:102b50f941d0 816 }
dgabino 0:102b50f941d0 817 if (is_pretty) {
dgabino 0:102b50f941d0 818 APPEND_STRING("\n");
dgabino 0:102b50f941d0 819 }
dgabino 0:102b50f941d0 820 }
dgabino 0:102b50f941d0 821 if (count > 0 && is_pretty) {
dgabino 0:102b50f941d0 822 APPEND_INDENT(level);
dgabino 0:102b50f941d0 823 }
dgabino 0:102b50f941d0 824 APPEND_STRING("]");
dgabino 0:102b50f941d0 825 return written_total;
dgabino 0:102b50f941d0 826 case JSONObject:
dgabino 0:102b50f941d0 827 object = json_value_get_object(value);
dgabino 0:102b50f941d0 828 count = json_object_get_count(object);
dgabino 0:102b50f941d0 829 APPEND_STRING("{");
dgabino 0:102b50f941d0 830 if (count > 0 && is_pretty) {
dgabino 0:102b50f941d0 831 APPEND_STRING("\n");
dgabino 0:102b50f941d0 832 }
dgabino 0:102b50f941d0 833 for (i = 0; i < count; i++) {
dgabino 0:102b50f941d0 834 key = json_object_get_name(object, i);
dgabino 0:102b50f941d0 835 if (is_pretty) {
dgabino 0:102b50f941d0 836 APPEND_INDENT(level + 1);
dgabino 0:102b50f941d0 837 }
dgabino 0:102b50f941d0 838 written = json_serialize_string(key, buf);
dgabino 0:102b50f941d0 839 if (written < 0) {
dgabino 0:102b50f941d0 840 return -1;
dgabino 0:102b50f941d0 841 }
dgabino 0:102b50f941d0 842 if (buf != NULL) {
dgabino 0:102b50f941d0 843 buf += written;
dgabino 0:102b50f941d0 844 }
dgabino 0:102b50f941d0 845 written_total += written;
dgabino 0:102b50f941d0 846 APPEND_STRING(":");
dgabino 0:102b50f941d0 847 if (is_pretty) {
dgabino 0:102b50f941d0 848 APPEND_STRING(" ");
dgabino 0:102b50f941d0 849 }
dgabino 0:102b50f941d0 850 temp_value = json_object_get_value(object, key);
dgabino 0:102b50f941d0 851 written = json_serialize_to_buffer_r(temp_value, buf, level + 1, is_pretty, num_buf);
dgabino 0:102b50f941d0 852 if (written < 0) {
dgabino 0:102b50f941d0 853 return -1;
dgabino 0:102b50f941d0 854 }
dgabino 0:102b50f941d0 855 if (buf != NULL) {
dgabino 0:102b50f941d0 856 buf += written;
dgabino 0:102b50f941d0 857 }
dgabino 0:102b50f941d0 858 written_total += written;
dgabino 0:102b50f941d0 859 if (i < (count - 1)) {
dgabino 0:102b50f941d0 860 APPEND_STRING(",");
dgabino 0:102b50f941d0 861 }
dgabino 0:102b50f941d0 862 if (is_pretty) {
dgabino 0:102b50f941d0 863 APPEND_STRING("\n");
dgabino 0:102b50f941d0 864 }
dgabino 0:102b50f941d0 865 }
dgabino 0:102b50f941d0 866 if (count > 0 && is_pretty) {
dgabino 0:102b50f941d0 867 APPEND_INDENT(level);
dgabino 0:102b50f941d0 868 }
dgabino 0:102b50f941d0 869 APPEND_STRING("}");
dgabino 0:102b50f941d0 870 return written_total;
dgabino 0:102b50f941d0 871 case JSONString:
dgabino 0:102b50f941d0 872 string = json_value_get_string(value);
dgabino 0:102b50f941d0 873 written = json_serialize_string(string, buf);
dgabino 0:102b50f941d0 874 if (written < 0) {
dgabino 0:102b50f941d0 875 return -1;
dgabino 0:102b50f941d0 876 }
dgabino 0:102b50f941d0 877 if (buf != NULL) {
dgabino 0:102b50f941d0 878 buf += written;
dgabino 0:102b50f941d0 879 }
dgabino 0:102b50f941d0 880 written_total += written;
dgabino 0:102b50f941d0 881 return written_total;
dgabino 0:102b50f941d0 882 case JSONBoolean:
dgabino 0:102b50f941d0 883 if (json_value_get_boolean(value)) {
dgabino 0:102b50f941d0 884 APPEND_STRING("true");
dgabino 0:102b50f941d0 885 } else {
dgabino 0:102b50f941d0 886 APPEND_STRING("false");
dgabino 0:102b50f941d0 887 }
dgabino 0:102b50f941d0 888 return written_total;
dgabino 0:102b50f941d0 889 case JSONNumber:
dgabino 0:102b50f941d0 890 num = json_value_get_number(value);
dgabino 0:102b50f941d0 891 if (buf != NULL) {
dgabino 0:102b50f941d0 892 num_buf = buf;
dgabino 0:102b50f941d0 893 }
dgabino 0:102b50f941d0 894 if (num == ((double)(int)num)) { /* check if num is integer */
dgabino 0:102b50f941d0 895 written = sprintf(num_buf, "%d", (int)num);
dgabino 0:102b50f941d0 896 } else {
dgabino 0:102b50f941d0 897 written = sprintf(num_buf, DOUBLE_SERIALIZATION_FORMAT, num);
dgabino 0:102b50f941d0 898 }
dgabino 0:102b50f941d0 899 if (written < 0) {
dgabino 0:102b50f941d0 900 return -1;
dgabino 0:102b50f941d0 901 }
dgabino 0:102b50f941d0 902 if (buf != NULL) {
dgabino 0:102b50f941d0 903 buf += written;
dgabino 0:102b50f941d0 904 }
dgabino 0:102b50f941d0 905 written_total += written;
dgabino 0:102b50f941d0 906 return written_total;
dgabino 0:102b50f941d0 907 case JSONNull:
dgabino 0:102b50f941d0 908 APPEND_STRING("null");
dgabino 0:102b50f941d0 909 return written_total;
dgabino 0:102b50f941d0 910 case JSONError:
dgabino 0:102b50f941d0 911 return -1;
dgabino 0:102b50f941d0 912 default:
dgabino 0:102b50f941d0 913 return -1;
dgabino 0:102b50f941d0 914 }
dgabino 0:102b50f941d0 915 }
dgabino 0:102b50f941d0 916
dgabino 0:102b50f941d0 917 static int json_serialize_string(const char *string, char *buf) {
dgabino 0:102b50f941d0 918 size_t i = 0, len = strlen(string);
dgabino 0:102b50f941d0 919 char c = '\0';
dgabino 0:102b50f941d0 920 int written = -1, written_total = 0;
dgabino 0:102b50f941d0 921 APPEND_STRING("\"");
dgabino 0:102b50f941d0 922 for (i = 0; i < len; i++) {
dgabino 0:102b50f941d0 923 c = string[i];
dgabino 0:102b50f941d0 924 switch (c) {
dgabino 0:102b50f941d0 925 case '\"':
dgabino 0:102b50f941d0 926 APPEND_STRING("\\\"");
dgabino 0:102b50f941d0 927 break;
dgabino 0:102b50f941d0 928 case '\\':
dgabino 0:102b50f941d0 929 APPEND_STRING("\\\\");
dgabino 0:102b50f941d0 930 break;
dgabino 0:102b50f941d0 931 case '/':
dgabino 0:102b50f941d0 932 APPEND_STRING("\\/");
dgabino 0:102b50f941d0 933 break; /* to make json embeddable in xml\/html */
dgabino 0:102b50f941d0 934 case '\b':
dgabino 0:102b50f941d0 935 APPEND_STRING("\\b");
dgabino 0:102b50f941d0 936 break;
dgabino 0:102b50f941d0 937 case '\f':
dgabino 0:102b50f941d0 938 APPEND_STRING("\\f");
dgabino 0:102b50f941d0 939 break;
dgabino 0:102b50f941d0 940 case '\n':
dgabino 0:102b50f941d0 941 APPEND_STRING("\\n");
dgabino 0:102b50f941d0 942 break;
dgabino 0:102b50f941d0 943 case '\r':
dgabino 0:102b50f941d0 944 APPEND_STRING("\\r");
dgabino 0:102b50f941d0 945 break;
dgabino 0:102b50f941d0 946 case '\t':
dgabino 0:102b50f941d0 947 APPEND_STRING("\\t");
dgabino 0:102b50f941d0 948 break;
dgabino 0:102b50f941d0 949 default:
dgabino 0:102b50f941d0 950 if (buf != NULL) {
dgabino 0:102b50f941d0 951 buf[0] = c;
dgabino 0:102b50f941d0 952 buf += 1;
dgabino 0:102b50f941d0 953 }
dgabino 0:102b50f941d0 954 written_total += 1;
dgabino 0:102b50f941d0 955 break;
dgabino 0:102b50f941d0 956 }
dgabino 0:102b50f941d0 957 }
dgabino 0:102b50f941d0 958 APPEND_STRING("\"");
dgabino 0:102b50f941d0 959 return written_total;
dgabino 0:102b50f941d0 960 }
dgabino 0:102b50f941d0 961
dgabino 0:102b50f941d0 962 static int append_indent(char *buf, int level) {
dgabino 0:102b50f941d0 963 int i;
dgabino 0:102b50f941d0 964 int written = -1, written_total = 0;
dgabino 0:102b50f941d0 965 for (i = 0; i < level; i++) {
dgabino 0:102b50f941d0 966 APPEND_STRING(" ");
dgabino 0:102b50f941d0 967 }
dgabino 0:102b50f941d0 968 return written_total;
dgabino 0:102b50f941d0 969 }
dgabino 0:102b50f941d0 970
dgabino 0:102b50f941d0 971 static int append_string(char *buf, const char *string) {
dgabino 0:102b50f941d0 972 if (buf == NULL) {
dgabino 0:102b50f941d0 973 return (int)strlen(string);
dgabino 0:102b50f941d0 974 }
dgabino 0:102b50f941d0 975 return sprintf(buf, "%s", string);
dgabino 0:102b50f941d0 976 }
dgabino 0:102b50f941d0 977
dgabino 0:102b50f941d0 978 #undef APPEND_STRING
dgabino 0:102b50f941d0 979 #undef APPEND_INDENT
dgabino 0:102b50f941d0 980
dgabino 0:102b50f941d0 981 /* Parser API */
dgabino 0:102b50f941d0 982 JSON_Value * json_parse_file(const char *filename) {
dgabino 0:102b50f941d0 983 char *file_contents = read_file(filename);
dgabino 0:102b50f941d0 984 JSON_Value *output_value = NULL;
dgabino 0:102b50f941d0 985 if (file_contents == NULL) {
dgabino 0:102b50f941d0 986 return NULL;
dgabino 0:102b50f941d0 987 }
dgabino 0:102b50f941d0 988 output_value = json_parse_string(file_contents);
dgabino 0:102b50f941d0 989 parson_free(file_contents);
dgabino 0:102b50f941d0 990 return output_value;
dgabino 0:102b50f941d0 991 }
dgabino 0:102b50f941d0 992
dgabino 0:102b50f941d0 993 JSON_Value * json_parse_file_with_comments(const char *filename) {
dgabino 0:102b50f941d0 994 char *file_contents = read_file(filename);
dgabino 0:102b50f941d0 995 JSON_Value *output_value = NULL;
dgabino 0:102b50f941d0 996 if (file_contents == NULL) {
dgabino 0:102b50f941d0 997 return NULL;
dgabino 0:102b50f941d0 998 }
dgabino 0:102b50f941d0 999 output_value = json_parse_string_with_comments(file_contents);
dgabino 0:102b50f941d0 1000 parson_free(file_contents);
dgabino 0:102b50f941d0 1001 return output_value;
dgabino 0:102b50f941d0 1002 }
dgabino 0:102b50f941d0 1003
dgabino 0:102b50f941d0 1004 JSON_Value * json_parse_string(const char *string) {
dgabino 0:102b50f941d0 1005 if (string == NULL) {
dgabino 0:102b50f941d0 1006 return NULL;
dgabino 0:102b50f941d0 1007 }
dgabino 0:102b50f941d0 1008 SKIP_WHITESPACES(&string);
dgabino 0:102b50f941d0 1009 if (*string != '{' && *string != '[') {
dgabino 0:102b50f941d0 1010 return NULL;
dgabino 0:102b50f941d0 1011 }
dgabino 0:102b50f941d0 1012 return parse_value((const char**)&string, 0);
dgabino 0:102b50f941d0 1013 }
dgabino 0:102b50f941d0 1014
dgabino 0:102b50f941d0 1015 JSON_Value * json_parse_string_with_comments(const char *string) {
dgabino 0:102b50f941d0 1016 JSON_Value *result = NULL;
dgabino 0:102b50f941d0 1017 char *string_mutable_copy = NULL, *string_mutable_copy_ptr = NULL;
dgabino 0:102b50f941d0 1018 string_mutable_copy = parson_strdup(string);
dgabino 0:102b50f941d0 1019 if (string_mutable_copy == NULL) {
dgabino 0:102b50f941d0 1020 return NULL;
dgabino 0:102b50f941d0 1021 }
dgabino 0:102b50f941d0 1022 remove_comments(string_mutable_copy, "/*", "*/");
dgabino 0:102b50f941d0 1023 remove_comments(string_mutable_copy, "//", "\n");
dgabino 0:102b50f941d0 1024 string_mutable_copy_ptr = string_mutable_copy;
dgabino 0:102b50f941d0 1025 SKIP_WHITESPACES(&string_mutable_copy_ptr);
dgabino 0:102b50f941d0 1026 if (*string_mutable_copy_ptr != '{' && *string_mutable_copy_ptr != '[') {
dgabino 0:102b50f941d0 1027 parson_free(string_mutable_copy);
dgabino 0:102b50f941d0 1028 return NULL;
dgabino 0:102b50f941d0 1029 }
dgabino 0:102b50f941d0 1030 result = parse_value((const char**)&string_mutable_copy_ptr, 0);
dgabino 0:102b50f941d0 1031 parson_free(string_mutable_copy);
dgabino 0:102b50f941d0 1032 return result;
dgabino 0:102b50f941d0 1033 }
dgabino 0:102b50f941d0 1034
dgabino 0:102b50f941d0 1035
dgabino 0:102b50f941d0 1036 /* JSON Object API */
dgabino 0:102b50f941d0 1037
dgabino 0:102b50f941d0 1038 JSON_Value * json_object_get_value(const JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1039 if (object == NULL || name == NULL) {
dgabino 0:102b50f941d0 1040 return NULL;
dgabino 0:102b50f941d0 1041 }
dgabino 0:102b50f941d0 1042 return json_object_nget_value(object, name, strlen(name));
dgabino 0:102b50f941d0 1043 }
dgabino 0:102b50f941d0 1044
dgabino 0:102b50f941d0 1045 const char * json_object_get_string(const JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1046 return json_value_get_string(json_object_get_value(object, name));
dgabino 0:102b50f941d0 1047 }
dgabino 0:102b50f941d0 1048
dgabino 0:102b50f941d0 1049 double json_object_get_number(const JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1050 return json_value_get_number(json_object_get_value(object, name));
dgabino 0:102b50f941d0 1051 }
dgabino 0:102b50f941d0 1052
dgabino 0:102b50f941d0 1053 JSON_Object * json_object_get_object(const JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1054 return json_value_get_object(json_object_get_value(object, name));
dgabino 0:102b50f941d0 1055 }
dgabino 0:102b50f941d0 1056
dgabino 0:102b50f941d0 1057 JSON_Array * json_object_get_array(const JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1058 return json_value_get_array(json_object_get_value(object, name));
dgabino 0:102b50f941d0 1059 }
dgabino 0:102b50f941d0 1060
dgabino 0:102b50f941d0 1061 int json_object_get_boolean(const JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1062 return json_value_get_boolean(json_object_get_value(object, name));
dgabino 0:102b50f941d0 1063 }
dgabino 0:102b50f941d0 1064
dgabino 0:102b50f941d0 1065 JSON_Value * json_object_dotget_value(const JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1066 const char *dot_position = strchr(name, '.');
dgabino 0:102b50f941d0 1067 if (!dot_position) {
dgabino 0:102b50f941d0 1068 return json_object_get_value(object, name);
dgabino 0:102b50f941d0 1069 }
dgabino 0:102b50f941d0 1070 object = json_value_get_object(json_object_nget_value(object, name, dot_position - name));
dgabino 0:102b50f941d0 1071 return json_object_dotget_value(object, dot_position + 1);
dgabino 0:102b50f941d0 1072 }
dgabino 0:102b50f941d0 1073
dgabino 0:102b50f941d0 1074 const char * json_object_dotget_string(const JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1075 return json_value_get_string(json_object_dotget_value(object, name));
dgabino 0:102b50f941d0 1076 }
dgabino 0:102b50f941d0 1077
dgabino 0:102b50f941d0 1078 double json_object_dotget_number(const JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1079 return json_value_get_number(json_object_dotget_value(object, name));
dgabino 0:102b50f941d0 1080 }
dgabino 0:102b50f941d0 1081
dgabino 0:102b50f941d0 1082 JSON_Object * json_object_dotget_object(const JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1083 return json_value_get_object(json_object_dotget_value(object, name));
dgabino 0:102b50f941d0 1084 }
dgabino 0:102b50f941d0 1085
dgabino 0:102b50f941d0 1086 JSON_Array * json_object_dotget_array(const JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1087 return json_value_get_array(json_object_dotget_value(object, name));
dgabino 0:102b50f941d0 1088 }
dgabino 0:102b50f941d0 1089
dgabino 0:102b50f941d0 1090 int json_object_dotget_boolean(const JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1091 return json_value_get_boolean(json_object_dotget_value(object, name));
dgabino 0:102b50f941d0 1092 }
dgabino 0:102b50f941d0 1093
dgabino 0:102b50f941d0 1094 size_t json_object_get_count(const JSON_Object *object) {
dgabino 0:102b50f941d0 1095 return object ? object->count : 0;
dgabino 0:102b50f941d0 1096 }
dgabino 0:102b50f941d0 1097
dgabino 0:102b50f941d0 1098 const char * json_object_get_name(const JSON_Object *object, size_t index) {
dgabino 0:102b50f941d0 1099 if (index >= json_object_get_count(object)) {
dgabino 0:102b50f941d0 1100 return NULL;
dgabino 0:102b50f941d0 1101 }
dgabino 0:102b50f941d0 1102 return object->names[index];
dgabino 0:102b50f941d0 1103 }
dgabino 0:102b50f941d0 1104
dgabino 0:102b50f941d0 1105 /* JSON Array API */
dgabino 0:102b50f941d0 1106 JSON_Value * json_array_get_value(const JSON_Array *array, size_t index) {
dgabino 0:102b50f941d0 1107 if (index >= json_array_get_count(array)) {
dgabino 0:102b50f941d0 1108 return NULL;
dgabino 0:102b50f941d0 1109 }
dgabino 0:102b50f941d0 1110 return array->items[index];
dgabino 0:102b50f941d0 1111 }
dgabino 0:102b50f941d0 1112
dgabino 0:102b50f941d0 1113 const char * json_array_get_string(const JSON_Array *array, size_t index) {
dgabino 0:102b50f941d0 1114 return json_value_get_string(json_array_get_value(array, index));
dgabino 0:102b50f941d0 1115 }
dgabino 0:102b50f941d0 1116
dgabino 0:102b50f941d0 1117 double json_array_get_number(const JSON_Array *array, size_t index) {
dgabino 0:102b50f941d0 1118 return json_value_get_number(json_array_get_value(array, index));
dgabino 0:102b50f941d0 1119 }
dgabino 0:102b50f941d0 1120
dgabino 0:102b50f941d0 1121 JSON_Object * json_array_get_object(const JSON_Array *array, size_t index) {
dgabino 0:102b50f941d0 1122 return json_value_get_object(json_array_get_value(array, index));
dgabino 0:102b50f941d0 1123 }
dgabino 0:102b50f941d0 1124
dgabino 0:102b50f941d0 1125 JSON_Array * json_array_get_array(const JSON_Array *array, size_t index) {
dgabino 0:102b50f941d0 1126 return json_value_get_array(json_array_get_value(array, index));
dgabino 0:102b50f941d0 1127 }
dgabino 0:102b50f941d0 1128
dgabino 0:102b50f941d0 1129 int json_array_get_boolean(const JSON_Array *array, size_t index) {
dgabino 0:102b50f941d0 1130 return json_value_get_boolean(json_array_get_value(array, index));
dgabino 0:102b50f941d0 1131 }
dgabino 0:102b50f941d0 1132
dgabino 0:102b50f941d0 1133 size_t json_array_get_count(const JSON_Array *array) {
dgabino 0:102b50f941d0 1134 return array ? array->count : 0;
dgabino 0:102b50f941d0 1135 }
dgabino 0:102b50f941d0 1136
dgabino 0:102b50f941d0 1137 /* JSON Value API */
dgabino 0:102b50f941d0 1138 JSON_Value_Type json_value_get_type(const JSON_Value *value) {
dgabino 0:102b50f941d0 1139 return value ? value->type : JSONError;
dgabino 0:102b50f941d0 1140 }
dgabino 0:102b50f941d0 1141
dgabino 0:102b50f941d0 1142 JSON_Object * json_value_get_object(const JSON_Value *value) {
dgabino 0:102b50f941d0 1143 return json_value_get_type(value) == JSONObject ? value->value.object : NULL;
dgabino 0:102b50f941d0 1144 }
dgabino 0:102b50f941d0 1145
dgabino 0:102b50f941d0 1146 JSON_Array * json_value_get_array(const JSON_Value *value) {
dgabino 0:102b50f941d0 1147 return json_value_get_type(value) == JSONArray ? value->value.array : NULL;
dgabino 0:102b50f941d0 1148 }
dgabino 0:102b50f941d0 1149
dgabino 0:102b50f941d0 1150 const char * json_value_get_string(const JSON_Value *value) {
dgabino 0:102b50f941d0 1151 return json_value_get_type(value) == JSONString ? value->value.string : NULL;
dgabino 0:102b50f941d0 1152 }
dgabino 0:102b50f941d0 1153
dgabino 0:102b50f941d0 1154 double json_value_get_number(const JSON_Value *value) {
dgabino 0:102b50f941d0 1155 return json_value_get_type(value) == JSONNumber ? value->value.number : 0;
dgabino 0:102b50f941d0 1156 }
dgabino 0:102b50f941d0 1157
dgabino 0:102b50f941d0 1158 int json_value_get_boolean(const JSON_Value *value) {
dgabino 0:102b50f941d0 1159 return json_value_get_type(value) == JSONBoolean ? value->value.boolean : -1;
dgabino 0:102b50f941d0 1160 }
dgabino 0:102b50f941d0 1161
dgabino 0:102b50f941d0 1162 void json_value_free(JSON_Value *value) {
dgabino 0:102b50f941d0 1163 switch (json_value_get_type(value)) {
dgabino 0:102b50f941d0 1164 case JSONObject:
dgabino 0:102b50f941d0 1165 json_object_free(value->value.object);
dgabino 0:102b50f941d0 1166 break;
dgabino 0:102b50f941d0 1167 case JSONString:
dgabino 0:102b50f941d0 1168 if (value->value.string) {
dgabino 0:102b50f941d0 1169 parson_free(value->value.string);
dgabino 0:102b50f941d0 1170 }
dgabino 0:102b50f941d0 1171 break;
dgabino 0:102b50f941d0 1172 case JSONArray:
dgabino 0:102b50f941d0 1173 json_array_free(value->value.array);
dgabino 0:102b50f941d0 1174 break;
dgabino 0:102b50f941d0 1175 default:
dgabino 0:102b50f941d0 1176 break;
dgabino 0:102b50f941d0 1177 }
dgabino 0:102b50f941d0 1178 parson_free(value);
dgabino 0:102b50f941d0 1179 }
dgabino 0:102b50f941d0 1180
dgabino 0:102b50f941d0 1181 JSON_Value * json_value_init_object(void) {
dgabino 0:102b50f941d0 1182 JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
dgabino 0:102b50f941d0 1183 if (!new_value) {
dgabino 0:102b50f941d0 1184 return NULL;
dgabino 0:102b50f941d0 1185 }
dgabino 0:102b50f941d0 1186 new_value->type = JSONObject;
dgabino 0:102b50f941d0 1187 new_value->value.object = json_object_init();
dgabino 0:102b50f941d0 1188 if (!new_value->value.object) {
dgabino 0:102b50f941d0 1189 parson_free(new_value);
dgabino 0:102b50f941d0 1190 return NULL;
dgabino 0:102b50f941d0 1191 }
dgabino 0:102b50f941d0 1192 return new_value;
dgabino 0:102b50f941d0 1193 }
dgabino 0:102b50f941d0 1194
dgabino 0:102b50f941d0 1195 JSON_Value * json_value_init_array(void) {
dgabino 0:102b50f941d0 1196 JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
dgabino 0:102b50f941d0 1197 if (!new_value) {
dgabino 0:102b50f941d0 1198 return NULL;
dgabino 0:102b50f941d0 1199 }
dgabino 0:102b50f941d0 1200 new_value->type = JSONArray;
dgabino 0:102b50f941d0 1201 new_value->value.array = json_array_init();
dgabino 0:102b50f941d0 1202 if (!new_value->value.array) {
dgabino 0:102b50f941d0 1203 parson_free(new_value);
dgabino 0:102b50f941d0 1204 return NULL;
dgabino 0:102b50f941d0 1205 }
dgabino 0:102b50f941d0 1206 return new_value;
dgabino 0:102b50f941d0 1207 }
dgabino 0:102b50f941d0 1208
dgabino 0:102b50f941d0 1209 JSON_Value * json_value_init_string(const char *string) {
dgabino 0:102b50f941d0 1210 char *copy = NULL;
dgabino 0:102b50f941d0 1211 JSON_Value *value;
dgabino 0:102b50f941d0 1212 size_t string_len = 0;
dgabino 0:102b50f941d0 1213 if (string == NULL) {
dgabino 0:102b50f941d0 1214 return NULL;
dgabino 0:102b50f941d0 1215 }
dgabino 0:102b50f941d0 1216 string_len = strlen(string);
dgabino 0:102b50f941d0 1217 if (!is_valid_utf8(string, string_len)) {
dgabino 0:102b50f941d0 1218 return NULL;
dgabino 0:102b50f941d0 1219 }
dgabino 0:102b50f941d0 1220 copy = parson_strndup(string, string_len);
dgabino 0:102b50f941d0 1221 if (copy == NULL) {
dgabino 0:102b50f941d0 1222 return NULL;
dgabino 0:102b50f941d0 1223 }
dgabino 0:102b50f941d0 1224 value = json_value_init_string_no_copy(copy);
dgabino 0:102b50f941d0 1225 if (value == NULL) {
dgabino 0:102b50f941d0 1226 parson_free(copy);
dgabino 0:102b50f941d0 1227 }
dgabino 0:102b50f941d0 1228 return value;
dgabino 0:102b50f941d0 1229 }
dgabino 0:102b50f941d0 1230
dgabino 0:102b50f941d0 1231 JSON_Value * json_value_init_number(double number) {
dgabino 0:102b50f941d0 1232 JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
dgabino 0:102b50f941d0 1233 if (!new_value) {
dgabino 0:102b50f941d0 1234 return NULL;
dgabino 0:102b50f941d0 1235 }
dgabino 0:102b50f941d0 1236 new_value->type = JSONNumber;
dgabino 0:102b50f941d0 1237 new_value->value.number = number;
dgabino 0:102b50f941d0 1238 return new_value;
dgabino 0:102b50f941d0 1239 }
dgabino 0:102b50f941d0 1240
dgabino 0:102b50f941d0 1241 JSON_Value * json_value_init_boolean(int boolean) {
dgabino 0:102b50f941d0 1242 JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
dgabino 0:102b50f941d0 1243 if (!new_value) {
dgabino 0:102b50f941d0 1244 return NULL;
dgabino 0:102b50f941d0 1245 }
dgabino 0:102b50f941d0 1246 new_value->type = JSONBoolean;
dgabino 0:102b50f941d0 1247 new_value->value.boolean = boolean ? 1 : 0;
dgabino 0:102b50f941d0 1248 return new_value;
dgabino 0:102b50f941d0 1249 }
dgabino 0:102b50f941d0 1250
dgabino 0:102b50f941d0 1251 JSON_Value * json_value_init_null(void) {
dgabino 0:102b50f941d0 1252 JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
dgabino 0:102b50f941d0 1253 if (!new_value) {
dgabino 0:102b50f941d0 1254 return NULL;
dgabino 0:102b50f941d0 1255 }
dgabino 0:102b50f941d0 1256 new_value->type = JSONNull;
dgabino 0:102b50f941d0 1257 return new_value;
dgabino 0:102b50f941d0 1258 }
dgabino 0:102b50f941d0 1259
dgabino 0:102b50f941d0 1260 JSON_Value * json_value_deep_copy(const JSON_Value *value) {
dgabino 0:102b50f941d0 1261 size_t i = 0;
dgabino 0:102b50f941d0 1262 JSON_Value *return_value = NULL, *temp_value_copy = NULL, *temp_value = NULL;
dgabino 0:102b50f941d0 1263 const char *temp_string = NULL, *temp_key = NULL;
dgabino 0:102b50f941d0 1264 char *temp_string_copy = NULL;
dgabino 0:102b50f941d0 1265 JSON_Array *temp_array = NULL, *temp_array_copy = NULL;
dgabino 0:102b50f941d0 1266 JSON_Object *temp_object = NULL, *temp_object_copy = NULL;
dgabino 0:102b50f941d0 1267
dgabino 0:102b50f941d0 1268 switch (json_value_get_type(value)) {
dgabino 0:102b50f941d0 1269 case JSONArray:
dgabino 0:102b50f941d0 1270 temp_array = json_value_get_array(value);
dgabino 0:102b50f941d0 1271 return_value = json_value_init_array();
dgabino 0:102b50f941d0 1272 if (return_value == NULL) {
dgabino 0:102b50f941d0 1273 return NULL;
dgabino 0:102b50f941d0 1274 }
dgabino 0:102b50f941d0 1275 temp_array_copy = json_value_get_array(return_value);
dgabino 0:102b50f941d0 1276 for (i = 0; i < json_array_get_count(temp_array); i++) {
dgabino 0:102b50f941d0 1277 temp_value = json_array_get_value(temp_array, i);
dgabino 0:102b50f941d0 1278 temp_value_copy = json_value_deep_copy(temp_value);
dgabino 0:102b50f941d0 1279 if (temp_value_copy == NULL) {
dgabino 0:102b50f941d0 1280 json_value_free(return_value);
dgabino 0:102b50f941d0 1281 return NULL;
dgabino 0:102b50f941d0 1282 }
dgabino 0:102b50f941d0 1283 if (json_array_add(temp_array_copy, temp_value_copy) == JSONFailure) {
dgabino 0:102b50f941d0 1284 json_value_free(return_value);
dgabino 0:102b50f941d0 1285 json_value_free(temp_value_copy);
dgabino 0:102b50f941d0 1286 return NULL;
dgabino 0:102b50f941d0 1287 }
dgabino 0:102b50f941d0 1288 }
dgabino 0:102b50f941d0 1289 return return_value;
dgabino 0:102b50f941d0 1290 case JSONObject:
dgabino 0:102b50f941d0 1291 temp_object = json_value_get_object(value);
dgabino 0:102b50f941d0 1292 return_value = json_value_init_object();
dgabino 0:102b50f941d0 1293 if (return_value == NULL) {
dgabino 0:102b50f941d0 1294 return NULL;
dgabino 0:102b50f941d0 1295 }
dgabino 0:102b50f941d0 1296 temp_object_copy = json_value_get_object(return_value);
dgabino 0:102b50f941d0 1297 for (i = 0; i < json_object_get_count(temp_object); i++) {
dgabino 0:102b50f941d0 1298 temp_key = json_object_get_name(temp_object, i);
dgabino 0:102b50f941d0 1299 temp_value = json_object_get_value(temp_object, temp_key);
dgabino 0:102b50f941d0 1300 temp_value_copy = json_value_deep_copy(temp_value);
dgabino 0:102b50f941d0 1301 if (temp_value_copy == NULL) {
dgabino 0:102b50f941d0 1302 json_value_free(return_value);
dgabino 0:102b50f941d0 1303 return NULL;
dgabino 0:102b50f941d0 1304 }
dgabino 0:102b50f941d0 1305 if (json_object_add(temp_object_copy, temp_key, temp_value_copy) == JSONFailure) {
dgabino 0:102b50f941d0 1306 json_value_free(return_value);
dgabino 0:102b50f941d0 1307 json_value_free(temp_value_copy);
dgabino 0:102b50f941d0 1308 return NULL;
dgabino 0:102b50f941d0 1309 }
dgabino 0:102b50f941d0 1310 }
dgabino 0:102b50f941d0 1311 return return_value;
dgabino 0:102b50f941d0 1312 case JSONBoolean:
dgabino 0:102b50f941d0 1313 return json_value_init_boolean(json_value_get_boolean(value));
dgabino 0:102b50f941d0 1314 case JSONNumber:
dgabino 0:102b50f941d0 1315 return json_value_init_number(json_value_get_number(value));
dgabino 0:102b50f941d0 1316 case JSONString:
dgabino 0:102b50f941d0 1317 temp_string = json_value_get_string(value);
dgabino 0:102b50f941d0 1318 temp_string_copy = parson_strdup(temp_string);
dgabino 0:102b50f941d0 1319 if (temp_string_copy == NULL) {
dgabino 0:102b50f941d0 1320 return NULL;
dgabino 0:102b50f941d0 1321 }
dgabino 0:102b50f941d0 1322 return_value = json_value_init_string_no_copy(temp_string_copy);
dgabino 0:102b50f941d0 1323 if (return_value == NULL) {
dgabino 0:102b50f941d0 1324 parson_free(temp_string_copy);
dgabino 0:102b50f941d0 1325 }
dgabino 0:102b50f941d0 1326 return return_value;
dgabino 0:102b50f941d0 1327 case JSONNull:
dgabino 0:102b50f941d0 1328 return json_value_init_null();
dgabino 0:102b50f941d0 1329 case JSONError:
dgabino 0:102b50f941d0 1330 return NULL;
dgabino 0:102b50f941d0 1331 default:
dgabino 0:102b50f941d0 1332 return NULL;
dgabino 0:102b50f941d0 1333 }
dgabino 0:102b50f941d0 1334 }
dgabino 0:102b50f941d0 1335
dgabino 0:102b50f941d0 1336 size_t json_serialization_size(const JSON_Value *value) {
dgabino 0:102b50f941d0 1337 char num_buf[1100]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */
dgabino 0:102b50f941d0 1338 int res = json_serialize_to_buffer_r(value, NULL, 0, 0, num_buf);
dgabino 0:102b50f941d0 1339 return res < 0 ? 0 : (size_t)(res + 1);
dgabino 0:102b50f941d0 1340 }
dgabino 0:102b50f941d0 1341
dgabino 0:102b50f941d0 1342 JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) {
dgabino 0:102b50f941d0 1343 int written = -1;
dgabino 0:102b50f941d0 1344 size_t needed_size_in_bytes = json_serialization_size(value);
dgabino 0:102b50f941d0 1345 if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) {
dgabino 0:102b50f941d0 1346 return JSONFailure;
dgabino 0:102b50f941d0 1347 }
dgabino 0:102b50f941d0 1348 written = json_serialize_to_buffer_r(value, buf, 0, 0, NULL);
dgabino 0:102b50f941d0 1349 if (written < 0) {
dgabino 0:102b50f941d0 1350 return JSONFailure;
dgabino 0:102b50f941d0 1351 }
dgabino 0:102b50f941d0 1352 return JSONSuccess;
dgabino 0:102b50f941d0 1353 }
dgabino 0:102b50f941d0 1354
dgabino 0:102b50f941d0 1355 JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename) {
dgabino 0:102b50f941d0 1356 JSON_Status return_code = JSONSuccess;
dgabino 0:102b50f941d0 1357 FILE *fp = NULL;
dgabino 0:102b50f941d0 1358 char *serialized_string = json_serialize_to_string(value);
dgabino 0:102b50f941d0 1359 if (serialized_string == NULL) {
dgabino 0:102b50f941d0 1360 return JSONFailure;
dgabino 0:102b50f941d0 1361 }
dgabino 0:102b50f941d0 1362 fp = fopen (filename, "w");
dgabino 0:102b50f941d0 1363 if (fp != NULL) {
dgabino 0:102b50f941d0 1364 if (fputs (serialized_string, fp) == EOF) {
dgabino 0:102b50f941d0 1365 return_code = JSONFailure;
dgabino 0:102b50f941d0 1366 }
dgabino 0:102b50f941d0 1367 if (fclose (fp) == EOF) {
dgabino 0:102b50f941d0 1368 return_code = JSONFailure;
dgabino 0:102b50f941d0 1369 }
dgabino 0:102b50f941d0 1370 }
dgabino 0:102b50f941d0 1371 json_free_serialized_string(serialized_string);
dgabino 0:102b50f941d0 1372 return return_code;
dgabino 0:102b50f941d0 1373 }
dgabino 0:102b50f941d0 1374
dgabino 0:102b50f941d0 1375 char * json_serialize_to_string(const JSON_Value *value) {
dgabino 0:102b50f941d0 1376 JSON_Status serialization_result = JSONFailure;
dgabino 0:102b50f941d0 1377 size_t buf_size_bytes = json_serialization_size(value);
dgabino 0:102b50f941d0 1378 char *buf = NULL;
dgabino 0:102b50f941d0 1379 if (buf_size_bytes == 0) {
dgabino 0:102b50f941d0 1380 return NULL;
dgabino 0:102b50f941d0 1381 }
dgabino 0:102b50f941d0 1382 buf = (char*)parson_malloc(buf_size_bytes);
dgabino 0:102b50f941d0 1383 if (buf == NULL) {
dgabino 0:102b50f941d0 1384 return NULL;
dgabino 0:102b50f941d0 1385 }
dgabino 0:102b50f941d0 1386 serialization_result = json_serialize_to_buffer(value, buf, buf_size_bytes);
dgabino 0:102b50f941d0 1387 if (serialization_result == JSONFailure) {
dgabino 0:102b50f941d0 1388 json_free_serialized_string(buf);
dgabino 0:102b50f941d0 1389 return NULL;
dgabino 0:102b50f941d0 1390 }
dgabino 0:102b50f941d0 1391 return buf;
dgabino 0:102b50f941d0 1392 }
dgabino 0:102b50f941d0 1393
dgabino 0:102b50f941d0 1394 size_t json_serialization_size_pretty(const JSON_Value *value) {
dgabino 0:102b50f941d0 1395 char num_buf[1100]; /* recursively allocating buffer on stack is a bad idea, so let's do it only once */
dgabino 0:102b50f941d0 1396 int res = json_serialize_to_buffer_r(value, NULL, 0, 1, num_buf);
dgabino 0:102b50f941d0 1397 return res < 0 ? 0 : (size_t)(res + 1);
dgabino 0:102b50f941d0 1398 }
dgabino 0:102b50f941d0 1399
dgabino 0:102b50f941d0 1400 JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes) {
dgabino 0:102b50f941d0 1401 int written = -1;
dgabino 0:102b50f941d0 1402 size_t needed_size_in_bytes = json_serialization_size_pretty(value);
dgabino 0:102b50f941d0 1403 if (needed_size_in_bytes == 0 || buf_size_in_bytes < needed_size_in_bytes) {
dgabino 0:102b50f941d0 1404 return JSONFailure;
dgabino 0:102b50f941d0 1405 }
dgabino 0:102b50f941d0 1406 written = json_serialize_to_buffer_r(value, buf, 0, 1, NULL);
dgabino 0:102b50f941d0 1407 if (written < 0) {
dgabino 0:102b50f941d0 1408 return JSONFailure;
dgabino 0:102b50f941d0 1409 }
dgabino 0:102b50f941d0 1410 return JSONSuccess;
dgabino 0:102b50f941d0 1411 }
dgabino 0:102b50f941d0 1412
dgabino 0:102b50f941d0 1413 JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename) {
dgabino 0:102b50f941d0 1414 JSON_Status return_code = JSONSuccess;
dgabino 0:102b50f941d0 1415 FILE *fp = NULL;
dgabino 0:102b50f941d0 1416 char *serialized_string = json_serialize_to_string_pretty(value);
dgabino 0:102b50f941d0 1417 if (serialized_string == NULL) {
dgabino 0:102b50f941d0 1418 return JSONFailure;
dgabino 0:102b50f941d0 1419 }
dgabino 0:102b50f941d0 1420 fp = fopen (filename, "w");
dgabino 0:102b50f941d0 1421 if (fp != NULL) {
dgabino 0:102b50f941d0 1422 if (fputs (serialized_string, fp) == EOF) {
dgabino 0:102b50f941d0 1423 return_code = JSONFailure;
dgabino 0:102b50f941d0 1424 }
dgabino 0:102b50f941d0 1425 if (fclose (fp) == EOF) {
dgabino 0:102b50f941d0 1426 return_code = JSONFailure;
dgabino 0:102b50f941d0 1427 }
dgabino 0:102b50f941d0 1428 }
dgabino 0:102b50f941d0 1429 json_free_serialized_string(serialized_string);
dgabino 0:102b50f941d0 1430 return return_code;
dgabino 0:102b50f941d0 1431 }
dgabino 0:102b50f941d0 1432
dgabino 0:102b50f941d0 1433 char * json_serialize_to_string_pretty(const JSON_Value *value) {
dgabino 0:102b50f941d0 1434 JSON_Status serialization_result = JSONFailure;
dgabino 0:102b50f941d0 1435 size_t buf_size_bytes = json_serialization_size_pretty(value);
dgabino 0:102b50f941d0 1436 char *buf = NULL;
dgabino 0:102b50f941d0 1437 if (buf_size_bytes == 0) {
dgabino 0:102b50f941d0 1438 return NULL;
dgabino 0:102b50f941d0 1439 }
dgabino 0:102b50f941d0 1440 buf = (char*)parson_malloc(buf_size_bytes);
dgabino 0:102b50f941d0 1441 if (buf == NULL) {
dgabino 0:102b50f941d0 1442 return NULL;
dgabino 0:102b50f941d0 1443 }
dgabino 0:102b50f941d0 1444 serialization_result = json_serialize_to_buffer_pretty(value, buf, buf_size_bytes);
dgabino 0:102b50f941d0 1445 if (serialization_result == JSONFailure) {
dgabino 0:102b50f941d0 1446 json_free_serialized_string(buf);
dgabino 0:102b50f941d0 1447 return NULL;
dgabino 0:102b50f941d0 1448 }
dgabino 0:102b50f941d0 1449 return buf;
dgabino 0:102b50f941d0 1450 }
dgabino 0:102b50f941d0 1451
dgabino 0:102b50f941d0 1452 void json_free_serialized_string(char *string) {
dgabino 0:102b50f941d0 1453 parson_free(string);
dgabino 0:102b50f941d0 1454 }
dgabino 0:102b50f941d0 1455
dgabino 0:102b50f941d0 1456 JSON_Status json_array_remove(JSON_Array *array, size_t ix) {
dgabino 0:102b50f941d0 1457 JSON_Value *temp_value = NULL;
dgabino 0:102b50f941d0 1458 size_t last_element_ix = 0;
dgabino 0:102b50f941d0 1459 if (array == NULL || ix >= json_array_get_count(array)) {
dgabino 0:102b50f941d0 1460 return JSONFailure;
dgabino 0:102b50f941d0 1461 }
dgabino 0:102b50f941d0 1462 last_element_ix = json_array_get_count(array) - 1;
dgabino 0:102b50f941d0 1463 json_value_free(json_array_get_value(array, ix));
dgabino 0:102b50f941d0 1464 if (ix != last_element_ix) { /* Replace value with one from the end of array */
dgabino 0:102b50f941d0 1465 temp_value = json_array_get_value(array, last_element_ix);
dgabino 0:102b50f941d0 1466 if (temp_value == NULL) {
dgabino 0:102b50f941d0 1467 return JSONFailure;
dgabino 0:102b50f941d0 1468 }
dgabino 0:102b50f941d0 1469 array->items[ix] = temp_value;
dgabino 0:102b50f941d0 1470 }
dgabino 0:102b50f941d0 1471 array->count -= 1;
dgabino 0:102b50f941d0 1472 return JSONSuccess;
dgabino 0:102b50f941d0 1473 }
dgabino 0:102b50f941d0 1474
dgabino 0:102b50f941d0 1475 JSON_Status json_array_replace_value(JSON_Array *array, size_t ix, JSON_Value *value) {
dgabino 0:102b50f941d0 1476 if (array == NULL || value == NULL || ix >= json_array_get_count(array)) {
dgabino 0:102b50f941d0 1477 return JSONFailure;
dgabino 0:102b50f941d0 1478 }
dgabino 0:102b50f941d0 1479 json_value_free(json_array_get_value(array, ix));
dgabino 0:102b50f941d0 1480 array->items[ix] = value;
dgabino 0:102b50f941d0 1481 return JSONSuccess;
dgabino 0:102b50f941d0 1482 }
dgabino 0:102b50f941d0 1483
dgabino 0:102b50f941d0 1484 JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string) {
dgabino 0:102b50f941d0 1485 JSON_Value *value = json_value_init_string(string);
dgabino 0:102b50f941d0 1486 if (value == NULL) {
dgabino 0:102b50f941d0 1487 return JSONFailure;
dgabino 0:102b50f941d0 1488 }
dgabino 0:102b50f941d0 1489 if (json_array_replace_value(array, i, value) == JSONFailure) {
dgabino 0:102b50f941d0 1490 json_value_free(value);
dgabino 0:102b50f941d0 1491 return JSONFailure;
dgabino 0:102b50f941d0 1492 }
dgabino 0:102b50f941d0 1493 return JSONSuccess;
dgabino 0:102b50f941d0 1494 }
dgabino 0:102b50f941d0 1495
dgabino 0:102b50f941d0 1496 JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number) {
dgabino 0:102b50f941d0 1497 JSON_Value *value = json_value_init_number(number);
dgabino 0:102b50f941d0 1498 if (value == NULL) {
dgabino 0:102b50f941d0 1499 return JSONFailure;
dgabino 0:102b50f941d0 1500 }
dgabino 0:102b50f941d0 1501 if (json_array_replace_value(array, i, value) == JSONFailure) {
dgabino 0:102b50f941d0 1502 json_value_free(value);
dgabino 0:102b50f941d0 1503 return JSONFailure;
dgabino 0:102b50f941d0 1504 }
dgabino 0:102b50f941d0 1505 return JSONSuccess;
dgabino 0:102b50f941d0 1506 }
dgabino 0:102b50f941d0 1507
dgabino 0:102b50f941d0 1508 JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean) {
dgabino 0:102b50f941d0 1509 JSON_Value *value = json_value_init_boolean(boolean);
dgabino 0:102b50f941d0 1510 if (value == NULL) {
dgabino 0:102b50f941d0 1511 return JSONFailure;
dgabino 0:102b50f941d0 1512 }
dgabino 0:102b50f941d0 1513 if (json_array_replace_value(array, i, value) == JSONFailure) {
dgabino 0:102b50f941d0 1514 json_value_free(value);
dgabino 0:102b50f941d0 1515 return JSONFailure;
dgabino 0:102b50f941d0 1516 }
dgabino 0:102b50f941d0 1517 return JSONSuccess;
dgabino 0:102b50f941d0 1518 }
dgabino 0:102b50f941d0 1519
dgabino 0:102b50f941d0 1520 JSON_Status json_array_replace_null(JSON_Array *array, size_t i) {
dgabino 0:102b50f941d0 1521 JSON_Value *value = json_value_init_null();
dgabino 0:102b50f941d0 1522 if (value == NULL) {
dgabino 0:102b50f941d0 1523 return JSONFailure;
dgabino 0:102b50f941d0 1524 }
dgabino 0:102b50f941d0 1525 if (json_array_replace_value(array, i, value) == JSONFailure) {
dgabino 0:102b50f941d0 1526 json_value_free(value);
dgabino 0:102b50f941d0 1527 return JSONFailure;
dgabino 0:102b50f941d0 1528 }
dgabino 0:102b50f941d0 1529 return JSONSuccess;
dgabino 0:102b50f941d0 1530 }
dgabino 0:102b50f941d0 1531
dgabino 0:102b50f941d0 1532 JSON_Status json_array_clear(JSON_Array *array) {
dgabino 0:102b50f941d0 1533 size_t i = 0;
dgabino 0:102b50f941d0 1534 if (array == NULL) {
dgabino 0:102b50f941d0 1535 return JSONFailure;
dgabino 0:102b50f941d0 1536 }
dgabino 0:102b50f941d0 1537 for (i = 0; i < json_array_get_count(array); i++) {
dgabino 0:102b50f941d0 1538 json_value_free(json_array_get_value(array, i));
dgabino 0:102b50f941d0 1539 }
dgabino 0:102b50f941d0 1540 array->count = 0;
dgabino 0:102b50f941d0 1541 return JSONSuccess;
dgabino 0:102b50f941d0 1542 }
dgabino 0:102b50f941d0 1543
dgabino 0:102b50f941d0 1544 JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value) {
dgabino 0:102b50f941d0 1545 if (array == NULL || value == NULL) {
dgabino 0:102b50f941d0 1546 return JSONFailure;
dgabino 0:102b50f941d0 1547 }
dgabino 0:102b50f941d0 1548 return json_array_add(array, value);
dgabino 0:102b50f941d0 1549 }
dgabino 0:102b50f941d0 1550
dgabino 0:102b50f941d0 1551 JSON_Status json_array_append_string(JSON_Array *array, const char *string) {
dgabino 0:102b50f941d0 1552 JSON_Value *value = json_value_init_string(string);
dgabino 0:102b50f941d0 1553 if (value == NULL) {
dgabino 0:102b50f941d0 1554 return JSONFailure;
dgabino 0:102b50f941d0 1555 }
dgabino 0:102b50f941d0 1556 if (json_array_append_value(array, value) == JSONFailure) {
dgabino 0:102b50f941d0 1557 json_value_free(value);
dgabino 0:102b50f941d0 1558 return JSONFailure;
dgabino 0:102b50f941d0 1559 }
dgabino 0:102b50f941d0 1560 return JSONSuccess;
dgabino 0:102b50f941d0 1561 }
dgabino 0:102b50f941d0 1562
dgabino 0:102b50f941d0 1563 JSON_Status json_array_append_number(JSON_Array *array, double number) {
dgabino 0:102b50f941d0 1564 JSON_Value *value = json_value_init_number(number);
dgabino 0:102b50f941d0 1565 if (value == NULL) {
dgabino 0:102b50f941d0 1566 return JSONFailure;
dgabino 0:102b50f941d0 1567 }
dgabino 0:102b50f941d0 1568 if (json_array_append_value(array, value) == JSONFailure) {
dgabino 0:102b50f941d0 1569 json_value_free(value);
dgabino 0:102b50f941d0 1570 return JSONFailure;
dgabino 0:102b50f941d0 1571 }
dgabino 0:102b50f941d0 1572 return JSONSuccess;
dgabino 0:102b50f941d0 1573 }
dgabino 0:102b50f941d0 1574
dgabino 0:102b50f941d0 1575 JSON_Status json_array_append_boolean(JSON_Array *array, int boolean) {
dgabino 0:102b50f941d0 1576 JSON_Value *value = json_value_init_boolean(boolean);
dgabino 0:102b50f941d0 1577 if (value == NULL) {
dgabino 0:102b50f941d0 1578 return JSONFailure;
dgabino 0:102b50f941d0 1579 }
dgabino 0:102b50f941d0 1580 if (json_array_append_value(array, value) == JSONFailure) {
dgabino 0:102b50f941d0 1581 json_value_free(value);
dgabino 0:102b50f941d0 1582 return JSONFailure;
dgabino 0:102b50f941d0 1583 }
dgabino 0:102b50f941d0 1584 return JSONSuccess;
dgabino 0:102b50f941d0 1585 }
dgabino 0:102b50f941d0 1586
dgabino 0:102b50f941d0 1587 JSON_Status json_array_append_null(JSON_Array *array) {
dgabino 0:102b50f941d0 1588 JSON_Value *value = json_value_init_null();
dgabino 0:102b50f941d0 1589 if (value == NULL) {
dgabino 0:102b50f941d0 1590 return JSONFailure;
dgabino 0:102b50f941d0 1591 }
dgabino 0:102b50f941d0 1592 if (json_array_append_value(array, value) == JSONFailure) {
dgabino 0:102b50f941d0 1593 json_value_free(value);
dgabino 0:102b50f941d0 1594 return JSONFailure;
dgabino 0:102b50f941d0 1595 }
dgabino 0:102b50f941d0 1596 return JSONSuccess;
dgabino 0:102b50f941d0 1597 }
dgabino 0:102b50f941d0 1598
dgabino 0:102b50f941d0 1599 JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value) {
dgabino 0:102b50f941d0 1600 size_t i = 0;
dgabino 0:102b50f941d0 1601 JSON_Value *old_value;
dgabino 0:102b50f941d0 1602 if (object == NULL || name == NULL || value == NULL) {
dgabino 0:102b50f941d0 1603 return JSONFailure;
dgabino 0:102b50f941d0 1604 }
dgabino 0:102b50f941d0 1605 old_value = json_object_get_value(object, name);
dgabino 0:102b50f941d0 1606 if (old_value != NULL) { /* free and overwrite old value */
dgabino 0:102b50f941d0 1607 json_value_free(old_value);
dgabino 0:102b50f941d0 1608 for (i = 0; i < json_object_get_count(object); i++) {
dgabino 0:102b50f941d0 1609 if (strcmp(object->names[i], name) == 0) {
dgabino 0:102b50f941d0 1610 object->values[i] = value;
dgabino 0:102b50f941d0 1611 return JSONSuccess;
dgabino 0:102b50f941d0 1612 }
dgabino 0:102b50f941d0 1613 }
dgabino 0:102b50f941d0 1614 }
dgabino 0:102b50f941d0 1615 /* add new key value pair */
dgabino 0:102b50f941d0 1616 return json_object_add(object, name, value);
dgabino 0:102b50f941d0 1617 }
dgabino 0:102b50f941d0 1618
dgabino 0:102b50f941d0 1619 JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string) {
dgabino 0:102b50f941d0 1620 return json_object_set_value(object, name, json_value_init_string(string));
dgabino 0:102b50f941d0 1621 }
dgabino 0:102b50f941d0 1622
dgabino 0:102b50f941d0 1623 JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number) {
dgabino 0:102b50f941d0 1624 return json_object_set_value(object, name, json_value_init_number(number));
dgabino 0:102b50f941d0 1625 }
dgabino 0:102b50f941d0 1626
dgabino 0:102b50f941d0 1627 JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean) {
dgabino 0:102b50f941d0 1628 return json_object_set_value(object, name, json_value_init_boolean(boolean));
dgabino 0:102b50f941d0 1629 }
dgabino 0:102b50f941d0 1630
dgabino 0:102b50f941d0 1631 JSON_Status json_object_set_null(JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1632 return json_object_set_value(object, name, json_value_init_null());
dgabino 0:102b50f941d0 1633 }
dgabino 0:102b50f941d0 1634
dgabino 0:102b50f941d0 1635 JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value) {
dgabino 0:102b50f941d0 1636 const char *dot_pos = NULL;
dgabino 0:102b50f941d0 1637 char *current_name = NULL;
dgabino 0:102b50f941d0 1638 JSON_Object *temp_obj = NULL;
dgabino 0:102b50f941d0 1639 JSON_Value *new_value = NULL;
dgabino 0:102b50f941d0 1640 if (value == NULL || name == NULL || value == NULL) {
dgabino 0:102b50f941d0 1641 return JSONFailure;
dgabino 0:102b50f941d0 1642 }
dgabino 0:102b50f941d0 1643 dot_pos = strchr(name, '.');
dgabino 0:102b50f941d0 1644 if (dot_pos == NULL) {
dgabino 0:102b50f941d0 1645 return json_object_set_value(object, name, value);
dgabino 0:102b50f941d0 1646 } else {
dgabino 0:102b50f941d0 1647 current_name = parson_strndup(name, dot_pos - name);
dgabino 0:102b50f941d0 1648 temp_obj = json_object_get_object(object, current_name);
dgabino 0:102b50f941d0 1649 if (temp_obj == NULL) {
dgabino 0:102b50f941d0 1650 new_value = json_value_init_object();
dgabino 0:102b50f941d0 1651 if (new_value == NULL) {
dgabino 0:102b50f941d0 1652 parson_free(current_name);
dgabino 0:102b50f941d0 1653 return JSONFailure;
dgabino 0:102b50f941d0 1654 }
dgabino 0:102b50f941d0 1655 if (json_object_add(object, current_name, new_value) == JSONFailure) {
dgabino 0:102b50f941d0 1656 json_value_free(new_value);
dgabino 0:102b50f941d0 1657 parson_free(current_name);
dgabino 0:102b50f941d0 1658 return JSONFailure;
dgabino 0:102b50f941d0 1659 }
dgabino 0:102b50f941d0 1660 temp_obj = json_object_get_object(object, current_name);
dgabino 0:102b50f941d0 1661 }
dgabino 0:102b50f941d0 1662 parson_free(current_name);
dgabino 0:102b50f941d0 1663 return json_object_dotset_value(temp_obj, dot_pos + 1, value);
dgabino 0:102b50f941d0 1664 }
dgabino 0:102b50f941d0 1665 }
dgabino 0:102b50f941d0 1666
dgabino 0:102b50f941d0 1667 JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string) {
dgabino 0:102b50f941d0 1668 JSON_Value *value = json_value_init_string(string);
dgabino 0:102b50f941d0 1669 if (value == NULL) {
dgabino 0:102b50f941d0 1670 return JSONFailure;
dgabino 0:102b50f941d0 1671 }
dgabino 0:102b50f941d0 1672 if (json_object_dotset_value(object, name, value) == JSONFailure) {
dgabino 0:102b50f941d0 1673 json_value_free(value);
dgabino 0:102b50f941d0 1674 return JSONFailure;
dgabino 0:102b50f941d0 1675 }
dgabino 0:102b50f941d0 1676 return JSONSuccess;
dgabino 0:102b50f941d0 1677 }
dgabino 0:102b50f941d0 1678
dgabino 0:102b50f941d0 1679 JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number) {
dgabino 0:102b50f941d0 1680 JSON_Value *value = json_value_init_number(number);
dgabino 0:102b50f941d0 1681 if (value == NULL) {
dgabino 0:102b50f941d0 1682 return JSONFailure;
dgabino 0:102b50f941d0 1683 }
dgabino 0:102b50f941d0 1684 if (json_object_dotset_value(object, name, value) == JSONFailure) {
dgabino 0:102b50f941d0 1685 json_value_free(value);
dgabino 0:102b50f941d0 1686 return JSONFailure;
dgabino 0:102b50f941d0 1687 }
dgabino 0:102b50f941d0 1688 return JSONSuccess;
dgabino 0:102b50f941d0 1689 }
dgabino 0:102b50f941d0 1690
dgabino 0:102b50f941d0 1691 JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean) {
dgabino 0:102b50f941d0 1692 JSON_Value *value = json_value_init_boolean(boolean);
dgabino 0:102b50f941d0 1693 if (value == NULL) {
dgabino 0:102b50f941d0 1694 return JSONFailure;
dgabino 0:102b50f941d0 1695 }
dgabino 0:102b50f941d0 1696 if (json_object_dotset_value(object, name, value) == JSONFailure) {
dgabino 0:102b50f941d0 1697 json_value_free(value);
dgabino 0:102b50f941d0 1698 return JSONFailure;
dgabino 0:102b50f941d0 1699 }
dgabino 0:102b50f941d0 1700 return JSONSuccess;
dgabino 0:102b50f941d0 1701 }
dgabino 0:102b50f941d0 1702
dgabino 0:102b50f941d0 1703 JSON_Status json_object_dotset_null(JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1704 JSON_Value *value = json_value_init_null();
dgabino 0:102b50f941d0 1705 if (value == NULL) {
dgabino 0:102b50f941d0 1706 return JSONFailure;
dgabino 0:102b50f941d0 1707 }
dgabino 0:102b50f941d0 1708 if (json_object_dotset_value(object, name, value) == JSONFailure) {
dgabino 0:102b50f941d0 1709 json_value_free(value);
dgabino 0:102b50f941d0 1710 return JSONFailure;
dgabino 0:102b50f941d0 1711 }
dgabino 0:102b50f941d0 1712 return JSONSuccess;
dgabino 0:102b50f941d0 1713 }
dgabino 0:102b50f941d0 1714
dgabino 0:102b50f941d0 1715 JSON_Status json_object_remove(JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1716 size_t i = 0, last_item_index = 0;
dgabino 0:102b50f941d0 1717 if (object == NULL || json_object_get_value(object, name) == NULL) {
dgabino 0:102b50f941d0 1718 return JSONFailure;
dgabino 0:102b50f941d0 1719 }
dgabino 0:102b50f941d0 1720 last_item_index = json_object_get_count(object) - 1;
dgabino 0:102b50f941d0 1721 for (i = 0; i < json_object_get_count(object); i++) {
dgabino 0:102b50f941d0 1722 if (strcmp(object->names[i], name) == 0) {
dgabino 0:102b50f941d0 1723 parson_free(object->names[i]);
dgabino 0:102b50f941d0 1724 json_value_free(object->values[i]);
dgabino 0:102b50f941d0 1725 if (i != last_item_index) { /* Replace key value pair with one from the end */
dgabino 0:102b50f941d0 1726 object->names[i] = object->names[last_item_index];
dgabino 0:102b50f941d0 1727 object->values[i] = object->values[last_item_index];
dgabino 0:102b50f941d0 1728 }
dgabino 0:102b50f941d0 1729 object->count -= 1;
dgabino 0:102b50f941d0 1730 return JSONSuccess;
dgabino 0:102b50f941d0 1731 }
dgabino 0:102b50f941d0 1732 }
dgabino 0:102b50f941d0 1733 return JSONFailure; /* No execution path should end here */
dgabino 0:102b50f941d0 1734 }
dgabino 0:102b50f941d0 1735
dgabino 0:102b50f941d0 1736 JSON_Status json_object_dotremove(JSON_Object *object, const char *name) {
dgabino 0:102b50f941d0 1737 const char *dot_pos = strchr(name, '.');
dgabino 0:102b50f941d0 1738 char *current_name = NULL;
dgabino 0:102b50f941d0 1739 JSON_Object *temp_obj = NULL;
dgabino 0:102b50f941d0 1740 if (dot_pos == NULL) {
dgabino 0:102b50f941d0 1741 return json_object_remove(object, name);
dgabino 0:102b50f941d0 1742 } else {
dgabino 0:102b50f941d0 1743 current_name = parson_strndup(name, dot_pos - name);
dgabino 0:102b50f941d0 1744 temp_obj = json_object_get_object(object, current_name);
dgabino 0:102b50f941d0 1745 if (temp_obj == NULL) {
dgabino 0:102b50f941d0 1746 parson_free(current_name);
dgabino 0:102b50f941d0 1747 return JSONFailure;
dgabino 0:102b50f941d0 1748 }
dgabino 0:102b50f941d0 1749 parson_free(current_name);
dgabino 0:102b50f941d0 1750 return json_object_dotremove(temp_obj, dot_pos + 1);
dgabino 0:102b50f941d0 1751 }
dgabino 0:102b50f941d0 1752 }
dgabino 0:102b50f941d0 1753
dgabino 0:102b50f941d0 1754 JSON_Status json_object_clear(JSON_Object *object) {
dgabino 0:102b50f941d0 1755 size_t i = 0;
dgabino 0:102b50f941d0 1756 if (object == NULL) {
dgabino 0:102b50f941d0 1757 return JSONFailure;
dgabino 0:102b50f941d0 1758 }
dgabino 0:102b50f941d0 1759 for (i = 0; i < json_object_get_count(object); i++) {
dgabino 0:102b50f941d0 1760 parson_free(object->names[i]);
dgabino 0:102b50f941d0 1761 json_value_free(object->values[i]);
dgabino 0:102b50f941d0 1762 }
dgabino 0:102b50f941d0 1763 object->count = 0;
dgabino 0:102b50f941d0 1764 return JSONSuccess;
dgabino 0:102b50f941d0 1765 }
dgabino 0:102b50f941d0 1766
dgabino 0:102b50f941d0 1767 JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value) {
dgabino 0:102b50f941d0 1768 JSON_Value *temp_schema_value = NULL, *temp_value = NULL;
dgabino 0:102b50f941d0 1769 JSON_Array *schema_array = NULL, *value_array = NULL;
dgabino 0:102b50f941d0 1770 JSON_Object *schema_object = NULL, *value_object = NULL;
dgabino 0:102b50f941d0 1771 JSON_Value_Type schema_type = JSONError, value_type = JSONError;
dgabino 0:102b50f941d0 1772 const char *key = NULL;
dgabino 0:102b50f941d0 1773 size_t i = 0, count = 0;
dgabino 0:102b50f941d0 1774 if (schema == NULL || value == NULL) {
dgabino 0:102b50f941d0 1775 return JSONFailure;
dgabino 0:102b50f941d0 1776 }
dgabino 0:102b50f941d0 1777 schema_type = json_value_get_type(schema);
dgabino 0:102b50f941d0 1778 value_type = json_value_get_type(value);
dgabino 0:102b50f941d0 1779 if (schema_type != value_type && schema_type != JSONNull) { /* null represents all values */
dgabino 0:102b50f941d0 1780 return JSONFailure;
dgabino 0:102b50f941d0 1781 }
dgabino 0:102b50f941d0 1782 switch (schema_type) {
dgabino 0:102b50f941d0 1783 case JSONArray:
dgabino 0:102b50f941d0 1784 schema_array = json_value_get_array(schema);
dgabino 0:102b50f941d0 1785 value_array = json_value_get_array(value);
dgabino 0:102b50f941d0 1786 count = json_array_get_count(schema_array);
dgabino 0:102b50f941d0 1787 if (count == 0) {
dgabino 0:102b50f941d0 1788 return JSONSuccess; /* Empty array allows all types */
dgabino 0:102b50f941d0 1789 }
dgabino 0:102b50f941d0 1790 /* Get first value from array, rest is ignored */
dgabino 0:102b50f941d0 1791 temp_schema_value = json_array_get_value(schema_array, 0);
dgabino 0:102b50f941d0 1792 for (i = 0; i < json_array_get_count(value_array); i++) {
dgabino 0:102b50f941d0 1793 temp_value = json_array_get_value(value_array, i);
dgabino 0:102b50f941d0 1794 if (json_validate(temp_schema_value, temp_value) == 0) {
dgabino 0:102b50f941d0 1795 return JSONFailure;
dgabino 0:102b50f941d0 1796 }
dgabino 0:102b50f941d0 1797 }
dgabino 0:102b50f941d0 1798 return JSONSuccess;
dgabino 0:102b50f941d0 1799 case JSONObject:
dgabino 0:102b50f941d0 1800 schema_object = json_value_get_object(schema);
dgabino 0:102b50f941d0 1801 value_object = json_value_get_object(value);
dgabino 0:102b50f941d0 1802 count = json_object_get_count(schema_object);
dgabino 0:102b50f941d0 1803 if (count == 0) {
dgabino 0:102b50f941d0 1804 return JSONSuccess; /* Empty object allows all objects */
dgabino 0:102b50f941d0 1805 } else if (json_object_get_count(value_object) < count) {
dgabino 0:102b50f941d0 1806 return JSONFailure; /* Tested object mustn't have less name-value pairs than schema */
dgabino 0:102b50f941d0 1807 }
dgabino 0:102b50f941d0 1808 for (i = 0; i < count; i++) {
dgabino 0:102b50f941d0 1809 key = json_object_get_name(schema_object, i);
dgabino 0:102b50f941d0 1810 temp_schema_value = json_object_get_value(schema_object, key);
dgabino 0:102b50f941d0 1811 temp_value = json_object_get_value(value_object, key);
dgabino 0:102b50f941d0 1812 if (temp_value == NULL) {
dgabino 0:102b50f941d0 1813 return JSONFailure;
dgabino 0:102b50f941d0 1814 }
dgabino 0:102b50f941d0 1815 if (json_validate(temp_schema_value, temp_value) == JSONFailure) {
dgabino 0:102b50f941d0 1816 return JSONFailure;
dgabino 0:102b50f941d0 1817 }
dgabino 0:102b50f941d0 1818 }
dgabino 0:102b50f941d0 1819 return JSONSuccess;
dgabino 0:102b50f941d0 1820 case JSONString:
dgabino 0:102b50f941d0 1821 case JSONNumber:
dgabino 0:102b50f941d0 1822 case JSONBoolean:
dgabino 0:102b50f941d0 1823 case JSONNull:
dgabino 0:102b50f941d0 1824 return JSONSuccess; /* equality already tested before switch */
dgabino 0:102b50f941d0 1825 case JSONError:
dgabino 0:102b50f941d0 1826 default:
dgabino 0:102b50f941d0 1827 return JSONFailure;
dgabino 0:102b50f941d0 1828 }
dgabino 0:102b50f941d0 1829 }
dgabino 0:102b50f941d0 1830
dgabino 0:102b50f941d0 1831 JSON_Status json_value_equals(const JSON_Value *a, const JSON_Value *b) {
dgabino 0:102b50f941d0 1832 JSON_Object *a_object = NULL, *b_object = NULL;
dgabino 0:102b50f941d0 1833 JSON_Array *a_array = NULL, *b_array = NULL;
dgabino 0:102b50f941d0 1834 const char *a_string = NULL, *b_string = NULL;
dgabino 0:102b50f941d0 1835 const char *key = NULL;
dgabino 0:102b50f941d0 1836 size_t a_count = 0, b_count = 0, i = 0;
dgabino 0:102b50f941d0 1837 JSON_Value_Type a_type, b_type;
dgabino 0:102b50f941d0 1838 a_type = json_value_get_type(a);
dgabino 0:102b50f941d0 1839 b_type = json_value_get_type(b);
dgabino 0:102b50f941d0 1840 if (a_type != b_type) {
dgabino 0:102b50f941d0 1841 return 0;
dgabino 0:102b50f941d0 1842 }
dgabino 0:102b50f941d0 1843 switch (a_type) {
dgabino 0:102b50f941d0 1844 case JSONArray:
dgabino 0:102b50f941d0 1845 a_array = json_value_get_array(a);
dgabino 0:102b50f941d0 1846 b_array = json_value_get_array(b);
dgabino 0:102b50f941d0 1847 a_count = json_array_get_count(a_array);
dgabino 0:102b50f941d0 1848 b_count = json_array_get_count(b_array);
dgabino 0:102b50f941d0 1849 if (a_count != b_count) {
dgabino 0:102b50f941d0 1850 return 0;
dgabino 0:102b50f941d0 1851 }
dgabino 0:102b50f941d0 1852 for (i = 0; i < a_count; i++) {
dgabino 0:102b50f941d0 1853 if (!json_value_equals(json_array_get_value(a_array, i),
dgabino 0:102b50f941d0 1854 json_array_get_value(b_array, i))) {
dgabino 0:102b50f941d0 1855 return 0;
dgabino 0:102b50f941d0 1856 }
dgabino 0:102b50f941d0 1857 }
dgabino 0:102b50f941d0 1858 return 1;
dgabino 0:102b50f941d0 1859 case JSONObject:
dgabino 0:102b50f941d0 1860 a_object = json_value_get_object(a);
dgabino 0:102b50f941d0 1861 b_object = json_value_get_object(b);
dgabino 0:102b50f941d0 1862 a_count = json_object_get_count(a_object);
dgabino 0:102b50f941d0 1863 b_count = json_object_get_count(b_object);
dgabino 0:102b50f941d0 1864 if (a_count != b_count) {
dgabino 0:102b50f941d0 1865 return 0;
dgabino 0:102b50f941d0 1866 }
dgabino 0:102b50f941d0 1867 for (i = 0; i < a_count; i++) {
dgabino 0:102b50f941d0 1868 key = json_object_get_name(a_object, i);
dgabino 0:102b50f941d0 1869 if (!json_value_equals(json_object_get_value(a_object, key),
dgabino 0:102b50f941d0 1870 json_object_get_value(b_object, key))) {
dgabino 0:102b50f941d0 1871 return 0;
dgabino 0:102b50f941d0 1872 }
dgabino 0:102b50f941d0 1873 }
dgabino 0:102b50f941d0 1874 return 1;
dgabino 0:102b50f941d0 1875 case JSONString:
dgabino 0:102b50f941d0 1876 a_string = json_value_get_string(a);
dgabino 0:102b50f941d0 1877 b_string = json_value_get_string(b);
dgabino 0:102b50f941d0 1878 return strcmp(a_string, b_string) == 0;
dgabino 0:102b50f941d0 1879 case JSONBoolean:
dgabino 0:102b50f941d0 1880 return json_value_get_boolean(a) == json_value_get_boolean(b);
dgabino 0:102b50f941d0 1881 case JSONNumber:
dgabino 0:102b50f941d0 1882 return fabs(json_value_get_number(a) - json_value_get_number(b)) < 0.000001; /* EPSILON */
dgabino 0:102b50f941d0 1883 case JSONError:
dgabino 0:102b50f941d0 1884 return 1;
dgabino 0:102b50f941d0 1885 case JSONNull:
dgabino 0:102b50f941d0 1886 return 1;
dgabino 0:102b50f941d0 1887 default:
dgabino 0:102b50f941d0 1888 return 1;
dgabino 0:102b50f941d0 1889 }
dgabino 0:102b50f941d0 1890 }
dgabino 0:102b50f941d0 1891
dgabino 0:102b50f941d0 1892 JSON_Value_Type json_type(const JSON_Value *value) {
dgabino 0:102b50f941d0 1893 return json_value_get_type(value);
dgabino 0:102b50f941d0 1894 }
dgabino 0:102b50f941d0 1895
dgabino 0:102b50f941d0 1896 JSON_Object * json_object (const JSON_Value *value) {
dgabino 0:102b50f941d0 1897 return json_value_get_object(value);
dgabino 0:102b50f941d0 1898 }
dgabino 0:102b50f941d0 1899
dgabino 0:102b50f941d0 1900 JSON_Array * json_array (const JSON_Value *value) {
dgabino 0:102b50f941d0 1901 return json_value_get_array(value);
dgabino 0:102b50f941d0 1902 }
dgabino 0:102b50f941d0 1903
dgabino 0:102b50f941d0 1904 const char * json_string (const JSON_Value *value) {
dgabino 0:102b50f941d0 1905 return json_value_get_string(value);
dgabino 0:102b50f941d0 1906 }
dgabino 0:102b50f941d0 1907
dgabino 0:102b50f941d0 1908 double json_number (const JSON_Value *value) {
dgabino 0:102b50f941d0 1909 return json_value_get_number(value);
dgabino 0:102b50f941d0 1910 }
dgabino 0:102b50f941d0 1911
dgabino 0:102b50f941d0 1912 int json_boolean(const JSON_Value *value) {
dgabino 0:102b50f941d0 1913 return json_value_get_boolean(value);
dgabino 0:102b50f941d0 1914 }
dgabino 0:102b50f941d0 1915
dgabino 0:102b50f941d0 1916 void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun) {
dgabino 0:102b50f941d0 1917 parson_malloc = malloc_fun;
dgabino 0:102b50f941d0 1918 parson_free = free_fun;
dgabino 0:102b50f941d0 1919 }