Skip to content

Commit 1f875ce

Browse files
authored
Merge pull request #717 from WilhelmWiens/Realloc
Add realloc
2 parents b5d4cdb + 0c4db95 commit 1f875ce

File tree

14 files changed

+429
-26
lines changed

14 files changed

+429
-26
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,7 @@ if (NOT JANSSON_WITHOUT_TESTS)
491491
set(api_tests
492492
test_array
493493
test_chaos
494+
test_chaos_realloc
494495
test_copy
495496
test_dump
496497
test_dump_callback
@@ -510,6 +511,7 @@ if (NOT JANSSON_WITHOUT_TESTS)
510511
# such as secure_malloc and secure_free is doing, so exclude it for now.
511512
if (NOT MSVC)
512513
list(APPEND api_tests test_memory_funcs)
514+
list(APPEND api_tests test_memory_funcs_realloc)
513515
endif()
514516

515517
# Helper macro for building and linking a test program.

doc/apiref.rst

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1907,7 +1907,7 @@ Copying objects preserves the insertion order of keys.
19071907
Custom Memory Allocation
19081908
========================
19091909

1910-
By default, Jansson uses :func:`malloc()` and :func:`free()` for
1910+
By default, Jansson uses :func:`malloc()`, :func:`realloc()` and :func:`free()` for
19111911
memory allocation. These functions can be overridden if custom
19121912
behavior is needed.
19131913

@@ -1918,6 +1918,16 @@ behavior is needed.
19181918

19191919
typedef void *(*json_malloc_t)(size_t);
19201920

1921+
.. type:: json_realloc_t
1922+
1923+
A typedef for a function pointer with :func:`realloc()`'s
1924+
signature::
1925+
1926+
typedef void *(*json_realloc_t)(void*, size_t);
1927+
1928+
1929+
.. versionadded:: 2.15
1930+
19211931
.. type:: json_free_t
19221932

19231933
A typedef for a function pointer with :func:`free()`'s
@@ -1932,13 +1942,29 @@ behavior is needed.
19321942
Jansson's API functions to ensure that all memory operations use
19331943
the same functions.
19341944

1945+
.. function:: void json_set_alloc_funcs2(json_malloc_t malloc_fn, json_relloc_t relloc_fn, json_free_t free_fn)
1946+
1947+
Use *malloc_fn* instead of :func:`malloc()`, *realloc_fn* instead of :func:`realloc()` and *free_fn* instead
1948+
of :func:`free()`. This function has to be called before any other
1949+
Jansson's API functions to ensure that all memory operations use
1950+
the same functions.
1951+
1952+
.. versionadded:: 2.15
1953+
19351954
.. function:: void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn)
19361955

19371956
Fetch the current malloc_fn and free_fn used. Either parameter
19381957
may be NULL.
19391958

19401959
.. versionadded:: 2.8
19411960

1961+
.. function:: void json_get_alloc_funcs2(json_malloc_t *malloc_fn, json_realloc_t *realloc_fn, json_free_t *free_fn)
1962+
1963+
Fetch the current malloc_fn,realloc_fn and free_fn used. Either parameter
1964+
may be NULL.
1965+
1966+
.. versionadded:: 2.15
1967+
19421968
**Examples:**
19431969

19441970
Circumvent problems with different CRT heaps on Windows by using
@@ -1950,6 +1976,12 @@ Use the `Boehm's conservative garbage collector`_ for memory
19501976
operations::
19511977

19521978
json_set_alloc_funcs(GC_malloc, GC_free);
1979+
or
1980+
json_set_alloc_funcs2(GC_malloc, GC_realloc, GC_free);
1981+
1982+
1983+
When realloc is not defined is it emulated using malloc and free.
1984+
19531985

19541986
.. _Boehm's conservative garbage collector: http://www.hboehm.info/gc/
19551987

