realloc.c - scc - simple c99 compiler
HTML git clone git://git.simple-cc.org/scc
DIR Log
DIR Files
DIR Refs
DIR Submodules
DIR README
DIR LICENSE
---
realloc.c (1330B)
---
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 } else if (nbytes > SIZE_MAX - sizeof(Header)-1) {
19 errno = ENOMEM;
20 return NULL;
21 }
22
23 if (!ptr)
24 return malloc(nbytes);
25
26 nunits = (nbytes+sizeof(Header)-1)/sizeof(Header) + 1;
27 oh = (Header *) ptr - 1;
28
29 if (oh->h.size == nunits)
30 return ptr;
31
32 new = oh + nunits;
33
34 if (nunits < oh->h.size) {
35 new->h.size = oh->h.size - nunits;
36 oh->h.size = nunits;
37 free(new + 1);
38 return ptr;
39 }
40
41 prev = _prevchunk(oh);
42 next = prev->h.next;
43
44 if (oh + oh->h.size == next) {
45 /*
46 * if there is free space adjacent
47 * to the current memory
48 */
49 avail = oh->h.size + next->h.size;
50
51 if (avail == nunits) {
52 oh->h.size = nunits;
53 prev->h.next = next->h.next;
54 _freep = prev;
55 return ptr;
56 }
57
58 if (nunits < avail) {
59 oh->h.size = nunits;
60 prev->h.next = new;
61 new->h.next = next->h.next;
62 new->h.size = avail - nunits;
63 _freep = new;
64 return ptr;
65 }
66 }
67
68 if ((new = malloc(nbytes)) == NULL)
69 return NULL;
70
71 n = (oh->h.size - 1) * sizeof(Header);
72 if (n > nbytes)
73 n = nbytes;
74 memcpy(new, ptr, n);
75 free(ptr);
76
77 return new;
78 }