Projekt

Allgemein

Profil

Herunterladen (19,2 KB) Statistiken
| Zweig: | Markierung: | Revision:
/***************************************************************************
$RCSfile$
-------------------
cvs : $Id$
begin : Fri Sep 12 2003
copyright : (C) 2003 by Martin Preuss
email : martin@libchipcard.de

***************************************************************************
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
* MA 02111-1307 USA *
* *
***************************************************************************/


#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include "buffer_p.h"
#include <gwenhywfar/misc.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/text.h>

#define DISABLE_DEBUGLOG


#ifdef GWEN_MEMTRACE
static GWEN_TYPE_UINT32 GWEN_Buffer_Buffers=0;

#endif

GWEN_BUFFER *GWEN_Buffer_new(char *buffer,
GWEN_TYPE_UINT32 size,
GWEN_TYPE_UINT32 used,
int take){
GWEN_BUFFER *bf;

GWEN_NEW_OBJECT(GWEN_BUFFER, bf);
#ifdef GWEN_MEMTRACE
GWEN_Buffer_Buffers++;
DBG_DEBUG(0, "New buffer (now %d)", GWEN_Buffer_Buffers);
#endif
if (!buffer) {
/* allocate buffer */
if (size) {
bf->realPtr=(char*)malloc(size);
assert(bf->realPtr);
bf->ptr=bf->realPtr;
bf->realBufferSize=size;
bf->bufferSize=size;
bf->flags=GWEN_BUFFER_FLAGS_OWNED;
bf->bytesUsed=used;
bf->ptr[0]=0;
}
}
else {
/* use existing buffer */
bf->realPtr=buffer;
bf->ptr=buffer;
bf->realBufferSize=size;
bf->bufferSize=size;
bf->bytesUsed=used;
if (take)
bf->flags=GWEN_BUFFER_FLAGS_OWNED;
}

bf->mode=GWEN_BUFFER_MODE_DEFAULT;
bf->hardLimit=GWEN_BUFFER_DEFAULT_HARDLIMIT;
bf->step=GWEN_BUFFER_DYNAMIC_STEP;
return bf;
}



void GWEN_Buffer_free(GWEN_BUFFER *bf){
if (bf) {
#ifdef GWEN_MEMTRACE
assert(GWEN_Buffer_Buffers);
GWEN_Buffer_Buffers--;
DBG_DEBUG(0, "Free buffer (now %d)", GWEN_Buffer_Buffers);
#endif
if (bf->flags & GWEN_BUFFER_FLAGS_OWNED)
free(bf->realPtr);
if (bf->bio) {
if (bf->flags & GWEN_BUFFER_FLAGS_OWN_BIO) {
GWEN_BufferedIO_free(bf->bio);
}
}
GWEN_FREE_OBJECT(bf);
}
}



GWEN_BUFFER *GWEN_Buffer_dup(GWEN_BUFFER *bf) {
GWEN_BUFFER *newbf;
GWEN_TYPE_UINT32 i;

GWEN_NEW_OBJECT(GWEN_BUFFER, newbf);
#ifdef GWEN_MEMTRACE
GWEN_Buffer_Buffers++;
DBG_DEBUG(0, "New buffer (now %d)", GWEN_Buffer_Buffers);
#endif
if (bf->realPtr && bf->realBufferSize) {
newbf->realPtr=(char*)malloc(bf->realBufferSize);
newbf->ptr=newbf->realPtr+(bf->ptr-bf->realPtr);
newbf->realBufferSize=bf->realBufferSize;
newbf->bufferSize=bf->bufferSize;
newbf->bytesUsed=bf->bytesUsed;
if (newbf->bytesUsed)
memmove(newbf->ptr, bf->ptr, bf->bytesUsed);
newbf->pos=bf->pos;
}
newbf->flags=bf->flags | GWEN_BUFFER_FLAGS_OWNED;
newbf->mode=bf->mode&GWEN_BUFFER_MODE_COPYMASK;
newbf->hardLimit=bf->hardLimit;
newbf->step=bf->step;
for (i=0; i<GWEN_BUFFER_MAX_BOOKMARKS; i++)
newbf->bookmarks[i]=bf->bookmarks[i];

return newbf;
}