src/hashtable.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ static int hashtable_do_rehash(hashtable_t *hashtable) {
154154
hashtable->buckets = new_buckets;
155155
hashtable->order = new_order;
156156

157-
for (i = 0; i < hashsize(hashtable->order); i++) {
157+
for (i = 0; i < new_size; i++) {
158158
hashtable->buckets[i].first = hashtable->buckets[i].last = &hashtable->list;
159159
}
160160

src/jansson.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ EXPORTS
7777
json_unpack_ex
7878
json_vunpack_ex
7979
json_set_alloc_funcs
80+
json_set_alloc_funcs2
8081
json_get_alloc_funcs
82+
json_get_alloc_funcs2
8183
jansson_version_str
8284
jansson_version_cmp
8385

src/jansson.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,11 +402,17 @@ int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *
402402
/* custom memory allocation */
403403

404404
typedef void *(*json_malloc_t)(size_t);
405+
typedef void *(*json_realloc_t)(void *, size_t);
405406
typedef void (*json_free_t)(void *);
406407

407408
void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn);
408409
void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn);
409410

411+
void json_set_alloc_funcs2(json_malloc_t malloc_fn, json_realloc_t realloc_fn,
412+
json_free_t free_fn);
413+
void json_get_alloc_funcs2(json_malloc_t *malloc_fn, json_realloc_t *realloc_fn,
414+
json_free_t *free_fn);
415+
410416
/* runtime version checking */
411417

412418
const char *jansson_version_str(void);

src/jansson_private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ int jsonp_dtostr(char *buffer, size_t size, double value, int prec);
8383

8484
/* Wrappers for custom memory functions */
8585
void *jsonp_malloc(size_t size) JANSSON_ATTRS((warn_unused_result));
86+
void *jsonp_realloc(void *ptr, size_t originalSize, size_t newSize)
87+
JANSSON_ATTRS((warn_unused_result));
8688
void jsonp_free(void *ptr);
8789
char *jsonp_strndup(const char *str, size_t length) JANSSON_ATTRS((warn_unused_result));
8890
char *jsonp_strdup(const char *str) JANSSON_ATTRS((warn_unused_result));

src/memory.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414

1515
/* C89 allows these to be macros */
1616
#undef malloc
17+
#undef realloc
1718
#undef free
1819

1920
/* memory function pointers */
2021
static json_malloc_t do_malloc = malloc;
22+
static json_realloc_t do_realloc = realloc;
2123
static json_free_t do_free = free;
2224

2325
void *jsonp_malloc(size_t size) {
@@ -34,6 +36,31 @@ void jsonp_free(void *ptr) {
3436
(*do_free)(ptr);
3537
}
3638

39+
void *jsonp_realloc(void *ptr, size_t originalSize, size_t newSize) {
40+
void *newMemory;
41+
42+
if (do_realloc)
43+
return (*do_realloc)(ptr, newSize);
44+
45+
// realloc emulation using malloc and free
46+
if (newSize == 0) {
47+
if (ptr != NULL)
48+
(*do_free)(ptr);
49+
50+
return NULL;
51+
} else {
52+
newMemory = (*do_malloc)(newSize);
53+
54+
if ((newMemory != NULL) && (ptr != NULL)) {
55+
memcpy(newMemory, ptr, (originalSize < newSize) ? originalSize : newSize);
56+
57+
(*do_free)(ptr);
58+
}
59+
60+
return newMemory;
61+
}
62+
}
63+
3764
char *jsonp_strdup(const char *str) { return jsonp_strndup(str, strlen(str)); }
3865

3966
char *jsonp_strndup(const char *str, size_t len) {
@@ -50,6 +77,14 @@ char *jsonp_strndup(const char *str, size_t len) {
5077

5178
void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn) {
5279
do_malloc = malloc_fn;
80+
do_realloc = NULL;
81+
do_free = free_fn;
82+
}
83+
84+
void json_set_alloc_funcs2(json_malloc_t malloc_fn, json_realloc_t realloc_fn,
85+
json_free_t free_fn) {
86+
do_malloc = malloc_fn;
87+
do_realloc = realloc_fn;
5388
do_free = free_fn;
5489
}
5590

@@ -59,3 +94,12 @@ void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn) {
5994
if (free_fn)
6095
*free_fn = do_free;
6196
}
97+
void json_get_alloc_funcs2(json_malloc_t *malloc_fn, json_realloc_t *realloc_fn,
98+
json_free_t *free_fn) {
99+
if (malloc_fn)
100+
*malloc_fn = do_malloc;
101+
if (realloc_fn)
102+
*realloc_fn = do_realloc;
103+
if (free_fn)
104+
*free_fn = do_free;
105+
}

src/strbuffer.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,10 @@ int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size)
7070

