| /* |
| * GraphApp - Cross-Platform Graphics Programming Library. |
| * |
| * File: array.c -- memory allocation functions. |
| * Platform: Neutral Version: 2.35 Date: 1998/03/04 |
| * |
| * Version: 2.30 Changes: Original version by Lachlan Patrick. |
| * Version: 2.35 Changes: Join and append improved by Jim McDonald. |
| */ |
| |
| /* Copyright (C) 1993-1998 Lachlan Patrick |
| |
| This file is part of GraphApp, a cross-platform C graphics library. |
| |
| GraphApp is free software; you can redistribute it and/or modify it |
| under the terms of the GNU Library General Public License. |
| GraphApp is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY. |
| |
| See the file COPYLIB.TXT for details. |
| */ |
| |
| #include <stdlib.h> |
| #include "internal.h" |
| |
| #ifndef array |
| |
| #define create(type) ( (type*) memalloc(sizeof(type)) ) |
| #define array(n,type) ( (type*) memalloc(n*sizeof(type)) ) |
| #define len(a) ( memlength((char*)(a))/sizeof((a)[0]) ) |
| #define element(a,i) ( (((i)<len(a)) && ((i)>=0)) ? (a)[i] : 0 ) |
| #define append(a,e) ( *(char**)&(a)=memexpand((char*)(a),sizeof((a)[0])), \ |
| (a)[len(a)-1]=(e) ) |
| #define shrink(a,ns) ( *(char**)&(a)=memrealloc((char*)(a),(ns)) ) |
| #define join(a,b) ( *(char**)&(a)=memjoin((char*)(a),(char*)(b)) ) |
| #define discard(a) ( memfree((char*)(a)), (a)=0 ) |
| |
| char * memalloc(long size); |
| char * memrealloc(char *a, long new_size); |
| void memfree(char *a); |
| long memlength(char *a); |
| char * memexpand(char *a, long extra); |
| char * memjoin(char *a, char *b); |
| |
| #endif /* array defintions */ |
| |
| #define TRACEAR(a) |
| |
| char * memalloc(long size) |
| { |
| long *block; |
| char *a; |
| long i, datasize; |
| TRACEAR("alloc"); |
| datasize = (((size + 4) >> 2) << 2); |
| #ifdef COMPILER |
| #if (COMPILER <= 16) |
| if ((sizeof(long)+datasize) >= (1<<16)) |
| return NULL; |
| #endif |
| #endif |
| block = (long *) malloc(sizeof(long) + datasize); |
| if (block == NULL) |
| return NULL; |
| block[0] = size; |
| a = (char *) & block[1]; |
| for (i=0; i<datasize; i++) |
| a[i] = '\0'; |
| return a; |
| } |
| |
| char * memrealloc(char *a, long new_size) |
| { |
| long *block; |
| long i, size, oldsize, newsize; |
| TRACEAR("realloc"); |
| if (new_size <= 0) { |
| memfree(a); |
| return NULL; |
| } |
| |
| if (a == NULL) { |
| block = NULL; |
| size = 0; |
| } |
| else { |
| block = ((long*)a) - 1; |
| size = block[0]; |
| } |
| |
| oldsize = size ? (((size + 4) >> 2) << 2) : 0; |
| newsize = (((new_size + 4) >> 2) << 2); |
| |
| if ( newsize != oldsize ) { |
| #ifdef COMPILER |
| #if (COMPILER <= 16) |
| if ((sizeof(long)+newsize) >= (1<<16)) |
| return NULL; |
| #endif |
| #endif |
| block = (long *) realloc(block, sizeof(long) + newsize); |
| if (block == NULL) |
| return NULL; |
| a = (char *) & block[1]; |
| for (i=oldsize; i<newsize; i++) |
| a[i] = '\0'; |
| } |
| |
| block[0] = new_size; |
| return a; |
| } |
| |
| long memlength(char *a) |
| { |
| return (a) ? ((long*)(a)-1)[0] : 0; |
| } |
| |
| void memfree(char *a) |
| { |
| if (a) free((long*)(a)-1); |
| } |
| |
| char * memexpand(char *a, long extra) |
| { |
| long *block; |
| long i, size, oldsize, newsize; |
| TRACEAR("exp"); |
| if (extra == 0) |
| return a; |
| |
| if (a == NULL) { |
| block = NULL; |
| size = 0; |
| } |
| else { |
| block = ((long*)a) - 1; |
| size = block[0]; |
| } |
| |
| oldsize = size ? (((size + 4) >> 2) << 2) : 0; |
| newsize = (((size + extra + 4) >> 2) << 2); |
| |
| if ( newsize != oldsize ) { |
| #ifdef COMPILER |
| #if (COMPILER <= 16) |
| if ((sizeof(long)+newsize) >= (1<<16)) |
| return NULL; |
| #endif |
| #endif |
| block = (long *) realloc(block, sizeof(long) + newsize); |
| if (block == NULL) |
| return NULL; |
| a = (char *) & block[1]; |
| for (i=oldsize; i<newsize; i++) |
| a[i] = '\0'; |
| } |
| |
| block[0] = size + extra; |
| return a; |
| } |
| |
| char * memjoin(char *a, char *b) |
| { |
| long i, size, extra; |
| |
| size = memlength(a); |
| extra = memlength(b); |
| a = memexpand(a, extra); |
| if (a) { |
| for (i=0; i<extra; i++) |
| a[i+size] = b[i]; |
| } |
| return a; |
| } |