| 238 | } |
| 239 | |
| 240 | std::vector<std::string> tokenize(const std::string& in, const std::string& delims, |
| 241 | const int maxTokens, const bool useQuotes, size_t offset) { |
| 242 | std::vector<std::string> tokens; |
| 243 | int numTokens = 0; |
| 244 | bool inQuote = false; |
| 245 | |
| 246 | std::ostringstream currentToken; |
| 247 | |
| 248 | std::string::size_type pos = in.find_first_not_of(delims, offset); |
| 249 | int currentChar = (pos == std::string::npos) ? -1 : in[pos]; |
| 250 | bool enoughTokens = (maxTokens && (numTokens >= (maxTokens - 1))); |
| 251 | |
| 252 | while (pos != std::string::npos && !enoughTokens) { |
| 253 | |
| 254 | // get next token |
| 255 | bool tokenDone = false; |
| 256 | bool foundSlash = false; |
| 257 | |
| 258 | currentChar = (pos < in.size()) ? in[pos] : -1; |
| 259 | while ((currentChar != -1) && !tokenDone) { |
| 260 | |
| 261 | tokenDone = false; |
| 262 | |
| 263 | if (delims.find(currentChar) != std::string::npos && !inQuote) { // currentChar is a delim |
| 264 | pos ++; |
| 265 | break; // breaks out of while loop |
| 266 | } |
| 267 | |
| 268 | if (!useQuotes) { |
| 269 | currentToken << char(currentChar); |
| 270 | } |
| 271 | else { |
| 272 | |
| 273 | switch (currentChar) { |
| 274 | case '\\' : // found a backslash |
| 275 | if (foundSlash) { |
| 276 | currentToken << char(currentChar); |
| 277 | foundSlash = false; |
| 278 | } |
| 279 | else { |
| 280 | foundSlash = true; |
| 281 | } |
| 282 | break; |
| 283 | case '\"' : // found a quote |
| 284 | if (foundSlash) { // found \" |
| 285 | currentToken << char(currentChar); |
| 286 | foundSlash = false; |
| 287 | } |
| 288 | else { // found unescaped " |
| 289 | if (inQuote) { // exiting a quote |
| 290 | // finish off current token |
| 291 | tokenDone = true; |
| 292 | inQuote = false; |
| 293 | //slurp off one additional delimeter if possible |
| 294 | if (pos + 1 < in.size() && |
| 295 | delims.find(in[pos + 1]) != std::string::npos) { |
| 296 | pos++; |
| 297 | } |
no test coverage detected