json_t *json_true(void) { static json_t the_true = { .type = JSON_TRUE, .refcount = (unsigned int)1 }; return &the_true; } json_t *json_false(void) { static json_t the_false = { .type = JSON_FALSE, .refcount = (unsigned int)1 }; return &the_false; } json_t *json_null(void) { static json_t the_null = { .type = JSON_NULL, .refcount = (unsigned int)1 }; return &the_null; } /*** deletion ***/ void json_delete(json_t *json) { if(json_is_object(json)) json_delete_object(json_to_object(json)); else if(json_is_array(json)) json_delete_array(json_to_array(json)); else if(json_is_string(json)) json_delete_string(json_to_string(json)); else if(json_is_integer(json)) json_delete_integer(json_to_integer(json)); else if(json_is_real(json)) json_delete_real(json_to_real(json)); /* json_delete is not called for true, false or null */ }
void json_delete(json_t *json) { if(json_is_object(json)) json_delete_object(json_to_object(json)); else if(json_is_array(json)) json_delete_array(json_to_array(json)); else if(json_is_string(json)) json_delete_string(json_to_string(json)); else if(json_is_integer(json)) json_delete_integer(json_to_integer(json)); else if(json_is_real(json)) json_delete_real(json_to_real(json)); /* json_delete is not called for true, false or null */ }
json_t *json_true(void) { static json_t the_true = { .type = JSON_TRUE, .refcount = (unsigned int)1 }; return &the_true; } json_t *json_false(void) { static json_t the_false = { .type = JSON_FALSE, .refcount = (unsigned int)1 }; return &the_false; } json_t *json_null(void) { static json_t the_null = { .type = JSON_NULL, .refcount = (unsigned int)1 }; return &the_null; } /*** deletion ***/ void json_delete(json_t *json) { if(json_is_object(json)) json_delete_object(json_to_object(json)); else if(json_is_array(json)) json_delete_array(json_to_array(json)); else if(json_is_string(json)) json_delete_string(json_to_string(json)); else if(json_is_integer(json)) json_delete_integer(json_to_integer(json)); else if(json_is_real(json)) json_delete_real(json_to_real(json)); /* json_delete is not called for true, false or null */ } /*** equality ***/ int json_equal(json_t *json1, json_t *json2) { if(!json1 || !json2) return 0; if(json_typeof(json1) != json_typeof(json2)) return 0; /* this covers true, false and null as they are singletons */ if(json1 == json2) return 1; if(json_is_object(json1)) return json_object_equal(json1, json2); if(json_is_array(json1)) return json_array_equal(json1, json2); if(json_is_string(json1)) return json_string_equal(json1, json2); if(json_is_integer(json1)) return json_integer_equal(json1, json2); if(json_is_real(json1)) return json_real_equal(json1, json2); return 0; } /*** copying ***/ json_t *json_copy(json_t *json) { if(!json) return NULL; if(json_is_object(json)) return json_object_copy(json); if(json_is_array(json)) return json_array_copy(json); if(json_is_string(json)) return json_string_copy(json); if(json_is_integer(json)) return json_integer_copy(json); if(json_is_real(json)) return json_real_copy(json); if(json_is_true(json) || json_is_false(json) || json_is_null(json)) return json; return NULL; } json_t *json_deep_copy(json_t *json) { if(!json) return NULL; if(json_is_object(json)) return json_object_deep_copy(json); if(json_is_array(json)) return json_array_deep_copy(json); /* for the rest of the types, deep copying doesn't differ from shallow copying */ if(json_is_string(json)) return json_string_copy(json); if(json_is_integer(json)) return json_integer_copy(json); if(json_is_real(json)) return json_real_copy(json); if(json_is_true(json) || json_is_false(json) || json_is_null(json)) return json; return NULL; }
int json_parse_object( json_task_t *task, json_object_t *parent ) { char ch; json_object_t node, * append = NULL; node.next = parent; node.key = NULL; node.key_len = 0; if( !task->callback ) { if( !task->root ) { append = task->root = json_create_object(); } else { append = parent->value.p = json_create_object(); } } task->status = STS_OBJECT_START; while(( ch = *(task->str + task->count) )) { task->count ++; if( ch == ' ' || ch == '\n' || ch == '\t' ) { continue; } switch( task->status ) { case STS_OBJECT_START: if( ch == '"' ) { node.key = task->str + task->count; if( json_parse_string( task ) != 0 ) { return -1; } // WARNING: key_len 可能发生溢出 node.key_len = task->str + task->count - node.key - 1; task->status = STS_OBJECT_COLON; } else if( ch == '}' ) { // 空对象 {},忽略 return 0; } else { task->err_msg = "expect '\"' or '}'"; return -1; } break; case STS_OBJECT_COLON: if( ch == ':' ) { task->status = STS_OBJECT_VALUE; } else { task->err_msg = "expect ':'"; return -1; } break; case STS_OBJECT_VALUE: /* 这里需要将计数减一,因为 json_parse_value 需要根据这一个字符判断 value 类型 */ task->count --; node.value.s = task->str + task->count; if( json_parse_value( task, &node ) != 0 ) { if( node.value_type == JSON_OBJECT || node.value_type == JSON_ARRAY ) { json_delete_object(node.value.p); } return -1; } // WARNING: value_len 可能发生溢出 node.value_len = task->str + task->count - node.value.s; task->status = STS_OBJECT_COMMA; break; case STS_OBJECT_COMMA: if( ( ch == ',' || ch == '}' ) ) { // 对 value 进行处理 switch(node.value_type) { case JSON_STRING: // 去除字符串两端的引号 node.value.s += 1; node.value_len -= 2; break; case JSON_DOUBLE: node.value.d = atof(node.value.s); break; case JSON_LONGLONG: node.value.l = atoll(node.value.s); break; case JSON_ARRAY: case JSON_OBJECT: break; } if( task->callback ) { task->callback( task, &node ); } if( !task->callback ) { switch( node.value_type ) { case JSON_ARRAY: case JSON_OBJECT: case JSON_STRING: append = json_append(append, node.key, node.key_len, node.value_type, node.value.p, node.value_len); break; default: append = json_append(append, node.key, node.key_len, node.value_type, &node.value, node.value_len); } } } if( ch == ',' ) { task->status = STS_OBJECT_START; } else if( ch == '}' ) { return 0; } else { task->err_msg = "expect ',' or '}'"; return -1; } break; default: task->err_msg = "unknown status"; return -1; } } task->err_msg = "unexpect EOF"; return -1; }
int json_parse_array( json_task_t *task, json_object_t *parent ) { char ch; json_object_t node, * append = NULL; node.next = parent; node.key = NULL; node.key_len = 0; if( !task->callback ) { if( !task->root ) { append = task->root = json_create_array(); } else { append = parent->value.p = json_create_array(); } } task->status = STS_ARRAY_START; while(( ch = *(task->str + task->count) )) { task->count ++; if( ch == ' ' || ch == '\n' || ch == '\t' ) { continue; } switch( task->status ) { case STS_ARRAY_START: if( ch == ']' ) { return 0; } else { /* 这里需要将计数减一,因为 json_parse_value 需要根据这一个字符判断 value 类型 */ task->count --; node.value.s = task->str + task->count; if( json_parse_value( task, &node ) != 0 ) { if( node.value_type == JSON_OBJECT || node.value_type == JSON_ARRAY ) { json_delete_object(node.value.p); } return -1; } // WARNING: value_len 可能发生溢出 node.value_len = task->str + task->count - node.value.s; // 对 value 进行处理 switch(node.value_type) { case JSON_STRING: // 去除字符串两端的引号 node.value.s += 1; node.value_len -= 2; break; case JSON_DOUBLE: // TODO 在解析测试用例时,atof 与 atoll 使解析时间延长了几乎一半 // 移除对数值的默认解析可以显著提升性能 node.value.d = atof(node.value.s); break; case JSON_LONGLONG: node.value.l = atoll(node.value.s); break; case JSON_ARRAY: case JSON_OBJECT: break; } // 需要放在 node.key_len ++ 之前以便正确输出数组下标 if( task->callback ) { task->callback( task, &node ); } if( !task->callback ) { switch( node.value_type ) { case JSON_ARRAY: case JSON_OBJECT: case JSON_STRING: append = json_append(append, node.key, node.key_len, node.value_type, node.value.p, node.value_len); break; default: append = json_append(append, node.key, node.key_len, node.value_type, &node.value, node.value_len); } } node.key_len ++; task->status = STS_ARRAY_COMMA; } break; case STS_ARRAY_COMMA: if( ch == ',' ) { task->status = STS_ARRAY_START; } else if( ch == ']' ) { return 0; } else { task->err_msg = "expect ',' or ']'"; return -1; } break; default: task->err_msg = "unknown status"; return -1; } } task->err_msg = "unexpect EOF"; return -1; }