libcm is a C development framework with an emphasis on audio signal processing applications.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

cmSymTbl.c 9.6KB

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