1 /*
2 * Copyright (C) 2022 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/cvd/parser/cf_configs_common.h"
17
18 #include <android-base/logging.h>
19 namespace cuttlefish {
20
21 /**
22 * Validate Json data Name and type
23 */
ValidateTypo(const Json::Value & root,const std::map<std::string,Json::ValueType> & map)24 Result<void> ValidateTypo(const Json::Value& root,
25 const std::map<std::string, Json::ValueType>& map) {
26 for (const std::string& flag : root.getMemberNames()) {
27 CF_EXPECT(map.count(flag) != 0 , "Invalid flag name (typo) , Param --> " << flag<< " not recognized");
28 CF_EXPECT(root[flag].isConvertibleTo(map.at(flag)), "Invalid flag typ"<< flag);
29 }
30 return {};
31 }
32
ValidateIntConfig(const Json::Value & instances,const std::string & group,const std::string & json_flag,std::function<Result<void> (int)> validate_config)33 Result<void> ValidateIntConfig(
34 const Json::Value& instances, const std::string& group,
35 const std::string& json_flag,
36 std::function<Result<void>(int)> validate_config) {
37 // Allocate and initialize with default values
38 int size = instances.size();
39 for (int i = 0; i < size; i++) {
40 if (instances[i].isMember(group) &&
41 (instances[i][group].isMember(json_flag))) {
42 int flag = instances[i][group][json_flag].asInt();
43 CF_EXPECT(validate_config(flag), "Invalid flag value \"" << flag << "\"");
44 }
45 }
46 return {};
47 }
48
ValidateIntConfigSubGroup(const Json::Value & instances,const std::string & group,const std::string & subgroup,const std::string & json_flag,std::function<Result<void> (int)> validate_config)49 Result<void> ValidateIntConfigSubGroup(
50 const Json::Value& instances, const std::string& group,
51 const std::string& subgroup, const std::string& json_flag,
52 std::function<Result<void>(int)> validate_config) {
53 // Allocate and initialize with default values
54 int size = instances.size();
55 for (int i = 0; i < size; i++) {
56 if (instances[i].isMember(group) &&
57 (instances[i][group].isMember(subgroup)) &&
58 (instances[i][group][subgroup].isMember(json_flag))) {
59 int flag = instances[i][group][subgroup][json_flag].asInt();
60 CF_EXPECT(validate_config(flag), "Invalid flag value \"" << flag << "\"");
61 }
62 }
63 return {};
64 }
65
ValidateStringConfig(const Json::Value & instances,const std::string & group,const std::string & json_flag,std::function<Result<void> (const std::string &)> validate_config)66 Result<void> ValidateStringConfig(
67 const Json::Value& instances, const std::string& group,
68 const std::string& json_flag,
69 std::function<Result<void>(const std::string&)> validate_config) {
70 // Allocate and initialize with default values
71 int size = instances.size();
72 for (int i = 0; i < size; i++) {
73 if (instances[i].isMember(group) &&
74 (instances[i][group].isMember(json_flag))) {
75 // Validate input parameter
76 std::string flag = instances[i][group][json_flag].asString();
77 CF_EXPECT(validate_config(flag), "Invalid flag value \"" << flag << "\"");
78 }
79 }
80 return {};
81 }
82
ValidateStringConfigSubGroup(const Json::Value & instances,const std::string & group,const std::string & subgroup,const std::string & json_flag,std::function<Result<void> (const std::string &)> validate_config)83 Result<void> ValidateStringConfigSubGroup(
84 const Json::Value& instances, const std::string& group,
85 const std::string& subgroup, const std::string& json_flag,
86 std::function<Result<void>(const std::string&)> validate_config) {
87 // Allocate and initialize with default values
88 int size = instances.size();
89 for (int i = 0; i < size; i++) {
90 if (!instances[i].isMember(group) ||
91 (!instances[i][group].isMember(subgroup)) ||
92 (!instances[i][group][subgroup].isMember(json_flag))) {
93 std::string flag = instances[i][group][subgroup][json_flag].asString();
94 CF_EXPECT(validate_config(flag), "Invalid flag value \"" << flag << "\"");
95 }
96 }
97 return {};
98 }
99
InitIntConfig(Json::Value & instances,const std::string & group,const std::string & json_flag,int default_value)100 void InitIntConfig(Json::Value& instances, const std::string& group,
101 const std::string& json_flag, int default_value) {
102 // Allocate and initialize with default values
103 int size = instances.size();
104 for (int i = 0; i < size; i++) {
105 if (!instances[i].isMember(group) ||
106 (!instances[i][group].isMember(json_flag))) {
107 instances[i][group][json_flag] = default_value;
108 }
109 }
110 }
111
InitIntConfigSubGroup(Json::Value & instances,const std::string & group,const std::string & subgroup,const std::string & json_flag,int default_value)112 void InitIntConfigSubGroup(Json::Value& instances, const std::string& group,
113 const std::string& subgroup,
114 const std::string& json_flag, int default_value) {
115 // Allocate and initialize with default values
116 int size = instances.size();
117 for (int i = 0; i < size; i++) {
118 if (!instances[i].isMember(group) ||
119 (!instances[i][group].isMember(subgroup)) ||
120 (!instances[i][group][subgroup].isMember(json_flag))) {
121 instances[i][group][subgroup][json_flag] = default_value;
122 }
123 }
124 }
125
InitIntConfigSubGroupVector(Json::Value & instances,const std::string & group,const std::string & subgroup,const std::string & json_flag,int default_value)126 void InitIntConfigSubGroupVector(Json::Value& instances,
127 const std::string& group,
128 const std::string& subgroup,
129 const std::string& json_flag,
130 int default_value) {
131 // Allocate and initialize with default values
132 for (int i = 0; i < instances.size(); i++) {
133 if (!instances[i].isMember(group) ||
134 (!instances[i][group].isMember(subgroup)) ||
135 (instances[i][group][subgroup].size() == 0)) {
136 instances[i][group][subgroup][0][json_flag] = default_value;
137
138 } else {
139 // Check the whole array
140 int vector_size = instances[i][group][subgroup].size();
141 for (int j = 0; j < vector_size; j++) {
142 if (!instances[i][group][subgroup][j].isMember(json_flag)) {
143 instances[i][group][subgroup][j][json_flag] = default_value;
144 }
145 }
146 }
147 }
148 }
149
InitStringConfig(Json::Value & instances,const std::string & group,const std::string & json_flag,const std::string & default_value)150 void InitStringConfig(Json::Value& instances, const std::string& group,
151 const std::string& json_flag, const std::string& default_value) {
152 // Allocate and initialize with default values
153 int size = instances.size();
154 for (int i = 0; i < size; i++) {
155 if (!instances[i].isMember(group) ||
156 (!instances[i][group].isMember(json_flag))) {
157 instances[i][group][json_flag] = default_value;
158 }
159 }
160 }
161
InitStringConfigSubGroup(Json::Value & instances,const std::string & group,const std::string & subgroup,const std::string & json_flag,const std::string & default_value)162 void InitStringConfigSubGroup(Json::Value& instances, const std::string& group,
163 const std::string& subgroup,
164 const std::string& json_flag,
165 const std::string& default_value) {
166 // Allocate and initialize with default values
167 int size = instances.size();
168 for (int i = 0; i < size; i++) {
169 if (!instances[i].isMember(group) ||
170 (!instances[i][group].isMember(subgroup)) ||
171 (!instances[i][group][subgroup].isMember(json_flag))) {
172 instances[i][group][subgroup][json_flag] = default_value;
173 }
174 }
175 }
176
InitBoolConfig(Json::Value & instances,const std::string & group,const std::string & json_flag,const bool default_value)177 void InitBoolConfig(Json::Value& instances, const std::string& group,
178 const std::string& json_flag, const bool default_value) {
179 // Allocate and initialize with default values
180 int size = instances.size();
181 for (int i = 0; i < size; i++) {
182 if (!instances[i].isMember(group) ||
183 (!instances[i][group].isMember(json_flag))) {
184 instances[i][group][json_flag] = default_value;
185 }
186 }
187 }
188
InitBoolConfigSubGroup(Json::Value & instances,const std::string & group,const std::string & subgroup,const std::string & json_flag,const bool default_value)189 void InitBoolConfigSubGroup(Json::Value& instances, const std::string& group,
190 const std::string& subgroup,
191 const std::string& json_flag,
192 const bool default_value) {
193 // Allocate and initialize with default values
194 int size = instances.size();
195 for (int i = 0; i < size; i++) {
196 if (!instances[i].isMember(group) ||
197 (!instances[i][group].isMember(subgroup)) ||
198 (!instances[i][group][subgroup].isMember(json_flag))) {
199 instances[i][group][subgroup][json_flag] = default_value;
200 }
201 }
202 }
203
204 // TODO(b/255384531) for using variadic functions
205
GenerateGflag(const Json::Value & instances,const std::string & gflag_name,const std::string & group,const std::string & json_flag)206 std::string GenerateGflag(const Json::Value& instances,
207 const std::string& gflag_name,
208 const std::string& group,
209 const std::string& json_flag) {
210 int size = instances.size();
211 std::stringstream buff;
212 // Append Header
213 buff << "--" << gflag_name << "=";
214 // Append values
215 for (int i = 0; i < size; i++) {
216 buff << instances[i][group][json_flag].asString();
217 if (i != size - 1) {
218 buff << ",";
219 }
220 }
221 return buff.str();
222 }
223
GenerateGflagSubGroup(const Json::Value & instances,const std::string & gflag_name,const std::string & group,const std::string & subgroup,const std::string & json_flag)224 std::string GenerateGflagSubGroup(const Json::Value& instances,
225 const std::string& gflag_name,
226 const std::string& group,
227 const std::string& subgroup,
228 const std::string& json_flag) {
229 int size = instances.size();
230 std::stringstream buff;
231 // Append Header
232 buff << "--" << gflag_name << "=";
233 // Append values
234 for (int i = 0; i < size; i++) {
235 buff << instances[i][group][subgroup][json_flag].asString();
236 if (i != size - 1){ buff << ",";}
237 }
238 return buff.str();
239 }
240
MergeResults(std::vector<std::string> first_list,std::vector<std::string> scond_list)241 std::vector<std::string> MergeResults(std::vector<std::string> first_list,
242 std::vector<std::string> scond_list) {
243 std::vector<std::string> result;
244 result.reserve(first_list.size() + scond_list.size());
245 result.insert(result.begin(), first_list.begin(), first_list.end());
246 result.insert(result.end(), scond_list.begin(), scond_list.end());
247 return result;
248 }
249
250 /**
251 * @brief This function merges two json objects and override json tree in dst
252 * with src json keys
253 *
254 * @param dst : destination json object tree(modified in place)
255 * @param src : input json object tree to be merged
256 */
MergeTwoJsonObjs(Json::Value & dst,const Json::Value & src)257 void MergeTwoJsonObjs(Json::Value& dst, const Json::Value& src) {
258 // Merge all members of src into dst
259 for (const auto& key : src.getMemberNames()) {
260 if (src[key].type() == Json::arrayValue) {
261 for (int i = 0; i < src[key].size(); i++) {
262 MergeTwoJsonObjs(dst[key][i], src[key][i]);
263 }
264 } else if (src[key].type() == Json::objectValue) {
265 MergeTwoJsonObjs(dst[key], src[key]);
266 } else {
267 dst[key] = src[key];
268 }
269 }
270 }
271
272 } // namespace cuttlefish
273