libcm is a C development framework with an emphasis on audio signal processing applications.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

cmSymTbl.c 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. #include "cmPrefix.h"
  2. #include "cmGlobal.h"
  3. #include "cmRpt.h"
  4. #include "cmErr.h"
  5. #include "cmCtx.h"
  6. #include "cmMem.h"
  7. #include "cmMallocDebug.h"
  8. #include "cmSymTbl.h"
  9. #include "cmLinkedHeap.h"
  10. cmSymTblH_t cmSymTblNullHandle = cmSTATIC_NULL_HANDLE;
  11. enum
  12. {
  13. kDynStFl = 0x01
  14. };
  15. typedef struct cmSymLabel_str
  16. {
  17. unsigned flags;
  18. const cmChar_t* label;
  19. } cmSymLabel_t;
  20. struct cmSym_str;
  21. typedef struct cmSymAvail_str
  22. {
  23. unsigned id;
  24. struct cmSym_str* linkPtr;
  25. } cmSymAvail_t;
  26. typedef struct cmSym_str
  27. {
  28. union
  29. {
  30. cmSymLabel_t label;
  31. cmSymAvail_t avail;
  32. } u;
  33. } cmSym_t;
  34. typedef struct cmSymBlock_t
  35. {
  36. cmSym_t* base; // block base - contains cmSymTbl_t.symPerBlock cmSym_t records
  37. unsigned cnt; // cout of symbols actually used in this block
  38. struct cmSymBlock_t* link; // next block
  39. } cmSymBlock_t;
  40. typedef struct
  41. {
  42. cmSymTblH_t parentH; // parent symbols table
  43. cmLHeapH_t heapH; // symbol label storage
  44. cmSymBlock_t* first; // pointer to head of symbol block chain
  45. cmSymBlock_t* last; // pointer to last symbol block in chain
  46. unsigned blkCnt; // count of blocks on chain
  47. unsigned symCnt; // total count of symbols controlled by this symbol (does not include parent symbols)
  48. unsigned baseSymId;
  49. unsigned symPerBlock;
  50. cmSym_t* availPtr;
  51. } cmSymTbl_t;
  52. cmSymTbl_t* _cmSymTblHandleToPtr( cmSymTblH_t h )
  53. {
  54. cmSymTbl_t* stp = (cmSymTbl_t*)h.h;
  55. assert( stp != NULL );
  56. return stp;
  57. }
  58. cmSymBlock_t* _cmSymTblAllocateBlock( cmSymTbl_t* stp )
  59. {
  60. // allocate the new block
  61. cmSymBlock_t* sbp = (cmSymBlock_t*)cmMemMallocZ( sizeof(cmSymBlock_t) + (stp->symPerBlock * sizeof(cmSym_t)));
  62. // initialize the new block control recd
  63. sbp->base = (cmSym_t*)(sbp+1);
  64. sbp->cnt = 0;
  65. sbp->link = NULL;
  66. // add the new block control recd to the end of the block chain
  67. if( stp->last == NULL )
  68. stp->first = sbp;
  69. else
  70. stp->last->link = sbp;
  71. // the new block control recd always becomes the last recd in the chain
  72. stp->last = sbp;
  73. ++stp->blkCnt;
  74. return sbp;
  75. }
  76. bool _cmSymTblIsSymbolRemoved( cmSymTbl_t* stp, unsigned symId )
  77. {
  78. const cmSym_t* sp = stp->availPtr;
  79. for(; sp != NULL; sp=sp->u.avail.linkPtr)
  80. if( sp->u.avail.id == symId )
  81. return true;
  82. return false;
  83. }
  84. unsigned _cmSymTblLabelToId( cmSymTbl_t* stp, const char* label )
  85. {
  86. cmSymBlock_t* sbp = stp->first;
  87. unsigned symId = stp->baseSymId;
  88. while( sbp != NULL )
  89. {
  90. cmSym_t* sp = sbp->base;
  91. cmSym_t* ep = sbp->base + sbp->cnt;
  92. for(; sp<ep; ++sp,++symId)
  93. {
  94. if( _cmSymTblIsSymbolRemoved(stp, symId ) == false )
  95. if( strcmp( sp->u.label.label, label ) == 0 )
  96. return symId;
  97. }
  98. sbp = sbp->link;
  99. }
  100. return cmInvalidId;
  101. }
  102. cmSym_t* _cmSymTblIdToSymPtr( cmSymTbl_t* stp, unsigned symId )
  103. {
  104. if( cmSymTblIsValid(stp->parentH) && cmSymTblIsValidId( stp->parentH, symId ) )
  105. return _cmSymTblIdToSymPtr( _cmSymTblHandleToPtr(stp->parentH), symId );
  106. symId -= stp->baseSymId;
  107. unsigned n = symId / stp->symPerBlock;
  108. unsigned i = symId % stp->symPerBlock;
  109. if( n >= stp->blkCnt )
  110. return NULL;
  111. cmSymBlock_t* sbp = stp->first;
  112. unsigned j;
  113. for(j=0; j<n; ++j)
  114. sbp = sbp->link;
  115. if( i >= sbp->cnt )
  116. return NULL;
  117. return sbp->base + i;
  118. }
  119. cmSymTblH_t cmSymTblCreate( cmSymTblH_t parentH, unsigned baseSymId, cmCtx_t* ctx )
  120. {
  121. cmSymTblH_t h;
  122. cmSymTbl_t* stp = cmMemAllocZ( cmSymTbl_t, 1 );
  123. stp->heapH = cmLHeapCreate( 2048, ctx );
  124. stp->symPerBlock = 3;
  125. stp->baseSymId = baseSymId;
  126. stp->parentH = parentH;
  127. _cmSymTblAllocateBlock( stp );
  128. h.h = stp;
  129. return h;
  130. }
  131. void cmSymTblDestroy( cmSymTblH_t* hp )
  132. {
  133. if( hp==NULL || hp->h == NULL )
  134. return;
  135. cmSymTbl_t* stp = _cmSymTblHandleToPtr(*hp);
  136. assert( stp != NULL );
  137. cmSymBlock_t* sbp = stp->first;
  138. while( sbp != NULL )
  139. {
  140. cmSymBlock_t* t = sbp;
  141. sbp = sbp->link;
  142. cmMemFree(t);
  143. }
  144. cmLHeapDestroy(&stp->heapH);
  145. cmMemFree(hp->h);
  146. hp->h = NULL;
  147. }
  148. unsigned cmSymTblRegister( cmSymTblH_t h, const char* label, bool staticFl )
  149. {
  150. cmSymTbl_t* stp = _cmSymTblHandleToPtr(h);
  151. unsigned symId;
  152. unsigned flags = 0;
  153. cmSym_t* sp = NULL;
  154. // check for the label in the local symbol table
  155. if((symId = _cmSymTblLabelToId( stp, label )) != cmInvalidId )
  156. return symId;
  157. // check for the label in the parent symbol table
  158. if( cmSymTblIsValid(stp->parentH) )
  159. if((symId = _cmSymTblLabelToId( _cmSymTblHandleToPtr(stp->parentH), label)) != cmInvalidId )
  160. return symId;
  161. // if the label is not static then create a copy of it on the local heap
  162. if( !staticFl )
  163. {
  164. char* cp = (char*)cmLHeapAlloc( stp->heapH, strlen(label) + 1 );
  165. strcpy(cp,label);
  166. label = cp;
  167. flags |= kDynStFl;
  168. }
  169. // if there are no previosly removed symbols available
  170. if( stp->availPtr == NULL )
  171. {
  172. cmSymBlock_t*sbp = stp->last;
  173. // if the last block is full
  174. if( sbp->cnt == stp->symPerBlock )
  175. sbp = _cmSymTblAllocateBlock(stp);
  176. // the last block must now have an empty slot
  177. assert( sbp->cnt < stp->symPerBlock );
  178. unsigned idx = sbp->cnt++;
  179. sp = sbp->base + idx;
  180. //sbp->base[ idx ].u.label.label = label;
  181. //sbp->base[ idx ].u.label.flags = flags;
  182. // calculate the symbol id
  183. symId = stp->baseSymId + ((stp->blkCnt-1) * stp->symPerBlock) + sbp->cnt - 1;
  184. }
  185. else // there are previously removed symbols available
  186. {
  187. sp = stp->availPtr; // get the next avail symbol
  188. stp->availPtr = sp->u.avail.linkPtr; // take it off the avail list
  189. symId = sp->u.avail.id; // store the new symbol's id
  190. }
  191. // setup the symbol record
  192. sp->u.label.label = label;
  193. sp->u.label.flags = flags;
  194. // verify that the new symId does not already belong to the parent
  195. assert( cmSymTblIsValid(stp->parentH)==false ? 1 : cmSymTblLabel( stp->parentH, symId)==NULL );
  196. ++stp->symCnt;
  197. return symId;
  198. }
  199. unsigned cmSymTblRegisterSymbol( cmSymTblH_t h, const char* label )
  200. { return cmSymTblRegister( h, label, false ); }
  201. unsigned cmSymTblRegisterStaticSymbol( cmSymTblH_t h, const char* label )
  202. { return cmSymTblRegister( h, label, true ); }
  203. unsigned cmSymTblRegisterVFmt( cmSymTblH_t h, const cmChar_t* fmt, va_list vl )
  204. {
  205. unsigned n = vsnprintf(NULL,0,fmt,vl);
  206. cmChar_t b[n+1];
  207. vsnprintf(b,n,fmt,vl);
  208. return cmSymTblRegister(h,fmt,vl);
  209. }
  210. unsigned cmSymTblRegisterFmt( cmSymTblH_t h, const cmChar_t* fmt, ... )
  211. {
  212. va_list vl;
  213. va_start(vl,fmt);
  214. cmSymTblRegisterVFmt(h,fmt,vl);
  215. va_end(vl);
  216. }
  217. bool cmSymTblRemove( cmSymTblH_t h, unsigned symId )
  218. {
  219. cmSymTbl_t* stp = _cmSymTblHandleToPtr(h);
  220. cmSym_t* sp;
  221. if((sp = _cmSymTblIdToSymPtr(stp,symId)) == NULL )
  222. return false;
  223. if( cmIsFlag(sp->u.label.flags,kDynStFl))
  224. cmLHeapFree(stp->heapH,(void*)sp->u.label.label);
  225. sp->u.avail.id = symId;
  226. sp->u.avail.linkPtr = stp->availPtr;
  227. stp->availPtr = sp;
  228. return true;
  229. }
  230. const char* cmSymTblLabel( cmSymTblH_t h, unsigned symId )
  231. {
  232. cmSymTbl_t* stp = _cmSymTblHandleToPtr(h);
  233. cmSym_t* sp;
  234. if((sp = _cmSymTblIdToSymPtr(stp,symId)) == NULL )
  235. return NULL;
  236. return sp->u.label.label;
  237. }
  238. unsigned cmSymTblId( cmSymTblH_t h, const char* label )
  239. {
  240. cmSymTbl_t* stp = _cmSymTblHandleToPtr(h);
  241. unsigned id;
  242. if((id=_cmSymTblLabelToId(stp,label)) == cmInvalidId )
  243. if( cmSymTblIsValid(stp->parentH))
  244. return _cmSymTblLabelToId( _cmSymTblHandleToPtr(stp->parentH), label );
  245. return id;
  246. }
  247. bool cmSymTblIsValid( cmSymTblH_t h )
  248. { return h.h != NULL; }
  249. bool cmSymTblIsValidId( cmSymTblH_t h, unsigned symId )
  250. {
  251. cmSymTbl_t* stp = _cmSymTblHandleToPtr(h);
  252. return stp->baseSymId <= symId && symId < (stp->baseSymId + stp->symCnt);
  253. }
  254. void cmSymTblReport( cmSymTblH_t h )
  255. {
  256. cmSymTbl_t* stp = _cmSymTblHandleToPtr(h);
  257. cmSymBlock_t* sbp = stp->first;
  258. unsigned i=0, j=0, symId = stp->baseSymId;
  259. printf("blks:%i syms:%i\n", stp->blkCnt, stp->symCnt );
  260. for(; sbp != NULL; sbp=sbp->link,++i)
  261. for(j=0; j<sbp->cnt; ++j,++symId)
  262. {
  263. bool remFl = _cmSymTblIsSymbolRemoved(stp, symId );
  264. printf("blk:%i sym:%i id:%i label:%s\n",i,j,symId,remFl ? "<removed>" : sbp->base[j].u.label.label);
  265. }
  266. }
  267. //{ { label:cmSymTblEx }
  268. //(
  269. // cmSymTblTest() gives a usage example for the symbol table component.
  270. //)
  271. //[
  272. void cmSymTblTest( cmCtx_t* ctx )
  273. {
  274. unsigned baseSymId = 100;
  275. unsigned i;
  276. unsigned n = 10;
  277. unsigned idArray[n];
  278. // create a symbol table
  279. cmSymTblH_t h = cmSymTblCreate( cmSymTblNullHandle, baseSymId, ctx );
  280. if( cmSymTblIsValid(h) == false )
  281. {
  282. cmRptPrintf(&ctx->rpt,"Symbol table creation failed.");
  283. return;
  284. }
  285. // generate and register some symbols
  286. for(i=0; i<n; ++i)
  287. {
  288. bool staticFl = false;
  289. char str[10];
  290. snprintf(str,9,"sym%i",i);
  291. idArray[i] = cmSymTblRegister( h, str, staticFl );
  292. }
  293. // remove the fourth symbol generated
  294. cmSymTblRemove( h, baseSymId+3 );
  295. // print the symbol table
  296. cmSymTblReport(h);
  297. // iterate through the symbol table
  298. for(i=0; i<n; ++i)
  299. {
  300. const cmChar_t* lbl = cmSymTblLabel(h,idArray[i]);
  301. if( lbl == NULL )
  302. cmRptPrintf(&ctx->rpt,"%i <removed>\n",i);
  303. else
  304. cmRptPrintf(&ctx->rpt,"%i %i==%i %s \n",i,idArray[i],cmSymTblId(h,lbl),lbl);
  305. }
  306. // release the symbol table
  307. cmSymTblDestroy(&h);
  308. return;
  309. }
  310. //]
  311. //}