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