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 | |||||