int GWEN_Buffer_ReserveBytes(GWEN_BUFFER *bf, GWEN_TYPE_UINT32 res){
assert(bf);
if (!res)
return 0;

if (bf->bytesUsed) {
/* we need to move data */
if (GWEN_Buffer_AllocRoom(bf, res))
return -1;

memmove(bf->ptr+res, bf->ptr, bf->bytesUsed);
bf->ptr+=res;
bf->bufferSize-=res;
return 0;
}
else {
/* no data in buffer, so simply move ptrs */
if (GWEN_Buffer_AllocRoom(bf, res))
return -1;

bf->ptr+=res;
bf->bufferSize-=res;
return 0;
}
}



GWEN_TYPE_UINT32 GWEN_Buffer_GetMode(GWEN_BUFFER *bf){
assert(bf);
return bf->mode;
}



void GWEN_Buffer_SetMode(GWEN_BUFFER *bf, GWEN_TYPE_UINT32 mode){
assert(bf);
bf->mode=mode;
}


void GWEN_Buffer_AddMode(GWEN_BUFFER *bf, GWEN_TYPE_UINT32 mode){
assert(bf);
bf->mode|=mode;
}


void GWEN_Buffer_SubMode(GWEN_BUFFER *bf, GWEN_TYPE_UINT32 mode){
assert(bf);
bf->mode&=~mode;
}



GWEN_TYPE_UINT32 GWEN_Buffer_GetHardLimit(GWEN_BUFFER *bf){
assert(bf);
return bf->hardLimit;
}



void GWEN_Buffer_SetHardLimit(GWEN_BUFFER *bf, GWEN_TYPE_UINT32 l){
assert(bf);
assert(l);
bf->hardLimit=l;
}



char *GWEN_Buffer_GetStart(GWEN_BUFFER *bf){
assert(bf);
return bf->ptr;
}



GWEN_TYPE_UINT32 GWEN_Buffer_GetSize(GWEN_BUFFER *bf){
assert(bf);
if (bf->mode & GWEN_BUFFER_MODE_DYNAMIC)
return bf->hardLimit;
return bf->bufferSize;
}



GWEN_TYPE_UINT32 GWEN_Buffer_GetPos(GWEN_BUFFER *bf){
assert(bf);
return bf->pos;
}



int GWEN_Buffer_SetPos(GWEN_BUFFER *bf, GWEN_TYPE_UINT32 i){
assert(bf);

if (i>=bf->bufferSize) {
if (bf->mode & GWEN_BUFFER_MODE_USE_BIO) {
bf->pos=i;
}
else {
DBG_ERROR(0, "Position %d outside buffer boundaries (%d bytes)",
i, bf->bufferSize);
return -1;
}
}
bf->pos=i;
return 0;
}



GWEN_TYPE_UINT32 GWEN_Buffer_GetUsedBytes(GWEN_BUFFER *bf){
assert(bf);
return bf->bytesUsed;
}



int GWEN_Buffer_SetUsedBytes(GWEN_BUFFER *bf, GWEN_TYPE_UINT32 i){
assert(bf);

DBG_WARN(0,
"GWEN_Buffer_SetUsedBytes: Deprecated, "
"please use GWEN_Buffer_Crop instead.");
if (i>bf->bufferSize) {
DBG_ERROR(0, "Bytes used>buffer size (%d>%d bytes)",
i, bf->bufferSize);
return 1;
}
bf->bytesUsed=i;
return 0;
}



