1 /*
2 * Copyright (C) 2017 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
17 // Convert objects from and to strings.
18
19 #include "parse_string.h"
20
21 #include <android-base/parseint.h>
22
23 #include "constants-private.h"
24
25 namespace android {
26 using base::ParseUint;
27
28 namespace vintf {
29
30 static const std::string kRequired("required");
31 static const std::string kOptional("optional");
32 static const std::string kConfigPrefix("CONFIG_");
33
SplitString(const std::string & s,char c)34 std::vector<std::string> SplitString(const std::string &s, char c) {
35 std::vector<std::string> components;
36
37 size_t startPos = 0;
38 size_t matchPos;
39 while ((matchPos = s.find(c, startPos)) != std::string::npos) {
40 components.push_back(s.substr(startPos, matchPos - startPos));
41 startPos = matchPos + 1;
42 }
43
44 if (startPos <= s.length()) {
45 components.push_back(s.substr(startPos));
46 }
47 return components;
48 }
49
50 template <typename T>
operator <<(std::ostream & os,const std::vector<T> objs)51 std::ostream &operator<<(std::ostream &os, const std::vector<T> objs) {
52 bool first = true;
53 for (const T &v : objs) {
54 if (!first) {
55 os << ",";
56 }
57 os << v;
58 first = false;
59 }
60 return os;
61 }
62
63 template <typename T>
parse(const std::string & s,std::vector<T> * objs)64 bool parse(const std::string &s, std::vector<T> *objs) {
65 std::vector<std::string> v = SplitString(s, ',');
66 objs->resize(v.size());
67 size_t idx = 0;
68 for (const auto &item : v) {
69 T ver;
70 if (!parse(item, &ver)) {
71 return false;
72 }
73 objs->at(idx++) = ver;
74 }
75 return true;
76 }
77
78 template<typename E, typename Array>
parseEnum(const std::string & s,E * e,const Array & strings)79 bool parseEnum(const std::string &s, E *e, const Array &strings) {
80 for (size_t i = 0; i < strings.size(); ++i) {
81 if (s == strings.at(i)) {
82 *e = static_cast<E>(i);
83 return true;
84 }
85 }
86 return false;
87 }
88
89 #define DEFINE_PARSE_STREAMIN_FOR_ENUM(ENUM) \
90 bool parse(const std::string &s, ENUM *hf) { \
91 return parseEnum(s, hf, g##ENUM##Strings); \
92 } \
93 std::ostream &operator<<(std::ostream &os, ENUM hf) { \
94 return os << g##ENUM##Strings.at(static_cast<size_t>(hf)); \
95 } \
96
97 DEFINE_PARSE_STREAMIN_FOR_ENUM(HalFormat)
98 DEFINE_PARSE_STREAMIN_FOR_ENUM(Transport)
99 DEFINE_PARSE_STREAMIN_FOR_ENUM(Arch)
100 DEFINE_PARSE_STREAMIN_FOR_ENUM(KernelConfigType)
101 DEFINE_PARSE_STREAMIN_FOR_ENUM(Tristate)
102 DEFINE_PARSE_STREAMIN_FOR_ENUM(SchemaType)
103 DEFINE_PARSE_STREAMIN_FOR_ENUM(XmlSchemaFormat)
104
105 std::ostream &operator<<(std::ostream &os, const KernelConfigTypedValue &kctv) {
106 switch (kctv.mType) {
107 case KernelConfigType::STRING:
108 return os << kctv.mStringValue;
109 case KernelConfigType::INTEGER:
110 return os << to_string(kctv.mIntegerValue);
111 case KernelConfigType::RANGE:
112 return os << to_string(kctv.mRangeValue.first) << "-"
113 << to_string(kctv.mRangeValue.second);
114 case KernelConfigType::TRISTATE:
115 return os << to_string(kctv.mTristateValue);
116 }
117 }
118
parse(const std::string & s,Level * l)119 bool parse(const std::string& s, Level* l) {
120 if (s.empty()) {
121 *l = Level::UNSPECIFIED;
122 return true;
123 }
124 if (s == "legacy") {
125 *l = Level::LEGACY;
126 return true;
127 }
128 size_t value;
129 if (!ParseUint(s, &value)) {
130 return false;
131 }
132 *l = static_cast<Level>(value);
133 return true;
134 }
135
operator <<(std::ostream & os,Level l)136 std::ostream& operator<<(std::ostream& os, Level l) {
137 if (l == Level::UNSPECIFIED) {
138 return os;
139 }
140 if (l == Level::LEGACY) {
141 return os << "legacy";
142 }
143 return os << static_cast<size_t>(l);
144 }
145
146 // Notice that strtoull is used even though KernelConfigIntValue is signed int64_t,
147 // because strtoull can accept negative values as well.
148 // Notice that according to man strtoul, strtoull can actually accept
149 // -2^64 + 1 to 2^64 - 1, with the 65th bit truncated.
150 // ParseInt / ParseUint are not used because they do not handle signed hex very well.
151 template <typename T>
parseKernelConfigIntHelper(const std::string & s,T * i)152 bool parseKernelConfigIntHelper(const std::string &s, T *i) {
153 char *end;
154 errno = 0;
155 unsigned long long int ulli = strtoull(s.c_str(), &end, 0 /* base */);
156 // It is implementation defined that what value will be returned by strtoull
157 // in the error case, so we are checking errno directly here.
158 if (errno == 0 && s.c_str() != end && *end == '\0') {
159 *i = static_cast<T>(ulli);
160 return true;
161 }
162 return false;
163 }
164
parseKernelConfigInt(const std::string & s,int64_t * i)165 bool parseKernelConfigInt(const std::string &s, int64_t *i) {
166 return parseKernelConfigIntHelper(s, i);
167 }
168
parseKernelConfigInt(const std::string & s,uint64_t * i)169 bool parseKernelConfigInt(const std::string &s, uint64_t *i) {
170 return parseKernelConfigIntHelper(s, i);
171 }
172
parseRange(const std::string & s,KernelConfigRangeValue * range)173 bool parseRange(const std::string &s, KernelConfigRangeValue *range) {
174 auto pos = s.find('-');
175 if (pos == std::string::npos) {
176 return false;
177 }
178 return parseKernelConfigInt(s.substr(0, pos), &range->first)
179 && parseKernelConfigInt(s.substr(pos + 1), &range->second);
180 }
181
parse(const std::string & s,KernelConfigKey * key)182 bool parse(const std::string &s, KernelConfigKey *key) {
183 *key = s;
184 return true;
185 }
186
parseKernelConfigValue(const std::string & s,KernelConfigTypedValue * kctv)187 bool parseKernelConfigValue(const std::string &s, KernelConfigTypedValue *kctv) {
188 switch (kctv->mType) {
189 case KernelConfigType::STRING:
190 kctv->mStringValue = s;
191 return true;
192 case KernelConfigType::INTEGER:
193 return parseKernelConfigInt(s, &kctv->mIntegerValue);
194 case KernelConfigType::RANGE:
195 return parseRange(s, &kctv->mRangeValue);
196 case KernelConfigType::TRISTATE:
197 return parse(s, &kctv->mTristateValue);
198 }
199 }
200
parseKernelConfigTypedValue(const std::string & s,KernelConfigTypedValue * kctv)201 bool parseKernelConfigTypedValue(const std::string& s, KernelConfigTypedValue* kctv) {
202 if (s.size() > 1 && s[0] == '"' && s.back() == '"') {
203 kctv->mType = KernelConfigType::STRING;
204 kctv->mStringValue = s.substr(1, s.size()-2);
205 return true;
206 }
207 if (parseKernelConfigInt(s, &kctv->mIntegerValue)) {
208 kctv->mType = KernelConfigType::INTEGER;
209 return true;
210 }
211 if (parse(s, &kctv->mTristateValue)) {
212 kctv->mType = KernelConfigType::TRISTATE;
213 return true;
214 }
215 // Do not test for KernelConfigType::RANGE.
216 return false;
217 }
218
parse(const std::string & s,Version * ver)219 bool parse(const std::string &s, Version *ver) {
220 std::vector<std::string> v = SplitString(s, '.');
221 if (v.size() != 2) {
222 return false;
223 }
224 size_t major, minor;
225 if (!ParseUint(v[0], &major)) {
226 return false;
227 }
228 if (!ParseUint(v[1], &minor)) {
229 return false;
230 }
231 *ver = Version(major, minor);
232 return true;
233 }
234
operator <<(std::ostream & os,const Version & ver)235 std::ostream &operator<<(std::ostream &os, const Version &ver) {
236 return os << ver.majorVer << "." << ver.minorVer;
237 }
238
239 // Helper for parsing a VersionRange object. versionParser defines how the first half
240 // (before the '-' character) of the string is parsed.
parseVersionRange(const std::string & s,VersionRange * vr,const std::function<bool (const std::string &,Version *)> & versionParser)241 static bool parseVersionRange(
242 const std::string& s, VersionRange* vr,
243 const std::function<bool(const std::string&, Version*)>& versionParser) {
244 std::vector<std::string> v = SplitString(s, '-');
245 if (v.size() != 1 && v.size() != 2) {
246 return false;
247 }
248 Version minVer;
249 if (!versionParser(v[0], &minVer)) {
250 return false;
251 }
252 if (v.size() == 1) {
253 *vr = VersionRange(minVer.majorVer, minVer.minorVer);
254 } else {
255 size_t maxMinor;
256 if (!ParseUint(v[1], &maxMinor)) {
257 return false;
258 }
259 *vr = VersionRange(minVer.majorVer, minVer.minorVer, maxMinor);
260 }
261 return true;
262 }
263
parse(const std::string & s,VersionRange * vr)264 bool parse(const std::string& s, VersionRange* vr) {
265 bool (*versionParser)(const std::string&, Version*) = parse;
266 return parseVersionRange(s, vr, versionParser);
267 }
268
operator <<(std::ostream & os,const VersionRange & vr)269 std::ostream &operator<<(std::ostream &os, const VersionRange &vr) {
270 if (vr.isSingleVersion()) {
271 return os << vr.minVer();
272 }
273 return os << vr.minVer() << "-" << vr.maxMinor;
274 }
275
276 #pragma clang diagnostic push
277 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
parse(const std::string & s,VndkVersionRange * vr)278 bool parse(const std::string &s, VndkVersionRange *vr) {
279 std::vector<std::string> v = SplitString(s, '-');
280 if (v.size() != 1 && v.size() != 2) {
281 return false;
282 }
283 std::vector<std::string> minVector = SplitString(v[0], '.');
284 if (minVector.size() != 3) {
285 return false;
286 }
287 if (!ParseUint(minVector[0], &vr->sdk) ||
288 !ParseUint(minVector[1], &vr->vndk) ||
289 !ParseUint(minVector[2], &vr->patchMin)) {
290 return false;
291 }
292 if (v.size() == 1) {
293 vr->patchMax = vr->patchMin;
294 return true;
295 } else {
296 return ParseUint(v[1], &vr->patchMax);
297 }
298 }
299
operator <<(std::ostream & os,const VndkVersionRange & vr)300 std::ostream &operator<<(std::ostream &os, const VndkVersionRange &vr) {
301 os << vr.sdk << "." << vr.vndk << "." << vr.patchMin;
302 if (!vr.isSingleVersion()) {
303 os << "-" << vr.patchMax;
304 }
305 return os;
306 }
307 #pragma clang diagnostic pop
308
parse(const std::string & s,KernelVersion * kernelVersion)309 bool parse(const std::string &s, KernelVersion *kernelVersion) {
310 std::vector<std::string> v = SplitString(s, '.');
311 if (v.size() != 3) {
312 return false;
313 }
314 size_t version, major, minor;
315 if (!ParseUint(v[0], &version)) {
316 return false;
317 }
318 if (!ParseUint(v[1], &major)) {
319 return false;
320 }
321 if (!ParseUint(v[2], &minor)) {
322 return false;
323 }
324 *kernelVersion = KernelVersion(version, major, minor);
325 return true;
326 }
327
operator <<(std::ostream & os,const TransportArch & ta)328 std::ostream &operator<<(std::ostream &os, const TransportArch &ta) {
329 return os << to_string(ta.transport) << to_string(ta.arch);
330 }
331
operator <<(std::ostream & os,const KernelVersion & ver)332 std::ostream &operator<<(std::ostream &os, const KernelVersion &ver) {
333 return os << ver.version << "." << ver.majorRev << "." << ver.minorRev;
334 }
335
operator <<(std::ostream & os,const ManifestHal & hal)336 std::ostream &operator<<(std::ostream &os, const ManifestHal &hal) {
337 return os << hal.format << "/"
338 << hal.name << "/"
339 << hal.transportArch << "/"
340 << hal.versions;
341 }
342
expandInstances(const MatrixHal & req,const VersionRange & vr,bool brace)343 std::string expandInstances(const MatrixHal& req, const VersionRange& vr, bool brace) {
344 std::string s;
345 size_t count = 0;
346 req.forEachInstance(vr, [&](const auto& matrixInstance) {
347 if (count > 0) s += " AND ";
348 auto instance = matrixInstance.isRegex() ? matrixInstance.regexPattern()
349 : matrixInstance.exactInstance();
350 switch (req.format) {
351 case HalFormat::AIDL: {
352 s += toFQNameString(matrixInstance.interface(), instance) + " (@" +
353 aidlVersionRangeToString(vr) + ")";
354 } break;
355 case HalFormat::HIDL:
356 [[fallthrough]];
357 case HalFormat::NATIVE: {
358 s += toFQNameString(vr, matrixInstance.interface(), instance);
359 } break;
360 }
361 count++;
362 return true;
363 });
364 if (count == 0) {
365 s += "@" + to_string(vr);
366 }
367 if (count >= 2 && brace) {
368 s = "(" + s + ")";
369 }
370 return s;
371 }
372
expandInstances(const MatrixHal & req)373 std::vector<std::string> expandInstances(const MatrixHal& req) {
374 size_t count = req.instancesCount();
375 if (count == 0) {
376 return {};
377 }
378 if (count == 1) {
379 return {expandInstances(req, req.versionRanges.front(), false /* brace */)};
380 }
381 std::vector<std::string> ss;
382 for (const auto& vr : req.versionRanges) {
383 if (!ss.empty()) {
384 ss.back() += " OR";
385 }
386 ss.push_back(expandInstances(req, vr, true /* brace */));
387 }
388 return ss;
389 }
390
operator <<(std::ostream & os,KernelSepolicyVersion ksv)391 std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv){
392 return os << ksv.value;
393 }
394
parse(const std::string & s,KernelSepolicyVersion * ksv)395 bool parse(const std::string &s, KernelSepolicyVersion *ksv){
396 return ParseUint(s, &ksv->value);
397 }
398
dump(const HalManifest & vm)399 std::string dump(const HalManifest &vm) {
400 std::ostringstream oss;
401 bool first = true;
402 for (const auto &hal : vm.getHals()) {
403 if (!first) {
404 oss << ":";
405 }
406 oss << hal;
407 first = false;
408 }
409 return oss.str();
410 }
411
dump(const RuntimeInfo & ki,bool verbose)412 std::string dump(const RuntimeInfo& ki, bool verbose) {
413 std::ostringstream oss;
414
415 oss << "kernel = " << ki.osName() << "/" << ki.nodeName() << "/" << ki.osRelease() << "/"
416 << ki.osVersion() << "/" << ki.hardwareId() << ";" << ki.mBootAvbVersion << "/"
417 << ki.mBootVbmetaAvbVersion << ";"
418 << "kernelSepolicyVersion = " << ki.kernelSepolicyVersion() << ";";
419
420 if (verbose) {
421 oss << "\n\ncpu info:\n" << ki.cpuInfo();
422 }
423
424 oss << "\n#CONFIG's loaded = " << ki.kernelConfigs().size() << ";\n";
425
426 if (verbose) {
427 for (const auto& pair : ki.kernelConfigs()) {
428 oss << pair.first << "=" << pair.second << "\n";
429 }
430 }
431
432 return oss.str();
433 }
434
toFQNameString(const std::string & package,const std::string & version,const std::string & interface,const std::string & instance)435 std::string toFQNameString(const std::string& package, const std::string& version,
436 const std::string& interface, const std::string& instance) {
437 std::stringstream ss;
438 ss << package << "@" << version;
439 if (!interface.empty()) {
440 ss << "::" << interface;
441 if (!instance.empty()) {
442 ss << "/" << instance;
443 }
444 }
445 return ss.str();
446 }
447
toFQNameString(const std::string & package,const Version & version,const std::string & interface,const std::string & instance)448 std::string toFQNameString(const std::string& package, const Version& version,
449 const std::string& interface, const std::string& instance) {
450 return toFQNameString(package, to_string(version), interface, instance);
451 }
452
toFQNameString(const Version & version,const std::string & interface,const std::string & instance)453 std::string toFQNameString(const Version& version, const std::string& interface,
454 const std::string& instance) {
455 return toFQNameString("", version, interface, instance);
456 }
457
458 // android.hardware.foo@1.0-1::IFoo/default.
459 // Note that the format is extended to support a range of versions.
toFQNameString(const std::string & package,const VersionRange & range,const std::string & interface,const std::string & instance)460 std::string toFQNameString(const std::string& package, const VersionRange& range,
461 const std::string& interface, const std::string& instance) {
462 return toFQNameString(package, to_string(range), interface, instance);
463 }
464
toFQNameString(const VersionRange & range,const std::string & interface,const std::string & instance)465 std::string toFQNameString(const VersionRange& range, const std::string& interface,
466 const std::string& instance) {
467 return toFQNameString("", range, interface, instance);
468 }
469
toFQNameString(const std::string & interface,const std::string & instance)470 std::string toFQNameString(const std::string& interface, const std::string& instance) {
471 return interface + "/" + instance;
472 }
473
operator <<(std::ostream & os,const FqInstance & fqInstance)474 std::ostream& operator<<(std::ostream& os, const FqInstance& fqInstance) {
475 return os << fqInstance.string();
476 }
477
parse(const std::string & s,FqInstance * fqInstance)478 bool parse(const std::string& s, FqInstance* fqInstance) {
479 return fqInstance->setTo(s);
480 }
481
toAidlFqnameString(const std::string & package,const std::string & interface,const std::string & instance)482 std::string toAidlFqnameString(const std::string& package, const std::string& interface,
483 const std::string& instance) {
484 std::stringstream ss;
485 ss << package << "." << interface;
486 if (!instance.empty()) {
487 ss << "/" << instance;
488 }
489 return ss.str();
490 }
491
aidlVersionToString(const Version & v)492 std::string aidlVersionToString(const Version& v) {
493 return to_string(v.minorVer);
494 }
parseAidlVersion(const std::string & s,Version * version)495 bool parseAidlVersion(const std::string& s, Version* version) {
496 version->majorVer = details::kFakeAidlMajorVersion;
497 return android::base::ParseUint(s, &version->minorVer);
498 }
499
aidlVersionRangeToString(const VersionRange & vr)500 std::string aidlVersionRangeToString(const VersionRange& vr) {
501 if (vr.isSingleVersion()) {
502 return to_string(vr.minMinor);
503 }
504 return to_string(vr.minMinor) + "-" + to_string(vr.maxMinor);
505 }
506
parseAidlVersionRange(const std::string & s,VersionRange * vr)507 bool parseAidlVersionRange(const std::string& s, VersionRange* vr) {
508 return parseVersionRange(s, vr, parseAidlVersion);
509 }
510
511 } // namespace vintf
512 } // namespace android
513