Line data Source code
1 : //------------------------------------------------------------------------------ 2 : // LAGraph_Realloc: wrapper for realloc 3 : //------------------------------------------------------------------------------ 4 : 5 : // LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved. 6 : // SPDX-License-Identifier: BSD-2-Clause 7 : // 8 : // For additional details (including references to third party source code and 9 : // other files) see the LICENSE file or contact permission@sei.cmu.edu. See 10 : // Contributors.txt for a full list of contributors. Created, in part, with 11 : // funding and support from the U.S. Government (see Acknowledgments.txt file). 12 : // DM22-0790 13 : 14 : // Contributed by Timothy A. Davis, Texas A&M University 15 : 16 : //------------------------------------------------------------------------------ 17 : 18 : // If p is non-NULL on input, it points to a previously allocated object of 19 : // size at least nitems_old * size_of_item. The object is reallocated to be of 20 : // size at least nitems_new * size_of_item. If p is NULL on input, then a new 21 : // object of that size is allocated. On success, a pointer to the new object 22 : // is returned, and ok is returned as true. If the allocation fails, ok is set 23 : // to false and a pointer to the old (unmodified) object is returned. 24 : 25 : // Usage: 26 : 27 : // int status = LAGraph_Realloc (&p, nitems_new, nitems_old, size_of_item, msg) 28 : // if (status == GrB_SUCCESS) 29 : // { 30 : // p points to a block of at least nitems_new*size_of_item bytes and 31 : // the first part, of size min(nitems_new,nitems_old)*size_of_item, 32 : // has the same content as the old memory block if it was present. 33 : // } 34 : // else 35 : // { 36 : // p points to the old block, unchanged. This case never occurs if 37 : // nitems_new < nitems_old. 38 : // } 39 : 40 : #include "LG_internal.h" 41 : 42 109 : int LAGraph_Realloc 43 : ( 44 : // input/output: 45 : void **p, // old block to reallocate 46 : // input: 47 : size_t nitems_new, // new number of items in the object 48 : size_t nitems_old, // old number of items in the object 49 : size_t size_of_item, // size of each item 50 : char *msg 51 : ) 52 : { 53 : 54 : //-------------------------------------------------------------------------- 55 : // check inputs 56 : //-------------------------------------------------------------------------- 57 : 58 109 : LG_CLEAR_MSG ; 59 109 : LG_ASSERT (p != NULL, GrB_NULL_POINTER) ; 60 : 61 : //-------------------------------------------------------------------------- 62 : // malloc a new block if p is NULL on input 63 : //-------------------------------------------------------------------------- 64 : 65 109 : if ((*p) == NULL) 66 : { 67 1 : LG_TRY (LAGraph_Malloc (p, nitems_new, size_of_item, msg)) ; 68 1 : return (GrB_SUCCESS) ; 69 : } 70 : 71 : //-------------------------------------------------------------------------- 72 : // check inputs 73 : //-------------------------------------------------------------------------- 74 : 75 : // make sure at least one item is allocated 76 108 : nitems_old = LAGRAPH_MAX (1, nitems_old) ; 77 108 : nitems_new = LAGRAPH_MAX (1, nitems_new) ; 78 : 79 : // make sure at least one byte is allocated 80 108 : size_of_item = LAGRAPH_MAX (1, size_of_item) ; 81 : 82 : size_t newsize, oldsize ; 83 108 : bool ok = LG_Multiply_size_t (&newsize, nitems_new, size_of_item) 84 108 : && LG_Multiply_size_t (&oldsize, nitems_old, size_of_item) ; 85 108 : if (!ok) 86 : { 87 : // overflow 88 1 : return (GrB_OUT_OF_MEMORY) ; 89 : } 90 : 91 : //-------------------------------------------------------------------------- 92 : // reallocate an existing block to accommodate the change in # of items 93 : //-------------------------------------------------------------------------- 94 : 95 : //-------------------------------------------------------------------------- 96 : // check for quick return 97 : //-------------------------------------------------------------------------- 98 : 99 107 : if (newsize == oldsize) 100 : { 101 : // If the block does not change, or is shrinking but only by a small 102 : // amount, or is growing but still fits inside the existing block, 103 : // then leave the block as-is. 104 71 : return (GrB_SUCCESS) ; 105 : } 106 : 107 : //-------------------------------------------------------------------------- 108 : // reallocate the memory, or use malloc/memcpy/free 109 : //-------------------------------------------------------------------------- 110 : 111 36 : void *pnew = NULL ; 112 : 113 36 : if (LAGraph_Realloc_function == NULL) 114 : { 115 : 116 : //---------------------------------------------------------------------- 117 : // use malloc/memcpy/free 118 : //---------------------------------------------------------------------- 119 : 120 : // allocate the new space 121 1 : LG_TRY (LAGraph_Malloc (&pnew, nitems_new, size_of_item, msg)) ; 122 : // copy over the data from the old block to the new block 123 : // copy from the old to the new space 124 1 : memcpy (pnew, *p, LAGRAPH_MIN (oldsize, newsize)) ; 125 : // free the old space 126 1 : LG_TRY (LAGraph_Free (p, msg)) ; 127 1 : (*p) = pnew ; 128 : 129 : } 130 : else 131 : { 132 : 133 : //---------------------------------------------------------------------- 134 : // use realloc 135 : //---------------------------------------------------------------------- 136 : 137 35 : pnew = LAGraph_Realloc_function (*p, newsize) ; 138 35 : if (pnew == NULL) return (GrB_OUT_OF_MEMORY) ; 139 35 : (*p) = pnew ; 140 : } 141 : 142 36 : return (GrB_SUCCESS) ; 143 : }