Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/leptonica/src/stack.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /*====================================================================* | |
| 2 - Copyright (C) 2001 Leptonica. All rights reserved. | |
| 3 - | |
| 4 - Redistribution and use in source and binary forms, with or without | |
| 5 - modification, are permitted provided that the following conditions | |
| 6 - are met: | |
| 7 - 1. Redistributions of source code must retain the above copyright | |
| 8 - notice, this list of conditions and the following disclaimer. | |
| 9 - 2. Redistributions in binary form must reproduce the above | |
| 10 - copyright notice, this list of conditions and the following | |
| 11 - disclaimer in the documentation and/or other materials | |
| 12 - provided with the distribution. | |
| 13 - | |
| 14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY | |
| 18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
| 22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 25 *====================================================================*/ | |
| 26 | |
| 27 /*! | |
| 28 * \file stack.c | |
| 29 * <pre> | |
| 30 * | |
| 31 * Generic stack | |
| 32 * | |
| 33 * The lstack is an array of void * ptrs, onto which | |
| 34 * objects can be stored. At any time, the number of | |
| 35 * stored objects is lstack->n. The object at the bottom | |
| 36 * of the lstack is at array[0]; the object at the top of | |
| 37 * the lstack is at array[n-1]. New objects are added | |
| 38 * to the top of the lstack; i.e., the first available | |
| 39 * location, which is at array[n]. The lstack is expanded | |
| 40 * by doubling, when needed. Objects are removed | |
| 41 * from the top of the lstack. When an attempt is made | |
| 42 * to remove an object from an empty lstack, the result is null. | |
| 43 * | |
| 44 * Create/Destroy | |
| 45 * L_STACK *lstackCreate() | |
| 46 * void lstackDestroy() | |
| 47 * | |
| 48 * Accessors | |
| 49 * l_int32 lstackAdd() | |
| 50 * void *lstackRemove() | |
| 51 * static l_int32 lstackExtendArray() | |
| 52 * l_int32 lstackGetCount() | |
| 53 * | |
| 54 * Text description | |
| 55 * l_int32 lstackPrint() | |
| 56 * </pre> | |
| 57 */ | |
| 58 | |
| 59 #ifdef HAVE_CONFIG_H | |
| 60 #include <config_auto.h> | |
| 61 #endif /* HAVE_CONFIG_H */ | |
| 62 | |
| 63 #include "allheaders.h" | |
| 64 | |
| 65 /* Bounds on initial array size */ | |
| 66 static const l_uint32 MaxPtrArraySize = 100000; | |
| 67 static const l_int32 InitialPtrArraySize = 20; /*!< n'importe quoi */ | |
| 68 | |
| 69 /* Static function */ | |
| 70 static l_int32 lstackExtendArray(L_STACK *lstack); | |
| 71 | |
| 72 /*---------------------------------------------------------------------* | |
| 73 * Create/Destroy * | |
| 74 *---------------------------------------------------------------------*/ | |
| 75 /*! | |
| 76 * \brief lstackCreate() | |
| 77 * | |
| 78 * \param[in] n initial ptr array size; use 0 for default | |
| 79 * \return lstack, or NULL on error | |
| 80 */ | |
| 81 L_STACK * | |
| 82 lstackCreate(l_int32 n) | |
| 83 { | |
| 84 L_STACK *lstack; | |
| 85 | |
| 86 if (n <= 0 || n > (l_int32)MaxPtrArraySize) | |
| 87 n = InitialPtrArraySize; | |
| 88 | |
| 89 lstack = (L_STACK *)LEPT_CALLOC(1, sizeof(L_STACK)); | |
| 90 lstack->array = (void **)LEPT_CALLOC(n, sizeof(void *)); | |
| 91 if (!lstack->array) { | |
| 92 lstackDestroy(&lstack, FALSE); | |
| 93 return (L_STACK *)ERROR_PTR("lstack array not made", __func__, NULL); | |
| 94 } | |
| 95 | |
| 96 lstack->nalloc = n; | |
| 97 lstack->n = 0; | |
| 98 return lstack; | |
| 99 } | |
| 100 | |
| 101 | |
| 102 /*! | |
| 103 * \brief lstackDestroy() | |
| 104 * | |
| 105 * \param[in,out] plstack will be set to null before returning | |
| 106 * \param[in] freeflag TRUE to free each remaining struct in the array | |
| 107 * \return void | |
| 108 * | |
| 109 * <pre> | |
| 110 * Notes: | |
| 111 * (1) If %freeflag is TRUE, frees each struct in the array. | |
| 112 * (2) If %freeflag is FALSE but there are elements on the array, | |
| 113 * gives a warning and destroys the array. This will | |
| 114 * cause a memory leak of all the items that were on the lstack. | |
| 115 * So if the items require their own destroy function, they | |
| 116 * must be destroyed before the lstack. | |
| 117 * (3) To destroy the lstack, we destroy the ptr array, then | |
| 118 * the lstack, and then null the contents of the input ptr. | |
| 119 * </pre> | |
| 120 */ | |
| 121 void | |
| 122 lstackDestroy(L_STACK **plstack, | |
| 123 l_int32 freeflag) | |
| 124 { | |
| 125 void *item; | |
| 126 L_STACK *lstack; | |
| 127 | |
| 128 if (plstack == NULL) { | |
| 129 L_WARNING("ptr address is NULL\n", __func__); | |
| 130 return; | |
| 131 } | |
| 132 if ((lstack = *plstack) == NULL) | |
| 133 return; | |
| 134 | |
| 135 if (freeflag) { | |
| 136 while(lstack->n > 0) { | |
| 137 item = lstackRemove(lstack); | |
| 138 LEPT_FREE(item); | |
| 139 } | |
| 140 } else if (lstack->n > 0) { | |
| 141 L_WARNING("memory leak of %d items in lstack\n", __func__, lstack->n); | |
| 142 } | |
| 143 | |
| 144 if (lstack->auxstack) | |
| 145 lstackDestroy(&lstack->auxstack, freeflag); | |
| 146 | |
| 147 if (lstack->array) | |
| 148 LEPT_FREE(lstack->array); | |
| 149 LEPT_FREE(lstack); | |
| 150 *plstack = NULL; | |
| 151 } | |
| 152 | |
| 153 | |
| 154 | |
| 155 /*---------------------------------------------------------------------* | |
| 156 * Accessors * | |
| 157 *---------------------------------------------------------------------*/ | |
| 158 /*! | |
| 159 * \brief lstackAdd() | |
| 160 * | |
| 161 * \param[in] lstack | |
| 162 * \param[in] item to be added to the lstack | |
| 163 * \return 0 if OK; 1 on error. | |
| 164 */ | |
| 165 l_ok | |
| 166 lstackAdd(L_STACK *lstack, | |
| 167 void *item) | |
| 168 { | |
| 169 if (!lstack) | |
| 170 return ERROR_INT("lstack not defined", __func__, 1); | |
| 171 if (!item) | |
| 172 return ERROR_INT("item not defined", __func__, 1); | |
| 173 | |
| 174 /* Do we need to extend the array? */ | |
| 175 if (lstack->n >= lstack->nalloc) { | |
| 176 if (lstackExtendArray(lstack)) | |
| 177 return ERROR_INT("extension failed", __func__, 1); | |
| 178 } | |
| 179 | |
| 180 /* Store the new pointer */ | |
| 181 lstack->array[lstack->n] = (void *)item; | |
| 182 lstack->n++; | |
| 183 | |
| 184 return 0; | |
| 185 } | |
| 186 | |
| 187 | |
| 188 /*! | |
| 189 * \brief lstackRemove() | |
| 190 * | |
| 191 * \param[in] lstack | |
| 192 * \return ptr to item popped from the top of the lstack, | |
| 193 * or NULL if the lstack is empty or on error | |
| 194 */ | |
| 195 void * | |
| 196 lstackRemove(L_STACK *lstack) | |
| 197 { | |
| 198 void *item; | |
| 199 | |
| 200 if (!lstack) | |
| 201 return ERROR_PTR("lstack not defined", __func__, NULL); | |
| 202 | |
| 203 if (lstack->n == 0) | |
| 204 return NULL; | |
| 205 | |
| 206 lstack->n--; | |
| 207 item = lstack->array[lstack->n]; | |
| 208 | |
| 209 return item; | |
| 210 } | |
| 211 | |
| 212 | |
| 213 /*! | |
| 214 * \brief lstackExtendArray() | |
| 215 * | |
| 216 * \param[in] lstack | |
| 217 * \return 0 if OK; 1 on error | |
| 218 */ | |
| 219 static l_int32 | |
| 220 lstackExtendArray(L_STACK *lstack) | |
| 221 { | |
| 222 if (!lstack) | |
| 223 return ERROR_INT("lstack not defined", __func__, 1); | |
| 224 | |
| 225 if ((lstack->array = (void **)reallocNew((void **)&lstack->array, | |
| 226 sizeof(void *) * lstack->nalloc, | |
| 227 2 * sizeof(void *) * lstack->nalloc)) == NULL) | |
| 228 return ERROR_INT("new lstack array not defined", __func__, 1); | |
| 229 | |
| 230 lstack->nalloc = 2 * lstack->nalloc; | |
| 231 return 0; | |
| 232 } | |
| 233 | |
| 234 | |
| 235 /*! | |
| 236 * \brief lstackGetCount() | |
| 237 * | |
| 238 * \param[in] lstack | |
| 239 * \return count, or 0 on error | |
| 240 */ | |
| 241 l_int32 | |
| 242 lstackGetCount(L_STACK *lstack) | |
| 243 { | |
| 244 if (!lstack) | |
| 245 return ERROR_INT("lstack not defined", __func__, 1); | |
| 246 | |
| 247 return lstack->n; | |
| 248 } | |
| 249 | |
| 250 | |
| 251 | |
| 252 /*---------------------------------------------------------------------* | |
| 253 * Debug output * | |
| 254 *---------------------------------------------------------------------*/ | |
| 255 /*! | |
| 256 * \brief lstackPrint() | |
| 257 * | |
| 258 * \param[in] fp file stream | |
| 259 * \param[in] lstack | |
| 260 * \return 0 if OK; 1 on error | |
| 261 */ | |
| 262 l_ok | |
| 263 lstackPrint(FILE *fp, | |
| 264 L_STACK *lstack) | |
| 265 { | |
| 266 l_int32 i; | |
| 267 | |
| 268 if (!fp) | |
| 269 return ERROR_INT("stream not defined", __func__, 1); | |
| 270 if (!lstack) | |
| 271 return ERROR_INT("lstack not defined", __func__, 1); | |
| 272 | |
| 273 fprintf(fp, "\n Stack: nalloc = %d, n = %d, array = %p\n", | |
| 274 lstack->nalloc, lstack->n, lstack->array); | |
| 275 for (i = 0; i < lstack->n; i++) | |
| 276 fprintf(fp, "array[%d] = %p\n", i, lstack->array[i]); | |
| 277 | |
| 278 return 0; | |
| 279 } |
