blob: a477cb26893268740a4ebfcd9d45d2e4b4c6ce37 [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 ")");
32static const std::regex kRE4(RE_PATH);
Andreas Huber84f89de2016-07-28 15:39:51 -070033
34namespace android {
35
Andreas Huberda51b8e2016-07-28 16:00:57 -070036FQName::FQName()
37 : mValid(false) {
38}
39
Andreas Huber84f89de2016-07-28 15:39:51 -070040FQName::FQName(const std::string &s)
41 : mValid(false) {
42 setTo(s);
43}
44
Andreas Huber68f24592016-07-29 14:53:48 -070045FQName::FQName(
46 const std::string &package,
47 const std::string &version,
48 const std::string &name)
49 : mValid(true),
50 mPackage(package),
51 mVersion(version),
52 mName(name) {
53}
54
Andreas Huber84f89de2016-07-28 15:39:51 -070055bool FQName::isValid() const {
56 return mValid;
57}
58
Andreas Huber68f24592016-07-29 14:53:48 -070059bool FQName::isFullyQualified() const {
60 return !mPackage.empty() && !mVersion.empty() && !mName.empty();
61}
62
Andreas Huber84f89de2016-07-28 15:39:51 -070063bool FQName::setTo(const std::string &s) {
64 mPackage.clear();
65 mVersion.clear();
66 mName.clear();
67
68 mValid = true;
69
70 std::smatch match;
71 if (std::regex_match(s, match, kRE1)) {
72 CHECK_EQ(match.size(), 6u);
73
74 mPackage = match.str(1);
75 mVersion = match.str(3);
76 mName = match.str(4);
77 } else if (std::regex_match(s, match, kRE2)) {
78 CHECK_EQ(match.size(), 4u);
79
80 mVersion = match.str(1);
81 mName = match.str(2);
82 } else if (std::regex_match(s, match, kRE3)) {
Andreas Huberda51b8e2016-07-28 16:00:57 -070083 CHECK_EQ(match.size(), 4u);
84
85 mPackage = match.str(1);
86 mVersion = match.str(3);
87 } else if (std::regex_match(s, match, kRE4)) {
Andreas Huber84f89de2016-07-28 15:39:51 -070088 mName = match.str(0);
89 } else {
90 mValid = false;
91 }
92
93 return isValid();
94}
95
96std::string FQName::package() const {
97 return mPackage;
98}
99
100std::string FQName::version() const {
101 return mVersion;
102}
103
104std::string FQName::name() const {
105 return mName;
106}
107
Iliyan Malchev800273d2016-09-02 15:25:07 -0700108std::vector<std::string> FQName::names() const {
109 std::vector<std::string> res {};
110 std::istringstream ss(name());
111 std::string s;
112 while (std::getline(ss, s, '.')) {
113 res.push_back(s);
114 }
115 return res;
116}
117
Andreas Huber84f89de2016-07-28 15:39:51 -0700118void FQName::applyDefaults(
119 const std::string &defaultPackage,
120 const std::string &defaultVersion) {
121 if (mPackage.empty()) {
122 mPackage = defaultPackage;
123 }
124
125 if (mVersion.empty()) {
126 mVersion = defaultVersion;
127 }
128}
129
Andreas Huber68f24592016-07-29 14:53:48 -0700130std::string FQName::string() const {
Andreas Huber84f89de2016-07-28 15:39:51 -0700131 CHECK(mValid);
132
Andreas Huber5345ec22016-07-29 13:33:27 -0700133 std::string out;
Andreas Huber84f89de2016-07-28 15:39:51 -0700134 out.append(mPackage);
135 out.append(mVersion);
Andreas Huberda51b8e2016-07-28 16:00:57 -0700136 if (!mName.empty()) {
137 if (!mPackage.empty() || !mVersion.empty()) {
138 out.append("::");
139 }
140 out.append(mName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700141 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700142
143 return out;
144}
145
Andreas Huberda51b8e2016-07-28 16:00:57 -0700146void FQName::print() const {
147 if (!mValid) {
148 LOG(INFO) << "INVALID";
149 return;
150 }
151
Andreas Huber68f24592016-07-29 14:53:48 -0700152 LOG(INFO) << string();
153}
154
155bool FQName::operator<(const FQName &other) const {
156 return string() < other.string();
Andreas Huberda51b8e2016-07-28 16:00:57 -0700157}
158
Andreas Huberd2943e12016-08-05 11:59:31 -0700159bool FQName::operator==(const FQName &other) const {
160 return string() == other.string();
161}
162
Steven Moreland197d56c2016-09-09 10:03:58 -0700163std::string FQName::getInterfaceBaseName() const {
164 CHECK(names().size() == 1) << "Must be a top level type";
165 CHECK(!mName.empty() && mName[0] == 'I') << mName;
166
167 // cut off the leading 'I'.
168 return mName.substr(1);
169}
170
Steven Moreland9c387612016-09-07 09:54:26 -0700171const FQName FQName::getTopLevelType() const {
172 auto idx = mName.find('.');
173
174 if (idx == std::string::npos) {
175 return *this;
176 }
177
178 return FQName(mPackage, mVersion, mName.substr(0, idx));
179}
180
181std::string FQName::tokenName() const {
182 std::vector<std::string> components;
183 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
184
185 std::vector<std::string> nameComponents;
Steven Morelandaf440142016-09-07 10:09:11 -0700186 StringHelper::SplitString(mName, '.', &nameComponents);
Steven Moreland9c387612016-09-07 09:54:26 -0700187
188 components.insert(components.end(), nameComponents.begin(), nameComponents.end());
189
Steven Morelandaf440142016-09-07 10:09:11 -0700190 return StringHelper::JoinStrings(components, "_");
Steven Moreland9c387612016-09-07 09:54:26 -0700191}
192
Andreas Huber0e00de42016-08-03 09:56:02 -0700193std::string FQName::cppNamespace() const {
194 std::vector<std::string> components;
195 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
196
197 std::string out = "::";
Steven Morelandaf440142016-09-07 10:09:11 -0700198 out += StringHelper::JoinStrings(components, "::");
Andreas Huber0e00de42016-08-03 09:56:02 -0700199
200 return out;
201}
202
Steven Moreland979e0992016-09-07 09:18:08 -0700203std::string FQName::cppLocalName() const {
204 std::vector<std::string> components;
Steven Morelandaf440142016-09-07 10:09:11 -0700205 StringHelper::SplitString(mName, '.', &components);
Steven Moreland979e0992016-09-07 09:18:08 -0700206
Steven Morelandaf440142016-09-07 10:09:11 -0700207 return StringHelper::JoinStrings(components, "::");
Steven Moreland979e0992016-09-07 09:18:08 -0700208}
209
Andreas Huber0e00de42016-08-03 09:56:02 -0700210std::string FQName::cppName() const {
211 std::string out = cppNamespace();
212
213 std::vector<std::string> components;
Steven Morelandaf440142016-09-07 10:09:11 -0700214 StringHelper::SplitString(name(), '.', &components);
Andreas Huber0e00de42016-08-03 09:56:02 -0700215 out += "::";
Steven Morelandaf440142016-09-07 10:09:11 -0700216 out += StringHelper::JoinStrings(components, "::");
Andreas Huber0e00de42016-08-03 09:56:02 -0700217
218 return out;
219}
220
Andreas Huber2831d512016-08-15 09:33:47 -0700221std::string FQName::javaPackage() const {
222 std::vector<std::string> components;
223 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
224
Steven Morelandaf440142016-09-07 10:09:11 -0700225 return StringHelper::JoinStrings(components, ".");
Andreas Huber2831d512016-08-15 09:33:47 -0700226}
227
228std::string FQName::javaName() const {
229 return javaPackage() + "." + name();
230}
231
Andreas Huber0e00de42016-08-03 09:56:02 -0700232void FQName::getPackageComponents(std::vector<std::string> *components) const {
Steven Morelandaf440142016-09-07 10:09:11 -0700233 StringHelper::SplitString(package(), '.', components);
Andreas Huber0e00de42016-08-03 09:56:02 -0700234}
235
236void FQName::getPackageAndVersionComponents(
237 std::vector<std::string> *components,
238 bool cpp_compatible) const {
239 getPackageComponents(components);
240
Andreas Huber0e00de42016-08-03 09:56:02 -0700241 if (!cpp_compatible) {
Martijn Coenena21f1492016-09-08 15:55:14 +0200242 components->push_back(getPackageMajorVersion() +
243 "." + getPackageMinorVersion());
Andreas Huber0e00de42016-08-03 09:56:02 -0700244 return;
245 }
246
Andreas Huber0e00de42016-08-03 09:56:02 -0700247 // Form "Vmajor_minor".
248 std::string versionString = "V";
Martijn Coenena21f1492016-09-08 15:55:14 +0200249 versionString.append(getPackageMajorVersion());
Andreas Huber0e00de42016-08-03 09:56:02 -0700250 versionString.append("_");
Martijn Coenena21f1492016-09-08 15:55:14 +0200251 versionString.append(getPackageMinorVersion());
Andreas Huber0e00de42016-08-03 09:56:02 -0700252
253 components->push_back(versionString);
254}
255
Martijn Coenena21f1492016-09-08 15:55:14 +0200256std::string FQName::getPackageMajorVersion() const {
257 const std::string packageVersion = version();
258 CHECK(packageVersion[0] == '@');
259 const size_t dotPos = packageVersion.find('.');
260 CHECK(dotPos != std::string::npos);
261 return packageVersion.substr(1, dotPos - 1);
262}
263
264std::string FQName::getPackageMinorVersion() const {
265 const std::string packageVersion = version();
266 CHECK(packageVersion[0] == '@');
267 const size_t dotPos = packageVersion.find('.');
268 CHECK(dotPos != std::string::npos);
269 return packageVersion.substr(dotPos + 1);
270}
271
Andreas Huber39fa7182016-08-19 14:27:33 -0700272bool FQName::endsWith(const FQName &other) const {
273 std::string s1 = string();
274 std::string s2 = other.string();
275
276 size_t pos = s1.rfind(s2);
277 if (pos == std::string::npos || pos + s2.size() != s1.size()) {
278 return false;
279 }
280
281 if (pos > 0) {
282 // A match is only a match if it is preceded by a "boundary", i.e.
283 // we perform a component-wise match from the end.
284 // "az" is not a match for "android.hardware.foo@1.0::IFoo.bar.baz",
285 // "baz", "bar.baz", "IFoo.bar.baz" are.
286
287 char separator = s1[pos - 1];
288 if (separator != '.' && separator != ':') {
289 return false;
290 }
291 }
292
293 return true;
294}
295
Andreas Huber84f89de2016-07-28 15:39:51 -0700296} // namespace android
297