blob: 641138279be3fc0f7847e8811ba99ac8cc1c7004 [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
Yifan Hongf24fa852016-09-23 11:03:15 -070063FQName::FQName(const FQName& other)
64 : mValid(other.mValid),
65 mIsIdentifier(other.mIsIdentifier),
66 mPackage(other.mPackage),
67 mVersion(other.mVersion),
68 mName(other.mName),
69 mValueName(other.mValueName) {
70}
71
Andreas Huber84f89de2016-07-28 15:39:51 -070072bool FQName::isValid() const {
73 return mValid;
74}
75
Yifan Hongb44a6c82016-09-22 15:50:18 -070076bool FQName::isIdentifier() const {
77 return mIsIdentifier;
78}
79
Andreas Huber68f24592016-07-29 14:53:48 -070080bool FQName::isFullyQualified() const {
81 return !mPackage.empty() && !mVersion.empty() && !mName.empty();
82}
83
Yifan Hongb44a6c82016-09-22 15:50:18 -070084bool FQName::isValidValueName() const {
85 return mIsIdentifier
86 || (!mName.empty() && !mValueName.empty());
87}
88
Andreas Huber84f89de2016-07-28 15:39:51 -070089bool FQName::setTo(const std::string &s) {
90 mPackage.clear();
91 mVersion.clear();
92 mName.clear();
93
94 mValid = true;
95
96 std::smatch match;
97 if (std::regex_match(s, match, kRE1)) {
98 CHECK_EQ(match.size(), 6u);
99
100 mPackage = match.str(1);
101 mVersion = match.str(3);
102 mName = match.str(4);
103 } else if (std::regex_match(s, match, kRE2)) {
104 CHECK_EQ(match.size(), 4u);
105
106 mVersion = match.str(1);
107 mName = match.str(2);
108 } else if (std::regex_match(s, match, kRE3)) {
Andreas Huberda51b8e2016-07-28 16:00:57 -0700109 CHECK_EQ(match.size(), 4u);
110
111 mPackage = match.str(1);
112 mVersion = match.str(3);
113 } else if (std::regex_match(s, match, kRE4)) {
Andreas Huber84f89de2016-07-28 15:39:51 -0700114 mName = match.str(0);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700115 } else if (std::regex_match(s, match, kRE5)) {
116 mIsIdentifier = true;
117 mName = match.str(0);
118 } else if (std::regex_match(s, match, kRE6)) {
119 CHECK_EQ(match.size(), 7u);
120
121 mPackage = match.str(1);
122 mVersion = match.str(3);
123 mName = match.str(4);
124 mValueName = match.str(6);
125 } else if (std::regex_match(s, match, kRE7)) {
126 CHECK_EQ(match.size(), 5u);
127
128 mVersion = match.str(1);
129 mName = match.str(2);
130 mValueName = match.str(4);
131 } else if (std::regex_match(s, match, kRE8)) {
132 CHECK_EQ(match.size(), 4u);
133
134 mName = match.str(1);
135 mValueName = match.str(3);
Andreas Huber84f89de2016-07-28 15:39:51 -0700136 } else {
137 mValid = false;
138 }
139
Yifan Hongb44a6c82016-09-22 15:50:18 -0700140 // mValueName must go with mName.
141 if (!mValueName.empty()) {
142 CHECK(!mName.empty());
143 }
144
Andreas Huber84f89de2016-07-28 15:39:51 -0700145 return isValid();
146}
147
148std::string FQName::package() const {
149 return mPackage;
150}
151
152std::string FQName::version() const {
153 return mVersion;
154}
155
156std::string FQName::name() const {
157 return mName;
158}
159
Iliyan Malchev800273d2016-09-02 15:25:07 -0700160std::vector<std::string> FQName::names() const {
161 std::vector<std::string> res {};
162 std::istringstream ss(name());
163 std::string s;
164 while (std::getline(ss, s, '.')) {
165 res.push_back(s);
166 }
167 return res;
168}
169
Yifan Hongb44a6c82016-09-22 15:50:18 -0700170std::string FQName::valueName() const {
171 return mValueName;
172}
173
174FQName FQName::typeName() const {
175 return FQName(mPackage, mVersion, mName);
176}
177
Andreas Huber84f89de2016-07-28 15:39:51 -0700178void FQName::applyDefaults(
179 const std::string &defaultPackage,
180 const std::string &defaultVersion) {
181 if (mPackage.empty()) {
182 mPackage = defaultPackage;
183 }
184
185 if (mVersion.empty()) {
186 mVersion = defaultVersion;
187 }
188}
189
Andreas Huber68f24592016-07-29 14:53:48 -0700190std::string FQName::string() const {
Andreas Huber84f89de2016-07-28 15:39:51 -0700191 CHECK(mValid);
192
Andreas Huber5345ec22016-07-29 13:33:27 -0700193 std::string out;
Andreas Huber84f89de2016-07-28 15:39:51 -0700194 out.append(mPackage);
195 out.append(mVersion);
Andreas Huberda51b8e2016-07-28 16:00:57 -0700196 if (!mName.empty()) {
197 if (!mPackage.empty() || !mVersion.empty()) {
198 out.append("::");
199 }
200 out.append(mName);
Yifan Hongb44a6c82016-09-22 15:50:18 -0700201
202 if (!mValueName.empty()) {
203 out.append(":");
204 out.append(mValueName);
205 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700206 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700207
208 return out;
209}
210
Andreas Huberda51b8e2016-07-28 16:00:57 -0700211void FQName::print() const {
212 if (!mValid) {
213 LOG(INFO) << "INVALID";
214 return;
215 }
216
Andreas Huber68f24592016-07-29 14:53:48 -0700217 LOG(INFO) << string();
218}
219
220bool FQName::operator<(const FQName &other) const {
221 return string() < other.string();
Andreas Huberda51b8e2016-07-28 16:00:57 -0700222}
223
Andreas Huberd2943e12016-08-05 11:59:31 -0700224bool FQName::operator==(const FQName &other) const {
225 return string() == other.string();
226}
227
Steven Moreland197d56c2016-09-09 10:03:58 -0700228std::string FQName::getInterfaceBaseName() const {
229 CHECK(names().size() == 1) << "Must be a top level type";
230 CHECK(!mName.empty() && mName[0] == 'I') << mName;
231
232 // cut off the leading 'I'.
233 return mName.substr(1);
234}
235
Steven Moreland9c387612016-09-07 09:54:26 -0700236const FQName FQName::getTopLevelType() const {
237 auto idx = mName.find('.');
238
239 if (idx == std::string::npos) {
240 return *this;
241 }
242
243 return FQName(mPackage, mVersion, mName.substr(0, idx));
244}
245
246std::string FQName::tokenName() const {
247 std::vector<std::string> components;
248 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
249
250 std::vector<std::string> nameComponents;
Steven Morelandaf440142016-09-07 10:09:11 -0700251 StringHelper::SplitString(mName, '.', &nameComponents);
Steven Moreland9c387612016-09-07 09:54:26 -0700252
253 components.insert(components.end(), nameComponents.begin(), nameComponents.end());
254
Steven Morelandaf440142016-09-07 10:09:11 -0700255 return StringHelper::JoinStrings(components, "_");
Steven Moreland9c387612016-09-07 09:54:26 -0700256}
257
Andreas Huber0e00de42016-08-03 09:56:02 -0700258std::string FQName::cppNamespace() const {
259 std::vector<std::string> components;
260 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
261
262 std::string out = "::";
Steven Morelandaf440142016-09-07 10:09:11 -0700263 out += StringHelper::JoinStrings(components, "::");
Andreas Huber0e00de42016-08-03 09:56:02 -0700264
265 return out;
266}
267
Steven Moreland979e0992016-09-07 09:18:08 -0700268std::string FQName::cppLocalName() const {
269 std::vector<std::string> components;
Steven Morelandaf440142016-09-07 10:09:11 -0700270 StringHelper::SplitString(mName, '.', &components);
Steven Moreland979e0992016-09-07 09:18:08 -0700271
Yifan Hongb44a6c82016-09-22 15:50:18 -0700272 return StringHelper::JoinStrings(components, "::")
273 + (mValueName.empty() ? "" : ("::" + mValueName));
Steven Moreland979e0992016-09-07 09:18:08 -0700274}
275
Andreas Huber0e00de42016-08-03 09:56:02 -0700276std::string FQName::cppName() const {
277 std::string out = cppNamespace();
278
279 std::vector<std::string> components;
Steven Morelandaf440142016-09-07 10:09:11 -0700280 StringHelper::SplitString(name(), '.', &components);
Andreas Huber0e00de42016-08-03 09:56:02 -0700281 out += "::";
Steven Morelandaf440142016-09-07 10:09:11 -0700282 out += StringHelper::JoinStrings(components, "::");
Yifan Hongb44a6c82016-09-22 15:50:18 -0700283 if (!mValueName.empty()) {
284 out += "::" + mValueName;
285 }
Andreas Huber0e00de42016-08-03 09:56:02 -0700286
287 return out;
288}
289
Andreas Huber2831d512016-08-15 09:33:47 -0700290std::string FQName::javaPackage() const {
291 std::vector<std::string> components;
292 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
293
Steven Morelandaf440142016-09-07 10:09:11 -0700294 return StringHelper::JoinStrings(components, ".");
Andreas Huber2831d512016-08-15 09:33:47 -0700295}
296
297std::string FQName::javaName() const {
Yifan Hongb44a6c82016-09-22 15:50:18 -0700298 return javaPackage() + "." + name()
299 + (mValueName.empty() ? "" : ("." + mValueName));
Andreas Huber2831d512016-08-15 09:33:47 -0700300}
301
Andreas Huber0e00de42016-08-03 09:56:02 -0700302void FQName::getPackageComponents(std::vector<std::string> *components) const {
Steven Morelandaf440142016-09-07 10:09:11 -0700303 StringHelper::SplitString(package(), '.', components);
Andreas Huber0e00de42016-08-03 09:56:02 -0700304}
305
306void FQName::getPackageAndVersionComponents(
307 std::vector<std::string> *components,
308 bool cpp_compatible) const {
309 getPackageComponents(components);
310
Andreas Huber0e00de42016-08-03 09:56:02 -0700311 if (!cpp_compatible) {
Martijn Coenena21f1492016-09-08 15:55:14 +0200312 components->push_back(getPackageMajorVersion() +
313 "." + getPackageMinorVersion());
Andreas Huber0e00de42016-08-03 09:56:02 -0700314 return;
315 }
316
Andreas Huber0e00de42016-08-03 09:56:02 -0700317 // Form "Vmajor_minor".
318 std::string versionString = "V";
Martijn Coenena21f1492016-09-08 15:55:14 +0200319 versionString.append(getPackageMajorVersion());
Andreas Huber0e00de42016-08-03 09:56:02 -0700320 versionString.append("_");
Martijn Coenena21f1492016-09-08 15:55:14 +0200321 versionString.append(getPackageMinorVersion());
Andreas Huber0e00de42016-08-03 09:56:02 -0700322
323 components->push_back(versionString);
324}
325
Martijn Coenena21f1492016-09-08 15:55:14 +0200326std::string FQName::getPackageMajorVersion() const {
327 const std::string packageVersion = version();
328 CHECK(packageVersion[0] == '@');
329 const size_t dotPos = packageVersion.find('.');
330 CHECK(dotPos != std::string::npos);
331 return packageVersion.substr(1, dotPos - 1);
332}
333
334std::string FQName::getPackageMinorVersion() const {
335 const std::string packageVersion = version();
336 CHECK(packageVersion[0] == '@');
337 const size_t dotPos = packageVersion.find('.');
338 CHECK(dotPos != std::string::npos);
339 return packageVersion.substr(dotPos + 1);
340}
341
Andreas Huber39fa7182016-08-19 14:27:33 -0700342bool FQName::endsWith(const FQName &other) const {
343 std::string s1 = string();
344 std::string s2 = other.string();
345
346 size_t pos = s1.rfind(s2);
347 if (pos == std::string::npos || pos + s2.size() != s1.size()) {
348 return false;
349 }
350
351 if (pos > 0) {
352 // A match is only a match if it is preceded by a "boundary", i.e.
353 // we perform a component-wise match from the end.
354 // "az" is not a match for "android.hardware.foo@1.0::IFoo.bar.baz",
355 // "baz", "bar.baz", "IFoo.bar.baz" are.
356
357 char separator = s1[pos - 1];
358 if (separator != '.' && separator != ':') {
359 return false;
360 }
361 }
362
363 return true;
364}
365
Andreas Huber84f89de2016-07-28 15:39:51 -0700366} // namespace android
367