cstring.C 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: cstring.C /main/2 1995/07/17 14:10:22 drk $ */
  24. /*******************************************************************
  25. ** (c) Copyright Hewlett-Packard Company, 1990, 1991, 1992, 1993.
  26. ** All rights are reserved. Copying or other reproduction of this
  27. ** program except for archival purposes is prohibited without prior
  28. ** written consent of Hewlett-Packard Company.
  29. ********************************************************************
  30. ****************************<+>*************************************/
  31. #include "cstring.h"
  32. #include <ctype.h>
  33. CString::CString()
  34. {
  35. contents = 0;
  36. skipWhiteSpace = 1;
  37. }
  38. CString::CString
  39. (
  40. const char * s,
  41. unsigned char ws
  42. ) : skipWhiteSpace(ws)
  43. {
  44. if (s != 0) {
  45. contents = new char [strlen(s) + 1];
  46. strcpy(contents,s);
  47. }
  48. else {
  49. contents = new char [1];
  50. strcpy(contents,"");
  51. }
  52. }
  53. CString::CString
  54. (
  55. const char c,
  56. unsigned char ws
  57. ) : skipWhiteSpace(ws)
  58. {
  59. contents = new char [2];
  60. contents[0] = c;
  61. contents[1] = 0;
  62. }
  63. CString::~CString()
  64. {
  65. delete [] contents;
  66. }
  67. CString::CString
  68. (
  69. const CString & s
  70. )
  71. {
  72. contents = new char [s.length() + 1];
  73. strcpy(contents,s.data());
  74. skipWhiteSpace = s.skipWhiteSpace;
  75. }
  76. char & CString::operator[]
  77. (
  78. int index
  79. ) const
  80. {
  81. if (index < 0)
  82. return contents[0];
  83. if (index > strlen(contents))
  84. return contents[strlen(contents)-1];
  85. return contents[index];
  86. }
  87. int CString::operator!=
  88. (
  89. const CString & s
  90. ) const
  91. {
  92. return !(*this == s);
  93. }
  94. int CString::operator==
  95. (
  96. const CString & s
  97. ) const
  98. {
  99. if (isNull() && s.isNull())
  100. return 1;
  101. if (isNull() || s.isNull())
  102. return 0;
  103. if (strcmp(contents,s.data()) == 0)
  104. return 1;
  105. return 0;
  106. }
  107. CString & CString::operator=
  108. (
  109. const CString & s
  110. )
  111. {
  112. if (s != *this) {
  113. delete [] contents;
  114. contents = new char [s.length() + 1];
  115. strcpy(contents,s.data());
  116. }
  117. return *this;
  118. }
  119. CString & CString::operator=
  120. (
  121. const char * s
  122. )
  123. {
  124. delete [] contents;
  125. contents = new char [strlen(s) + 1];
  126. strcpy(contents,s);
  127. return *this;
  128. }
  129. CString & CString::operator+=
  130. (
  131. const char * cs
  132. )
  133. {
  134. char * temp;
  135. if (contents) {
  136. if (cs)
  137. temp = new char [strlen(contents) + strlen(cs) + 1];
  138. else
  139. return *this;
  140. }
  141. else {
  142. if (cs)
  143. temp = new char [strlen(cs) + 1];
  144. else
  145. return *this;
  146. }
  147. *temp = 0;
  148. if (contents)
  149. strcat(temp,contents);
  150. if (cs)
  151. strcat(temp,cs);
  152. delete [] contents;
  153. contents = temp;
  154. return *this;
  155. }
  156. CString & CString::operator+=
  157. (
  158. const CString & s
  159. )
  160. {
  161. char * temp;
  162. if (contents) {
  163. if (s.contents)
  164. temp = new char [strlen(contents) + s.length() + 1];
  165. else
  166. return *this;
  167. }
  168. else {
  169. if (s.contents)
  170. temp = new char [s.length() + 1];
  171. else
  172. return *this;
  173. }
  174. *temp = 0;
  175. if (contents)
  176. strcat(temp,contents);
  177. if (s.contents)
  178. strcat(temp,s.data());
  179. delete [] contents;
  180. contents = temp;
  181. return *this;
  182. }
  183. CString operator+
  184. (
  185. const CString & s1,
  186. const CString & s2
  187. )
  188. {
  189. CString result(s1);
  190. result += s2;
  191. return result;
  192. }
  193. CString operator+
  194. (
  195. const CString & s,
  196. const char * cs
  197. )
  198. {
  199. CString result(s);
  200. result += cs;
  201. return result;
  202. }
  203. CString operator+
  204. (
  205. const char * cs,
  206. const CString & s
  207. )
  208. {
  209. CString result(cs);
  210. result += s;
  211. return result;
  212. }
  213. CString CString::copy
  214. (
  215. unsigned int start,
  216. const char * delim
  217. )
  218. {
  219. if (isNull())
  220. return *this;
  221. for (int i = 0; i < strlen(delim); i++) {
  222. char * q;
  223. if (q = strchr(contents,delim[i])) {
  224. char remember = *q;
  225. *q = 0;
  226. CString result(&contents[start]);
  227. *q = remember;
  228. return result;
  229. }
  230. }
  231. return *this;
  232. }
  233. CString CString::copy
  234. (
  235. const char * delim1,
  236. const char * delim2
  237. )
  238. {
  239. if (isNull())
  240. return *this;
  241. for (int i = 0; i < strlen(delim1); i++) {
  242. char * q;
  243. if (q = strchr(contents,delim1[i])) {
  244. for (int j = 0; j < strlen(delim2); j++) {
  245. char * p;
  246. if (p = strchr(q+1,delim2[j])) {
  247. char remember = *p;
  248. *p = 0;
  249. CString result(q+1);
  250. *p = remember;
  251. return result;
  252. }
  253. }
  254. return CString(q);
  255. }
  256. }
  257. return *this;
  258. }
  259. CString CString::find
  260. (
  261. const char * cs
  262. )
  263. {
  264. char * q;
  265. if (isNull())
  266. return *this;
  267. if (q = strstr(contents,cs))
  268. return CString(q);
  269. return *this;
  270. }
  271. int CString::contains
  272. (
  273. const CString & s,
  274. const char * leader,
  275. const char * trailer
  276. ) const
  277. {
  278. return contains(s.data(), leader, trailer);
  279. }
  280. int CString::contains
  281. (
  282. const char * cs,
  283. const char * leader,
  284. const char * trailer
  285. ) const
  286. {
  287. // first see if there is anything in contents
  288. if (isNull())
  289. return 0;
  290. // or if the strings are exactly the same
  291. if (strcmp(cs,data()) == 0)
  292. return 1;
  293. // now check to see if it is embedded in the string
  294. CString search(leader);
  295. search += cs;
  296. search += trailer;
  297. if (strstr (contents, search.data()))
  298. return 1;
  299. // if skipWhiteSpace is on then check for spaces on one or
  300. // both sides of the target in the source.
  301. if (skipWhiteSpace) {
  302. // first, a space in front, delimiter on the end
  303. search = " ";
  304. search += cs;
  305. search += trailer;
  306. if (strstr (contents, search.data()))
  307. return 1;
  308. // second, a delimiter on the front, space on the end
  309. search = leader;
  310. search += cs;
  311. search += " ";
  312. if (strstr (contents, search.data()))
  313. return 1;
  314. // third, spaces before and after
  315. search = " ";
  316. search += cs;
  317. search += " ";
  318. if (strstr (contents, search.data()))
  319. return 1;
  320. }
  321. // now check to see if it is the start of the string
  322. search = cs;
  323. search += trailer;
  324. if (strncmp (contents, search.data(), search.length()) == 0)
  325. return 1;
  326. // now check to see if it is the start of the string followed
  327. // by a space
  328. search = cs;
  329. search += " ";
  330. if (strncmp (contents, search.data(), search.length()) == 0)
  331. return 1;
  332. // last, check to see if it is on the end of the string using
  333. // the delimiter and a space
  334. search = leader;
  335. while (1) {
  336. search += cs;
  337. char *q, *r = 0;
  338. char *p = contents;
  339. while (q = strstr(p, search.data())) {
  340. r = q + strlen(leader);
  341. p = q + 1;
  342. }
  343. if (r && strcmp(r,cs) == 0)
  344. return 1;
  345. if (search[0] == ' ')
  346. break;
  347. search = " ";
  348. }
  349. return 0;
  350. }
  351. void CString::replace
  352. (
  353. const CString & to_be_replaced,
  354. const CString & replacee
  355. )
  356. {
  357. char * q;
  358. if (isNull())
  359. return;
  360. if (q = strstr(contents,to_be_replaced.data())) {
  361. *q = 0;
  362. char * prefix = new char [strlen(contents) + 1];
  363. strcpy(prefix,contents);
  364. q += to_be_replaced.length();
  365. char * suffix = new char [strlen(q) + 1];
  366. strcpy(suffix,q);
  367. delete [] contents;
  368. contents = new char [strlen(prefix) +
  369. replacee.length() +
  370. strlen(suffix) + 1];
  371. strcpy(contents,prefix);
  372. strcat(contents,replacee.data());
  373. strcat(contents,suffix);
  374. delete [] prefix;
  375. delete [] suffix;
  376. }
  377. }
  378. int CString::isNull() const
  379. {
  380. if (contents == 0)
  381. return 1;
  382. if (strlen(contents) == 0)
  383. return 1;
  384. return 0;
  385. }
  386. CTokenizedString::CTokenizedString()
  387. : CString(""), finished(0), cursor(0), delimiter(0)
  388. {}
  389. CTokenizedString::CTokenizedString
  390. (
  391. const CTokenizedString & s
  392. )
  393. {
  394. if (s != *this) {
  395. cursor = new char [strlen(s.cursor) + 1];
  396. strcpy(cursor,s.cursor);
  397. delimiter = new char [strlen(s.delimiter) + 1];
  398. strcpy(delimiter,s.delimiter);
  399. finished = s.finished;
  400. skipWhiteSpace = s.skipWhiteSpace;
  401. contents = new char [strlen(s.contents) + 1];
  402. strcpy(contents,s.contents);
  403. }
  404. }
  405. CTokenizedString::CTokenizedString
  406. (
  407. const CString & s,
  408. char * d,
  409. unsigned char ws
  410. ) : CString(s), finished(0)
  411. {
  412. cursor = new char [s.length() + 1];
  413. strcpy(cursor,s.data());
  414. delimiter = new char [strlen(d) + 1];
  415. strcpy(delimiter,d);
  416. skipWhiteSpace = ws;
  417. }
  418. CTokenizedString::~CTokenizedString()
  419. {
  420. delete [] cursor;
  421. delete [] delimiter;
  422. }
  423. CString CTokenizedString::next()
  424. {
  425. char * q = 0;
  426. char * p;
  427. int i;
  428. if (cursor) {
  429. if (strlen(delimiter) == 1)
  430. q = strchr(cursor,delimiter[0]);
  431. else {
  432. for (i = 0; i < strlen(cursor); i++)
  433. if (strchr(delimiter,cursor[i])) {
  434. q = &cursor[i];
  435. break;
  436. }
  437. }
  438. }
  439. if (q) {
  440. // a delimiter has been found. Create the return token,
  441. // adjust the cursor
  442. *q = 0;
  443. // eliminate trailing white space
  444. if (skipWhiteSpace) {
  445. for (p = q; isspace(*(p-1)); p--);
  446. *p = 0;
  447. }
  448. CString result(cursor);
  449. // eliminate leading white space
  450. if (skipWhiteSpace)
  451. for (; isspace(*(q+1)); q++);
  452. char * temp = new char [strlen(q+1) + 1];
  453. strcpy(temp,q+1);
  454. delete [] cursor;
  455. cursor = temp;
  456. return result;
  457. }
  458. else if (cursor) {
  459. // no delimiter found. Return what is left of the string
  460. CString result(cursor);
  461. delete [] cursor;
  462. cursor = 0;
  463. return result;
  464. }
  465. else {
  466. finished = 1;
  467. return CString("");
  468. }
  469. }
  470. std::ostream & operator<<
  471. (
  472. std::ostream & os,
  473. const CString & s
  474. )
  475. {
  476. if (s.isNull())
  477. return os << "(null)";
  478. return os << s.data();
  479. }