123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527 |
- /*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // Convert objects from and to strings.
- #include "parse_string.h"
- #include <android-base/parseint.h>
- namespace android {
- using base::ParseUint;
- namespace vintf {
- static const std::string kRequired("required");
- static const std::string kOptional("optional");
- static const std::string kConfigPrefix("CONFIG_");
- std::vector<std::string> SplitString(const std::string &s, char c) {
- std::vector<std::string> components;
- size_t startPos = 0;
- size_t matchPos;
- while ((matchPos = s.find(c, startPos)) != std::string::npos) {
- components.push_back(s.substr(startPos, matchPos - startPos));
- startPos = matchPos + 1;
- }
- if (startPos <= s.length()) {
- components.push_back(s.substr(startPos));
- }
- return components;
- }
- template <typename T>
- std::ostream &operator<<(std::ostream &os, const std::vector<T> objs) {
- bool first = true;
- for (const T &v : objs) {
- if (!first) {
- os << ",";
- }
- os << v;
- first = false;
- }
- return os;
- }
- template <typename T>
- bool parse(const std::string &s, std::vector<T> *objs) {
- std::vector<std::string> v = SplitString(s, ',');
- objs->resize(v.size());
- size_t idx = 0;
- for (const auto &item : v) {
- T ver;
- if (!parse(item, &ver)) {
- return false;
- }
- objs->at(idx++) = ver;
- }
- return true;
- }
- template<typename E, typename Array>
- bool parseEnum(const std::string &s, E *e, const Array &strings) {
- for (size_t i = 0; i < strings.size(); ++i) {
- if (s == strings.at(i)) {
- *e = static_cast<E>(i);
- return true;
- }
- }
- return false;
- }
- #define DEFINE_PARSE_STREAMIN_FOR_ENUM(ENUM) \
- bool parse(const std::string &s, ENUM *hf) { \
- return parseEnum(s, hf, g##ENUM##Strings); \
- } \
- std::ostream &operator<<(std::ostream &os, ENUM hf) { \
- return os << g##ENUM##Strings.at(static_cast<size_t>(hf)); \
- } \
- DEFINE_PARSE_STREAMIN_FOR_ENUM(HalFormat);
- DEFINE_PARSE_STREAMIN_FOR_ENUM(Transport);
- DEFINE_PARSE_STREAMIN_FOR_ENUM(Arch);
- DEFINE_PARSE_STREAMIN_FOR_ENUM(KernelConfigType);
- DEFINE_PARSE_STREAMIN_FOR_ENUM(Tristate);
- DEFINE_PARSE_STREAMIN_FOR_ENUM(SchemaType);
- DEFINE_PARSE_STREAMIN_FOR_ENUM(XmlSchemaFormat);
- std::ostream &operator<<(std::ostream &os, const KernelConfigTypedValue &kctv) {
- switch (kctv.mType) {
- case KernelConfigType::STRING:
- return os << kctv.mStringValue;
- case KernelConfigType::INTEGER:
- return os << to_string(kctv.mIntegerValue);
- case KernelConfigType::RANGE:
- return os << to_string(kctv.mRangeValue.first) << "-"
- << to_string(kctv.mRangeValue.second);
- case KernelConfigType::TRISTATE:
- return os << to_string(kctv.mTristateValue);
- }
- }
- bool parse(const std::string& s, Level* l) {
- if (s.empty()) {
- *l = Level::UNSPECIFIED;
- return true;
- }
- if (s == "legacy") {
- *l = Level::LEGACY;
- return true;
- }
- size_t value;
- if (!ParseUint(s, &value)) {
- return false;
- }
- *l = static_cast<Level>(value);
- return true;
- }
- std::ostream& operator<<(std::ostream& os, Level l) {
- if (l == Level::UNSPECIFIED) {
- return os;
- }
- if (l == Level::LEGACY) {
- return os << "legacy";
- }
- return os << static_cast<size_t>(l);
- }
- // Notice that strtoull is used even though KernelConfigIntValue is signed int64_t,
- // because strtoull can accept negative values as well.
- // Notice that according to man strtoul, strtoull can actually accept
- // -2^64 + 1 to 2^64 - 1, with the 65th bit truncated.
- // ParseInt / ParseUint are not used because they do not handle signed hex very well.
- template <typename T>
- bool parseKernelConfigIntHelper(const std::string &s, T *i) {
- char *end;
- errno = 0;
- unsigned long long int ulli = strtoull(s.c_str(), &end, 0 /* base */);
- // It is implementation defined that what value will be returned by strtoull
- // in the error case, so we are checking errno directly here.
- if (errno == 0 && s.c_str() != end && *end == '\0') {
- *i = static_cast<T>(ulli);
- return true;
- }
- return false;
- }
- bool parseKernelConfigInt(const std::string &s, int64_t *i) {
- return parseKernelConfigIntHelper(s, i);
- }
- bool parseKernelConfigInt(const std::string &s, uint64_t *i) {
- return parseKernelConfigIntHelper(s, i);
- }
- bool parseRange(const std::string &s, KernelConfigRangeValue *range) {
- auto pos = s.find('-');
- if (pos == std::string::npos) {
- return false;
- }
- return parseKernelConfigInt(s.substr(0, pos), &range->first)
- && parseKernelConfigInt(s.substr(pos + 1), &range->second);
- }
- bool parse(const std::string &s, KernelConfigKey *key) {
- *key = s;
- return true;
- }
- bool parseKernelConfigValue(const std::string &s, KernelConfigTypedValue *kctv) {
- switch (kctv->mType) {
- case KernelConfigType::STRING:
- kctv->mStringValue = s;
- return true;
- case KernelConfigType::INTEGER:
- return parseKernelConfigInt(s, &kctv->mIntegerValue);
- case KernelConfigType::RANGE:
- return parseRange(s, &kctv->mRangeValue);
- case KernelConfigType::TRISTATE:
- return parse(s, &kctv->mTristateValue);
- }
- }
- bool parseKernelConfigTypedValue(const std::string& s, KernelConfigTypedValue* kctv) {
- if (s.size() > 1 && s[0] == '"' && s.back() == '"') {
- kctv->mType = KernelConfigType::STRING;
- kctv->mStringValue = s.substr(1, s.size()-2);
- return true;
- }
- if (parseKernelConfigInt(s, &kctv->mIntegerValue)) {
- kctv->mType = KernelConfigType::INTEGER;
- return true;
- }
- if (parse(s, &kctv->mTristateValue)) {
- kctv->mType = KernelConfigType::TRISTATE;
- return true;
- }
- // Do not test for KernelConfigType::RANGE.
- return false;
- }
- bool parse(const std::string &s, Version *ver) {
- std::vector<std::string> v = SplitString(s, '.');
- if (v.size() != 2) {
- return false;
- }
- size_t major, minor;
- if (!ParseUint(v[0], &major)) {
- return false;
- }
- if (!ParseUint(v[1], &minor)) {
- return false;
- }
- *ver = Version(major, minor);
- return true;
- }
- std::ostream &operator<<(std::ostream &os, const Version &ver) {
- return os << ver.majorVer << "." << ver.minorVer;
- }
- bool parse(const std::string &s, VersionRange *vr) {
- std::vector<std::string> v = SplitString(s, '-');
- if (v.size() != 1 && v.size() != 2) {
- return false;
- }
- Version minVer;
- if (!parse(v[0], &minVer)) {
- return false;
- }
- if (v.size() == 1) {
- *vr = VersionRange(minVer.majorVer, minVer.minorVer);
- } else {
- size_t maxMinor;
- if (!ParseUint(v[1], &maxMinor)) {
- return false;
- }
- *vr = VersionRange(minVer.majorVer, minVer.minorVer, maxMinor);
- }
- return true;
- }
- std::ostream &operator<<(std::ostream &os, const VersionRange &vr) {
- if (vr.isSingleVersion()) {
- return os << vr.minVer();
- }
- return os << vr.minVer() << "-" << vr.maxMinor;
- }
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
- bool parse(const std::string &s, VndkVersionRange *vr) {
- std::vector<std::string> v = SplitString(s, '-');
- if (v.size() != 1 && v.size() != 2) {
- return false;
- }
- std::vector<std::string> minVector = SplitString(v[0], '.');
- if (minVector.size() != 3) {
- return false;
- }
- if (!ParseUint(minVector[0], &vr->sdk) ||
- !ParseUint(minVector[1], &vr->vndk) ||
- !ParseUint(minVector[2], &vr->patchMin)) {
- return false;
- }
- if (v.size() == 1) {
- vr->patchMax = vr->patchMin;
- return true;
- } else {
- return ParseUint(v[1], &vr->patchMax);
- }
- }
- std::ostream &operator<<(std::ostream &os, const VndkVersionRange &vr) {
- os << vr.sdk << "." << vr.vndk << "." << vr.patchMin;
- if (!vr.isSingleVersion()) {
- os << "-" << vr.patchMax;
- }
- return os;
- }
- #pragma clang diagnostic pop
- bool parse(const std::string &s, KernelVersion *kernelVersion) {
- std::vector<std::string> v = SplitString(s, '.');
- if (v.size() != 3) {
- return false;
- }
- size_t version, major, minor;
- if (!ParseUint(v[0], &version)) {
- return false;
- }
- if (!ParseUint(v[1], &major)) {
- return false;
- }
- if (!ParseUint(v[2], &minor)) {
- return false;
- }
- *kernelVersion = KernelVersion(version, major, minor);
- return true;
- }
- std::ostream &operator<<(std::ostream &os, const TransportArch &ta) {
- return os << to_string(ta.transport) << to_string(ta.arch);
- }
- bool parse(const std::string &s, TransportArch *ta) {
- bool transportSet = false;
- bool archSet = false;
- for (size_t i = 0; i < gTransportStrings.size(); ++i) {
- if (s.find(gTransportStrings.at(i)) != std::string::npos) {
- ta->transport = static_cast<Transport>(i);
- transportSet = true;
- break;
- }
- }
- if (!transportSet) {
- return false;
- }
- for (size_t i = 0; i < gArchStrings.size(); ++i) {
- if (s.find(gArchStrings.at(i)) != std::string::npos) {
- ta->arch = static_cast<Arch>(i);
- archSet = true;
- break;
- }
- }
- if (!archSet) {
- return false;
- }
- return ta->isValid();
- }
- std::ostream &operator<<(std::ostream &os, const KernelVersion &ver) {
- return os << ver.version << "." << ver.majorRev << "." << ver.minorRev;
- }
- bool parse(const std::string &s, ManifestHal *hal) {
- std::vector<std::string> v = SplitString(s, '/');
- if (v.size() != 4) {
- return false;
- }
- if (!parse(v[0], &hal->format)) {
- return false;
- }
- hal->name = v[1];
- if (!parse(v[2], &hal->transportArch)) {
- return false;
- }
- if (!parse(v[3], &hal->versions)) {
- return false;
- }
- return hal->isValid();
- }
- std::ostream &operator<<(std::ostream &os, const ManifestHal &hal) {
- return os << hal.format << "/"
- << hal.name << "/"
- << hal.transportArch << "/"
- << hal.versions;
- }
- bool parse(const std::string &s, MatrixHal *req) {
- std::vector<std::string> v = SplitString(s, '/');
- if (v.size() != 4) {
- return false;
- }
- if (!parse(v[0], &req->format)) {
- return false;
- }
- req->name = v[1];
- if (!parse(v[2], &req->versionRanges)) {
- return false;
- }
- if (v[3] != kRequired || v[3] != kOptional) {
- return false;
- }
- req->optional = (v[3] == kOptional);
- return true;
- }
- std::ostream &operator<<(std::ostream &os, const MatrixHal &req) {
- return os << req.format << "/"
- << req.name << "/"
- << req.versionRanges << "/"
- << (req.optional ? kOptional : kRequired);
- }
- std::string expandInstances(const MatrixHal& req, const VersionRange& vr, bool brace) {
- std::string s;
- size_t count = 0;
- req.forEachInstance(vr, [&](const auto& matrixInstance) {
- if (count > 0) s += " AND ";
- s += toFQNameString(vr, matrixInstance.interface(),
- matrixInstance.isRegex() ? matrixInstance.regexPattern()
- : matrixInstance.exactInstance());
- count++;
- return true;
- });
- if (count == 0) {
- s += "@" + to_string(vr);
- }
- if (count >= 2 && brace) {
- s = "(" + s + ")";
- }
- return s;
- }
- std::vector<std::string> expandInstances(const MatrixHal& req) {
- size_t count = req.instancesCount();
- if (count == 0) {
- return {};
- }
- if (count == 1) {
- return {expandInstances(req, req.versionRanges.front(), false /* brace */)};
- }
- std::vector<std::string> ss;
- for (const auto& vr : req.versionRanges) {
- if (!ss.empty()) {
- ss.back() += " OR";
- }
- ss.push_back(expandInstances(req, vr, true /* brace */));
- }
- return ss;
- }
- std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv){
- return os << ksv.value;
- }
- bool parse(const std::string &s, KernelSepolicyVersion *ksv){
- return ParseUint(s, &ksv->value);
- }
- std::string dump(const HalManifest &vm) {
- std::ostringstream oss;
- bool first = true;
- for (const auto &hal : vm.getHals()) {
- if (!first) {
- oss << ":";
- }
- oss << hal;
- first = false;
- }
- return oss.str();
- }
- std::string dump(const RuntimeInfo& ki, bool verbose) {
- std::ostringstream oss;
- oss << "kernel = " << ki.osName() << "/" << ki.nodeName() << "/" << ki.osRelease() << "/"
- << ki.osVersion() << "/" << ki.hardwareId() << ";" << ki.mBootAvbVersion << "/"
- << ki.mBootVbmetaAvbVersion << ";"
- << "kernelSepolicyVersion = " << ki.kernelSepolicyVersion() << ";";
- if (verbose) {
- oss << "\n\ncpu info:\n" << ki.cpuInfo();
- }
- oss << "\n#CONFIG's loaded = " << ki.kernelConfigs().size() << ";\n";
- if (verbose) {
- for (const auto& pair : ki.kernelConfigs()) {
- oss << pair.first << "=" << pair.second << "\n";
- }
- }
- return oss.str();
- }
- std::string toFQNameString(const std::string& package, const std::string& version,
- const std::string& interface, const std::string& instance) {
- std::stringstream ss;
- ss << package << "@" << version;
- if (!interface.empty()) {
- ss << "::" << interface;
- if (!instance.empty()) {
- ss << "/" << instance;
- }
- }
- return ss.str();
- }
- std::string toFQNameString(const std::string& package, const Version& version,
- const std::string& interface, const std::string& instance) {
- return toFQNameString(package, to_string(version), interface, instance);
- }
- std::string toFQNameString(const Version& version, const std::string& interface,
- const std::string& instance) {
- return toFQNameString("", version, interface, instance);
- }
- // [email protected]::IFoo/default.
- // Note that the format is extended to support a range of versions.
- std::string toFQNameString(const std::string& package, const VersionRange& range,
- const std::string& interface, const std::string& instance) {
- return toFQNameString(package, to_string(range), interface, instance);
- }
- std::string toFQNameString(const VersionRange& range, const std::string& interface,
- const std::string& instance) {
- return toFQNameString("", range, interface, instance);
- }
- std::ostream& operator<<(std::ostream& os, const FqInstance& fqInstance) {
- return os << fqInstance.string();
- }
- bool parse(const std::string& s, FqInstance* fqInstance) {
- return fqInstance->setTo(s);
- }
- } // namespace vintf
- } // namespace android
|