Leptonica 1.68
C Image Processing Library
|
00001 /*====================================================================* 00002 - Copyright (C) 2001 Leptonica. All rights reserved. 00003 - This software is distributed in the hope that it will be 00004 - useful, but with NO WARRANTY OF ANY KIND. 00005 - No author or distributor accepts responsibility to anyone for the 00006 - consequences of using this software, or for whether it serves any 00007 - particular purpose or works at all, unless he or she says so in 00008 - writing. Everyone is granted permission to copy, modify and 00009 - redistribute this source code, for commercial or non-commercial 00010 - purposes, with the following restrictions: (1) the origin of this 00011 - source code must not be misrepresented; (2) modified versions must 00012 - be plainly marked as such; and (3) this notice may not be removed 00013 - or altered from any source or modified source distribution. 00014 *====================================================================*/ 00015 00016 /* 00017 * bbuffer.c 00018 * 00019 * Create/Destroy BBuffer 00020 * BBUFFER *bbufferCreate() 00021 * void *bbufferDestroy() 00022 * l_uint8 *bbufferDestroyAndSaveData() 00023 * 00024 * Operations to read data TO a BBuffer 00025 * l_int32 bbufferRead() 00026 * l_int32 bbufferReadStream() 00027 * l_int32 bbufferExtendArray() 00028 * 00029 * Operations to write data FROM a BBuffer 00030 * l_int32 bbufferWrite() 00031 * l_int32 bbufferWriteStream() 00032 * 00033 * Accessors 00034 * l_int32 bbufferBytesToWrite() 00035 * 00036 * 00037 * The bbuffer is an implementation of a byte queue. 00038 * The bbuffer holds a byte array from which bytes are 00039 * processed in a first-in/first-out fashion. As with 00040 * any queue, bbuffer maintains two "pointers," one to the 00041 * tail of the queue (where you read new bytes onto it) 00042 * and one to the head of the queue (where you start from 00043 * when writing bytes out of it. 00044 * 00045 * The queue can be visualized: 00046 * 00047 * 00048 * byte 0 byte (nalloc - 1) 00049 * | | 00050 * -------------------------------------------------- 00051 * H T 00052 * [ aw ][ bytes currently on queue ][ anr ] 00053 * 00054 * ---: all allocated data in bbuffer 00055 * H: queue head (ptr to next byte to be written out) 00056 * T: queue tail (ptr to first byte to be written to) 00057 * aw: already written from queue 00058 * anr: allocated but not yet read to 00059 * 00060 * The purpose of bbuffer is to allow you to safely read 00061 * bytes in, and to sequentially write them out as well. 00062 * In the process of writing bytes out, you don't actually 00063 * remove the bytes in the array; you just move the pointer 00064 * (nwritten) which points to the head of the queue. In 00065 * the process of reading bytes in, you sometimes need to 00066 * expand the array size. If a read is performed after a 00067 * write, so that the head of the queue is not at the 00068 * beginning of the array, the bytes already written are 00069 * first removed by copying the others over them; then the 00070 * new bytes are read onto the tail of the queue. 00071 * 00072 * Note that the meaning of "read into" and "write from" 00073 * the bbuffer is OPPOSITE to that for a stream, where 00074 * you read "from" a stream and write "into" a stream. 00075 * As a mnemonic for remembering the direction: 00076 * - to read bytes from a stream into the bbuffer, 00077 * you call fread on the stream 00078 * - to write bytes from the bbuffer into a stream, 00079 * you call fwrite on the stream 00080 * 00081 * See zlibmem.c for an example use of bbuffer, where we 00082 * compress and decompress an array of bytes in memory. 00083 */ 00084 00085 #include <string.h> 00086 #include "allheaders.h" 00087 00088 static const l_int32 INITIAL_BUFFER_ARRAYSIZE = 1024; /* n'importe quoi */ 00089 00090 00091 /*--------------------------------------------------------------------------* 00092 * BBuffer create/destroy * 00093 *--------------------------------------------------------------------------*/ 00094 /*! 00095 * bbufferCreate() 00096 * 00097 * Input: buffer address in memory (<optional>) 00098 * size of byte array to be alloc'd (0 for default) 00099 * Return: bbuffer, or null on error 00100 * 00101 * Notes: 00102 * (1) If a buffer address is given, you should read all the data in. 00103 * (2) Allocates a bbuffer with associated byte array of 00104 * the given size. If a buffer address is given, 00105 * it then reads the number of bytes into the byte array. 00106 */ 00107 BBUFFER * 00108 bbufferCreate(l_uint8 *indata, 00109 l_int32 nalloc) 00110 { 00111 BBUFFER *bb; 00112 00113 PROCNAME("bbufferCreate"); 00114 00115 if (nalloc <= 0) 00116 nalloc = INITIAL_BUFFER_ARRAYSIZE; 00117 00118 if ((bb = (BBUFFER *)CALLOC(1, sizeof(BBUFFER))) == NULL) 00119 return (BBUFFER *)ERROR_PTR("bb not made", procName, NULL); 00120 if ((bb->array = (l_uint8 *)CALLOC(nalloc, sizeof(l_uint8))) == NULL) 00121 return (BBUFFER *)ERROR_PTR("byte array not made", procName, NULL); 00122 bb->nalloc = nalloc; 00123 bb->nwritten = 0; 00124 00125 if (indata) { 00126 memcpy((l_uint8 *)bb->array, indata, nalloc); 00127 bb->n = nalloc; 00128 } 00129 else 00130 bb->n = 0; 00131 00132 return bb; 00133 } 00134 00135 00136 /*! 00137 * bbufferDestroy() 00138 * 00139 * Input: &bbuffer (<to be nulled>) 00140 * Return: void 00141 * 00142 * Notes: 00143 * (1) Destroys the byte array in the bbuffer and then the bbuffer; 00144 * then nulls the contents of the input ptr. 00145 */ 00146 void 00147 bbufferDestroy(BBUFFER **pbb) 00148 { 00149 BBUFFER *bb; 00150 00151 PROCNAME("bbufferDestroy"); 00152 00153 if (pbb == NULL) { 00154 L_WARNING("ptr address is NULL", procName); 00155 return; 00156 } 00157 00158 if ((bb = *pbb) == NULL) 00159 return; 00160 00161 if (bb->array) 00162 FREE(bb->array); 00163 FREE(bb); 00164 *pbb = NULL; 00165 00166 return; 00167 } 00168 00169 00170 /*! 00171 * bbufferDestroyAndSaveData() 00172 * 00173 * Input: &bbuffer (<to be nulled>) 00174 * &nbytes (<return> number of bytes saved in array) 00175 * Return: barray (newly allocated array of data) 00176 * 00177 * Notes: 00178 * (1) Copies data to newly allocated array; then destroys the bbuffer. 00179 */ 00180 l_uint8 * 00181 bbufferDestroyAndSaveData(BBUFFER **pbb, 00182 size_t *pnbytes) 00183 { 00184 l_uint8 *array; 00185 size_t nbytes; 00186 BBUFFER *bb; 00187 00188 PROCNAME("bbufferDestroyAndSaveData"); 00189 00190 if (pbb == NULL) { 00191 L_WARNING("ptr address is NULL", procName); 00192 return NULL; 00193 } 00194 if (pnbytes == NULL) { 00195 L_WARNING("&nbytes is NULL", procName); 00196 bbufferDestroy(pbb); 00197 return NULL; 00198 } 00199 00200 if ((bb = *pbb) == NULL) 00201 return NULL; 00202 00203 /* write all unwritten bytes out to a new array */ 00204 nbytes = bb->n - bb->nwritten; 00205 *pnbytes = nbytes; 00206 if ((array = (l_uint8 *)CALLOC(nbytes, sizeof(l_uint8))) == NULL) { 00207 L_WARNING("calloc failure for array", procName); 00208 return NULL; 00209 } 00210 memcpy((void *)array, (void *)(bb->array + bb->nwritten), nbytes); 00211 00212 bbufferDestroy(pbb); 00213 return array; 00214 } 00215 00216 00217 00218 /*--------------------------------------------------------------------------* 00219 * Operations to read data INTO a BBuffer * 00220 *--------------------------------------------------------------------------*/ 00221 /*! 00222 * bbufferRead() 00223 * 00224 * Input: bbuffer 00225 * src (source memory buffer from which bytes are read) 00226 * nbytes (bytes to be read) 00227 * Return: 0 if OK, 1 on error 00228 * 00229 * Notes: 00230 * (1) For a read after write, first remove the written 00231 * bytes by shifting the unwritten bytes in the array, 00232 * then check if there is enough room to add the new bytes. 00233 * If not, realloc with bbufferExpandArray(), resulting 00234 * in a second writing of the unwritten bytes. While less 00235 * efficient, this is simpler than making a special case 00236 * of reallocNew(). 00237 */ 00238 l_int32 00239 bbufferRead(BBUFFER *bb, 00240 l_uint8 *src, 00241 l_int32 nbytes) 00242 { 00243 l_int32 navail, nadd, nwritten; 00244 00245 PROCNAME("bbufferRead"); 00246 00247 if (!bb) 00248 return ERROR_INT("bb not defined", procName, 1); 00249 if (!src) 00250 return ERROR_INT("src not defined", procName, 1); 00251 if (nbytes == 0) 00252 return ERROR_INT("no bytes to read", procName, 1); 00253 00254 if ((nwritten = bb->nwritten)) { /* move the unwritten bytes over */ 00255 memmove((l_uint8 *)bb->array, (l_uint8 *)(bb->array + nwritten), 00256 bb->n - nwritten); 00257 bb->nwritten = 0; 00258 bb->n -= nwritten; 00259 } 00260 00261 /* If necessary, expand the allocated array. Do so by 00262 * by at least a factor of two. */ 00263 navail = bb->nalloc - bb->n; 00264 if (nbytes > navail) { 00265 nadd = L_MAX(bb->nalloc, nbytes); 00266 bbufferExtendArray(bb, nadd); 00267 } 00268 00269 /* Read in the new bytes */ 00270 memcpy((l_uint8 *)(bb->array + bb->n), src, nbytes); 00271 bb->n += nbytes; 00272 00273 return 0; 00274 } 00275 00276 00277 /*! 00278 * bbufferReadStream() 00279 * 00280 * Input: bbuffer 00281 * fp (source stream from which bytes are read) 00282 * nbytes (bytes to be read) 00283 * Return: 0 if OK, 1 on error 00284 */ 00285 l_int32 00286 bbufferReadStream(BBUFFER *bb, 00287 FILE *fp, 00288 l_int32 nbytes) 00289 { 00290 l_int32 navail, nadd, nread, nwritten; 00291 00292 PROCNAME("bbufferReadStream"); 00293 00294 if (!bb) 00295 return ERROR_INT("bb not defined", procName, 1); 00296 if (!fp) 00297 return ERROR_INT("fp not defined", procName, 1); 00298 if (nbytes == 0) 00299 return ERROR_INT("no bytes to read", procName, 1); 00300 00301 if ((nwritten = bb->nwritten)) { /* move any unwritten bytes over */ 00302 memmove((l_uint8 *)bb->array, (l_uint8 *)(bb->array + nwritten), 00303 bb->n - nwritten); 00304 bb->nwritten = 0; 00305 bb->n -= nwritten; 00306 } 00307 00308 /* If necessary, expand the allocated array. Do so by 00309 * by at least a factor of two. */ 00310 navail = bb->nalloc - bb->n; 00311 if (nbytes > navail) { 00312 nadd = L_MAX(bb->nalloc, nbytes); 00313 bbufferExtendArray(bb, nadd); 00314 } 00315 00316 /* Read in the new bytes */ 00317 nread = fread((void *)(bb->array + bb->n), 1, nbytes, fp); 00318 bb->n += nread; 00319 00320 return 0; 00321 } 00322 00323 00324 /*! 00325 * bbufferExtendArray() 00326 * 00327 * Input: bbuffer 00328 * nbytes (number of bytes to extend array size) 00329 * Return: 0 if OK, 1 on error 00330 * 00331 * Notes: 00332 * (1) reallocNew() copies all bb->nalloc bytes, even though 00333 * only bb->n are data. 00334 */ 00335 l_int32 00336 bbufferExtendArray(BBUFFER *bb, 00337 l_int32 nbytes) 00338 { 00339 PROCNAME("bbufferExtendArray"); 00340 00341 if (!bb) 00342 return ERROR_INT("bb not defined", procName, 1); 00343 00344 if ((bb->array = (l_uint8 *)reallocNew((void **)&bb->array, 00345 bb->nalloc, 00346 bb->nalloc + nbytes)) == NULL) 00347 return ERROR_INT("new ptr array not returned", procName, 1); 00348 00349 bb->nalloc += nbytes; 00350 return 0; 00351 } 00352 00353 00354 00355 /*--------------------------------------------------------------------------* 00356 * Operations to write data FROM a BBuffer * 00357 *--------------------------------------------------------------------------*/ 00358 /*! 00359 * bbufferWrite() 00360 * 00361 * Input: bbuffer 00362 * dest (dest memory buffer to which bytes are written) 00363 * nbytes (bytes requested to be written) 00364 * &nout (<return> bytes actually written) 00365 * Return: 0 if OK, 1 on error 00366 */ 00367 l_int32 00368 bbufferWrite(BBUFFER *bb, 00369 l_uint8 *dest, 00370 size_t nbytes, 00371 size_t *pnout) 00372 { 00373 l_int32 nleft, nout; 00374 00375 PROCNAME("bbufferWrite"); 00376 00377 if (!bb) 00378 return ERROR_INT("bb not defined", procName, 1); 00379 if (!dest) 00380 return ERROR_INT("dest not defined", procName, 1); 00381 if (nbytes <= 0) 00382 return ERROR_INT("no bytes requested to write", procName, 1); 00383 if (!pnout) 00384 return ERROR_INT("&nout not defined", procName, 1); 00385 00386 nleft = bb->n - bb->nwritten; 00387 nout = L_MIN(nleft, nbytes); 00388 *pnout = nout; 00389 00390 if (nleft == 0) { /* nothing to write; reinitialize the buffer */ 00391 bb->n = 0; 00392 bb->nwritten = 0; 00393 return 0; 00394 } 00395 00396 /* nout > 0; transfer the data out */ 00397 memcpy(dest, (l_uint8 *)(bb->array + bb->nwritten), nout); 00398 bb->nwritten += nout; 00399 00400 /* If all written; "empty" the buffer */ 00401 if (nout == nleft) { 00402 bb->n = 0; 00403 bb->nwritten = 0; 00404 } 00405 00406 return 0; 00407 } 00408 00409 00410 /*! 00411 * bbufferWriteStream() 00412 * 00413 * Input: bbuffer 00414 * fp (dest stream to which bytes are written) 00415 * nbytes (bytes requested to be written) 00416 * &nout (<return> bytes actually written) 00417 * Return: 0 if OK, 1 on error 00418 */ 00419 l_int32 00420 bbufferWriteStream(BBUFFER *bb, 00421 FILE *fp, 00422 size_t nbytes, 00423 size_t *pnout) 00424 { 00425 l_int32 nleft, nout; 00426 00427 PROCNAME("bbufferWriteStream"); 00428 00429 if (!bb) 00430 return ERROR_INT("bb not defined", procName, 1); 00431 if (!fp) 00432 return ERROR_INT("output stream not defined", procName, 1); 00433 if (nbytes <= 0) 00434 return ERROR_INT("no bytes requested to write", procName, 1); 00435 if (!pnout) 00436 return ERROR_INT("&nout not defined", procName, 1); 00437 00438 nleft = bb->n - bb->nwritten; 00439 nout = L_MIN(nleft, nbytes); 00440 *pnout = nout; 00441 00442 if (nleft == 0) { /* nothing to write; reinitialize the buffer */ 00443 bb->n = 0; 00444 bb->nwritten = 0; 00445 return 0; 00446 } 00447 00448 /* nout > 0; transfer the data out */ 00449 fwrite((void *)(bb->array + bb->nwritten), 1, nout, fp); 00450 bb->nwritten += nout; 00451 00452 /* If all written; "empty" the buffer */ 00453 if (nout == nleft) { 00454 bb->n = 0; 00455 bb->nwritten = 0; 00456 } 00457 00458 return 0; 00459 } 00460 00461 00462 00463 /*--------------------------------------------------------------------------* 00464 * Accessors * 00465 *--------------------------------------------------------------------------*/ 00466 /*! 00467 * bbufferBytesToWrite() 00468 * 00469 * Input: bbuffer 00470 * &nbytes (<return>) 00471 * Return: 0 if OK; 1 on error 00472 */ 00473 l_int32 00474 bbufferBytesToWrite(BBUFFER *bb, 00475 size_t *pnbytes) 00476 { 00477 PROCNAME("bbufferBytesToWrite"); 00478 00479 if (!bb) 00480 return ERROR_INT("bb not defined", procName, 1); 00481 if (!pnbytes) 00482 return ERROR_INT("&nbytes not defined", procName, 1); 00483 00484 *pnbytes = bb->n - bb->nwritten; 00485 return 0; 00486 } 00487 00488