Home | History | Annotate | Download | only in utils
      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