blob: 5e9e34740f1dfdce0a285cb07f077e231b6e37fb [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
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
Andreas Huber84f89de2016-07-28 15:39:51 -070017#include "FQName.h"
18
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070019#include <hidl-util/StringHelper.h>
Andreas Huber84f89de2016-07-28 15:39:51 -070020#include <android-base/logging.h>
Iliyan Malchev800273d2016-09-02 15:25:07 -070021#include <iostream>
Andreas Huber84f89de2016-07-28 15:39:51 -070022#include <regex>
Iliyan Malchev800273d2016-09-02 15:25:07 -070023#include <sstream>
Andreas Huber84f89de2016-07-28 15:39:51 -070024
25#define RE_COMPONENT "[a-zA-Z_][a-zA-Z_0-9]*"
Yifan Hong95a47bb2016-09-29 10:08:10 -070026#define RE_PATH RE_COMPONENT "(?:[.]" RE_COMPONENT ")*"
Yifan Hong90ea87f2016-11-01 14:25:47 -070027#define RE_MAJOR "[0-9]+"
28#define RE_MINOR "[0-9]+"
Andreas Huber84f89de2016-07-28 15:39:51 -070029
Yifan Hong90ea87f2016-11-01 14:25:47 -070030static const std::regex kRE1("(" RE_PATH ")@(" RE_MAJOR ")[.](" RE_MINOR ")?::(" RE_PATH ")");
31static const std::regex kRE2("@(" RE_MAJOR ")[.](" RE_MINOR ")::(" RE_PATH ")");
32static const std::regex kRE3("(" RE_PATH ")@(" RE_MAJOR ")[.](" RE_MINOR ")");
Yifan Hongb44a6c82016-09-22 15:50:18 -070033static const std::regex kRE4("(" RE_COMPONENT ")([.]" RE_COMPONENT ")+");
34static const std::regex kRE5("(" RE_COMPONENT ")");
35
Yifan Hong90ea87f2016-11-01 14:25:47 -070036static const std::regex kRE6("(" RE_PATH ")@(" RE_MAJOR ")[.](" RE_MINOR ")?::(" RE_PATH "):(" RE_COMPONENT ")");
37static const std::regex kRE7("@(" RE_MAJOR ")[.](" RE_MINOR ")::(" RE_PATH "):(" RE_COMPONENT ")");
Yifan Hongb44a6c82016-09-22 15:50:18 -070038static const std::regex kRE8("(" RE_PATH "):(" RE_COMPONENT ")");
Andreas Huber84f89de2016-07-28 15:39:51 -070039
Yifan Hong90ea87f2016-11-01 14:25:47 -070040static const std::regex kREVer("(" RE_MAJOR ")[.](" RE_MINOR ")");
41
Andreas Huber84f89de2016-07-28 15:39:51 -070042namespace android {
43
Andreas Huberda51b8e2016-07-28 16:00:57 -070044FQName::FQName()
Yifan Hong327cfe12016-10-03 10:29:42 -070045 : mValid(false),
46 mIsIdentifier(false) {
Andreas Huberda51b8e2016-07-28 16:00:57 -070047}
48
Andreas Huber84f89de2016-07-28 15:39:51 -070049FQName::FQName(const std::string &s)
Yifan Hong327cfe12016-10-03 10:29:42 -070050 : mValid(false),
51 mIsIdentifier(false) {
Andreas Huber84f89de2016-07-28 15:39:51 -070052 setTo(s);
53}
54
Andreas Huber68f24592016-07-29 14:53:48 -070055FQName::FQName(
56 const std::string &package,
57 const std::string &version,
Yifan Hongb44a6c82016-09-22 15:50:18 -070058 const std::string &name,
59 const std::string &valueName)
Andreas Huber68f24592016-07-29 14:53:48 -070060 : mValid(true),
Yifan Hongb44a6c82016-09-22 15:50:18 -070061 mIsIdentifier(false),
Andreas Huber68f24592016-07-29 14:53:48 -070062 mPackage(package),
Yifan Hongb44a6c82016-09-22 15:50:18 -070063 mName(name),
64 mValueName(valueName) {
Yifan Hong90ea87f2016-11-01 14:25:47 -070065 setVersion(version);
Andreas Huber68f24592016-07-29 14:53:48 -070066}
67
Yifan Hongf24fa852016-09-23 11:03:15 -070068FQName::FQName(const FQName& other)
69 : mValid(other.mValid),
70 mIsIdentifier(other.mIsIdentifier),
71 mPackage(other.mPackage),
Yifan Hong90ea87f2016-11-01 14:25:47 -070072 mMajor(other.mMajor),
73 mMinor(other.mMinor),
Yifan Hongf24fa852016-09-23 11:03:15 -070074 mName(other.mName),
75 mValueName(other.mValueName) {
76}
77
Yifan Hong327cfe12016-10-03 10:29:42 -070078FQName::FQName(const std::vector<std::string> &names)
79 : mValid(false),
80 mIsIdentifier(false) {
81 setTo(StringHelper::JoinStrings(names, "."));
82}
83
Andreas Huber84f89de2016-07-28 15:39:51 -070084bool FQName::isValid() const {
85 return mValid;
86}
87
Yifan Hongb44a6c82016-09-22 15:50:18 -070088bool FQName::isIdentifier() const {
89 return mIsIdentifier;
90}
91
Andreas Huber68f24592016-07-29 14:53:48 -070092bool FQName::isFullyQualified() const {
Yifan Hong90ea87f2016-11-01 14:25:47 -070093 return !mPackage.empty() && !version().empty() && !mName.empty();
Andreas Huber68f24592016-07-29 14:53:48 -070094}
95
Yifan Hongb44a6c82016-09-22 15:50:18 -070096bool FQName::isValidValueName() const {
97 return mIsIdentifier
98 || (!mName.empty() && !mValueName.empty());
99}
100
Andreas Huber84f89de2016-07-28 15:39:51 -0700101bool FQName::setTo(const std::string &s) {
102 mPackage.clear();
Yifan Hong90ea87f2016-11-01 14:25:47 -0700103 mMajor.clear();
104 mMinor.clear();
Andreas Huber84f89de2016-07-28 15:39:51 -0700105 mName.clear();
106
107 mValid = true;
108
109 std::smatch match;
110 if (std::regex_match(s, match, kRE1)) {
Yifan Hong90ea87f2016-11-01 14:25:47 -0700111 CHECK_EQ(match.size(), 5u);
112
113 mPackage = match.str(1);
114 mMajor = match.str(2);
115 mMinor = 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 mMajor = match.str(1);
121 mMinor = match.str(2);
122 mName = match.str(3);
123 } else if (std::regex_match(s, match, kRE3)) {
Yifan Hong95a47bb2016-09-29 10:08:10 -0700124 CHECK_EQ(match.size(), 4u);
Andreas Huber84f89de2016-07-28 15:39:51 -0700125
126 mPackage = match.str(1);
Yifan Hong90ea87f2016-11-01 14:25:47 -0700127 mMajor = match.str(2);
128 mMinor = match.str(3);
Andreas Huberda51b8e2016-07-28 16:00:57 -0700129 } else if (std::regex_match(s, match, kRE4)) {
Andreas Huber84f89de2016-07-28 15:39:51 -0700130 mName = match.str(0);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700131 } else if (std::regex_match(s, match, kRE5)) {
132 mIsIdentifier = true;
133 mName = match.str(0);
134 } else if (std::regex_match(s, match, kRE6)) {
Yifan Hong90ea87f2016-11-01 14:25:47 -0700135 CHECK_EQ(match.size(), 6u);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700136
137 mPackage = match.str(1);
Yifan Hong90ea87f2016-11-01 14:25:47 -0700138 mMajor = match.str(2);
139 mMinor = match.str(3);
140 mName = match.str(4);
141 mValueName = match.str(5);
142 } else if (std::regex_match(s, match, kRE7)) {
143 CHECK_EQ(match.size(), 5u);
144
145 mMajor = match.str(1);
146 mMinor = match.str(2);
Yifan Hong95a47bb2016-09-29 10:08:10 -0700147 mName = match.str(3);
148 mValueName = match.str(4);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700149 } else if (std::regex_match(s, match, kRE8)) {
Yifan Hong95a47bb2016-09-29 10:08:10 -0700150 CHECK_EQ(match.size(), 3u);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700151
152 mName = match.str(1);
Yifan Hong95a47bb2016-09-29 10:08:10 -0700153 mValueName = match.str(2);
Andreas Huber84f89de2016-07-28 15:39:51 -0700154 } else {
155 mValid = false;
156 }
157
Yifan Hongb44a6c82016-09-22 15:50:18 -0700158 // mValueName must go with mName.
159 if (!mValueName.empty()) {
160 CHECK(!mName.empty());
161 }
162
Andreas Huber84f89de2016-07-28 15:39:51 -0700163 return isValid();
164}
165
166std::string FQName::package() const {
167 return mPackage;
168}
169
170std::string FQName::version() const {
Yifan Hong90ea87f2016-11-01 14:25:47 -0700171 CHECK(mMajor.empty() == mMinor.empty());
172 if (mMajor.empty() && mMinor.empty()) {
173 return "";
174 }
175 return mMajor + "." + mMinor;
176}
177
Yifan Hong97288ac2016-12-12 16:03:51 -0800178std::string FQName::sanitizedVersion() const {
179 CHECK(mMajor.empty() == mMinor.empty());
180 if (mMajor.empty() && mMinor.empty()) {
181 return "";
182 }
183 return "V" + mMajor + "_" + mMinor;
184}
185
Yifan Hong90ea87f2016-11-01 14:25:47 -0700186std::string FQName::atVersion() const {
187 std::string v = version();
188 return v.empty() ? "" : ("@" + v);
189}
190
191void FQName::setVersion(const std::string &v) {
192 if (v.empty()) {
193 mMajor.clear();
194 mMinor.clear();
195 return;
196 }
197 std::smatch match;
198 if (std::regex_match(v, match, kREVer)) {
199 CHECK_EQ(match.size(), 3u);
200
201 mMajor = match.str(1);
202 mMinor = match.str(2);
203 } else {
204 mValid = false;
205 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700206}
207
208std::string FQName::name() const {
209 return mName;
210}
211
Iliyan Malchev800273d2016-09-02 15:25:07 -0700212std::vector<std::string> FQName::names() const {
213 std::vector<std::string> res {};
214 std::istringstream ss(name());
215 std::string s;
216 while (std::getline(ss, s, '.')) {
217 res.push_back(s);
218 }
219 return res;
220}
221
Yifan Hongb44a6c82016-09-22 15:50:18 -0700222std::string FQName::valueName() const {
223 return mValueName;
224}
225
226FQName FQName::typeName() const {
Yifan Hong90ea87f2016-11-01 14:25:47 -0700227 return FQName(mPackage, version(), mName);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700228}
229
Andreas Huber84f89de2016-07-28 15:39:51 -0700230void FQName::applyDefaults(
231 const std::string &defaultPackage,
232 const std::string &defaultVersion) {
233 if (mPackage.empty()) {
234 mPackage = defaultPackage;
235 }
236
Yifan Hong90ea87f2016-11-01 14:25:47 -0700237 if (version().empty()) {
238 setVersion(defaultVersion);
Andreas Huber84f89de2016-07-28 15:39:51 -0700239 }
240}
241
Andreas Huber68f24592016-07-29 14:53:48 -0700242std::string FQName::string() const {
Andreas Huber84f89de2016-07-28 15:39:51 -0700243 CHECK(mValid);
244
Andreas Huber5345ec22016-07-29 13:33:27 -0700245 std::string out;
Andreas Huber84f89de2016-07-28 15:39:51 -0700246 out.append(mPackage);
Yifan Hong90ea87f2016-11-01 14:25:47 -0700247 out.append(atVersion());
Andreas Huberda51b8e2016-07-28 16:00:57 -0700248 if (!mName.empty()) {
Yifan Hong90ea87f2016-11-01 14:25:47 -0700249 if (!mPackage.empty() || !version().empty()) {
Andreas Huberda51b8e2016-07-28 16:00:57 -0700250 out.append("::");
251 }
252 out.append(mName);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700253
254 if (!mValueName.empty()) {
255 out.append(":");
256 out.append(mValueName);
257 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700258 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700259
260 return out;
261}
262
Andreas Huberda51b8e2016-07-28 16:00:57 -0700263void FQName::print() const {
264 if (!mValid) {
265 LOG(INFO) << "INVALID";
266 return;
267 }
268
Andreas Huber68f24592016-07-29 14:53:48 -0700269 LOG(INFO) << string();
270}
271
272bool FQName::operator<(const FQName &other) const {
273 return string() < other.string();
Andreas Huberda51b8e2016-07-28 16:00:57 -0700274}
275
Andreas Huberd2943e12016-08-05 11:59:31 -0700276bool FQName::operator==(const FQName &other) const {
277 return string() == other.string();
278}
279
Yifan Hongc8934042016-11-17 17:10:52 -0800280bool FQName::operator!=(const FQName &other) const {
281 return !(*this == other);
282}
283
Yifan Hongeefe4f22017-01-04 15:32:42 -0800284std::string FQName::getInterfaceName() const {
Steven Moreland197d56c2016-09-09 10:03:58 -0700285 CHECK(names().size() == 1) << "Must be a top level type";
286 CHECK(!mName.empty() && mName[0] == 'I') << mName;
287
Yifan Hongeefe4f22017-01-04 15:32:42 -0800288 return mName;
289}
290
291std::string FQName::getInterfaceBaseName() const {
Steven Moreland197d56c2016-09-09 10:03:58 -0700292 // cut off the leading 'I'.
Yifan Hongeefe4f22017-01-04 15:32:42 -0800293 return getInterfaceName().substr(1);
294}
295
296std::string FQName::getInterfaceHwName() const {
297 return "IHw" + getInterfaceBaseName();
298}
299
300std::string FQName::getInterfaceProxyName() const {
301 return "Bp" + getInterfaceBaseName();
302}
303
304std::string FQName::getInterfaceStubName() const {
305 return "Bn" + getInterfaceBaseName();
306}
307
308std::string FQName::getInterfacePassthroughName() const {
309 return "Bs" + getInterfaceBaseName();
310}
311
312FQName FQName::getInterfaceProxyFqName() const {
313 return FQName(package(), version(), getInterfaceProxyName());
314}
315
316FQName FQName::getInterfaceStubFqName() const {
317 return FQName(package(), version(), getInterfaceStubName());
318}
319
320FQName FQName::getInterfacePassthroughFqName() const {
321 return FQName(package(), version(), getInterfacePassthroughName());
Steven Moreland197d56c2016-09-09 10:03:58 -0700322}
323
Yifan Hong1977ea32016-10-05 12:49:08 -0700324FQName FQName::getTypesForPackage() const {
325 return FQName(package(), version(), "types");
326}
327
Steven Moreland9c387612016-09-07 09:54:26 -0700328const FQName FQName::getTopLevelType() const {
329 auto idx = mName.find('.');
330
331 if (idx == std::string::npos) {
332 return *this;
333 }
334
Yifan Hong90ea87f2016-11-01 14:25:47 -0700335 return FQName(mPackage, version(), mName.substr(0, idx));
Steven Moreland9c387612016-09-07 09:54:26 -0700336}
337
338std::string FQName::tokenName() const {
339 std::vector<std::string> components;
340 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
341
Steven Moreland6f596c82016-11-29 18:45:24 -0800342 if (!mName.empty()) {
343 std::vector<std::string> nameComponents;
344 StringHelper::SplitString(mName, '.', &nameComponents);
Steven Moreland9c387612016-09-07 09:54:26 -0700345
Steven Moreland6f596c82016-11-29 18:45:24 -0800346 components.insert(components.end(), nameComponents.begin(), nameComponents.end());
347 }
Steven Moreland9c387612016-09-07 09:54:26 -0700348
Steven Morelandaf440142016-09-07 10:09:11 -0700349 return StringHelper::JoinStrings(components, "_");
Steven Moreland9c387612016-09-07 09:54:26 -0700350}
351
Andreas Huber0e00de42016-08-03 09:56:02 -0700352std::string FQName::cppNamespace() const {
353 std::vector<std::string> components;
354 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
355
356 std::string out = "::";
Steven Morelandaf440142016-09-07 10:09:11 -0700357 out += StringHelper::JoinStrings(components, "::");
Andreas Huber0e00de42016-08-03 09:56:02 -0700358
359 return out;
360}
361
Steven Moreland979e0992016-09-07 09:18:08 -0700362std::string FQName::cppLocalName() const {
363 std::vector<std::string> components;
Steven Morelandaf440142016-09-07 10:09:11 -0700364 StringHelper::SplitString(mName, '.', &components);
Steven Moreland979e0992016-09-07 09:18:08 -0700365
Yifan Hongb44a6c82016-09-22 15:50:18 -0700366 return StringHelper::JoinStrings(components, "::")
367 + (mValueName.empty() ? "" : ("::" + mValueName));
Steven Moreland979e0992016-09-07 09:18:08 -0700368}
369
Andreas Huber0e00de42016-08-03 09:56:02 -0700370std::string FQName::cppName() const {
371 std::string out = cppNamespace();
372
373 std::vector<std::string> components;
Steven Morelandaf440142016-09-07 10:09:11 -0700374 StringHelper::SplitString(name(), '.', &components);
Andreas Huber0e00de42016-08-03 09:56:02 -0700375 out += "::";
Steven Morelandaf440142016-09-07 10:09:11 -0700376 out += StringHelper::JoinStrings(components, "::");
Yifan Hongb44a6c82016-09-22 15:50:18 -0700377 if (!mValueName.empty()) {
378 out += "::" + mValueName;
379 }
Andreas Huber0e00de42016-08-03 09:56:02 -0700380
381 return out;
382}
383
Andreas Huber2831d512016-08-15 09:33:47 -0700384std::string FQName::javaPackage() const {
385 std::vector<std::string> components;
386 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
387
Steven Morelandaf440142016-09-07 10:09:11 -0700388 return StringHelper::JoinStrings(components, ".");
Andreas Huber2831d512016-08-15 09:33:47 -0700389}
390
391std::string FQName::javaName() const {
Yifan Hongb44a6c82016-09-22 15:50:18 -0700392 return javaPackage() + "." + name()
393 + (mValueName.empty() ? "" : ("." + mValueName));
Andreas Huber2831d512016-08-15 09:33:47 -0700394}
395
Andreas Huber0e00de42016-08-03 09:56:02 -0700396void FQName::getPackageComponents(std::vector<std::string> *components) const {
Steven Morelandaf440142016-09-07 10:09:11 -0700397 StringHelper::SplitString(package(), '.', components);
Andreas Huber0e00de42016-08-03 09:56:02 -0700398}
399
400void FQName::getPackageAndVersionComponents(
401 std::vector<std::string> *components,
402 bool cpp_compatible) const {
403 getPackageComponents(components);
404
Andreas Huber0e00de42016-08-03 09:56:02 -0700405 if (!cpp_compatible) {
Martijn Coenena21f1492016-09-08 15:55:14 +0200406 components->push_back(getPackageMajorVersion() +
407 "." + getPackageMinorVersion());
Andreas Huber0e00de42016-08-03 09:56:02 -0700408 return;
409 }
410
Yifan Hong97288ac2016-12-12 16:03:51 -0800411 components->push_back(sanitizedVersion());
Andreas Huber0e00de42016-08-03 09:56:02 -0700412}
413
Martijn Coenena21f1492016-09-08 15:55:14 +0200414std::string FQName::getPackageMajorVersion() const {
Yifan Hong90ea87f2016-11-01 14:25:47 -0700415 return mMajor;
Martijn Coenena21f1492016-09-08 15:55:14 +0200416}
417
418std::string FQName::getPackageMinorVersion() const {
Yifan Hong90ea87f2016-11-01 14:25:47 -0700419 return mMinor;
Zhuoyao Zhang8f492942016-09-28 14:27:56 -0700420}
421
Andreas Huber39fa7182016-08-19 14:27:33 -0700422bool FQName::endsWith(const FQName &other) const {
423 std::string s1 = string();
424 std::string s2 = other.string();
425
426 size_t pos = s1.rfind(s2);
427 if (pos == std::string::npos || pos + s2.size() != s1.size()) {
428 return false;
429 }
430
Yifan Hongd9f22f72016-10-05 15:17:33 -0700431 // A match is only a match if it is preceded by a "boundary", i.e.
432 // we perform a component-wise match from the end.
433 // "az" is not a match for "android.hardware.foo@1.0::IFoo.bar.baz",
434 // "baz", "bar.baz", "IFoo.bar.baz", "@1.0::IFoo.bar.baz" are.
435 if (pos == 0) {
436 // matches "android.hardware.foo@1.0::IFoo.bar.baz"
437 return true;
Andreas Huber39fa7182016-08-19 14:27:33 -0700438 }
439
Yifan Hongd9f22f72016-10-05 15:17:33 -0700440 if (s1[pos - 1] == '.') {
441 // matches "baz" and "bar.baz"
442 return true;
443 }
444
445 if (s1[pos - 1] == ':') {
446 // matches "IFoo.bar.baz"
447 return true;
448 }
449
450 if (s1[pos] == '@') {
451 // matches "@1.0::IFoo.bar.baz"
452 return true;
453 }
454
455 return false;
Andreas Huber39fa7182016-08-19 14:27:33 -0700456}
457
Andreas Huber84f89de2016-07-28 15:39:51 -0700458} // namespace android
459