int GWEN_Buffer_AllocRoom(GWEN_BUFFER *bf, GWEN_TYPE_UINT32 size) {
assert(bf);
/*DBG_VERBOUS(0, "Allocating %d bytes", size);*/
/*if (bf->pos+size>bf->bufferSize) {*/
if (bf->bytesUsed+size>bf->bufferSize) {
/* need to realloc */
GWEN_TYPE_UINT32 nsize;
GWEN_TYPE_UINT32 noffs;
GWEN_TYPE_UINT32 reserved;
void *p;

/* check for dynamic mode */
if (!(bf->mode & GWEN_BUFFER_MODE_DYNAMIC)) {
DBG_ERROR(0, "Not in dynamic mode");
if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
abort();
}
return 1;
}

/* calculate reserved bytes (to set ptr later) */
reserved=bf->ptr-bf->realPtr;
/* this is the raw number of bytes we need */
/*nsize=bf->pos+size-bf->bufferSize;*/
nsize=bf->bytesUsed+size-bf->bufferSize;
/* round it up */
nsize=(nsize+(bf->step-1));
nsize&=~(bf->step-1);
/* store number of additional bytes to allocate */
noffs=nsize;
/* add current size to it */
nsize+=bf->realBufferSize;
if (nsize>bf->hardLimit) {
DBG_ERROR(0, "Size is beyond hard limit (%d>%d)", nsize, bf->hardLimit);
if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
abort();
}
return 1;
}
DBG_VERBOUS(0, "Reallocating from %d to %d bytes", bf->bufferSize, nsize);
p=realloc(bf->realPtr, nsize);
if (!p) {
DBG_ERROR(0, "Realloc failed.");
if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL) {
abort();
}
return 1;
}
/* store new size and pointer */
bf->realPtr=p;
bf->ptr=bf->realPtr+reserved;
bf->realBufferSize=nsize;
bf->bufferSize+=noffs;
}

return 0;
}



int GWEN_Buffer_AppendBytes(GWEN_BUFFER *bf,
const char *buffer,
GWEN_TYPE_UINT32 size){
assert(bf);
if (GWEN_Buffer_AllocRoom(bf, size+1)) {
DBG_DEBUG(0, "called from here");
return 1;
}
/* if (bf->pos+size>bf->bufferSize) { */
if (bf->bytesUsed+size>bf->bufferSize) {
DBG_ERROR(0, "Buffer full (%d [%d] of %d bytes)",
/*bf->pos, size,*/
bf->bytesUsed, size+1,
bf->bufferSize);
return 1;
}
/*memmove(bf->ptr+bf->pos, buffer, size);*/
memmove(bf->ptr+bf->bytesUsed, buffer, size);
/*bf->pos+=size;*/
if (bf->pos==bf->bytesUsed)
bf->pos+=size;
bf->bytesUsed+=size;
/* append a NULL to allow using the buffer as ASCIIZ string */
bf->ptr[bf->bytesUsed]=0;
return 0;
}



int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c){
assert(bf);

if (GWEN_Buffer_AllocRoom(bf, 1+1)) { /* +1 for the trailing 0 */
DBG_DEBUG(0, "called from here");
return 1;
}
/*if (bf->pos+1>bf->bufferSize) {*/
if (bf->bytesUsed+1>bf->bufferSize) {
/*DBG_ERROR(0, "Buffer full (%d of %d bytes)", bf->pos, bf->bufferSize);*/
DBG_ERROR(0, "Buffer full (%d of %d bytes)",
bf->bytesUsed, bf->bufferSize);
return 1;
}
bf->ptr[bf->bytesUsed]=c;
if (bf->pos==bf->bytesUsed)
bf->pos++;
bf->bytesUsed++;
/* append a NULL to allow using the buffer as ASCIIZ string */
bf->ptr[bf->bytesUsed]=0;
return 0;
}



int GWEN_Buffer_PeekByte(GWEN_BUFFER *bf){
assert(bf);

if (bf->pos>=bf->bytesUsed) {
if (bf->mode & GWEN_BUFFER_MODE_USE_BIO) {
if (bf->bio) {
unsigned int toread;
GWEN_ERRORCODE gerr;

if (GWEN_BufferedIO_CheckEOF(bf->bio)) {
DBG_INFO(0, "End of data stream reached");
return -1;
}
toread=bf->pos-bf->bytesUsed+1;
if (GWEN_Buffer_AllocRoom(bf, toread+1)) {
DBG_INFO(0, "Buffer too small");
return -1;
}
gerr=GWEN_BufferedIO_ReadRawForced(bf->bio,
bf->ptr+bf->bytesUsed,
&toread);
if (!GWEN_Error_IsOk(gerr)) {
DBG_INFO_ERR(0, gerr);
return -1;
}
bf->bytesUsed+=toread;
}
else {
DBG_DEBUG(0, "End of used area reached and no BIO (%d bytes)",
bf->pos);
return -1;
}
}
else {
DBG_VERBOUS(0, "End of used area reached (%d bytes)", bf->pos);
return -1;
}
}

return (unsigned char) (bf->ptr[bf->pos]);
}



