/* * Copyright(C) 1999-2020, 2022 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * * See packages/seacas/LICENSE for details */ #include "fmt/ostream.h" #include // for va_arg, va_end, va_list, etc #include // for size_t #include // for nullptr, stderr #include // for exit, free, malloc /*#include "rf_allo.h"*/ #ifdef DEBUG extern int Proc; #endif static void *smalloc(size_t n, char *filename, int lineno); /****************************************************************************** * * Dynamic Allocation of Multidimensional Arrays *----------------------------------------------------------------------------- * * Example Usage: * * typedef struct * { int bus1; * int bus2; * int dest; * } POINT; * * POINT **points, corner; * * points = (POINT **) array_alloc (2, x, y, sizeof(POINT)); * ^ ^ ^ * | | | * number of dimensions--+ | | * | | * first dimension max----+ | * | * second dimension max------+ * * (points may be now be used as if it were declared * POINT points[x][y]) * * This particular version is limited to dimensions of 3 or less. * * corner = points[2][3]; (refer to the structure as you would any array) * * free (points); (frees the entire structure in one fell swoop) * *****************************************************************************/ /****************************************************************************** * The following section is a commented section containing * an example main code: ******************************************************************************* *double *array_alloc(); *main() *{ * int ***temp; * int *temp2; * int i, j, k; * int il, jl, kl; * * malloc_debug(2); * il = 2; * jl = 3; * kl = 3; * temp = (int ***) array_alloc(3,il,jl,kl,sizeof(int)); * for (i=0; i 3) { fmt::print(stderr, "{} ({}: {}) ERROR: number of dimensions, {}, is > 3\n", __func__, file, lineno, numdim); exit(1); } dim[0].index = va_arg(va, size_t); if (dim[0].index == 0) { #ifdef DEBUG fmt::print(stderr, "WARNING, {} ({}: {}) called with first " "dimension == 0; will return nullptr\n", __func__, file, lineno); #endif va_end(va); return (nullptr); } dim[0].total = dim[0].index; dim[0].size = sizeof(void *); dim[0].off = 0; for (int i = 1; i < numdim; i++) { dim[i].index = va_arg(va, size_t); if (dim[i].index == 0) { fmt::print(stderr, "WARNING: {} ({}: {}) called with dimension {} == 0, " " will return nullptr\n", __func__, file, lineno, i + 1); va_end(va); return (nullptr); } dim[i].total = dim[i - 1].total * dim[i].index; dim[i].size = sizeof(void *); dim[i].off = dim[i - 1].off + dim[i - 1].total * dim[i - 1].size; } dim[numdim - 1].size = va_arg(va, size_t); va_end(va); /* Round up the last offset value so data is properly aligned. */ dim[numdim - 1].off = dim[numdim - 1].size * ((dim[numdim - 1].off + dim[numdim - 1].size - 1) / dim[numdim - 1].size); total = dim[numdim - 1].off + dim[numdim - 1].total * dim[numdim - 1].size; dfield = smalloc(total, const_cast(file), lineno); field = reinterpret_cast(dfield); for (int i = 0; i < numdim - 1; i++) { ptr = reinterpret_cast(field + dim[i].off); data = (field + dim[i + 1].off); for (size_t j = 0; j < dim[i].total; j++) { ptr[j] = data + j * dim[i + 1].size * dim[i + 1].index; } } return (dfield); } /* Safe version of malloc. Does not initialize memory .*/ /* Modified by Scott Hutchinson (1421) 20 January 1993 */ /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ static void *smalloc(size_t n, char *filename, int lineno) { void *pntr = nullptr; /* return value */ if (n != 0) { pntr = malloc(n); } if (pntr == nullptr && n != 0) { fmt::print(stderr, "{} (from {},{}) Out of space - number of bytes " "requested = {}\n", __func__, filename, lineno, fmt::group_digits(n)); exit(0); } return pntr; } /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ void safe_free(void **ptr) { /* * This version of free calls the system's free function * with maximum error checking. It also doesn't call free if ptr is * the nullptr pointer. */ if (*ptr != nullptr) { free(*ptr); /* * Set the value of ptr to nullptr, so that further references * to it will be flagged. */ *ptr = nullptr; } } /* safe_free */ /*****************************************************************************/ /* END of rf_allo.c */ /*****************************************************************************/