Leptonica  1.82.0
Image processing and image analysis suite
bbuffer.c
Go to the documentation of this file.
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 
100 #ifdef HAVE_CONFIG_H
101 #include <config_auto.h>
102 #endif /* HAVE_CONFIG_H */
103 
104 #include <string.h>
105 #include "allheaders.h"
106 
107  /* Bounds on array size */
108 static const l_uint32 MaxArraySize = 1000000000; /* 10^9 bytes */
109 static const l_int32 InitialArraySize = 1024;
111 /*--------------------------------------------------------------------------*
112  * BBuffer create/destroy *
113  *--------------------------------------------------------------------------*/
129 L_BBUFFER *
130 bbufferCreate(const l_uint8 *indata,
131  l_int32 nalloc)
132 {
133 L_BBUFFER *bb;
134 
135  PROCNAME("bbufferCreate");
136 
137  if (nalloc <= 0 || nalloc > MaxArraySize)
138  nalloc = InitialArraySize;
139 
140  bb = (L_BBUFFER *)LEPT_CALLOC(1, sizeof(L_BBUFFER));
141  if ((bb->array = (l_uint8 *)LEPT_CALLOC(nalloc, sizeof(l_uint8))) == NULL) {
142  LEPT_FREE(bb);
143  return (L_BBUFFER *)ERROR_PTR("byte array not made", procName, NULL);
144  }
145  bb->nalloc = nalloc;
146  bb->nwritten = 0;
147 
148  if (indata) {
149  memcpy(bb->array, indata, nalloc);
150  bb->n = nalloc;
151  } else {
152  bb->n = 0;
153  }
154 
155  return bb;
156 }
157 
158 
171 void
173 {
174 L_BBUFFER *bb;
175 
176  PROCNAME("bbufferDestroy");
177 
178  if (pbb == NULL) {
179  L_WARNING("ptr address is NULL\n", procName);
180  return;
181  }
182 
183  if ((bb = *pbb) == NULL)
184  return;
185 
186  if (bb->array)
187  LEPT_FREE(bb->array);
188  LEPT_FREE(bb);
189  *pbb = NULL;
190 }
191 
192 
205 l_uint8 *
207  size_t *pnbytes)
208 {
209 l_uint8 *array;
210 size_t nbytes;
211 L_BBUFFER *bb;
212 
213  PROCNAME("bbufferDestroyAndSaveData");
214 
215  if (pbb == NULL) {
216  L_WARNING("ptr address is NULL\n", procName);
217  return NULL;
218  }
219  if (pnbytes == NULL) {
220  L_WARNING("&nbytes is NULL\n", procName);
221  bbufferDestroy(pbb);
222  return NULL;
223  }
224 
225  if ((bb = *pbb) == NULL)
226  return NULL;
227 
228  /* write all unwritten bytes out to a new array */
229  nbytes = bb->n - bb->nwritten;
230  *pnbytes = nbytes;
231  if ((array = (l_uint8 *)LEPT_CALLOC(nbytes, sizeof(l_uint8))) == NULL) {
232  L_WARNING("calloc failure for array\n", procName);
233  return NULL;
234  }
235  memcpy(array, bb->array + bb->nwritten, nbytes);
236 
237  bbufferDestroy(pbb);
238  return array;
239 }
240 
241 
242 /*--------------------------------------------------------------------------*
243  * Operations to read data INTO a BBuffer *
244  *--------------------------------------------------------------------------*/
264 l_ok
266  l_uint8 *src,
267  l_int32 nbytes)
268 {
269 l_int32 navail, nadd, nwritten;
270 
271  PROCNAME("bbufferRead");
272 
273  if (!bb)
274  return ERROR_INT("bb not defined", procName, 1);
275  if (!src)
276  return ERROR_INT("src not defined", procName, 1);
277  if (nbytes == 0)
278  return ERROR_INT("no bytes to read", procName, 1);
279 
280  if ((nwritten = bb->nwritten)) { /* move the unwritten bytes over */
281  memmove(bb->array, bb->array + nwritten, bb->n - nwritten);
282  bb->nwritten = 0;
283  bb->n -= nwritten;
284  }
285 
286  /* If necessary, expand the allocated array. Do so by
287  * by at least a factor of two. */
288  navail = bb->nalloc - bb->n;
289  if (nbytes > navail) {
290  nadd = L_MAX(bb->nalloc, nbytes);
291  if (bbufferExtendArray(bb, nadd))
292  return ERROR_INT("extension failed", procName, 1);
293  }
294 
295  /* Read in the new bytes */
296  memcpy(bb->array + bb->n, src, nbytes);
297  bb->n += nbytes;
298  return 0;
299 }
300 
301 
310 l_ok
312  FILE *fp,
313  l_int32 nbytes)
314 {
315 l_int32 navail, nadd, nread, nwritten;
316 
317  PROCNAME("bbufferReadStream");
318 
319  if (!bb)
320  return ERROR_INT("bb not defined", procName, 1);
321  if (!fp)
322  return ERROR_INT("fp not defined", procName, 1);
323  if (nbytes == 0)
324  return ERROR_INT("no bytes to read", procName, 1);
325 
326  if ((nwritten = bb->nwritten)) { /* move any unwritten bytes over */
327  memmove(bb->array, bb->array + nwritten, bb->n - nwritten);
328  bb->nwritten = 0;
329  bb->n -= nwritten;
330  }
331 
332  /* If necessary, expand the allocated array. Do so by
333  * by at least a factor of two. */
334  navail = bb->nalloc - bb->n;
335  if (nbytes > navail) {
336  nadd = L_MAX(bb->nalloc, nbytes);
337  if (bbufferExtendArray(bb, nadd))
338  return ERROR_INT("extension failed", procName, 1);
339  }
340 
341  /* Read in the new bytes */
342  nread = fread(bb->array + bb->n, 1, nbytes, fp);
343  bb->n += nread;
344 
345  return 0;
346 }
347 
348 
362 l_ok
364  l_int32 nbytes)
365 {
366  PROCNAME("bbufferExtendArray");
367 
368  if (!bb)
369  return ERROR_INT("bb not defined", procName, 1);
370 
371  if ((bb->array = (l_uint8 *)reallocNew((void **)&bb->array,
372  bb->nalloc,
373  bb->nalloc + nbytes)) == NULL)
374  return ERROR_INT("new ptr array not returned", procName, 1);
375 
376  bb->nalloc += nbytes;
377  return 0;
378 }
379 
380 
381 /*--------------------------------------------------------------------------*
382  * Operations to write data FROM a BBuffer *
383  *--------------------------------------------------------------------------*/
393 l_ok
395  l_uint8 *dest,
396  size_t nbytes,
397  size_t *pnout)
398 {
399 size_t nleft, nout;
400 
401  PROCNAME("bbufferWrite");
402 
403  if (!bb)
404  return ERROR_INT("bb not defined", procName, 1);
405  if (!dest)
406  return ERROR_INT("dest not defined", procName, 1);
407  if (nbytes <= 0)
408  return ERROR_INT("no bytes requested to write", procName, 1);
409  if (!pnout)
410  return ERROR_INT("&nout not defined", procName, 1);
411 
412  nleft = bb->n - bb->nwritten;
413  nout = L_MIN(nleft, nbytes);
414  *pnout = nout;
415 
416  if (nleft == 0) { /* nothing to write; reinitialize the buffer */
417  bb->n = 0;
418  bb->nwritten = 0;
419  return 0;
420  }
421 
422  /* nout > 0; transfer the data out */
423  memcpy(dest, bb->array + bb->nwritten, nout);
424  bb->nwritten += nout;
425 
426  /* If all written; "empty" the buffer */
427  if (nout == nleft) {
428  bb->n = 0;
429  bb->nwritten = 0;
430  }
431 
432  return 0;
433 }
434 
435 
445 l_ok
447  FILE *fp,
448  size_t nbytes,
449  size_t *pnout)
450 {
451 size_t nleft, nout;
452 
453  PROCNAME("bbufferWriteStream");
454 
455  if (!bb)
456  return ERROR_INT("bb not defined", procName, 1);
457  if (!fp)
458  return ERROR_INT("output stream not defined", procName, 1);
459  if (nbytes <= 0)
460  return ERROR_INT("no bytes requested to write", procName, 1);
461  if (!pnout)
462  return ERROR_INT("&nout not defined", procName, 1);
463 
464  nleft = bb->n - bb->nwritten;
465  nout = L_MIN(nleft, nbytes);
466  *pnout = nout;
467 
468  if (nleft == 0) { /* nothing to write; reinitialize the buffer */
469  bb->n = 0;
470  bb->nwritten = 0;
471  return 0;
472  }
473 
474  /* nout > 0; transfer the data out */
475  fwrite(bb->array + bb->nwritten, 1, nout, fp);
476  bb->nwritten += nout;
477 
478  /* If all written; "empty" the buffer */
479  if (nout == nleft) {
480  bb->n = 0;
481  bb->nwritten = 0;
482  }
483 
484  return 0;
485 }
l_ok bbufferWrite(L_BBUFFER *bb, l_uint8 *dest, size_t nbytes, size_t *pnout)
bbufferWrite()
Definition: bbuffer.c:394
l_ok bbufferRead(L_BBUFFER *bb, l_uint8 *src, l_int32 nbytes)
bbufferRead()
Definition: bbuffer.c:265
L_BBUFFER * bbufferCreate(const l_uint8 *indata, l_int32 nalloc)
bbufferCreate()
Definition: bbuffer.c:130
l_ok bbufferExtendArray(L_BBUFFER *bb, l_int32 nbytes)
bbufferExtendArray()
Definition: bbuffer.c:363
static const l_int32 InitialArraySize
Definition: bbuffer.c:109
l_ok bbufferReadStream(L_BBUFFER *bb, FILE *fp, l_int32 nbytes)
bbufferReadStream()
Definition: bbuffer.c:311
l_ok bbufferWriteStream(L_BBUFFER *bb, FILE *fp, size_t nbytes, size_t *pnout)
bbufferWriteStream()
Definition: bbuffer.c:446
l_uint8 * bbufferDestroyAndSaveData(L_BBUFFER **pbb, size_t *pnbytes)
bbufferDestroyAndSaveData()
Definition: bbuffer.c:206
void bbufferDestroy(L_BBUFFER **pbb)
bbufferDestroy()
Definition: bbuffer.c:172
l_int32 n
Definition: bbuffer.h:53
l_int32 nalloc
Definition: bbuffer.h:52
l_int32 nwritten
Definition: bbuffer.h:54
l_uint8 * array
Definition: bbuffer.h:55
void * reallocNew(void **pindata, size_t oldsize, size_t newsize)
reallocNew()
Definition: utils2.c:1302