libcm/cmStrStream.c

232 rader
4.4 KiB
C

#include "cmGlobal.h"
#include "cmRpt.h"
#include "cmErr.h"
#include "cmCtx.h"
#include "cmMem.h"
#include "cmMallocDebug.h"
#include "cmLinkedHeap.h"
#include "cmStrStream.h"
#include "cmText.h"
typedef struct cmSsBlk_str
{
char* blk;
unsigned i;
struct cmSsBlk_str* link;
} cmSsBlk_t;
typedef struct
{
cmErr_t err;
cmLHeapH_t lhH;
unsigned blkByteCnt;
cmSsBlk_t* blp;
cmSsBlk_t* elp;
} cmOss_t;
cmStrStreamH_t cmStrStreamNullHandle = cmSTATIC_NULL_HANDLE;
cmOss_t* _cmOssHandleToPtr( cmStrStreamH_t h )
{
cmOss_t* p = (cmOss_t*)h.h;
assert(p != NULL );
return p;
}
cmSsRC_t _cmOssDestroy( cmOss_t* p )
{
cmSsRC_t rc = kOkSsRC;
cmLHeapDestroy(&p->lhH);
cmMemFree(p);
return rc;
}
cmSsRC_t cmOStrStreamCreate( cmCtx_t* ctx, cmStrStreamH_t* hp, unsigned dfltBlkByteCnt )
{
cmSsRC_t rc;
if((rc = cmOStrStreamDestroy(hp)) != kOkSsRC )
return rc;
cmOss_t* p = cmMemAllocZ(cmOss_t,1);
p->blkByteCnt = dfltBlkByteCnt==0 ? 4096 : dfltBlkByteCnt;
cmErrSetup(&p->err,&ctx->rpt,"OStrStream");
if( cmLHeapIsValid(p->lhH = cmLHeapCreate(p->blkByteCnt+sizeof(cmSsBlk_t),ctx)) == false )
{
rc = cmErrMsg(&p->err,kLHeapMemFailSsRC,"Linked heap allocation failed.");
goto errLabel;
}
hp->h = p;
errLabel:
if(rc != kOkSsRC )
_cmOssDestroy(p);
return rc;
}
cmSsRC_t cmOStrStreamDestroy(cmStrStreamH_t* hp )
{
cmSsRC_t rc = kOkSsRC;
if( hp==NULL || cmOStrStreamIsValid(*hp)==false )
return rc;
cmOss_t* p = _cmOssHandleToPtr(*hp);
if((rc = _cmOssDestroy(p)) != kOkSsRC )
return rc;
hp->h = NULL;
return rc;
}
bool cmOStrStreamIsValid( cmStrStreamH_t h )
{ return h.h != NULL; }
cmSsRC_t cmOStrStreamWrite( cmStrStreamH_t h, const void* vp, unsigned byteCnt )
{
cmSsRC_t rc = kOkSsRC;
if( vp==NULL || byteCnt == 0 )
return rc;
cmOss_t* p = _cmOssHandleToPtr(h);
char* cp = (char*)vp;
unsigned j = 0;
do
{
// if a blk exists
if( p->elp != NULL )
{
// copy as much of vp[] as possible into the current end block
unsigned n = cmMin(byteCnt, p->blkByteCnt - p->elp->i);
memcpy(p->elp->blk + p->elp->i,cp + j,n);
byteCnt -= n;
p->elp->i += n;
j += n;
}
// if all of vp[] has been copied then we are done
if( byteCnt == 0 )
break;
assert( p->elp==NULL || p->elp->i == p->blkByteCnt );
// allocate a new block
cmSsBlk_t* nbp = (cmSsBlk_t*)cmLHeapAlloc(p->lhH,p->blkByteCnt+sizeof(cmSsBlk_t));
nbp->blk = (char*)(nbp + 1);
nbp->i = 0;
nbp->link = NULL;
// append the new blk onto the end of the list
if( p->elp == NULL )
p->blp = nbp;
else
p->elp->link = nbp;
p->elp = nbp;
}while(1);
return rc;
}
cmSsRC_t cmOStrStreamWriteStr( cmStrStreamH_t h, const cmChar_t* str )
{
if( str == NULL )
return kOkSsRC;
return cmOStrStreamWrite(h,str,strlen(str));
}
cmSsRC_t cmOStrStreamWriteStrN( cmStrStreamH_t h, const cmChar_t* str, unsigned n )
{ return cmOStrStreamWrite(h,str,n); }
cmSsRC_t cmOStrStreamVPrintf( cmStrStreamH_t h, const cmChar_t* fmt, va_list vl )
{
cmChar_t* s = cmTsVPrintfP(NULL,fmt,vl);
cmSsRC_t rc = cmOStrStreamWriteStr(h,s);
cmMemFree(s);
return rc;
}
cmSsRC_t cmOStrStreamPrintf( cmStrStreamH_t h, const cmChar_t* fmt, ... )
{
va_list vl;
va_start(vl,fmt);
cmSsRC_t rc = cmOStrStreamVPrintf(h,fmt,vl);
va_end(vl);
return rc;
}
unsigned cmOStrStreamByteCount( cmStrStreamH_t h )
{
unsigned n = 0;
cmOss_t* p = _cmOssHandleToPtr(h);
cmSsBlk_t* bp = p->blp;
for(; bp!=NULL; bp=bp->link)
n += bp->i;
return n;
}
unsigned _cmOssCopyBuf( cmOss_t* p, char* buf, unsigned n )
{
unsigned i = 0;
cmSsBlk_t* bp = p->blp;
for(; bp!=NULL; bp=bp->link)
{
assert( i + bp->i <= n );
memcpy(buf+i,bp->blk,bp->i);
i += bp->i;
}
return i;
}
void* cmOStrStreamAllocBuf( cmStrStreamH_t h )
{
unsigned n = cmOStrStreamByteCount(h);
cmOss_t* p = _cmOssHandleToPtr(h);
if( n == 0 )
return NULL;
char* buf = cmMemAlloc(char,n);
unsigned i = _cmOssCopyBuf(p,buf,n);
assert(i==n);
return buf;
}
cmChar_t* cmOStrStreamAllocText( cmStrStreamH_t h )
{
unsigned n = cmOStrStreamByteCount(h);
cmOss_t* p = _cmOssHandleToPtr(h);
if( n == 0 )
return NULL;
char* buf = cmMemAlloc(char,n+1);
unsigned i = _cmOssCopyBuf(p,buf,n);
assert(i==n);
buf[n] = 0;
return buf;
}