| 298 | } |
| 299 | |
| 300 | StatusOr<std::vector<std::string>> SplitArguments(std::string_view in) { |
| 301 | std::vector<std::string> arguments; |
| 302 | std::string current_string; |
| 303 | |
| 304 | enum State { NORMAL, DOUBLE_QUOTED, SINGLE_QUOTED, ESCAPE } state = NORMAL; |
| 305 | |
| 306 | bool done = false; |
| 307 | for (size_t i = 0; i < in.size() && !done; i++) { |
| 308 | const auto c = in[i]; |
| 309 | switch (state) { |
| 310 | case NORMAL: |
| 311 | if (std::isspace(c)) { |
| 312 | if (!current_string.empty()) { |
| 313 | arguments.emplace_back(std::move(current_string)); |
| 314 | current_string.clear(); |
| 315 | } |
| 316 | } else if (c == '\r' || c == '\n' || c == '\t') { |
| 317 | done = true; |
| 318 | } else if (c == '"') { |
| 319 | state = DOUBLE_QUOTED; |
| 320 | } else if (c == '\'') { |
| 321 | state = SINGLE_QUOTED; |
| 322 | } else { |
| 323 | current_string.push_back(c); |
| 324 | } |
| 325 | break; |
| 326 | case SINGLE_QUOTED: |
| 327 | if (c == '\\' && (i + 1) < in.size() && in[i + 1] == '\'') { |
| 328 | current_string.push_back('\''); |
| 329 | i++; |
| 330 | } else if (c == '\'') { |
| 331 | // |
| 332 | if (i + 1 < in.size() && !std::isspace(in[i + 1])) { |
| 333 | return {Status::NotOK, "the closed single quote must be followed by a space"}; |
| 334 | } |
| 335 | state = NORMAL; |
| 336 | } else { |
| 337 | current_string.push_back(c); |
| 338 | } |
| 339 | break; |
| 340 | case DOUBLE_QUOTED: |
| 341 | if (c == '\\') { |
| 342 | state = ESCAPE; |
| 343 | } else if (c == '"') { |
| 344 | if (i + 1 < in.size() && !std::isspace(in[i + 1])) { |
| 345 | return {Status::NotOK, "the closed double quote must be followed by a space"}; |
| 346 | } |
| 347 | state = NORMAL; |
| 348 | } else { |
| 349 | current_string.push_back(c); |
| 350 | } |
| 351 | break; |
| 352 | case ESCAPE: |
| 353 | // It's the hex digit after the \x |
| 354 | if (c == 'x' && (i + 2) < in.size() && std::isxdigit(in[i + 1]) && std::isxdigit(in[i + 2])) { |
| 355 | // Convert the hex digit to a char |
| 356 | auto hex_byte = static_cast<char>(HexDigitToInt(in[i + 1]) * 16 | HexDigitToInt(in[i + 2])); |
| 357 | current_string.push_back(hex_byte); |