| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/developer/cmd/command.h" |
| |
| namespace cmd { |
| |
| Command::Command() = default; |
| |
| Command::~Command() = default; |
| |
| const char Command::kWhitespace[] = " \t\r\n"; |
| |
| bool Command::Parse(const std::string& line) { |
| args_.clear(); |
| size_t pos = 0; |
| while (pos != std::string::npos) { |
| size_t start = line.find_first_not_of(kWhitespace, pos); |
| if (start == std::string::npos) { |
| return true; |
| } |
| if (line[start] == '#') { |
| return true; |
| } |
| if (line[start] == '"') { |
| std::string token; |
| if (!ParseQuotedToken(line, start + 1, &token, &pos)) { |
| args_.clear(); |
| return false; |
| } |
| args_.push_back(std::move(token)); |
| } else { |
| size_t end = line.find_first_of(kWhitespace, start); |
| std::string token = line.substr(start, end - start); |
| if (token.find('"') != std::string::npos) { |
| args_.clear(); |
| parse_error_ = "Unexpected quotation in token."; |
| return false; |
| } |
| args_.push_back(std::move(token)); |
| pos = end; |
| } |
| } |
| return true; |
| } |
| |
| bool Command::ParseQuotedToken(const std::string& line, size_t pos, std::string* token, |
| size_t* end) { |
| std::vector<char> buffer; |
| while (pos < line.size()) { |
| char ch = line[pos++]; |
| switch (ch) { |
| case '\\': |
| if (pos == line.size()) { |
| parse_error_ = "Unterminated escape sequence."; |
| return false; |
| } |
| ch = line[pos++]; |
| switch (ch) { |
| case 't': |
| buffer.push_back('\t'); |
| break; |
| case 'n': |
| buffer.push_back('\n'); |
| break; |
| case 'r': |
| buffer.push_back('\r'); |
| break; |
| case '"': |
| buffer.push_back('\"'); |
| break; |
| case '\\': |
| buffer.push_back('\\'); |
| break; |
| default: |
| parse_error_ = "Unknown escape character: "; |
| parse_error_ += ch; |
| return false; |
| } |
| break; |
| case '"': |
| if (pos < line.size()) { |
| ch = line[pos]; |
| if (strchr(kWhitespace, ch) == nullptr) { |
| parse_error_ = "Ending quotation mark did not terminate token."; |
| return false; |
| } |
| } |
| *token = std::string(buffer.data(), buffer.size()); |
| *end = pos; |
| return true; |
| default: |
| buffer.push_back(ch); |
| break; |
| } |
| } |
| parse_error_ = "Unterminated quotation."; |
| return false; |
| } |
| |
| } // namespace cmd |