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 
parse(const std::string & s,TransportArch * ta)332 bool parse(const std::string &s, TransportArch *ta) {
333     bool transportSet = false;
334     bool archSet = false;
335     for (size_t i = 0; i < gTransportStrings.size(); ++i) {
336         if (s.find(gTransportStrings.at(i)) != std::string::npos) {
337             ta->transport = static_cast<Transport>(i);
338             transportSet = true;
339             break;
340         }
341     }
342     if (!transportSet) {
343         return false;
344     }
345     for (size_t i = 0; i < gArchStrings.size(); ++i) {
346         if (s.find(gArchStrings.at(i)) != std::string::npos) {
347             ta->arch = static_cast<Arch>(i);
348             archSet = true;
349             break;
350         }
351     }
352     if (!archSet) {
353         return false;
354     }
355     return ta->isValid();
356 }
357 
operator <<(std::ostream & os,const KernelVersion & ver)358 std::ostream &operator<<(std::ostream &os, const KernelVersion &ver) {
359     return os << ver.version << "." << ver.majorRev << "." << ver.minorRev;
360 }
361 
parse(const std::string & s,ManifestHal * hal)362 bool parse(const std::string &s, ManifestHal *hal) {
363     std::vector<std::string> v = SplitString(s, '/');
364     if (v.size() != 4) {
365         return false;
366     }
367     if (!parse(v[0], &hal->format)) {
368         return false;
369     }
370     hal->name = v[1];
371     if (!parse(v[2], &hal->transportArch)) {
372         return false;
373     }
374     if (!parse(v[3], &hal->versions)) {
375         return false;
376     }
377     return hal->isValid();
378 }
379 
operator <<(std::ostream & os,const ManifestHal & hal)380 std::ostream &operator<<(std::ostream &os, const ManifestHal &hal) {
381     return os << hal.format << "/"
382               << hal.name << "/"
383               << hal.transportArch << "/"
384               << hal.versions;
385 }
386 
expandInstances(const MatrixHal & req,const VersionRange & vr,bool brace)387 std::string expandInstances(const MatrixHal& req, const VersionRange& vr, bool brace) {
388     std::string s;
389     size_t count = 0;
390     req.forEachInstance(vr, [&](const auto& matrixInstance) {
391         if (count > 0) s += " AND ";
392         auto instance = matrixInstance.isRegex() ? matrixInstance.regexPattern()
393                                                  : matrixInstance.exactInstance();
394         switch (req.format) {
395             case HalFormat::AIDL: {
396                 s += toFQNameString(matrixInstance.interface(), instance) + " (@" +
397                      aidlVersionRangeToString(vr) + ")";
398             } break;
399             case HalFormat::HIDL:
400                 [[fallthrough]];
401             case HalFormat::NATIVE: {
402                 s += toFQNameString(vr, matrixInstance.interface(), instance);
403             } break;
404         }
405         count++;
406         return true;
407     });
408     if (count == 0) {
409         s += "@" + to_string(vr);
410     }
411     if (count >= 2 && brace) {
412         s = "(" + s + ")";
413     }
414     return s;
415 }
416 
expandInstances(const MatrixHal & req)417 std::vector<std::string> expandInstances(const MatrixHal& req) {
418     size_t count = req.instancesCount();
419     if (count == 0) {
420         return {};
421     }
422     if (count == 1) {
423         return {expandInstances(req, req.versionRanges.front(), false /* brace */)};
424     }
425     std::vector<std::string> ss;
426     for (const auto& vr : req.versionRanges) {
427         if (!ss.empty()) {
428             ss.back() += " OR";
429         }
430         ss.push_back(expandInstances(req, vr, true /* brace */));
431     }
432     return ss;
433 }
434 
operator <<(std::ostream & os,KernelSepolicyVersion ksv)435 std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv){
436     return os << ksv.value;
437 }
438 
parse(const std::string & s,KernelSepolicyVersion * ksv)439 bool parse(const std::string &s, KernelSepolicyVersion *ksv){
440     return ParseUint(s, &ksv->value);
441 }
442 
dump(const HalManifest & vm)443 std::string dump(const HalManifest &vm) {
444     std::ostringstream oss;
445     bool first = true;
446     for (const auto &hal : vm.getHals()) {
447         if (!first) {
448             oss << ":";
449         }
450         oss << hal;
451         first = false;
452     }
453     return oss.str();
454 }
455 
dump(const RuntimeInfo & ki,bool verbose)456 std::string dump(const RuntimeInfo& ki, bool verbose) {
457     std::ostringstream oss;
458 
459     oss << "kernel = " << ki.osName() << "/" << ki.nodeName() << "/" << ki.osRelease() << "/"
460         << ki.osVersion() << "/" << ki.hardwareId() << ";" << ki.mBootAvbVersion << "/"
461         << ki.mBootVbmetaAvbVersion << ";"
462         << "kernelSepolicyVersion = " << ki.kernelSepolicyVersion() << ";";
463 
464     if (verbose) {
465         oss << "\n\ncpu info:\n" << ki.cpuInfo();
466     }
467 
468     oss << "\n#CONFIG's loaded = " << ki.kernelConfigs().size() << ";\n";
469 
470     if (verbose) {
471         for (const auto& pair : ki.kernelConfigs()) {
472             oss << pair.first << "=" << pair.second << "\n";
473         }
474     }
475 
476     return oss.str();
477 }
478 
toFQNameString(const std::string & package,const std::string & version,const std::string & interface,const std::string & instance)479 std::string toFQNameString(const std::string& package, const std::string& version,
480                            const std::string& interface, const std::string& instance) {
481     std::stringstream ss;
482     ss << package << "@" << version;
483     if (!interface.empty()) {
484         ss << "::" << interface;
485         if (!instance.empty()) {
486             ss << "/" << instance;
487         }
488     }
489     return ss.str();
490 }
491 
toFQNameString(const std::string & package,const Version & version,const std::string & interface,const std::string & instance)492 std::string toFQNameString(const std::string& package, const Version& version,
493                            const std::string& interface, const std::string& instance) {
494     return toFQNameString(package, to_string(version), interface, instance);
495 }
496 
toFQNameString(const Version & version,const std::string & interface,const std::string & instance)497 std::string toFQNameString(const Version& version, const std::string& interface,
498                            const std::string& instance) {
499     return toFQNameString("", version, interface, instance);
500 }
501 
502 // android.hardware.foo@1.0-1::IFoo/default.
503 // 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)504 std::string toFQNameString(const std::string& package, const VersionRange& range,
505                            const std::string& interface, const std::string& instance) {
506     return toFQNameString(package, to_string(range), interface, instance);
507 }
508 
toFQNameString(const VersionRange & range,const std::string & interface,const std::string & instance)509 std::string toFQNameString(const VersionRange& range, const std::string& interface,
510                            const std::string& instance) {
511     return toFQNameString("", range, interface, instance);
512 }
513 
toFQNameString(const std::string & interface,const std::string & instance)514 std::string toFQNameString(const std::string& interface, const std::string& instance) {
515     return 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 
toAidlFqnameString(const std::string & package,const std::string & interface,const std::string & instance)526 std::string toAidlFqnameString(const std::string& package, const std::string& interface,
527                                const std::string& instance) {
528     std::stringstream ss;
529     ss << package << "." << interface;
530     if (!instance.empty()) {
531         ss << "/" << instance;
532     }
533     return ss.str();
534 }
535 
aidlVersionToString(const Version & v)536 std::string aidlVersionToString(const Version& v) {
537     return to_string(v.minorVer);
538 }
parseAidlVersion(const std::string & s,Version * version)539 bool parseAidlVersion(const std::string& s, Version* version) {
540     version->majorVer = details::kFakeAidlMajorVersion;
541     return android::base::ParseUint(s, &version->minorVer);
542 }
543 
aidlVersionRangeToString(const VersionRange & vr)544 std::string aidlVersionRangeToString(const VersionRange& vr) {
545     if (vr.isSingleVersion()) {
546         return to_string(vr.minMinor);
547     }
548     return to_string(vr.minMinor) + "-" + to_string(vr.maxMinor);
549 }
550 
parseAidlVersionRange(const std::string & s,VersionRange * vr)551 bool parseAidlVersionRange(const std::string& s, VersionRange* vr) {
552     return parseVersionRange(s, vr, parseAidlVersion);
553 }
554 
555 } // namespace vintf
556 } // namespace android
557