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 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> 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> 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> 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 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 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> 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 162 bool parseKernelConfigInt(const std::string &s, int64_t *i) { 163 return parseKernelConfigIntHelper(s, i); 164 } 165 166 bool parseKernelConfigInt(const std::string &s, uint64_t *i) { 167 return parseKernelConfigIntHelper(s, i); 168 } 169 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 179 bool parse(const std::string &s, KernelConfigKey *key) { 180 *key = s; 181 return true; 182 } 183 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 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 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 232 std::ostream &operator<<(std::ostream &os, const Version &ver) { 233 return os << ver.majorVer << "." << ver.minorVer; 234 } 235 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 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" 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 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 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 316 std::ostream &operator<<(std::ostream &os, const TransportArch &ta) { 317 return os << to_string(ta.transport) << to_string(ta.arch); 318 } 319 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 346 std::ostream &operator<<(std::ostream &os, const KernelVersion &ver) { 347 return os << ver.version << "." << ver.majorRev << "." << ver.minorRev; 348 } 349 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 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 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 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 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 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 449 std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv){ 450 return os << ksv.value; 451 } 452 453 bool parse(const std::string &s, KernelSepolicyVersion *ksv){ 454 return ParseUint(s, &ksv->value); 455 } 456 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 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 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 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 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 // [email protected]::IFoo/default. 517 // Note that the format is extended to support a range of versions. 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 523 std::string toFQNameString(const VersionRange& range, const std::string& interface, 524 const std::string& instance) { 525 return toFQNameString("", range, interface, instance); 526 } 527 528 std::string toFQNameString(const std::string& interface, const std::string& instance) { 529 return interface + "/" + instance; 530 } 531 532 std::ostream& operator<<(std::ostream& os, const FqInstance& fqInstance) { 533 return os << fqInstance.string(); 534 } 535 536 bool parse(const std::string& s, FqInstance* fqInstance) { 537 return fqInstance->setTo(s); 538 } 539 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