blob: 5d9c3261d6f8827137ac051b7c9f8baf252e1faa [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]*"
26#define RE_PATH RE_COMPONENT "([.]" RE_COMPONENT ")*"
27#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 Hongb44a6c82016-09-22 15:50:18 -070042 : mValid(false), mIsIdentifier(false) {
Andreas Huberda51b8e2016-07-28 16:00:57 -070043}
44
Andreas Huber84f89de2016-07-28 15:39:51 -070045FQName::FQName(const std::string &s)
Yifan Hongb44a6c82016-09-22 15:50:18 -070046 : mValid(false), mIsIdentifier(false) {
Andreas Huber84f89de2016-07-28 15:39:51 -070047 setTo(s);
48}
49
Andreas Huber68f24592016-07-29 14:53:48 -070050FQName::FQName(
51 const std::string &package,
52 const std::string &version,
Yifan Hongb44a6c82016-09-22 15:50:18 -070053 const std::string &name,
54 const std::string &valueName)
Andreas Huber68f24592016-07-29 14:53:48 -070055 : mValid(true),
Yifan Hongb44a6c82016-09-22 15:50:18 -070056 mIsIdentifier(false),
Andreas Huber68f24592016-07-29 14:53:48 -070057 mPackage(package),
58 mVersion(version),
Yifan Hongb44a6c82016-09-22 15:50:18 -070059 mName(name),
60 mValueName(valueName) {
Andreas Huber68f24592016-07-29 14:53:48 -070061}
62
Andreas Huber84f89de2016-07-28 15:39:51 -070063bool FQName::isValid() const {
64 return mValid;
65}
66
Yifan Hongb44a6c82016-09-22 15:50:18 -070067bool FQName::isIdentifier() const {
68 return mIsIdentifier;
69}
70
Andreas Huber68f24592016-07-29 14:53:48 -070071bool FQName::isFullyQualified() const {
72 return !mPackage.empty() && !mVersion.empty() && !mName.empty();
73}
74
Yifan Hongb44a6c82016-09-22 15:50:18 -070075bool FQName::isValidValueName() const {
76 return mIsIdentifier
77 || (!mName.empty() && !mValueName.empty());
78}
79
Andreas Huber84f89de2016-07-28 15:39:51 -070080bool FQName::setTo(const std::string &s) {
81 mPackage.clear();
82 mVersion.clear();
83 mName.clear();
84
85 mValid = true;
86
87 std::smatch match;
88 if (std::regex_match(s, match, kRE1)) {
89 CHECK_EQ(match.size(), 6u);
90
91 mPackage = match.str(1);
92 mVersion = match.str(3);
93 mName = match.str(4);
94 } else if (std::regex_match(s, match, kRE2)) {
95 CHECK_EQ(match.size(), 4u);
96
97 mVersion = match.str(1);
98 mName = match.str(2);
99 } else if (std::regex_match(s, match, kRE3)) {
Andreas Huberda51b8e2016-07-28 16:00:57 -0700100 CHECK_EQ(match.size(), 4u);
101
102 mPackage = match.str(1);
103 mVersion = match.str(3);
104 } else if (std::regex_match(s, match, kRE4)) {
Andreas Huber84f89de2016-07-28 15:39:51 -0700105 mName = match.str(0);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700106 } else if (std::regex_match(s, match, kRE5)) {
107 mIsIdentifier = true;
108 mName = match.str(0);
109 } else if (std::regex_match(s, match, kRE6)) {
110 CHECK_EQ(match.size(), 7u);
111
112 mPackage = match.str(1);
113 mVersion = match.str(3);
114 mName = match.str(4);
115 mValueName = match.str(6);
116 } else if (std::regex_match(s, match, kRE7)) {
117 CHECK_EQ(match.size(), 5u);
118
119 mVersion = match.str(1);
120 mName = match.str(2);
121 mValueName = match.str(4);
122 } else if (std::regex_match(s, match, kRE8)) {
123 CHECK_EQ(match.size(), 4u);
124
125 mName = match.str(1);
126 mValueName = match.str(3);
Andreas Huber84f89de2016-07-28 15:39:51 -0700127 } else {
128 mValid = false;
129 }
130
Yifan Hongb44a6c82016-09-22 15:50:18 -0700131 // mValueName must go with mName.
132 if (!mValueName.empty()) {
133 CHECK(!mName.empty());
134 }
135
Andreas Huber84f89de2016-07-28 15:39:51 -0700136 return isValid();
137}
138
139std::string FQName::package() const {
140 return mPackage;
141}
142
143std::string FQName::version() const {
144 return mVersion;
145}
146
147std::string FQName::name() const {
148 return mName;
149}
150
Iliyan Malchev800273d2016-09-02 15:25:07 -0700151std::vector<std::string> FQName::names() const {
152 std::vector<std::string> res {};
153 std::istringstream ss(name());
154 std::string s;
155 while (std::getline(ss, s, '.')) {
156 res.push_back(s);
157 }
158 return res;
159}
160
Yifan Hongb44a6c82016-09-22 15:50:18 -0700161std::string FQName::valueName() const {
162 return mValueName;
163}
164
165FQName FQName::typeName() const {
166 return FQName(mPackage, mVersion, mName);
167}
168
Andreas Huber84f89de2016-07-28 15:39:51 -0700169void FQName::applyDefaults(
170 const std::string &defaultPackage,
171 const std::string &defaultVersion) {
172 if (mPackage.empty()) {
173 mPackage = defaultPackage;
174 }
175
176 if (mVersion.empty()) {
177 mVersion = defaultVersion;
178 }
179}
180
Andreas Huber68f24592016-07-29 14:53:48 -0700181std::string FQName::string() const {
Andreas Huber84f89de2016-07-28 15:39:51 -0700182 CHECK(mValid);
183
Andreas Huber5345ec22016-07-29 13:33:27 -0700184 std::string out;
Andreas Huber84f89de2016-07-28 15:39:51 -0700185 out.append(mPackage);
186 out.append(mVersion);
Andreas Huberda51b8e2016-07-28 16:00:57 -0700187 if (!mName.empty()) {
188 if (!mPackage.empty() || !mVersion.empty()) {
189 out.append("::");
190 }
191 out.append(mName);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700192
193 if (!mValueName.empty()) {
194 out.append(":");
195 out.append(mValueName);
196 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700197 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700198
199 return out;
200}
201
Andreas Huberda51b8e2016-07-28 16:00:57 -0700202void FQName::print() const {
203 if (!mValid) {
204 LOG(INFO) << "INVALID";
205 return;
206 }
207
Andreas Huber68f24592016-07-29 14:53:48 -0700208 LOG(INFO) << string();
209}
210
211bool FQName::operator<(const FQName &other) const {
212 return string() < other.string();
Andreas Huberda51b8e2016-07-28 16:00:57 -0700213}
214
Andreas Huberd2943e12016-08-05 11:59:31 -0700215bool FQName::operator==(const FQName &other) const {
216 return string() == other.string();
217}
218
Steven Moreland197d56c2016-09-09 10:03:58 -0700219std::string FQName::getInterfaceBaseName() const {
220 CHECK(names().size() == 1) << "Must be a top level type";
221 CHECK(!mName.empty() && mName[0] == 'I') << mName;
222
223 // cut off the leading 'I'.
224 return mName.substr(1);
225}
226
Steven Moreland9c387612016-09-07 09:54:26 -0700227const FQName FQName::getTopLevelType() const {
228 auto idx = mName.find('.');
229
230 if (idx == std::string::npos) {
231 return *this;
232 }
233
234 return FQName(mPackage, mVersion, mName.substr(0, idx));
235}
236
237std::string FQName::tokenName() const {
238 std::vector<std::string> components;
239 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
240
241 std::vector<std::string> nameComponents;
Steven Morelandaf440142016-09-07 10:09:11 -0700242 StringHelper::SplitString(mName, '.', &nameComponents);
Steven Moreland9c387612016-09-07 09:54:26 -0700243
244 components.insert(components.end(), nameComponents.begin(), nameComponents.end());
245
Steven Morelandaf440142016-09-07 10:09:11 -0700246 return StringHelper::JoinStrings(components, "_");
Steven Moreland9c387612016-09-07 09:54:26 -0700247}
248
Andreas Huber0e00de42016-08-03 09:56:02 -0700249std::string FQName::cppNamespace() const {
250 std::vector<std::string> components;
251 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
252
253 std::string out = "::";
Steven Morelandaf440142016-09-07 10:09:11 -0700254 out += StringHelper::JoinStrings(components, "::");
Andreas Huber0e00de42016-08-03 09:56:02 -0700255
256 return out;
257}
258
Steven Moreland979e0992016-09-07 09:18:08 -0700259std::string FQName::cppLocalName() const {
260 std::vector<std::string> components;
Steven Morelandaf440142016-09-07 10:09:11 -0700261 StringHelper::SplitString(mName, '.', &components);
Steven Moreland979e0992016-09-07 09:18:08 -0700262
Yifan Hongb44a6c82016-09-22 15:50:18 -0700263 return StringHelper::JoinStrings(components, "::")
264 + (mValueName.empty() ? "" : ("::" + mValueName));
Steven Moreland979e0992016-09-07 09:18:08 -0700265}
266
Andreas Huber0e00de42016-08-03 09:56:02 -0700267std::string FQName::cppName() const {
268 std::string out = cppNamespace();
269
270 std::vector<std::string> components;
Steven Morelandaf440142016-09-07 10:09:11 -0700271 StringHelper::SplitString(name(), '.', &components);
Andreas Huber0e00de42016-08-03 09:56:02 -0700272 out += "::";
Steven Morelandaf440142016-09-07 10:09:11 -0700273 out += StringHelper::JoinStrings(components, "::");
Yifan Hongb44a6c82016-09-22 15:50:18 -0700274 if (!mValueName.empty()) {
275 out += "::" + mValueName;
276 }
Andreas Huber0e00de42016-08-03 09:56:02 -0700277
278 return out;
279}
280
Andreas Huber2831d512016-08-15 09:33:47 -0700281std::string FQName::javaPackage() const {
282 std::vector<std::string> components;
283 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
284
Steven Morelandaf440142016-09-07 10:09:11 -0700285 return StringHelper::JoinStrings(components, ".");
Andreas Huber2831d512016-08-15 09:33:47 -0700286}
287
288std::string FQName::javaName() const {
Yifan Hongb44a6c82016-09-22 15:50:18 -0700289 return javaPackage() + "." + name()
290 + (mValueName.empty() ? "" : ("." + mValueName));
Andreas Huber2831d512016-08-15 09:33:47 -0700291}
292
Andreas Huber0e00de42016-08-03 09:56:02 -0700293void FQName::getPackageComponents(std::vector<std::string> *components) const {
Steven Morelandaf440142016-09-07 10:09:11 -0700294 StringHelper::SplitString(package(), '.', components);
Andreas Huber0e00de42016-08-03 09:56:02 -0700295}
296
297void FQName::getPackageAndVersionComponents(
298 std::vector<std::string> *components,
299 bool cpp_compatible) const {
300 getPackageComponents(components);
301
Andreas Huber0e00de42016-08-03 09:56:02 -0700302 if (!cpp_compatible) {
Martijn Coenena21f1492016-09-08 15:55:14 +0200303 components->push_back(getPackageMajorVersion() +
304 "." + getPackageMinorVersion());
Andreas Huber0e00de42016-08-03 09:56:02 -0700305 return;
306 }
307
Andreas Huber0e00de42016-08-03 09:56:02 -0700308 // Form "Vmajor_minor".
309 std::string versionString = "V";
Martijn Coenena21f1492016-09-08 15:55:14 +0200310 versionString.append(getPackageMajorVersion());
Andreas Huber0e00de42016-08-03 09:56:02 -0700311 versionString.append("_");
Martijn Coenena21f1492016-09-08 15:55:14 +0200312 versionString.append(getPackageMinorVersion());
Andreas Huber0e00de42016-08-03 09:56:02 -0700313
314 components->push_back(versionString);
315}
316
Martijn Coenena21f1492016-09-08 15:55:14 +0200317std::string FQName::getPackageMajorVersion() const {
318 const std::string packageVersion = version();
319 CHECK(packageVersion[0] == '@');
320 const size_t dotPos = packageVersion.find('.');
321 CHECK(dotPos != std::string::npos);
322 return packageVersion.substr(1, dotPos - 1);
323}
324
325std::string FQName::getPackageMinorVersion() const {
326 const std::string packageVersion = version();
327 CHECK(packageVersion[0] == '@');
328 const size_t dotPos = packageVersion.find('.');
329 CHECK(dotPos != std::string::npos);
330 return packageVersion.substr(dotPos + 1);
331}
332
Andreas Huber39fa7182016-08-19 14:27:33 -0700333bool FQName::endsWith(const FQName &other) const {
334 std::string s1 = string();
335 std::string s2 = other.string();
336
337 size_t pos = s1.rfind(s2);
338 if (pos == std::string::npos || pos + s2.size() != s1.size()) {
339 return false;
340 }
341
342 if (pos > 0) {
343 // A match is only a match if it is preceded by a "boundary", i.e.
344 // we perform a component-wise match from the end.
345 // "az" is not a match for "android.hardware.foo@1.0::IFoo.bar.baz",
346 // "baz", "bar.baz", "IFoo.bar.baz" are.
347
348 char separator = s1[pos - 1];
349 if (separator != '.' && separator != ':') {
350 return false;
351 }
352 }
353
354 return true;
355}
356
Andreas Huber84f89de2016-07-28 15:39:51 -0700357} // namespace android
358