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