blob: 4d7ae9af89f3b503240a727d4ccff43ef048b865 [file] [log] [blame]
Yifan Hong676447a2016-11-15 12:57:23 -08001/*
2 * Copyright (C) 2017 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
17// Convert objects from and to strings.
18
19#include "parse_string.h"
20#include <android-base/parseint.h>
21
22namespace android {
23using base::ParseUint;
24
25namespace vintf {
26
27static const std::string kRequired("required");
28static const std::string kOptional("optional");
29static const std::string kConfigPrefix("CONFIG_");
30
31std::vector<std::string> SplitString(const std::string &s, char c) {
32 std::vector<std::string> components;
33
34 size_t startPos = 0;
35 size_t matchPos;
36 while ((matchPos = s.find(c, startPos)) != std::string::npos) {
37 components.push_back(s.substr(startPos, matchPos - startPos));
38 startPos = matchPos + 1;
39 }
40
41 if (startPos <= s.length()) {
42 components.push_back(s.substr(startPos));
43 }
44 return components;
45}
46
47template <typename T>
48std::ostream &operator<<(std::ostream &os, const std::vector<T> objs) {
49 bool first = true;
50 for (const T &v : objs) {
51 if (!first) {
52 os << ",";
53 }
54 os << v;
55 first = false;
56 }
57 return os;
58}
59
60template <typename T>
61bool parse(const std::string &s, std::vector<T> *objs) {
62 std::vector<std::string> v = SplitString(s, ',');
63 objs->resize(v.size());
64 size_t idx = 0;
65 for (const auto &item : v) {
66 T ver;
67 if (!parse(item, &ver)) {
68 return false;
69 }
70 objs->at(idx++) = ver;
71 }
72 return true;
73}
74
75template<typename E, typename Array>
76bool parseEnum(const std::string &s, E *e, const Array &strings) {
77 for (size_t i = 0; i < strings.size(); ++i) {
78 if (s == strings.at(i)) {
79 *e = static_cast<E>(i);
80 return true;
81 }
82 }
83 return false;
84}
85
Yifan Hongc54d32c2017-03-07 19:12:26 -080086#define DEFINE_PARSE_STREAMIN_FOR_ENUM(ENUM) \
87 bool parse(const std::string &s, ENUM *hf) { \
88 return parseEnum(s, hf, g##ENUM##Strings); \
89 } \
90 std::ostream &operator<<(std::ostream &os, ENUM hf) { \
91 return os << g##ENUM##Strings.at(static_cast<size_t>(hf)); \
92 } \
Yifan Hong676447a2016-11-15 12:57:23 -080093
Yifan Hongc54d32c2017-03-07 19:12:26 -080094DEFINE_PARSE_STREAMIN_FOR_ENUM(HalFormat);
Yifan Hongc54d32c2017-03-07 19:12:26 -080095DEFINE_PARSE_STREAMIN_FOR_ENUM(Transport);
96DEFINE_PARSE_STREAMIN_FOR_ENUM(Arch);
97DEFINE_PARSE_STREAMIN_FOR_ENUM(KernelConfigType);
98DEFINE_PARSE_STREAMIN_FOR_ENUM(Tristate);
Yifan Hong7c7d7062017-04-04 16:26:51 -070099DEFINE_PARSE_STREAMIN_FOR_ENUM(SchemaType);
Yifan Hongd4857902017-06-13 14:13:56 -0700100DEFINE_PARSE_STREAMIN_FOR_ENUM(XmlSchemaFormat);
Yifan Hong3f5489a2017-02-08 11:14:21 -0800101
102std::ostream &operator<<(std::ostream &os, const KernelConfigTypedValue &kctv) {
103 switch (kctv.mType) {
104 case KernelConfigType::STRING:
105 return os << kctv.mStringValue;
106 case KernelConfigType::INTEGER:
107 return os << to_string(kctv.mIntegerValue);
108 case KernelConfigType::RANGE:
109 return os << to_string(kctv.mRangeValue.first) << "-"
110 << to_string(kctv.mRangeValue.second);
111 case KernelConfigType::TRISTATE:
112 return os << to_string(kctv.mTristateValue);
113 }
114}
115
116// Notice that strtoull is used even though KernelConfigIntValue is signed int64_t,
117// because strtoull can accept negative values as well.
118// Notice that according to man strtoul, strtoull can actually accept
119// -2^64 + 1 to 2^64 - 1, with the 65th bit truncated.
120// ParseInt / ParseUint are not used because they do not handle signed hex very well.
121template <typename T>
122bool parseKernelConfigIntHelper(const std::string &s, T *i) {
123 char *end;
124 errno = 0;
125 unsigned long long int ulli = strtoull(s.c_str(), &end, 0 /* base */);
126 // It is implementation defined that what value will be returned by strtoull
127 // in the error case, so we are checking errno directly here.
128 if (errno == 0 && s.c_str() != end && *end == '\0') {
129 *i = static_cast<T>(ulli);
130 return true;
131 }
132 return false;
133}
134
135bool parseKernelConfigInt(const std::string &s, int64_t *i) {
136 return parseKernelConfigIntHelper(s, i);
137}
138
139bool parseKernelConfigInt(const std::string &s, uint64_t *i) {
140 return parseKernelConfigIntHelper(s, i);
141}
142
143bool parseRange(const std::string &s, KernelConfigRangeValue *range) {
144 auto pos = s.find('-');
145 if (pos == std::string::npos) {
146 return false;
147 }
148 return parseKernelConfigInt(s.substr(0, pos), &range->first)
149 && parseKernelConfigInt(s.substr(pos + 1), &range->second);
150}
151
152bool parse(const std::string &s, KernelConfigKey *key) {
153 *key = s;
154 return true;
155}
156
157bool parseKernelConfigValue(const std::string &s, KernelConfigTypedValue *kctv) {
158 switch (kctv->mType) {
159 case KernelConfigType::STRING:
160 kctv->mStringValue = s;
161 return true;
162 case KernelConfigType::INTEGER:
163 return parseKernelConfigInt(s, &kctv->mIntegerValue);
164 case KernelConfigType::RANGE:
165 return parseRange(s, &kctv->mRangeValue);
166 case KernelConfigType::TRISTATE:
167 return parse(s, &kctv->mTristateValue);
168 }
Yifan Hong676447a2016-11-15 12:57:23 -0800169}
170
171bool parse(const std::string &s, Version *ver) {
172 std::vector<std::string> v = SplitString(s, '.');
173 if (v.size() != 2) {
174 return false;
175 }
176 size_t major, minor;
177 if (!ParseUint(v[0], &major)) {
178 return false;
179 }
180 if (!ParseUint(v[1], &minor)) {
181 return false;
182 }
183 *ver = Version(major, minor);
184 return true;
185}
186
187std::ostream &operator<<(std::ostream &os, const Version &ver) {
188 return os << ver.majorVer << "." << ver.minorVer;
189}
190
191bool parse(const std::string &s, VersionRange *vr) {
192 std::vector<std::string> v = SplitString(s, '-');
193 if (v.size() != 1 && v.size() != 2) {
194 return false;
195 }
196 Version minVer;
197 if (!parse(v[0], &minVer)) {
198 return false;
199 }
200 if (v.size() == 1) {
201 *vr = VersionRange(minVer.majorVer, minVer.minorVer);
202 } else {
203 size_t maxMinor;
204 if (!ParseUint(v[1], &maxMinor)) {
205 return false;
206 }
207 *vr = VersionRange(minVer.majorVer, minVer.minorVer, maxMinor);
208 }
209 return true;
210}
211
212std::ostream &operator<<(std::ostream &os, const VersionRange &vr) {
213 if (vr.isSingleVersion()) {
214 return os << vr.minVer();
215 }
216 return os << vr.minVer() << "-" << vr.maxMinor;
217}
218
Yifan Honga04e1472017-04-05 13:15:34 -0700219bool parse(const std::string &s, VndkVersionRange *vr) {
220 std::vector<std::string> v = SplitString(s, '-');
221 if (v.size() != 1 && v.size() != 2) {
222 return false;
223 }
224 std::vector<std::string> minVector = SplitString(v[0], '.');
225 if (minVector.size() != 3) {
226 return false;
227 }
228 if (!ParseUint(minVector[0], &vr->sdk) ||
229 !ParseUint(minVector[1], &vr->vndk) ||
230 !ParseUint(minVector[2], &vr->patchMin)) {
231 return false;
232 }
233 if (v.size() == 1) {
234 vr->patchMax = vr->patchMin;
235 return true;
236 } else {
237 return ParseUint(v[1], &vr->patchMax);
238 }
239}
240
241std::ostream &operator<<(std::ostream &os, const VndkVersionRange &vr) {
242 os << vr.sdk << "." << vr.vndk << "." << vr.patchMin;
243 if (!vr.isSingleVersion()) {
244 os << "-" << vr.patchMax;
245 }
246 return os;
247}
248
Yifan Hong3f5489a2017-02-08 11:14:21 -0800249bool parse(const std::string &s, KernelVersion *kernelVersion) {
250 std::vector<std::string> v = SplitString(s, '.');
251 if (v.size() != 3) {
252 return false;
253 }
254 size_t version, major, minor;
255 if (!ParseUint(v[0], &version)) {
256 return false;
257 }
258 if (!ParseUint(v[1], &major)) {
259 return false;
260 }
261 if (!ParseUint(v[2], &minor)) {
262 return false;
263 }
264 *kernelVersion = KernelVersion(version, major, minor);
265 return true;
266}
267
Yifan Hongc54d32c2017-03-07 19:12:26 -0800268std::ostream &operator<<(std::ostream &os, const TransportArch &ta) {
269 return os << to_string(ta.transport) << to_string(ta.arch);
270}
271
272bool parse(const std::string &s, TransportArch *ta) {
273 bool transportSet = false;
274 bool archSet = false;
275 for (size_t i = 0; i < gTransportStrings.size(); ++i) {
276 if (s.find(gTransportStrings.at(i)) != std::string::npos) {
277 ta->transport = static_cast<Transport>(i);
278 transportSet = true;
279 break;
280 }
281 }
282 if (!transportSet) {
283 return false;
284 }
285 for (size_t i = 0; i < gArchStrings.size(); ++i) {
286 if (s.find(gArchStrings.at(i)) != std::string::npos) {
287 ta->arch = static_cast<Arch>(i);
288 archSet = true;
289 break;
290 }
291 }
292 if (!archSet) {
293 return false;
294 }
295 return ta->isValid();
296}
297
Yifan Hong3f5489a2017-02-08 11:14:21 -0800298std::ostream &operator<<(std::ostream &os, const KernelVersion &ver) {
299 return os << ver.version << "." << ver.majorRev << "." << ver.minorRev;
300}
301
Yifan Hong676447a2016-11-15 12:57:23 -0800302bool parse(const std::string &s, ManifestHal *hal) {
303 std::vector<std::string> v = SplitString(s, '/');
Yifan Hong974ad9c2017-04-04 15:37:39 -0700304 if (v.size() != 4) {
Yifan Hong676447a2016-11-15 12:57:23 -0800305 return false;
306 }
307 if (!parse(v[0], &hal->format)) {
308 return false;
309 }
310 hal->name = v[1];
Yifan Hongc54d32c2017-03-07 19:12:26 -0800311 if (!parse(v[2], &hal->transportArch)) {
Yifan Hong676447a2016-11-15 12:57:23 -0800312 return false;
313 }
Yifan Hong974ad9c2017-04-04 15:37:39 -0700314 if (!parse(v[3], &hal->versions)) {
Yifan Hong676447a2016-11-15 12:57:23 -0800315 return false;
316 }
Yifan Hong5a06ef72017-01-24 19:54:24 -0800317 return hal->isValid();
Yifan Hong676447a2016-11-15 12:57:23 -0800318}
319
320std::ostream &operator<<(std::ostream &os, const ManifestHal &hal) {
321 return os << hal.format << "/"
322 << hal.name << "/"
Yifan Hongc54d32c2017-03-07 19:12:26 -0800323 << hal.transportArch << "/"
Yifan Hong676447a2016-11-15 12:57:23 -0800324 << hal.versions;
325}
326
327bool parse(const std::string &s, MatrixHal *req) {
328 std::vector<std::string> v = SplitString(s, '/');
329 if (v.size() != 4) {
330 return false;
331 }
332 if (!parse(v[0], &req->format)) {
333 return false;
334 }
335 req->name = v[1];
336 if (!parse(v[2], &req->versionRanges)) {
337 return false;
338 }
339 if (v[3] != kRequired || v[3] != kOptional) {
340 return false;
341 }
342 req->optional = (v[3] == kOptional);
343 return true;
344}
345
346std::ostream &operator<<(std::ostream &os, const MatrixHal &req) {
347 return os << req.format << "/"
348 << req.name << "/"
349 << req.versionRanges << "/"
350 << (req.optional ? kOptional : kRequired);
351}
352
Yifan Hong558380a2017-02-09 15:37:32 -0800353
354std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv){
355 return os << ksv.value;
356}
357
358bool parse(const std::string &s, KernelSepolicyVersion *ksv){
359 return ParseUint(s, &ksv->value);
360}
361
Yifan Hongd2b7e642017-02-17 10:15:32 -0800362std::string dump(const HalManifest &vm) {
Yifan Hong676447a2016-11-15 12:57:23 -0800363 std::ostringstream oss;
364 bool first = true;
Yifan Hongef6d4d32017-01-23 14:12:28 -0800365 for (const auto &hal : vm.getHals()) {
Yifan Hong676447a2016-11-15 12:57:23 -0800366 if (!first) {
367 oss << ":";
368 }
369 oss << hal;
370 first = false;
371 }
372 return oss.str();
373}
374
Yifan Honga7201e72017-02-17 10:09:59 -0800375std::string dump(const RuntimeInfo &ki) {
Yifan Hongccf967b2017-01-18 11:04:19 -0800376 std::ostringstream oss;
377
378 oss << "kernel = "
379 << ki.osName() << "/"
380 << ki.nodeName() << "/"
381 << ki.osRelease() << "/"
382 << ki.osVersion() << "/"
383 << ki.hardwareId() << ";"
Yifan Hong881a9e452017-04-27 19:31:13 -0700384 << ki.mBootAvbVersion << "/"
385 << ki.mBootVbmetaAvbVersion << ";"
Yifan Hong3477f042017-05-08 14:02:22 -0700386 << "kernelSepolicyVersion = " << ki.kernelSepolicyVersion()
387 << ";\n\ncpu info:\n"
388 << ki.cpuInfo()
389 << "\n#CONFIG's loaded = " << ki.mKernelConfigs.size() << ";\n";
Yifan Hongf1af7522017-02-16 18:00:55 -0800390 for (const auto &pair : ki.mKernelConfigs) {
Yifan Hongccf967b2017-01-18 11:04:19 -0800391 oss << pair.first << "=" << pair.second << "\n";
392 }
393
394 return oss.str();
395}
396
Yifan Hong676447a2016-11-15 12:57:23 -0800397} // namespace vintf
398} // namespace android