00001
00002 #define _GNU_SOURCE
00003
00004 #include <microfeed-provider/microfeedjson.h>
00005 #include <microfeed-common/microfeedstore.h>
00006 #include <microfeed-common/microfeedmisc.h>
00007 #include <unistd.h>
00008 #include <string.h>
00009 #include <stdio.h>
00010 #include <stdarg.h>
00011
00012 struct _MicrofeedJson {
00013 MicrofeedJson* parent;
00014 MicrofeedStore* members;
00015 };
00016
00017 typedef struct {
00018 char* name;
00019 MicrofeedJsonType type;
00020 union {
00021 MicrofeedJson* object;
00022 MicrofeedJson* array;
00023 char* string;
00024 long long int integer;
00025 double decimal;
00026 int boolean;
00027 };
00028 char* as_string;
00029 } Member;
00030
00031 typedef struct {
00032 MicrofeedJson* json;
00033 MicrofeedJsonCompareMembersFunction compare_members;
00034 void* user_data;
00035 } SortData;
00036
00037 static Member* member_new(char* name, MicrofeedJsonType type);
00038 static void member_free(Member* member);
00039 static const char* member_get_name(Member* member);
00040 static const char* member_as_string(Member* member);
00041 static char* member_to_string(Member* member);
00042 static Member* parse_value(char* name, const char** data, const char* end);
00043 static MicrofeedJson* parse_object(const char** data, const char* end);
00044 static MicrofeedJson* parse_array(const char** data, const char* end);
00045 static char* parse_string(const char** data, const char* end);
00046 static Member* parse_number(char* name, const char** data, const char* end);
00047 static void eat_whitespaces(const char** data, const char* end);
00048 static int are_next_characters(const char* next, size_t next_length, const char** data, const char* end);
00049 static int hex_to_int(char hex, unsigned int* int_return);
00050 int compare_json_members_in_sort(const void* data1, const void* data2, unsigned int index1, unsigned int index2, void* user_data);
00051
00052 MicrofeedJson* microfeed_json_new_object(void) {
00053 MicrofeedJson* json;
00054
00055 json = microfeed_memory_allocate(MicrofeedJson);
00056 json->members = microfeed_store_new_sorted((MicrofeedStoreCompareKeysFunction)strcmp, (MicrofeedStoreGetKeyFunction)member_get_name);
00057
00058 return json;
00059 }
00060
00061 MicrofeedJson* microfeed_json_new_array(void) {
00062 MicrofeedJson* json;
00063
00064 json = microfeed_memory_allocate(MicrofeedJson);
00065 json->members = microfeed_store_new_unsorted((MicrofeedStoreCompareKeysFunction)strcmp, (MicrofeedStoreGetKeyFunction)member_get_name);
00066
00067 return json;
00068 }
00069
00070 MicrofeedJson* microfeed_json_new_from_data(const char* data, size_t length) {
00071 MicrofeedJson* json = NULL;
00072 Member* member;
00073
00074 if ((member = parse_value(NULL, &data, data + length))) {
00075 if (member->type == MICROFEED_JSON_TYPE_OBJECT) {
00076 json = member->object;
00077 member->object = NULL;
00078 } else if (member->type == MICROFEED_JSON_TYPE_ARRAY) {
00079 json = member->array;
00080 member->array = NULL;
00081 }
00082 member_free(member);
00083 } else {
00084 printf("JSON parsing failed: %s\n", data);
00085 }
00086
00087 return json;
00088 }
00089
00090 void microfeed_json_free(MicrofeedJson* json) {
00091 if (json) {
00092 if (json->parent) {
00093
00094 }
00095 microfeed_store_foreach(json->members, (MicrofeedStoreForeachFunction)member_free, NULL);
00096 microfeed_store_free(json->members);
00097 microfeed_memory_free(json);
00098 }
00099 }
00100
00101 int microfeed_json_is_array(MicrofeedJson* json) {
00102
00103 return !microfeed_store_is_sorted(json->members);
00104 }
00105
00106 MicrofeedJson* microfeed_json_get_parent(MicrofeedJson* json) {
00107
00108 return json->parent;
00109 }
00110
00111 unsigned int microfeed_json_get_size(MicrofeedJson* json) {
00112
00113 return microfeed_store_get_size(json->members);
00114 }
00115
00116 MicrofeedJsonType microfeed_json_get_type(MicrofeedJson* json, const char* name) {
00117 MicrofeedJsonType type = MICROFEED_JSON_TYPE_NULL;
00118 Member* member;
00119
00120 if (name) {
00121 if ((member = microfeed_store_get(json->members, name, Member))) {
00122 type = member->type;
00123 }
00124 } else {
00125 type = (microfeed_store_is_sorted(json->members) ? MICROFEED_JSON_TYPE_OBJECT : MICROFEED_JSON_TYPE_ARRAY);
00126 }
00127
00128 return type;
00129 }
00130
00131 MicrofeedJsonType microfeed_json_get_type_by_index(MicrofeedJson* json, unsigned int index) {
00132 MicrofeedJsonType type = MICROFEED_JSON_TYPE_NULL;
00133 Member* member;
00134
00135 if ((member = microfeed_store_get_index(json->members, index, Member))) {
00136 type = member->type;
00137 }
00138
00139 return type;
00140 }
00141
00142 MicrofeedJsonType microfeed_json_get_type_by_path(MicrofeedJson* json, const char* name, ...) {
00143 MicrofeedJsonType type = MICROFEED_JSON_TYPE_NULL;
00144 Member* member;
00145 va_list argp;
00146 const char* s;
00147
00148 if ((member = microfeed_store_get(json->members, name, Member))) {
00149 va_start(argp, name);
00150 while ((s = va_arg(argp, const char*)) && member->type == MICROFEED_JSON_TYPE_OBJECT &&
00151 (member = microfeed_store_get(member->object->members, s, Member))) {
00152 }
00153 va_end(argp);
00154 if (!s) {
00155 type = member->type;
00156 }
00157 }
00158
00159 return type;
00160 }
00161
00162 int microfeed_json_is_null(MicrofeedJson* json, const char* name) {
00163 int retvalue = 1;
00164 Member* member;
00165
00166 if (name) {
00167 if ((member = microfeed_store_get(json->members, name, Member))) {
00168 retvalue = (member->type == MICROFEED_JSON_TYPE_NULL);
00169 }
00170 } else {
00171 retvalue = 0;
00172 }
00173
00174 return retvalue;
00175 }
00176
00177 const char* microfeed_json_get_name_by_index(MicrofeedJson* json, unsigned int index) {
00178 const char* name = NULL;
00179 Member* member;
00180
00181 if ((member = microfeed_store_get_index(json->members, index, Member))) {
00182 name = member->name;
00183 }
00184
00185 return name;
00186 }
00187
00188 int microfeed_json_is_null_by_index(MicrofeedJson* json, unsigned int index) {
00189 int retvalue = 1;
00190 Member* member;
00191
00192 if ((member = microfeed_store_get_index(json->members, index, Member))) {
00193 retvalue = (member->type == MICROFEED_JSON_TYPE_NULL);
00194 }
00195
00196 return retvalue;
00197 }
00198
00199 int microfeed_json_is_null_by_path(MicrofeedJson* json,const char* name, ...) {
00200 int retvalue = 1;
00201 Member* member;
00202 va_list argp;
00203 const char* s;
00204
00205 if ((member = microfeed_store_get(json->members, name, Member))) {
00206 va_start(argp, name);
00207 while ((s = va_arg(argp, const char*)) && member->type == MICROFEED_JSON_TYPE_OBJECT &&
00208 (member = microfeed_store_get(member->object->members, s, Member))) {
00209 }
00210 va_end(argp);
00211 if (!s) {
00212 retvalue = (member->type == MICROFEED_JSON_TYPE_NULL);
00213 }
00214 }
00215
00216 return retvalue;
00217 }
00218
00219 MicrofeedJson* microfeed_json_get_object(MicrofeedJson* json, const char* name) {
00220 MicrofeedJson* object = NULL;
00221 Member* member;
00222
00223 if (name) {
00224 if ((member = microfeed_store_get(json->members, name, Member)) && member->type == MICROFEED_JSON_TYPE_OBJECT) {
00225 object = member->object;
00226 }
00227 } else {
00228 if (microfeed_store_is_sorted(json->members)) {
00229 object = json;
00230 }
00231 }
00232
00233 return object;
00234 }
00235
00236 MicrofeedJson* microfeed_json_get_object_by_index(MicrofeedJson* json, unsigned int index) {
00237 MicrofeedJson* object = NULL;
00238 Member* member;
00239
00240 if ((member = microfeed_store_get_index(json->members, index, Member)) && member->type == MICROFEED_JSON_TYPE_OBJECT) {
00241 object = member->object;
00242 }
00243
00244 return object;
00245 }
00246
00247 MicrofeedJson* microfeed_json_get_object_by_path(MicrofeedJson* json, const char* name, ...) {
00248 MicrofeedJson* object = NULL;
00249 Member* member;
00250 va_list argp;
00251 const char* s;
00252
00253 if ((member = microfeed_store_get(json->members, name, Member))) {
00254 va_start(argp, name);
00255 while ((s = va_arg(argp, const char*)) && member->type == MICROFEED_JSON_TYPE_OBJECT &&
00256 (member = microfeed_store_get(member->object->members, s, Member))) {
00257 }
00258 va_end(argp);
00259 if (!s && member->type == MICROFEED_JSON_TYPE_OBJECT) {
00260 object = member->object;
00261 }
00262 }
00263
00264 return object;
00265 }
00266
00267 MicrofeedJson* microfeed_json_get_array(MicrofeedJson* json, const char* name) {
00268 MicrofeedJson* array = NULL;
00269 Member* member;
00270
00271 if (name) {
00272 if ((member = microfeed_store_get(json->members, name, Member)) && member->type == MICROFEED_JSON_TYPE_ARRAY) {
00273 array = member->array;
00274 }
00275 } else {
00276 if (!microfeed_store_is_sorted(json->members)) {
00277 array = json;
00278 }
00279 }
00280
00281 return array;
00282 }
00283
00284 MicrofeedJson* microfeed_json_get_array_by_index(MicrofeedJson* json, unsigned int index) {
00285 MicrofeedJson* array = NULL;
00286 Member* member;
00287
00288 if ((member = microfeed_store_get_index(json->members, index, Member)) && member->type == MICROFEED_JSON_TYPE_ARRAY) {
00289 array = member->array;
00290 }
00291
00292 return array;
00293 }
00294
00295 MicrofeedJson* microfeed_json_get_array_by_path(MicrofeedJson* json, const char* name, ...) {
00296 MicrofeedJson* array = NULL;
00297 Member* member;
00298 va_list argp;
00299 const char* s;
00300
00301 if ((member = microfeed_store_get(json->members, name, Member))) {
00302 va_start(argp, name);
00303 while ((s = va_arg(argp, const char*)) && member->type == MICROFEED_JSON_TYPE_OBJECT &&
00304 (member = microfeed_store_get(member->object->members, s, Member))) {
00305 }
00306 va_end(argp);
00307 if (!s && member->type == MICROFEED_JSON_TYPE_ARRAY) {
00308 array = member->array;
00309 }
00310 }
00311
00312 return array;
00313 }
00314
00315 const char* microfeed_json_get_string(MicrofeedJson* json, const char* name) {
00316 const char* string = NULL;
00317 Member* member;
00318
00319 if (name) {
00320 if ((member = microfeed_store_get(json->members, name, Member)) && member->type == MICROFEED_JSON_TYPE_STRING) {
00321 string = member->string;
00322 }
00323 }
00324
00325 return string;
00326 }
00327
00328 const char* microfeed_json_get_string_by_index(MicrofeedJson* json, unsigned int index) {
00329 const char* string = NULL;
00330 Member* member;
00331
00332 if ((member = microfeed_store_get_index(json->members, index, Member)) && member->type == MICROFEED_JSON_TYPE_STRING) {
00333 string = member->string;
00334 }
00335
00336 return string;
00337 }
00338
00339 const char* microfeed_json_get_string_by_path(MicrofeedJson* json, const char* name, ...) {
00340 const char* string = NULL;
00341 Member* member;
00342 va_list argp;
00343 const char* s;
00344
00345 if ((member = microfeed_store_get(json->members, name, Member))) {
00346 va_start(argp, name);
00347 while ((s = va_arg(argp, const char*)) && member->type == MICROFEED_JSON_TYPE_OBJECT &&
00348 (member = microfeed_store_get(member->object->members, s, Member))) {
00349 }
00350 va_end(argp);
00351 if (!s && member->type == MICROFEED_JSON_TYPE_STRING) {
00352 string = member->string;
00353 }
00354 }
00355
00356 return string;
00357 }
00358
00359 int microfeed_json_get_boolean(MicrofeedJson* json, const char* name) {
00360 int boolean = 0;
00361 Member* member;
00362
00363 if ((member = microfeed_store_get(json->members, name, Member)) && member->type == MICROFEED_JSON_TYPE_BOOLEAN) {
00364 boolean = member->boolean;
00365 }
00366
00367 return boolean;
00368 }
00369
00370 int microfeed_json_get_boolean_by_index(MicrofeedJson* json, unsigned int index) {
00371 int boolean = 0;
00372 Member* member;
00373
00374 if ((member = microfeed_store_get_index(json->members, index, Member)) && member->type == MICROFEED_JSON_TYPE_BOOLEAN) {
00375 boolean = member->boolean;
00376 }
00377
00378 return boolean;
00379 }
00380
00381 int microfeed_json_get_boolean_by_path(MicrofeedJson* json, const char* name, ...) {
00382 int boolean = 0;
00383 Member* member;
00384 va_list argp;
00385 const char* s;
00386
00387 if ((member = microfeed_store_get(json->members, name, Member))) {
00388 va_start(argp, name);
00389 while ((s = va_arg(argp, const char*)) && member->type == MICROFEED_JSON_TYPE_OBJECT &&
00390 (member = microfeed_store_get(member->object->members, s, Member))) {
00391 }
00392 va_end(argp);
00393 if (!s && member->type == MICROFEED_JSON_TYPE_BOOLEAN) {
00394 boolean = member->boolean;
00395 }
00396 }
00397
00398 return boolean;
00399 }
00400
00401 const char* microfeed_json_get_as_string(MicrofeedJson* json, const char* name) {
00402 const char* string = NULL;
00403 Member* member;
00404
00405 if (name) {
00406 if ((member = microfeed_store_get(json->members, name, Member))) {
00407 string = member_as_string(member);
00408 }
00409 }
00410
00411 return string;
00412 }
00413
00414 const char* microfeed_json_get_as_string_by_index(MicrofeedJson* json, unsigned int index) {
00415 const char* string = NULL;
00416 Member* member;
00417
00418 if ((member = microfeed_store_get_index(json->members, index, Member))) {
00419 string = member_as_string(member);
00420 }
00421
00422 return string;
00423 }
00424
00425 const char* microfeed_json_get_as_string_by_path(MicrofeedJson* json, const char* name, ...) {
00426 const char* string = NULL;
00427 Member* member;
00428 va_list argp;
00429 const char* s;
00430
00431 if ((member = microfeed_store_get(json->members, name, Member))) {
00432 va_start(argp, name);
00433 while ((s = va_arg(argp, const char*)) && member->type == MICROFEED_JSON_TYPE_OBJECT &&
00434 (member = microfeed_store_get(member->object->members, s, Member))) {
00435 }
00436 va_end(argp);
00437 if (!s) {
00438 string = member_as_string(member);
00439 }
00440 }
00441
00442 return string;
00443 }
00444
00445 char* microfeed_json_to_string(MicrofeedJson* json, const char* name) {
00446 char* string = NULL;
00447 Member* member;
00448 size_t size;
00449 unsigned int i;
00450 MicrofeedStoreIterator* iterator;
00451 size_t length1;
00452 size_t length2;
00453 char* s;
00454
00455 if (name) {
00456 if ((member = microfeed_store_get(json->members, name, Member))) {
00457 string = member_to_string(member);
00458 } else {
00459 string = strdup("null");
00460 }
00461 } else {
00462 size = 2;
00463 string = (char*)malloc(size + 1);
00464 i = 1;
00465 string[i] = ' ';
00466 for (iterator = microfeed_store_iterate(json->members, NULL);
00467 (member = microfeed_store_iterator_get(iterator, Member));
00468 microfeed_store_iterator_next(iterator)) {
00469 if (member->name) {
00470 length1 = strlen(member->name);
00471 size += length1 + 3;
00472 } else {
00473 length1 = 0;
00474 }
00475 s = member_to_string(member);
00476 length2 = strlen(s);
00477 size += length2 + 1;
00478 string = (char*)realloc(string, size + 1);
00479 if (length1) {
00480 string[i++] = '"';
00481 memcpy(string + i, member->name, length1);
00482 i += length1;
00483 string[i++] = '"';
00484 string[i++] = ':';
00485 }
00486 memcpy(string + i, s, length2);
00487 i += length2;
00488 string[i++] = ',';
00489 free(s);
00490
00491 }
00492 microfeed_store_iterator_free(iterator);
00493 if (microfeed_store_is_sorted(json->members)) {
00494 string[0] = '{';
00495 string[size - 1] = '}';
00496 } else {
00497 string[0] = '[';
00498 string[size - 1] = ']';
00499 }
00500 string[size] = 0;
00501 }
00502
00503 return string;
00504 }
00505
00506 char* microfeed_json_to_string_by_index(MicrofeedJson* json, unsigned int index) {
00507 char* string = NULL;
00508 Member* member;
00509
00510 if ((member = microfeed_store_get_index(json->members, index, Member))) {
00511 string = member_to_string(member);
00512 } else {
00513 string = strdup("null");
00514 }
00515
00516 return string;
00517 }
00518
00519 char* microfeed_json_to_string_by_path(MicrofeedJson* json, const char* name, ...);
00520
00521 void microfeed_json_set_null(MicrofeedJson* json, const char* name) {
00522 Member* member;
00523
00524 member = member_new(strdup(name), MICROFEED_JSON_TYPE_NULL);
00525 if ((member = microfeed_store_replace(json->members, member, Member))) {
00526 member_free(member);
00527 }
00528 }
00529
00530 void microfeed_json_append_null(MicrofeedJson* json, MicrofeedJson* object) {
00531 Member* member;
00532
00533 member = member_new(NULL, MICROFEED_JSON_TYPE_NULL);
00534 microfeed_store_insert(json->members, member);
00535 }
00536
00537 void microfeed_json_set_object(MicrofeedJson* json, const char* name, MicrofeedJson* object) {
00538 Member* member;
00539
00540 member = member_new(strdup(name), MICROFEED_JSON_TYPE_OBJECT);
00541 member->object = object;
00542 if ((member = microfeed_store_replace(json->members, member, Member))) {
00543 member_free(member);
00544 }
00545 }
00546
00547 void microfeed_json_append_object(MicrofeedJson* json, MicrofeedJson* object) {
00548 Member* member;
00549
00550 member = member_new(NULL, MICROFEED_JSON_TYPE_OBJECT);
00551 member->object = object;
00552 microfeed_store_insert(json->members, member);
00553 }
00554
00555 void microfeed_json_set_string(MicrofeedJson* json, const char* name, const char* string) {
00556 Member* member;
00557
00558 member = member_new(strdup(name), MICROFEED_JSON_TYPE_STRING);
00559 member->string = strdup(string);
00560 if ((member = microfeed_store_replace(json->members, member, Member))) {
00561 member_free(member);
00562 }
00563 }
00564
00565 void microfeed_json_append_string(MicrofeedJson* json, const char* string) {
00566 Member* member;
00567
00568 member = member_new(NULL, MICROFEED_JSON_TYPE_STRING);
00569 member->string = strdup(string);
00570 microfeed_store_insert(json->members, member);
00571 }
00572
00573 void microfeed_json_set_boolean(MicrofeedJson* json, const char* name, int boolean) {
00574 Member* member;
00575
00576 member = member_new(strdup(name), MICROFEED_JSON_TYPE_BOOLEAN);
00577 member->boolean = boolean;
00578 if ((member = microfeed_store_replace(json->members, member, Member))) {
00579 member_free(member);
00580 }
00581 }
00582
00583 void microfeed_json_append_boolean(MicrofeedJson* json, int boolean) {
00584 Member* member;
00585
00586 member = member_new(NULL, MICROFEED_JSON_TYPE_BOOLEAN);
00587 member->boolean = boolean;
00588 microfeed_store_insert(json->members, member);
00589 }
00590
00591
00592 void microfeed_json_sort_array(MicrofeedJson* json, MicrofeedJsonCompareMembersFunction compare_members, void* user_data) {
00593 SortData* sort_data;
00594
00595 sort_data = microfeed_memory_allocate(SortData);
00596 sort_data->json = json;
00597 sort_data->compare_members = compare_members;
00598 sort_data->user_data = user_data;
00599 microfeed_store_sort(json->members, compare_json_members_in_sort, sort_data);
00600 microfeed_memory_free(sort_data);
00601 }
00602
00603 int microfeed_json_compare_members(MicrofeedJson* json, unsigned int index1, unsigned int index2) {
00604 int retvalue = 0;
00605 Member* member1;
00606 Member* member2;
00607
00608 if (json &&
00609 (member1 = microfeed_store_get_index(json->members, index1, Member)) &&
00610 (member2 = microfeed_store_get_index(json->members, index2, Member)) &&
00611 member1->type == member2->type) {
00612 switch (member1->type) {
00613 case MICROFEED_JSON_TYPE_INTEGER:
00614 retvalue = (member1->integer < member2->integer ? -1 : (member1->integer > member2->integer ? + 1 : 0));
00615 break;
00616 case MICROFEED_JSON_TYPE_DECIMAL:
00617 retvalue = member1->decimal - member2->decimal;
00618 break;
00619 case MICROFEED_JSON_TYPE_STRING:
00620 retvalue = strcmp(member1->string, member2->string);
00621 break;
00622 case MICROFEED_JSON_TYPE_BOOLEAN:
00623 retvalue = (member1->boolean == member2->boolean ? 0 : (!member1->boolean && member2->boolean ? -1 : 1));
00624 break;
00625 default:
00626
00627 break;
00628 }
00629 }
00630
00631 return retvalue;
00632 }
00633
00634
00635
00636
00637
00638 static Member* member_new(char* name, MicrofeedJsonType type) {
00639 Member* member;
00640
00641 member = microfeed_memory_allocate(Member);
00642 member->name = name;
00643 member->type = type;
00644
00645 return member;
00646 }
00647
00648 static void member_free(Member* member) {
00649 if (member->type == MICROFEED_JSON_TYPE_OBJECT || member->type == MICROFEED_JSON_TYPE_ARRAY) {
00650 if (member->object) {
00651 member->object->parent = NULL;
00652 microfeed_json_free(member->object);
00653 }
00654 } else if (member->type == MICROFEED_JSON_TYPE_STRING) {
00655 free(member->string);
00656 }
00657 free(member->name);
00658 free(member->as_string);
00659 microfeed_memory_free(member);
00660 }
00661
00662 static const char* member_get_name(Member* member) {
00663
00664 return member->name;
00665 }
00666
00667 static const char* member_as_string(Member* member) {
00668 const char* string;
00669 char buffer[1024];
00670
00671 switch (member->type) {
00672 case MICROFEED_JSON_TYPE_NULL:
00673 string = "null";
00674 break;
00675 case MICROFEED_JSON_TYPE_OBJECT:
00676 case MICROFEED_JSON_TYPE_ARRAY:
00677 string = "<object>";
00678 break;
00679 case MICROFEED_JSON_TYPE_INTEGER:
00680 if (!member->as_string) {
00681 snprintf(buffer, 1024, "%lld", member->integer);
00682 member->as_string = strdup(buffer);
00683 }
00684 string = member->as_string;
00685 break;
00686 case MICROFEED_JSON_TYPE_DECIMAL:
00687 if (!member->as_string) {
00688 snprintf(buffer, 1024, "%lf", member->decimal);
00689 member->as_string = strdup(buffer);
00690 }
00691 string = member->as_string;
00692 break;
00693 case MICROFEED_JSON_TYPE_STRING:
00694 string = member->string;
00695 break;
00696 case MICROFEED_JSON_TYPE_BOOLEAN:
00697 if (member->boolean) {
00698 string = "true";
00699 } else {
00700 string = "false";
00701 }
00702 break;
00703 default:
00704
00705 exit(1);
00706 }
00707
00708 return string;
00709 }
00710
00711 static char* member_to_string(Member* member) {
00712 char* string = NULL;
00713 char buffer[1024];
00714
00715 switch (member->type) {
00716 case MICROFEED_JSON_TYPE_NULL:
00717 string = strdup("null");
00718 break;
00719 case MICROFEED_JSON_TYPE_OBJECT:
00720 case MICROFEED_JSON_TYPE_ARRAY:
00721 string = microfeed_json_to_string(member->object, NULL);
00722 break;
00723 case MICROFEED_JSON_TYPE_INTEGER:
00724 snprintf(buffer, 1024, "%lld", member->integer);
00725 string = strdup(buffer);
00726 break;
00727 case MICROFEED_JSON_TYPE_DECIMAL:
00728 snprintf(buffer, 1024, "%lf", member->decimal);
00729 string = strdup(buffer);
00730 break;
00731 case MICROFEED_JSON_TYPE_STRING:
00732
00733 string = microfeed_util_string_concatenate("\"", member->string, "\"", NULL);
00734 break;
00735 case MICROFEED_JSON_TYPE_BOOLEAN:
00736 if (member->boolean) {
00737 string = strdup("true");
00738 } else {
00739 string = strdup("false");
00740 }
00741 break;
00742 default:
00743
00744 exit(1);
00745 }
00746
00747 return string;
00748 }
00749
00750
00751
00752
00753
00754 static Member* parse_value(char* name, const char** data, const char* end) {
00755 Member* member = NULL;
00756
00757 eat_whitespaces(data, end);
00758 if (*data < end) {
00759 switch(**data) {
00760 case 'f':
00761 case 'F':
00762 if (are_next_characters("alse", 4, data, end)) {
00763 member = member_new(name, MICROFEED_JSON_TYPE_BOOLEAN);
00764 member->boolean = 0;
00765 }
00766 break;
00767 case 't':
00768 case 'T':
00769 if (are_next_characters("rue", 3, data, end)) {
00770 member = member_new(name, MICROFEED_JSON_TYPE_BOOLEAN);
00771 member->boolean = 1;
00772 }
00773 break;
00774 case 'n':
00775 case 'N':
00776 if (are_next_characters("ull", 3, data, end)) {
00777 member = member_new(name, MICROFEED_JSON_TYPE_NULL);
00778 }
00779 break;
00780 case '{':
00781 (*data)++;
00782 member = member_new(name, MICROFEED_JSON_TYPE_OBJECT);
00783 if (!(member->object = parse_object(data, end))) {
00784 member_free(member);
00785 member = NULL;
00786 }
00787 break;
00788 case '[':
00789 (*data)++;
00790 member = member_new(name, MICROFEED_JSON_TYPE_ARRAY);
00791 if (!(member->array = parse_array(data, end))) {
00792 member_free(member);
00793 member = NULL;
00794 }
00795 break;
00796 case '"':
00797 member = member_new(name, MICROFEED_JSON_TYPE_STRING);
00798 if (!(member->string = parse_string(data, end))) {
00799 member_free(member);
00800 member = NULL;
00801 }
00802 break;
00803 case '-':
00804 case '0':
00805 case '1':
00806 case '2':
00807 case '3':
00808 case '4':
00809 case '5':
00810 case '6':
00811 case '7':
00812 case '8':
00813 case '9':
00814 member = parse_number(name, data, end);
00815 break;
00816 }
00817 }
00818
00819 return member;
00820 }
00821
00822 static MicrofeedJson* parse_object(const char** data, const char* end) {
00823 MicrofeedJson* json;
00824 char* name;
00825 Member* member;
00826
00827 json = microfeed_json_new_object();
00828 while ((name = parse_string(data, end))) {
00829 eat_whitespaces(data, end);
00830 if (*data >= end || **data != ':') {
00831 microfeed_json_free(json);
00832 json = NULL;
00833 break;
00834 }
00835 (*data)++;
00836 if ((member = parse_value(name, data, end))) {
00837 if (!microfeed_store_insert(json->members, member)) {
00838 member_free(member);
00839 }
00840 } else {
00841 free(name);
00842 microfeed_json_free(json);
00843 json = NULL;
00844 break;
00845 }
00846 eat_whitespaces(data, end);
00847 if (*data >= end || **data != ',') {
00848 break;
00849 }
00850 (*data)++;
00851 }
00852 if (*data < end && **data == '}') {
00853 (*data)++;
00854 } else {
00855 microfeed_json_free(json);
00856 json = NULL;
00857 }
00858
00859 return json;
00860 }
00861
00862 static MicrofeedJson* parse_array(const char** data, const char* end) {
00863 MicrofeedJson* json;
00864 Member* member;
00865
00866 json = microfeed_json_new_array();
00867 while ((member = parse_value(NULL, data, end))) {
00868 if (!microfeed_store_insert(json->members, member)) {
00869 member_free(member);
00870 }
00871 eat_whitespaces(data, end);
00872 if (*data >= end || **data != ',') {
00873 break;
00874 }
00875 (*data)++;
00876 }
00877 if (*data < end && **data == ']') {
00878 (*data)++;
00879 } else {
00880 microfeed_json_free(json);
00881 json = NULL;
00882 }
00883
00884 return json;
00885 }
00886
00887 static char* parse_string(const char** data, const char* end) {
00888 char* string = NULL;
00889 size_t size = 0;
00890 unsigned int i = 0;
00891 const char* p;
00892 unsigned int hex1, hex2, hex3, hex4, hex;
00893
00894 eat_whitespaces(data, end);
00895 if (*data < end && **data == '"') {
00896 for (p = ++(*data); p < end && *p != '"'; p++) {
00897 if (i + 4 > size) {
00898 size += 1024;
00899 string = (char*)realloc(string, size);
00900 }
00901 if (*p == '\\') {
00902 p++;
00903 if (p < end) {
00904 if (*p == '"' || *p == '\\' || *p == '/') {
00905 string[i++] = *p;
00906 } else if (*p == 'b') {
00907 string[i++] = '\b';
00908 } else if (*p == 'f') {
00909 string[i++] = '\f';
00910 } else if (*p == 'n') {
00911 string[i++] = '\n';
00912 } else if (*p == 'r') {
00913 string[i++] = '\r';
00914 } else if (*p == 't') {
00915 string[i++] = '\t';
00916 } else if (*p == 'u') {
00917 p++;
00918 if (p + 3 < end &&
00919 hex_to_int(p[0], &hex1) && hex_to_int(p[1], &hex2) &&
00920 hex_to_int(p[2], &hex3) && hex_to_int(p[3], &hex4)) {
00921 hex = (hex1 << 12) | (hex2 << 8) | (hex3 << 4) | hex4;
00922 if (hex == 0) {
00923 string[i++] = ' ';
00924 } else if (hex < 0x80) {
00925 string[i++] = hex;
00926 } else if (hex < 0x800) {
00927 string[i++] = (char)(0xc0 | (hex >> 6));
00928 string[i++] = (char)(0x80 | (hex & 0x3f));
00929 } else {
00930 string[i++] = (char)(0xe0 | (hex >> 12));
00931 string[i++] = (char)(0x80 | ((hex >> 6) & 0x3f));
00932 string[i++] = (char)(0x80 | (hex & 0x3f));
00933 }
00934 p += 3;
00935 } else {
00936 break;
00937 }
00938 } else {
00939 break;
00940 }
00941 } else {
00942 break;
00943 }
00944 } else {
00945 string[i++] = *p;
00946 }
00947 }
00948 if (p < end && *p == '"') {
00949 string = (char*)realloc(string, i + 1);
00950 string[i] = 0;
00951 *data = p + 1;
00952 } else {
00953 free(string);
00954 string = NULL;
00955 *data = p;
00956 }
00957 }
00958
00959 return string;
00960 }
00961
00962 static Member* parse_number(char* name, const char** data, const char* end) {
00963 Member* member = NULL;
00964 const char* p;
00965 int decimal = 0;
00966 char* s;
00967 double d;
00968 long long int i;
00969
00970 p = *data;
00971 while (p < end && strchr("0123456789.eE+-", *p)) {
00972 if (*p == '.' || *p == 'e' || *p == 'E') {
00973 decimal = 1;
00974 }
00975 p++;
00976 }
00977 s = strndup(*data, p - *data);
00978 if (decimal) {
00979 if (sscanf(s, "%lf", &d) == 1) {
00980 member = member_new(name, MICROFEED_JSON_TYPE_DECIMAL);
00981 member->decimal = d;
00982 }
00983 } else {
00984 if (sscanf(s, "%lld", &i) == 1) {
00985 member = member_new(name, MICROFEED_JSON_TYPE_INTEGER);
00986 member->integer = i;
00987 }
00988 }
00989 free(s);
00990 *data = p;
00991
00992 return member;
00993 }
00994
00995 static void eat_whitespaces(const char** data, const char* end) {
00996 while (*data < end && (**data == 0x20 || **data == 0x09 || **data == 0x0A || **data == 0x0D)) {
00997 (*data)++;
00998 }
00999 }
01000
01001 static int are_next_characters(const char* next, size_t next_length, const char** data, const char* end) {
01002 size_t offset;
01003
01004 if (*data + next_length + 1 < end) {
01005 for (offset = 0; offset < next_length; offset++) {
01006 if (((*data)[offset + 1] | 0x20) != next[offset]) {
01007
01008 return 1;
01009 }
01010 }
01011 }
01012 *data += 1 + next_length;
01013
01014 return 1;
01015 }
01016
01017 static int hex_to_int(char hex, unsigned int* int_return) {
01018 int retvalue = 0;
01019
01020 if (hex >= '0' && hex <= '9') {
01021 *int_return = hex - '0';
01022 retvalue = 1;
01023 } else if (hex >= 'a' || hex <= 'f') {
01024 *int_return = hex - 'a' + 10;
01025 retvalue = 1;
01026 } else if (hex >= 'A' || hex <= 'F') {
01027 *int_return = hex - 'A' + 10;
01028 retvalue = 1;
01029 }
01030
01031 return retvalue;
01032 }
01033
01034 int compare_json_members_in_sort(const void* data1, const void* data2, unsigned int index1, unsigned int index2, void* user_data) {
01035 Member* member1;
01036 Member* member2;
01037 SortData* sort_data;
01038
01039 member1 = (Member*)data1;
01040 member2 = (Member*)data2;
01041 sort_data = (void*)user_data;
01042
01043 return sort_data->compare_members(sort_data->json, index1, index2, sort_data->user_data);
01044 }