blob: 0169e0c5a596ada1545744cc0710485feb6791e9 [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 ")*"
Andreas Huber84f89de2016-07-28 15:39:51 -070027#define RE_VERSION "@[0-9]+[.][0-9]+"
28
29static const std::regex kRE1("(" RE_PATH ")(" RE_VERSION ")?::(" RE_PATH ")");
30static const std::regex kRE2("(" RE_VERSION ")::(" RE_PATH ")");
Andreas Huberda51b8e2016-07-28 16:00:57 -070031static const std::regex kRE3("(" RE_PATH ")(" RE_VERSION ")");
Yifan Hongb44a6c82016-09-22 15:50:18 -070032static const std::regex kRE4("(" RE_COMPONENT ")([.]" RE_COMPONENT ")+");
33static const std::regex kRE5("(" RE_COMPONENT ")");
34
35static const std::regex kRE6("(" RE_PATH ")(" RE_VERSION ")?::(" RE_PATH "):(" RE_COMPONENT ")");
36static const std::regex kRE7("(" RE_VERSION ")::(" RE_PATH "):(" RE_COMPONENT ")");
37static const std::regex kRE8("(" RE_PATH "):(" RE_COMPONENT ")");
Andreas Huber84f89de2016-07-28 15:39:51 -070038
39namespace android {
40
Andreas Huberda51b8e2016-07-28 16:00:57 -070041FQName::FQName()
Yifan Hong327cfe12016-10-03 10:29:42 -070042 : mValid(false),
43 mIsIdentifier(false) {
Andreas Huberda51b8e2016-07-28 16:00:57 -070044}
45
Andreas Huber84f89de2016-07-28 15:39:51 -070046FQName::FQName(const std::string &s)
Yifan Hong327cfe12016-10-03 10:29:42 -070047 : mValid(false),
48 mIsIdentifier(false) {
Andreas Huber84f89de2016-07-28 15:39:51 -070049 setTo(s);
50}
51
Andreas Huber68f24592016-07-29 14:53:48 -070052FQName::FQName(
53 const std::string &package,
54 const std::string &version,
Yifan Hongb44a6c82016-09-22 15:50:18 -070055 const std::string &name,
56 const std::string &valueName)
Andreas Huber68f24592016-07-29 14:53:48 -070057 : mValid(true),
Yifan Hongb44a6c82016-09-22 15:50:18 -070058 mIsIdentifier(false),
Andreas Huber68f24592016-07-29 14:53:48 -070059 mPackage(package),
60 mVersion(version),
Yifan Hongb44a6c82016-09-22 15:50:18 -070061 mName(name),
62 mValueName(valueName) {
Andreas Huber68f24592016-07-29 14:53:48 -070063}
64
Yifan Hongf24fa852016-09-23 11:03:15 -070065FQName::FQName(const FQName& other)
66 : mValid(other.mValid),
67 mIsIdentifier(other.mIsIdentifier),
68 mPackage(other.mPackage),
69 mVersion(other.mVersion),
70 mName(other.mName),
71 mValueName(other.mValueName) {
72}
73
Yifan Hong327cfe12016-10-03 10:29:42 -070074FQName::FQName(const std::vector<std::string> &names)
75 : mValid(false),
76 mIsIdentifier(false) {
77 setTo(StringHelper::JoinStrings(names, "."));
78}
79
Andreas Huber84f89de2016-07-28 15:39:51 -070080bool FQName::isValid() const {
81 return mValid;
82}
83
Yifan Hongb44a6c82016-09-22 15:50:18 -070084bool FQName::isIdentifier() const {
85 return mIsIdentifier;
86}
87
Andreas Huber68f24592016-07-29 14:53:48 -070088bool FQName::isFullyQualified() const {
89 return !mPackage.empty() && !mVersion.empty() && !mName.empty();
90}
91
Yifan Hongb44a6c82016-09-22 15:50:18 -070092bool FQName::isValidValueName() const {
93 return mIsIdentifier
94 || (!mName.empty() && !mValueName.empty());
95}
96
Andreas Huber84f89de2016-07-28 15:39:51 -070097bool FQName::setTo(const std::string &s) {
98 mPackage.clear();
99 mVersion.clear();
100 mName.clear();
101
102 mValid = true;
103
104 std::smatch match;
105 if (std::regex_match(s, match, kRE1)) {
Yifan Hong95a47bb2016-09-29 10:08:10 -0700106 CHECK_EQ(match.size(), 4u);
Andreas Huber84f89de2016-07-28 15:39:51 -0700107
108 mPackage = match.str(1);
Yifan Hong95a47bb2016-09-29 10:08:10 -0700109 mVersion = match.str(2);
110 mName = match.str(3);
Andreas Huber84f89de2016-07-28 15:39:51 -0700111 } else if (std::regex_match(s, match, kRE2)) {
Yifan Hong95a47bb2016-09-29 10:08:10 -0700112 CHECK_EQ(match.size(), 3u);
Andreas Huber84f89de2016-07-28 15:39:51 -0700113
114 mVersion = match.str(1);
115 mName = match.str(2);
116 } else if (std::regex_match(s, match, kRE3)) {
Yifan Hong95a47bb2016-09-29 10:08:10 -0700117 CHECK_EQ(match.size(), 3u);
Andreas Huberda51b8e2016-07-28 16:00:57 -0700118
119 mPackage = match.str(1);
Yifan Hong95a47bb2016-09-29 10:08:10 -0700120 mVersion = match.str(2);
Andreas Huberda51b8e2016-07-28 16:00:57 -0700121 } else if (std::regex_match(s, match, kRE4)) {
Andreas Huber84f89de2016-07-28 15:39:51 -0700122 mName = match.str(0);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700123 } else if (std::regex_match(s, match, kRE5)) {
124 mIsIdentifier = true;
125 mName = match.str(0);
126 } else if (std::regex_match(s, match, kRE6)) {
Yifan Hong95a47bb2016-09-29 10:08:10 -0700127 CHECK_EQ(match.size(), 5u);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700128
129 mPackage = match.str(1);
Yifan Hong95a47bb2016-09-29 10:08:10 -0700130 mVersion = match.str(2);
131 mName = match.str(3);
132 mValueName = match.str(4);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700133 } else if (std::regex_match(s, match, kRE7)) {
Yifan Hong95a47bb2016-09-29 10:08:10 -0700134 CHECK_EQ(match.size(), 4u);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700135
136 mVersion = match.str(1);
137 mName = match.str(2);
Yifan Hong95a47bb2016-09-29 10:08:10 -0700138 mValueName = match.str(3);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700139 } else if (std::regex_match(s, match, kRE8)) {
Yifan Hong95a47bb2016-09-29 10:08:10 -0700140 CHECK_EQ(match.size(), 3u);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700141
142 mName = match.str(1);
Yifan Hong95a47bb2016-09-29 10:08:10 -0700143 mValueName = match.str(2);
Andreas Huber84f89de2016-07-28 15:39:51 -0700144 } else {
145 mValid = false;
146 }
147
Yifan Hongb44a6c82016-09-22 15:50:18 -0700148 // mValueName must go with mName.
149 if (!mValueName.empty()) {
150 CHECK(!mName.empty());
151 }
152
Andreas Huber84f89de2016-07-28 15:39:51 -0700153 return isValid();
154}
155
156std::string FQName::package() const {
157 return mPackage;
158}
159
160std::string FQName::version() const {
161 return mVersion;
162}
163
164std::string FQName::name() const {
165 return mName;
166}
167
Iliyan Malchev800273d2016-09-02 15:25:07 -0700168std::vector<std::string> FQName::names() const {
169 std::vector<std::string> res {};
170 std::istringstream ss(name());
171 std::string s;
172 while (std::getline(ss, s, '.')) {
173 res.push_back(s);
174 }
175 return res;
176}
177
Yifan Hongb44a6c82016-09-22 15:50:18 -0700178std::string FQName::valueName() const {
179 return mValueName;
180}
181
182FQName FQName::typeName() const {
183 return FQName(mPackage, mVersion, mName);
184}
185
Andreas Huber84f89de2016-07-28 15:39:51 -0700186void FQName::applyDefaults(
187 const std::string &defaultPackage,
188 const std::string &defaultVersion) {
189 if (mPackage.empty()) {
190 mPackage = defaultPackage;
191 }
192
193 if (mVersion.empty()) {
194 mVersion = defaultVersion;
195 }
196}
197
Andreas Huber68f24592016-07-29 14:53:48 -0700198std::string FQName::string() const {
Andreas Huber84f89de2016-07-28 15:39:51 -0700199 CHECK(mValid);
200
Andreas Huber5345ec22016-07-29 13:33:27 -0700201 std::string out;
Andreas Huber84f89de2016-07-28 15:39:51 -0700202 out.append(mPackage);
203 out.append(mVersion);
Andreas Huberda51b8e2016-07-28 16:00:57 -0700204 if (!mName.empty()) {
205 if (!mPackage.empty() || !mVersion.empty()) {
206 out.append("::");
207 }
208 out.append(mName);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700209
210 if (!mValueName.empty()) {
211 out.append(":");
212 out.append(mValueName);
213 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700214 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700215
216 return out;
217}
218
Andreas Huberda51b8e2016-07-28 16:00:57 -0700219void FQName::print() const {
220 if (!mValid) {
221 LOG(INFO) << "INVALID";
222 return;
223 }
224
Andreas Huber68f24592016-07-29 14:53:48 -0700225 LOG(INFO) << string();
226}
227
228bool FQName::operator<(const FQName &other) const {
229 return string() < other.string();
Andreas Huberda51b8e2016-07-28 16:00:57 -0700230}
231
Andreas Huberd2943e12016-08-05 11:59:31 -0700232bool FQName::operator==(const FQName &other) const {
233 return string() == other.string();
234}
235
Steven Moreland197d56c2016-09-09 10:03:58 -0700236std::string FQName::getInterfaceBaseName() const {
237 CHECK(names().size() == 1) << "Must be a top level type";
238 CHECK(!mName.empty() && mName[0] == 'I') << mName;
239
240 // cut off the leading 'I'.
241 return mName.substr(1);
242}
243
Yifan Hong1977ea32016-10-05 12:49:08 -0700244FQName FQName::getTypesForPackage() const {
245 return FQName(package(), version(), "types");
246}
247
Steven Moreland9c387612016-09-07 09:54:26 -0700248const FQName FQName::getTopLevelType() const {
249 auto idx = mName.find('.');
250
251 if (idx == std::string::npos) {
252 return *this;
253 }
254
255 return FQName(mPackage, mVersion, mName.substr(0, idx));
256}
257
258std::string FQName::tokenName() const {
259 std::vector<std::string> components;
260 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
261
262 std::vector<std::string> nameComponents;
Steven Morelandaf440142016-09-07 10:09:11 -0700263 StringHelper::SplitString(mName, '.', &nameComponents);
Steven Moreland9c387612016-09-07 09:54:26 -0700264
265 components.insert(components.end(), nameComponents.begin(), nameComponents.end());
266
Steven Morelandaf440142016-09-07 10:09:11 -0700267 return StringHelper::JoinStrings(components, "_");
Steven Moreland9c387612016-09-07 09:54:26 -0700268}
269
Andreas Huber0e00de42016-08-03 09:56:02 -0700270std::string FQName::cppNamespace() const {
271 std::vector<std::string> components;
272 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
273
274 std::string out = "::";
Steven Morelandaf440142016-09-07 10:09:11 -0700275 out += StringHelper::JoinStrings(components, "::");
Andreas Huber0e00de42016-08-03 09:56:02 -0700276
277 return out;
278}
279
Steven Moreland979e0992016-09-07 09:18:08 -0700280std::string FQName::cppLocalName() const {
281 std::vector<std::string> components;
Steven Morelandaf440142016-09-07 10:09:11 -0700282 StringHelper::SplitString(mName, '.', &components);
Steven Moreland979e0992016-09-07 09:18:08 -0700283
Yifan Hongb44a6c82016-09-22 15:50:18 -0700284 return StringHelper::JoinStrings(components, "::")
285 + (mValueName.empty() ? "" : ("::" + mValueName));
Steven Moreland979e0992016-09-07 09:18:08 -0700286}
287
Andreas Huber0e00de42016-08-03 09:56:02 -0700288std::string FQName::cppName() const {
289 std::string out = cppNamespace();
290
291 std::vector<std::string> components;
Steven Morelandaf440142016-09-07 10:09:11 -0700292 StringHelper::SplitString(name(), '.', &components);
Andreas Huber0e00de42016-08-03 09:56:02 -0700293 out += "::";
Steven Morelandaf440142016-09-07 10:09:11 -0700294 out += StringHelper::JoinStrings(components, "::");
Yifan Hongb44a6c82016-09-22 15:50:18 -0700295 if (!mValueName.empty()) {
296 out += "::" + mValueName;
297 }
Andreas Huber0e00de42016-08-03 09:56:02 -0700298
299 return out;
300}
301
Andreas Huber2831d512016-08-15 09:33:47 -0700302std::string FQName::javaPackage() const {
303 std::vector<std::string> components;
304 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
305
Steven Morelandaf440142016-09-07 10:09:11 -0700306 return StringHelper::JoinStrings(components, ".");
Andreas Huber2831d512016-08-15 09:33:47 -0700307}
308
309std::string FQName::javaName() const {
Yifan Hongb44a6c82016-09-22 15:50:18 -0700310 return javaPackage() + "." + name()
311 + (mValueName.empty() ? "" : ("." + mValueName));
Andreas Huber2831d512016-08-15 09:33:47 -0700312}
313
Andreas Huber0e00de42016-08-03 09:56:02 -0700314void FQName::getPackageComponents(std::vector<std::string> *components) const {
Steven Morelandaf440142016-09-07 10:09:11 -0700315 StringHelper::SplitString(package(), '.', components);
Andreas Huber0e00de42016-08-03 09:56:02 -0700316}
317
318void FQName::getPackageAndVersionComponents(
319 std::vector<std::string> *components,
320 bool cpp_compatible) const {
321 getPackageComponents(components);
322
Andreas Huber0e00de42016-08-03 09:56:02 -0700323 if (!cpp_compatible) {
Martijn Coenena21f1492016-09-08 15:55:14 +0200324 components->push_back(getPackageMajorVersion() +
325 "." + getPackageMinorVersion());
Andreas Huber0e00de42016-08-03 09:56:02 -0700326 return;
327 }
328
Andreas Huber0e00de42016-08-03 09:56:02 -0700329 // Form "Vmajor_minor".
330 std::string versionString = "V";
Martijn Coenena21f1492016-09-08 15:55:14 +0200331 versionString.append(getPackageMajorVersion());
Andreas Huber0e00de42016-08-03 09:56:02 -0700332 versionString.append("_");
Martijn Coenena21f1492016-09-08 15:55:14 +0200333 versionString.append(getPackageMinorVersion());
Andreas Huber0e00de42016-08-03 09:56:02 -0700334
335 components->push_back(versionString);
336}
337
Martijn Coenena21f1492016-09-08 15:55:14 +0200338std::string FQName::getPackageMajorVersion() const {
339 const std::string packageVersion = version();
340 CHECK(packageVersion[0] == '@');
341 const size_t dotPos = packageVersion.find('.');
342 CHECK(dotPos != std::string::npos);
343 return packageVersion.substr(1, dotPos - 1);
344}
345
346std::string FQName::getPackageMinorVersion() const {
347 const std::string packageVersion = version();
348 CHECK(packageVersion[0] == '@');
349 const size_t dotPos = packageVersion.find('.');
350 CHECK(dotPos != std::string::npos);
351 return packageVersion.substr(dotPos + 1);
352}
353
Zhuoyao Zhang8f492942016-09-28 14:27:56 -0700354std::string FQName::getPackageFullVersion() const {
355 const std::string packageVersion = version();
356 CHECK_GT(packageVersion.length(), 1u);
357 return packageVersion.substr(1);
358}
359
Andreas Huber39fa7182016-08-19 14:27:33 -0700360bool FQName::endsWith(const FQName &other) const {
361 std::string s1 = string();
362 std::string s2 = other.string();
363
364 size_t pos = s1.rfind(s2);
365 if (pos == std::string::npos || pos + s2.size() != s1.size()) {
366 return false;
367 }
368
Yifan Hongd9f22f72016-10-05 15:17:33 -0700369 // A match is only a match if it is preceded by a "boundary", i.e.
370 // we perform a component-wise match from the end.
371 // "az" is not a match for "android.hardware.foo@1.0::IFoo.bar.baz",
372 // "baz", "bar.baz", "IFoo.bar.baz", "@1.0::IFoo.bar.baz" are.
373 if (pos == 0) {
374 // matches "android.hardware.foo@1.0::IFoo.bar.baz"
375 return true;
Andreas Huber39fa7182016-08-19 14:27:33 -0700376 }
377
Yifan Hongd9f22f72016-10-05 15:17:33 -0700378 if (s1[pos - 1] == '.') {
379 // matches "baz" and "bar.baz"
380 return true;
381 }
382
383 if (s1[pos - 1] == ':') {
384 // matches "IFoo.bar.baz"
385 return true;
386 }
387
388 if (s1[pos] == '@') {
389 // matches "@1.0::IFoo.bar.baz"
390 return true;
391 }
392
393 return false;
Andreas Huber39fa7182016-08-19 14:27:33 -0700394}
395
Andreas Huber84f89de2016-07-28 15:39:51 -0700396} // namespace android
397