From: Jehiah Czebotar Date: Fri, 14 Jan 2011 17:23:06 +0000 (+0000) Subject: update json_object_new_string_len, json_escape_str (internal). Writer handles \x00... X-Git-Tag: json-c-0.10-20120530~56 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ac601b5b5f9bc76200a37f39a47a62d414708aa2;p=json-c update json_object_new_string_len, json_escape_str (internal). Writer handles \x00 correctly Added parse_null test. This does not change anything with how the parser handles \u0000 or null characters This commit is addapted from one by Adomas Paltanavičius git-svn-id: http://svn.metaparadigm.com/svn/json-c/trunk@63 327403b1-1117-474d-bef2-5cb71233fd97 --- diff --git a/Makefile.am b/Makefile.am index dc920f8..dc8b348 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,7 +32,7 @@ libjson_la_SOURCES = \ linkhash.c \ printbuf.c -check_PROGRAMS = test1 test2 test4 test_parse_int64 +check_PROGRAMS = test1 test2 test4 test_parse_int64 test_null test1_SOURCES = test1.c test1_LDADD = $(lib_LTLIBRARIES) @@ -46,7 +46,10 @@ test4_LDADD = $(lib_LTLIBRARIES) test_parse_int64_SOURCES = test_parse_int64.c test_parse_int64_LDADD = $(lib_LTLIBRARIES) -TESTS = test1.test test2.test test4.test parse_int64.test +test_null_SOURCES = test_null.c +test_null_LDADD = $(lib_LTLIBRARIES) + +TESTS = test1.test test2.test test4.test parse_int64.test test_null.test EXTRA_DIST += $(TESTS) testsubdir=testSubDir TESTS_ENVIRONMENT = top_builddir=$(top_builddir) diff --git a/json_object.c b/json_object.c index 2b6dad4..8f1a67e 100644 --- a/json_object.c +++ b/json_object.c @@ -83,15 +83,13 @@ static void json_object_fini(void) { /* string escaping */ -static int json_escape_str(struct printbuf *pb, char *str) +static int json_escape_str(struct printbuf *pb, char *str, int len) { int pos = 0, start_offset = 0; unsigned char c; - do { + while (len--) { c = str[pos]; switch(c) { - case '\0': - break; case '\b': case '\n': case '\r': @@ -120,7 +118,7 @@ static int json_escape_str(struct printbuf *pb, char *str) start_offset = ++pos; } else pos++; } - } while(c); + } if(pos - start_offset > 0) printbuf_memappend(pb, str + start_offset, pos - start_offset); return 0; @@ -218,7 +216,7 @@ static int json_object_object_to_json_string(struct json_object* jso, json_object_object_foreachC(jso, iter) { if(i) sprintbuf(pb, ","); sprintbuf(pb, " \""); - json_escape_str(pb, iter.key); + json_escape_str(pb, iter.key, strlen(iter.key)); sprintbuf(pb, "\": "); if(iter.val == NULL) sprintbuf(pb, "null"); else iter.val->_to_json_string(iter.val, pb); @@ -309,7 +307,7 @@ boolean json_object_get_boolean(struct json_object *jso) case json_type_double: return (jso->o.c_double != 0); case json_type_string: - return (strlen(jso->o.c_string) != 0); + return (jso->o.c_string.len != 0); default: return FALSE; } @@ -346,7 +344,7 @@ int32_t json_object_get_int(struct json_object *jso) * Parse strings into 64-bit numbers, then use the * 64-to-32-bit number handling below. */ - if (json_parse_int64(jso->o.c_string, &cint64) != 0) + if (json_parse_int64(jso->o.c_string.str, &cint64) != 0) return 0; /* whoops, it didn't work. */ o_type = json_type_int; } @@ -391,7 +389,7 @@ int64_t json_object_get_int64(struct json_object *jso) case json_type_boolean: return jso->o.c_boolean; case json_type_string: - if (json_parse_int64(jso->o.c_string, &cint) == 0) return cint; + if (json_parse_int64(jso->o.c_string.str, &cint) == 0) return cint; default: return 0; } @@ -428,7 +426,7 @@ double json_object_get_double(struct json_object *jso) case json_type_boolean: return jso->o.c_boolean; case json_type_string: - if(sscanf(jso->o.c_string, "%lf", &cdouble) == 1) return cdouble; + if(sscanf(jso->o.c_string.str, "%lf", &cdouble) == 1) return cdouble; default: return 0.0; } @@ -441,14 +439,14 @@ static int json_object_string_to_json_string(struct json_object* jso, struct printbuf *pb) { sprintbuf(pb, "\""); - json_escape_str(pb, jso->o.c_string); + json_escape_str(pb, jso->o.c_string.str, jso->o.c_string.len); sprintbuf(pb, "\""); return 0; } static void json_object_string_delete(struct json_object* jso) { - free(jso->o.c_string); + free(jso->o.c_string.str); json_object_generic_delete(jso); } @@ -458,7 +456,8 @@ struct json_object* json_object_new_string(const char *s) if(!jso) return NULL; jso->_delete = &json_object_string_delete; jso->_to_json_string = &json_object_string_to_json_string; - jso->o.c_string = strdup(s); + jso->o.c_string.str = strdup(s); + jso->o.c_string.len = strlen(s); return jso; } @@ -468,7 +467,9 @@ struct json_object* json_object_new_string_len(const char *s, int len) if(!jso) return NULL; jso->_delete = &json_object_string_delete; jso->_to_json_string = &json_object_string_to_json_string; - jso->o.c_string = strndup(s, len); + jso->o.c_string.str = malloc(len); + memcpy(jso->o.c_string.str, (void *)s, len); + jso->o.c_string.len = len; return jso; } @@ -477,12 +478,22 @@ const char* json_object_get_string(struct json_object *jso) if(!jso) return NULL; switch(jso->o_type) { case json_type_string: - return jso->o.c_string; + return jso->o.c_string.str; default: return json_object_to_json_string(jso); } } +int json_object_get_string_len(struct json_object *jso) { + if(!jso) return 0; + switch(jso->o_type) { + case json_type_string: + return jso->o.c_string.len; + default: + return 0; + } +} + /* json_object_array */ diff --git a/json_object.h b/json_object.h index 9a44c6e..d8fdc29 100644 --- a/json_object.h +++ b/json_object.h @@ -337,6 +337,16 @@ extern struct json_object* json_object_new_string_len(const char *s, int len); */ extern const char* json_object_get_string(struct json_object *obj); +/** Get the string length of a json_object + * + * If the passed object is not of type json_type_string then zero + * will be returned. + * + * @param obj the json_object instance + * @returns int + */ +extern int json_object_get_string_len(struct json_object *obj); + #ifdef __cplusplus } #endif diff --git a/json_object_private.h b/json_object_private.h index 04f510a..c7f604b 100644 --- a/json_object_private.h +++ b/json_object_private.h @@ -33,7 +33,10 @@ struct json_object int64_t c_int64; struct lh_table *c_object; struct array_list *c_array; - char *c_string; + struct { + char *str; + int len; + } c_string; } o; }; diff --git a/test_null.c b/test_null.c new file mode 100644 index 0000000..73729b8 --- /dev/null +++ b/test_null.c @@ -0,0 +1,35 @@ +/* +* Tests if binary strings are supported. +*/ + +#include +#include +#include "config.h" + +#include "json_inttypes.h" +#include "json_object.h" + +int main() { + // this test has a space after the null character. check that it's still included + const char *input = " \0 "; + const char *expected = "\" \\u0000 \""; + struct json_object *string = json_object_new_string_len(input, 3); + const char *json = json_object_to_json_string(string); + + int strings_match = !strcmp( expected, json); + int retval = 0; + if (strings_match) { + printf("JSON write result is correct: %s\n", json); + printf("PASS\n"); + } else { + printf("JSON write result doesn't match expected string\n"); + printf("expected string: "); + printf("%s\n", expected); + printf("parsed string: "); + printf("%s\n", json); + printf("FAIL\n"); + retval=1; + } + json_object_put(string); + return retval; +} diff --git a/test_null.expected b/test_null.expected new file mode 100644 index 0000000..fd7b479 --- /dev/null +++ b/test_null.expected @@ -0,0 +1,2 @@ +JSON write result is correct: " \u0000 " +PASS diff --git a/test_null.test b/test_null.test new file mode 100644 index 0000000..469ec64 --- /dev/null +++ b/test_null.test @@ -0,0 +1,12 @@ +#!/bin/sh + +# Common definitions +if test -z "$srcdir"; then + srcdir="${0%/*}" + test "$srcdir" = "$0" && srcdir=. + test -z "$srcdir" && srcdir=. +fi +. "$srcdir/test-defs.sh" + +run_output_test test_null +exit $?