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 }