libcm is a C development framework with an emphasis on audio signal processing applications.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

cmText.c 23KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295
  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. cmChar_t* cmTextRemoveConsecutiveSpaces( cmChar_t* s )
  590. {
  591. if( s==NULL || strlen(s) < 2 )
  592. return s;
  593. int i=1;
  594. while( s[i] )
  595. {
  596. if( isspace(s[i-1]) && isspace(s[i]) )
  597. cmTextShrinkS(s, s+i, 1 );
  598. else
  599. ++i;
  600. }
  601. return s;
  602. }
  603. cmChar_t* cmTextColumize( cmChar_t* s, unsigned colCnt )
  604. {
  605. if( s==NULL || strlen(s) < colCnt )
  606. return s;
  607. int i = 0;
  608. int c = 0;
  609. cmChar_t* c0 = NULL;
  610. for(; s[i]; ++i)
  611. {
  612. // remove any existing newlines
  613. if( s[i] == '\n' )
  614. s[i] = ' ';
  615. // track the last space (which is a potential wrap point).
  616. if( isspace(s[i]) )
  617. c0 = s+i;
  618. if( c < colCnt )
  619. ++c;
  620. else
  621. {
  622. // if there is no previous wrap point ...
  623. if( c0 == NULL )
  624. {
  625. // ... then insert one
  626. s = cmTextInsertS(s,s+i,"\n");
  627. }
  628. else
  629. {
  630. // replace the wrap point with a '\n'
  631. *c0 = '\n';
  632. }
  633. c = 0;
  634. c0 = NULL;
  635. }
  636. }
  637. return s;
  638. }
  639. cmChar_t* _cmTextPrefixRows( cmChar_t* s, const cmChar_t* t )
  640. {
  641. if( s==NULL || t==NULL || strlen(t)==0 )
  642. return s;
  643. int i;
  644. for(i=0; s[i]; ++i)
  645. if( i==0 || s[i]=='\n')
  646. {
  647. cmChar_t* u = s + (i==0 ? 0 : i+1);
  648. s = cmTextInsertS(s,u,t);
  649. }
  650. return s;
  651. }
  652. cmChar_t* cmTextIndentRows( cmChar_t* s, unsigned indent )
  653. {
  654. if( s==NULL || indent==0 )
  655. return s;
  656. cmChar_t* t = cmMemAllocZ( cmChar_t, indent+1 );
  657. cmVOC_Fill(t,indent,' ');
  658. t[indent] = 0;
  659. s = _cmTextPrefixRows(s,t);
  660. cmMemFree(t);
  661. return s;
  662. }
  663. cmChar_t* cmTextPrefixRows( cmChar_t* s, const cmChar_t* t )
  664. { return _cmTextPrefixRows(s,t); }
  665. cmChar_t* cmTextTrimRows( cmChar_t* s )
  666. {
  667. bool fl = true;
  668. int i = 0;
  669. while( s[i] )
  670. {
  671. if( s[i] == '\n' )
  672. {
  673. fl = true;
  674. ++i;
  675. }
  676. else
  677. {
  678. if( isspace(s[i]) && fl )
  679. cmTextShrinkS(s, s+i, 1 );
  680. else
  681. {
  682. fl = false;
  683. ++i;
  684. }
  685. }
  686. }
  687. return s;
  688. }
  689. cmChar_t* cmTextEatLeadingSpace( cmChar_t* s )
  690. {
  691. if( s == NULL )
  692. return s;
  693. while( *s )
  694. {
  695. if( !isspace(*s) )
  696. break;
  697. cmTextShrinkS(s,s,1);
  698. }
  699. return s;
  700. }
  701. cmChar_t* cmTextNextRow( cmChar_t* s )
  702. {
  703. if( s == NULL)
  704. return NULL;
  705. for(; *s; ++s)
  706. if( *s == '\n' )
  707. {
  708. ++s;
  709. return *s==0 ? NULL : s;
  710. }
  711. return NULL;
  712. }
  713. const cmChar_t* cmTextNextRowC( const cmChar_t* s )
  714. { return cmTextNextRow((cmChar_t*)s); }
  715. unsigned cmTextMinIndent( const cmChar_t* s )
  716. {
  717. // leadFl=true if at beginning of row
  718. bool leadFl = true;
  719. unsigned min_indent = INT_MAX;
  720. unsigned indent = 0;
  721. for(; *s; ++s)
  722. {
  723. if( leadFl )
  724. {
  725. if( isspace(*s) && *s!='\n' )
  726. indent += 1;
  727. else
  728. {
  729. if( indent < min_indent )
  730. min_indent = indent;
  731. indent = 0;
  732. leadFl = false;
  733. }
  734. }
  735. else
  736. {
  737. if( *s == '\n' )
  738. leadFl = true;
  739. }
  740. }
  741. return min_indent==INT_MAX ? 0 : min_indent;
  742. }
  743. cmChar_t* cmTextOutdent( cmChar_t* s, unsigned outdent )
  744. {
  745. // leadFl=true if at beginning of row
  746. bool leadFl = true;
  747. unsigned indent = 0;
  748. cmChar_t* cs = s;
  749. cmChar_t* s0 = s;
  750. for(; *cs; ++cs)
  751. {
  752. if( leadFl )
  753. {
  754. if( isspace(*cs) && *cs!='\n' )
  755. indent += 1;
  756. else
  757. {
  758. unsigned n = cmMin(outdent,indent);
  759. cmTextShrinkS(s,s0,n);
  760. cs -= n;
  761. indent = 0;
  762. leadFl = false;
  763. }
  764. }
  765. else
  766. {
  767. if( *cs == '\n' )
  768. {
  769. leadFl = true;
  770. s0 = cs + 1;
  771. }
  772. }
  773. }
  774. return s;
  775. }
  776. unsigned cmTextDecodeBase64BufferByteCount( const char* xV, unsigned xN )
  777. {
  778. if( xN % 4 != 0 )
  779. return cmInvalidCnt;
  780. unsigned yN = xN / 4 * 3;
  781. if( xV[xN-1] == '=' )
  782. yN -= 1;
  783. if( xV[xN-2] == '=' )
  784. yN -= 2;
  785. return yN;
  786. }
  787. cmTxRC_t cmTextDecodeBase64( const char* xV, unsigned xN, void* yV, unsigned yN )
  788. {
  789. int t[] =
  790. {
  791. 64, // 0
  792. 64, // 1
  793. 64, // 2
  794. 64, // 3
  795. 64, // 4
  796. 64, // 5
  797. 64, // 6
  798. 64, // 7
  799. 64, // 8
  800. 64, // 9
  801. 64, // 10
  802. 64, // 11
  803. 64, // 12
  804. 64, // 13
  805. 64, // 14
  806. 64, // 15
  807. 64, // 16
  808. 64, // 17
  809. 64, // 18
  810. 64, // 19
  811. 64, // 20
  812. 64, // 21
  813. 64, // 22
  814. 64, // 23
  815. 64, // 24
  816. 64, // 25
  817. 64, // 26
  818. 64, // 27
  819. 64, // 28
  820. 64, // 29
  821. 64, // 30
  822. 64, // 31
  823. 64, // 32
  824. 64, // 33
  825. 64, // 34
  826. 64, // 35
  827. 64, // 36
  828. 64, // 37
  829. 64, // 38
  830. 64, // 39
  831. 64, // 40
  832. 64, // 41
  833. 64, // 42
  834. 62, // 43 +
  835. 64, // 44
  836. 64, // 45
  837. 64, // 46
  838. 63, // 47 /
  839. 52, // 48 0
  840. 53, // 49 1
  841. 54, // 50 2
  842. 55, // 51 3
  843. 56, // 52 4
  844. 57, // 53 5
  845. 58, // 54 6
  846. 59, // 55 7
  847. 60, // 56 8
  848. 61, // 57 9
  849. 64, // 58
  850. 64, // 59
  851. 64, // 60
  852. 64, // 61
  853. 64, // 62
  854. 64, // 63
  855. 64, // 64
  856. 0, // 65 A
  857. 1, // 66 B
  858. 2, // 67 C
  859. 3, // 68 D
  860. 4, // 69 E
  861. 5, // 70 F
  862. 6, // 71 G
  863. 7, // 72 H
  864. 8, // 73 I
  865. 9, // 74 J
  866. 10, // 75 K
  867. 11, // 76 L
  868. 12, // 77 M
  869. 13, // 78 N
  870. 14, // 79 O
  871. 15, // 80 P
  872. 16, // 81 Q
  873. 17, // 82 R
  874. 18, // 83 S
  875. 19, // 84 T
  876. 20, // 85 U
  877. 21, // 86 V
  878. 22, // 87 W
  879. 23, // 88 X
  880. 24, // 89 Y
  881. 25, // 90 Z
  882. 64, // 91
  883. 64, // 92
  884. 64, // 93
  885. 64, // 94
  886. 64, // 95
  887. 64, // 96
  888. 26, // 97 a
  889. 27, // 98 b
  890. 28, // 99 c
  891. 29, //100 d
  892. 30, //101 e
  893. 31, //102 f
  894. 32, //103 g
  895. 33, //104 h
  896. 34, //105 i
  897. 35, //106 j
  898. 36, //107 k
  899. 37, //108 l
  900. 38, //109 m
  901. 39, //110 n
  902. 40, //111 o
  903. 41, //112 p
  904. 42, //113 q
  905. 43, //114 r
  906. 44, //115 s
  907. 45, //116 t
  908. 46, //117 u
  909. 47, //118 v
  910. 48, //119 w
  911. 49, //120 x
  912. 50, //121 y
  913. 51, //122 z
  914. 64, //123
  915. 64, //124
  916. 64, //125
  917. 64, //126
  918. 64 //127
  919. };
  920. unsigned i = 0;
  921. unsigned j = 0;
  922. char* zV = (char*)yV;
  923. while( i < xN )
  924. {
  925. unsigned yn = 3;
  926. if( xV[i+3] == '=' )
  927. --yn;
  928. if( xV[i+2] == '=' )
  929. --yn;
  930. unsigned v = 0;
  931. assert( i + 4 <= xN );
  932. v += t[(int)xV[i++]] << 18;
  933. v += t[(int)xV[i++]] << 12;
  934. v += t[(int)xV[i++]] << 6;
  935. v += t[(int)xV[i++]] << 0;
  936. if( j >= yN )
  937. break;
  938. zV[j++] = (v & 0xff0000) >> 16;
  939. if( yn > 1 )
  940. {
  941. if( j >= yN )
  942. break;
  943. zV[j++] = (v & 0x00ff00) >> 8;
  944. }
  945. if( yn > 2 )
  946. {
  947. if( j >= yN )
  948. break;
  949. zV[j++] = (v & 0x0000ff) >> 0;
  950. }
  951. }
  952. return j;
  953. }
  954. unsigned cmTextEncodeBase64BufferByteCount( unsigned binByteCnt )
  955. {
  956. int rem = binByteCnt % 3;
  957. binByteCnt -= rem;
  958. int n = binByteCnt / 3 * 4;
  959. if( rem )
  960. n += 4;
  961. return n;
  962. }
  963. unsigned cmTextEncodeBase64( const void* xV, unsigned xN, char* yV, unsigned yN )
  964. {
  965. const char* t = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  966. const char* zV = (const char*)xV;
  967. unsigned i = 0;
  968. unsigned j = 0;
  969. while( 1 )
  970. {
  971. unsigned k = 3;
  972. unsigned v = ((int)zV[i++]) << 16;
  973. if( i < xN )
  974. v += ((int)zV[i++]) << 8;
  975. else
  976. --k;
  977. if( i < xN )
  978. v += ((int)zV[i++]);
  979. else
  980. --k;
  981. if( j >= yN )
  982. break;
  983. yV[j++] = t[ (v & 0xfc0000) >> 18 ];
  984. if( j >= yN )
  985. break;
  986. yV[j++] = t[ (v & 0x03f000) >> 12 ];
  987. if( j >= yN )
  988. break;
  989. if( k > 1 )
  990. yV[j++] = t[ (v & 0x000fc0) >> 6 ];
  991. else
  992. yV[j++] = '=';
  993. if( j >= yN )
  994. break;
  995. if( k > 2 )
  996. yV[j++] = t[ (v & 0x00003f) >> 0 ];
  997. else
  998. yV[j++] = '=';
  999. }
  1000. return j;
  1001. }