summaryrefslogtreecommitdiffstats
path: root/memory/alloc/reallocarray.c
blob: c58dfe980550c1107a8d7fa26192beaef72ea1a6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
 * Copyright (c) Jon Santmyer.
 * This source file is released under the LGPL Version 3 as detailed in
 * the LICENSE file provided in the following repository:
 * https://git.jonsantmyer.com/heap/
 * */

#include "malloc.h"
#include "assert.h"
#include "string.h"

void*
__reallocarray_impl(heap_cache_t *cache, void *ptr, size_t nmemb, size_t w)
{
    /* Free if w == nmemb == 0*/
    if(w == 0 || nmemb == 0) {
        __free_impl(cache, ptr);
        return NULL;
    }
    
    if(ptr == NULL)
        return __calloc_impl(cache, nmemb, w);

    size_t allocw = w * nmemb;
    w = REALW(w);
    
    bucket_obj_t *obj = OBJ_FROM_PTR(ptr);
    assert(OBJ_VALID(obj));
    size_t oldw = OBJ_WIDTH(obj);
    if(allocw < oldw) return ptr;

    ptr = __realloc_impl(cache, ptr, allocw);
    size_t wdiff = allocw - oldw;
    void *zeroat = (void*)(((uintptr_t)ptr) + oldw);
    memset(zeroat, 0, wdiff);
    return ptr;
}