PageRenderTime 50ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/bzflag-1.10.5.20040426/include/TextUtils.h

https://bitbucket.org/minnesotaice/frozendocs
C Header | 540 lines | 341 code | 86 blank | 113 comment | 118 complexity | 1bc63b1e411444895af5f457b6fd27ab MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-2.0, GPL-3.0
  1. /* bzflag
  2. * Copyright (c) 1993 - 2004 Tim Riker
  3. *
  4. * This package is free software; you can redistribute it and/or
  5. * modify it under the terms of the license found in the file
  6. * named COPYING that should have accompanied this file.
  7. *
  8. * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  9. * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  10. * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  11. */
  12. /*
  13. * common definitions
  14. */
  15. #ifndef __TEXTUTILS_H__
  16. #define __TEXTUTILS_H__
  17. #include <algorithm>
  18. #include <common.h>
  19. /** The string utility class provides basic functionality to parse and
  20. * format strings
  21. */
  22. class string_util {
  23. public:
  24. inline static std::string vformat(const char* fmt, va_list args) {
  25. // FIXME -- should prevent buffer overflow in all cases
  26. // not all platforms support vsnprintf so we'll use vsprintf and a
  27. // big temporary buffer and hope for the best.
  28. char buffer[8192];
  29. vsnprintf(buffer, 8192, fmt, args);
  30. return std::string(buffer);
  31. }
  32. inline static std::string format(const char* fmt, ...) {
  33. va_list args;
  34. va_start(args, fmt);
  35. std::string result = vformat(fmt, args);
  36. va_end(args);
  37. return result;
  38. }
  39. /** returns a string converted to lowercase
  40. */
  41. inline static std::string tolower(const std::string& s)
  42. {
  43. std::string trans = s;
  44. std::transform(trans.begin(), trans.end(), // source
  45. trans.begin(), // destination
  46. ::tolower);
  47. return trans;
  48. }
  49. /** returns a string converted to uppercase
  50. */
  51. inline static std::string toupper(const std::string& s)
  52. {
  53. std::string trans = s;
  54. std::transform (trans.begin(), trans.end(), // source
  55. trans.begin(), // destination
  56. ::toupper);
  57. return trans;
  58. }
  59. /** replace all of in in replaceMe with withMe
  60. */
  61. static std::string replace_all(const std::string& in, const std::string& replaceMe, const std::string& withMe)
  62. {
  63. std::string result;
  64. unsigned int beginPos = 0;
  65. unsigned int endPos = 0;
  66. std::ostringstream tempStream;
  67. endPos = (unsigned int)in.find(replaceMe);
  68. if (endPos == std::string::npos) return in; // can't find anything to replace
  69. if (replaceMe == "") return in; // can't replace nothing with something -- can do reverse
  70. while (endPos != std::string::npos){
  71. // push the part up to
  72. tempStream << in.substr(beginPos,endPos-beginPos);
  73. tempStream << withMe;
  74. beginPos = endPos + replaceMe.size();
  75. endPos = (unsigned int)in.find(replaceMe,beginPos);
  76. }
  77. tempStream << in.substr(beginPos);
  78. return tempStream.str();
  79. }
  80. /**
  81. * Get a vector of strings from a string, using all of chars of thedelims
  82. * string as separators. If maxTokens > 0, then the last 'token' maycontain delimiters
  83. * as it just returns the rest of the line
  84. * if you specify use quotes then tokens can be grouped in quotes and delimeters
  85. * inside quotes are ignored.
  86. * Hence /ban "Mr Blahblah" isajerk parses to "/ban", "Mr Blahlah" and "isajerk"
  87. * but so does "Mr Blahblah" "isajerk", so if you want 3 tokens and a delimeter
  88. * is in one of the tokens, by puting quotes around it you can get the correct
  89. * parsing. When use quotes is enabled, \'s and "'s should\can be escaped with \
  90. * escaping is not currently done for any other character.
  91. * Should not have " as a delimeter if you want to use quotes
  92. */
  93. static std::vector<std::string> tokenize(const std::string& in, const std::string delims, const int maxTokens = 0, const bool useQuotes = false){
  94. std::vector<std::string> tokens;
  95. int numTokens = 0;
  96. bool inQuote = false;
  97. bool enoughTokens;
  98. unsigned int pos = 0;
  99. int currentChar;
  100. std::ostringstream currentToken;
  101. pos = (unsigned int)in.find_first_not_of(delims);
  102. currentChar = (pos == std::string::npos)? -1: in[pos];
  103. enoughTokens = (maxTokens && (numTokens >= (maxTokens-1)));
  104. while (pos != std::string::npos && !enoughTokens){
  105. // get next token
  106. bool tokenDone = false;
  107. bool foundSlash = false;
  108. currentChar = (pos < in.size()) ? in[pos] : -1;
  109. while ((currentChar != -1) && !tokenDone){
  110. tokenDone = false;
  111. if (delims.find(currentChar) != std::string::npos && !inQuote) { // currentChar is a delim
  112. pos ++;
  113. break; // breaks out of while look
  114. }
  115. if (!useQuotes){
  116. currentToken << char(currentChar);
  117. } else {
  118. switch (currentChar){
  119. case '\\' : // found a slash
  120. if (foundSlash){
  121. currentToken << char(currentChar);
  122. foundSlash = false;
  123. } else {
  124. foundSlash = true;
  125. }
  126. break;
  127. case '\"' : // found a quote
  128. if (foundSlash){ // found \"
  129. currentToken << char(currentChar);
  130. foundSlash = false;
  131. } else { // found unescaped "
  132. if (inQuote){ // exiting a quote
  133. // finish off current token
  134. tokenDone = true;
  135. inQuote = false;
  136. //slurp off one additional delimeter if possible
  137. if ( (pos+1 < in.size()) && (delims.find(in[pos+1]) != std::string::npos)){
  138. pos++;
  139. }
  140. } else { // entering a quote
  141. // finish off current token
  142. tokenDone = true;
  143. inQuote = true;
  144. }
  145. }
  146. break;
  147. default:
  148. if (foundSlash){ // don't care about slashes except for above cases
  149. currentToken << '\\';
  150. foundSlash = false;
  151. }
  152. currentToken << char(currentChar);
  153. break;
  154. }
  155. }
  156. pos ++;
  157. currentChar = (pos < in.size() )? in[pos] : -1;
  158. } // end of getting a Token
  159. if (currentToken.str().size() > 0){ // if the token is something add to list
  160. tokens.push_back(currentToken.str());
  161. currentToken.str("");
  162. numTokens ++;
  163. }
  164. enoughTokens = (maxTokens && (numTokens >= (maxTokens-1)));
  165. if (enoughTokens){
  166. break;
  167. } else{
  168. pos = (unsigned int)in.find_first_not_of(delims,pos);
  169. }
  170. } // end of getting all tokens -- either EOL or max tokens reached
  171. if (enoughTokens && pos != std::string::npos){
  172. std::string lastToken = in.substr(pos);
  173. if (lastToken.size() > 0)
  174. tokens.push_back(lastToken);
  175. }
  176. return tokens;
  177. }
  178. static int parseDuration(std::string &duration)
  179. {
  180. int durationInt = 0;
  181. int t = 0;
  182. int len = (int)duration.length();
  183. for(int i=0; i < len; i++) {
  184. if( isdigit(duration[i]) ) {
  185. t = t * 10 + (duration[i] - '0');
  186. }
  187. else if(duration[i] == 'h' || duration[i] == 'H') {
  188. durationInt += (t * 60);
  189. t = 0;
  190. }
  191. else if(duration[i] == 'd' || duration[i] == 'D') {
  192. durationInt += (t * 1440);
  193. t = 0;
  194. }
  195. else if(duration[i] == 'w' || duration[i] == 'w') {
  196. durationInt += (t * 10080);
  197. t = 0;
  198. }
  199. }
  200. durationInt += t;
  201. return durationInt;
  202. }
  203. };
  204. // C h a r a c t e r c o m p a r i s o n
  205. /** compare_nocase is strait from Stroustrup. This implementation uses
  206. * strings instead of char arrays and includes a maxlength bounds check.
  207. * It compares two strings and returns 0 if equal, <0 if s1 is less than
  208. * s2, and >0 if s1 is greater than s2.
  209. */
  210. inline static int compare_nocase(const std::string& s1, const std::string &s2, int maxlength=4096)
  211. {
  212. std::string::const_iterator p1 = s1.begin();
  213. std::string::const_iterator p2 = s2.begin();
  214. int i=0;
  215. while (p1 != s1.end() && p2 != s2.end()) {
  216. if (i >= maxlength) {
  217. return 0;
  218. }
  219. if (tolower(*p1) != tolower(*p2)) {
  220. return (tolower(*p1) < tolower(*p2)) ? -1 : 1;
  221. }
  222. ++p1;
  223. ++p2;
  224. ++i;
  225. }
  226. return (s2.size() == s1.size()) ? 0 : (s1.size() < s2.size()) ? -1 : 1; // size is unsigned
  227. }
  228. /** utility function returns truthfully whether
  229. * given character is a letter.
  230. */
  231. inline bool isAlphabetic(const char c)
  232. {
  233. if (( c > 64 && c < 91) ||
  234. ( c > 96 && c < 123)) {
  235. return true;
  236. }
  237. return false;
  238. }
  239. /** utility function returns truthfully whether
  240. * given character is a number.
  241. */
  242. inline bool isNumeric(const char c)
  243. {
  244. if (( c > 47 && c < 58)) {
  245. return true;
  246. }
  247. return false;
  248. }
  249. /** utility function returns truthfully whether
  250. * a given character is printable whitespace.
  251. * this includes newline, carriage returns, tabs
  252. * and spaces.
  253. */
  254. inline bool isWhitespace(const char c)
  255. {
  256. if ((( c >= 9 ) && ( c <= 13 )) ||
  257. (c == 32)) {
  258. return true;
  259. }
  260. return false;
  261. }
  262. /** utility function returns truthfully whether
  263. * a given character is punctuation.
  264. */
  265. inline bool isPunctuation(const char c)
  266. {
  267. if (( c > 32 && c < 48) ||
  268. ( c > 57 && c < 65) ||
  269. ( c > 90 && c < 97) ||
  270. ( c > 122 && c < 127)) {
  271. return true;
  272. }
  273. return false;
  274. }
  275. /** utility function returns truthfully whether
  276. * given character is an alphanumeric. this is
  277. * strictly letters and numbers.
  278. */
  279. inline bool isAlphanumeric(const char c)
  280. {
  281. if ( isAlphabetic(c) || isNumeric(c) ) {
  282. return true;
  283. }
  284. return false;
  285. }
  286. /** utility function returns truthfully whether
  287. * given character is printable. this includes
  288. * letters, numbers, and punctuation.
  289. * (but NOT whitespace)
  290. */
  291. inline bool isVisible(const char c)
  292. {
  293. if ( isAlphanumeric(c) || isPunctuation(c) ) {
  294. return true;
  295. }
  296. return false;
  297. }
  298. /** utility function returns truthfully whether
  299. * given character is printable. this includes
  300. * letters, numbers, punctuation, and whitespace
  301. */
  302. inline bool isPrintable(const char c)
  303. {
  304. if ( isVisible(c) || isWhitespace(c) ) {
  305. return false;
  306. }
  307. return true;
  308. }
  309. // S t r i n g i t e r a t i o n
  310. /** utility method that returns the position of the
  311. * first alphanumeric character from a string
  312. */
  313. inline int firstAlphanumeric(const std::string &input, unsigned short int max=4096)
  314. {
  315. if (input.size() == 0) {
  316. return -1;
  317. }
  318. int i = 0;
  319. while (!isAlphanumeric(input[i]) && (i < max)) {
  320. i++;
  321. }
  322. return i;
  323. }
  324. /** utility method that returns the position of the
  325. * first non-alphanumeric character from a string
  326. */
  327. inline int firstNonalphanumeric(const std::string &input, unsigned short int max=4096)
  328. {
  329. if (input.size() == 0) {
  330. return -1;
  331. }
  332. int i = 0;
  333. while (isAlphanumeric(input[i]) && (i < max)) {
  334. i++;
  335. }
  336. return i;
  337. }
  338. /** utility method that returns the position of the
  339. * first printable character from a string
  340. */
  341. inline int firstPrintable(const std::string &input, unsigned short int max=4096)
  342. {
  343. if (input.size() == 0) {
  344. return -1;
  345. }
  346. int i = 0;
  347. while (!isPrintable(input[i]) && (i < max)) {
  348. i++;
  349. }
  350. return i;
  351. }
  352. /** utility method that returns the position of the
  353. * first non-printable character from a string
  354. */
  355. inline int firstNonprintable(const std::string &input, unsigned short int max=4096)
  356. {
  357. if (input.size() == 0) {
  358. return -1;
  359. }
  360. int i = 0;
  361. while (isPrintable(input[i]) && (i < max)) {
  362. i++;
  363. }
  364. return i;
  365. }
  366. /** utility method that returns the position of the
  367. * first visible character from a string
  368. */
  369. inline int firstVisible(const std::string &input, unsigned short int max=4096)
  370. {
  371. if (input.size() == 0) {
  372. return -1;
  373. }
  374. int i = 0;
  375. while (isVisible(input[i]) && (i < max)) {
  376. i++;
  377. }
  378. return i;
  379. }
  380. /** utility method that returns the position of the
  381. * first non visible character from a string (control
  382. * codes or whitespace
  383. */
  384. inline int firstNonvisible(const std::string &input, unsigned short int max=4096)
  385. {
  386. if (input.size() == 0) {
  387. return -1;
  388. }
  389. int i = 0;
  390. while (!isVisible(input[i]) && (i < max)) {
  391. i++;
  392. }
  393. return i;
  394. }
  395. /** utility method that returns the position of the
  396. * first alphabetic character from a string
  397. */
  398. inline int firstAlphabetic(const std::string &input, unsigned short int max=4096)
  399. {
  400. if (input.size() == 0) {
  401. return -1;
  402. }
  403. int i = 0;
  404. while (!isAlphabetic(input[i]) && (i < max)) {
  405. i++;
  406. }
  407. return i;
  408. }
  409. /** utility method that returns the position of the
  410. * first printable character from a string
  411. */
  412. inline int firstNonalphabetic(const std::string &input, unsigned short int max=4096)
  413. {
  414. if (input.size() == 0) {
  415. return -1;
  416. }
  417. int i = 0;
  418. while (isAlphabetic(input[i]) && (i < max)) {
  419. i++;
  420. }
  421. return i;
  422. }
  423. /** url-encodes a string
  424. */
  425. inline std::string url_encode(std::string text)
  426. {
  427. char c;
  428. char hex[5];
  429. int i;
  430. std::string destination;
  431. for (i=0; i < (int) text.size(); i++) {
  432. c = text[i];
  433. if (isAlphanumeric(c)) {
  434. destination+=c;
  435. } else if (isWhitespace(c)) {
  436. destination+='+';
  437. } else {
  438. destination+='%';
  439. sprintf(hex, "%-2.2X", c);
  440. destination.append(hex);
  441. }
  442. }
  443. return destination;
  444. }
  445. // so we can keep a map with strings as the key
  446. inline bool operator < (const std::string &s1,const std::string &s2) { return (s1.compare(s2)<0);}
  447. #endif // __TEXTUTILS_H__
  448. // Local Variables: ***
  449. // mode:C++ ***
  450. // tab-width: 8 ***
  451. // c-basic-offset: 2 ***
  452. // indent-tabs-mode: t ***
  453. // End: ***
  454. // ex: shiftwidth=2 tabstop=8