1/* 2 * $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $ 3 * 4 * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd. 5 * Michael Clark <michael@metaparadigm.com> 6 * Copyright (c) 2009 Hewlett-Packard Development Company, L.P. 7 * 8 * This library is free software; you can redistribute it and/or modify 9 * it under the terms of the MIT license. See COPYING for details. 10 * 11 */ 12 13#include "config.h" 14 15#include <stdio.h> 16#include <stdlib.h> 17#include <stddef.h> 18#include <string.h> 19#include <math.h> 20#include <errno.h> 21 22#include "debug.h" 23#include "printbuf.h" 24#include "linkhash.h" 25#include "arraylist.h" 26#include "json_inttypes.h" 27#include "json_object.h" 28#include "json_object_private.h" 29#include "json_util.h" 30#include "math_compat.h" 31 32#if !defined(HAVE_STRDUP) && defined(_MSC_VER) 33 /* MSC has the version as _strdup */ 34# define strdup _strdup 35#elif !defined(HAVE_STRDUP) 36# error You do not have strdup on your system. 37#endif /* HAVE_STRDUP */ 38 39#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER) 40 /* MSC has the version as _snprintf */ 41# define snprintf _snprintf 42#elif !defined(HAVE_SNPRINTF) 43# error You do not have snprintf on your system. 44#endif /* HAVE_SNPRINTF */ 45 46// Don't define this. It's not thread-safe. 47/* #define REFCOUNT_DEBUG 1 */ 48 49const char *json_number_chars = "0123456789.+-eE"; 50const char *json_hex_chars = "0123456789abcdefABCDEF"; 51 52static void json_object_generic_delete(struct json_object* jso); 53static struct json_object* json_object_new(enum json_type o_type); 54 55static json_object_to_json_string_fn json_object_object_to_json_string; 56static json_object_to_json_string_fn json_object_boolean_to_json_string; 57static json_object_to_json_string_fn json_object_int_to_json_string; 58static json_object_to_json_string_fn json_object_double_to_json_string; 59static json_object_to_json_string_fn json_object_string_to_json_string; 60static json_object_to_json_string_fn json_object_array_to_json_string; 61 62 63/* ref count debugging */ 64 65#ifdef REFCOUNT_DEBUG 66 67static struct lh_table *json_object_table; 68 69static void json_object_init(void) __attribute__ ((constructor)); 70static void json_object_init(void) { 71 MC_DEBUG("json_object_init: creating object table\n"); 72 json_object_table = lh_kptr_table_new(128, "json_object_table", NULL); 73} 74 75static void json_object_fini(void) __attribute__ ((destructor)); 76static void json_object_fini(void) { 77 struct lh_entry *ent; 78 if(MC_GET_DEBUG()) { 79 if (json_object_table->count) { 80 MC_DEBUG("json_object_fini: %d referenced objects at exit\n", 81 json_object_table->count); 82 lh_foreach(json_object_table, ent) { 83 struct json_object* obj = (struct json_object*)ent->v; 84 MC_DEBUG("\t%s:%p\n", json_type_to_name(obj->o_type), obj); 85 } 86 } 87 } 88 MC_DEBUG("json_object_fini: freeing object table\n"); 89 lh_table_free(json_object_table); 90} 91#endif /* REFCOUNT_DEBUG */ 92 93 94/* string escaping */ 95 96static int json_escape_str(struct printbuf *pb, char *str, int len) 97{ 98 int pos = 0, start_offset = 0; 99 unsigned char c; 100 while (len--) { 101 c = str[pos]; 102 switch(c) { 103 case '\b': 104 case '\n': 105 case '\r': 106 case '\t': 107 case '\f': 108 case '"': 109 case '\\': 110 case '/': 111 if(pos - start_offset > 0) 112 printbuf_memappend(pb, str + start_offset, pos - start_offset); 113 if(c == '\b') printbuf_memappend(pb, "\\b", 2); 114 else if(c == '\n') printbuf_memappend(pb, "\\n", 2); 115 else if(c == '\r') printbuf_memappend(pb, "\\r", 2); 116 else if(c == '\t') printbuf_memappend(pb, "\\t", 2); 117 else if(c == '\f') printbuf_memappend(pb, "\\f", 2); 118 else if(c == '"') printbuf_memappend(pb, "\\\"", 2); 119 else if(c == '\\') printbuf_memappend(pb, "\\\\", 2); 120 else if(c == '/') printbuf_memappend(pb, "\\/", 2); 121 start_offset = ++pos; 122 break; 123 default: 124 if(c < ' ') { 125 if(pos - start_offset > 0) 126 printbuf_memappend(pb, str + start_offset, pos - start_offset); 127 sprintbuf(pb, "\\u00%c%c", 128 json_hex_chars[c >> 4], 129 json_hex_chars[c & 0xf]); 130 start_offset = ++pos; 131 } else pos++; 132 } 133 } 134 if(pos - start_offset > 0) 135 printbuf_memappend(pb, str + start_offset, pos - start_offset); 136 return 0; 137} 138 139 140/* reference counting */ 141 142extern struct json_object* json_object_get(struct json_object *jso) 143{ 144 if(jso) { 145 jso->_ref_count++; 146 } 147 return jso; 148} 149 150int json_object_put(struct json_object *jso) 151{ 152 if(jso) 153 { 154 jso->_ref_count--; 155 if(!jso->_ref_count) 156 { 157 if (jso->_user_delete) 158 jso->_user_delete(jso, jso->_userdata); 159 jso->_delete(jso); 160 return 1; 161 } 162 } 163 return 0; 164} 165 166 167/* generic object construction and destruction parts */ 168 169static void json_object_generic_delete(struct json_object* jso) 170{ 171#ifdef REFCOUNT_DEBUG 172 MC_DEBUG("json_object_delete_%s: %p\n", 173 json_type_to_name(jso->o_type), jso); 174 lh_table_delete(json_object_table, jso); 175#endif /* REFCOUNT_DEBUG */ 176 printbuf_free(jso->_pb); 177 free(jso); 178} 179 180static struct json_object* json_object_new(enum json_type o_type) 181{ 182 struct json_object *jso; 183 184 jso = (struct json_object*)calloc(sizeof(struct json_object), 1); 185 if(!jso) return NULL; 186 jso->o_type = o_type; 187 jso->_ref_count = 1; 188 jso->_delete = &json_object_generic_delete; 189#ifdef REFCOUNT_DEBUG 190 lh_table_insert(json_object_table, jso, jso); 191 MC_DEBUG("json_object_new_%s: %p\n", json_type_to_name(jso->o_type), jso); 192#endif /* REFCOUNT_DEBUG */ 193 return jso; 194} 195 196 197/* type checking functions */ 198 199int json_object_is_type(struct json_object *jso, enum json_type type) 200{ 201 if (!jso) 202 return (type == json_type_null); 203 return (jso->o_type == type); 204} 205 206enum json_type json_object_get_type(struct json_object *jso) 207{ 208 if (!jso) 209 return json_type_null; 210 return jso->o_type; 211} 212 213/* set a custom conversion to string */ 214 215void json_object_set_serializer(json_object *jso, 216 json_object_to_json_string_fn to_string_func, 217 void *userdata, 218 json_object_delete_fn *user_delete) 219{ 220 // First, clean up any previously existing user info 221 if (jso->_user_delete) 222 { 223 jso->_user_delete(jso, jso->_userdata); 224 } 225 jso->_userdata = NULL; 226 jso->_user_delete = NULL; 227 228 if (to_string_func == NULL) 229 { 230 // Reset to the standard serialization function 231 switch(jso->o_type) 232 { 233 case json_type_null: 234 jso->_to_json_string = NULL; 235 break; 236 case json_type_boolean: 237 jso->_to_json_string = &json_object_boolean_to_json_string; 238 break; 239 case json_type_double: 240 jso->_to_json_string = &json_object_double_to_json_string; 241 break; 242 case json_type_int: 243 jso->_to_json_string = &json_object_int_to_json_string; 244 break; 245 case json_type_object: 246 jso->_to_json_string = &json_object_object_to_json_string; 247 break; 248 case json_type_array: 249 jso->_to_json_string = &json_object_array_to_json_string; 250 break; 251 case json_type_string: 252 jso->_to_json_string = &json_object_string_to_json_string; 253 break; 254 } 255 return; 256 } 257 258 jso->_to_json_string = to_string_func; 259 jso->_userdata = userdata; 260 jso->_user_delete = user_delete; 261} 262 263 264/* extended conversion to string */ 265 266const char* json_object_to_json_string_ext(struct json_object *jso, int flags) 267{ 268 if (!jso) 269 return "null"; 270 271 if ((!jso->_pb) && !(jso->_pb = printbuf_new())) 272 return NULL; 273 274 printbuf_reset(jso->_pb); 275 276 if(jso->_to_json_string(jso, jso->_pb, 0, flags) < 0) 277 return NULL; 278 279 return jso->_pb->buf; 280} 281 282/* backwards-compatible conversion to string */ 283 284const char* json_object_to_json_string(struct json_object *jso) 285{ 286 return json_object_to_json_string_ext(jso, JSON_C_TO_STRING_SPACED); 287} 288 289static void indent(struct printbuf *pb, int level, int flags) 290{ 291 if (flags & JSON_C_TO_STRING_PRETTY) 292 { 293 printbuf_memset(pb, -1, ' ', level * 2); 294 } 295} 296 297/* json_object_object */ 298 299static int json_object_object_to_json_string(struct json_object* jso, 300 struct printbuf *pb, 301 int level, 302 int flags) 303{ 304 int had_children = 0; 305 struct json_object_iter iter; 306 307 sprintbuf(pb, "{" /*}*/); 308 if (flags & JSON_C_TO_STRING_PRETTY) 309 sprintbuf(pb, "\n"); 310 json_object_object_foreachC(jso, iter) 311 { 312 if (had_children) 313 { 314 sprintbuf(pb, ","); 315 if (flags & JSON_C_TO_STRING_PRETTY) 316 sprintbuf(pb, "\n"); 317 } 318 had_children = 1; 319 if (flags & JSON_C_TO_STRING_SPACED) 320 sprintbuf(pb, " "); 321 indent(pb, level+1, flags); 322 sprintbuf(pb, "\""); 323 json_escape_str(pb, iter.key, strlen(iter.key)); 324 if (flags & JSON_C_TO_STRING_SPACED) 325 sprintbuf(pb, "\": "); 326 else 327 sprintbuf(pb, "\":"); 328 if(iter.val == NULL) 329 sprintbuf(pb, "null"); 330 else 331 iter.val->_to_json_string(iter.val, pb, level+1,flags); 332 } 333 if (flags & JSON_C_TO_STRING_PRETTY) 334 { 335 if (had_children) 336 sprintbuf(pb, "\n"); 337 indent(pb,level,flags); 338 } 339 if (flags & JSON_C_TO_STRING_SPACED) 340 return sprintbuf(pb, /*{*/ " }"); 341 else 342 return sprintbuf(pb, /*{*/ "}"); 343} 344 345 346static void json_object_lh_entry_free(struct lh_entry *ent) 347{ 348 free(ent->k); 349 json_object_put((struct json_object*)ent->v); 350} 351 352static void json_object_object_delete(struct json_object* jso) 353{ 354 lh_table_free(jso->o.c_object); 355 json_object_generic_delete(jso); 356} 357 358struct json_object* json_object_new_object(void) 359{ 360 struct json_object *jso = json_object_new(json_type_object); 361 if(!jso) return NULL; 362 jso->_delete = &json_object_object_delete; 363 jso->_to_json_string = &json_object_object_to_json_string; 364 jso->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES, 365 NULL, &json_object_lh_entry_free); 366 return jso; 367} 368 369struct lh_table* json_object_get_object(struct json_object *jso) 370{ 371 if(!jso) return NULL; 372 switch(jso->o_type) { 373 case json_type_object: 374 return jso->o.c_object; 375 default: 376 return NULL; 377 } 378} 379 380void json_object_object_add(struct json_object* jso, const char *key, 381 struct json_object *val) 382{ 383 // We lookup the entry and replace the value, rather than just deleting 384 // and re-adding it, so the existing key remains valid. 385 json_object *existing_value = NULL; 386 struct lh_entry *existing_entry; 387 existing_entry = lh_table_lookup_entry(jso->o.c_object, (void*)key); 388 if (!existing_entry) 389 { 390 lh_table_insert(jso->o.c_object, strdup(key), val); 391 return; 392 } 393 existing_value = (void *)existing_entry->v; 394 if (existing_value) 395 json_object_put(existing_value); 396 existing_entry->v = val; 397} 398 399int json_object_object_length(struct json_object *jso) 400{ 401 return lh_table_length(jso->o.c_object); 402} 403 404struct json_object* json_object_object_get(struct json_object* jso, const char *key) 405{ 406 struct json_object *result = NULL; 407 json_object_object_get_ex(jso, key, &result); 408 return result; 409} 410 411json_bool json_object_object_get_ex(struct json_object* jso, const char *key, struct json_object **value) 412{ 413 if (value != NULL) 414 *value = NULL; 415 416 if (NULL == jso) 417 return FALSE; 418 419 switch(jso->o_type) 420 { 421 case json_type_object: 422 return lh_table_lookup_ex(jso->o.c_object, (void*)key, (void**)value); 423 default: 424 if (value != NULL) 425 *value = NULL; 426 return FALSE; 427 } 428} 429 430void json_object_object_del(struct json_object* jso, const char *key) 431{ 432 lh_table_delete(jso->o.c_object, key); 433} 434 435 436/* json_object_boolean */ 437 438static int json_object_boolean_to_json_string(struct json_object* jso, 439 struct printbuf *pb, 440 int level, 441 int flags) 442{ 443 if(jso->o.c_boolean) return sprintbuf(pb, "true"); 444 else return sprintbuf(pb, "false"); 445} 446 447struct json_object* json_object_new_boolean(json_bool b) 448{ 449 struct json_object *jso = json_object_new(json_type_boolean); 450 if(!jso) return NULL; 451 jso->_to_json_string = &json_object_boolean_to_json_string; 452 jso->o.c_boolean = b; 453 return jso; 454} 455 456json_bool json_object_get_boolean(struct json_object *jso) 457{ 458 if(!jso) return FALSE; 459 switch(jso->o_type) { 460 case json_type_boolean: 461 return jso->o.c_boolean; 462 case json_type_int: 463 return (jso->o.c_int64 != 0); 464 case json_type_double: 465 return (jso->o.c_double != 0); 466 case json_type_string: 467 return (jso->o.c_string.len != 0); 468 default: 469 return FALSE; 470 } 471} 472 473 474/* json_object_int */ 475 476static int json_object_int_to_json_string(struct json_object* jso, 477 struct printbuf *pb, 478 int level, 479 int flags) 480{ 481 return sprintbuf(pb, "%"PRId64, jso->o.c_int64); 482} 483 484struct json_object* json_object_new_int(int32_t i) 485{ 486 struct json_object *jso = json_object_new(json_type_int); 487 if(!jso) return NULL; 488 jso->_to_json_string = &json_object_int_to_json_string; 489 jso->o.c_int64 = i; 490 return jso; 491} 492 493int32_t json_object_get_int(struct json_object *jso) 494{ 495 int64_t cint64; 496 enum json_type o_type; 497 498 if(!jso) return 0; 499 500 o_type = jso->o_type; 501 cint64 = jso->o.c_int64; 502 503 if (o_type == json_type_string) 504 { 505 /* 506 * Parse strings into 64-bit numbers, then use the 507 * 64-to-32-bit number handling below. 508 */ 509 if (json_parse_int64(jso->o.c_string.str, &cint64) != 0) 510 return 0; /* whoops, it didn't work. */ 511 o_type = json_type_int; 512 } 513 514 switch(o_type) { 515 case json_type_int: 516 /* Make sure we return the correct values for out of range numbers. */ 517 if (cint64 <= INT32_MIN) 518 return INT32_MIN; 519 else if (cint64 >= INT32_MAX) 520 return INT32_MAX; 521 else 522 return (int32_t)cint64; 523 case json_type_double: 524 return (int32_t)jso->o.c_double; 525 case json_type_boolean: 526 return jso->o.c_boolean; 527 default: 528 return 0; 529 } 530} 531 532struct json_object* json_object_new_int64(int64_t i) 533{ 534 struct json_object *jso = json_object_new(json_type_int); 535 if(!jso) return NULL; 536 jso->_to_json_string = &json_object_int_to_json_string; 537 jso->o.c_int64 = i; 538 return jso; 539} 540 541int64_t json_object_get_int64(struct json_object *jso) 542{ 543 int64_t cint; 544 545 if(!jso) return 0; 546 switch(jso->o_type) { 547 case json_type_int: 548 return jso->o.c_int64; 549 case json_type_double: 550 return (int64_t)jso->o.c_double; 551 case json_type_boolean: 552 return jso->o.c_boolean; 553 case json_type_string: 554 if (json_parse_int64(jso->o.c_string.str, &cint) == 0) return cint; 555 default: 556 return 0; 557 } 558} 559 560 561/* json_object_double */ 562 563static int json_object_double_to_json_string(struct json_object* jso, 564 struct printbuf *pb, 565 int level, 566 int flags) 567{ 568 char buf[128], *p, *q; 569 int size; 570 /* Although JSON RFC does not support 571 NaN or Infinity as numeric values 572 ECMA 262 section 9.8.1 defines 573 how to handle these cases as strings */ 574 if(isnan(jso->o.c_double)) 575 size = snprintf(buf, sizeof(buf), "NaN"); 576 else if(isinf(jso->o.c_double)) 577 if(jso->o.c_double > 0) 578 size = snprintf(buf, sizeof(buf), "Infinity"); 579 else 580 size = snprintf(buf, sizeof(buf), "-Infinity"); 581 else 582 size = snprintf(buf, sizeof(buf), "%.17g", jso->o.c_double); 583 584 p = strchr(buf, ','); 585 if (p) { 586 *p = '.'; 587 } else { 588 p = strchr(buf, '.'); 589 } 590 if (p && (flags & JSON_C_TO_STRING_NOZERO)) { 591 /* last useful digit, always keep 1 zero */ 592 p++; 593 for (q=p ; *q ; q++) { 594 if (*q!='0') p=q; 595 } 596 /* drop trailing zeroes */ 597 *(++p) = 0; 598 size = p-buf; 599 } 600 printbuf_memappend(pb, buf, size); 601 return size; 602} 603 604struct json_object* json_object_new_double(double d) 605{ 606 struct json_object *jso = json_object_new(json_type_double); 607 if (!jso) 608 return NULL; 609 jso->_to_json_string = &json_object_double_to_json_string; 610 jso->o.c_double = d; 611 return jso; 612} 613 614struct json_object* json_object_new_double_s(double d, const char *ds) 615{ 616 struct json_object *jso = json_object_new_double(d); 617 if (!jso) 618 return NULL; 619 620 json_object_set_serializer(jso, json_object_userdata_to_json_string, 621 strdup(ds), json_object_free_userdata); 622 return jso; 623} 624 625int json_object_userdata_to_json_string(struct json_object *jso, 626 struct printbuf *pb, int level, int flags) 627{ 628 int userdata_len = strlen(jso->_userdata); 629 printbuf_memappend(pb, jso->_userdata, userdata_len); 630 return userdata_len; 631} 632 633void json_object_free_userdata(struct json_object *jso, void *userdata) 634{ 635 free(userdata); 636} 637 638double json_object_get_double(struct json_object *jso) 639{ 640 double cdouble; 641 char *errPtr = NULL; 642 643 if(!jso) return 0.0; 644 switch(jso->o_type) { 645 case json_type_double: 646 return jso->o.c_double; 647 case json_type_int: 648 return jso->o.c_int64; 649 case json_type_boolean: 650 return jso->o.c_boolean; 651 case json_type_string: 652 errno = 0; 653 cdouble = strtod(jso->o.c_string.str,&errPtr); 654 655 /* if conversion stopped at the first character, return 0.0 */ 656 if (errPtr == jso->o.c_string.str) 657 return 0.0; 658 659 /* 660 * Check that the conversion terminated on something sensible 661 * 662 * For example, { "pay" : 123AB } would parse as 123. 663 */ 664 if (*errPtr != '\0') 665 return 0.0; 666 667 /* 668 * If strtod encounters a string which would exceed the 669 * capacity of a double, it returns +/- HUGE_VAL and sets 670 * errno to ERANGE. But +/- HUGE_VAL is also a valid result 671 * from a conversion, so we need to check errno. 672 * 673 * Underflow also sets errno to ERANGE, but it returns 0 in 674 * that case, which is what we will return anyway. 675 * 676 * See CERT guideline ERR30-C 677 */ 678 if ((HUGE_VAL == cdouble || -HUGE_VAL == cdouble) && 679 (ERANGE == errno)) 680 cdouble = 0.0; 681 return cdouble; 682 default: 683 return 0.0; 684 } 685} 686 687 688/* json_object_string */ 689 690static int json_object_string_to_json_string(struct json_object* jso, 691 struct printbuf *pb, 692 int level, 693 int flags) 694{ 695 sprintbuf(pb, "\""); 696 json_escape_str(pb, jso->o.c_string.str, jso->o.c_string.len); 697 sprintbuf(pb, "\""); 698 return 0; 699} 700 701static void json_object_string_delete(struct json_object* jso) 702{ 703 free(jso->o.c_string.str); 704 json_object_generic_delete(jso); 705} 706 707struct json_object* json_object_new_string(const char *s) 708{ 709 struct json_object *jso = json_object_new(json_type_string); 710 if(!jso) return NULL; 711 jso->_delete = &json_object_string_delete; 712 jso->_to_json_string = &json_object_string_to_json_string; 713 jso->o.c_string.str = strdup(s); 714 jso->o.c_string.len = strlen(s); 715 return jso; 716} 717 718struct json_object* json_object_new_string_len(const char *s, int len) 719{ 720 struct json_object *jso = json_object_new(json_type_string); 721 if(!jso) return NULL; 722 jso->_delete = &json_object_string_delete; 723 jso->_to_json_string = &json_object_string_to_json_string; 724 jso->o.c_string.str = (char*)malloc(len + 1); 725 memcpy(jso->o.c_string.str, (void *)s, len); 726 jso->o.c_string.str[len] = '\0'; 727 jso->o.c_string.len = len; 728 return jso; 729} 730 731const char* json_object_get_string(struct json_object *jso) 732{ 733 if(!jso) return NULL; 734 switch(jso->o_type) { 735 case json_type_string: 736 return jso->o.c_string.str; 737 default: 738 return json_object_to_json_string(jso); 739 } 740} 741 742int json_object_get_string_len(struct json_object *jso) { 743 if(!jso) return 0; 744 switch(jso->o_type) { 745 case json_type_string: 746 return jso->o.c_string.len; 747 default: 748 return 0; 749 } 750} 751 752 753/* json_object_array */ 754 755static int json_object_array_to_json_string(struct json_object* jso, 756 struct printbuf *pb, 757 int level, 758 int flags) 759{ 760 int had_children = 0; 761 int ii; 762 sprintbuf(pb, "["); 763 if (flags & JSON_C_TO_STRING_PRETTY) 764 sprintbuf(pb, "\n"); 765 for(ii=0; ii < json_object_array_length(jso); ii++) 766 { 767 struct json_object *val; 768 if (had_children) 769 { 770 sprintbuf(pb, ","); 771 if (flags & JSON_C_TO_STRING_PRETTY) 772 sprintbuf(pb, "\n"); 773 } 774 had_children = 1; 775 if (flags & JSON_C_TO_STRING_SPACED) 776 sprintbuf(pb, " "); 777 indent(pb, level + 1, flags); 778 val = json_object_array_get_idx(jso, ii); 779 if(val == NULL) 780 sprintbuf(pb, "null"); 781 else 782 val->_to_json_string(val, pb, level+1, flags); 783 } 784 if (flags & JSON_C_TO_STRING_PRETTY) 785 { 786 if (had_children) 787 sprintbuf(pb, "\n"); 788 indent(pb,level,flags); 789 } 790 791 if (flags & JSON_C_TO_STRING_SPACED) 792 return sprintbuf(pb, " ]"); 793 else 794 return sprintbuf(pb, "]"); 795} 796 797static void json_object_array_entry_free(void *data) 798{ 799 json_object_put((struct json_object*)data); 800} 801 802static void json_object_array_delete(struct json_object* jso) 803{ 804 array_list_free(jso->o.c_array); 805 json_object_generic_delete(jso); 806} 807 808struct json_object* json_object_new_array(void) 809{ 810 struct json_object *jso = json_object_new(json_type_array); 811 if(!jso) return NULL; 812 jso->_delete = &json_object_array_delete; 813 jso->_to_json_string = &json_object_array_to_json_string; 814 jso->o.c_array = array_list_new(&json_object_array_entry_free); 815 return jso; 816} 817 818struct array_list* json_object_get_array(struct json_object *jso) 819{ 820 if(!jso) return NULL; 821 switch(jso->o_type) { 822 case json_type_array: 823 return jso->o.c_array; 824 default: 825 return NULL; 826 } 827} 828 829void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *)) 830{ 831 array_list_sort(jso->o.c_array, sort_fn); 832} 833 834int json_object_array_length(struct json_object *jso) 835{ 836 return array_list_length(jso->o.c_array); 837} 838 839int json_object_array_add(struct json_object *jso,struct json_object *val) 840{ 841 return array_list_add(jso->o.c_array, val); 842} 843 844int json_object_array_put_idx(struct json_object *jso, int idx, 845 struct json_object *val) 846{ 847 return array_list_put_idx(jso->o.c_array, idx, val); 848} 849 850struct json_object* json_object_array_get_idx(struct json_object *jso, 851 int idx) 852{ 853 return (struct json_object*)array_list_get_idx(jso->o.c_array, idx); 854} 855 856