On some low memory systems, calling malloc (by the use of strdup) causes memory fragmentation which eventually results in out of memory situation. using json_object_new_string_noalloc helps to solve this issue. also add basic test for json_object_new_string_noallocpull/476/head
@@ -1015,6 +1015,23 @@ static void json_object_string_delete(struct json_object* jso) | |||||
json_object_generic_delete(jso); | json_object_generic_delete(jso); | ||||
} | } | ||||
struct json_object* json_object_new_string_noalloc(char *s) | |||||
{ | |||||
struct json_object *jso = json_object_new(json_type_string); | |||||
if (!jso) | |||||
return NULL; | |||||
jso->_delete = &json_object_string_delete; | |||||
jso->_to_json_string = &json_object_string_to_json_string; | |||||
jso->o.c_string.len = strlen(s); | |||||
if(jso->o.c_string.len < LEN_DIRECT_STRING_DATA) { | |||||
memcpy(jso->o.c_string.str.data, s, jso->o.c_string.len); | |||||
free(s); | |||||
} else { | |||||
jso->o.c_string.str.ptr = s; | |||||
} | |||||
return jso; | |||||
} | |||||
struct json_object* json_object_new_string(const char *s) | struct json_object* json_object_new_string(const char *s) | ||||
{ | { | ||||
struct json_object *jso = json_object_new(json_type_string); | struct json_object *jso = json_object_new(json_type_string); | ||||
@@ -893,6 +893,19 @@ JSON_EXPORT int json_object_set_double(struct json_object *obj,double new_value) | |||||
/* string type methods */ | /* string type methods */ | ||||
/** Create a new empty json_object of type json_type_string | |||||
* | |||||
* Use given string as is, do not call malloc if given string is longer | |||||
* than internal buffer size. Ownership of s will be transferred to | |||||
* json_object and s will be freed when json_object_put decided to free | |||||
* memory of json_object. | |||||
* | |||||
* @param s the string, must be heap alloacted and must not be freed. | |||||
* @returns a json_object of type json_type_string | |||||
* @see json_object_new_string_len() | |||||
*/ | |||||
JSON_EXPORT struct json_object* json_object_new_string_noalloc(char *s); | |||||
/** Create a new empty json_object of type json_type_string | /** Create a new empty json_object of type json_type_string | ||||
* | * | ||||
* A copy of the string is made and the memory is managed by the json_object | * A copy of the string is made and the memory is managed by the json_object | ||||
@@ -27,6 +27,7 @@ TESTS+= test_set_value.test | |||||
TESTS+= test_visit.test | TESTS+= test_visit.test | ||||
TESTS+= test_json_pointer.test | TESTS+= test_json_pointer.test | ||||
TESTS+= test_int_add.test | TESTS+= test_int_add.test | ||||
TESTS+= test_string_noalloc.test | |||||
check_PROGRAMS= | check_PROGRAMS= | ||||
check_PROGRAMS += $(TESTS:.test=) | check_PROGRAMS += $(TESTS:.test=) | ||||
@@ -0,0 +1,48 @@ | |||||
/* | |||||
* Tests if binary strings are supported. | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <string.h> | |||||
#include <string.h> | |||||
#include "config.h" | |||||
#include "json_inttypes.h" | |||||
#include "json_object.h" | |||||
#include "json_tokener.h" | |||||
int main(void) | |||||
{ | |||||
/* this test has a space after the null character. check that it's still included */ | |||||
char *str1 = strdup("This string should be longer than 32 characters"); | |||||
char *str2 = strdup("this string is short"); | |||||
struct json_object *jso_str = NULL; | |||||
if (!str1 || !str2) | |||||
{ | |||||
puts("FAIL: strdup() returned NULL"); | |||||
return 1; | |||||
} | |||||
jso_str = json_object_new_string_noalloc(str1); | |||||
if (!jso_str) | |||||
{ | |||||
puts("FAIL: json_object_new_string_noalloc(str1) returned NULL"); | |||||
return 2; | |||||
} | |||||
json_object_put(jso_str); | |||||
jso_str = NULL; | |||||
jso_str = json_object_new_string_noalloc(str2); | |||||
if (!jso_str) | |||||
{ | |||||
puts("FAIL: json_object_new_string_noalloc(str2) returned NULL"); | |||||
return 3; | |||||
} | |||||
json_object_put(jso_str); | |||||
puts("PASS"); | |||||
return 0; | |||||
} |
@@ -0,0 +1 @@ | |||||
PASS |
@@ -0,0 +1 @@ | |||||
test_basic.test |