PageRenderTime 63ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/packages/thirdParty/fox/fox-1.6.44/src/FXString.cpp

https://bitbucket.org/lixinyiabc123/newton-dynamics
C++ | 3065 lines | 2323 code | 471 blank | 271 comment | 393 complexity | dcf0462ada5b87e3ee42290aff6aa19f MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, GPL-3.0, 0BSD, LGPL-2.1, LGPL-3.0, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /********************************************************************************
  2. * *
  3. * S t r i n g O b j e c t *
  4. * *
  5. *********************************************************************************
  6. * Copyright (C) 1997,2006 by Jeroen van der Zijp. All Rights Reserved. *
  7. *********************************************************************************
  8. * This library is free software; you can redistribute it and/or *
  9. * modify it under the terms of the GNU Lesser General Public *
  10. * License as published by the Free Software Foundation; either *
  11. * version 2.1 of the License, or (at your option) any later version. *
  12. * *
  13. * This library is distributed in the hope that it will be useful, *
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
  16. * Lesser General Public License for more details. *
  17. * *
  18. * You should have received a copy of the GNU Lesser General Public *
  19. * License along with this library; if not, write to the Free Software *
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
  21. *********************************************************************************
  22. * $Id: FXString.cpp,v 1.218.2.1 2006/08/15 05:03:16 fox Exp $ *
  23. ********************************************************************************/
  24. #include "xincs.h"
  25. #include "fxver.h"
  26. #include "fxdefs.h"
  27. #include "fxascii.h"
  28. #include "fxunicode.h"
  29. #include "FXHash.h"
  30. #include "FXStream.h"
  31. #include "FXString.h"
  32. /*
  33. Notes:
  34. - The special pointer-value null represents an empty "" string.
  35. - Strings are never NULL:- this speeds things up a lot as there is no
  36. need to check for NULL strings anymore.
  37. - In the new representation, '\0' is allowed as a character everywhere; but there
  38. is always an (uncounted) '\0' at the end.
  39. - The length preceeds the text in the buffer.
  40. */
  41. // The string buffer is always rounded to a multiple of ROUNDVAL
  42. // which must be 2^n. Thus, small size changes will not result in any
  43. // actual resizing of the buffer except when ROUNDVAL is exceeded.
  44. #define ROUNDVAL 16
  45. // Round up to nearest ROUNDVAL
  46. #define ROUNDUP(n) (((n)+ROUNDVAL-1)&-ROUNDVAL)
  47. // This will come in handy
  48. #define EMPTY ((FXchar*)&emptystring[1])
  49. using namespace FX;
  50. /*******************************************************************************/
  51. namespace FX {
  52. // For conversion from UTF16 to UTF32
  53. const FXint SURROGATE_OFFSET=0x10000-(0xD800<<10)-0xDC00;
  54. // For conversion of UTF32 to UTF16
  55. const FXint LEAD_OFFSET=0xD800-(0x10000>>10);
  56. // Empty string
  57. static const FXint emptystring[2]={0,0};
  58. // Special NULL string
  59. const FXchar FXString::null[4]={0,0,0,0};
  60. // Numbers for hexadecimal
  61. const FXchar FXString::hex[17]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',0};
  62. const FXchar FXString::HEX[17]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F',0};
  63. // Length of a utf8 character representation
  64. const signed char FXString::utfBytes[256]={
  65. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  66. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  67. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  68. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  69. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  70. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  71. 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  72. 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
  73. };
  74. /*******************************************************************************/
  75. // Length of wide character string
  76. static inline FXint strlen(const FXchar *src){
  77. return ::strlen(src);
  78. }
  79. // Length of wide character string
  80. static inline FXint strlen(const FXwchar *src){
  81. register FXint i=0;
  82. while(src[i]) i++;
  83. return i;
  84. }
  85. // Length of narrow character string
  86. static inline FXint strlen(const FXnchar *src){
  87. register FXint i=0;
  88. while(src[i]) i++;
  89. return i;
  90. }
  91. /*******************************************************************************/
  92. // Return wide character from utf8 string at ptr
  93. FXwchar wc(const FXchar *ptr){
  94. register FXwchar w=(FXuchar)ptr[0];
  95. if(0xC0<=w){ w=(w<<6)^(FXuchar)ptr[1]^0x3080;
  96. if(0x800<=w){ w=(w<<6)^(FXuchar)ptr[2]^0x20080;
  97. if(0x10000<=w){ w=(w<<6)^(FXuchar)ptr[3]^0x400080;
  98. if(0x200000<=w){ w=(w<<6)^(FXuchar)ptr[4]^0x8000080;
  99. if(0x4000000<=w){ w=(w<<6)^(FXuchar)ptr[5]^0x80; }}}}}
  100. return w;
  101. }
  102. // Return wide character from utf16 string at ptr
  103. FXwchar wc(const FXnchar *ptr){
  104. register FXwchar w=ptr[0];
  105. if(0xD800<=w && w<0xDC00){ w=(w<<10)+ptr[1]+SURROGATE_OFFSET; }
  106. return w;
  107. }
  108. // Return number of FXchar's of wide character at ptr
  109. FXint wclen(const FXchar *ptr){
  110. return FXString::utfBytes[(FXuchar)ptr[0]];
  111. }
  112. // Return number of FXnchar's of narrow character at ptr
  113. FXint wclen(const FXnchar *ptr){
  114. return (0xD800<=ptr[0] && ptr[0]<0xDC00) ? 2 : 1;
  115. }
  116. // Return start of utf8 character containing position
  117. FXint wcvalidate(const FXchar* string,FXint pos){
  118. return (pos<=0 || FXISUTF(string[pos]) || --pos<=0 || FXISUTF(string[pos]) || --pos<=0 || FXISUTF(string[pos]) || --pos<=0 || FXISUTF(string[pos]) || --pos<=0 || FXISUTF(string[pos]) || --pos), pos;
  119. }
  120. // Return start of utf16 character containing position
  121. FXint wcvalidate(const FXnchar *string,FXint pos){
  122. return (pos<=0 || !(0xDC00<=string[pos] && string[pos]<=0xDFFF) || --pos), pos;
  123. }
  124. // Advance to next utf8 character start
  125. FXint wcinc(const FXchar* string,FXint pos){
  126. return (string[pos++]==0 || FXISUTF(string[pos]) || string[pos++]==0 || FXISUTF(string[pos]) || string[pos++]==0 || FXISUTF(string[pos]) || string[pos++]==0 || FXISUTF(string[pos]) || string[pos++]==0 || FXISUTF(string[pos]) || ++pos), pos;
  127. }
  128. // Advance to next utf16 character start
  129. FXint wcinc(const FXnchar *string,FXint pos){
  130. return ((0xDC00<=string[++pos] && string[pos]<=0xDFFF) || ++pos),pos;
  131. }
  132. // Retreat to previous utf8 character start
  133. FXint wcdec(const FXchar* string,FXint pos){
  134. return (--pos<=0 || FXISUTF(string[pos]) || --pos<=0 || FXISUTF(string[pos]) || --pos<=0 || FXISUTF(string[pos]) || --pos<=0 || FXISUTF(string[pos]) || --pos<=0 || FXISUTF(string[pos]) || --pos), pos;
  135. }
  136. // Retreat to previous utf16 character start
  137. FXint wcdec(const FXnchar *string,FXint pos){
  138. return (--pos<=0 || !(0xDC00<=string[pos] && string[pos]<=0xDFFF) || --pos), pos;
  139. }
  140. // Return true if valid utf8 character sequence
  141. bool isutfvalid(const FXchar* str){
  142. if((FXuchar)str[0]<0x80) return true;
  143. if((FXuchar)str[0]<0xC0) return false;
  144. if((FXuchar)str[1]<0x80) return false;
  145. if((FXuchar)str[1]>0xBF) return false;
  146. if((FXuchar)str[0]<0xE0) return true;
  147. if((FXuchar)str[2]<0x80) return false;
  148. if((FXuchar)str[2]>0xBF) return false;
  149. if((FXuchar)str[0]<0xF0) return true;
  150. if((FXuchar)str[3]<0x80) return false;
  151. if((FXuchar)str[3]>0xBF) return false;
  152. if((FXuchar)str[0]<0xF8) return true;
  153. if((FXuchar)str[4]<0x80) return false;
  154. if((FXuchar)str[4]>0xBF) return false;
  155. if((FXuchar)str[0]<0xFC) return true;
  156. if((FXuchar)str[5]<0x80) return false;
  157. if((FXuchar)str[5]>0xBF) return false;
  158. return true;
  159. }
  160. // Length of utf8 representation of wide characters string str of length n
  161. FXint utfslen(const FXwchar *str,FXint n){
  162. register FXint len=0;
  163. register FXint p=0;
  164. register FXwchar w;
  165. while(p<n){
  166. w=str[p++];
  167. len++;
  168. if(0x80<=w){ len++;
  169. if(0x800<=w){ len++;
  170. if(0x10000<=w){ len++;
  171. if(0x200000<=w){ len++;
  172. if(0x4000000<=w){ len++; }}}}}
  173. }
  174. return len;
  175. }
  176. // Length of utf8 representation of wide character string str
  177. FXint utfslen(const FXwchar *str){
  178. return utfslen(str,strlen(str));
  179. }
  180. // Length of utf8 representation of narrow characters string str of length n
  181. // Test for surrogates is deferred till code possibly exceeds 0xD800
  182. FXint utfslen(const FXnchar *str,FXint n){
  183. register FXint len=0;
  184. register FXint p=0;
  185. register FXwchar w;
  186. while(p<n){
  187. w=str[p++];
  188. len++;
  189. if(0x80<=w){ len++;
  190. if(0x800<=w){ len++; if(0xD800<=w && w<0xDC00 && p<n){ w=(w<<10)+str[p++]+SURROGATE_OFFSET; }
  191. if(0x10000<=w){ len++;
  192. if(0x200000<=w){ len++;
  193. if(0x4000000<=w){ len++; }}}}}
  194. }
  195. return len;
  196. }
  197. // Length of utf8 representation of narrow characters string str
  198. FXint utfslen(const FXnchar *str){
  199. return utfslen(str,strlen(str));
  200. }
  201. // Length of wide character representation of utf8 string str of length n
  202. FXint wcslen(const FXchar *str,FXint n){
  203. register FXint len=0;
  204. register FXint p=0;
  205. while(p<n){
  206. p+=FXString::utfBytes[(FXuchar)str[p]];
  207. len++;
  208. }
  209. return len;
  210. }
  211. // Length of wide character representation of utf8 string str
  212. FXint wcslen(const FXchar *str){
  213. return wcslen(str,strlen(str));
  214. }
  215. // Length of narrow character representation of utf8 string str of length n
  216. // Assume surrogates are needed if utf8 code is more than 16 bits
  217. FXint ncslen(const FXchar *str,FXint n){
  218. register FXint len=0;
  219. register FXint p=0;
  220. register FXwchar c;
  221. while(p<n){
  222. c=(FXuchar)str[p++];
  223. if(0xC0<=c){ p++;
  224. if(0xE0<=c){ p++;
  225. if(0xF0<=c){ p++;
  226. if(0xF8<=c){ p++;
  227. if(0xFC<=c){ p++; }} len++; }}}
  228. len++;
  229. }
  230. return len;
  231. }
  232. // Length of narrow character representation of utf8 string str
  233. FXint ncslen(const FXchar *str){
  234. return ncslen(str,strlen(str));
  235. }
  236. /*******************************************************************************/
  237. // Copy utf8 string of length n to wide character string dst
  238. FXint utf2wcs(FXwchar *dst,const FXchar *src,FXint n){
  239. register FXint len=0;
  240. register FXint p=0;
  241. register FXwchar w;
  242. while(p<n){
  243. w=(FXuchar)src[p++];
  244. if(0xC0<=w){ w=(w<<6)^(FXuchar)src[p++]^0x3080;
  245. if(0x800<=w){ w=(w<<6)^(FXuchar)src[p++]^0x20080;
  246. if(0x10000<=w){ w=(w<<6)^(FXuchar)src[p++]^0x400080;
  247. if(0x200000<=w){ w=(w<<6)^(FXuchar)src[p++]^0x8000080;
  248. if(0x4000000<=w){ w=(w<<6)^(FXuchar)src[p++]^0x80; }}}}}
  249. dst[len++]=w;
  250. }
  251. return len;
  252. }
  253. // Copy utf8 string to wide character string dst
  254. FXint utf2wcs(FXwchar *dst,const FXchar *src){
  255. return utf2wcs(dst,src,strlen(src)+1);
  256. }
  257. // Copy utf8 string of length n to narrow character string dst
  258. // Assume surrogates are needed if utf8 code is more than 16 bits
  259. FXint utf2ncs(FXnchar *dst,const FXchar *src,FXint n){
  260. register FXint len=0;
  261. register FXint p=0;
  262. register FXwchar w;
  263. while(p<n){
  264. w=(FXuchar)src[p++];
  265. if(0xC0<=w){ w=(w<<6)^(FXuchar)src[p++]^0x3080;
  266. if(0x800<=w){ w=(w<<6)^(FXuchar)src[p++]^0x20080;
  267. if(0x10000<=w){ w=(w<<6)^(FXuchar)src[p++]^0x400080;
  268. if(0x200000<=w){ w=(w<<6)^(FXuchar)src[p++]^0x8000080;
  269. if(0x4000000<=w){ w=(w<<6)^(FXuchar)src[p++]^0x80; }} dst[len++]=(w>>10)+LEAD_OFFSET; w=(w&0x3FF)+0xDC00; }}}
  270. dst[len++]=w;
  271. }
  272. return len;
  273. }
  274. // Copy utf8 string to narrow character string dst
  275. FXint utf2ncs(FXnchar *dst,const FXchar *src){
  276. return utf2ncs(dst,src,strlen(src)+1);
  277. }
  278. /*******************************************************************************/
  279. // Copy wide character substring of length n to dst
  280. FXint wc2utfs(FXchar* dst,const FXwchar *src,FXint n){
  281. register FXint len=0;
  282. register FXint p=0;
  283. register FXwchar w;
  284. while(p<n){
  285. w=src[p++];
  286. if(w<0x80){
  287. dst[len++]=w;
  288. continue;
  289. }
  290. if(w<0x800){
  291. dst[len++]=(w>>6)|0xC0;
  292. dst[len++]=(w&0x3F)|0x80;
  293. continue;
  294. }
  295. if(w<0x10000){
  296. dst[len++]=(w>>12)|0xE0;
  297. dst[len++]=((w>>6)&0x3F)|0x80;
  298. dst[len++]=(w&0x3F)|0x80;
  299. continue;
  300. }
  301. if(w<0x200000){
  302. dst[len++]=(w>>18)|0xF0;
  303. dst[len++]=((w>>12)&0x3F)|0x80;
  304. dst[len++]=((w>>6)&0x3F)|0x80;
  305. dst[len++]=(w&0x3F)|0x80;
  306. continue;
  307. }
  308. if(w<0x4000000){
  309. dst[len++]=(w>>24)|0xF8;
  310. dst[len++]=((w>>18)&0x3F)|0x80;
  311. dst[len++]=((w>>12)&0x3F)|0x80;
  312. dst[len++]=((w>>6)&0x3F)|0x80;
  313. dst[len++]=(w&0x3F)|0x80;
  314. continue;
  315. }
  316. dst[len++]=(w>>30)|0xFC;
  317. dst[len++]=((w>>24)&0X3F)|0x80;
  318. dst[len++]=((w>>18)&0X3F)|0x80;
  319. dst[len++]=((w>>12)&0X3F)|0x80;
  320. dst[len++]=((w>>6)&0X3F)|0x80;
  321. dst[len++]=(w&0X3F)|0x80;
  322. }
  323. return len;
  324. }
  325. // Copy wide character string to dst
  326. FXint wc2utfs(FXchar* dst,const FXwchar *src){
  327. return wc2utfs(dst,src,strlen(src)+1);
  328. }
  329. // Copy narrow character substring of length n to dst
  330. // Test for surrogates is deferred till code possibly exceeds 0xD800
  331. FXint nc2utfs(FXchar* dst,const FXnchar *src,FXint n){
  332. register FXint len=0;
  333. register FXint p=0;
  334. register FXwchar w;
  335. while(p<n){
  336. w=src[p++];
  337. if(w<0x80){
  338. dst[len++]=w;
  339. continue;
  340. }
  341. if(w<0x800){
  342. dst[len++]=(w>>6)|0xC0;
  343. dst[len++]=(w&0x3F)|0x80;
  344. continue;
  345. }
  346. if(0xD800<=w && w<0xDC00 && p<n){ w=(w<<10)+src[p++]+SURROGATE_OFFSET; }
  347. if(w<0x10000){
  348. dst[len++]=(w>>12)|0xE0;
  349. dst[len++]=((w>>6)&0x3F)|0x80;
  350. dst[len++]=(w&0x3F)|0x80;
  351. continue;
  352. }
  353. if(w<0x200000){
  354. dst[len++]=(w>>18)|0xF0;
  355. dst[len++]=((w>>12)&0x3F)|0x80;
  356. dst[len++]=((w>>6)&0x3F)|0x80;
  357. dst[len++]=(w&0x3F)|0x80;
  358. continue;
  359. }
  360. if(w<0x4000000){
  361. dst[len++]=(w>>24)|0xF8;
  362. dst[len++]=((w>>18)&0x3F)|0x80;
  363. dst[len++]=((w>>12)&0x3F)|0x80;
  364. dst[len++]=((w>>6)&0x3F)|0x80;
  365. dst[len++]=(w&0x3F)|0x80;
  366. continue;
  367. }
  368. dst[len++]=(w>>30)|0xFC;
  369. dst[len++]=((w>>24)&0X3F)|0x80;
  370. dst[len++]=((w>>18)&0X3F)|0x80;
  371. dst[len++]=((w>>12)&0X3F)|0x80;
  372. dst[len++]=((w>>6)&0X3F)|0x80;
  373. dst[len++]=(w&0X3F)|0x80;
  374. }
  375. return len;
  376. }
  377. // Copy narrow character string to dst
  378. FXint nc2utfs(FXchar* dst,const FXnchar *src){
  379. return nc2utfs(dst,src,strlen(src)+1);
  380. }
  381. /*******************************************************************************/
  382. // Change the length of the string to len
  383. void FXString::length(FXint len){
  384. if(*(((FXint*)str)-1)!=len){
  385. if(0<len){
  386. if(str==EMPTY)
  387. str=sizeof(FXint)+(FXchar*)malloc(ROUNDUP(1+len)+sizeof(FXint));
  388. else
  389. str=sizeof(FXint)+(FXchar*)realloc(str-sizeof(FXint),ROUNDUP(1+len)+sizeof(FXint));
  390. str[len]=0;
  391. *(((FXint*)str)-1)=len;
  392. }
  393. else if(str!=EMPTY){
  394. free(str-sizeof(FXint));
  395. str=EMPTY;
  396. }
  397. }
  398. }
  399. // Return start of utf8 character containing position
  400. FXint FXString::validate(FXint p) const { return wcvalidate(str,p); }
  401. // Advance to next utf8 character start
  402. FXint FXString::inc(FXint p) const { return wcinc(str,p); }
  403. // Retreat to previous utf8 character start
  404. FXint FXString::dec(FXint p) const { return wcdec(str,p); }
  405. // Return wide character starting at offset i
  406. FXwchar FXString::wc(FXint i) const {
  407. register FXwchar w=(FXuchar)str[i];
  408. if(0xC0<=w){ w=(w<<6)^(FXuchar)str[i+1]^0x3080;
  409. if(0x800<=w){ w=(w<<6)^(FXuchar)str[i+2]^0x20080;
  410. if(0x10000<=w){ w=(w<<6)^(FXuchar)str[i+3]^0x400080;
  411. if(0x200000<=w){ w=(w<<6)^(FXuchar)str[i+4]^0x8000080;
  412. if(0x4000000<=w){ w=(w<<6)^(FXuchar)str[i+5]^0x80; }}}}}
  413. return w;
  414. }
  415. // Count number of utf8 characters in subrange
  416. FXint FXString::count(FXint pos,FXint len) const {
  417. register FXint cnt=0;
  418. while(pos<len){
  419. pos+=utfBytes[(FXuchar)str[pos]];
  420. cnt++;
  421. }
  422. return cnt;
  423. }
  424. // Count number of utf8 characters
  425. FXint FXString::count() const {
  426. return count(0,length());
  427. }
  428. // Return index of utf8 character at byte offset
  429. FXint FXString::index(FXint offs) const {
  430. register FXint len=length();
  431. register FXint i=0;
  432. register FXint p=0;
  433. while(p<offs && p<len){
  434. p+=utfBytes[(FXuchar)str[p]];
  435. i++;
  436. }
  437. return i;
  438. }
  439. // Return byte offset of utf8 character at index
  440. FXint FXString::offset(FXint indx) const {
  441. register FXint len=length();
  442. register FXint i=0;
  443. register FXint p=0;
  444. while(i<indx && p<len){
  445. p+=utfBytes[(FXuchar)str[p]];
  446. i++;
  447. }
  448. return p;
  449. }
  450. // Simple construct
  451. FXString::FXString():str(EMPTY){
  452. }
  453. // Copy construct
  454. FXString::FXString(const FXString& s):str(EMPTY){
  455. register FXint n=s.length();
  456. if(0<n){
  457. length(n);
  458. memcpy(str,s.str,n);
  459. }
  460. }
  461. // Construct and init
  462. FXString::FXString(const FXchar* s):str(EMPTY){
  463. if(s && s[0]){
  464. register FXint n=strlen(s);
  465. length(n);
  466. memcpy(str,s,n);
  467. }
  468. }
  469. // Construct and init
  470. FXString::FXString(const FXwchar* s):str(EMPTY){
  471. if(s && s[0]){
  472. register FXint n=utfslen(s);
  473. length(n);
  474. wc2utfs(str,s);
  475. }
  476. }
  477. // Construct and init
  478. FXString::FXString(const FXnchar* s):str(EMPTY){
  479. if(s && s[0]){
  480. register FXint n=utfslen(s);
  481. length(n);
  482. nc2utfs(str,s);
  483. }
  484. }
  485. // Construct and init with substring
  486. FXString::FXString(const FXchar* s,FXint n):str(EMPTY){
  487. if(s && 0<n){
  488. length(n);
  489. memcpy(str,s,n);
  490. }
  491. }
  492. // Construct and init with wide character substring
  493. FXString::FXString(const FXwchar* s,FXint m):str(EMPTY){
  494. if(s && 0<m){
  495. register FXint n=utfslen(s,m);
  496. length(n);
  497. wc2utfs(str,s,m);
  498. }
  499. }
  500. // Construct and init with narrow character substring
  501. FXString::FXString(const FXnchar* s,FXint m):str(EMPTY){
  502. if(s && 0<m){
  503. register FXint n=utfslen(s,m);
  504. length(n);
  505. nc2utfs(str,s,m);
  506. }
  507. }
  508. // Construct and fill with constant
  509. FXString::FXString(FXchar c,FXint n):str(EMPTY){
  510. if(0<n){
  511. length(n);
  512. memset(str,c,n);
  513. }
  514. }
  515. // Return partition of string separated by delimiter delim
  516. FXString FXString::section(FXchar delim,FXint start,FXint num) const {
  517. register FXint len=length(),s,e;
  518. s=0;
  519. if(0<start){
  520. while(s<len){
  521. ++s;
  522. if(str[s-1]==delim && --start==0) break;
  523. }
  524. }
  525. e=s;
  526. if(0<num){
  527. while(e<len){
  528. if(str[e]==delim && --num==0) break;
  529. ++e;
  530. }
  531. }
  532. return FXString(str+s,e-s);
  533. }
  534. // Return partition of string separated by delimiters in delim
  535. FXString FXString::section(const FXchar* delim,FXint n,FXint start,FXint num) const {
  536. register FXint len=length(),s,e,i;
  537. register FXchar c;
  538. s=0;
  539. if(0<start){
  540. while(s<len){
  541. c=str[s++];
  542. i=n;
  543. while(--i>=0){
  544. if(delim[i]==c){
  545. if(--start==0) goto a;
  546. break;
  547. }
  548. }
  549. }
  550. }
  551. a:e=s;
  552. if(0<num){
  553. while(e<len){
  554. c=str[e];
  555. i=n;
  556. while(--i>=0){
  557. if(delim[i]==c){
  558. if(--num==0) goto b;
  559. break;
  560. }
  561. }
  562. ++e;
  563. }
  564. }
  565. b:return FXString(str+s,e-s);
  566. }
  567. // Return partition of string separated by delimiters in delim
  568. FXString FXString::section(const FXchar* delim,FXint start,FXint num) const {
  569. return section(delim,strlen(delim),start,num);
  570. }
  571. // Return partition of string separated by delimiters in delim
  572. FXString FXString::section(const FXString& delim,FXint start,FXint num) const {
  573. return section(delim.text(),delim.length(),start,num);
  574. }
  575. // Adopt string s, leaving s empty
  576. FXString& FXString::adopt(FXString& s){
  577. if(this!=&s){
  578. if(str!=EMPTY){ free(str-sizeof(FXint)); }
  579. str=s.str;
  580. s.str=EMPTY;
  581. }
  582. return *this;
  583. }
  584. // Assign input character to this string
  585. FXString& FXString::assign(FXchar c){
  586. length(1);
  587. str[0]=c;
  588. return *this;
  589. }
  590. // Assign input n characters c to this string
  591. FXString& FXString::assign(FXchar c,FXint n){
  592. length(n);
  593. memset(str,c,n);
  594. return *this;
  595. }
  596. // Assign first n characters of input string to this string
  597. FXString& FXString::assign(const FXchar* s,FXint n){
  598. if(s && 0<n){
  599. length(n);
  600. memmove(str,s,n);
  601. }
  602. else{
  603. length(0);
  604. }
  605. return *this;
  606. }
  607. // Assign first n characters of wide character string s to this string
  608. FXString& FXString::assign(const FXwchar* s,FXint m){
  609. if(s && 0<m){
  610. register FXint n=utfslen(s,m);
  611. length(n);
  612. wc2utfs(str,s,m);
  613. }
  614. else{
  615. length(0);
  616. }
  617. return *this;
  618. }
  619. // Assign first n characters of narrow character string s to this string
  620. FXString& FXString::assign(const FXnchar* s,FXint m){
  621. if(s && 0<m){
  622. register FXint n=utfslen(s,m);
  623. length(n);
  624. nc2utfs(str,s,m);
  625. }
  626. else{
  627. length(0);
  628. }
  629. return *this;
  630. }
  631. // Assign input string to this string
  632. FXString& FXString::assign(const FXchar* s){
  633. if(s && s[0]){
  634. register FXint n=strlen(s);
  635. length(n);
  636. memmove(str,s,n);
  637. }
  638. else{
  639. length(0);
  640. }
  641. return *this;
  642. }
  643. // Assign wide character string s to this string
  644. FXString& FXString::assign(const FXwchar* s){
  645. if(s && s[0]){
  646. register FXint n=utfslen(s);
  647. length(n);
  648. wc2utfs(str,s);
  649. }
  650. else{
  651. length(0);
  652. }
  653. return *this;
  654. }
  655. // Assign narrow character string s to this string
  656. FXString& FXString::assign(const FXnchar* s){
  657. if(s && s[0]){
  658. register FXint n=utfslen(s);
  659. length(n);
  660. nc2utfs(str,s);
  661. }
  662. else{
  663. length(0);
  664. }
  665. return *this;
  666. }
  667. // Assign input string to this string
  668. FXString& FXString::assign(const FXString& s){
  669. if(str!=s.str) assign(s.str,s.length());
  670. return *this;
  671. }
  672. // Assign a string
  673. FXString& FXString::operator=(const FXchar* s){
  674. return assign(s);
  675. }
  676. // Assign a wide character string to this
  677. FXString& FXString::operator=(const FXwchar* s){
  678. return assign(s);
  679. }
  680. // Assign a narrow character string to this
  681. FXString& FXString::operator=(const FXnchar* s){
  682. return assign(s);
  683. }
  684. // Assignment
  685. FXString& FXString::operator=(const FXString& s){
  686. if(str!=s.str) assign(s.str,s.length());
  687. return *this;
  688. }
  689. // Insert character at position
  690. FXString& FXString::insert(FXint pos,FXchar c){
  691. register FXint len=length();
  692. length(len+1);
  693. if(pos<=0){
  694. memmove(str+1,str,len);
  695. str[0]=c;
  696. }
  697. else if(pos>=len){
  698. str[len]=c;
  699. }
  700. else{
  701. memmove(str+pos+1,str+pos,len-pos);
  702. str[pos]=c;
  703. }
  704. return *this;
  705. }
  706. // Insert n characters c at specified position
  707. FXString& FXString::insert(FXint pos,FXchar c,FXint n){
  708. if(0<n){
  709. register FXint len=length();
  710. length(len+n);
  711. if(pos<=0){
  712. memmove(str+n,str,len);
  713. memset(str,c,n);
  714. }
  715. else if(pos>=len){
  716. memset(str+len,c,n);
  717. }
  718. else{
  719. memmove(str+pos+n,str+pos,len-pos);
  720. memset(str+pos,c,n);
  721. }
  722. }
  723. return *this;
  724. }
  725. // Insert string at position
  726. FXString& FXString::insert(FXint pos,const FXchar* s,FXint n){
  727. if(s && 0<n){
  728. register FXint len=length();
  729. length(len+n);
  730. if(pos<=0){
  731. memmove(str+n,str,len);
  732. memcpy(str,s,n);
  733. }
  734. else if(pos>=len){
  735. memcpy(str+len,s,n);
  736. }
  737. else{
  738. memmove(str+pos+n,str+pos,len-pos);
  739. memcpy(str+pos,s,n);
  740. }
  741. }
  742. return *this;
  743. }
  744. // Insert wide character string at position
  745. FXString& FXString::insert(FXint pos,const FXwchar* s,FXint m){
  746. if(s && 0<m){
  747. register FXint len=length();
  748. register FXint n=utfslen(s,m);
  749. length(len+n);
  750. if(pos<=0){
  751. memmove(str+n,str,len);
  752. wc2utfs(str,s,m);
  753. }
  754. else if(pos>=len){
  755. wc2utfs(str+len,s,m);
  756. }
  757. else{
  758. memmove(str+pos+n,str+pos,len-pos);
  759. wc2utfs(str+pos,s,m);
  760. }
  761. }
  762. return *this;
  763. }
  764. // Insert narrow character string at position
  765. FXString& FXString::insert(FXint pos,const FXnchar* s,FXint m){
  766. if(s && 0<m){
  767. register FXint len=length();
  768. register FXint n=utfslen(s,m);
  769. length(len+n);
  770. if(pos<=0){
  771. memmove(str+n,str,len);
  772. nc2utfs(str,s,m);
  773. }
  774. else if(pos>=len){
  775. nc2utfs(str+len,s,m);
  776. }
  777. else{
  778. memmove(str+pos+n,str+pos,len-pos);
  779. nc2utfs(str+pos,s,m);
  780. }
  781. }
  782. return *this;
  783. }
  784. // Insert string at position
  785. FXString& FXString::insert(FXint pos,const FXchar* s){
  786. if(s && s[0]){
  787. register FXint len=length();
  788. register FXint n=strlen(s);
  789. length(len+n);
  790. if(pos<=0){
  791. memmove(str+n,str,len);
  792. memcpy(str,s,n);
  793. }
  794. else if(pos>=len){
  795. memcpy(str+len,s,n);
  796. }
  797. else{
  798. memmove(str+pos+n,str+pos,len-pos);
  799. memcpy(str+pos,s,n);
  800. }
  801. }
  802. return *this;
  803. }
  804. // Insert wide character string at position
  805. FXString& FXString::insert(FXint pos,const FXwchar* s){
  806. if(s && s[0]){
  807. register FXint len=length();
  808. register FXint n=utfslen(s);
  809. length(len+n);
  810. if(pos<=0){
  811. memmove(str+n,str,len);
  812. wc2utfs(str,s);
  813. }
  814. else if(pos>=len){
  815. wc2utfs(str+len,s);
  816. }
  817. else{
  818. memmove(str+pos+n,str+pos,len-pos);
  819. wc2utfs(str+pos,s);
  820. }
  821. }
  822. return *this;
  823. }
  824. // Insert narrow character string at position
  825. FXString& FXString::insert(FXint pos,const FXnchar* s){
  826. if(s && s[0]){
  827. register FXint len=length();
  828. register FXint n=utfslen(s);
  829. length(len+n);
  830. if(pos<=0){
  831. memmove(str+n,str,len);
  832. nc2utfs(str,s);
  833. }
  834. else if(pos>=len){
  835. nc2utfs(str+len,s);
  836. }
  837. else{
  838. memmove(str+pos+n,str+pos,len-pos);
  839. nc2utfs(str+pos,s);
  840. }
  841. }
  842. return *this;
  843. }
  844. // Insert string at position
  845. FXString& FXString::insert(FXint pos,const FXString& s){
  846. return insert(pos,s.str,s.length());
  847. }
  848. // Append character c to this string
  849. FXString& FXString::append(FXchar c){
  850. register FXint len=length();
  851. length(len+1);
  852. str[len]=c;
  853. return *this;
  854. }
  855. // Append n characters c to this string
  856. FXString& FXString::append(FXchar c,FXint n){
  857. if(0<n){
  858. register FXint len=length();
  859. length(len+n);
  860. memset(str+len,c,n);
  861. }
  862. return *this;
  863. }
  864. // Append string to this string
  865. FXString& FXString::append(const FXchar* s,FXint n){
  866. if(s && 0<n){
  867. register FXint len=length();
  868. length(len+n);
  869. memcpy(str+len,s,n);
  870. }
  871. return *this;
  872. }
  873. // Append string to this string
  874. FXString& FXString::append(const FXwchar* s,FXint m){
  875. if(s && 0<m){
  876. register FXint len=length();
  877. register FXint n=utfslen(s,m);
  878. length(len+n);
  879. wc2utfs(str+len,s,m);
  880. }
  881. return *this;
  882. }
  883. // Append string to this string
  884. FXString& FXString::append(const FXnchar* s,FXint m){
  885. if(s && 0<m){
  886. register FXint len=length();
  887. register FXint n=utfslen(s,m);
  888. length(len+n);
  889. nc2utfs(str+len,s,m);
  890. }
  891. return *this;
  892. }
  893. // Append string to this string
  894. FXString& FXString::append(const FXchar* s){
  895. if(s && s[0]){
  896. register FXint len=length();
  897. register FXint n=strlen(s);
  898. length(len+n);
  899. memcpy(str+len,s,n);
  900. }
  901. return *this;
  902. }
  903. // Append string to this string
  904. FXString& FXString::append(const FXwchar* s){
  905. if(s && s[0]){
  906. register FXint len=length();
  907. register FXint n=utfslen(s);
  908. length(len+n);
  909. wc2utfs(str+len,s);
  910. }
  911. return *this;
  912. }
  913. // Append string to this string
  914. FXString& FXString::append(const FXnchar* s){
  915. if(s && s[0]){
  916. register FXint len=length();
  917. register FXint n=utfslen(s);
  918. length(len+n);
  919. nc2utfs(str+len,s);
  920. }
  921. return *this;
  922. }
  923. // Append string to this string
  924. FXString& FXString::append(const FXString& s){
  925. return append(s.str,s.length());
  926. }
  927. // Append character
  928. FXString& FXString::operator+=(FXchar c){
  929. return append(c);
  930. }
  931. // Append string
  932. FXString& FXString::operator+=(const FXchar* s){
  933. return append(s);
  934. }
  935. // Append string
  936. FXString& FXString::operator+=(const FXwchar* s){
  937. return append(s);
  938. }
  939. // Append string
  940. FXString& FXString::operator+=(const FXnchar* s){
  941. return append(s);
  942. }
  943. // Append FXString
  944. FXString& FXString::operator+=(const FXString& s){
  945. return append(s);
  946. }
  947. // Prepend character
  948. FXString& FXString::prepend(FXchar c){
  949. register FXint len=length();
  950. length(len+1);
  951. memmove(str+1,str,len);
  952. str[0]=c;
  953. return *this;
  954. }
  955. // Prepend string with n characters c
  956. FXString& FXString::prepend(FXchar c,FXint n){
  957. if(0<n){
  958. register FXint len=length();
  959. length(len+n);
  960. memmove(str+n,str,len);
  961. memset(str,c,n);
  962. }
  963. return *this;
  964. }
  965. // Prepend string
  966. FXString& FXString::prepend(const FXchar* s,FXint n){
  967. if(s && 0<n){
  968. register FXint len=length();
  969. length(len+n);
  970. memmove(str+n,str,len);
  971. memcpy(str,s,n);
  972. }
  973. return *this;
  974. }
  975. // Prepend wide character string
  976. FXString& FXString::prepend(const FXwchar* s,FXint m){
  977. if(s && 0<m){
  978. register FXint len=length();
  979. register FXint n=utfslen(s,m);
  980. length(len+n);
  981. memmove(str+n,str,len);
  982. wc2utfs(str,s,m);
  983. }
  984. return *this;
  985. }
  986. // Prepend narrow character string
  987. FXString& FXString::prepend(const FXnchar* s,FXint m){
  988. if(s && 0<m){
  989. register FXint len=length();
  990. register FXint n=utfslen(s,m);
  991. length(len+n);
  992. memmove(str+n,str,len);
  993. nc2utfs(str,s,m);
  994. }
  995. return *this;
  996. }
  997. // Prepend string
  998. FXString& FXString::prepend(const FXchar* s){
  999. if(s && s[0]){
  1000. register FXint len=length();
  1001. register FXint n=strlen(s);
  1002. length(len+n);
  1003. memmove(str+n,str,len);
  1004. memcpy(str,s,n);
  1005. }
  1006. return *this;
  1007. }
  1008. // Prepend wide character string
  1009. FXString& FXString::prepend(const FXwchar* s){
  1010. if(s && s[0]){
  1011. register FXint len=length();
  1012. register FXint n=utfslen(s);
  1013. length(len+n);
  1014. memmove(str+n,str,len);
  1015. wc2utfs(str,s);
  1016. }
  1017. return *this;
  1018. }
  1019. // Prepend narrow character string
  1020. FXString& FXString::prepend(const FXnchar* s){
  1021. if(s && s[0]){
  1022. register FXint len=length();
  1023. register FXint n=utfslen(s);
  1024. length(len+n);
  1025. memmove(str+n,str,len);
  1026. nc2utfs(str,s);
  1027. }
  1028. return *this;
  1029. }
  1030. // Prepend string
  1031. FXString& FXString::prepend(const FXString& s){
  1032. return prepend(s.str,s.length());
  1033. }
  1034. // Replace character in string
  1035. FXString& FXString::replace(FXint pos,FXchar c){
  1036. register FXint len=length();
  1037. if(pos<0){
  1038. length(len+1);
  1039. memmove(str+1,str,len);
  1040. str[0]=c;
  1041. }
  1042. else if(pos>=len){
  1043. length(len+1);
  1044. str[len]=c;
  1045. }
  1046. else{
  1047. str[pos]=c;
  1048. }
  1049. return *this;
  1050. }
  1051. // Replace the m characters at pos with n characters c
  1052. FXString& FXString::replace(FXint pos,FXint m,FXchar c,FXint n){
  1053. register FXint len=length();
  1054. if(pos<0){
  1055. m+=pos;
  1056. if(m<0) m=0;
  1057. pos=0;
  1058. }
  1059. if(pos+m>len){
  1060. if(pos>len) pos=len;
  1061. m=len-pos;
  1062. }
  1063. if(m<n){
  1064. length(len+n-m);
  1065. memmove(str+pos+n,str+pos+m,len-pos-m);
  1066. }
  1067. else if(m>n){
  1068. memmove(str+pos+n,str+pos+m,len-pos-m);
  1069. length(len+n-m);
  1070. }
  1071. memset(str+pos,c,n);
  1072. return *this;
  1073. }
  1074. // Replace part of string
  1075. FXString& FXString::replace(FXint pos,FXint m,const FXchar* s,FXint n){
  1076. register FXint len=length();
  1077. if(pos<0){
  1078. m+=pos;
  1079. if(m<0) m=0;
  1080. pos=0;
  1081. }
  1082. if(pos+m>len){
  1083. if(pos>len) pos=len;
  1084. m=len-pos;
  1085. }
  1086. if(m<n){
  1087. length(len+n-m);
  1088. memmove(str+pos+n,str+pos+m,len-pos-m);
  1089. }
  1090. else if(m>n){
  1091. memmove(str+pos+n,str+pos+m,len-pos-m);
  1092. length(len+n-m);
  1093. }
  1094. memcpy(str+pos,s,n);
  1095. return *this;
  1096. }
  1097. // Replace part of wide character string
  1098. FXString& FXString::replace(FXint pos,FXint m,const FXwchar* s,FXint n){
  1099. register FXint w=utfslen(s,n);
  1100. register FXint len=length();
  1101. if(pos<0){
  1102. m+=pos;
  1103. if(m<0) m=0;
  1104. pos=0;
  1105. }
  1106. if(pos+m>len){
  1107. if(pos>len) pos=len;
  1108. m=len-pos;
  1109. }
  1110. if(m<w){
  1111. length(len+w-m);
  1112. memmove(str+pos+w,str+pos+m,len-pos-m);
  1113. }
  1114. else if(m>w){
  1115. memmove(str+pos+w,str+pos+m,len-pos-m);
  1116. length(len+w-m);
  1117. }
  1118. wc2utfs(str+pos,s,n);
  1119. return *this;
  1120. }
  1121. // Replace part of narrow character string
  1122. FXString& FXString::replace(FXint pos,FXint m,const FXnchar* s,FXint n){
  1123. register FXint w=utfslen(s,n);
  1124. register FXint len=length();
  1125. if(pos<0){
  1126. m+=pos;
  1127. if(m<0) m=0;
  1128. pos=0;
  1129. }
  1130. if(pos+m>len){
  1131. if(pos>len) pos=len;
  1132. m=len-pos;
  1133. }
  1134. if(m<w){
  1135. length(len+w-m);
  1136. memmove(str+pos+w,str+pos+m,len-pos-m);
  1137. }
  1138. else if(m>w){
  1139. memmove(str+pos+w,str+pos+m,len-pos-m);
  1140. length(len+w-m);
  1141. }
  1142. nc2utfs(str+pos,s,n);
  1143. return *this;
  1144. }
  1145. // Replace part of string
  1146. FXString& FXString::replace(FXint pos,FXint m,const FXchar* s){
  1147. return replace(pos,m,s,strlen(s));
  1148. }
  1149. // Replace part of string
  1150. FXString& FXString::replace(FXint pos,FXint m,const FXwchar* s){
  1151. return replace(pos,m,s,strlen(s));
  1152. }
  1153. // Replace part of string
  1154. FXString& FXString::replace(FXint pos,FXint m,const FXnchar* s){
  1155. return replace(pos,m,s,strlen(s));
  1156. }
  1157. // Replace part of string
  1158. FXString& FXString::replace(FXint pos,FXint m,const FXString& s){
  1159. return replace(pos,m,s.str,s.length());
  1160. }
  1161. // Move range of m characters from src position to dst position
  1162. FXString& FXString::move(FXint dst,FXint src,FXint n){
  1163. register FXint len=length();
  1164. if(0<n && 0<=src && src+n<=len){
  1165. if(dst<0){ // Move below begin
  1166. if(dst<-n) dst=-n;
  1167. length(len-dst);
  1168. memmove(str-dst,str,len);
  1169. memmove(str,str-dst+src,n);
  1170. }
  1171. else if(dst+n>len){ // Move beyond end
  1172. if(dst>len) dst=len;
  1173. length(dst+n);
  1174. memmove(str+dst,str+src,n);
  1175. }
  1176. else{
  1177. memmove(str+dst,str+src,n); // Move inside
  1178. }
  1179. }
  1180. return *this;
  1181. }
  1182. // Remove one character
  1183. FXString& FXString::erase(FXint pos){
  1184. register FXint len=length();
  1185. if(0<=pos && pos<len){
  1186. memmove(str+pos,str+pos+1,len-pos-1);
  1187. length(len-1);
  1188. }
  1189. return *this;
  1190. }
  1191. // Remove section from buffer
  1192. FXString& FXString::erase(FXint pos,FXint n){
  1193. if(0<n){
  1194. register FXint len=length();
  1195. if(pos<len && pos+n>0){
  1196. if(pos<0){n+=pos;pos=0;}
  1197. if(pos+n>len){n=len-pos;}
  1198. memmove(str+pos,str+pos+n,len-pos-n);
  1199. length(len-n);
  1200. }
  1201. }
  1202. return *this;
  1203. }
  1204. // Return number of occurrences of ch in string
  1205. FXint FXString::contains(FXchar ch) const {
  1206. register FXint len=length();
  1207. register FXint c=ch;
  1208. register FXint m=0;
  1209. register FXint i=0;
  1210. while(i<len){
  1211. if(str[i]==c){
  1212. m++;
  1213. }
  1214. i++;
  1215. }
  1216. return m;
  1217. }
  1218. // Return number of occurrences of string sub in string
  1219. FXint FXString::contains(const FXchar* sub,FXint n) const {
  1220. register FXint len=length()-n;
  1221. register FXint m=0;
  1222. register FXint i=0;
  1223. while(i<=len){
  1224. if(compare(str+i,sub,n)==0){
  1225. m++;
  1226. }
  1227. i++;
  1228. }
  1229. return m;
  1230. }
  1231. // Return number of occurrences of string sub in string
  1232. FXint FXString::contains(const FXchar* sub) const {
  1233. return contains(sub,strlen(sub));
  1234. }
  1235. // Return number of occurrences of string sub in string
  1236. FXint FXString::contains(const FXString& sub) const {
  1237. return contains(sub.text(),sub.length());
  1238. }
  1239. // Concatenate two FXStrings
  1240. FXString operator+(const FXString& s1,const FXString& s2){
  1241. FXString result(s1);
  1242. return result.append(s2);
  1243. }
  1244. // Concatenate FXString and string
  1245. FXString operator+(const FXString& s1,const FXchar* s2){
  1246. FXString result(s1);
  1247. return result.append(s2);
  1248. }
  1249. // Concatenate FXString and wide character string
  1250. FXString operator+(const FXString& s1,const FXwchar* s2){
  1251. FXString result(s1);
  1252. return result.append(s2);
  1253. }
  1254. // Concatenate FXString and narrow character string
  1255. FXString operator+(const FXString& s1,const FXnchar* s2){
  1256. FXString result(s1);
  1257. return result.append(s2);
  1258. }
  1259. // Concatenate string and FXString
  1260. FXString operator+(const FXchar* s1,const FXString& s2){
  1261. FXString result(s1);
  1262. return result.append(s2);
  1263. }
  1264. // Concatenate wide character string and FXString
  1265. FXString operator+(const FXwchar* s1,const FXString& s2){
  1266. FXString result(s1);
  1267. return result.append(s2);
  1268. }
  1269. // Concatenate narrow character string and FXString
  1270. FXString operator+(const FXnchar* s1,const FXString& s2){
  1271. FXString result(s1);
  1272. return result.append(s2);
  1273. }
  1274. // Concatenate FXString and character
  1275. FXString operator+(const FXString& s,FXchar c){
  1276. FXString result(s);
  1277. return result.append(c);
  1278. }
  1279. // Concatenate character and FXString
  1280. FXString operator+(FXchar c,const FXString& s){
  1281. FXString result(&c,1);
  1282. return result.append(s);
  1283. }
  1284. // Substitute one character by another
  1285. FXString& FXString::substitute(FXchar org,FXchar sub,bool all){
  1286. register FXint len=length();
  1287. register FXint c=org;
  1288. register FXint s=sub;
  1289. register FXint i=0;
  1290. while(i<len){
  1291. if(str[i]==c){
  1292. str[i]=s;
  1293. if(!all) break;
  1294. }
  1295. i++;
  1296. }
  1297. return *this;
  1298. }
  1299. // Substitute one string by another
  1300. FXString& FXString::substitute(const FXchar* org,FXint olen,const FXchar* rep,FXint rlen,bool all){
  1301. if(0<olen){
  1302. register FXint pos=0;
  1303. while(pos<=length()-olen){
  1304. if(compare(str+pos,org,olen)==0){
  1305. replace(pos,olen,rep,rlen);
  1306. if(!all) break;
  1307. pos+=rlen;
  1308. continue;
  1309. }
  1310. pos++;
  1311. }
  1312. }
  1313. return *this;
  1314. }
  1315. // Substitute one string by another
  1316. FXString& FXString::substitute(const FXchar* org,const FXchar* rep,bool all){
  1317. return substitute(org,strlen(org),rep,strlen(rep),all);
  1318. }
  1319. // Substitute one string by another
  1320. FXString& FXString::substitute(const FXString& org,const FXString& rep,bool all){
  1321. return substitute(org.text(),org.length(),rep.text(),rep.length(),all);
  1322. }
  1323. // Simplify whitespace in string
  1324. FXString& FXString::simplify(){
  1325. if(str!=EMPTY){
  1326. register FXint s=0;
  1327. register FXint d=0;
  1328. register FXint e=length();
  1329. while(s<e && Ascii::isSpace(str[s])) s++;
  1330. while(1){
  1331. while(s<e && !Ascii::isSpace(str[s])) str[d++]=str[s++];
  1332. while(s<e && Ascii::isSpace(str[s])) s++;
  1333. if(s>=e) break;
  1334. str[d++]=' ';
  1335. }
  1336. length(d);
  1337. }
  1338. return *this;
  1339. }
  1340. // Remove leading and trailing whitespace
  1341. FXString& FXString::trim(){
  1342. if(str!=EMPTY){
  1343. register FXint s=0;
  1344. register FXint e=length();
  1345. while(0<e && Ascii::isSpace(str[e-1])) e--;
  1346. while(s<e && Ascii::isSpace(str[s])) s++;
  1347. memmove(str,&str[s],e-s);
  1348. length(e-s);
  1349. }
  1350. return *this;
  1351. }
  1352. // Remove leading whitespace
  1353. FXString& FXString::trimBegin(){
  1354. if(str!=EMPTY){
  1355. register FXint s=0;
  1356. register FXint e=length();
  1357. while(s<e && Ascii::isSpace(str[s])) s++;
  1358. memmove(str,str+s,e-s);
  1359. length(e-s);
  1360. }
  1361. return *this;
  1362. }
  1363. // Remove trailing whitespace
  1364. FXString& FXString::trimEnd(){
  1365. if(str!=EMPTY){
  1366. register FXint e=length();
  1367. while(0<e && Ascii::isSpace(str[e-1])) e--;
  1368. length(e);
  1369. }
  1370. return *this;
  1371. }
  1372. // Truncate string
  1373. FXString& FXString::trunc(FXint pos){
  1374. register FXint len=length();
  1375. if(pos>len) pos=len;
  1376. length(pos);
  1377. return *this;
  1378. }
  1379. // Clean string
  1380. FXString& FXString::clear(){
  1381. length(0);
  1382. return *this;
  1383. }
  1384. // Get leftmost part
  1385. FXString FXString::left(FXint n) const {
  1386. if(0<n){
  1387. register FXint len=length();
  1388. if(n>len) n=len;
  1389. return FXString(str,n);
  1390. }
  1391. return FXString::null;
  1392. }
  1393. // Get rightmost part
  1394. FXString FXString::right(FXint n) const {
  1395. if(0<n){
  1396. register FXint len=length();
  1397. if(n>len) n=len;
  1398. return FXString(str+len-n,n);
  1399. }
  1400. return FXString::null;
  1401. }
  1402. // Get some part in the middle
  1403. FXString FXString::mid(FXint pos,FXint n) const {
  1404. if(0<n){
  1405. register FXint len=length();
  1406. if(pos<len && pos+n>0){
  1407. if(pos<0){n+=pos;pos=0;}
  1408. if(pos+n>len){n=len-pos;}
  1409. return FXString(str+pos,n);
  1410. }
  1411. }
  1412. return FXString::null;
  1413. }
  1414. // Return all characters before the nth occurrence of ch, searching forward
  1415. FXString FXString::before(FXchar c,FXint n) const {
  1416. register FXint len=length();
  1417. register FXint p=0;
  1418. if(0<n){
  1419. while(p<len){
  1420. if(str[p]==c && --n==0) break;
  1421. p++;
  1422. }
  1423. }
  1424. return FXString(str,p);
  1425. }
  1426. // Return all characters before the nth occurrence of ch, searching backward
  1427. FXString FXString::rbefore(FXchar c,FXint n) const {
  1428. register FXint p=length();
  1429. if(0<n){
  1430. while(0<p){
  1431. p--;
  1432. if(str[p]==c && --n==0) break;
  1433. }
  1434. }
  1435. return FXString(str,p);
  1436. }
  1437. // Return all characters after the nth occurrence of ch, searching forward
  1438. FXString FXString::after(FXchar c,FXint n) const {
  1439. register FXint len=length();
  1440. register FXint p=0;
  1441. if(0<n){
  1442. while(p<len){
  1443. p++;
  1444. if(str[p-1]==c && --n==0) break;
  1445. }
  1446. }
  1447. return FXString(str+p,len-p);
  1448. }
  1449. // Return all characters after the nth occurrence of ch, searching backward
  1450. FXString FXString::rafter(FXchar c,FXint n) const {
  1451. register FXint len=length();
  1452. register FXint p=len;
  1453. if(0<n){
  1454. while(0<p){
  1455. if(str[p-1]==c && --n==0) break;
  1456. p--;
  1457. }
  1458. }
  1459. return FXString(str+p,len-p);
  1460. }
  1461. // Convert to lower case
  1462. FXString& FXString::lower(){
  1463. FXString string;
  1464. for(FXint p=0; p<length(); p=inc(p)){
  1465. FXwchar w=Unicode::toLower(wc(p));
  1466. string.append(&w,1);
  1467. }
  1468. adopt(string);
  1469. return *this;
  1470. }
  1471. // Convert to upper case
  1472. FXString& FXString::upper(){
  1473. FXString string;
  1474. for(FXint p=0; p<length(); p=inc(p)){
  1475. FXwchar w=Unicode::toUpper(wc(p));
  1476. string.append(&w,1);
  1477. }
  1478. adopt(string);
  1479. return *this;
  1480. }
  1481. // Compare strings
  1482. FXint compare(const FXchar* s1,const FXchar* s2){
  1483. register const FXuchar *p1=(const FXuchar *)s1;
  1484. register const FXuchar *p2=(const FXuchar *)s2;
  1485. register FXint c1,c2;
  1486. do{
  1487. c1=*p1++;
  1488. c2=*p2++;
  1489. }
  1490. while(c1 && (c1==c2));
  1491. return c1-c2;
  1492. }
  1493. FXint compare(const FXchar* s1,const FXString& s2){
  1494. return compare(s1,s2.str);
  1495. }
  1496. FXint compare(const FXString& s1,const FXchar* s2){
  1497. return compare(s1.str,s2);
  1498. }
  1499. FXint compare(const FXString& s1,const FXString& s2){
  1500. return compare(s1.str,s2.str);
  1501. }
  1502. // Compare strings up to n
  1503. FXint compare(const FXchar* s1,const FXchar* s2,FXint n){
  1504. register const FXuchar *p1=(const FXuchar *)s1;
  1505. register const FXuchar *p2=(const FXuchar *)s2;
  1506. register FXint c1,c2;
  1507. if(0<n){
  1508. do{
  1509. c1=*p1++;
  1510. c2=*p2++;
  1511. }
  1512. while(--n && c1 && (c1==c2));
  1513. return c1-c2;
  1514. }
  1515. return 0;
  1516. }
  1517. FXint compare(const FXchar* s1,const FXString& s2,FXint n){
  1518. return compare(s1,s2.str,n);
  1519. }
  1520. FXint compare(const FXString& s1,const FXchar* s2,FXint n){
  1521. return compare(s1.str,s2,n);
  1522. }
  1523. FXint compare(const FXString& s1,const FXString& s2,FXint n){
  1524. return compare(s1.str,s2.str,n);
  1525. }
  1526. // Compare utf-8 strings case insensitive
  1527. // At each iteration through the loop, the following is true:
  1528. // o Both characters are ascii. In this case, fold using Ascii
  1529. // and compare.
  1530. // o One of the two is ascii. This means the other is > 0x80
  1531. // so fold using Ascii [leaving upper 128 codes invariant], and
  1532. // compare; they will be unequal so we'll fall out of the loop.
  1533. // o Both characters are wide. This is the complex case, and
  1534. // here we have to obtain the wide character, convert to lower
  1535. // case using the Unicode, and compare. Skip to the start of
  1536. // the next character by consulting character-width table.
  1537. FXint comparecase(const FXchar* s1,const FXchar* s2){
  1538. register FXint c1,c2;
  1539. do{
  1540. if((*s1 & 0x80) && (*s2 & 0x80)){
  1541. c1=Unicode::toLower(wc(s1)); s1+=wclen(s1);
  1542. c2=Unicode::toLower(wc(s2)); s2+=wclen(s2);
  1543. }
  1544. else{
  1545. c1=Ascii::toLower(*s1); s1+=1;
  1546. c2=Ascii::toLower(*s2); s2+=1;
  1547. }
  1548. }
  1549. while(c1 && (c1==c2));
  1550. return c1-c2;
  1551. }
  1552. // Compare strings case insensitive up to n
  1553. FXint comparecase(const FXchar* s1,const FXchar* s2,FXint n){
  1554. register FXint c1,c2;
  1555. if(0<n){
  1556. do{
  1557. if((*s1 & 0x80) && (*s2 & 0x80)){
  1558. c1=Unicode::toLower(wc(s1)); s1+=wclen(s1);
  1559. c2=Unicode::toLower(wc(s2)); s2+=wclen(s2);
  1560. }
  1561. else{
  1562. c1=Ascii::toLower(*s1); s1+=1;
  1563. c2=Ascii::toLower(*s2); s2+=1;
  1564. }
  1565. }
  1566. while(--n && c1 && (c1==c2));
  1567. return c1-c2;
  1568. }
  1569. return 0;
  1570. }
  1571. #if 0
  1572. // Compare strings case insensitive
  1573. FXint comparecase(const FXchar* s1,const FXchar* s2){
  1574. register const FXuchar *p1=(const FXuchar *)s1;
  1575. register const FXuchar *p2=(const FXuchar *)s2;
  1576. register FXint c1,c2;
  1577. do{
  1578. c1=Ascii::toLower(*p1++);
  1579. c2=Ascii::toLower(*p2++);
  1580. }
  1581. while(c1 && (c1==c2));
  1582. return c1-c2;
  1583. }
  1584. #endif
  1585. FXint comparecase(const FXchar* s1,const FXString& s2){
  1586. return comparecase(s1,s2.str);
  1587. }
  1588. FXint comparecase(const FXString& s1,const FXchar* s2){
  1589. return comparecase(s1.str,s2);
  1590. }
  1591. FXint comparecase(const FXString& s1,const FXString& s2){
  1592. return comparecase(s1.str,s2.str);
  1593. }
  1594. #if 0
  1595. // Compare strings case insensitive up to n
  1596. FXint comparecase(const FXchar* s1,const FXchar* s2,FXint n){
  1597. register const FXuchar *p1=(const FXuchar *)s1;
  1598. register const FXuchar *p2=(const FXuchar *)s2;
  1599. register FXint c1,c2;
  1600. if(0<n){
  1601. do{
  1602. c1=Ascii::toLower(*p1++);
  1603. c2=Ascii::toLower(*p2++);
  1604. }
  1605. while(--n && c1 && (c1==c2));
  1606. return c1-c2;
  1607. }
  1608. return 0;
  1609. }
  1610. #endif
  1611. FXint comparecase(const FXchar* s1,const FXString& s2,FXint n){
  1612. return comparecase(s1,s2.str,n);
  1613. }
  1614. FXint comparecase(const FXString& s1,const FXchar* s2,FXint n){
  1615. return comparecase(s1.str,s2,n);
  1616. }
  1617. FXint comparecase(const FXString& s1,const FXString& s2,FXint n){
  1618. return comparecase(s1.str,s2.str,n);
  1619. }
  1620. // Comparison operators
  1621. bool operator==(const FXString& s1,const FXString& s2){
  1622. return compare(s1.str,s2.str)==0;
  1623. }
  1624. bool operator==(const FXString& s1,const FXchar* s2){
  1625. return compare(s1.str,s2)==0;
  1626. }
  1627. bool operator==(const FXchar* s1,const FXString& s2){
  1628. return compare(s1,s2.str)==0;
  1629. }
  1630. bool operator!=(const FXString& s1,const FXString& s2){
  1631. return compare(s1.str,s2.str)!=0;
  1632. }
  1633. bool operator!=(const FXString& s1,const FXchar* s2){
  1634. return compare(s1.str,s2)!=0;
  1635. }
  1636. bool operator!=(const FXchar* s1,const FXString& s2){
  1637. return compare(s1,s2.str)!=0;
  1638. }
  1639. bool operator<(const FXString& s1,const FXString& s2){
  1640. return compare(s1.str,s2.str)<0;
  1641. }
  1642. bool operator<(const FXString& s1,const FXchar* s2){
  1643. return compare(s1.str,s2)<0;
  1644. }
  1645. bool operator<(const FXchar* s1,const FXString& s2){
  1646. return compare(s1,s2.str)<0;
  1647. }
  1648. bool operator<=(const FXString& s1,const FXString& s2){
  1649. return compare(s1.str,s2.str)<=0;
  1650. }
  1651. bool operator<=(const FXString& s1,const FXchar* s2){
  1652. return compare(s1.str,s2)<=0;
  1653. }
  1654. bool operator<=(const FXchar* s1,const FXString& s2){
  1655. return compare(s1,s2.str)<=0;
  1656. }
  1657. bool operator>(const FXString& s1,const FXString& s2){
  1658. return compare(s1.str,s2.str)>0;
  1659. }
  1660. bool operator>(const FXString& s1,const FXchar* s2){
  1661. return compare(s1.str,s2)>0;
  1662. }
  1663. bool operator>(const FXchar* s1,const FXString& s2){
  1664. return compare(s1,s2.str)>0;
  1665. }
  1666. bool operator>=(const FXString& s1,const FXString& s2){
  1667. return compare(s1.str,s2.str)>=0;
  1668. }
  1669. bool operator>=(const FXString& s1,const FXchar* s2){
  1670. return compare(s1.str,s2)>=0;
  1671. }
  1672. bool operator>=(const FXchar* s1,const FXString& s2){
  1673. return compare(s1,s2.str)>=0;
  1674. }
  1675. // Find n-th occurrence of character, searching forward; return position or -1
  1676. FXint FXString::find(FXchar c,FXint pos,FXint n) const {
  1677. register FXint len=length();
  1678. register FXint p=pos;
  1679. register FXint cc=c;
  1680. if(p<0) p=0;
  1681. if(n<=0) return p;
  1682. while(p<len){
  1683. if(str[p]==cc){ if(--n==0) return p; }
  1684. ++p;
  1685. }
  1686. return -1;
  1687. }
  1688. // Find n-th occurrence of character, searching backward; return position or -1
  1689. FXint FXString::rfind(FXchar c,FXint pos,FXint n) const {
  1690. register FXint len=length();
  1691. register FXint p=pos;
  1692. register FXint cc=c;
  1693. if(p>=len) p=len-1;
  1694. if(n<=0) return p;
  1695. while(0<=p){
  1696. if(str[p]==cc){ if(--n==0) return p; }
  1697. --p;
  1698. }
  1699. return -1;
  1700. }
  1701. // Find a character, searching forward; return position or -1
  1702. FXint FXString::find(FXchar c,FXint pos) const {
  1703. register FXint len=length();
  1704. register FXint p=pos;
  1705. register FXint cc=c;
  1706. if(p<0) p=0;
  1707. while(p<len){ if(str[p]==cc){ return p; } ++p; }
  1708. return -1;
  1709. }
  1710. // Find a character, searching backward; return position or -1
  1711. FXint FXString::rfind(FXchar c,FXint pos) const {
  1712. register FXint len=length();
  1713. register FXint p=pos;
  1714. register FXint cc=c;
  1715. if(p>=len) p=len-1;
  1716. while(0<=p){ if(str[p]==cc){ return p; } --p; }
  1717. return -1;
  1718. }
  1719. // Find a substring of length n, searching forward; return position or -1
  1720. FXint FXString::find(const FXchar* substr,FXint n,FXint pos) const {
  1721. register FXint len=length();
  1722. if(0<=pos && 0<n && n<=len){
  1723. register FXint c=substr[0];
  1724. len=len-n+1;
  1725. while(pos<len){
  1726. if(str[pos]==c){
  1727. if(!compare(str+pos,substr,n)){
  1728. return pos;
  1729. }
  1730. }
  1731. pos++;
  1732. }
  1733. }
  1734. return -1;
  1735. }
  1736. // Find a substring, searching forward; return position or -1
  1737. FXint FXString::find(const FXchar* substr,FXint pos) const {
  1738. return find(substr,strlen(substr),pos);
  1739. }
  1740. // Find a substring, searching forward; return position or -1
  1741. FXint FXString::find(const FXString& substr,FXint pos) const {
  1742. return find(substr.text(),substr.length(),pos);
  1743. }
  1744. // Find a substring of length n, searching backward; return position or -1
  1745. FXint FXString::rfind(const FXchar* substr,FXint n,FXint pos) const {
  1746. register FXint len=length();
  1747. if(0<=pos && 0<n && n<=len){
  1748. register FXint c=substr[0];
  1749. len-=n;
  1750. if(pos>len) pos=len;
  1751. while(0<=pos){
  1752. if(str[pos]==c){
  1753. if(!compare(str+pos,substr,n)){
  1754. return pos;
  1755. }
  1756. }
  1757. pos--;
  1758. }
  1759. }
  1760. return -1;
  1761. }
  1762. // Find a substring, searching backward; return position or -1
  1763. FXint FXString::rfind(const FXchar* substr,FXint pos) const {
  1764. return rfind(substr,strlen(substr),pos);
  1765. }
  1766. // Find a substring, searching backward; return position or -1
  1767. FXint FXString::rfind(const FXString& substr,FXint pos) const {
  1768. return rfind(substr.text(),substr.length(),pos);
  1769. }
  1770. // Find first character in the set of size n, starting from pos; return position or -1
  1771. FXint FXString::find_first_of(const FXchar* set,FXint n,FXint pos) const {
  1772. register FXint len=length();
  1773. register FXint p=pos;
  1774. if(p<0) p=0;
  1775. while(p<len){
  1776. register FXint c=str[p];
  1777. register FXint i=n;
  1778. while(--i>=0){ if(set[i]==c) return p; }
  1779. p++;
  1780. }
  1781. return -1;
  1782. }
  1783. // Find first character in the set, starting from pos; return positiā€¦

Large files files are truncated, but you can click here to view the full file