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

Generated on Sat Jan 2 09:32:35 2010 for gwenhywfar by  doxygen 1.6.1