blob: 45e3ad43fa1bca0a72f5aad3aa5ef9b3d79bb232 [file] [log] [blame]
Andreas Huber84f89de2016-07-28 15:39:51 -07001#include "FQName.h"
2
3#include <android-base/logging.h>
4#include <regex>
5
6#define RE_COMPONENT "[a-zA-Z_][a-zA-Z_0-9]*"
7#define RE_PATH RE_COMPONENT "([.]" RE_COMPONENT ")*"
8#define RE_VERSION "@[0-9]+[.][0-9]+"
9
10static const std::regex kRE1("(" RE_PATH ")(" RE_VERSION ")?::(" RE_PATH ")");
11static const std::regex kRE2("(" RE_VERSION ")::(" RE_PATH ")");
Andreas Huberda51b8e2016-07-28 16:00:57 -070012static const std::regex kRE3("(" RE_PATH ")(" RE_VERSION ")");
13static const std::regex kRE4(RE_PATH);
Andreas Huber84f89de2016-07-28 15:39:51 -070014
15namespace android {
16
Andreas Huberda51b8e2016-07-28 16:00:57 -070017FQName::FQName()
18 : mValid(false) {
19}
20
Andreas Huber84f89de2016-07-28 15:39:51 -070021FQName::FQName(const std::string &s)
22 : mValid(false) {
23 setTo(s);
24}
25
Andreas Huber68f24592016-07-29 14:53:48 -070026FQName::FQName(
27 const std::string &package,
28 const std::string &version,
29 const std::string &name)
30 : mValid(true),
31 mPackage(package),
32 mVersion(version),
33 mName(name) {
34}
35
Andreas Huber84f89de2016-07-28 15:39:51 -070036bool FQName::isValid() const {
37 return mValid;
38}
39
Andreas Huber68f24592016-07-29 14:53:48 -070040bool FQName::isFullyQualified() const {
41 return !mPackage.empty() && !mVersion.empty() && !mName.empty();
42}
43
Andreas Huber84f89de2016-07-28 15:39:51 -070044bool FQName::setTo(const std::string &s) {
45 mPackage.clear();
46 mVersion.clear();
47 mName.clear();
48
49 mValid = true;
50
51 std::smatch match;
52 if (std::regex_match(s, match, kRE1)) {
53 CHECK_EQ(match.size(), 6u);
54
55 mPackage = match.str(1);
56 mVersion = match.str(3);
57 mName = match.str(4);
58 } else if (std::regex_match(s, match, kRE2)) {
59 CHECK_EQ(match.size(), 4u);
60
61 mVersion = match.str(1);
62 mName = match.str(2);
63 } else if (std::regex_match(s, match, kRE3)) {
Andreas Huberda51b8e2016-07-28 16:00:57 -070064 CHECK_EQ(match.size(), 4u);
65
66 mPackage = match.str(1);
67 mVersion = match.str(3);
68 } else if (std::regex_match(s, match, kRE4)) {
Andreas Huber84f89de2016-07-28 15:39:51 -070069 mName = match.str(0);
70 } else {
71 mValid = false;
72 }
73
74 return isValid();
75}
76
77std::string FQName::package() const {
78 return mPackage;
79}
80
81std::string FQName::version() const {
82 return mVersion;
83}
84
85std::string FQName::name() const {
86 return mName;
87}
88
89void FQName::applyDefaults(
90 const std::string &defaultPackage,
91 const std::string &defaultVersion) {
92 if (mPackage.empty()) {
93 mPackage = defaultPackage;
94 }
95
96 if (mVersion.empty()) {
97 mVersion = defaultVersion;
98 }
99}
100
Andreas Huber68f24592016-07-29 14:53:48 -0700101std::string FQName::string() const {
Andreas Huber84f89de2016-07-28 15:39:51 -0700102 CHECK(mValid);
103
Andreas Huber5345ec22016-07-29 13:33:27 -0700104 std::string out;
Andreas Huber84f89de2016-07-28 15:39:51 -0700105 out.append(mPackage);
106 out.append(mVersion);
Andreas Huberda51b8e2016-07-28 16:00:57 -0700107 if (!mName.empty()) {
108 if (!mPackage.empty() || !mVersion.empty()) {
109 out.append("::");
110 }
111 out.append(mName);
Andreas Huber84f89de2016-07-28 15:39:51 -0700112 }
Andreas Huber84f89de2016-07-28 15:39:51 -0700113
114 return out;
115}
116
Andreas Huberda51b8e2016-07-28 16:00:57 -0700117void FQName::print() const {
118 if (!mValid) {
119 LOG(INFO) << "INVALID";
120 return;
121 }
122
Andreas Huber68f24592016-07-29 14:53:48 -0700123 LOG(INFO) << string();
124}
125
126bool FQName::operator<(const FQName &other) const {
127 return string() < other.string();
Andreas Huberda51b8e2016-07-28 16:00:57 -0700128}
129
Andreas Huberd2943e12016-08-05 11:59:31 -0700130bool FQName::operator==(const FQName &other) const {
131 return string() == other.string();
132}
133
Andreas Huber0e00de42016-08-03 09:56:02 -0700134static void SplitString(
135 const std::string &s, char c, std::vector<std::string> *components) {
136 components->clear();
137
138 size_t startPos = 0;
139 size_t matchPos;
140 while ((matchPos = s.find(c, startPos)) != std::string::npos) {
141 components->push_back(s.substr(startPos, matchPos - startPos));
142 startPos = matchPos + 1;
143 }
144
145 if (startPos + 1 < s.length()) {
146 components->push_back(s.substr(startPos));
147 }
148}
149
Andreas Huberd2943e12016-08-05 11:59:31 -0700150// static
151std::string FQName::JoinStrings(
Andreas Huber0e00de42016-08-03 09:56:02 -0700152 const std::vector<std::string> &components,
153 const std::string &separator) {
154 std::string out;
155 bool first = true;
156 for (const auto &component : components) {
157 if (!first) {
158 out += separator;
159 }
160 out += component;
161
162 first = false;
163 }
164
165 return out;
166}
167
168std::string FQName::cppNamespace() const {
169 std::vector<std::string> components;
170 getPackageAndVersionComponents(&components, true /* cpp_compatible */);
171
172 std::string out = "::";
173 out += JoinStrings(components, "::");
174
175 return out;
176}
177
178std::string FQName::cppName() const {
179 std::string out = cppNamespace();
180
181 std::vector<std::string> components;
182 SplitString(name(), '.', &components);
183 out += "::";
184 out += JoinStrings(components, "::");
185
186 return out;
187}
188
189void FQName::getPackageComponents(std::vector<std::string> *components) const {
190 SplitString(package(), '.', components);
191}
192
193void FQName::getPackageAndVersionComponents(
194 std::vector<std::string> *components,
195 bool cpp_compatible) const {
196 getPackageComponents(components);
197
198 const std::string packageVersion = version();
199 CHECK(packageVersion[0] == '@');
200
201 if (!cpp_compatible) {
202 components->push_back(packageVersion.substr(1));
203 return;
204 }
205
206 const size_t dotPos = packageVersion.find('.');
207
208 // Form "Vmajor_minor".
209 std::string versionString = "V";
210 versionString.append(packageVersion.substr(1, dotPos - 1));
211 versionString.append("_");
212 versionString.append(packageVersion.substr(dotPos + 1));
213
214 components->push_back(versionString);
215}
216
Andreas Huber84f89de2016-07-28 15:39:51 -0700217} // namespace android
218