int GWEN_Buffer_ReadByte(GWEN_BUFFER *bf){
int c;

c=GWEN_Buffer_PeekByte(bf);
if (c!=-1)
bf->pos++;
return c;
}



int GWEN_Buffer_IncrementPos(GWEN_BUFFER *bf, GWEN_TYPE_UINT32 i){
assert(bf);

if (i+bf->pos>=bf->bufferSize) {
if (!(bf->mode & GWEN_BUFFER_MODE_USE_BIO)) {
DBG_DEBUG(0,
"Position %d outside buffer boundaries (%d bytes)\n"
"Incrementing anyway",
i+bf->pos, bf->bufferSize);
}
}
bf->pos+=i;
return 0;
}



int GWEN_Buffer_AdjustUsedBytes(GWEN_BUFFER *bf){
assert(bf);
if (bf->pos<=bf->bufferSize) {
if (bf->pos>bf->bytesUsed) {
DBG_DEBUG(0, "Adjusted buffer (uses now %d bytes)",
bf->pos);
bf->bytesUsed=bf->pos;
}
return 0;
}
else {
DBG_ERROR(0, "Pointer outside buffer size (%d bytes)",
bf->bufferSize);
return 1;
}
}



int GWEN_Buffer_DecrementPos(GWEN_BUFFER *bf, GWEN_TYPE_UINT32 i){
assert(bf);

if (bf->pos-i<0) {
DBG_ERROR(0, "Position %d outside buffer boundaries (%d bytes)",
bf->pos-i, bf->bufferSize);
return 1;
}
bf->pos-=i;
return 0;
}



int GWEN_Buffer_AppendBuffer(GWEN_BUFFER *bf,
GWEN_BUFFER *sf){
assert(bf);
assert(sf);
if (sf->bytesUsed)
return GWEN_Buffer_AppendBytes(bf, sf->ptr, sf->bytesUsed);
return 0;
}



GWEN_TYPE_UINT32 GWEN_Buffer_RoomLeft(GWEN_BUFFER *bf){
assert(bf);

DBG_WARN(0, "You should better use \"GWEN_Buffer_AllocRoom\"");
if (bf->mode & GWEN_BUFFER_MODE_DYNAMIC)
return bf->hardLimit-bf->bytesUsed;
return (bf->bufferSize-bf->bytesUsed);
}



GWEN_TYPE_UINT32 GWEN_Buffer_BytesLeft(GWEN_BUFFER *bf){
DBG_WARN(0, "You should better use \"GWEN_Buffer_GetBytesLeft\"");
return GWEN_Buffer_GetBytesLeft(bf);
}


GWEN_TYPE_UINT32 GWEN_Buffer_GetBytesLeft(GWEN_BUFFER *bf){
assert(bf);

if (bf->pos<bf->bytesUsed)
return bf->bytesUsed-bf->pos;
else
return 0;
}



char *GWEN_Buffer_GetPosPointer(GWEN_BUFFER *bf){
assert(bf);
return bf->ptr+bf->pos;
}



GWEN_TYPE_UINT32 GWEN_Buffer_GetBookmark(GWEN_BUFFER *bf, unsigned int idx){
assert(bf);
assert(idx<GWEN_BUFFER_MAX_BOOKMARKS);
return bf->bookmarks[idx];
}



void GWEN_Buffer_SetBookmark(GWEN_BUFFER *bf, unsigned int idx,
GWEN_TYPE_UINT32 v){
assert(bf);
assert(idx<GWEN_BUFFER_MAX_BOOKMARKS);
bf->bookmarks[idx]=v;
}