7171
new_size = max(strbuff->size * STRBUFFER_FACTOR, strbuff->length + size + 1);
7272

73-
new_value = jsonp_malloc(new_size);
73+
new_value = jsonp_realloc(strbuff->value, strbuff->size, new_size);
7474
if (!new_value)
7575
return -1;
7676

77-
memcpy(new_value, strbuff->value, strbuff->length);
78-
79-
jsonp_free(strbuff->value);
8077
strbuff->value = new_value;
8178
strbuff->size = new_size;
8279
}

src/value.c

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ static void array_copy(json_t **dest, size_t dpos, json_t **src, size_t spos,
507507
memcpy(&dest[dpos], &src[spos], count * sizeof(json_t *));
508508
}
509509

510-
static json_t **json_array_grow(json_array_t *array, size_t amount, int copy) {
510+
static json_t **json_array_grow(json_array_t *array, size_t amount) {
511511
size_t new_size;
512512
json_t **old_table, **new_table;
513513

@@ -517,20 +517,15 @@ static json_t **json_array_grow(json_array_t *array, size_t amount, int copy) {
517517
old_table = array->table;
518518

519519
new_size = max(array->size + amount, array->size * 2);
520-
new_table = jsonp_malloc(new_size * sizeof(json_t *));
520+
new_table = jsonp_realloc(old_table, array->size * sizeof(json_t *),
521+
new_size * sizeof(json_t *));
521522
if (!new_table)
522523
return NULL;
523524

524525
array->size = new_size;
525526
array->table = new_table;
526527

527-
if (copy) {
528-
array_copy(array->table, 0, old_table, 0, array->entries);
529-
jsonp_free(old_table);
530-
return array->table;
531-
}
532-
533-
return old_table;
528+
return array->table;
534529
}
535530

536531
int json_array_append_new(json_t *json, json_t *value) {
@@ -545,7 +540,7 @@ int json_array_append_new(json_t *json, json_t *value) {
545540
}
546541
array = json_to_array(json);
547542

548-
if (!json_array_grow(array, 1, 1)) {
543+
if (!json_array_grow(array, 1)) {
549544
json_decref(value);
550545
return -1;
551546
}
@@ -558,7 +553,6 @@ int json_array_append_new(json_t *json, json_t *value) {
558553

559554
int json_array_insert_new(json_t *json, size_t index, json_t *value) {
560555
json_array_t *array;
561-
json_t **old_table;
562556

563557
if (!value)
564558
return -1;
@@ -574,17 +568,11 @@ int json_array_insert_new(json_t *json, size_t index, json_t *value) {
574568
return -1;
575569
}
576570

577-
old_table = json_array_grow(array, 1, 0);
578-
if (!old_table) {
571+
if (!json_array_grow(array, 1)) {
579572
json_decref(value);
580573
return -1;
581574
}
582-
583-
if (old_table != array->table) {
584-
array_copy(array->table, 0, old_table, 0, index);
585-
array_copy(array->table, index + 1, old_table, index, array->entries - index);
586-
jsonp_free(old_table);
587-
} else
575+
if (index != array->entries)
588576
array_move(array, index + 1, index, array->entries - index);
589577

590578
array->table[index] = value;
@@ -638,7 +626,7 @@ int json_array_extend(json_t *json, json_t *other_json) {
638626
array = json_to_array(json);
639627
other = json_to_array(other_json);
640628

641-
if (!json_array_grow(array, other->entries, 1))
629+
if (!json_array_grow(array, other->entries))
642630
return -1;
643631

644632
for (i = 0; i < other->entries; i++)

test/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ logs
22
bin/json_process
33
suites/api/test_array
44
suites/api/test_chaos
5+
suites/api/test_chaos_realloc
56
suites/api/test_copy
67
suites/api/test_cpp
78
suites/api/test_dump
@@ -12,6 +13,7 @@ suites/api/test_load
1213
suites/api/test_load_callback
1314
suites/api/test_loadb
1415
suites/api/test_memory_funcs
16+
suites/api/test_memory_funcs_realloc
1517
suites/api/test_number
1618
suites/api/test_object
1719
suites/api/test_pack

0 commit comments

Comments
 (0)