libcm is a C development framework with an emphasis on audio signal processing applications.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmStrStream.c 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #include "cmGlobal.h"
  2. #include "cmRpt.h"
  3. #include "cmErr.h"
  4. #include "cmCtx.h"
  5. #include "cmMem.h"
  6. #include "cmMallocDebug.h"
  7. #include "cmLinkedHeap.h"
  8. #include "cmStrStream.h"
  9. #include "cmText.h"
  10. typedef struct cmSsBlk_str
  11. {
  12. char* blk;
  13. unsigned i;
  14. struct cmSsBlk_str* link;
  15. } cmSsBlk_t;
  16. typedef struct
  17. {
  18. cmErr_t err;
  19. cmLHeapH_t lhH;
  20. unsigned blkByteCnt;
  21. cmSsBlk_t* blp;
  22. cmSsBlk_t* elp;
  23. } cmOss_t;
  24. cmStrStreamH_t cmStrStreamNullHandle = cmSTATIC_NULL_HANDLE;
  25. cmOss_t* _cmOssHandleToPtr( cmStrStreamH_t h )
  26. {
  27. cmOss_t* p = (cmOss_t*)h.h;
  28. assert(p != NULL );
  29. return p;
  30. }
  31. cmSsRC_t _cmOssDestroy( cmOss_t* p )
  32. {
  33. cmSsRC_t rc = kOkSsRC;
  34. cmLHeapDestroy(&p->lhH);
  35. cmMemFree(p);
  36. return rc;
  37. }
  38. cmSsRC_t cmOStrStreamCreate( cmCtx_t* ctx, cmStrStreamH_t* hp, unsigned dfltBlkByteCnt )
  39. {
  40. cmSsRC_t rc;
  41. if((rc = cmOStrStreamDestroy(hp)) != kOkSsRC )
  42. return rc;
  43. cmOss_t* p = cmMemAllocZ(cmOss_t,1);
  44. p->blkByteCnt = dfltBlkByteCnt==0 ? 4096 : dfltBlkByteCnt;
  45. cmErrSetup(&p->err,&ctx->rpt,"OStrStream");
  46. if( cmLHeapIsValid(p->lhH = cmLHeapCreate(p->blkByteCnt+sizeof(cmSsBlk_t),ctx)) == false )
  47. {
  48. rc = cmErrMsg(&p->err,kLHeapMemFailSsRC,"Linked heap allocation failed.");
  49. goto errLabel;
  50. }
  51. hp->h = p;
  52. errLabel:
  53. if(rc != kOkSsRC )
  54. _cmOssDestroy(p);
  55. return rc;
  56. }
  57. cmSsRC_t cmOStrStreamDestroy(cmStrStreamH_t* hp )
  58. {
  59. cmSsRC_t rc = kOkSsRC;
  60. if( hp==NULL || cmOStrStreamIsValid(*hp)==false )
  61. return rc;
  62. cmOss_t* p = _cmOssHandleToPtr(*hp);
  63. if((rc = _cmOssDestroy(p)) != kOkSsRC )
  64. return rc;
  65. hp->h = NULL;
  66. return rc;
  67. }
  68. bool cmOStrStreamIsValid( cmStrStreamH_t h )
  69. { return h.h != NULL; }
  70. cmSsRC_t cmOStrStreamWrite( cmStrStreamH_t h, const void* vp, unsigned byteCnt )
  71. {
  72. cmSsRC_t rc = kOkSsRC;
  73. if( vp==NULL || byteCnt == 0 )
  74. return rc;
  75. cmOss_t* p = _cmOssHandleToPtr(h);
  76. char* cp = (char*)vp;
  77. unsigned j = 0;
  78. do
  79. {
  80. // if a blk exists
  81. if( p->elp != NULL )
  82. {
  83. // copy as much of vp[] as possible into the current end block
  84. unsigned n = cmMin(byteCnt, p->blkByteCnt - p->elp->i);
  85. memcpy(p->elp->blk + p->elp->i,cp + j,n);
  86. byteCnt -= n;
  87. p->elp->i += n;
  88. j += n;
  89. }
  90. // if all of vp[] has been copied then we are done
  91. if( byteCnt == 0 )
  92. break;
  93. assert( p->elp==NULL || p->elp->i == p->blkByteCnt );
  94. // allocate a new block
  95. cmSsBlk_t* nbp = (cmSsBlk_t*)cmLHeapAlloc(p->lhH,p->blkByteCnt+sizeof(cmSsBlk_t));
  96. nbp->blk = (char*)(nbp + 1);
  97. nbp->i = 0;
  98. nbp->link = NULL;
  99. // append the new blk onto the end of the list
  100. if( p->elp == NULL )
  101. p->blp = nbp;
  102. else
  103. p->elp->link = nbp;
  104. p->elp = nbp;
  105. }while(1);
  106. return rc;
  107. }
  108. cmSsRC_t cmOStrStreamWriteStr( cmStrStreamH_t h, const cmChar_t* str )
  109. {
  110. if( str == NULL )
  111. return kOkSsRC;
  112. return cmOStrStreamWrite(h,str,strlen(str));
  113. }
  114. cmSsRC_t cmOStrStreamWriteStrN( cmStrStreamH_t h, const cmChar_t* str, unsigned n )
  115. { return cmOStrStreamWrite(h,str,n); }
  116. cmSsRC_t cmOStrStreamVPrintf( cmStrStreamH_t h, const cmChar_t* fmt, va_list vl )
  117. {
  118. cmChar_t* s = cmTsVPrintfP(NULL,fmt,vl);
  119. cmSsRC_t rc = cmOStrStreamWriteStr(h,s);
  120. cmMemFree(s);
  121. return rc;
  122. }
  123. cmSsRC_t cmOStrStreamPrintf( cmStrStreamH_t h, const cmChar_t* fmt, ... )
  124. {
  125. va_list vl;
  126. va_start(vl,fmt);
  127. cmSsRC_t rc = cmOStrStreamVPrintf(h,fmt,vl);
  128. va_end(vl);
  129. return rc;
  130. }
  131. unsigned cmOStrStreamByteCount( cmStrStreamH_t h )
  132. {
  133. unsigned n = 0;
  134. cmOss_t* p = _cmOssHandleToPtr(h);
  135. cmSsBlk_t* bp = p->blp;
  136. for(; bp!=NULL; bp=bp->link)
  137. n += bp->i;
  138. return n;
  139. }
  140. unsigned _cmOssCopyBuf( cmOss_t* p, char* buf, unsigned n )
  141. {
  142. unsigned i = 0;
  143. cmSsBlk_t* bp = p->blp;
  144. for(; bp!=NULL; bp=bp->link)
  145. {
  146. assert( i + bp->i <= n );
  147. memcpy(buf+i,bp->blk,bp->i);
  148. i += bp->i;
  149. }
  150. return i;
  151. }
  152. void* cmOStrStreamAllocBuf( cmStrStreamH_t h )
  153. {
  154. unsigned n = cmOStrStreamByteCount(h);
  155. cmOss_t* p = _cmOssHandleToPtr(h);
  156. if( n == 0 )
  157. return NULL;
  158. char* buf = cmMemAlloc(char,n);
  159. unsigned i = _cmOssCopyBuf(p,buf,n);
  160. assert(i==n);
  161. return buf;
  162. }
  163. cmChar_t* cmOStrStreamAllocText( cmStrStreamH_t h )
  164. {
  165. unsigned n = cmOStrStreamByteCount(h);
  166. cmOss_t* p = _cmOssHandleToPtr(h);
  167. if( n == 0 )
  168. return NULL;
  169. char* buf = cmMemAlloc(char,n+1);
  170. unsigned i = _cmOssCopyBuf(p,buf,n);
  171. assert(i==n);
  172. buf[n] = 0;
  173. return buf;
  174. }