PageRenderTime 26ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/casa/BasicSL/String.cc

http://casacore.googlecode.com/
C++ | 577 lines | 450 code | 85 blank | 42 comment | 119 complexity | d325ce4aa1d84c010dcff9ee37ca79bd MD5 | raw file
Possible License(s): GPL-2.0
  1. //# String.cc: String class
  2. //# Copyright (C) 2001,2002,2003
  3. //# Associated Universities, Inc. Washington DC, USA.
  4. //#
  5. //# This library is free software; you can redistribute it and/or modify it
  6. //# under the terms of the GNU Library General Public License as published by
  7. //# the Free Software Foundation; either version 2 of the License, or (at your
  8. //# option) any later version.
  9. //#
  10. //# This library is distributed in the hope that it will be useful, but WITHOUT
  11. //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
  13. //# License for more details.
  14. //#
  15. //# You should have received a copy of the GNU Library General Public License
  16. //# along with this library; if not, write to the Free Software Foundation,
  17. //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
  18. //#
  19. //# Correspondence concerning AIPS++ should be addressed as follows:
  20. //# Internet email: aips2-request@nrao.edu.
  21. //# Postal address: AIPS++ Project Office
  22. //# National Radio Astronomy Observatory
  23. //# 520 Edgemont Road
  24. //# Charlottesville, VA 22903-2475 USA
  25. //#
  26. //# $Id: String.cc 21022 2011-03-01 10:07:47Z gervandiepen $
  27. #include <casa/BasicSL/String.h>
  28. #include <casa/BasicSL/RegexBase.h>
  29. #include <algorithm>
  30. #include <casa/string.h>
  31. #include <casa/sstream.h>
  32. namespace casa { //# NAMESPACE CASA - BEGIN
  33. // Special constructors
  34. String::String(ostringstream &os) {
  35. *this = os.str();
  36. }
  37. // Count occurrences
  38. Int String::freq(Char c) const {
  39. size_type p(0);
  40. Int found(0);
  41. while (p < length()) {
  42. if ((p = find(c, p)) == npos) break;
  43. found++;
  44. p++;
  45. }
  46. return found;
  47. }
  48. Int String::freq(const string &str) const {
  49. size_type p(0);
  50. Int found(0);
  51. while (p < length()) {
  52. if ((p = find(str, p)) == npos) break;
  53. found++;
  54. p++;
  55. }
  56. return found;
  57. }
  58. Int String::freq(const Char *s) const {
  59. size_type p(0);
  60. Int found(0);
  61. while (p < length()) {
  62. if ((p = find(s, p)) == npos) break;
  63. found++;
  64. p++;
  65. }
  66. return found;
  67. }
  68. Double String::toDouble(const String& string) {
  69. istringstream instr(string);
  70. Double var;
  71. instr >> var;
  72. if (instr.fail()) {
  73. var = 0.0;
  74. }
  75. return var;
  76. }
  77. Float String::toFloat(const String& string) {
  78. istringstream instr(string);
  79. Float var;
  80. // Initialize in case the string is empty or non-numeric.
  81. instr >> var;
  82. if (instr.fail()) {
  83. var = 0.0;
  84. }
  85. return var;
  86. }
  87. Int String::toInt(const String& string) {
  88. istringstream instr(string);
  89. Int var;
  90. // Initialize in case the string is empty or non-numeric.
  91. instr >> var;
  92. if (instr.fail()) {
  93. var = 0.0;
  94. }
  95. return var;
  96. }
  97. void String::trim() {
  98. iterator iter = begin();
  99. while (iter != end() &&
  100. (*iter == ' ' || *iter == '\t' ||
  101. *iter == '\n' || *iter == '\r')) {
  102. ++iter;
  103. }
  104. erase (begin(), iter);
  105. if (! empty()) {
  106. iter = end() - 1;
  107. while (iter != begin() &&
  108. (*iter == ' ' || *iter == '\t' ||
  109. *iter == '\n' || *iter == '\r')) {
  110. --iter;
  111. }
  112. ++iter;
  113. erase (iter, end());
  114. }
  115. }
  116. // Obtain a (separate) 'sub'-string
  117. SubString String::at(size_type pos, size_type len) {
  118. return _substr(pos, len);
  119. }
  120. SubString String::at(const string &str, Int startpos) {
  121. return _substr(index(str, startpos), str.length());
  122. }
  123. SubString String::at(const Char *s, Int startpos) {
  124. return _substr(index(s, startpos), traits_type::length(s));
  125. }
  126. SubString String::at(Char c, Int startpos) {
  127. return _substr(index(c, startpos), 1);
  128. }
  129. SubString String::before(size_type pos) {
  130. return _substr(0, pos);
  131. }
  132. SubString String::before(const string &str, Int startpos) {
  133. return _substr(0, index(str, startpos));
  134. }
  135. SubString String::before(const Char *s, Int startpos) {
  136. return _substr(0, index(s, startpos));
  137. }
  138. SubString String::before(Char c, Int startpos) {
  139. return _substr(0, index(c, startpos));
  140. }
  141. SubString String::through(size_type pos) {
  142. return _substr(0, pos+1);
  143. }
  144. SubString String::through(const string &str, Int startpos) {
  145. size_type last(index(str, startpos));
  146. if (last != npos) last += str.length();
  147. return _substr(0, last);
  148. }
  149. SubString String::through(const Char *s, Int startpos) {
  150. size_type last(index(s, startpos));
  151. if (last != npos) last += traits_type::length(s);
  152. return _substr(0, last);
  153. }
  154. SubString String::through(Char c, Int startpos) {
  155. size_type last(index(c, startpos));
  156. if (last != npos) last += 1;
  157. return _substr(0, last);
  158. }
  159. SubString String::from(size_type pos) {
  160. return _substr(pos, length()-pos);
  161. }
  162. SubString String::from(const string &str, Int startpos) {
  163. size_type first(index(str, startpos));
  164. return _substr(first, length()-first);
  165. }
  166. SubString String::from(const Char *s, Int startpos) {
  167. size_type first(index(s, startpos));
  168. return _substr(first, length()-first);
  169. }
  170. SubString String::from(Char c, Int startpos) {
  171. size_type first(index(c, startpos));
  172. return _substr(first, length()-first);
  173. }
  174. SubString String::after(size_type pos) {
  175. return _substr(pos+1, length()-(pos+1));
  176. }
  177. SubString String::after(const string &str, Int startpos) {
  178. size_type first(index(str, startpos));
  179. if (first != npos) first += str.length();
  180. return _substr(first, length()-first);
  181. }
  182. SubString String::after(const Char *s, Int startpos) {
  183. size_type first(index(s, startpos));
  184. if (first != npos) first += traits_type::length(s);
  185. return _substr(first, length()-first);
  186. }
  187. SubString String::after(Char c, Int startpos) {
  188. size_type first(index(c, startpos));
  189. if (first != npos) first += 1;
  190. return _substr(first, length()-first);
  191. }
  192. // Prepend string
  193. void String::prepend(const string &str) {
  194. insert(size_type(0), str);
  195. }
  196. void String::prepend(const Char *s) {
  197. insert(size_type(0), s);
  198. }
  199. void String::prepend(Char c) {
  200. insert(size_type(0), c);
  201. }
  202. // Delete
  203. void String::del(size_type pos, size_type len) {
  204. erase(pos, len);
  205. }
  206. void String::del(const string &str, size_type startpos) {
  207. erase(index(str, startpos), str.length());
  208. }
  209. void String::del(const Char *s, size_type startpos) {
  210. erase(index(s, startpos), traits_type::length(s));
  211. }
  212. void String::del(Char c, size_type startpos) {
  213. erase(index(c, startpos), 1);
  214. }
  215. // Global substitution
  216. Int String::gsub(const string &pat, const string &repl) {
  217. Int nmatches(0);
  218. if (length() == 0 || pat.length() == 0 ||
  219. length() < pat.length()) return nmatches;
  220. size_type si(0);
  221. Int rl(repl.length());
  222. while (length()-si >= pat.length()) {
  223. size_type pos = find(pat, si);
  224. if (pos == npos) break;
  225. else {
  226. nmatches++;
  227. replace(pos, pat.length(), repl);
  228. si = pos + rl;
  229. }
  230. }
  231. return nmatches;
  232. }
  233. Int String::gsub(const Char *pat, const string &repl) {
  234. return gsub(String(pat), repl);
  235. }
  236. Int String::gsub(const Char *pat, const Char *repl) {
  237. return gsub(String(pat), String(repl));
  238. }
  239. // Member utilities
  240. void String::reverse() {
  241. std::reverse(begin(), end());
  242. }
  243. #if defined(AIPS_SUN_NATIVE)
  244. Int ToUpper(Int a){return toupper(a);}
  245. Int ToLower(Int a){return tolower(a);}
  246. #else
  247. #define ToUpper toupper
  248. #define ToLower tolower
  249. #endif
  250. void String::upcase() {
  251. std::transform(begin(), end(), begin(), ToUpper);
  252. }
  253. void String::downcase() {
  254. std::transform(begin(), end(), begin(), ToLower);
  255. }
  256. void String::capitalize() {
  257. for (iterator p=begin(); p < end(); p++) {
  258. Bool at_word;
  259. if ((at_word = islower(*p))) *p = ToUpper(*p);
  260. else at_word = isupper(*p) || isdigit(*p);
  261. if (at_word) {
  262. while (++p < end()) {
  263. if (isupper(*p)) *p = ToLower(*p);
  264. else if (!islower(*p) && !isdigit(*p)) break;
  265. }
  266. }
  267. }
  268. }
  269. // RegexBase related functions
  270. String::size_type String::find(const RegexBase &r, size_type pos) const {
  271. Int unused;
  272. return r.find(c_str(), length(), unused, pos);
  273. }
  274. String::size_type String::rfind(const RegexBase &r, size_type pos) const {
  275. Int unused;
  276. return r.rfind(c_str(), length(), unused, pos-length());
  277. }
  278. Bool String::matches(const string &str, Int pos) const {
  279. Bool rstat(False);
  280. if (pos < 0) {
  281. if (this->index(str,pos) == 0) {
  282. rstat = True;
  283. /// } else {
  284. /// cerr << "No Match " << this->index(str, pos) << endl;
  285. }
  286. } else {
  287. if (length() != 0 && str.length() != 0 &&
  288. length() == pos+str.length() &&
  289. static_cast<size_type>(pos) < length() &&
  290. index(str, pos) == static_cast<size_type>(pos)) {
  291. rstat = True;
  292. }
  293. }
  294. return rstat;
  295. }
  296. Bool String::contains(const RegexBase &r) const {
  297. Int unused;
  298. return (r.find(c_str(), length(), unused, 0)) != npos;
  299. }
  300. Bool String::matches(const RegexBase &r, Int pos) const {
  301. String::size_type l = (pos < 0) ? -pos : length() - pos;
  302. if (l>length()) return False;
  303. if (pos<0) return r.match(c_str(), l, 0) == l;
  304. return r.match(c_str(), length(), pos) == l;
  305. }
  306. String::size_type String::index(const RegexBase &r, Int startpos) const {
  307. Int unused;
  308. return r.search(c_str(), length(), unused, startpos);
  309. }
  310. SubString String::at(const RegexBase &r, Int startpos) {
  311. Int mlen;
  312. size_type first = r.search(c_str(), length(), mlen, startpos);
  313. return _substr(first, mlen);
  314. }
  315. SubString String::before(const RegexBase &r, Int startpos) {
  316. Int mlen;
  317. size_type first = r.search(c_str(), length(), mlen, startpos);
  318. return _substr(0, first);
  319. }
  320. SubString String::through(const RegexBase &r, Int startpos) {
  321. Int mlen;
  322. size_type first = r.search(c_str(), length(), mlen, startpos);
  323. if (first != npos) first += mlen;
  324. return _substr(0, first);
  325. }
  326. SubString String::from(const RegexBase &r, Int startpos) {
  327. Int mlen;
  328. size_type first = r.search(c_str(), length(), mlen, startpos);
  329. return _substr(first, length()-first);
  330. }
  331. SubString String::after(const RegexBase &r, Int startpos) {
  332. Int mlen;
  333. size_type first = r.search(c_str(), length(), mlen, startpos);
  334. if (first != npos) first += mlen;
  335. return _substr(first, length()-first);
  336. }
  337. void String::del(const RegexBase &r, size_type startpos) {
  338. Int mlen;
  339. size_type first = r.find(c_str(), length(), mlen, startpos);
  340. erase(first, mlen);
  341. }
  342. Int String::gsub(const RegexBase &pat, const string &repl) {
  343. Int nmatches(0);
  344. if (length() == 0) return nmatches;
  345. Int pl;
  346. size_type si(0);
  347. Int rl(repl.length());
  348. while (length() > si) {
  349. size_type pos = pat.find(c_str(), length(), pl, si);
  350. if (pos >= npos-1 || pl <= 0) break;
  351. else {
  352. nmatches++;
  353. si = pos + rl;
  354. if (pos == 0 && si == 0) { // could be problem with anchor at begin
  355. Int pls;
  356. size_type ps = pat.find(c_str(), length(), pls, pl); // try for begin
  357. if (ps >= npos-1 || pls <= 0) {
  358. replace(pos, pl, repl); // finish off if no more (anchored) match
  359. break;
  360. }
  361. }
  362. // Continue global substitution
  363. replace(pos, pl, repl);
  364. }
  365. }
  366. return nmatches;
  367. }
  368. // Global functions
  369. String reverse(string str) {
  370. std::reverse(str.begin(), str.end());
  371. return str;
  372. }
  373. String upcase(string str) {
  374. std::transform(str.begin(), str.end(), str.begin(), ToUpper);
  375. return str;
  376. }
  377. String downcase(string str) {
  378. std::transform(str.begin(), str.end(), str.begin(), ToLower);
  379. return str;
  380. }
  381. String capitalize(string str) {
  382. static_cast<String>(str).capitalize();
  383. return str;
  384. }
  385. String replicate(Char c, String::size_type n) {
  386. return String(n, c);
  387. }
  388. String replicate(const string &str, String::size_type n) {
  389. String t(str);
  390. t.reserve(n*str.length());
  391. while (--n > 0) t += str;
  392. return t;
  393. }
  394. Int split(const string &str, string res[], Int maxn,
  395. const string &sep) {
  396. Int i(0);
  397. String::size_type pos(0);
  398. while (i < maxn && pos < str.length()) {
  399. String::size_type p = str.find(sep, pos);
  400. if (p == String::npos) p = str.length();
  401. res[i] = String(str, pos, p-pos);
  402. i++;
  403. pos = p + sep.length();
  404. }
  405. return i;
  406. }
  407. Int split(const string &str, string res[], Int maxn,
  408. const RegexBase &sep) {
  409. Int i(0);
  410. String::size_type pos(0);
  411. Int matchlen;
  412. while (i < maxn && pos < str.length()) {
  413. String::size_type p = sep.find(str.c_str(), str.length(), matchlen, pos);
  414. if (p == String::npos) p = str.length();
  415. res[i] = String(str, pos, p-pos);
  416. i++;
  417. pos = p + matchlen;
  418. }
  419. return i;
  420. }
  421. Int split(const string &str, string res[], Int maxn,
  422. const Char sep) {
  423. return split(str, res, maxn, String(sep));
  424. }
  425. String common_prefix(const string &x, const string &y,
  426. Int startpos) {
  427. if (static_cast<String::size_type>(startpos) == String::npos ||
  428. static_cast<String::size_type>(startpos) >= x.length() ||
  429. static_cast<String::size_type>(startpos) >= y.length()) return String();
  430. String::const_iterator xs(x.begin() + startpos);
  431. String::const_iterator ys(y.begin() + startpos);
  432. String::size_type l(0);
  433. while (xs != x.end() && ys != y.end() && *xs++ == *ys++) l++;
  434. return String(x, startpos, l);
  435. }
  436. String common_suffix(const string &x, const string &y,
  437. Int startpos) {
  438. if (startpos >= 0 ||
  439. startpos + Int(x.length()) < 0 ||
  440. startpos + Int(y.length()) < 0) return String();
  441. String::const_iterator xs(x.end() + startpos+1);
  442. String::const_iterator ys(y.end() + startpos+1);
  443. String::size_type l(0);
  444. while (xs != x.begin() && ys != y.begin() && *--xs == *--ys) l++;
  445. return String(x, x.length()+startpos+1-l, l);
  446. }
  447. String join(string src[], Int n, const string& sep) {
  448. String x;
  449. for (Int i=0; i<n; i++) {
  450. x += src[i];
  451. if (i != n-1) x += sep;
  452. }
  453. return x;
  454. }
  455. Int fcompare(String x, String y) {
  456. x.downcase();
  457. y.downcase();
  458. return x.compare(y);
  459. }
  460. // SubString
  461. SubString &SubString::operator=(const SubString &str) {
  462. if (this != &str) *this = String(str);
  463. return *this;
  464. }
  465. SubString &SubString::operator=(const String &str) {
  466. const_cast<string &>(ref_p).replace(pos_p, len_p, str);
  467. return *this;
  468. }
  469. SubString &SubString::operator=(const Char *s) {
  470. const_cast<string &>(ref_p).replace(pos_p, len_p, s);
  471. return *this;
  472. }
  473. SubString &SubString::operator=(const Char c) {
  474. const_cast<string &>(ref_p).replace(pos_p, len_p, 1, c);
  475. return *this;
  476. }
  477. } //# NAMESPACE CASA - END
  478. // Create some needed templates
  479. #if !defined(AIPS_AUTO_STL)
  480. #if defined(__GNUG__)
  481. template void std::__reverse<char*>(char *, char *, std::random_access_iterator_tag);
  482. #endif
  483. #if defined(AIPS_SUN_NATIVE)
  484. template void std::__reverse(char *, char *, std::random_access_iterator_tag);
  485. template std::istream& __rwstd::rw_extract_string ( std::istream&, std::string&, std::char_traits<char>);
  486. #endif
  487. template char *std::transform<char *>(char *, char *, char *, int (*)(int));
  488. #if defined(AIPS_GCC3)
  489. template void std::__reverse<string::iterator>(string::iterator, string::iterator, std::random_access_iterator_tag);
  490. template string::iterator std::transform<string::iterator>(string::iterator, string::iterator, string::iterator, int (*)(int));
  491. #endif
  492. #endif