diff --git a/Makefile.am b/Makefile.am index 76f3e29..8653389 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,8 +12,8 @@ cmSRC += src/libcm/cmSerialize.c src/libcm/cmSymTbl.c src/libcm/cmFileSys.c src/ cmHDR += src/libcm/cmData.h src/libcm/cmLib.h src/libcm/cmText.h src/libcm/cmTextTemplate.h cmSRC += src/libcm/cmData.c src/libcm/cmLib.c src/libcm/cmText.c src/libcm/cmTextTemplate.c -cmHDR += src/libcm/cmMath.h src/libcm/cmGnuPlot.h src/libcm/cmKeyboard.h -cmSRC += src/libcm/cmMath.c src/libcm/cmGnuPlot.c src/libcm/cmKeyboard.c +cmHDR += src/libcm/cmMath.h src/libcm/cmGnuPlot.h src/libcm/cmKeyboard.h src/libcm/cmStrStream.h +cmSRC += src/libcm/cmMath.c src/libcm/cmGnuPlot.c src/libcm/cmKeyboard.c src/libcm/cmStrStream.c cmHDR += src/libcm/cmLinkedHeap.h src/libcm/cmMallocDebug.h src/libcm/cmLex.h src/libcm/cmJson.h src/libcm/cmPrefs.h src/libcm/cmStack.h src/libcm/cmArray.h cmSRC += src/libcm/cmLinkedHeap.c src/libcm/cmMallocDebug.c src/libcm/cmLex.c src/libcm/cmJson.c src/libcm/cmPrefs.c src/libcm/cmStack.c src/libcm/cmArray.c diff --git a/cmStrStream.c b/cmStrStream.c new file mode 100644 index 0000000..6c77b33 --- /dev/null +++ b/cmStrStream.c @@ -0,0 +1,219 @@ +#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; + +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; + cmOss_t* p = _cmOssHandleToPtr(h); + char* cp = (char*)vp; + 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,cp,n); + byteCnt -= n; + p->elp->i += 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; + + // end 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 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; +} diff --git a/cmStrStream.h b/cmStrStream.h new file mode 100644 index 0000000..dcba2c4 --- /dev/null +++ b/cmStrStream.h @@ -0,0 +1,39 @@ +#ifndef cmStrStream_h +#define cmStrStream_h + + +#ifdef __cplusplus +extern "C" { +#endif + + enum + { + kOkSsRC = cmOkRC, + kLHeapMemFailSsRC + }; + + typedef cmHandle_t cmStrStreamH_t; + typedef cmRC_t cmSsRC_t; + + extern cmStrStreamH_t cmStrStreamNullHandle_t; + + + cmSsRC_t cmOStrStreamCreate( cmCtx_t* ctx, cmStrStreamH_t* hp, unsigned dfltBlkByteCnt ); + cmSsRC_t cmOStrStreamDestroy(cmStrStreamH_t* hp ); + + bool cmOStrStreamIsValid( cmStrStreamH_t h ); + + cmSsRC_t cmOStrStreamWrite( cmStrStreamH_t h, const void* dp, unsigned byteCnt ); + cmSsRC_t cmOStrStreamWriteStr( cmStrStreamH_t h, const cmChar_t* str ); + cmSsRC_t cmOStrStreamVPrintf( cmStrStreamH_t h, const cmChar_t* fmt, va_list vl ); + cmSsRC_t cmOStrStreamPrintf( cmStrStreamH_t h, const cmChar_t* fmt, ... ); + + unsigned cmOStrStreamByteCount( cmStrStreamH_t h ); + void* cmOStrStreamAllocBuf( cmStrStreamH_t h ); + cmChar_t* cmOStrStreamAllocText( cmStrStreamH_t h ); + +#ifdef __cplusplus +} +#endif + +#endif