diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2010-06-27 19:52:28 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2010-06-27 19:52:28 +0000 |
commit | b64acd496028fb582d052f9e7fccfe6d542f85ca (patch) | |
tree | f857dd13be86692b13199c0da7bdfe343b8e30a2 /lib/libpm.c | |
parent | e0d1d6e5f3836c0f5b2bf20a8666b312802a540e (diff) | |
download | netpbm-mirror-b64acd496028fb582d052f9e7fccfe6d542f85ca.tar.gz netpbm-mirror-b64acd496028fb582d052f9e7fccfe6d542f85ca.tar.xz netpbm-mirror-b64acd496028fb582d052f9e7fccfe6d542f85ca.zip |
Add MALLOCARRAY2
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1249 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib/libpm.c')
-rw-r--r-- | lib/libpm.c | 149 |
1 files changed, 14 insertions, 135 deletions
diff --git a/lib/libpm.c b/lib/libpm.c index b8a322a1..6c01148c 100644 --- a/lib/libpm.c +++ b/lib/libpm.c @@ -311,140 +311,26 @@ pm_freerow(void * const itrow) { -static void -allocarrayNoHeap(unsigned char ** const rowIndex, - unsigned int const cols, - unsigned int const rows, - unsigned int const size, - const char ** const errorP) { - - if (cols != 0 && UINT_MAX / cols < size) - asprintfN(errorP, - "Arithmetic overflow multiplying %u by %u to get the " - "size of a row to allocate.", cols, size); - else { - unsigned int rowsDone; - - rowsDone = 0; - *errorP = NULL; - - while (rowsDone < rows && !*errorP) { - unsigned char * const rowSpace = mallocz(cols * size); - if (rowSpace == NULL) - asprintfN(errorP, - "Unable to allocate a %u-column by %u byte row", - cols, size); - else - rowIndex[rowsDone++] = rowSpace; - } - if (*errorP) { - unsigned int row; - for (row = 0; row < rowsDone; ++row) - free(rowIndex[row]); - } - } -} - - - -static unsigned char * -allocRowHeap(unsigned int const cols, - unsigned int const rows, - unsigned int const size) { -/*---------------------------------------------------------------------------- - Allocate a row heap. That's a chunk of memory for use in a - pm_allocarray two-dimensional array to contain the rows. - - The heap must fit 'rows' rows of 'cols' columns each of elements - 'size' bytes in size. - - Return NULL if we can't get the memory. ------------------------------------------------------------------------------*/ - unsigned char * retval; - - if (cols != 0 && rows != 0 && UINT_MAX / cols / rows < size) - /* Too big even to request the memory ! */ - retval = NULL; - else - retval = mallocz(rows * cols * size); - - return retval; -} - - - char ** pm_allocarray(int const cols, int const rows, - int const size ) { + int const elementSize ) { /*---------------------------------------------------------------------------- - Allocate an array of 'rows' rows of 'cols' columns each, with each - element 'size' bytes. - - We use the C multidimensional array paradigm: The array is a row - index (array of pointers to rows) plus an array of elements for each - of those rows. So a[row][col] gives you the element of the two - dimensional array at Row 'row', Column 'col'. - - But we use a special variation on that where we tack on an extra element to - the row index to indicate the format of the array. - - We do NOT TAKE CARE OF ALIGNMENT. Alignment of the elements is only one - byte even if 'size' indicates elements are 4 bytes each. Normally, it - would be a good idea to align such elements to 4 byte boundaries (address - is a multiple of 4). But we don't, so watch out. - - We have two ways of allocating the space: fragmented and - unfragmented. In both, the row index (plus the extra element) is - in one block of memory. In the fragmented format, each row is - also in an independent memory block, and the extra row pointer is - NULL. In the unfragmented format, all the rows are in a single - block of memory called the row heap and the extra row pointer is - the address of that block. - - We use unfragmented format if possible, but if the allocation of the - row heap fails, we fall back to fragmented. ------------------------------------------------------------------------------*/ - unsigned char ** rowIndex; - const char * error; - - MALLOCARRAY(rowIndex, rows + 1); - if (rowIndex == NULL) - asprintfN(&error, - "out of memory allocating row index (%u rows) for an array", - rows); - else { - unsigned char * rowheap; + This is for backward compatibility. MALLOCARRAY2 is usually better. - rowheap = allocRowHeap(cols, rows, size); + A problem with pm_allocarray() is that its return type is char ** + even though 'elementSize' can be other than 1. So users have + traditionally type cast the result. In the old days, that was just + messy; modern compilers can produce the wrong code if you do that. +-----------------------------------------------------------------------------*/ + char ** retval; + void * result; - if (rowheap) { - /* It's unfragmented format */ + pm_mallocarray2(&result, rows, cols, elementSize); - rowIndex[rows] = rowheap; /* Declare it unfragmented format */ + retval = result; - if (rowheap) { - unsigned int row; - - for (row = 0; row < rows; ++row) - rowIndex[row] = &(rowheap[row * cols * size]); - } - error = NULL; - } else { - /* We couldn't get the whole heap in one block, so try fragmented - format. - */ - rowIndex[rows] = NULL; /* Declare it fragmented format */ - - allocarrayNoHeap(rowIndex, cols, rows, size, &error); - } - } - if (error) { - pm_errormsg("Couldn't allocate %u-row array. %s", rows, error); - strfree(error); - pm_longjmp(); - } - return (char **)rowIndex; + return retval; } @@ -453,16 +339,9 @@ void pm_freearray(char ** const rowIndex, int const rows) { - void * const rowheap = rowIndex[rows]; + void * const rowIndexVoid = rowIndex; - if (rowheap != NULL) - free(rowheap); - else { - unsigned int row; - for (row = 0; row < rows; ++row) - pm_freerow(rowIndex[row]); - } - free(rowIndex); + pm_freearray2(rowIndexVoid); } |