1 //
2 // Copyright (C) 2020 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include "host/commands/modem_simulator/command_parser.h"
17 
18 #include <sstream>
19 #include <string>
20 
21 namespace cuttlefish {
22 
23 /**
24  * Parses the next string between double quotes
25  * returns the string on success and "" on fail
26  * updates command_
27  */
GetNextStr()28 std::string_view CommandParser::GetNextStr() {
29   auto fpos = command_.find('\"');
30   if (fpos == std::string_view::npos) {
31     return {};
32   }
33 
34   auto spos = command_.find('\"', fpos + 1);
35   if (spos == std::string_view::npos) {
36     command_ = command_.substr(fpos + 1);
37     return {};
38   }
39 
40   auto str = command_.substr(fpos + 1, (spos - fpos - 1));
41   command_ = command_.substr(spos + 1);
42   SkipComma();
43   return str;
44 }
45 
46 /**
47  * Parses the next string before the flag
48  * If flag not exists, returns the whole command_
49  * updates command_
50  */
GetNextStr(char flag)51 std::string_view CommandParser::GetNextStr(char flag) {
52   auto pos = command_.find(flag);
53   auto str = command_.substr(0, pos);
54   if (pos != std::string_view::npos) pos += 1;  // npos + 1 = 0
55   command_.remove_prefix(std::min(pos, command_.size()));
56   return str;
57 }
58 
59 /**
60  * Parses the next base 10 integer in the AT command and convert to upper case
61  * hex string
62  * returns the hex string on success and "" on fail
63  * updates command_
64  *
65  * Specially, for AT+CRSM
66  */
GetNextStrDeciToHex()67 std::string CommandParser::GetNextStrDeciToHex() {
68   std::string str;
69   int value = GetNextInt();
70   if (value == -1) {
71     return {};
72   } else {
73     std::stringstream ss;
74     ss << std::hex << std::uppercase << value;
75     return ss.str();
76   }
77 }
78 
parse_int(const std::string & snumber,int base)79 static int parse_int(const std::string& snumber, int base) {
80   if (snumber.empty()) return -1;
81   const char* p = snumber.c_str();
82   char* p_end = nullptr;
83   errno = 0;
84   const long lval = std::strtol(p, &p_end, base);
85   if (p == p_end) {
86     return -1;
87   }
88   const bool range_error = errno == ERANGE;
89 
90   if (range_error) return -1;
91   return lval;
92 }
93 
94 /**
95  * Parses the next base 10 integer in the AT command
96  * returns the value on success and -1 on fail
97  * updates command_
98  */
GetNextInt()99 int CommandParser::GetNextInt() {
100   if (command_.empty()) {
101     return -1;
102   }
103   std::string sub(GetNextStr(','));
104 
105   int value = parse_int(sub, 10);
106 
107   return value;
108 }
109 
110 /**
111  * Parses the next base 16 integer in the AT command
112  * returns the value on success and -1 on fail
113  * updates command_
114  */
GetNextHexInt()115 int CommandParser::GetNextHexInt() {
116   if (command_.empty()) {
117     return -1;
118   }
119 
120   std::string sub(GetNextStr(','));
121   int value = parse_int(sub, 16);
122   return value;
123 }
124 
125 }  // namespace cuttlefish
126