1 /* 2 * Copyright (C) 2016 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 #include "FQName.h" 18 19 #include "StringHelper.h" 20 21 #include <android-base/logging.h> 22 #include <android-base/parseint.h> 23 #include <iostream> 24 #include <regex> 25 #include <sstream> 26 27 #define RE_COMPONENT "[a-zA-Z_][a-zA-Z_0-9]*" 28 #define RE_PATH RE_COMPONENT "(?:[.]" RE_COMPONENT ")*" 29 #define RE_MAJOR "[0-9]+" 30 #define RE_MINOR "[0-9]+" 31 32 namespace android { 33 34 FQName::FQName() 35 : mValid(false), 36 mIsIdentifier(false) { 37 } 38 39 // TODO(b/73774955): delete 40 FQName::FQName(const std::string &s) 41 : mValid(false), 42 mIsIdentifier(false) { 43 (void)setTo(s); 44 } 45 46 bool FQName::parse(const std::string& s, FQName* into) { 47 return into->setTo(s); 48 } 49 50 FQName::FQName( 51 const std::string &package, 52 const std::string &version, 53 const std::string &name, 54 const std::string &valueName) 55 : mValid(true), 56 mIsIdentifier(false), 57 mPackage(package), 58 mName(name), 59 mValueName(valueName) { 60 CHECK(setVersion(version)) << version; 61 62 // Check if this is actually a valid fqName 63 FQName other; 64 CHECK(parse(this->string(), &other)) << this->string(); 65 CHECK((*this) == other) << this->string() << " " << other.string(); 66 } 67 68 FQName::FQName(const FQName& other) 69 : mValid(other.mValid), 70 mIsIdentifier(other.mIsIdentifier), 71 mPackage(other.mPackage), 72 mMajor(other.mMajor), 73 mMinor(other.mMinor), 74 mName(other.mName), 75 mValueName(other.mValueName) { 76 } 77 78 bool FQName::isValid() const { 79 return mValid; 80 } 81 82 bool FQName::isIdentifier() const { 83 return mIsIdentifier; 84 } 85 86 bool FQName::isFullyQualified() const { 87 return !mPackage.empty() && !version().empty() && !mName.empty(); 88 } 89 90 bool FQName::isValidValueName() const { 91 return mIsIdentifier 92 || (!mName.empty() && !mValueName.empty()); 93 } 94 95 bool FQName::isInterfaceName() const { 96 return !mName.empty() && mName[0] == 'I' && mName.find('.') == std::string::npos; 97 } 98 99 bool FQName::setTo(const std::string &s) { 100 // android.hardware.foo (at) 1.0::IFoo.Type 101 static const std::regex kRE1("(" RE_PATH ")@(" RE_MAJOR ")[.](" RE_MINOR ")::(" RE_PATH ")"); 102 // @1.0::IFoo.Type 103 static const std::regex kRE2("@(" RE_MAJOR ")[.](" RE_MINOR ")::(" RE_PATH ")"); 104 // android.hardware.foo (at) 1.0 (for package declaration and whole package import) 105 static const std::regex kRE3("(" RE_PATH ")@(" RE_MAJOR ")[.](" RE_MINOR ")"); 106 // IFoo.Type 107 static const std::regex kRE4("(" RE_COMPONENT ")([.]" RE_COMPONENT ")+"); 108 // Type (a plain identifier) 109 static const std::regex kRE5("(" RE_COMPONENT ")"); 110 111 // android.hardware.foo (at) 1.0::IFoo.Type:MY_ENUM_VALUE 112 static const std::regex kRE6("(" RE_PATH ")@(" RE_MAJOR ")[.](" RE_MINOR ")::(" RE_PATH 113 "):(" RE_COMPONENT ")"); 114 // @1.0::IFoo.Type:MY_ENUM_VALUE 115 static const std::regex kRE7("@(" RE_MAJOR ")[.](" RE_MINOR ")::(" RE_PATH "):(" RE_COMPONENT 116 ")"); 117 // IFoo.Type:MY_ENUM_VALUE 118 static const std::regex kRE8("(" RE_PATH "):(" RE_COMPONENT ")"); 119 120 bool invalid = false; 121 clear(); 122 123 std::smatch match; 124 if (std::regex_match(s, match, kRE1)) { 125 CHECK_EQ(match.size(), 5u); 126 127 mPackage = match.str(1); 128 invalid |= !parseVersion(match.str(2), match.str(3)); 129 mName = match.str(4); 130 } else if (std::regex_match(s, match, kRE2)) { 131 CHECK_EQ(match.size(), 4u); 132 133 invalid |= !parseVersion(match.str(1), match.str(2)); 134 mName = match.str(3); 135 } else if (std::regex_match(s, match, kRE3)) { 136 CHECK_EQ(match.size(), 4u); 137 138 mPackage = match.str(1); 139 invalid |= !parseVersion(match.str(2), match.str(3)); 140 } else if (std::regex_match(s, match, kRE4)) { 141 mName = match.str(0); 142 } else if (std::regex_match(s, match, kRE5)) { 143 mIsIdentifier = true; 144 mName = match.str(0); 145 } else if (std::regex_match(s, match, kRE6)) { 146 CHECK_EQ(match.size(), 6u); 147 148 mPackage = match.str(1); 149 invalid |= !parseVersion(match.str(2), match.str(3)); 150 mName = match.str(4); 151 mValueName = match.str(5); 152 } else if (std::regex_match(s, match, kRE7)) { 153 CHECK_EQ(match.size(), 5u); 154 155 invalid |= !parseVersion(match.str(1), match.str(2)); 156 mName = match.str(3); 157 mValueName = match.str(4); 158 } else if (std::regex_match(s, match, kRE8)) { 159 CHECK_EQ(match.size(), 3u); 160 161 mName = match.str(1); 162 mValueName = match.str(2); 163 } else { 164 invalid = true; 165 } 166 167 // mValueName must go with mName. 168 CHECK(mValueName.empty() || !mName.empty()); 169 170 // package without version is not allowed. 171 CHECK(invalid || mPackage.empty() || !version().empty()); 172 173 // TODO(b/73774955): remove isValid and users 174 // of old FQName constructors 175 return mValid = !invalid; 176 } 177 178 const std::string& FQName::package() const { 179 return mPackage; 180 } 181 182 std::string FQName::version() const { 183 if (!hasVersion()) { 184 return ""; 185 } 186 return std::to_string(mMajor) + "." + std::to_string(mMinor); 187 } 188 189 std::string FQName::sanitizedVersion() const { 190 if (!hasVersion()) { 191 return ""; 192 } 193 return "V" + std::to_string(mMajor) + "_" + std::to_string(mMinor); 194 } 195 196 std::string FQName::atVersion() const { 197 std::string v = version(); 198 return v.empty() ? "" : ("@" + v); 199 } 200 201 void FQName::clear() { 202 mValid = true; 203 mIsIdentifier = false; 204 mPackage.clear(); 205 clearVersion(); 206 mName.clear(); 207 mValueName.clear(); 208 } 209 210 bool FQName::setVersion(const std::string& v) { 211 static const std::regex kREVer("(" RE_MAJOR ")[.](" RE_MINOR ")"); 212 213 if (v.empty()) { 214 clearVersion(); 215 return true; 216 } 217 218 std::smatch match; 219 if (!std::regex_match(v, match, kREVer)) { 220 return mValid = false; 221 } 222 CHECK_EQ(match.size(), 3u); 223 224 return parseVersion(match.str(1), match.str(2)); 225 } 226 227 void FQName::clearVersion() { 228 mMajor = mMinor = 0; 229 } 230 231 bool FQName::parseVersion(const std::string& majorStr, const std::string& minorStr) { 232 bool versionParseSuccess = 233 ::android::base::ParseUint(majorStr, &mMajor) && 234 ::android::base::ParseUint(minorStr, &mMinor); 235 if (!versionParseSuccess) { 236 LOG(ERROR) << "numbers in " << majorStr << "." << minorStr << " are out of range."; 237 mValid = false; 238 } 239 return versionParseSuccess; 240 } 241 242 const std::string& FQName::name() const { 243 return mName; 244 } 245 246 std::vector<std::string> FQName::names() const { 247 std::vector<std::string> res {}; 248 std::istringstream ss(name()); 249 std::string s; 250 while (std::getline(ss, s, '.')) { 251 res.push_back(s); 252 } 253 return res; 254 } 255 256 const std::string& FQName::valueName() const { 257 return mValueName; 258 } 259 260 FQName FQName::typeName() const { 261 return FQName(mPackage, version(), mName); 262 } 263 264 void FQName::applyDefaults( 265 const std::string &defaultPackage, 266 const std::string &defaultVersion) { 267 268 // package without version is not allowed. 269 CHECK(mPackage.empty() || !version().empty()); 270 271 if (mPackage.empty()) { 272 mPackage = defaultPackage; 273 } 274 275 if (version().empty()) { 276 CHECK(setVersion(defaultVersion)); 277 } 278 } 279 280 std::string FQName::string() const { 281 CHECK(mValid) << mPackage << atVersion() << mName; 282 283 std::string out; 284 out.append(mPackage); 285 out.append(atVersion()); 286 if (!mName.empty()) { 287 if (!mPackage.empty() || !version().empty()) { 288 out.append("::"); 289 } 290 out.append(mName); 291 292 if (!mValueName.empty()) { 293 out.append(":"); 294 out.append(mValueName); 295 } 296 } 297 298 return out; 299 } 300 301 bool FQName::operator<(const FQName &other) const { 302 return string() < other.string(); 303 } 304 305 bool FQName::operator==(const FQName &other) const { 306 return string() == other.string(); 307 } 308 309 bool FQName::operator!=(const FQName &other) const { 310 return !(*this == other); 311 } 312 313 const std::string& FQName::getInterfaceName() const { 314 CHECK(isInterfaceName()) << mName; 315 316 return mName; 317 } 318 319 std::string FQName::getInterfaceBaseName() const { 320 // cut off the leading 'I'. 321 return getInterfaceName().substr(1); 322 } 323 324 std::string FQName::getInterfaceAdapterName() const { 325 return "A" + getInterfaceBaseName(); 326 } 327 328 std::string FQName::getInterfaceHwName() const { 329 return "IHw" + getInterfaceBaseName(); 330 } 331 332 std::string FQName::getInterfaceProxyName() const { 333 return "BpHw" + getInterfaceBaseName(); 334 } 335 336 std::string FQName::getInterfaceStubName() const { 337 return "BnHw" + getInterfaceBaseName(); 338 } 339 340 std::string FQName::getInterfacePassthroughName() const { 341 return "Bs" + getInterfaceBaseName(); 342 } 343 344 FQName FQName::getInterfaceProxyFqName() const { 345 return FQName(package(), version(), getInterfaceProxyName()); 346 } 347 348 FQName FQName::getInterfaceAdapterFqName() const { 349 return FQName(package(), version(), getInterfaceAdapterName()); 350 } 351 352 FQName FQName::getInterfaceStubFqName() const { 353 return FQName(package(), version(), getInterfaceStubName()); 354 } 355 356 FQName FQName::getInterfacePassthroughFqName() const { 357 return FQName(package(), version(), getInterfacePassthroughName()); 358 } 359 360 FQName FQName::getTypesForPackage() const { 361 return FQName(package(), version(), "types"); 362 } 363 364 FQName FQName::getPackageAndVersion() const { 365 return FQName(package(), version(), ""); 366 } 367 368 FQName FQName::getTopLevelType() const { 369 auto idx = mName.find('.'); 370 371 if (idx == std::string::npos) { 372 return *this; 373 } 374 375 return FQName(mPackage, version(), mName.substr(0, idx)); 376 } 377 378 std::string FQName::tokenName() const { 379 std::vector<std::string> components; 380 getPackageAndVersionComponents(&components, true /* cpp_compatible */); 381 382 if (!mName.empty()) { 383 std::vector<std::string> nameComponents; 384 StringHelper::SplitString(mName, '.', &nameComponents); 385 386 components.insert(components.end(), nameComponents.begin(), nameComponents.end()); 387 } 388 389 return StringHelper::JoinStrings(components, "_"); 390 } 391 392 std::string FQName::cppNamespace() const { 393 std::vector<std::string> components; 394 getPackageAndVersionComponents(&components, true /* cpp_compatible */); 395 396 std::string out = "::"; 397 out += StringHelper::JoinStrings(components, "::"); 398 399 return out; 400 } 401 402 std::string FQName::cppLocalName() const { 403 std::vector<std::string> components; 404 StringHelper::SplitString(mName, '.', &components); 405 406 return StringHelper::JoinStrings(components, "::") 407 + (mValueName.empty() ? "" : ("::" + mValueName)); 408 } 409 410 std::string FQName::cppName() const { 411 std::string out = cppNamespace(); 412 413 std::vector<std::string> components; 414 StringHelper::SplitString(name(), '.', &components); 415 out += "::"; 416 out += StringHelper::JoinStrings(components, "::"); 417 if (!mValueName.empty()) { 418 out += "::" + mValueName; 419 } 420 421 return out; 422 } 423 424 std::string FQName::javaPackage() const { 425 std::vector<std::string> components; 426 getPackageAndVersionComponents(&components, true /* cpp_compatible */); 427 428 return StringHelper::JoinStrings(components, "."); 429 } 430 431 std::string FQName::javaName() const { 432 return javaPackage() + "." + name() 433 + (mValueName.empty() ? "" : ("." + mValueName)); 434 } 435 436 void FQName::getPackageComponents(std::vector<std::string> *components) const { 437 StringHelper::SplitString(package(), '.', components); 438 } 439 440 void FQName::getPackageAndVersionComponents( 441 std::vector<std::string> *components, 442 bool cpp_compatible) const { 443 getPackageComponents(components); 444 445 if (!hasVersion()) { 446 LOG(WARNING) << "FQName: getPackageAndVersionComponents expects version."; 447 return; 448 } 449 450 if (!cpp_compatible) { 451 components->push_back(std::to_string(getPackageMajorVersion()) + 452 "." + std::to_string(getPackageMinorVersion())); 453 return; 454 } 455 456 components->push_back(sanitizedVersion()); 457 } 458 459 bool FQName::hasVersion() const { 460 return mMajor > 0; 461 } 462 463 FQName FQName::withVersion(size_t major, size_t minor) const { 464 FQName ret(*this); 465 ret.mMajor = major; 466 ret.mMinor = minor; 467 return ret; 468 } 469 470 size_t FQName::getPackageMajorVersion() const { 471 CHECK(hasVersion()) << "FQName: No version exists at getPackageMajorVersion(). " 472 << "Did you check hasVersion()?"; 473 return mMajor; 474 } 475 476 size_t FQName::getPackageMinorVersion() const { 477 CHECK(hasVersion()) << "FQName: No version exists at getPackageMinorVersion(). " 478 << "Did you check hasVersion()?"; 479 return mMinor; 480 } 481 482 bool FQName::endsWith(const FQName &other) const { 483 std::string s1 = string(); 484 std::string s2 = other.string(); 485 486 size_t pos = s1.rfind(s2); 487 if (pos == std::string::npos || pos + s2.size() != s1.size()) { 488 return false; 489 } 490 491 // A match is only a match if it is preceded by a "boundary", i.e. 492 // we perform a component-wise match from the end. 493 // "az" is not a match for "android.hardware.foo (at) 1.0::IFoo.bar.baz", 494 // "baz", "bar.baz", "IFoo.bar.baz", "@1.0::IFoo.bar.baz" are. 495 if (pos == 0) { 496 // matches "android.hardware.foo (at) 1.0::IFoo.bar.baz" 497 return true; 498 } 499 500 if (s1[pos - 1] == '.') { 501 // matches "baz" and "bar.baz" 502 return true; 503 } 504 505 if (s1[pos - 1] == ':') { 506 // matches "IFoo.bar.baz" 507 return true; 508 } 509 510 if (s1[pos] == '@') { 511 // matches "@1.0::IFoo.bar.baz" 512 return true; 513 } 514 515 return false; 516 } 517 518 bool FQName::inPackage(const std::string &package) const { 519 std::vector<std::string> components; 520 getPackageComponents(&components); 521 522 std::vector<std::string> inComponents; 523 StringHelper::SplitString(package, '.', &inComponents); 524 525 if (inComponents.size() > components.size()) { 526 return false; 527 } 528 529 for (size_t i = 0; i < inComponents.size(); i++) { 530 if (inComponents[i] != components[i]) { 531 return false; 532 } 533 } 534 535 return true; 536 } 537 538 FQName FQName::downRev() const { 539 FQName ret(*this); 540 CHECK(ret.mMinor > 0); 541 ret.mMinor--; 542 return ret; 543 } 544 545 const FQName gIBaseFqName = FQName("android.hidl.base", "1.0", "IBase"); 546 const FQName gIManagerFqName = FQName("android.hidl.manager", "1.0", "IServiceManager"); 547 548 } // namespace android 549 550