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.

cmText.c 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323
  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 "cmLinkedHeap.h"
  9. #include "cmText.h"
  10. #include "cmFloatTypes.h"
  11. #include "cmVectOps.h"
  12. typedef struct cmTextSys_str
  13. {
  14. cmErr_t err;
  15. cmLHeapH_t lhH;
  16. cmChar_t* buf;
  17. } cmTextSys_t;
  18. cmTextSysH_t cmTextSysNullHandle = cmSTATIC_NULL_HANDLE;
  19. cmTextSysH_t _cmTextSysGlobalH = cmSTATIC_NULL_HANDLE;
  20. cmTextSys_t* _cmTextSysHandleToPtr( cmTextSysH_t h )
  21. {
  22. cmTextSys_t* p = (cmTextSys_t*)h.h;
  23. assert(p != NULL);
  24. return p;
  25. }
  26. cmTxRC_t _cmTextSysFinalize( cmTextSys_t* p )
  27. {
  28. cmTxRC_t rc = kOkTxRC;
  29. if( cmLHeapIsValid(p->lhH) )
  30. cmLHeapDestroy(&p->lhH);
  31. cmMemFree(p->buf);
  32. cmMemFree(p);
  33. return rc;
  34. }
  35. cmTxRC_t cmTextSysInitialize( cmCtx_t* ctx, cmTextSysH_t* hp )
  36. {
  37. cmTxRC_t rc;
  38. if((rc = cmTextSysFinalize(hp)) != kOkTxRC )
  39. return rc;
  40. cmTextSys_t* p = cmMemAllocZ(cmTextSys_t,1);
  41. cmErrSetup(&p->err,&ctx->rpt,"Text System");
  42. if( cmLHeapIsValid( p->lhH = cmLHeapCreate( 8192, ctx )) == false )
  43. {
  44. rc = cmErrMsg(&p->err,kLHeapFailTxRC,"Linked Heap create failed.");
  45. goto errLabel;
  46. }
  47. hp->h = p;
  48. errLabel:
  49. return rc;
  50. }
  51. cmTxRC_t cmTextSysFinalize( cmTextSysH_t* hp )
  52. {
  53. cmTxRC_t rc = kOkTxRC;
  54. if( hp == NULL || cmTextSysIsValid(*hp)==false )
  55. return kOkTxRC;
  56. cmTextSys_t* p = _cmTextSysHandleToPtr(*hp);
  57. if((rc = _cmTextSysFinalize(p)) == kOkTxRC )
  58. {
  59. hp->h = NULL;
  60. }
  61. return rc;
  62. }
  63. bool cmTextSysIsValid( cmTextSysH_t h )
  64. { return h.h != NULL; }
  65. cmChar_t* _cmTextSysVPrintf( cmTextSysH_t h, cmLHeapH_t lhH, bool staticFl, const cmChar_t* fmt, va_list vl )
  66. {
  67. va_list vl1;
  68. va_copy(vl1,vl);
  69. cmTextSys_t* p = cmLHeapIsValid(lhH) ? NULL : _cmTextSysHandleToPtr(h);
  70. unsigned n = vsnprintf(NULL,0,fmt,vl);
  71. cmChar_t* s = NULL;
  72. if( staticFl )
  73. s = p->buf = cmMemResize(cmChar_t,p->buf,n+1);
  74. else
  75. s = cmLhAllocZ(cmLHeapIsValid(lhH) ? lhH : p->lhH,cmChar_t,n+1);
  76. unsigned m = vsnprintf(s,n+1,fmt,vl1);
  77. assert(m==n);
  78. s[n] = 0;
  79. va_end(vl1);
  80. return s;
  81. }
  82. cmChar_t* cmTextSysVPrintfH( cmLHeapH_t lhH, const cmChar_t* fmt, va_list vl )
  83. { return _cmTextSysVPrintf( cmTextSysNullHandle, lhH, false, fmt, vl ); }
  84. cmChar_t* cmTextSysPrintfH( cmLHeapH_t lhH, const cmChar_t* fmt, ... )
  85. {
  86. va_list vl;
  87. va_start( vl, fmt );
  88. cmChar_t* s = cmTextSysVPrintfH(lhH,fmt,vl);
  89. va_end(vl);
  90. return s;
  91. }
  92. cmChar_t* cmTextSysVPrintfS( cmTextSysH_t h, const cmChar_t* fmt, va_list vl )
  93. { return _cmTextSysVPrintf(h,cmLHeapNullHandle,true,fmt,vl); }
  94. cmChar_t* cmTextSysPrintfS( cmTextSysH_t h, const cmChar_t* fmt, ... )
  95. {
  96. va_list vl;
  97. va_start(vl,fmt);
  98. cmChar_t* s = cmTextSysVPrintfS(h,fmt,vl);
  99. va_end(vl);
  100. return s;
  101. }
  102. cmChar_t* cmTextSysVPrintf( cmTextSysH_t h, const cmChar_t* fmt, va_list vl )
  103. { return _cmTextSysVPrintf(h,cmLHeapNullHandle,false,fmt,vl); }
  104. cmChar_t* cmTextSysPrintf( cmTextSysH_t h, const cmChar_t* fmt, ... )
  105. {
  106. va_list vl;
  107. va_start(vl,fmt);
  108. cmChar_t* s = cmTextSysVPrintf(h,fmt,vl);
  109. va_end(vl);
  110. return s;
  111. }
  112. void cmTextSysFreeStr( cmTextSysH_t h, const cmChar_t* s )
  113. {
  114. cmTextSys_t* p = _cmTextSysHandleToPtr(h);
  115. cmLhFree(p->lhH,(cmChar_t*)s);
  116. }
  117. bool cmTextSysIsStored(cmTextSysH_t h, const cmChar_t* s )
  118. {
  119. cmTextSys_t* p = _cmTextSysHandleToPtr(h);
  120. return cmLHeapIsPtrInHeap(p->lhH,s);
  121. }
  122. //
  123. // Global interface
  124. //
  125. cmTxRC_t cmTsInitialize( cmCtx_t* ctx )
  126. { return cmTextSysInitialize(ctx,&_cmTextSysGlobalH); }
  127. cmTxRC_t cmTsFinalize()
  128. { return cmTextSysFinalize(&_cmTextSysGlobalH); }
  129. bool cmTsIsValid()
  130. { return cmTextSysIsValid(_cmTextSysGlobalH); }
  131. cmChar_t* cmTsVPrintfS( const cmChar_t* fmt, va_list vl )
  132. { return cmTextSysVPrintfS(_cmTextSysGlobalH,fmt,vl); }
  133. cmChar_t* cmTsPrintfS( const cmChar_t* fmt, ... )
  134. {
  135. va_list vl;
  136. va_start(vl,fmt);
  137. cmChar_t* s = cmTsVPrintfS(fmt,vl);
  138. va_end(vl);
  139. return s;
  140. }
  141. cmChar_t* cmTsVPrintfH( cmLHeapH_t h, const cmChar_t* fmt, va_list vl )
  142. { return cmTextSysVPrintfH(h,fmt,vl); }
  143. cmChar_t* cmTsPrintfH( cmLHeapH_t h, const cmChar_t* fmt, ... )
  144. {
  145. va_list vl;
  146. va_start(vl,fmt);
  147. cmChar_t* s = cmTsVPrintfH(h,fmt,vl);
  148. va_end(vl);
  149. return s;
  150. }
  151. cmChar_t* cmTsVPrintf( const cmChar_t* fmt, va_list vl )
  152. { return cmTextSysVPrintf(_cmTextSysGlobalH,fmt,vl); }
  153. cmChar_t* cmTsPrintf( const cmChar_t* fmt, ... )
  154. {
  155. va_list vl;
  156. va_start(vl,fmt);
  157. cmChar_t* s = cmTsVPrintf(fmt,vl);
  158. va_end(vl);
  159. return s;
  160. }
  161. void cmTsFreeStr( const cmChar_t* s )
  162. { cmTextSysFreeStr(_cmTextSysGlobalH,s); }
  163. bool cmTsIsStored( const cmChar_t* s )
  164. { return cmTextSysIsStored(_cmTextSysGlobalH,s); }
  165. cmChar_t* cmTsVPrintfP( cmChar_t* s, const cmChar_t* fmt, va_list vl )
  166. {
  167. va_list vl1;
  168. va_copy(vl1,vl);
  169. int n = vsnprintf(NULL,0,fmt,vl);
  170. assert(n != -1);
  171. s = cmMemResize(cmChar_t,s,n+1);
  172. unsigned m = vsnprintf(s,n+1,fmt,vl1);
  173. assert(m==n);
  174. s[n] = 0;
  175. return s;
  176. }
  177. cmChar_t* cmTsPrintfP( cmChar_t* s, const cmChar_t* fmt, ... )
  178. {
  179. va_list vl;
  180. va_start(vl,fmt);
  181. s = cmTsVPrintfP(s,fmt,vl);
  182. va_end(vl);
  183. return s;
  184. }
  185. void _cmTxError( cmErr_t* err, cmTxRC_t rc, const char* fmt, ... )
  186. {
  187. va_list vl;
  188. va_start(vl,fmt);
  189. cmErrVMsg(err,rc,fmt,vl);
  190. va_end(vl);
  191. }
  192. cmTxRC_t _cmTxRptError( cmErr_t* err, const char* msg, const char* inputText )
  193. {
  194. if( err == NULL )
  195. return kOkTxRC;
  196. if( inputText == NULL )
  197. {
  198. _cmTxError(err,kNullTxRC,"Text to %s conversion failed due to NULL input text.");
  199. return kNullTxRC;
  200. }
  201. if( errno != 0 )
  202. {
  203. _cmTxError(err,kCvtErrTxRC,"Text to %s conversion failed on input '%s'.",msg,inputText);
  204. return kCvtErrTxRC;
  205. }
  206. return kOkTxRC;
  207. }
  208. cmTxRC_t cmTextToInt(const char* text, int* vp, cmErr_t* err )
  209. {
  210. assert( vp != NULL );
  211. cmTxRC_t rc = kOkTxRC;
  212. int en = errno;
  213. errno = 0;
  214. *vp = text==NULL ? 0 : strtol(text,NULL,0);
  215. rc = _cmTxRptError(err,"integer",text);
  216. errno = en;
  217. return rc;
  218. }
  219. cmTxRC_t cmTextToUInt( const char* text, unsigned* vp, cmErr_t* err )
  220. {
  221. assert( vp != NULL );
  222. cmTxRC_t rc = kOkTxRC;
  223. int en = errno;
  224. errno = 0;
  225. *vp = text==NULL ? 0 : (unsigned)strtol(text,NULL,0);
  226. rc = _cmTxRptError(err,"unsigned integer",text);
  227. errno = en;
  228. return rc;
  229. }
  230. cmTxRC_t cmTextToFloat( const char* text, float* vp, cmErr_t* err )
  231. {
  232. assert( vp != NULL );
  233. cmTxRC_t rc = kOkTxRC;
  234. int en = errno;
  235. errno = 0;
  236. *vp = text==NULL ? 0 : (float)strtod(text,NULL);
  237. rc = _cmTxRptError(err,"float",text);
  238. errno = en;
  239. return rc;
  240. }
  241. cmTxRC_t cmTextToDouble( const char* text, double* vp, cmErr_t* err )
  242. {
  243. assert( vp != NULL );
  244. cmTxRC_t rc = kOkTxRC;
  245. int en = errno;
  246. errno = 0;
  247. *vp = text==NULL ? 0 : strtod(text,NULL);
  248. rc = _cmTxRptError(err,"double",text);
  249. errno = en;
  250. return rc;
  251. }
  252. cmTxRC_t cmTextToBool( const char* text, bool* vp, cmErr_t* err )
  253. {
  254. assert( vp != NULL );
  255. cmTxRC_t rc = kOkTxRC;
  256. if( strcasecmp(text,"true") == 0 || strcasecmp(text,"0") == 0 )
  257. *vp = true;
  258. else
  259. if( strcasecmp(text,"false") == 0 || strcasecmp(text,"1") == 0 )
  260. *vp = false;
  261. else
  262. rc = _cmTxRptError(err,"bool",text);
  263. return rc;
  264. }
  265. cmChar_t* cmTextNextNonWhiteOrEos( cmChar_t* s )
  266. {
  267. assert( s != NULL );
  268. while( (*s) && isspace(*s) )
  269. ++s;
  270. return s;
  271. }
  272. const cmChar_t* cmTextNextNonWhiteOrEosC( const cmChar_t* s )
  273. { return cmTextNextNonWhiteOrEos((cmChar_t*)s); }
  274. cmChar_t* cmTextNextNonWhite( cmChar_t* s )
  275. { //return (*(s=cmTextNextNonWhiteOrEos(s))) == 0 ? NULL : s;
  276. s=cmTextNextNonWhiteOrEos(s);
  277. if( *s == 0 )
  278. return NULL;
  279. return s;
  280. }
  281. const cmChar_t* cmTextNextNonWhiteC( const cmChar_t* s )
  282. { return cmTextNextNonWhite((cmChar_t*)s); }
  283. cmChar_t* cmTextPrevNonWhiteOrBos( cmChar_t* s0, const cmChar_t* s1 )
  284. {
  285. assert( s0!=NULL && s1!=NULL && s0 <= s1 );
  286. for(; s0 < s1; --s1 )
  287. if( !isspace(*s1) )
  288. break;
  289. return (cmChar_t*)s1;
  290. }
  291. const cmChar_t* cmTextPrevNonWhiteOrBosC( const cmChar_t* s0, const cmChar_t* s1 )
  292. { return cmTextPrevNonWhiteOrBos((cmChar_t*)s0,s1); }
  293. cmChar_t* cmTextPrevNonWhite( cmChar_t* s0, const cmChar_t* s1 )
  294. {
  295. cmChar_t* s2;
  296. if((s2 = cmTextPrevNonWhiteOrBos(s0,s1)) == s0 )
  297. return NULL;
  298. return s2;
  299. }
  300. const cmChar_t* cmTextPrevNonWhiteC( const cmChar_t* s0, const cmChar_t* s1 )
  301. { return cmTextPrevNonWhite((cmChar_t*)s0,s1); }
  302. cmChar_t* cmTextNextWhiteOrEos( cmChar_t* s )
  303. {
  304. assert( s!=NULL);
  305. while(*s && !isspace(*s) )
  306. ++s;
  307. return s;
  308. }
  309. const cmChar_t* cmTextNextWhiteOrEosC( const cmChar_t* s )
  310. { return cmTextNextWhiteOrEos((cmChar_t*)s); }
  311. cmChar_t* cmTextNextWhite( cmChar_t* s )
  312. { return (*(s=cmTextNextWhiteOrEos(s)))!=0 ? s : NULL; }
  313. const cmChar_t* cmTextNextWhiteC( const cmChar_t* s )
  314. { return cmTextNextWhite((cmChar_t*)s); }
  315. cmChar_t* cmTextPrevWhiteOrBos( cmChar_t* s0, const cmChar_t* s1 )
  316. {
  317. assert( s0!=NULL && s1!=NULL && s0 <= s1 );
  318. while( s1>s0 && !isspace(*s1) )
  319. --s1;
  320. return (cmChar_t*)s1;
  321. }
  322. const cmChar_t* cmTextPrevWhiteOrBosC( const cmChar_t* s0, const cmChar_t* s1 )
  323. { return cmTextPrevWhiteOrBos((cmChar_t*)s0,s1); }
  324. cmChar_t* cmTextPrevWhite( cmChar_t* s0, const cmChar_t* s1 )
  325. {
  326. cmChar_t* s2;
  327. if((s2 = cmTextPrevWhiteOrBos(s0,s1)) == s0 )
  328. return NULL;
  329. return s2;
  330. }
  331. const cmChar_t* cmTextPrevWhiteC( const cmChar_t* s0, const cmChar_t* s1 )
  332. { return cmTextPrevWhite((cmChar_t*)s0,s1); }
  333. cmChar_t* cmTextBegOfLine( cmChar_t* s0, const cmChar_t* s1 )
  334. {
  335. assert( s1!=NULL && s0!=NULL && s1 >= s0 );
  336. if( s0 == s1 )
  337. return s0;
  338. --s1;
  339. while( s1>s0 && *s1 != '\n' )
  340. --s1;
  341. if( *s1 == '\n' )
  342. ++s1;
  343. return (cmChar_t*)s1;
  344. }
  345. const cmChar_t* cmTextBegOfLineC( const cmChar_t* s0, const cmChar_t* s1 )
  346. { return cmTextBegOfLine((cmChar_t*)s0,s1); }
  347. cmChar_t* cmTextEndOfLine( cmChar_t* s )
  348. {
  349. assert( s!=NULL);
  350. while( *s!=0 && *s != '\n' )
  351. ++s;
  352. return s;
  353. }
  354. const cmChar_t* cmTextEndOfLineC( const cmChar_t* s )
  355. { return cmTextEndOfLine((cmChar_t*)s); }
  356. cmChar_t* cmTextLastNonWhiteChar( const cmChar_t* s )
  357. {
  358. unsigned n;
  359. if(s==NULL || (n = strlen(s)) == 0 )
  360. return NULL;
  361. cmChar_t* s0 = (cmChar_t*)s + n-1;
  362. for(; s0>=s; --s0)
  363. if( !isspace(*s0) )
  364. return s0;
  365. return NULL;
  366. }
  367. const cmChar_t* cmTextLastNonWhiteCharC( const cmChar_t* s )
  368. { return cmTextLastNonWhiteChar(s); }
  369. cmChar_t* cmTextLastWhiteChar( const cmChar_t* s )
  370. {
  371. unsigned n;
  372. if(s==NULL || (n = strlen(s)) == 0 )
  373. return NULL;
  374. cmChar_t* s0 = (cmChar_t*)s + n-1;
  375. for(; s0>=s; --s0)
  376. if( isspace(*s0) )
  377. return s0;
  378. return NULL;
  379. }
  380. const cmChar_t* cmTextLastWhiteCharC( const cmChar_t* s )
  381. { return cmTextLastWhiteChar(s); }
  382. void cmTextShrinkS( cmChar_t* s, const cmChar_t* t, unsigned tn )
  383. { cmVOC_Shrink(s,strlen(s)+1,t,tn); }
  384. void cmTextShrinkSN(cmChar_t* s, unsigned sn, const cmChar_t* t, unsigned tn )
  385. { cmVOC_Shrink(s,sn,t,tn); }
  386. void cmTextClip( cmChar_t* s, unsigned n )
  387. {
  388. if( n == 0 || s == NULL || strlen(s)==0 )
  389. return;
  390. if( n >= strlen(s) )
  391. {
  392. s[0]=0;
  393. return;
  394. }
  395. s[ strlen(s)-n ] = 0;
  396. }
  397. cmChar_t* cmTextTrimBegin( cmChar_t* s )
  398. {
  399. if( s==NULL || strlen(s) == 0 )
  400. return s;
  401. cmChar_t* s0 = cmTextNextNonWhite(s);
  402. // no non-white char's exist
  403. if( s0 == NULL )
  404. {
  405. s[0] = 0;
  406. return s;
  407. }
  408. if( s0 != s )
  409. cmTextShrinkS(s,s,s0-s);
  410. return s;
  411. }
  412. cmChar_t* cmTextTrimEnd( cmChar_t* s )
  413. {
  414. unsigned sn;
  415. if( s==NULL || (sn = strlen(s))==0)
  416. return s;
  417. cmChar_t* s0 = cmTextLastNonWhiteChar(s);
  418. if(s0-s+1 < sn )
  419. s[s0-s+1] = 0;
  420. return s;
  421. }
  422. cmChar_t* cmTextTrim( cmChar_t* s)
  423. {
  424. cmTextTrimBegin(s);
  425. cmTextTrimEnd(s);
  426. return s;
  427. }
  428. cmChar_t* cmTextExpandS( cmChar_t* s, const cmChar_t* t, unsigned tn )
  429. { return cmVOC_Expand(s,strlen(s)+1,t,tn); }
  430. cmChar_t* cmTextReplaceSN( cmChar_t* s, const cmChar_t* t, unsigned tn, const cmChar_t* u, unsigned un )
  431. {
  432. unsigned n = strlen(s)+1;
  433. return cmVOC_Replace(s,&n,t,tn,u,un);
  434. }
  435. cmChar_t* cmTextReplaceS( cmChar_t* s, const cmChar_t* t, unsigned tn, const cmChar_t* u )
  436. { return cmTextReplaceSN(s,t,tn,u,u==NULL ? 0 : strlen(u)); }
  437. cmChar_t* _cmTextReplace( cmChar_t* s, const cmChar_t* t, const cmChar_t* u, unsigned n )
  438. {
  439. // we will go into an endless loop if 't' is contained in 'u' and n > 1.
  440. //assert( s!= NULL && t!=NULL && u!=NULL && (n==1 || strstr(u,t) == NULL) );
  441. assert( s!= NULL && t!=NULL && u!=NULL );
  442. int tn = strlen(t);
  443. cmChar_t* c = NULL;
  444. unsigned i = 0;
  445. cmChar_t* s0 = s;
  446. while( (c = strstr(s0,t)) != NULL )
  447. {
  448. int offs = c - s;
  449. s = cmTextReplaceS(s,c,tn,u);
  450. assert(s!=NULL);
  451. s0 = s + offs + tn;
  452. ++i;
  453. if( n!=cmInvalidCnt && i>=n)
  454. break;
  455. };
  456. return s;
  457. }
  458. cmChar_t* cmTextReplaceAll( cmChar_t* s, const cmChar_t* t, const cmChar_t* u )
  459. { return _cmTextReplace(s,t,u,cmInvalidCnt); }
  460. cmChar_t* cmTextReplaceFirst( cmChar_t* s, const cmChar_t* t, const cmChar_t* u )
  461. { return _cmTextReplace(s,t,u,1); }
  462. cmChar_t* cmTextInsertSN( cmChar_t* s, const cmChar_t* t, const cmChar_t* u, unsigned un )
  463. {
  464. unsigned n = strlen(s)+1;
  465. return cmVOC_Replace(s,&n,t,0,u,un);
  466. }
  467. cmChar_t* cmTextInsertS( cmChar_t* s, const cmChar_t* t, const cmChar_t* u )
  468. { return cmTextInsertSN(s,t,u,u==NULL?0:strlen(u)); }
  469. cmChar_t* cmTextAppend( cmChar_t* s, unsigned* sn, const cmChar_t* u, unsigned un )
  470. { return cmVOC_Replace(s,sn,s+(*sn),0,u,un); }
  471. cmChar_t* cmTextAppendSN( cmChar_t* s, const cmChar_t* u, unsigned un )
  472. {
  473. unsigned sn = s==NULL ? 0 : strlen(s);
  474. if( un > 0 )
  475. {
  476. s = cmTextAppend(s,&sn,u,un+1);
  477. s[sn-1] = 0;
  478. }
  479. return s;
  480. }
  481. // append u[un] to s[] and append terminating zero.
  482. cmChar_t* cmTextAppendSNZ( cmChar_t* s, const cmChar_t* u, unsigned un )
  483. {
  484. unsigned sn = s==NULL ? 0 : strlen(s)+1;
  485. cmChar_t z = 0;
  486. s = cmTextAppend(s,&sn,u,un);
  487. return cmTextAppend(s,&sn,&z,1);
  488. }
  489. // both s[] and u[] are strz's
  490. cmChar_t* cmTextAppendSS( cmChar_t* s, const cmChar_t* u )
  491. { return cmTextAppendSN(s,u,strlen(u)); }
  492. cmChar_t* cmTextVAppendSS( cmChar_t* s, ... )
  493. {
  494. va_list vl;
  495. va_start(vl,s);
  496. do
  497. {
  498. cmChar_t* s0 = va_arg(vl,cmChar_t*);
  499. if( s0 == NULL )
  500. break;
  501. s = cmTextAppendSS(s,s0);
  502. }while(1);
  503. va_end(vl);
  504. return s;
  505. }
  506. cmChar_t* cmTextAppendChar( cmChar_t* s, cmChar_t c, unsigned n )
  507. {
  508. if( n <= 0 )
  509. return s;
  510. cmChar_t t[ n+1 ];
  511. memset(t,' ',n);
  512. t[n] = 0;
  513. return cmTextAppendSS(s,t);
  514. }
  515. bool cmTextIsEmpty( const cmChar_t* s )
  516. {
  517. if( s!=NULL )
  518. for(; *s; ++s )
  519. if( !isspace(*s) )
  520. return false;
  521. return true;
  522. }
  523. bool cmTextIsNotEmpty( const cmChar_t* s )
  524. { return !cmTextIsEmpty(s); }
  525. unsigned cmTextLength( const cmChar_t* s0 )
  526. {
  527. if( s0 == NULL )
  528. return 0;
  529. return strlen(s0);
  530. }
  531. int cmTextCmp( const cmChar_t* s0, const cmChar_t* s1 )
  532. {
  533. if( s0 == NULL && s1 == NULL )
  534. return 0;
  535. if( s0 == NULL || s1 == NULL )
  536. {
  537. if( s0 == NULL )
  538. return -1;
  539. return 1;
  540. }
  541. return strcmp(s0,s1);
  542. }
  543. int cmTextCmpN( const cmChar_t* s0, const cmChar_t* s1, unsigned n )
  544. {
  545. if( s0 == NULL && s1 == NULL )
  546. return 0;
  547. if( s0 == NULL || s1 == NULL )
  548. {
  549. if( s0 == NULL )
  550. return -1;
  551. return 1;
  552. }
  553. return strncmp(s0,s1,n);
  554. }
  555. void cmTextToLower( const cmChar_t* s0, cmChar_t* s1 )
  556. {
  557. if( s0 == NULL || s1==NULL )
  558. return;
  559. for(; *s0; ++s0,++s1)
  560. *s1 = tolower(*s0);
  561. *s1 = 0;
  562. return;
  563. }
  564. void cmTextToUpper( const cmChar_t* s0, cmChar_t* s1 )
  565. {
  566. if( s0 == NULL || s1==NULL )
  567. return;
  568. for(; *s0; ++s0,++s1)
  569. *s1 = toupper(*s0);
  570. *s1 = 0;
  571. return;
  572. }
  573. cmChar_t* cmTextLine( cmChar_t* s, unsigned line )
  574. {
  575. assert( line>0);
  576. unsigned i;
  577. // count down to the code line containing the tag reference
  578. for(i=0; i<line-1; ++i)
  579. {
  580. s = strchr(s,'\n');
  581. if( s == NULL )
  582. return NULL;
  583. ++s;
  584. }
  585. return s+1;
  586. }
  587. const cmChar_t* cmTextLineC( const cmChar_t* s, unsigned line )
  588. { return cmTextLine((cmChar_t*)s,line); }
  589. unsigned cmTextLineCount( const cmChar_t* s )
  590. {
  591. unsigned n = *s ? 1 : 0;
  592. while( *s )
  593. {
  594. s = cmTextEndOfLineC(s);
  595. switch( *s )
  596. {
  597. case 0:
  598. break;
  599. case '\n':
  600. s += 1;
  601. n += 1;
  602. break;
  603. default:
  604. { assert(0); }
  605. }
  606. }
  607. return n;
  608. }
  609. cmChar_t* cmTextRemoveConsecutiveSpaces( cmChar_t* s )
  610. {
  611. if( s==NULL || strlen(s) < 2 )
  612. return s;
  613. int i=1;
  614. while( s[i] )
  615. {
  616. if( isspace(s[i-1]) && isspace(s[i]) )
  617. cmTextShrinkS(s, s+i, 1 );
  618. else
  619. ++i;
  620. }
  621. return s;
  622. }
  623. cmChar_t* cmTextColumize( cmChar_t* s, unsigned colCnt )
  624. {
  625. if( s==NULL || strlen(s) < colCnt )
  626. return s;
  627. int i = 0;
  628. int c = 0;
  629. cmChar_t* c0 = NULL;
  630. for(; s[i]; ++i)
  631. {
  632. // remove any existing newlines
  633. if( s[i] == '\n' )
  634. s[i] = ' ';
  635. // track the last space (which is a potential wrap point).
  636. if( isspace(s[i]) )
  637. c0 = s+i;
  638. if( c < colCnt )
  639. ++c;
  640. else
  641. {
  642. // if there is no previous wrap point ...
  643. if( c0 == NULL )
  644. {
  645. // ... then insert one
  646. s = cmTextInsertS(s,s+i,"\n");
  647. }
  648. else
  649. {
  650. // replace the wrap point with a '\n'
  651. *c0 = '\n';
  652. }
  653. c = 0;
  654. c0 = NULL;
  655. }
  656. }
  657. return s;
  658. }
  659. cmChar_t* _cmTextPrefixRows( cmChar_t* s, const cmChar_t* t )
  660. {
  661. if( s==NULL || t==NULL || strlen(t)==0 )
  662. return s;
  663. int i;
  664. for(i=0; s[i]; ++i)
  665. if( i==0 || s[i]=='\n')
  666. {
  667. cmChar_t* u = s + (i==0 ? 0 : i+1);
  668. s = cmTextInsertS(s,u,t);
  669. }
  670. return s;
  671. }
  672. cmChar_t* cmTextIndentRows( cmChar_t* s, unsigned indent )
  673. {
  674. if( s==NULL || indent==0 )
  675. return s;
  676. cmChar_t* t = cmMemAllocZ( cmChar_t, indent+1 );
  677. cmVOC_Fill(t,indent,' ');
  678. t[indent] = 0;
  679. s = _cmTextPrefixRows(s,t);
  680. cmMemFree(t);
  681. return s;
  682. }
  683. cmChar_t* cmTextPrefixRows( cmChar_t* s, const cmChar_t* t )
  684. { return _cmTextPrefixRows(s,t); }
  685. cmChar_t* cmTextTrimRows( cmChar_t* s )
  686. {
  687. bool fl = true;
  688. int i = 0;
  689. while( s[i] )
  690. {
  691. if( s[i] == '\n' )
  692. {
  693. fl = true;
  694. ++i;
  695. }
  696. else
  697. {
  698. if( isspace(s[i]) && fl )
  699. cmTextShrinkS(s, s+i, 1 );
  700. else
  701. {
  702. fl = false;
  703. ++i;
  704. }
  705. }
  706. }
  707. return s;
  708. }
  709. cmChar_t* cmTextEatLeadingSpace( cmChar_t* s )
  710. {
  711. if( s == NULL )
  712. return s;
  713. while( *s )
  714. {
  715. if( !isspace(*s) )
  716. break;
  717. cmTextShrinkS(s,s,1);
  718. }
  719. return s;
  720. }
  721. cmChar_t* cmTextNextRow( cmChar_t* s )
  722. {
  723. if( s == NULL)
  724. return NULL;
  725. for(; *s; ++s)
  726. if( *s == '\n' )
  727. {
  728. ++s;
  729. return *s==0 ? NULL : s;
  730. }
  731. return NULL;
  732. }
  733. const cmChar_t* cmTextNextRowC( const cmChar_t* s )
  734. { return cmTextNextRow((cmChar_t*)s); }
  735. unsigned cmTextMinIndent( const cmChar_t* s )
  736. {
  737. // leadFl=true if at beginning of row
  738. bool leadFl = true;
  739. unsigned min_indent = INT_MAX;
  740. unsigned indent = 0;
  741. for(; *s; ++s)
  742. {
  743. if( leadFl )
  744. {
  745. if( isspace(*s) && *s!='\n' )
  746. indent += 1;
  747. else
  748. {
  749. if( indent < min_indent )
  750. min_indent = indent;
  751. indent = 0;
  752. leadFl = false;
  753. }
  754. }
  755. else
  756. {
  757. if( *s == '\n' )
  758. leadFl = true;
  759. }
  760. }
  761. return min_indent==INT_MAX ? 0 : min_indent;
  762. }
  763. cmChar_t* cmTextOutdent( cmChar_t* s, unsigned outdent )
  764. {
  765. // leadFl=true if at beginning of row
  766. bool leadFl = true;
  767. unsigned indent = 0;
  768. cmChar_t* cs = s;
  769. cmChar_t* s0 = s;
  770. for(; *cs; ++cs)
  771. {
  772. if( leadFl )
  773. {
  774. if( isspace(*cs) && *cs!='\n' )
  775. indent += 1;
  776. else
  777. {
  778. unsigned n = cmMin(outdent,indent);
  779. cmTextShrinkS(s,s0,n);
  780. cs -= n;
  781. indent = 0;
  782. leadFl = false;
  783. }
  784. }
  785. else
  786. {
  787. if( *cs == '\n' )
  788. {
  789. leadFl = true;
  790. s0 = cs + 1;
  791. }
  792. }
  793. }
  794. return s;
  795. }
  796. unsigned cmTextDecodeBase64BufferByteCount( const char* xV, unsigned xN )
  797. {
  798. if( xN % 4 != 0 )
  799. return cmInvalidCnt;
  800. unsigned yN = xN / 4 * 3;
  801. if( xV[xN-1] == '=' )
  802. yN -= 1;
  803. if( xV[xN-2] == '=' )
  804. yN -= 2;
  805. return yN;
  806. }
  807. cmTxRC_t cmTextDecodeBase64( const char* xV, unsigned xN, void* yV, unsigned yN )
  808. {
  809. int t[] =
  810. {
  811. 64, // 0
  812. 64, // 1
  813. 64, // 2
  814. 64, // 3
  815. 64, // 4
  816. 64, // 5
  817. 64, // 6
  818. 64, // 7
  819. 64, // 8
  820. 64, // 9
  821. 64, // 10
  822. 64, // 11
  823. 64, // 12
  824. 64, // 13
  825. 64, // 14
  826. 64, // 15
  827. 64, // 16
  828. 64, // 17
  829. 64, // 18
  830. 64, // 19
  831. 64, // 20
  832. 64, // 21
  833. 64, // 22
  834. 64, // 23
  835. 64, // 24
  836. 64, // 25
  837. 64, // 26
  838. 64, // 27
  839. 64, // 28
  840. 64, // 29
  841. 64, // 30
  842. 64, // 31
  843. 64, // 32
  844. 64, // 33
  845. 64, // 34
  846. 64, // 35
  847. 64, // 36
  848. 64, // 37
  849. 64, // 38
  850. 64, // 39
  851. 64, // 40
  852. 64, // 41
  853. 64, // 42
  854. 62, // 43 +
  855. 64, // 44
  856. 64, // 45
  857. 64, // 46
  858. 63, // 47 /
  859. 52, // 48 0
  860. 53, // 49 1
  861. 54, // 50 2
  862. 55, // 51 3
  863. 56, // 52 4
  864. 57, // 53 5
  865. 58, // 54 6
  866. 59, // 55 7
  867. 60, // 56 8
  868. 61, // 57 9
  869. 64, // 58
  870. 64, // 59
  871. 64, // 60
  872. 64, // 61
  873. 64, // 62
  874. 64, // 63
  875. 64, // 64
  876. 0, // 65 A
  877. 1, // 66 B
  878. 2, // 67 C
  879. 3, // 68 D
  880. 4, // 69 E
  881. 5, // 70 F
  882. 6, // 71 G
  883. 7, // 72 H
  884. 8, // 73 I
  885. 9, // 74 J
  886. 10, // 75 K
  887. 11, // 76 L
  888. 12, // 77 M
  889. 13, // 78 N
  890. 14, // 79 O
  891. 15, // 80 P
  892. 16, // 81 Q
  893. 17, // 82 R
  894. 18, // 83 S
  895. 19, // 84 T
  896. 20, // 85 U
  897. 21, // 86 V
  898. 22, // 87 W
  899. 23, // 88 X
  900. 24, // 89 Y
  901. 25, // 90 Z
  902. 64, // 91
  903. 64, // 92
  904. 64, // 93
  905. 64, // 94
  906. 64, // 95
  907. 64, // 96
  908. 26, // 97 a
  909. 27, // 98 b
  910. 28, // 99 c
  911. 29, //100 d
  912. 30, //101 e
  913. 31, //102 f
  914. 32, //103 g
  915. 33, //104 h
  916. 34, //105 i
  917. 35, //106 j
  918. 36, //107 k
  919. 37, //108 l
  920. 38, //109 m
  921. 39, //110 n
  922. 40, //111 o
  923. 41, //112 p
  924. 42, //113 q
  925. 43, //114 r
  926. 44, //115 s
  927. 45, //116 t
  928. 46, //117 u
  929. 47, //118 v
  930. 48, //119 w
  931. 49, //120 x
  932. 50, //121 y
  933. 51, //122 z
  934. 64, //123
  935. 64, //124
  936. 64, //125
  937. 64, //126
  938. 64 //127
  939. };
  940. unsigned i = 0;
  941. unsigned j = 0;
  942. char* zV = (char*)yV;
  943. while( i < xN )
  944. {
  945. unsigned yn = 3;
  946. if( xV[i+3] == '=' )
  947. --yn;
  948. if( xV[i+2] == '=' )
  949. --yn;
  950. unsigned v = 0;
  951. assert( i + 4 <= xN );
  952. v += t[(int)xV[i++]] << 18;
  953. v += t[(int)xV[i++]] << 12;
  954. v += t[(int)xV[i++]] << 6;
  955. v += t[(int)xV[i++]] << 0;
  956. if( j >= yN )
  957. break;
  958. zV[j++] = (v & 0xff0000) >> 16;
  959. if( yn > 1 )
  960. {
  961. if( j >= yN )
  962. break;
  963. zV[j++] = (v & 0x00ff00) >> 8;
  964. }
  965. if( yn > 2 )
  966. {
  967. if( j >= yN )
  968. break;
  969. zV[j++] = (v & 0x0000ff) >> 0;
  970. }
  971. }
  972. return j;
  973. }
  974. unsigned cmTextEncodeBase64BufferByteCount( unsigned binByteCnt )
  975. {
  976. int rem = binByteCnt % 3;
  977. binByteCnt -= rem;
  978. int n = binByteCnt / 3 * 4;
  979. if( rem )
  980. n += 4;
  981. return n;
  982. }
  983. unsigned cmTextEncodeBase64( const void* xV, unsigned xN, char* yV, unsigned yN )
  984. {
  985. const char* t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  986. const char* zV = (const char*)xV;
  987. unsigned i = 0;
  988. unsigned j = 0;
  989. while( 1 )
  990. {
  991. unsigned k = 3;
  992. unsigned v = ((int)zV[i++]) << 16;
  993. if( i < xN )
  994. v += ((int)zV[i++]) << 8;
  995. else
  996. --k;
  997. if( i < xN )
  998. v += ((int)zV[i++]);
  999. else
  1000. --k;
  1001. if( j >= yN )
  1002. break;
  1003. yV[j++] = t[ (v & 0xfc0000) >> 18 ];
  1004. if( j >= yN )
  1005. break;
  1006. yV[j++] = t[ (v & 0x03f000) >> 12 ];
  1007. if( j >= yN )
  1008. break;
  1009. if( k > 1 )
  1010. yV[j++] = t[ (v & 0x000fc0) >> 6 ];
  1011. else
  1012. yV[j++] = '=';
  1013. if( j >= yN )
  1014. break;
  1015. if( k > 2 )
  1016. yV[j++] = t[ (v & 0x00003f) >> 0 ];
  1017. else
  1018. yV[j++] = '=';
  1019. }
  1020. return j;
  1021. }