diff options
author | Eric Haszlakiewicz <erh+git@nimenees.com> | 2013-09-11 20:27:39 -0500 |
---|---|---|
committer | Eric Haszlakiewicz <erh+git@nimenees.com> | 2013-09-11 20:27:39 -0500 |
commit | 51993c28c2721b00340e1ddbd9bb133fdedf1bf4 (patch) | |
tree | e18192800a28eae1aaafb36648a3320d37e07ff5 | |
parent | b83e0f11826e86747885fc066fa5b06d50f60520 (diff) | |
download | json-c-51993c28c2721b00340e1ddbd9bb133fdedf1bf4.tar.gz |
Added a json_object_new_double_s() convenience function to allow an exact string representation of a double to be specified when creating the object and use it in json_tokener_parse_ex() so a re-serialized object more exactly matches the input.
Add json_object_free_userdata() and json_object_userdata_to_json_string() too.
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | json_object.c | 35 | ||||
-rw-r--r-- | json_object.h | 42 | ||||
-rw-r--r-- | json_tokener.c | 6 | ||||
-rw-r--r-- | tests/test_locale.expected | 4 | ||||
-rw-r--r-- | tests/test_parse.expected | 2 |
6 files changed, 83 insertions, 11 deletions
@@ -1,7 +1,10 @@ NEXT.VERSION - * Nothing yet... + * Added a json_object_new_double_s() convenience function to allow + an exact string representation of a double to be specified when + creating the object and use it in json_tokener_parse_ex() so + a re-serialized object more exactly matches the input. 0.11 diff --git a/json_object.c b/json_object.c index 1b3fc76..f65ae52 100644 --- a/json_object.c +++ b/json_object.c @@ -601,11 +601,36 @@ static int json_object_double_to_json_string(struct json_object* jso, struct json_object* json_object_new_double(double d) { - struct json_object *jso = json_object_new(json_type_double); - if(!jso) return NULL; - jso->_to_json_string = &json_object_double_to_json_string; - jso->o.c_double = d; - return jso; + struct json_object *jso = json_object_new(json_type_double); + if (!jso) + return NULL; + jso->_to_json_string = &json_object_double_to_json_string; + jso->o.c_double = d; + return jso; +} + +struct json_object* json_object_new_double_s(double d, const char *ds) +{ + struct json_object *jso = json_object_new_double(d); + if (!jso) + return NULL; + + json_object_set_serializer(jso, json_object_userdata_to_json_string, + strdup(ds), json_object_free_userdata); + return jso; +} + +int json_object_userdata_to_json_string(struct json_object *jso, + struct printbuf *pb, int level, int flags) +{ + int userdata_len = strlen(jso->_userdata); + printbuf_memappend(pb, jso->_userdata, userdata_len); + return userdata_len; +} + +void json_object_free_userdata(struct json_object *jso, void *userdata) +{ + free(userdata); } double json_object_get_double(struct json_object *jso) diff --git a/json_object.h b/json_object.h index df958bf..1005734 100644 --- a/json_object.h +++ b/json_object.h @@ -197,6 +197,25 @@ extern void json_object_set_serializer(json_object *jso, void *userdata, json_object_delete_fn *user_delete); +/** + * Simply call free on the userdata pointer. + * Can be used with json_object_set_serializer(). + * + * @param jso unused + * @param userdata the pointer that is passed to free(). + */ +json_object_delete_fn json_object_free_userdata; + +/** + * Copy the jso->_userdata string over to pb as-is. + * Can be used with json_object_set_serializer(). + * + * @param jso The object whose _userdata is used. + * @param pb The destination buffer. + * @param level Ignored. + * @param flags Ignored. + */ +json_object_to_json_string_fn json_object_userdata_to_json_string; /* object type methods */ @@ -493,6 +512,29 @@ extern int64_t json_object_get_int64(struct json_object *obj); */ extern struct json_object* json_object_new_double(double d); +/** + * Create a new json_object of type json_type_double, using + * the exact serialized representation of the value. + * + * This allows for numbers that would otherwise get displayed + * inefficiently (e.g. 12.3 => "12.300000000000001") to be + * serialized with the more convenient form. + * + * Note: this is used by json_tokener_parse_ex() to allow for + * an exact re-serialization of a parsed object. + * + * An equivalent sequence of calls is: + * @code + * jso = json_object_new_double(d); + * json_object_set_serializer(d, json_object_userdata_to_json_string, + * strdup(ds), json_object_free_userdata) + * @endcode + * + * @param d the numeric value of the double. + * @param ds the string representation of the double. This will be copied. + */ +extern struct json_object* json_object_new_double_s(double d, const char *ds); + /** Get the double floating point value of a json_object * * The type is coerced to a double if the passed object is not a double. diff --git a/json_tokener.c b/json_tokener.c index 7e1fb68..a2a598b 100644 --- a/json_tokener.c +++ b/json_tokener.c @@ -599,8 +599,10 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, goto out; } current = json_object_new_int64(num64); - } else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0) { - current = json_object_new_double(numd); + } + else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0) + { + current = json_object_new_double_s(numd, tok->pb->buf); } else { tok->err = json_tokener_error_parse_number; goto out; diff --git a/tests/test_locale.expected b/tests/test_locale.expected index 8031785..0068be4 100644 --- a/tests/test_locale.expected +++ b/tests/test_locale.expected @@ -1,2 +1,2 @@ -new_obj.to_string()=[ 1.200000, 3.400000, 123456.780000, 5.000000, 23000000000.000000 ] -new_obj.to_string()=[1.2,3.4,123456.78,5.0,23000000000.0] +new_obj.to_string()=[ 1.2, 3.4, 123456.78, 5.0, 2.3e10 ] +new_obj.to_string()=[1.2,3.4,123456.78,5.0,2.3e10] diff --git a/tests/test_parse.expected b/tests/test_parse.expected index f0af0fa..5ea99d8 100644 --- a/tests/test_parse.expected +++ b/tests/test_parse.expected @@ -5,7 +5,7 @@ new_obj.to_string()="ABC" new_obj.to_string()=null new_obj.to_string()=true new_obj.to_string()=12 -new_obj.to_string()=12.300000 +new_obj.to_string()=12.3 new_obj.to_string()=[ "\n" ] new_obj.to_string()=[ "\nabc\n" ] new_obj.to_string()=[ null ] |