scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

realloc.c (1333B)


      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 		errno = EINVAL;
     17 		return 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 }