realloc.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
realloc.c (1327B)
---
1 #include <errno.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include "malloc.h"
7 #undef realloc
8
9 void *
10 realloc(void *ptr, size_t nbytes)
11 {
12 Header *oh, *prev, *next, *new;
13 size_t nunits, avail, onbytes, n;
14
15 if (nbytes == 0) {
16 free(ptr);
17 ptr = NULL;
18 }
19
20 if (nbytes > SIZE_MAX - sizeof(Header)-1) {
21 errno = ENOMEM;
22 return NULL;
23 }
24
25 if (!ptr)
26 return malloc(nbytes);
27
28 nunits = (nbytes+sizeof(Header)-1)/sizeof(Header) + 1;
29 oh = (Header *) ptr - 1;
30
31 if (oh->h.size == nunits)
32 return ptr;
33
34 new = oh + nunits;
35
36 if (nunits < oh->h.size) {
37 new->h.size = oh->h.size - nunits;
38 oh->h.size = nunits;
39 free(new + 1);
40 return ptr;
41 }
42
43 prev = _prevchunk(oh);
44 next = prev->h.next;
45
46 if (oh + oh->h.size == next) {
47 /*
48 * if there is free space adjacent
49 * to the current memory
50 */
51 avail = oh->h.size + next->h.size;
52
53 if (avail == nunits) {
54 oh->h.size = nunits;
55 prev->h.next = next->h.next;
56 _freep = prev;
57 return ptr;
58 }
59
60 if (nunits < avail) {
61 oh->h.size = nunits;
62 prev->h.next = new;
63 new->h.next = next->h.next;
64 new->h.size = avail - nunits;
65 _freep = new;
66 return ptr;
67 }
68 }
69
70 if ((new = malloc(nbytes)) == NULL)
71 return NULL;
72
73 n = (oh->h.size - 1) * sizeof(Header);
74 if (n > nbytes)
75 n = nbytes;
76 memcpy(new, ptr, n);
77 free(ptr);
78
79 return new;
80 }