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 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> 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> 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> 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 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 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> 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 165 bool parseKernelConfigInt(const std::string &s, int64_t *i) { 166 return parseKernelConfigIntHelper(s, i); 167 } 168 169 bool parseKernelConfigInt(const std::string &s, uint64_t *i) { 170 return parseKernelConfigIntHelper(s, i); 171 } 172 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 182 bool parse(const std::string &s, KernelConfigKey *key) { 183 *key = s; 184 return true; 185 } 186 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 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 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 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. 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 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 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" 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 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 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 328 std::ostream &operator<<(std::ostream &os, const TransportArch &ta) { 329 return os << to_string(ta.transport) << to_string(ta.arch); 330 } 331 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 358 std::ostream &operator<<(std::ostream &os, const KernelVersion &ver) { 359 return os << ver.version << "." << ver.majorRev << "." << ver.minorRev; 360 } 361 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 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 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 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 435 std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv){ 436 return os << ksv.value; 437 } 438 439 bool parse(const std::string &s, KernelSepolicyVersion *ksv){ 440 return ParseUint(s, &ksv->value); 441 } 442 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 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 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 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 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. 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 509 std::string toFQNameString(const VersionRange& range, const std::string& interface, 510 const std::string& instance) { 511 return toFQNameString("", range, interface, instance); 512 } 513 514 std::string toFQNameString(const std::string& interface, const std::string& instance) { 515 return interface + "/" + instance; 516 } 517 518 std::ostream& operator<<(std::ostream& os, const FqInstance& fqInstance) { 519 return os << fqInstance.string(); 520 } 521 522 bool parse(const std::string& s, FqInstance* fqInstance) { 523 return fqInstance->setTo(s); 524 } 525 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 536 std::string aidlVersionToString(const Version& v) { 537 return to_string(v.minorVer); 538 } 539 bool parseAidlVersion(const std::string& s, Version* version) { 540 version->majorVer = details::kFakeAidlMajorVersion; 541 return android::base::ParseUint(s, &version->minorVer); 542 } 543 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 551 bool parseAidlVersionRange(const std::string& s, VersionRange* vr) { 552 return parseVersionRange(s, vr, parseAidlVersion); 553 } 554 555 } // namespace vintf 556 } // namespace android 557