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