void GWEN_Buffer_Dump(GWEN_BUFFER *bf, FILE *f, unsigned int insert) {
GWEN_TYPE_UINT32 k;

for (k=0; k<insert; k++)
fprintf(f, " ");
fprintf(f, "Buffer:\n");

for (k=0; k<insert; k++)
fprintf(f, " ");
fprintf(f, "Pos : %d (%04x)\n", bf->pos, bf->pos);

for (k=0; k<insert; k++)
fprintf(f, " ");
fprintf(f, "Buffer Size : %d\n", bf->bufferSize);

for (k=0; k<insert; k++)
fprintf(f, " ");
fprintf(f, "Hard limit : %d\n", bf->hardLimit);

for (k=0; k<insert; k++)
fprintf(f, " ");
fprintf(f, "Bytes Used : %d\n", bf->bytesUsed);

for (k=0; k<insert; k++)
fprintf(f, " ");
fprintf(f, "Bytes Reserved : %d\n", bf->ptr-bf->realPtr);

for (k=0; k<insert; k++)
fprintf(f, " ");
fprintf(f, "Flags : %08x ( ", bf->flags);
if (bf->flags & GWEN_BUFFER_FLAGS_OWNED)
fprintf(f, "OWNED ");
fprintf(f, ")\n");

for (k=0; k<insert; k++)
fprintf(f, " ");
fprintf(f, "Mode : %08x ( ", bf->mode);
if (bf->mode & GWEN_BUFFER_MODE_DYNAMIC)
fprintf(f, "DYNAMIC ");
if (bf->mode & GWEN_BUFFER_MODE_ABORT_ON_MEMFULL)
fprintf(f, "ABORT_ON_MEMFULL ");
fprintf(f, ")\n");

for (k=0; k<insert; k++)
fprintf(f, " ");
fprintf(f, "Bookmarks :");
for (k=0; k<GWEN_BUFFER_MAX_BOOKMARKS; k++)
fprintf(f, " %d", bf->bookmarks[k]);
fprintf(f, "\n");

if (bf->ptr && bf->bytesUsed) {
for (k=0; k<insert; k++)
fprintf(f, " ");
fprintf(f, "Data:\n");
GWEN_Text_DumpString(bf->ptr, bf->bytesUsed, f, insert+1);
}
}



void GWEN_Buffer_Reset(GWEN_BUFFER *bf){
assert(bf);
bf->pos=0;
bf->bytesUsed=0;
bf->ptr[0]=0;
}



void GWEN_Buffer_Rewind(GWEN_BUFFER *bf){
assert(bf);
bf->pos=0;
}



int GWEN_Buffer_ReadBytes(GWEN_BUFFER *bf,
char *buffer,
GWEN_TYPE_UINT32 *size){
GWEN_TYPE_UINT32 i;
int c;

i=0;

while(i<*size) {
c=GWEN_Buffer_ReadByte(bf);
if (c==-1)
break;
buffer[i]=c;
i++;
} /* while */

*size=i;
return 0;
}



GWEN_TYPE_UINT32 GWEN_Buffer_GetStep(GWEN_BUFFER *bf){
assert(bf);
return bf->step;
}



void GWEN_Buffer_SetStep(GWEN_BUFFER *bf, GWEN_TYPE_UINT32 step){
assert(bf);
bf->step=step;
}



void GWEN_Buffer_AdjustBookmarks(GWEN_BUFFER *bf,
GWEN_TYPE_UINT32 pos,
int offset) {
GWEN_TYPE_UINT32 i;

assert(bf);
for (i=0; i<GWEN_BUFFER_MAX_BOOKMARKS; i++) {
if (bf->bookmarks[i]>=pos)
bf->bookmarks[i]+=offset;
} /* for */
}



