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 <adomas@leanholding.com> git-svn-id: http://svn.metaparadigm.com/svn/json-c/trunk@63 327403b1-1117-474d-bef2-5cb71233fd97
This commit is contained in:
@@ -32,7 +32,7 @@ libjson_la_SOURCES = \
|
|||||||
linkhash.c \
|
linkhash.c \
|
||||||
printbuf.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_SOURCES = test1.c
|
||||||
test1_LDADD = $(lib_LTLIBRARIES)
|
test1_LDADD = $(lib_LTLIBRARIES)
|
||||||
@@ -46,7 +46,10 @@ test4_LDADD = $(lib_LTLIBRARIES)
|
|||||||
test_parse_int64_SOURCES = test_parse_int64.c
|
test_parse_int64_SOURCES = test_parse_int64.c
|
||||||
test_parse_int64_LDADD = $(lib_LTLIBRARIES)
|
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)
|
EXTRA_DIST += $(TESTS)
|
||||||
testsubdir=testSubDir
|
testsubdir=testSubDir
|
||||||
TESTS_ENVIRONMENT = top_builddir=$(top_builddir)
|
TESTS_ENVIRONMENT = top_builddir=$(top_builddir)
|
||||||
|
|||||||
@@ -83,15 +83,13 @@ static void json_object_fini(void) {
|
|||||||
|
|
||||||
/* string escaping */
|
/* 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;
|
int pos = 0, start_offset = 0;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
do {
|
while (len--) {
|
||||||
c = str[pos];
|
c = str[pos];
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case '\0':
|
|
||||||
break;
|
|
||||||
case '\b':
|
case '\b':
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
@@ -120,7 +118,7 @@ static int json_escape_str(struct printbuf *pb, char *str)
|
|||||||
start_offset = ++pos;
|
start_offset = ++pos;
|
||||||
} else pos++;
|
} else pos++;
|
||||||
}
|
}
|
||||||
} while(c);
|
}
|
||||||
if(pos - start_offset > 0)
|
if(pos - start_offset > 0)
|
||||||
printbuf_memappend(pb, str + start_offset, pos - start_offset);
|
printbuf_memappend(pb, str + start_offset, pos - start_offset);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -218,7 +216,7 @@ static int json_object_object_to_json_string(struct json_object* jso,
|
|||||||
json_object_object_foreachC(jso, iter) {
|
json_object_object_foreachC(jso, iter) {
|
||||||
if(i) sprintbuf(pb, ",");
|
if(i) sprintbuf(pb, ",");
|
||||||
sprintbuf(pb, " \"");
|
sprintbuf(pb, " \"");
|
||||||
json_escape_str(pb, iter.key);
|
json_escape_str(pb, iter.key, strlen(iter.key));
|
||||||
sprintbuf(pb, "\": ");
|
sprintbuf(pb, "\": ");
|
||||||
if(iter.val == NULL) sprintbuf(pb, "null");
|
if(iter.val == NULL) sprintbuf(pb, "null");
|
||||||
else iter.val->_to_json_string(iter.val, pb);
|
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:
|
case json_type_double:
|
||||||
return (jso->o.c_double != 0);
|
return (jso->o.c_double != 0);
|
||||||
case json_type_string:
|
case json_type_string:
|
||||||
return (strlen(jso->o.c_string) != 0);
|
return (jso->o.c_string.len != 0);
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
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
|
* Parse strings into 64-bit numbers, then use the
|
||||||
* 64-to-32-bit number handling below.
|
* 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. */
|
return 0; /* whoops, it didn't work. */
|
||||||
o_type = json_type_int;
|
o_type = json_type_int;
|
||||||
}
|
}
|
||||||
@@ -391,7 +389,7 @@ int64_t json_object_get_int64(struct json_object *jso)
|
|||||||
case json_type_boolean:
|
case json_type_boolean:
|
||||||
return jso->o.c_boolean;
|
return jso->o.c_boolean;
|
||||||
case json_type_string:
|
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:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -428,7 +426,7 @@ double json_object_get_double(struct json_object *jso)
|
|||||||
case json_type_boolean:
|
case json_type_boolean:
|
||||||
return jso->o.c_boolean;
|
return jso->o.c_boolean;
|
||||||
case json_type_string:
|
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:
|
default:
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
@@ -441,14 +439,14 @@ static int json_object_string_to_json_string(struct json_object* jso,
|
|||||||
struct printbuf *pb)
|
struct printbuf *pb)
|
||||||
{
|
{
|
||||||
sprintbuf(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, "\"");
|
sprintbuf(pb, "\"");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void json_object_string_delete(struct json_object* jso)
|
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);
|
json_object_generic_delete(jso);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,7 +456,8 @@ struct json_object* json_object_new_string(const char *s)
|
|||||||
if(!jso) return NULL;
|
if(!jso) return NULL;
|
||||||
jso->_delete = &json_object_string_delete;
|
jso->_delete = &json_object_string_delete;
|
||||||
jso->_to_json_string = &json_object_string_to_json_string;
|
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;
|
return jso;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,7 +467,9 @@ struct json_object* json_object_new_string_len(const char *s, int len)
|
|||||||
if(!jso) return NULL;
|
if(!jso) return NULL;
|
||||||
jso->_delete = &json_object_string_delete;
|
jso->_delete = &json_object_string_delete;
|
||||||
jso->_to_json_string = &json_object_string_to_json_string;
|
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;
|
return jso;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,12 +478,22 @@ const char* json_object_get_string(struct json_object *jso)
|
|||||||
if(!jso) return NULL;
|
if(!jso) return NULL;
|
||||||
switch(jso->o_type) {
|
switch(jso->o_type) {
|
||||||
case json_type_string:
|
case json_type_string:
|
||||||
return jso->o.c_string;
|
return jso->o.c_string.str;
|
||||||
default:
|
default:
|
||||||
return json_object_to_json_string(jso);
|
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 */
|
/* json_object_array */
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -33,7 +33,10 @@ struct json_object
|
|||||||
int64_t c_int64;
|
int64_t c_int64;
|
||||||
struct lh_table *c_object;
|
struct lh_table *c_object;
|
||||||
struct array_list *c_array;
|
struct array_list *c_array;
|
||||||
char *c_string;
|
struct {
|
||||||
|
char *str;
|
||||||
|
int len;
|
||||||
|
} c_string;
|
||||||
} o;
|
} o;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
35
test_null.c
Normal file
35
test_null.c
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Tests if binary strings are supported.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
2
test_null.expected
Normal file
2
test_null.expected
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
JSON write result is correct: " \u0000 "
|
||||||
|
PASS
|
||||||
12
test_null.test
Normal file
12
test_null.test
Normal file
@@ -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 $?
|
||||||
Reference in New Issue
Block a user