buffer.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003                              -------------------
00004     cvs         : $Id$
00005     begin       : Fri Sep 12 2003
00006     copyright   : (C) 2003 by Martin Preuss
00007     email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU Lesser General Public            *
00013  *   License as published by the Free Software Foundation; either          *
00014  *   version 2.1 of the License, or (at your option) any later version.    *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00024  *   MA  02111-1307  USA                                                   *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 
00029 #ifdef HAVE_CONFIG_H
00030 # include <config.h>
00031 #endif
00032 
00033 #define DISABLE_DEBUGLOG
00034 
00035 #include "buffer_p.h"
00036 #include <gwenhywfar/misc.h>
00037 #include <gwenhywfar/debug.h>
00038 #include <gwenhywfar/text.h>
00039 
00040 
00041 GWEN_BUFFER *GWEN_Buffer_new(char *buffer,
00042                              uint32_t size,
00043                              uint32_t used,
00044                              int take){
00045   GWEN_BUFFER *bf;
00046 
00047   GWEN_NEW_OBJECT(GWEN_BUFFER, bf);
00048   if (!buffer) {
00049     /* allocate buffer */
00050     if (size) {
00051       bf->realPtr=(char*)GWEN_Memory_malloc(size+1);
00052       assert(bf->realPtr);
00053       bf->ptr=bf->realPtr;
00054       bf->realBufferSize=size+1;
00055       bf->bufferSize=size+1;
00056       bf->flags=GWEN_BUFFER_FLAGS_OWNED;
00057       bf->bytesUsed=used;
00058       bf->ptr[0]=0;
00059     }
00060   }
00061   else {
00062     /* use existing buffer */
00063     bf->realPtr=buffer;
00064     bf->ptr=buffer;
00065     bf->realBufferSize=size;
00066     bf->bufferSize=size;
00067     bf->bytesUsed=used;
00068     if (take)
00069       bf->flags=GWEN_BUFFER_FLAGS_OWNED;
00070   }
00071 
00072   bf->mode=GWEN_BUFFER_MODE_DEFAULT;
00073   bf->hardLimit=GWEN_BUFFER_DEFAULT_HARDLIMIT;
00074   bf->step=GWEN_BUFFER_DYNAMIC_STEP;
00075   return bf;
00076 }
00077 
00078 
00079 
00080 void GWEN_Buffer_free(GWEN_BUFFER *bf){
00081   if (bf) {
00082     if (bf->flags & GWEN_BUFFER_FLAGS_OWNED)
00083       GWEN_Memory_dealloc(bf->realPtr);
00084     if (bf->bio) {
00085       if (bf->flags & GWEN_BUFFER_FLAGS_OWN_BIO) {
00086         GWEN_BufferedIO_free(bf->bio);
00087       }
00088     }
00089     GWEN_FREE_OBJECT(bf);
00090   }
00091 }
00092 
00093 
00094 
00095 GWEN_BUFFER *GWEN_Buffer_dup(GWEN_BUFFER *bf) {
00096   GWEN_BUFFER *newbf;
00097   uint32_t i;
00098 
00099   GWEN_NEW_OBJECT(GWEN_BUFFER, newbf);
00100   if (bf->realPtr && bf->realBufferSize) {
00101     newbf->realPtr=(char*)GWEN_Memory_malloc(bf->realBufferSize);
00102     newbf->ptr=newbf->realPtr+(bf->ptr-bf->realPtr);
00103     newbf->realBufferSize=bf->realBufferSize;
00104     newbf->bufferSize=bf->bufferSize;
00105     newbf->bytesUsed=bf->bytesUsed;
00106     if (newbf->bytesUsed) {
00107       unsigned int toCopy;
00108 
00109       toCopy=bf->bytesUsed+1;
00110       if (toCopy>(newbf->bufferSize)) {
00111         fprintf(stderr, "Panic: Too many bytes in buffer");
00112         abort();
00113       }
00114       memmove(newbf->ptr, bf->ptr, toCopy);
00115     }
00116     newbf->pos=bf->pos;
00117   }
00118   newbf->flags=bf->flags | GWEN_BUFFER_FLAGS_OWNED;
00119   newbf->mode=bf->mode&GWEN_BUFFER_MODE_COPYMASK;
00120   newbf->hardLimit=bf->hardLimit;
00121   newbf->step=bf->step;
00122   for (i=0; i<GWEN_BUFFER_MAX_BOOKMARKS; i++)
00123     newbf->bookmarks[i]=bf->bookmarks[i];
00124 
00125   return newbf;
00126 }
00127 
00128 
00129 
00130 int GWEN_Buffer_Relinquish(GWEN_BUFFER *bf) {
00131   assert(bf);
00132   if (!(bf->flags & GWEN_BUFFER_FLAGS_OWNED))
00133     return GWEN_ERROR_INVALID;
00134   if (bf->realPtr!=bf->ptr)
00135     return GWEN_ERROR_INVALID;
00136 
00137   bf->flags&=~GWEN_BUFFER_FLAGS_OWNED;
00138   return 0;
00139 }
00140 
00141 
00142 
00143 int GWEN_Buffer_ReserveBytes(GWEN_BUFFER *bf, uint32_t res){
00144   assert(bf);
00145   if (!res)
00146     return 0;
00147 
00148   if (bf->bytesUsed) {
00149     /* we need to move data */
00150     if (GWEN_Buffer_AllocRoom(bf, res))
00151       return -1;
00152 
00153     memmove(bf->ptr+res, bf->ptr, bf->bytesUsed);
00154     bf->ptr+=res;
00155     bf->bufferSize-=res;
00156     return 0;
00157   }
00158   else {
00159     /* no data in buffer, so simply move ptrs */
00160     if (GWEN_Buffer_AllocRoom(bf, res))
00161       return -1;
00162 
00163     bf->ptr+=res;
00164     bf->bufferSize-=res;
00165     if (bf->bufferSize)
00166       bf->ptr[0]=0;
00167     return 0;
00168   }
00169 }
00170 
00171 
00172 
00173 uint32_t GWEN_Buffer_GetMode(GWEN_BUFFER *bf){
00174   assert(bf);
00175   return bf->mode;
00176 }
00177 
00178 
00179 
00180 void GWEN_Buffer_SetMode(GWEN_BUFFER *bf, uint32_t mode){
00181   assert(bf);
00182   bf->mode=mode;
00183 }
00184 
00185 
00186 void GWEN_Buffer_AddMode(GWEN_BUFFER *bf, uint32_t mode){
00187   assert(bf);
00188   bf->mode|=mode;
00189 }
00190 
00191 
00192 void GWEN_Buffer_SubMode(GWEN_BUFFER *bf, uint32_t mode){
00193   assert(bf);
00194   bf->mode&=~mode;
00195 }
00196 
00197 
00198 
00199 uint32_t GWEN_Buffer_GetHardLimit(GWEN_BUFFER *bf){
00200   assert(bf);
00201   return bf->hardLimit;
00202 }
00203 
00204 
00205 
00206 void GWEN_Buffer_SetHardLimit(GWEN_BUFFER *bf, uint32_t l){
00207   assert(bf);
00208   assert(l);
00209   bf->hardLimit=l;
00210 }
00211 
00212 
00213 
00214 char *GWEN_Buffer_GetStart(GWEN_BUFFER *bf){
00215   assert(bf);
00216   return bf->ptr;
00217 }
00218 
00219 
00220 
00221 uint32_t GWEN_Buffer_GetSize(GWEN_BUFFER *bf){
00222   assert(bf);
00223   if (bf->mode & GWEN_BUFFER_MODE_DYNAMIC)
00224     return bf->hardLimit;
00225   return bf->bufferSize;
00226 }
00227 
00228 
00229 
00230 uint32_t GWEN_Buffer_GetPos(GWEN_BUFFER *bf){
00231   assert(bf);
00232   return bf->pos;
00233 }
00234 
00235 
00236 
00237 int GWEN_Buffer_SetPos(GWEN_BUFFER *bf, uint32_t i){
00238   assert(bf);
00239 
00240   if (i>=bf->bufferSize) {
00241     if ((bf->mode & GWEN_BUFFER_MODE_USE_BIO) ||
00242         (bf->mode & GWEN_BUFFER_MODE_USE_IO)) {
00243       bf->pos=i;
00244     }
00245     else {
00246       DBG_ERROR(GWEN_LOGDOMAIN,
00247                 "Position %d outside buffer boundaries (%d bytes)",
00248                 i, bf->bufferSize);
00249       return -1;
00250     }
00251   }
00252   bf->pos=i;
00253   return 0;
00254 }
00255 
00256 
00257 
00258 uint32_t GWEN_Buffer_GetUsedBytes(GWEN_BUFFER *bf){
00259   assert(bf);
00260   return bf->bytesUsed;
00261 }
00262 
00263 
00264 
00265 int GWEN_Buffer_SetUsedBytes(GWEN_BUFFER *bf, uint32_t i){
00266   assert(bf);
00267 
00268   DBG_WARN(GWEN_LOGDOMAIN,
00269            "GWEN_Buffer_SetUsedBytes: Deprecated, "
00270            "please use GWEN_Buffer_Crop instead.");
00271   if (i>bf->bufferSize) {
00272     DBG_ERROR(GWEN_LOGDOMAIN, "Bytes used>buffer size (%d>%d bytes)",
00273               i, bf->bufferSize);
00274     return 1;
00275   }
00276   bf->bytesUsed=i;
00277   return 0;
00278 }
00279 
00280 
00281 
00282 int GWEN_Buffer_AllocRoom(GWEN_BUFFER *bf, uint32_t size) {
00283   assert(bf);
00284   /*DBG_VERBOUS(GWEN_LOGDOMAIN, "Allocating %d bytes", size);*/
00285   /*if (bf->pos+size>bf->bufferSize) {*/
00286   if (bf->bytesUsed+(size+1) > bf->bufferSize) {
00287     /* need to realloc */
00288     uint32_t nsize;
00289     uint32_t noffs;
00290     uint32_t reserved;
00291     void *p;
00292 
00293     /* check for dynamic mode */
00294     if (!(bf->mode & GWEN_BUFFER_MODE_DYNAMIC)) {
00295       DBG_ERROR(GWEN_LOGDOMAIN, "Not in dynamic mode");
00296       if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
00297         abort();
00298       }
00299       return 1;
00300     }
00301 
00302     /* calculate reserved bytes (to set ptr later) */
00303     reserved=bf->ptr-bf->realPtr;
00304     /* this is the raw number of bytes we need */
00305     /*nsize=bf->pos+size-bf->bufferSize;*/
00306     nsize=bf->bytesUsed+(size+1)-bf->bufferSize;
00307     /* round it up */
00308     nsize=(nsize+(bf->step-1));
00309     nsize&=~(bf->step-1);
00310     /* store number of additional bytes to allocate */
00311     noffs=nsize;
00312     /* add current size to it */
00313     nsize+=bf->realBufferSize;
00314     if (nsize>bf->hardLimit) {
00315       DBG_ERROR(GWEN_LOGDOMAIN,
00316                 "Size is beyond hard limit (%d>%d)",
00317                 nsize, bf->hardLimit);
00318       if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
00319         abort();
00320       }
00321       return 1;
00322     }
00323     DBG_VERBOUS(GWEN_LOGDOMAIN, "Reallocating from %d to %d bytes",
00324                 bf->bufferSize, nsize);
00325     /* we always add a NULL character */
00326     if (bf->realPtr==NULL) {
00327       p=GWEN_Memory_malloc(nsize+1);
00328     }
00329     else {
00330       p=GWEN_Memory_realloc(bf->realPtr, nsize+1);
00331     }
00332     if (!p) {
00333       DBG_ERROR(GWEN_LOGDOMAIN, "Realloc failed.");
00334       if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
00335         abort();
00336       }
00337       return 1;
00338     }
00339 
00340     /* store new size and pointer */
00341     bf->realPtr=p;
00342     bf->ptr=bf->realPtr+reserved;
00343     bf->realBufferSize=nsize;
00344     bf->bufferSize+=noffs;
00345   }
00346 
00347   return 0;
00348 }
00349 
00350 
00351 
00352 int GWEN_Buffer_AppendBytes(GWEN_BUFFER *bf,
00353                             const char *buffer,
00354                             uint32_t size){
00355   assert(bf);
00356   if (GWEN_Buffer_AllocRoom(bf, size+1)) {
00357     DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
00358     return 1;
00359   }
00360   /* if (bf->pos+size>bf->bufferSize) { */
00361   if (bf->bytesUsed+size>bf->bufferSize) {
00362     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer full (%d [%d] of %d bytes)",
00363               /*bf->pos, size,*/
00364               bf->bytesUsed, size+1,
00365               bf->bufferSize);
00366     return 1;
00367   }
00368   /*memmove(bf->ptr+bf->pos, buffer, size);*/
00369   memmove(bf->ptr+bf->bytesUsed, buffer, size);
00370   /*bf->pos+=size;*/
00371   if (bf->pos==bf->bytesUsed)
00372     bf->pos+=size;
00373   bf->bytesUsed+=size;
00374   /* append a NULL to allow using the buffer as ASCIIZ string */
00375   bf->ptr[bf->bytesUsed]=0;
00376   return 0;
00377 }
00378 
00379 
00380 
00381 int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c){
00382   assert(bf);
00383 
00384   if ((bf->bytesUsed+1+1 > bf->bufferSize) &&
00385       GWEN_Buffer_AllocRoom(bf, 1+1)) { /* +1 for the trailing 0 */
00386     DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
00387     return 1;
00388   }
00389 
00390   bf->ptr[bf->bytesUsed]=c;
00391   if (bf->pos == bf->bytesUsed)
00392     bf->pos++;
00393   /* append a NULL to allow using the buffer as ASCIIZ string */
00394   bf->ptr[++(bf->bytesUsed)]=0;
00395   return 0;
00396 }
00397 
00398 
00399 
00400 int GWEN_Buffer__FillBuffer_Bio(GWEN_BUFFER *bf){
00401   if (bf->bio) {
00402     unsigned int toread;
00403     int gerr;
00404 
00405     if (GWEN_BufferedIO_CheckEOF(bf->bio)) {
00406       DBG_INFO(GWEN_LOGDOMAIN, "End of data stream reached");
00407       return GWEN_ERROR_EOF;
00408     }
00409     toread=bf->pos-bf->bytesUsed+1;
00410     if (GWEN_Buffer_AllocRoom(bf, toread+1)) {
00411       DBG_INFO(GWEN_LOGDOMAIN, "Buffer too small");
00412       return -1;
00413     }
00414     gerr=GWEN_BufferedIO_ReadRawForced(bf->bio,
00415                                        bf->ptr+bf->bytesUsed,
00416                                        &toread);
00417     if (gerr) {
00418       DBG_INFO_ERR(GWEN_LOGDOMAIN, gerr);
00419       return -1;
00420     }
00421     bf->bytesUsed+=toread;
00422   }
00423   else {
00424     DBG_DEBUG(GWEN_LOGDOMAIN,
00425               "End of used area reached and no BIO (%d bytes)",
00426               bf->pos);
00427     return GWEN_ERROR_EOF;
00428   }
00429   return 0;
00430 }
00431 
00432 
00433 
00434 int GWEN_Buffer__FillBuffer_IoLayer(GWEN_BUFFER *bf){
00435   if (bf->ioLayer) {
00436     unsigned int toread;
00437     int rv;
00438 
00439     toread=bf->pos-bf->bytesUsed+1;
00440     if (GWEN_Buffer_AllocRoom(bf, toread+1)) {
00441       DBG_INFO(GWEN_LOGDOMAIN, "Buffer too small");
00442       return -1;
00443     }
00444     /* wait up to 30 secs for available data */
00445     rv=GWEN_Io_Layer_ReadBytes(bf->ioLayer,
00446                                (uint8_t*)bf->ptr+bf->bytesUsed,
00447                                toread,
00448                                GWEN_IO_REQUEST_FLAGS_READALL,
00449                                0, 30000);
00450     if (rv<toread) {
00451       if (rv<0) {
00452         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00453         return rv;
00454       }
00455       else {
00456         DBG_INFO(GWEN_LOGDOMAIN, "EOF met");
00457         /* still some bytes available, but not all */
00458         bf->bytesUsed+=toread;
00459         return GWEN_ERROR_EOF;
00460       }
00461     }
00462     bf->bytesUsed+=toread;
00463     return 0;
00464   }
00465   else {
00466     DBG_DEBUG(GWEN_LOGDOMAIN,
00467               "End of used area reached and no BIO (%d bytes)",
00468               bf->pos);
00469     return GWEN_ERROR_EOF;
00470   }
00471 }
00472 
00473 
00474 
00475 int GWEN_Buffer__FillBuffer(GWEN_BUFFER *bf){
00476   assert(bf);
00477   if (bf->mode & GWEN_BUFFER_MODE_USE_BIO)
00478     return GWEN_Buffer__FillBuffer_Bio(bf);
00479   else if (bf->mode & GWEN_BUFFER_MODE_USE_IO)
00480     return GWEN_Buffer__FillBuffer_IoLayer(bf);
00481   else {
00482     DBG_DEBUG(GWEN_LOGDOMAIN,
00483               "End of used area reached (%d bytes)", bf->pos);
00484     return GWEN_ERROR_EOF;
00485   }
00486 }
00487 
00488 
00489 
00490 int GWEN_Buffer_PeekByte(GWEN_BUFFER *bf){
00491   assert(bf);
00492 
00493   if (bf->pos>=bf->bytesUsed) {
00494     if (GWEN_Buffer__FillBuffer(bf))
00495       return -1;
00496   }
00497 
00498   return (unsigned char) (bf->ptr[bf->pos]);
00499 }
00500 
00501 
00502 
00503 int GWEN_Buffer_ReadByte(GWEN_BUFFER *bf){
00504   assert(bf);
00505 
00506   if (bf->pos>=bf->bytesUsed) {
00507     if (GWEN_Buffer__FillBuffer(bf))
00508       return -1;
00509   }
00510 
00511   return (unsigned char) (bf->ptr[bf->pos++]);
00512 }
00513 
00514 
00515 
00516 int GWEN_Buffer_IncrementPos(GWEN_BUFFER *bf, uint32_t i){
00517   assert(bf);
00518 
00519   if (i+bf->pos>=bf->bufferSize) {
00520     if (!(bf->mode & GWEN_BUFFER_MODE_USE_BIO)) {
00521       DBG_DEBUG(GWEN_LOGDOMAIN,
00522                 "Position %d outside buffer boundaries (%d bytes)\n"
00523                 "Incrementing anyway",
00524                 i+bf->pos, bf->bufferSize);
00525     }
00526   }
00527 
00528   bf->pos+=i;
00529   return 0;
00530 }
00531 
00532 
00533 
00534 int GWEN_Buffer_AdjustUsedBytes(GWEN_BUFFER *bf){
00535   assert(bf);
00536   if (bf->pos<=bf->bufferSize) {
00537     if (bf->pos>bf->bytesUsed) {
00538       DBG_DEBUG(GWEN_LOGDOMAIN, "Adjusted buffer (uses now %d bytes)",
00539                bf->pos);
00540       bf->bytesUsed=bf->pos;
00541     }
00542     /* append a NULL to allow using the buffer as ASCIIZ string */
00543     bf->ptr[bf->bytesUsed]=0;
00544     return 0;
00545   }
00546   else {
00547     DBG_ERROR(GWEN_LOGDOMAIN, "Pointer outside buffer size (%d bytes)",
00548               bf->bufferSize);
00549     return 1;
00550   }
00551 }
00552 
00553 
00554 
00555 int GWEN_Buffer_DecrementPos(GWEN_BUFFER *bf, uint32_t i){
00556   assert(bf);
00557 
00558   if (bf->pos<i) {
00559     DBG_ERROR(GWEN_LOGDOMAIN,
00560               "Position %d outside buffer boundaries (%d bytes)",
00561               bf->pos-i, bf->bufferSize);
00562     return 1;
00563   }
00564   bf->pos-=i;
00565   return 0;
00566 }
00567 
00568 
00569 
00570 int GWEN_Buffer_AppendBuffer(GWEN_BUFFER *bf,
00571                              GWEN_BUFFER *sf){
00572   assert(bf);
00573   assert(sf);
00574   if (sf->bytesUsed)
00575     return GWEN_Buffer_AppendBytes(bf, sf->ptr, sf->bytesUsed);
00576   return 0;
00577 }
00578 
00579 
00580 
00581 uint32_t GWEN_Buffer_GetMaxUnsegmentedWrite(GWEN_BUFFER *bf){
00582   assert(bf);
00583 
00584   return (bf->bufferSize-bf->bytesUsed);
00585 }
00586 
00587 
00588 
00589 uint32_t GWEN_Buffer_GetBytesLeft(GWEN_BUFFER *bf){
00590   assert(bf);
00591 
00592   if (bf->pos<bf->bytesUsed)
00593     return bf->bytesUsed-bf->pos;
00594   else
00595     return 0;
00596 }
00597 
00598 
00599 
00600 char *GWEN_Buffer_GetPosPointer(GWEN_BUFFER *bf){
00601   assert(bf);
00602   return bf->ptr+bf->pos;
00603 }
00604 
00605 
00606 
00607 uint32_t GWEN_Buffer_GetBookmark(GWEN_BUFFER *bf, unsigned int idx){
00608   assert(bf);
00609   assert(idx<GWEN_BUFFER_MAX_BOOKMARKS);
00610   return bf->bookmarks[idx];
00611 }
00612 
00613 
00614 
00615 void GWEN_Buffer_SetBookmark(GWEN_BUFFER *bf, unsigned int idx,
00616                              uint32_t v){
00617   assert(bf);
00618   assert(idx<GWEN_BUFFER_MAX_BOOKMARKS);
00619   bf->bookmarks[idx]=v;
00620 }
00621 
00622 
00623 
00624 void GWEN_Buffer_Dump(GWEN_BUFFER *bf, FILE *f, unsigned int insert) {
00625   uint32_t k;
00626 
00627   for (k=0; k<insert; k++)
00628     fprintf(f, " ");
00629   fprintf(f, "Buffer:\n");
00630 
00631   for (k=0; k<insert; k++)
00632     fprintf(f, " ");
00633   fprintf(f, "Pos            : %d (%04x)\n", bf->pos, bf->pos);
00634 
00635   for (k=0; k<insert; k++)
00636     fprintf(f, " ");
00637   fprintf(f, "Buffer Size    : %d\n", bf->bufferSize);
00638 
00639   for (k=0; k<insert; k++)
00640     fprintf(f, " ");
00641   fprintf(f, "Hard limit     : %d\n", bf->hardLimit);
00642 
00643   for (k=0; k<insert; k++)
00644     fprintf(f, " ");
00645   fprintf(f, "Bytes Used     : %d\n", bf->bytesUsed);
00646 
00647   for (k=0; k<insert; k++)
00648     fprintf(f, " ");
00649   fprintf(f, "Bytes Reserved : %u\n",
00650           (uint32_t)(bf->ptr-bf->realPtr));
00651 
00652   for (k=0; k<insert; k++)
00653     fprintf(f, " ");
00654   fprintf(f, "Flags          : %08x ( ", bf->flags);
00655   if (bf->flags & GWEN_BUFFER_FLAGS_OWNED)
00656     fprintf(f, "OWNED ");
00657   fprintf(f, ")\n");
00658 
00659   for (k=0; k<insert; k++)
00660     fprintf(f, " ");
00661   fprintf(f, "Mode           : %08x ( ", bf->mode);
00662   if (bf->mode & GWEN_BUFFER_MODE_DYNAMIC)
00663     fprintf(f, "DYNAMIC ");
00664   if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL)
00665     fprintf(f, "ABORT_ON_MEMFULL ");
00666   fprintf(f, ")\n");
00667 
00668   for (k=0; k<insert; k++)
00669     fprintf(f, " ");
00670   fprintf(f, "Bookmarks      :");
00671   for (k=0; k<GWEN_BUFFER_MAX_BOOKMARKS; k++)
00672     fprintf(f, " %d", bf->bookmarks[k]);
00673   fprintf(f, "\n");
00674 
00675   if (bf->ptr && bf->bytesUsed) {
00676     for (k=0; k<insert; k++)
00677       fprintf(f, " ");
00678     fprintf(f, "Data:\n");
00679     GWEN_Text_DumpString(bf->ptr, bf->bytesUsed, f, insert+1);
00680   }
00681 }
00682 
00683 
00684 
00685 void GWEN_Buffer_Reset(GWEN_BUFFER *bf){
00686   assert(bf);
00687   bf->pos=0;
00688   bf->bytesUsed=0;
00689   bf->ptr[0]=0;
00690 }
00691 
00692 
00693 
00694 void GWEN_Buffer_Rewind(GWEN_BUFFER *bf){
00695   assert(bf);
00696   bf->pos=0;
00697 }
00698 
00699 
00700 
00701 int GWEN_Buffer_ReadBytes(GWEN_BUFFER *bf,
00702                           char *buffer,
00703                           uint32_t *size){
00704 #if 0
00705   /* old behaviour */
00706   uint32_t i;
00707   int c;
00708 
00709   i=0;
00710 
00711   while(i<*size) {
00712     c=GWEN_Buffer_ReadByte(bf);
00713     if (c==-1)
00714       break;
00715     buffer[i]=c;
00716     i++;
00717   } /* while */
00718 
00719   *size=i;
00720   return 0;
00721 
00722 #else
00723   /* optimized for speed */
00724   uint32_t i;
00725   char *pdst;
00726 
00727   DBG_VERBOUS(GWEN_LOGDOMAIN, "About to copy up to %d bytes", *size);
00728   i=0;
00729   pdst=buffer;
00730 
00731   while(i<*size) {
00732     int j;
00733     int srcLeft;
00734 
00735     if (bf->pos>=bf->bytesUsed) {
00736       if (GWEN_Buffer__FillBuffer(bf)) {
00737         DBG_DEBUG(GWEN_LOGDOMAIN, "Could not fill buffer, but that's ok");
00738         break;
00739       }
00740     }
00741 
00742     srcLeft=bf->bytesUsed - bf->pos;
00743     if (srcLeft==0)
00744       break;
00745     j=(*size)-i;
00746     if (j>srcLeft)
00747       j=srcLeft;
00748     DBG_VERBOUS(GWEN_LOGDOMAIN, "Copying %d bytes", j);
00749     memmove(pdst, bf->ptr + bf->pos, j);
00750     pdst+=j;
00751     i+=j;
00752     bf->pos+=j;
00753   } /* while */
00754 
00755   *size=i;
00756   DBG_VERBOUS(GWEN_LOGDOMAIN, "Copied %d bytes", *size);
00757   return 0;
00758 #endif
00759 }
00760 
00761 
00762 
00763 uint32_t GWEN_Buffer_GetStep(GWEN_BUFFER *bf){
00764   assert(bf);
00765   return bf->step;
00766 }
00767 
00768 
00769 
00770 void GWEN_Buffer_SetStep(GWEN_BUFFER *bf, uint32_t step){
00771   assert(bf);
00772   bf->step=step;
00773 }
00774 
00775 
00776 
00777 void GWEN_Buffer_AdjustBookmarks(GWEN_BUFFER *bf,
00778                                  uint32_t pos,
00779                                  int offset) {
00780   uint32_t i;
00781 
00782   assert(bf);
00783   for (i=0; i<GWEN_BUFFER_MAX_BOOKMARKS; i++) {
00784     if (bf->bookmarks[i]>=pos)
00785       bf->bookmarks[i]+=offset;
00786   } /* for */
00787 }
00788 
00789 
00790 
00791 int GWEN_Buffer_InsertRoom(GWEN_BUFFER *bf,
00792                            uint32_t size){
00793   char *p;
00794   int i;
00795 
00796   assert(bf);
00797 
00798   if (bf->pos==0) {
00799     if (bf->bytesUsed==0) {
00800       int rv;
00801 
00802       /* no bytes used, simply return */
00803       rv=GWEN_Buffer_AllocRoom(bf, size);
00804       if (rv) {
00805         DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
00806         return rv;
00807       }
00808       bf->bytesUsed+=size;
00809       /* append "0" behind buffer */
00810       bf->ptr[bf->bytesUsed]=0;
00811       return 0;
00812     }
00813     else {
00814       if ( (bf->ptr - bf->realPtr) >= (int)size ) {
00815         /* simply occupy the reserved space */
00816         bf->ptr-=size;
00817         bf->bytesUsed+=size;
00818         bf->bufferSize+=size;
00819         GWEN_Buffer_AdjustBookmarks(bf, bf->pos, size);
00820         return 0;
00821       }
00822     }
00823   }
00824 
00825   if (GWEN_Buffer_AllocRoom(bf, size)) {
00826     DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
00827     return 1;
00828   }
00829   if (bf->pos+size>bf->bufferSize) {
00830     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer full (%d [%d] of %d bytes)",
00831               bf->pos, size,
00832               bf->bufferSize);
00833     return -1;
00834   }
00835   p=bf->ptr+bf->pos;
00836   i=bf->bytesUsed-bf->pos;
00837   if (i>0)
00838     /* move current data at pos out of the way */
00839     memmove(p+size, p, i);
00840   bf->bytesUsed+=size;
00841   /* append "0" behind buffer */
00842   bf->ptr[bf->bytesUsed]=0;
00843   GWEN_Buffer_AdjustBookmarks(bf, bf->pos, size);
00844   return 0;
00845 }
00846 
00847 
00848 
00849 int GWEN_Buffer_RemoveRoom(GWEN_BUFFER *bf, uint32_t size){
00850   char *p;
00851   int i;
00852 
00853   assert(bf);
00854 
00855   if (bf->pos==0) {
00856     if (bf->bytesUsed<size) {
00857       /* can't remove bytes we don't have */
00858       return GWEN_ERROR_INVALID;
00859     }
00860     /* simply add to reserved space */
00861     bf->ptr+=size;
00862     bf->bytesUsed-=size;
00863     bf->bufferSize-=size;
00864   }
00865   else {
00866     if (bf->bytesUsed+size<(bf->bytesUsed)) {
00867       /* can't remove more bytes than we have */
00868       return GWEN_ERROR_INVALID;
00869     }
00870 
00871     /* we need to get the rest closer */
00872     p=bf->ptr+bf->pos+size;
00873     i=bf->bytesUsed-bf->pos-size;
00874     memmove(bf->ptr+bf->pos, p, i);
00875     bf->bytesUsed+=size;
00876   }
00877 
00878   /* append "0" behind buffer */
00879   bf->ptr[bf->bytesUsed]=0;
00880   GWEN_Buffer_AdjustBookmarks(bf, bf->pos, -((int)size));
00881 
00882   return 0;
00883 }
00884 
00885 
00886 
00887 int GWEN_Buffer_ReplaceBytes(GWEN_BUFFER *bf,
00888                              uint32_t rsize,
00889                              const char *buffer,
00890                              uint32_t size){
00891   int32_t d;
00892   int rv;
00893 
00894   /* either insert or remove bytes */
00895   d=size-rsize;
00896   if (d<0) {
00897     rv=GWEN_Buffer_RemoveRoom(bf, -d);
00898   }
00899   else if (d>0) {
00900     rv=GWEN_Buffer_InsertRoom(bf, d);
00901   }
00902   else
00903     /* nothing to adjust if sizes are the same */
00904     rv=0;
00905   if (rv) {
00906     DBG_ERROR(GWEN_LOGDOMAIN,
00907               "Error replacing %d bytes with %d bytes (%d)",
00908               rsize, size, rv);
00909     return rv;
00910   }
00911 
00912   /* write new bytes */
00913   if (size)
00914     memmove(bf->ptr+bf->pos, buffer, size);
00915   return 0;
00916 }
00917 
00918 
00919 
00920 int GWEN_Buffer_InsertBytes(GWEN_BUFFER *bf,
00921                             const char *buffer,
00922                             uint32_t size){
00923   assert(bf);
00924   assert(buffer);
00925 
00926   if (GWEN_Buffer_InsertRoom(bf, size)) {
00927     return -1;
00928   }
00929   memmove(bf->ptr+bf->pos, buffer, size);
00930   return 0;
00931 }
00932 
00933 
00934 
00935 int GWEN_Buffer_InsertByte(GWEN_BUFFER *bf, char c){
00936   assert(bf);
00937 
00938   if (GWEN_Buffer_InsertRoom(bf, 1)) {
00939     return -1;
00940   }
00941   bf->ptr[bf->pos]=c;
00942   return 0;
00943 }
00944 
00945 
00946 
00947 int GWEN_Buffer_InsertBuffer(GWEN_BUFFER *bf,
00948                              GWEN_BUFFER *sf){
00949   assert(bf);
00950   assert(sf);
00951 
00952   return GWEN_Buffer_InsertBytes(bf, sf->ptr, sf->bytesUsed);
00953 }
00954 
00955 
00956 
00957 int GWEN_Buffer_Crop(GWEN_BUFFER *bf,
00958                      uint32_t pos,
00959                      uint32_t l) {
00960   if (pos>=bf->bufferSize) {
00961     DBG_ERROR(GWEN_LOGDOMAIN, "Position outside buffer");
00962     return -1;
00963   }
00964   bf->ptr+=pos;
00965   bf->bufferSize-=pos;
00966   bf->pos-=pos;
00967   if (bf->bytesUsed-pos<l) {
00968     DBG_INFO(GWEN_LOGDOMAIN, "Invalid length");
00969     return -1;
00970   }
00971   bf->bytesUsed=l;
00972   GWEN_Buffer_AdjustBookmarks(bf, pos, -pos);
00973   /* adjust position after possible truncation */
00974   if (bf->pos>bf->bytesUsed)
00975       bf->pos=bf->bytesUsed;
00976 
00977   bf->ptr[bf->bytesUsed]=0;
00978 
00979   return 0;
00980 }
00981 
00982 
00983 
00984 int GWEN_Buffer_AppendString(GWEN_BUFFER *bf,
00985                              const char *buffer){
00986   assert(bf);
00987   assert(buffer);
00988   return GWEN_Buffer_AppendBytes(bf, buffer, strlen(buffer));
00989 }
00990 
00991 
00992 
00993 int GWEN_Buffer_InsertString(GWEN_BUFFER *bf,
00994                              const char *buffer){
00995   assert(bf);
00996   assert(buffer);
00997   return GWEN_Buffer_InsertBytes(bf, buffer, strlen(buffer));
00998 }
00999 
01000 
01001 
01002 void GWEN_Buffer_SetSourceBIO(GWEN_BUFFER *bf,
01003                               GWEN_BUFFEREDIO *bio,
01004                               int take){
01005   assert(bf);
01006   if (bf->bio) {
01007     if (bf->flags & GWEN_BUFFER_FLAGS_OWN_BIO) {
01008       GWEN_BufferedIO_free(bf->bio);
01009     }
01010   }
01011   if (take)
01012     bf->flags|=GWEN_BUFFER_FLAGS_OWN_BIO;
01013   else
01014     bf->flags&=~GWEN_BUFFER_FLAGS_OWN_BIO;
01015   bf->bio=bio;
01016 }
01017 
01018 
01019 
01020 void GWEN_Buffer_SetSourceIoLayer(GWEN_BUFFER *bf,
01021                                   GWEN_IO_LAYER *io,
01022                                   int take) {
01023   assert(bf);
01024   if (bf->ioLayer) {
01025     if (bf->flags & GWEN_BUFFER_FLAGS_OWN_IO) {
01026       GWEN_Io_Layer_free(bf->ioLayer);
01027     }
01028   }
01029   if (take)
01030     bf->flags|=GWEN_BUFFER_FLAGS_OWN_IO;
01031   else
01032     bf->flags&=~GWEN_BUFFER_FLAGS_OWN_IO;
01033   bf->ioLayer=io;
01034 }
01035 
01036 
01037 
01038 int GWEN_Buffer_FillWithBytes(GWEN_BUFFER *bf,
01039                               unsigned char c,
01040                               uint32_t size){
01041   assert(bf);
01042   if (GWEN_Buffer_AllocRoom(bf, size+1)) {
01043     DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
01044     return 1;
01045   }
01046   /* if (bf->pos+size>bf->bufferSize) { */
01047   if (bf->bytesUsed+size>bf->bufferSize) {
01048     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer full (%d [%d] of %d bytes)",
01049               bf->bytesUsed, size+1,
01050               bf->bufferSize);
01051     return 1;
01052   }
01053   memset(bf->ptr+bf->bytesUsed, c, size);
01054   if (bf->pos==bf->bytesUsed)
01055     bf->pos+=size;
01056   bf->bytesUsed+=size;
01057   /* append a NULL to allow using the buffer as ASCIIZ string */
01058   bf->ptr[bf->bytesUsed]=0;
01059   return 0;
01060 }
01061 
01062 
01063 
01064 int GWEN_Buffer_FillLeftWithBytes(GWEN_BUFFER *bf,
01065                                   unsigned char c,
01066                                   uint32_t size){
01067   assert(bf);
01068 
01069   if (GWEN_Buffer_InsertRoom(bf, size)) {
01070     return -1;
01071   }
01072   memset(bf->ptr+bf->pos, c, size);
01073   return 0;
01074 }
01075 
01076 
01077 
01078 
01079 
01080 
01081 

Generated on Wed Jul 9 13:12:27 2008 for gwenhywfar by  doxygen 1.5.6