int GWEN_Buffer_InsertBytes(GWEN_BUFFER *bf,
const char *buffer,
GWEN_TYPE_UINT32 size){
char *p;
int i;

assert(bf);

if (bf->pos==0) {
if (bf->bytesUsed==0) {
int rv;
GWEN_TYPE_UINT32 pos;

/* no bytes used, simply append data */
pos=bf->pos;
rv=GWEN_Buffer_AppendBytes(bf, buffer, size);
if (rv) {
DBG_DEBUG(0, "here");
return rv;
}
bf->pos=pos;
return 0;
}
else {
if ( (bf->ptr - bf->realPtr) >= (int)size ) {
/* we can simply insert it by occupying the reserved space */
bf->ptr-=size;
memmove(bf->ptr, buffer, size);
bf->bytesUsed+=size;
bf->bufferSize+=size;
GWEN_Buffer_AdjustBookmarks(bf, bf->pos, size);
return 0;
}
}
}

if (GWEN_Buffer_AllocRoom(bf, size)) {
DBG_DEBUG(0, "called from here");
return 1;
}
if (bf->pos+size>bf->bufferSize) {
DBG_ERROR(0, "Buffer full (%d [%d] of %d bytes)",
bf->pos, size,
bf->bufferSize);
return -1;
}
p=bf->ptr+bf->pos;
i=bf->bytesUsed-bf->pos;
if (i>0)
/* move current data at pos out of the way */
memmove(p+size, p, i);
/* copy in new data */
memmove(bf->ptr+bf->pos, buffer, size);
bf->bytesUsed+=size;
GWEN_Buffer_AdjustBookmarks(bf, bf->pos, size);
return 0;
}



int GWEN_Buffer_InsertByte(GWEN_BUFFER *bf, char c){
char *p;
int i;
assert(bf);

if (bf->pos==0) {
if ((bf->ptr-bf->realPtr)>=1) {
/* we can simply insert it by occupying the reserved space */
DBG_DEBUG(0, "Using reserved space");
bf->ptr--;
bf->ptr[bf->pos]=c;
bf->bytesUsed++;
bf->bufferSize++;
GWEN_Buffer_AdjustBookmarks(bf, bf->pos, 1);
return 0;
}
}

if (GWEN_Buffer_AllocRoom(bf, 1)) {
DBG_DEBUG(0, "called from here");
return -1;
}
if (bf->pos+1>bf->bufferSize) {
DBG_ERROR(0, "Buffer full (%d [%d] of %d bytes)",
bf->pos, 1,
bf->bufferSize);
return -1;
}
p=bf->ptr+bf->pos;
i=bf->bytesUsed-bf->pos;
if (i>0)
/* move current data at pos out of the way */
memmove(p+1, p, i);

/* copy in new data */
bf->ptr[bf->pos]=c;
bf->bytesUsed++;
GWEN_Buffer_AdjustBookmarks(bf, bf->pos, 1);
return 0;
}



int GWEN_Buffer_InsertBuffer(GWEN_BUFFER *bf,
GWEN_BUFFER *sf){
assert(bf);
assert(sf);

return GWEN_Buffer_InsertBytes(bf, sf->ptr, sf->bytesUsed);
}



int GWEN_Buffer_Crop(GWEN_BUFFER *bf,
GWEN_TYPE_UINT32 pos,
GWEN_TYPE_UINT32 l) {
if (pos>=bf->bufferSize) {
DBG_ERROR(0, "Position outside buffer");
return -1;
}
bf->ptr+=pos;
bf->bufferSize-=pos;
bf->pos-=pos;
if (bf->bytesUsed-pos<l) {
DBG_INFO(0, "Invalid length");
return -1;
}
bf->bytesUsed=l;
GWEN_Buffer_AdjustBookmarks(bf, pos, -pos);
bf->ptr[bf->bytesUsed]=0;

return 0;
}



int GWEN_Buffer_AppendString(GWEN_BUFFER *bf,
const char *buffer){
assert(bf);
assert(buffer);
return GWEN_Buffer_AppendBytes(bf, buffer, strlen(buffer));
}



int GWEN_Buffer_InsertString(GWEN_BUFFER *bf,
const char *buffer){
assert(bf);
assert(buffer);
return GWEN_Buffer_InsertBytes(bf, buffer, strlen(buffer));
}



void GWEN_Buffer_SetSourceBIO(GWEN_BUFFER *bf,
GWEN_BUFFEREDIO *bio,
int take){
assert(bf);
if (bf->bio) {
if (bf->flags & GWEN_BUFFER_FLAGS_OWN_BIO) {
GWEN_BufferedIO_free(bf->bio);
}
}
if (take)
bf->flags|=GWEN_BUFFER_FLAGS_OWN_BIO;
else
bf->flags&=~GWEN_BUFFER_FLAGS_OWN_BIO;
bf->bio=bio;
}







(5-5/46)