X-Git-Url: http://git.maemo.org/git/?p=xmlrpc-c;a=blobdiff_plain;f=lib%2Futil%2Finclude%2Fmallocvar.h;fp=lib%2Futil%2Finclude%2Fmallocvar.h;h=9c4f9947fd1933343b63db1f7975e43f5eb18f8a;hp=0000000000000000000000000000000000000000;hb=ce67d0cdeaa37c3e856e23ae4010480887165630;hpb=e355d4e7962400470f467b88f5568de9c8324475 diff --git a/lib/util/include/mallocvar.h b/lib/util/include/mallocvar.h new file mode 100644 index 0000000..9c4f994 --- /dev/null +++ b/lib/util/include/mallocvar.h @@ -0,0 +1,100 @@ +/* These are some dynamic memory allocation facilities. They are essentially + an extension to C, as they do allocations with a cognizance of C + variables. You can use them to make C read more like a high level + language. + + Before including this, you must define an __inline__ macro if your + compiler doesn't recognize it as a keyword. +*/ + +#ifndef MALLOCVAR_INCLUDED +#define MALLOCVAR_INCLUDED + +#include "xmlrpc_config.h" + +#include +#include + +static __inline__ void +mallocProduct(void ** const resultP, + unsigned int const factor1, + unsigned int const factor2) { +/*---------------------------------------------------------------------------- + malloc a space whose size in bytes is the product of 'factor1' and + 'factor2'. But if that size cannot be represented as an unsigned int, + return NULL without allocating anything. Also return NULL if the malloc + fails. + + If either factor is zero, malloc a single byte. + + Note that malloc() actually takes a size_t size argument, so the + proper test would be whether the size can be represented by size_t, + not unsigned int. But there is no reliable indication available to + us, like UINT_MAX, of what the limitations of size_t are. We + assume size_t is at least as expressive as unsigned int and that + nobody really needs to allocate more than 4GB of memory. +-----------------------------------------------------------------------------*/ + if (factor1 == 0 || factor2 == 0) + *resultP = malloc(1); + else { + if (UINT_MAX / factor2 < factor1) + *resultP = NULL; + else + *resultP = malloc(factor1 * factor2); + } +} + + + +static __inline__ void +reallocProduct(void ** const blockP, + unsigned int const factor1, + unsigned int const factor2) { + + if (UINT_MAX / factor2 < factor1) + *blockP = NULL; + else + *blockP = realloc(*blockP, factor1 * factor2); +} + + +/* IMPLEMENTATION NOTE: There are huge strict aliasing pitfalls here + if you cast pointers, e.g. (void **) +*/ + +#define MALLOCARRAY(arrayName, nElements) do { \ + void * array; \ + mallocProduct(&array, nElements, sizeof(arrayName[0])); \ + arrayName = array; \ +} while (0) + +#define REALLOCARRAY(arrayName, nElements) { \ + void * array = arrayName; \ + reallocProduct(&array, nElements, sizeof(arrayName[0])); \ + arrayName = array; \ +} while (0) + + +#define MALLOCARRAY_NOFAIL(arrayName, nElements) \ +do { \ + MALLOCARRAY(arrayName, nElements); \ + if ((arrayName) == NULL) \ + abort(); \ +} while(0) + +#define REALLOCARRAY_NOFAIL(arrayName, nElements) \ +do { \ + REALLOCARRAY(arrayName, nElements); \ + if ((arrayName) == NULL) \ + abort(); \ +} while(0) + + +#define MALLOCVAR(varName) \ + varName = malloc(sizeof(*varName)) + +#define MALLOCVAR_NOFAIL(varName) \ + do {if ((varName = malloc(sizeof(*varName))) == NULL) abort();} while(0) + +#endif +