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