buffer.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003                              -------------------
00004     cvs         : $Id: buffer.c 1403 2008-01-22 11:25:17Z martin $
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     p=GWEN_Memory_realloc(bf->realPtr, nsize+1);
00327     if (!p) {
00328       DBG_ERROR(GWEN_LOGDOMAIN, "Realloc failed.");
00329       if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
00330         abort();
00331       }
00332       return 1;
00333     }
00334     /* store new size and pointer */
00335     bf->realPtr=p;
00336     bf->ptr=bf->realPtr+reserved;
00337     bf->realBufferSize=nsize;
00338     bf->bufferSize+=noffs;
00339   }
00340 
00341   return 0;
00342 }
00343 
00344 
00345 
00346 int GWEN_Buffer_AppendBytes(GWEN_BUFFER *bf,
00347                             const char *buffer,
00348                             uint32_t size){
00349   assert(bf);
00350   if (GWEN_Buffer_AllocRoom(bf, size+1)) {
00351     DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
00352     return 1;
00353   }
00354   /* if (bf->pos+size>bf->bufferSize) { */
00355   if (bf->bytesUsed+size>bf->bufferSize) {
00356     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer full (%d [%d] of %d bytes)",
00357               /*bf->pos, size,*/
00358               bf->bytesUsed, size+1,
00359               bf->bufferSize);
00360     return 1;
00361   }
00362   /*memmove(bf->ptr+bf->pos, buffer, size);*/
00363   memmove(bf->ptr+bf->bytesUsed, buffer, size);
00364   /*bf->pos+=size;*/
00365   if (bf->pos==bf->bytesUsed)
00366     bf->pos+=size;
00367   bf->bytesUsed+=size;
00368   /* append a NULL to allow using the buffer as ASCIIZ string */
00369   bf->ptr[bf->bytesUsed]=0;
00370   return 0;
00371 }
00372 
00373 
00374 
00375 int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c){
00376   assert(bf);
00377 
00378   if ((bf->bytesUsed+1+1 > bf->bufferSize) &&
00379       GWEN_Buffer_AllocRoom(bf, 1+1)) { /* +1 for the trailing 0 */
00380     DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
00381     return 1;
00382   }
00383 
00384   bf->ptr[bf->bytesUsed]=c;
00385   if (bf->pos == bf->bytesUsed)
00386     bf->pos++;
00387   /* append a NULL to allow using the buffer as ASCIIZ string */
00388   bf->ptr[++(bf->bytesUsed)]=0;
00389   return 0;
00390 }
00391 
00392 
00393 
00394 int GWEN_Buffer__FillBuffer_Bio(GWEN_BUFFER *bf){
00395   if (bf->bio) {
00396     unsigned int toread;
00397     int gerr;
00398 
00399     if (GWEN_BufferedIO_CheckEOF(bf->bio)) {
00400       DBG_INFO(GWEN_LOGDOMAIN, "End of data stream reached");
00401       return GWEN_ERROR_EOF;
00402     }
00403     toread=bf->pos-bf->bytesUsed+1;
00404     if (GWEN_Buffer_AllocRoom(bf, toread+1)) {
00405       DBG_INFO(GWEN_LOGDOMAIN, "Buffer too small");
00406       return -1;
00407     }
00408     gerr=GWEN_BufferedIO_ReadRawForced(bf->bio,
00409                                        bf->ptr+bf->bytesUsed,
00410                                        &toread);
00411     if (gerr) {
00412       DBG_INFO_ERR(GWEN_LOGDOMAIN, gerr);
00413       return -1;
00414     }
00415     bf->bytesUsed+=toread;
00416   }
00417   else {
00418     DBG_DEBUG(GWEN_LOGDOMAIN,
00419               "End of used area reached and no BIO (%d bytes)",
00420               bf->pos);
00421     return GWEN_ERROR_EOF;
00422   }
00423   return 0;
00424 }
00425 
00426 
00427 
00428 int GWEN_Buffer__FillBuffer_IoLayer(GWEN_BUFFER *bf){
00429   if (bf->ioLayer) {
00430     unsigned int toread;
00431     int rv;
00432 
00433     toread=bf->pos-bf->bytesUsed+1;
00434     if (GWEN_Buffer_AllocRoom(bf, toread+1)) {
00435       DBG_INFO(GWEN_LOGDOMAIN, "Buffer too small");
00436       return -1;
00437     }
00438     /* wait up to 30 secs for available data */
00439     rv=GWEN_Io_Layer_ReadBytes(bf->ioLayer,
00440                                (uint8_t*)bf->ptr+bf->bytesUsed,
00441                                toread,
00442                                GWEN_IO_REQUEST_FLAGS_READALL,
00443                                0, 30000);
00444     if (rv<toread) {
00445       if (rv<0) {
00446         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00447         return rv;
00448       }
00449       else {
00450         DBG_INFO(GWEN_LOGDOMAIN, "EOF met");
00451         /* still some bytes available, but not all */
00452         bf->bytesUsed+=toread;
00453         return GWEN_ERROR_EOF;
00454       }
00455     }
00456     bf->bytesUsed+=toread;
00457     return 0;
00458   }
00459   else {
00460     DBG_DEBUG(GWEN_LOGDOMAIN,
00461               "End of used area reached and no BIO (%d bytes)",
00462               bf->pos);
00463     return GWEN_ERROR_EOF;
00464   }
00465 }
00466 
00467 
00468 
00469 int GWEN_Buffer__FillBuffer(GWEN_BUFFER *bf){
00470   assert(bf);
00471   if (bf->mode & GWEN_BUFFER_MODE_USE_BIO)
00472     return GWEN_Buffer__FillBuffer_Bio(bf);
00473   else if (bf->mode & GWEN_BUFFER_MODE_USE_IO)
00474     return GWEN_Buffer__FillBuffer_IoLayer(bf);
00475   else {
00476     DBG_DEBUG(GWEN_LOGDOMAIN,
00477               "End of used area reached (%d bytes)", bf->pos);
00478     return GWEN_ERROR_EOF;
00479   }
00480 }
00481 
00482 
00483 
00484 int GWEN_Buffer_PeekByte(GWEN_BUFFER *bf){
00485   assert(bf);
00486 
00487   if (bf->pos>=bf->bytesUsed) {
00488     if (GWEN_Buffer__FillBuffer(bf))
00489       return -1;
00490   }
00491 
00492   return (unsigned char) (bf->ptr[bf->pos]);
00493 }
00494 
00495 
00496 
00497 int GWEN_Buffer_ReadByte(GWEN_BUFFER *bf){
00498   assert(bf);
00499 
00500   if (bf->pos>=bf->bytesUsed) {
00501     if (GWEN_Buffer__FillBuffer(bf))
00502       return -1;
00503   }
00504 
00505   return (unsigned char) (bf->ptr[bf->pos++]);
00506 }
00507 
00508 
00509 
00510 int GWEN_Buffer_IncrementPos(GWEN_BUFFER *bf, uint32_t i){
00511   assert(bf);
00512 
00513   if (i+bf->pos>=bf->bufferSize) {
00514     if (!(bf->mode & GWEN_BUFFER_MODE_USE_BIO)) {
00515       DBG_DEBUG(GWEN_LOGDOMAIN,
00516                 "Position %d outside buffer boundaries (%d bytes)\n"
00517                 "Incrementing anyway",
00518                 i+bf->pos, bf->bufferSize);
00519     }
00520   }
00521 
00522   bf->pos+=i;
00523   return 0;
00524 }
00525 
00526 
00527 
00528 int GWEN_Buffer_AdjustUsedBytes(GWEN_BUFFER *bf){
00529   assert(bf);
00530   if (bf->pos<=bf->bufferSize) {
00531     if (bf->pos>bf->bytesUsed) {
00532       DBG_DEBUG(GWEN_LOGDOMAIN, "Adjusted buffer (uses now %d bytes)",
00533                bf->pos);
00534       bf->bytesUsed=bf->pos;
00535     }
00536     /* append a NULL to allow using the buffer as ASCIIZ string */
00537     bf->ptr[bf->bytesUsed]=0;
00538     return 0;
00539   }
00540   else {
00541     DBG_ERROR(GWEN_LOGDOMAIN, "Pointer outside buffer size (%d bytes)",
00542               bf->bufferSize);
00543     return 1;
00544   }
00545 }
00546 
00547 
00548 
00549 int GWEN_Buffer_DecrementPos(GWEN_BUFFER *bf, uint32_t i){
00550   assert(bf);
00551 
00552   if (bf->pos<i) {
00553     DBG_ERROR(GWEN_LOGDOMAIN,
00554               "Position %d outside buffer boundaries (%d bytes)",
00555               bf->pos-i, bf->bufferSize);
00556     return 1;
00557   }
00558   bf->pos-=i;
00559   return 0;
00560 }
00561 
00562 
00563 
00564 int GWEN_Buffer_AppendBuffer(GWEN_BUFFER *bf,
00565                              GWEN_BUFFER *sf){
00566   assert(bf);
00567   assert(sf);
00568   if (sf->bytesUsed)
00569     return GWEN_Buffer_AppendBytes(bf, sf->ptr, sf->bytesUsed);
00570   return 0;
00571 }
00572 
00573 
00574 
00575 uint32_t GWEN_Buffer_GetMaxUnsegmentedWrite(GWEN_BUFFER *bf){
00576   assert(bf);
00577 
00578   return (bf->bufferSize-bf->bytesUsed);
00579 }
00580 
00581 
00582 
00583 uint32_t GWEN_Buffer_GetBytesLeft(GWEN_BUFFER *bf){
00584   assert(bf);
00585 
00586   if (bf->pos<bf->bytesUsed)
00587     return bf->bytesUsed-bf->pos;
00588   else
00589     return 0;
00590 }
00591 
00592 
00593 
00594 char *GWEN_Buffer_GetPosPointer(GWEN_BUFFER *bf){
00595   assert(bf);
00596   return bf->ptr+bf->pos;
00597 }
00598 
00599 
00600 
00601 uint32_t GWEN_Buffer_GetBookmark(GWEN_BUFFER *bf, unsigned int idx){
00602   assert(bf);
00603   assert(idx<GWEN_BUFFER_MAX_BOOKMARKS);
00604   return bf->bookmarks[idx];
00605 }
00606 
00607 
00608 
00609 void GWEN_Buffer_SetBookmark(GWEN_BUFFER *bf, unsigned int idx,
00610                              uint32_t v){
00611   assert(bf);
00612   assert(idx<GWEN_BUFFER_MAX_BOOKMARKS);
00613   bf->bookmarks[idx]=v;
00614 }
00615 
00616 
00617 
00618 void GWEN_Buffer_Dump(GWEN_BUFFER *bf, FILE *f, unsigned int insert) {
00619   uint32_t k;
00620 
00621   for (k=0; k<insert; k++)
00622     fprintf(f, " ");
00623   fprintf(f, "Buffer:\n");
00624 
00625   for (k=0; k<insert; k++)
00626     fprintf(f, " ");
00627   fprintf(f, "Pos            : %d (%04x)\n", bf->pos, bf->pos);
00628 
00629   for (k=0; k<insert; k++)
00630     fprintf(f, " ");
00631   fprintf(f, "Buffer Size    : %d\n", bf->bufferSize);
00632 
00633   for (k=0; k<insert; k++)
00634     fprintf(f, " ");
00635   fprintf(f, "Hard limit     : %d\n", bf->hardLimit);
00636 
00637   for (k=0; k<insert; k++)
00638     fprintf(f, " ");
00639   fprintf(f, "Bytes Used     : %d\n", bf->bytesUsed);
00640 
00641   for (k=0; k<insert; k++)
00642     fprintf(f, " ");
00643   fprintf(f, "Bytes Reserved : %u\n",
00644           (uint32_t)(bf->ptr-bf->realPtr));
00645 
00646   for (k=0; k<insert; k++)
00647     fprintf(f, " ");
00648   fprintf(f, "Flags          : %08x ( ", bf->flags);
00649   if (bf->flags & GWEN_BUFFER_FLAGS_OWNED)
00650     fprintf(f, "OWNED ");
00651   fprintf(f, ")\n");
00652 
00653   for (k=0; k<insert; k++)
00654     fprintf(f, " ");
00655   fprintf(f, "Mode           : %08x ( ", bf->mode);
00656   if (bf->mode & GWEN_BUFFER_MODE_DYNAMIC)
00657     fprintf(f, "DYNAMIC ");
00658   if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL)
00659     fprintf(f, "ABORT_ON_MEMFULL ");
00660   fprintf(f, ")\n");
00661 
00662   for (k=0; k<insert; k++)
00663     fprintf(f, " ");
00664   fprintf(f, "Bookmarks      :");
00665   for (k=0; k<GWEN_BUFFER_MAX_BOOKMARKS; k++)
00666     fprintf(f, " %d", bf->bookmarks[k]);
00667   fprintf(f, "\n");
00668 
00669   if (bf->ptr && bf->bytesUsed) {
00670     for (k=0; k<insert; k++)
00671       fprintf(f, " ");
00672     fprintf(f, "Data:\n");
00673     GWEN_Text_DumpString(bf->ptr, bf->bytesUsed, f, insert+1);
00674   }
00675 }
00676 
00677 
00678 
00679 void GWEN_Buffer_Reset(GWEN_BUFFER *bf){
00680   assert(bf);
00681   bf->pos=0;
00682   bf->bytesUsed=0;
00683   bf->ptr[0]=0;
00684 }
00685 
00686 
00687 
00688 void GWEN_Buffer_Rewind(GWEN_BUFFER *bf){
00689   assert(bf);
00690   bf->pos=0;
00691 }
00692 
00693 
00694 
00695 int GWEN_Buffer_ReadBytes(GWEN_BUFFER *bf,
00696                           char *buffer,
00697                           uint32_t *size){
00698 #if 0
00699   /* old behaviour */
00700   uint32_t i;
00701   int c;
00702 
00703   i=0;
00704 
00705   while(i<*size) {
00706     c=GWEN_Buffer_ReadByte(bf);
00707     if (c==-1)
00708       break;
00709     buffer[i]=c;
00710     i++;
00711   } /* while */
00712 
00713   *size=i;
00714   return 0;
00715 
00716 #else
00717   /* optimized for speed */
00718   uint32_t i;
00719   char *pdst;
00720 
00721   DBG_VERBOUS(GWEN_LOGDOMAIN, "About to copy up to %d bytes", *size);
00722   i=0;
00723   pdst=buffer;
00724 
00725   while(i<*size) {
00726     int j;
00727     int srcLeft;
00728 
00729     if (bf->pos>=bf->bytesUsed) {
00730       if (GWEN_Buffer__FillBuffer(bf)) {
00731         DBG_DEBUG(GWEN_LOGDOMAIN, "Could not fill buffer, but that's ok");
00732         break;
00733       }
00734     }
00735 
00736     srcLeft=bf->bytesUsed - bf->pos;
00737     if (srcLeft==0)
00738       break;
00739     j=(*size)-i;
00740     if (j>srcLeft)
00741       j=srcLeft;
00742     DBG_VERBOUS(GWEN_LOGDOMAIN, "Copying %d bytes", j);
00743     memmove(pdst, bf->ptr + bf->pos, j);
00744     pdst+=j;
00745     i+=j;
00746     bf->pos+=j;
00747   } /* while */
00748 
00749   *size=i;
00750   DBG_VERBOUS(GWEN_LOGDOMAIN, "Copied %d bytes", *size);
00751   return 0;
00752 #endif
00753 }
00754 
00755 
00756 
00757 uint32_t GWEN_Buffer_GetStep(GWEN_BUFFER *bf){
00758   assert(bf);
00759   return bf->step;
00760 }
00761 
00762 
00763 
00764 void GWEN_Buffer_SetStep(GWEN_BUFFER *bf, uint32_t step){
00765   assert(bf);
00766   bf->step=step;
00767 }
00768 
00769 
00770 
00771 void GWEN_Buffer_AdjustBookmarks(GWEN_BUFFER *bf,
00772                                  uint32_t pos,
00773                                  int offset) {
00774   uint32_t i;
00775 
00776   assert(bf);
00777   for (i=0; i<GWEN_BUFFER_MAX_BOOKMARKS; i++) {
00778     if (bf->bookmarks[i]>=pos)
00779       bf->bookmarks[i]+=offset;
00780   } /* for */
00781 }
00782 
00783 
00784 
00785 int GWEN_Buffer_InsertRoom(GWEN_BUFFER *bf,
00786                            uint32_t size){
00787   char *p;
00788   int i;
00789 
00790   assert(bf);
00791 
00792   if (bf->pos==0) {
00793     if (bf->bytesUsed==0) {
00794       int rv;
00795 
00796       /* no bytes used, simply return */
00797       rv=GWEN_Buffer_AllocRoom(bf, size);
00798       if (rv) {
00799         DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
00800         return rv;
00801       }
00802       bf->bytesUsed+=size;
00803       /* append "0" behind buffer */
00804       bf->ptr[bf->bytesUsed]=0;
00805       return 0;
00806     }
00807     else {
00808       if ( (bf->ptr - bf->realPtr) >= (int)size ) {
00809         /* simply occupy the reserved space */
00810         bf->ptr-=size;
00811         bf->bytesUsed+=size;
00812         bf->bufferSize+=size;
00813         GWEN_Buffer_AdjustBookmarks(bf, bf->pos, size);
00814         return 0;
00815       }
00816     }
00817   }
00818 
00819   if (GWEN_Buffer_AllocRoom(bf, size)) {
00820     DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
00821     return 1;
00822   }
00823   if (bf->pos+size>bf->bufferSize) {
00824     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer full (%d [%d] of %d bytes)",
00825               bf->pos, size,
00826               bf->bufferSize);
00827     return -1;
00828   }
00829   p=bf->ptr+bf->pos;
00830   i=bf->bytesUsed-bf->pos;
00831   if (i>0)
00832     /* move current data at pos out of the way */
00833     memmove(p+size, p, i);
00834   bf->bytesUsed+=size;
00835   /* append "0" behind buffer */
00836   bf->ptr[bf->bytesUsed]=0;
00837   GWEN_Buffer_AdjustBookmarks(bf, bf->pos, size);
00838   return 0;
00839 }
00840 
00841 
00842 
00843 int GWEN_Buffer_RemoveRoom(GWEN_BUFFER *bf, uint32_t size){
00844   char *p;
00845   int i;
00846 
00847   assert(bf);
00848 
00849   if (bf->pos==0) {
00850     if (bf->bytesUsed<size) {
00851       /* can't remove bytes we don't have */
00852       return GWEN_ERROR_INVALID;
00853     }
00854     /* simply add to reserved space */
00855     bf->ptr+=size;
00856     bf->bytesUsed-=size;
00857     bf->bufferSize-=size;
00858   }
00859   else {
00860     if (bf->bytesUsed+size<(bf->bytesUsed)) {
00861       /* can't remove more bytes than we have */
00862       return GWEN_ERROR_INVALID;
00863     }
00864 
00865     /* we need to get the rest closer */
00866     p=bf->ptr+bf->pos+size;
00867     i=bf->bytesUsed-bf->pos-size;
00868     memmove(bf->ptr+bf->pos, p, i);
00869     bf->bytesUsed+=size;
00870   }
00871 
00872   /* append "0" behind buffer */
00873   bf->ptr[bf->bytesUsed]=0;
00874   GWEN_Buffer_AdjustBookmarks(bf, bf->pos, -((int)size));
00875 
00876   return 0;
00877 }
00878 
00879 
00880 
00881 int GWEN_Buffer_ReplaceBytes(GWEN_BUFFER *bf,
00882                              uint32_t rsize,
00883                              const char *buffer,
00884                              uint32_t size){
00885   int32_t d;
00886   int rv;
00887 
00888   /* either insert or remove bytes */
00889   d=size-rsize;
00890   if (d<0) {
00891     rv=GWEN_Buffer_RemoveRoom(bf, -d);
00892   }
00893   else if (d>0) {
00894     rv=GWEN_Buffer_InsertRoom(bf, d);
00895   }
00896   else
00897     /* nothing to adjust if sizes are the same */
00898     rv=0;
00899   if (rv) {
00900     DBG_ERROR(GWEN_LOGDOMAIN,
00901               "Error replacing %d bytes with %d bytes (%d)",
00902               rsize, size, rv);
00903     return rv;
00904   }
00905 
00906   /* write new bytes */
00907   if (size)
00908     memmove(bf->ptr+bf->pos, buffer, size);
00909   return 0;
00910 }
00911 
00912 
00913 
00914 int GWEN_Buffer_InsertBytes(GWEN_BUFFER *bf,
00915                             const char *buffer,
00916                             uint32_t size){
00917   assert(bf);
00918   assert(buffer);
00919 
00920   if (GWEN_Buffer_InsertRoom(bf, size)) {
00921     return -1;
00922   }
00923   memmove(bf->ptr+bf->pos, buffer, size);
00924   return 0;
00925 }
00926 
00927 
00928 
00929 int GWEN_Buffer_InsertByte(GWEN_BUFFER *bf, char c){
00930   assert(bf);
00931 
00932   if (GWEN_Buffer_InsertRoom(bf, 1)) {
00933     return -1;
00934   }
00935   bf->ptr[bf->pos]=c;
00936   return 0;
00937 }
00938 
00939 
00940 
00941 int GWEN_Buffer_InsertBuffer(GWEN_BUFFER *bf,
00942                              GWEN_BUFFER *sf){
00943   assert(bf);
00944   assert(sf);
00945 
00946   return GWEN_Buffer_InsertBytes(bf, sf->ptr, sf->bytesUsed);
00947 }
00948 
00949 
00950 
00951 int GWEN_Buffer_Crop(GWEN_BUFFER *bf,
00952                      uint32_t pos,
00953                      uint32_t l) {
00954   if (pos>=bf->bufferSize) {
00955     DBG_ERROR(GWEN_LOGDOMAIN, "Position outside buffer");
00956     return -1;
00957   }
00958   bf->ptr+=pos;
00959   bf->bufferSize-=pos;
00960   bf->pos-=pos;
00961   if (bf->bytesUsed-pos<l) {
00962     DBG_INFO(GWEN_LOGDOMAIN, "Invalid length");
00963     return -1;
00964   }
00965   bf->bytesUsed=l;
00966   GWEN_Buffer_AdjustBookmarks(bf, pos, -pos);
00967   /* adjust position after possible truncation */
00968   if (bf->pos>bf->bytesUsed)
00969       bf->pos=bf->bytesUsed;
00970 
00971   bf->ptr[bf->bytesUsed]=0;
00972 
00973   return 0;
00974 }
00975 
00976 
00977 
00978 int GWEN_Buffer_AppendString(GWEN_BUFFER *bf,
00979                              const char *buffer){
00980   assert(bf);
00981   assert(buffer);
00982   return GWEN_Buffer_AppendBytes(bf, buffer, strlen(buffer));
00983 }
00984 
00985 
00986 
00987 int GWEN_Buffer_InsertString(GWEN_BUFFER *bf,
00988                              const char *buffer){
00989   assert(bf);
00990   assert(buffer);
00991   return GWEN_Buffer_InsertBytes(bf, buffer, strlen(buffer));
00992 }
00993 
00994 
00995 
00996 void GWEN_Buffer_SetSourceBIO(GWEN_BUFFER *bf,
00997                               GWEN_BUFFEREDIO *bio,
00998                               int take){
00999   assert(bf);
01000   if (bf->bio) {
01001     if (bf->flags & GWEN_BUFFER_FLAGS_OWN_BIO) {
01002       GWEN_BufferedIO_free(bf->bio);
01003     }
01004   }
01005   if (take)
01006     bf->flags|=GWEN_BUFFER_FLAGS_OWN_BIO;
01007   else
01008     bf->flags&=~GWEN_BUFFER_FLAGS_OWN_BIO;
01009   bf->bio=bio;
01010 }
01011 
01012 
01013 
01014 void GWEN_Buffer_SetSourceIoLayer(GWEN_BUFFER *bf,
01015                                   GWEN_IO_LAYER *io,
01016                                   int take) {
01017   assert(bf);
01018   if (bf->ioLayer) {
01019     if (bf->flags & GWEN_BUFFER_FLAGS_OWN_IO) {
01020       GWEN_Io_Layer_free(bf->ioLayer);
01021     }
01022   }
01023   if (take)
01024     bf->flags|=GWEN_BUFFER_FLAGS_OWN_IO;
01025   else
01026     bf->flags&=~GWEN_BUFFER_FLAGS_OWN_IO;
01027   bf->ioLayer=io;
01028 }
01029 
01030 
01031 
01032 int GWEN_Buffer_FillWithBytes(GWEN_BUFFER *bf,
01033                               unsigned char c,
01034                               uint32_t size){
01035   assert(bf);
01036   if (GWEN_Buffer_AllocRoom(bf, size+1)) {
01037     DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
01038     return 1;
01039   }
01040   /* if (bf->pos+size>bf->bufferSize) { */
01041   if (bf->bytesUsed+size>bf->bufferSize) {
01042     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer full (%d [%d] of %d bytes)",
01043               bf->bytesUsed, size+1,
01044               bf->bufferSize);
01045     return 1;
01046   }
01047   memset(bf->ptr+bf->bytesUsed, c, size);
01048   if (bf->pos==bf->bytesUsed)
01049     bf->pos+=size;
01050   bf->bytesUsed+=size;
01051   /* append a NULL to allow using the buffer as ASCIIZ string */
01052   bf->ptr[bf->bytesUsed]=0;
01053   return 0;
01054 }
01055 
01056 
01057 
01058 int GWEN_Buffer_FillLeftWithBytes(GWEN_BUFFER *bf,
01059                                   unsigned char c,
01060                                   uint32_t size){
01061   assert(bf);
01062 
01063   if (GWEN_Buffer_InsertRoom(bf, size)) {
01064     return -1;
01065   }
01066   memset(bf->ptr+bf->pos, c, size);
01067   return 0;
01068 }
01069 
01070 
01071 
01072 
01073 
01074 
01075 

Generated on Fri Apr 11 01:53:46 2008 for gwenhywfar by  doxygen 1.5.5