You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

StringUtils.cpp 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #include "StringUtils.h"
  2. #include <algorithm>
  3. #include <iostream>
  4. #include <iterator>
  5. /**
  6. * get an extension from a filename
  7. * @param fileName a filename string
  8. * @return '' or a string with the found extension
  9. */
  10. const std::string getFilenameExtension(std::string const& fileName) {
  11. auto dotPos = fileName.find_last_of('.');
  12. if (dotPos != std::string::npos && dotPos + 1 != std::string::npos) {
  13. //std::cout << "StringUtils::getFilenameExtension - " << fileName.substr(dotPos + 1) << std::endl;
  14. return fileName.substr(dotPos + 1);
  15. }
  16. return "";
  17. }
  18. /**
  19. * convert string to lowercase
  20. * @param str string
  21. * @return lowercased version of str
  22. */
  23. const std::string toLowercase(const std::string &str) {
  24. std::string returnString = "";
  25. std::transform(str.begin(),
  26. str.end(),
  27. back_inserter(returnString),
  28. tolower);
  29. return returnString;
  30. /*
  31. std::string stringToLower(std::string s) {
  32. std::transform(s.begin(), s.end(), s.begin(),
  33. [](unsigned char c){ return std::tolower(c); });
  34. return s;
  35. */
  36. }
  37. std::vector<std::string> split(const std::string &text, char sep) {
  38. std::vector<std::string> tokens;
  39. std::size_t start = 0, end = 0;
  40. while ((end = text.find(sep, start)) != std::string::npos) {
  41. if (end != start) {
  42. tokens.push_back(text.substr(start, end - start));
  43. }
  44. start = end + 1;
  45. }
  46. if (end != start) {
  47. tokens.push_back(text.substr(start));
  48. }
  49. return tokens;
  50. }
  51. bool in_array(std::string needle, std::vector<std::string> haystack) {
  52. for(auto it : haystack) {
  53. if (it == needle) return true;
  54. }
  55. return false;
  56. }
  57. // FIXME: , in quotes or {} (JSON) <= top priority for 4chan
  58. std::vector<std::string> parseSepButNotBetween(std::string string, std::string sep, std::vector<std::string> open, std::vector<std::string> close) {
  59. //std::cout << "looking at [" << string << "]" << std::endl;
  60. std::vector<std::string> arr;
  61. size_t state = 0;
  62. size_t last = 0;
  63. size_t cursor;
  64. size_t scopeLevel = 0;
  65. for (cursor = 0; cursor < string.length(); cursor++) {
  66. auto it = string[cursor];
  67. if (state == 0) {
  68. if (it == '{') {
  69. state = 1;
  70. scopeLevel++;
  71. } else if (it == '\'') {
  72. state = 4;
  73. } else if (it == '"') {
  74. state = 5;
  75. } else if (it == sep[0]) { // FIXME: only supports single char separators
  76. // flush buffer
  77. auto str3 = string.substr(last, last ? (cursor - last) : cursor);
  78. //std::cout << "from " << last << " to " << cursor << " pushing [" << str3 << "] it[" << it << "]" << std::endl;
  79. arr.push_back(str3);
  80. last = cursor + 1;
  81. }
  82. } else if (state == 1) {
  83. if (it == '{') {
  84. scopeLevel++;
  85. } else
  86. if (it == '}') {
  87. scopeLevel--;
  88. if (!scopeLevel) {
  89. state = 0;
  90. }
  91. }
  92. } else if (state == 4) {
  93. if (it == '\'') {
  94. if (string[cursor - 1] != '\\') {
  95. state = 0;
  96. }
  97. }
  98. } else if (state == 5) {
  99. if (it == '"') {
  100. if (string[cursor - 1] != '\\') {
  101. state = 0;
  102. }
  103. }
  104. }
  105. }
  106. // flush last bit
  107. auto str3 = string.substr(last, last - string.size());
  108. //std::cout << "ending on " << state << " pushing [" << str3 << "]" << std::endl;
  109. arr.push_back(str3);
  110. return arr;
  111. }
  112. /*
  113. std::vector<std::string> parseCommas(std::string string, std::string sep, std::vector<std::string> quotes) {
  114. std::vector<std::string> arr;
  115. if (!quotes.size()) {
  116. quotes.push_back("'");
  117. quotes.push_back("\"");
  118. }
  119. size_t mp = string.length();
  120. std::string str3 = "";
  121. for(int p = 0; p < mp; p++) {
  122. auto next = string.find(sep, p); // find next comma after p
  123. // if last string without a ,
  124. if (next == std::string::npos) {
  125. next = mp; // set to end
  126. }
  127. auto diff = next - p; // number of charaters to examine
  128. auto str2 = string.substr(p, diff); // get substring in this scan
  129. auto open = str2.substr(0, 1);
  130. str3 += str2;
  131. bool flush = true;
  132. if (in_array(open, quotes)) {
  133. auto last = trim(str2).substr(-1, 1);
  134. if (last!=open) {
  135. str3 += ',';
  136. flush = false;
  137. }
  138. }
  139. if (flush) {
  140. arr.push_back(str3);
  141. str3 = "";
  142. }
  143. p += diff;
  144. }
  145. return arr;
  146. }
  147. size_t findMatching(std::string string, std::string opens, std::string closes, std::string escape="\\") {
  148. // find open
  149. auto opos = string.find(open);
  150. if (opos == std::string::npos) {
  151. return 0;
  152. }
  153. auto pos = opos;
  154. while(pos != std::string::npos) {
  155. auto cpos = string.find(close, pos+(open==close?1:0)); // don't want to end up with the opening marker as the start
  156. if (escape!="") {
  157. auto prevchar = string.substr(cpos - escape.length(), escape.length()); // get previous char before cpos
  158. if (prevchar != escape) {
  159. return cpos;
  160. }
  161. }
  162. pos = cpos;
  163. }
  164. return 0;
  165. }
  166. */