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) {
55     pos += 1;  // npos + 1 = 0
56   }
57   command_.remove_prefix(std::min(pos, command_.size()));
58   return str;
59 }
60 
61 /**
62  * Parses the next base 10 integer in the AT command and convert to upper case
63  * hex string
64  * returns the hex string on success and "" on fail
65  * updates command_
66  *
67  * Specially, for AT+CRSM
68  */
GetNextStrDeciToHex()69 std::string CommandParser::GetNextStrDeciToHex() {
70   std::string str;
71   int value = GetNextInt();
72   if (value == -1) {
73     return {};
74   } else {
75     std::stringstream ss;
76     ss << std::hex << std::uppercase << value;
77     return ss.str();
78   }
79 }
80 
parse_int(const std::string & snumber,int base)81 static int parse_int(const std::string& snumber, int base) {
82   if (snumber.empty()) {
83     return -1;
84   }
85   const char* p = snumber.c_str();
86   char* p_end = nullptr;
87   errno = 0;
88   const long lval = std::strtol(p, &p_end, base);
89   if (p == p_end) {
90     return -1;
91   }
92   const bool range_error = errno == ERANGE;
93 
94   if (range_error) {
95     return -1;
96   }
97   return lval;
98 }
99 
100 /**
101  * Parses the next base 10 integer in the AT command
102  * returns the value on success and -1 on fail
103  * updates command_
104  */
GetNextInt()105 int CommandParser::GetNextInt() {
106   if (command_.empty()) {
107     return -1;
108   }
109   std::string sub(GetNextStr(','));
110 
111   int value = parse_int(sub, 10);
112 
113   return value;
114 }
115 
116 /**
117  * Parses the next base 16 integer in the AT command
118  * returns the value on success and -1 on fail
119  * updates command_
120  */
GetNextHexInt()121 int CommandParser::GetNextHexInt() {
122   if (command_.empty()) {
123     return -1;
124   }
125 
126   std::string sub(GetNextStr(','));
127   int value = parse_int(sub, 16);
128   return value;
129 }
130 
131 }  // namespace cuttlefish
132