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 
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         auto instance = matrixInstance.isRegex() ? matrixInstance.regexPattern()
407                                                  : matrixInstance.exactInstance();
408         switch (req.format) {
409             case HalFormat::AIDL: {
410                 // Hide fake version when printing human-readable error messages.
411                 s += toFQNameString(matrixInstance.interface(), instance);
412             } break;
413             case HalFormat::HIDL:
414                 [[fallthrough]];
415             case HalFormat::NATIVE: {
416                 s += toFQNameString(vr, matrixInstance.interface(), instance);
417             } break;
418         }
419         count++;
420         return true;
421     });
422     if (count == 0) {
423         s += "@" + to_string(vr);
424     }
425     if (count >= 2 && brace) {
426         s = "(" + s + ")";
427     }
428     return s;
429 }
430 
expandInstances(const MatrixHal & req)431 std::vector<std::string> expandInstances(const MatrixHal& req) {
432     size_t count = req.instancesCount();
433     if (count == 0) {
434         return {};
435     }
436     if (count == 1) {
437         return {expandInstances(req, req.versionRanges.front(), false /* brace */)};
438     }
439     std::vector<std::string> ss;
440     for (const auto& vr : req.versionRanges) {
441         if (!ss.empty()) {
442             ss.back() += " OR";
443         }
444         ss.push_back(expandInstances(req, vr, true /* brace */));
445     }
446     return ss;
447 }
448 
operator <<(std::ostream & os,KernelSepolicyVersion ksv)449 std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv){
450     return os << ksv.value;
451 }
452 
parse(const std::string & s,KernelSepolicyVersion * ksv)453 bool parse(const std::string &s, KernelSepolicyVersion *ksv){
454     return ParseUint(s, &ksv->value);
455 }
456 
dump(const HalManifest & vm)457 std::string dump(const HalManifest &vm) {
458     std::ostringstream oss;
459     bool first = true;
460     for (const auto &hal : vm.getHals()) {
461         if (!first) {
462             oss << ":";
463         }
464         oss << hal;
465         first = false;
466     }
467     return oss.str();
468 }
469 
dump(const RuntimeInfo & ki,bool verbose)470 std::string dump(const RuntimeInfo& ki, bool verbose) {
471     std::ostringstream oss;
472 
473     oss << "kernel = " << ki.osName() << "/" << ki.nodeName() << "/" << ki.osRelease() << "/"
474         << ki.osVersion() << "/" << ki.hardwareId() << ";" << ki.mBootAvbVersion << "/"
475         << ki.mBootVbmetaAvbVersion << ";"
476         << "kernelSepolicyVersion = " << ki.kernelSepolicyVersion() << ";";
477 
478     if (verbose) {
479         oss << "\n\ncpu info:\n" << ki.cpuInfo();
480     }
481 
482     oss << "\n#CONFIG's loaded = " << ki.kernelConfigs().size() << ";\n";
483 
484     if (verbose) {
485         for (const auto& pair : ki.kernelConfigs()) {
486             oss << pair.first << "=" << pair.second << "\n";
487         }
488     }
489 
490     return oss.str();
491 }
492 
toFQNameString(const std::string & package,const std::string & version,const std::string & interface,const std::string & instance)493 std::string toFQNameString(const std::string& package, const std::string& version,
494                            const std::string& interface, const std::string& instance) {
495     std::stringstream ss;
496     ss << package << "@" << version;
497     if (!interface.empty()) {
498         ss << "::" << interface;
499         if (!instance.empty()) {
500             ss << "/" << instance;
501         }
502     }
503     return ss.str();
504 }
505 
toFQNameString(const std::string & package,const Version & version,const std::string & interface,const std::string & instance)506 std::string toFQNameString(const std::string& package, const Version& version,
507                            const std::string& interface, const std::string& instance) {
508     return toFQNameString(package, to_string(version), interface, instance);
509 }
510 
toFQNameString(const Version & version,const std::string & interface,const std::string & instance)511 std::string toFQNameString(const Version& version, const std::string& interface,
512                            const std::string& instance) {
513     return toFQNameString("", version, interface, instance);
514 }
515 
516 // android.hardware.foo@1.0-1::IFoo/default.
517 // 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)518 std::string toFQNameString(const std::string& package, const VersionRange& range,
519                            const std::string& interface, const std::string& instance) {
520     return toFQNameString(package, to_string(range), interface, instance);
521 }
522 
toFQNameString(const VersionRange & range,const std::string & interface,const std::string & instance)523 std::string toFQNameString(const VersionRange& range, const std::string& interface,
524                            const std::string& instance) {
525     return toFQNameString("", range, interface, instance);
526 }
527 
toFQNameString(const std::string & interface,const std::string & instance)528 std::string toFQNameString(const std::string& interface, const std::string& instance) {
529     return interface + "/" + instance;
530 }
531 
operator <<(std::ostream & os,const FqInstance & fqInstance)532 std::ostream& operator<<(std::ostream& os, const FqInstance& fqInstance) {
533     return os << fqInstance.string();
534 }
535 
parse(const std::string & s,FqInstance * fqInstance)536 bool parse(const std::string& s, FqInstance* fqInstance) {
537     return fqInstance->setTo(s);
538 }
539 
toAidlFqnameString(const std::string & package,const std::string & interface,const std::string & instance)540 std::string toAidlFqnameString(const std::string& package, const std::string& interface,
541                                const std::string& instance) {
542     std::stringstream ss;
543     ss << package << "." << interface;
544     if (!instance.empty()) {
545         ss << "/" << instance;
546     }
547     return ss.str();
548 }
549 
550 } // namespace vintf
551 } // namespace android
552