1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16
17 #include "appspawn_utils.h"
18 #include "command_lexer.h"
19
20 using namespace OHOS::AppSpawn;
21
22 enum class ParsingState {
23 INIT,
24 IN_WHITESPACE,
25 IN_ARGUMENT,
26 IN_SINGLE_QUOTE,
27 IN_DOUBLE_QUOTE,
28 };
29
GetAllArguments(std::vector<std::string> & args)30 bool CommandLexer::GetAllArguments(std::vector<std::string> &args)
31 {
32 constexpr char singleQuote = '\'';
33 constexpr char doubleQuote = '"';
34 ParsingState state = ParsingState::INIT;
35 std::string lastArg;
36
37 for (size_t i = 0; i < str_.size(); i++) {
38 switch (state) {
39 case ParsingState::INIT:
40 if (isspace(str_[i])) {
41 state = ParsingState::IN_WHITESPACE;
42 } else if (str_[i] == singleQuote) {
43 state = ParsingState::IN_SINGLE_QUOTE;
44 } else if (str_[i] == doubleQuote) {
45 state = ParsingState::IN_DOUBLE_QUOTE;
46 } else {
47 state = ParsingState::IN_ARGUMENT;
48 lastArg += str_[i];
49 }
50 break;
51 case ParsingState::IN_WHITESPACE:
52 if (str_[i] == singleQuote) {
53 state = ParsingState::IN_SINGLE_QUOTE;
54 } else if (str_[i] == doubleQuote) {
55 state = ParsingState::IN_DOUBLE_QUOTE;
56 } else if (!isspace(str_[i])) {
57 state = ParsingState::IN_ARGUMENT;
58 lastArg += str_[i];
59 }
60 break;
61 case ParsingState::IN_ARGUMENT:
62 if (isspace(str_[i])) {
63 args.push_back(std::move(lastArg));
64 // Whether a moved string is empty depends on the
65 // implementation of C++ std library, so clear() is called.
66 lastArg.clear();
67 state = ParsingState::IN_WHITESPACE;
68 } else if (str_[i] == singleQuote) {
69 state = ParsingState::IN_SINGLE_QUOTE;
70 } else if (str_[i] == doubleQuote) {
71 state = ParsingState::IN_DOUBLE_QUOTE;
72 } else {
73 lastArg += str_[i];
74 }
75 break;
76 case ParsingState::IN_SINGLE_QUOTE:
77 if (str_[i] == singleQuote) {
78 state = ParsingState::IN_ARGUMENT;
79 } else {
80 lastArg += str_[i];
81 }
82 break;
83 case ParsingState::IN_DOUBLE_QUOTE:
84 if (str_[i] == doubleQuote) {
85 state = ParsingState::IN_ARGUMENT;
86 } else {
87 lastArg += str_[i];
88 }
89 break;
90 }
91 }
92
93 if (state == ParsingState::IN_ARGUMENT) {
94 args.push_back(std::move(lastArg));
95 } else if (state == ParsingState::IN_SINGLE_QUOTE ||
96 state == ParsingState::IN_DOUBLE_QUOTE) {
97 APPSPAWN_LOGE("Parsing arguments failed: missing terminated quote");
98 args.clear();
99 return false;
100 }
101
102 return true;
103 }
104