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.6KB

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