blob: a6bb4187e778cd346b5c877e7cbfd41df4b5aff2 [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
Yifan Hong8fac3f32017-07-06 14:06:54 -0700171bool parseKernelConfigTypedValue(const std::string& s, KernelConfigTypedValue* kctv) {
172 if (parseKernelConfigInt(s, &kctv->mIntegerValue)) {
173 kctv->mType = KernelConfigType::INTEGER;
174 return true;
175 }
176 if (parse(s, &kctv->mTristateValue)) {
177 kctv->mType = KernelConfigType::TRISTATE;
178 return true;
179 }
180 // Do not test for KernelConfigType::RANGE.
181 kctv->mType = KernelConfigType::STRING;
182 kctv->mStringValue = s;
183 return true;
184}
185
Yifan Hong676447a2016-11-15 12:57:23 -0800186bool parse(const std::string &s, Version *ver) {
187 std::vector<std::string> v = SplitString(s, '.');
188 if (v.size() != 2) {
189 return false;
190 }
191 size_t major, minor;
192 if (!ParseUint(v[0], &major)) {
193 return false;
194 }
195 if (!ParseUint(v[1], &minor)) {
196 return false;
197 }
198 *ver = Version(major, minor);
199 return true;
200}
201
202std::ostream &operator<<(std::ostream &os, const Version &ver) {
203 return os << ver.majorVer << "." << ver.minorVer;
204}
205
206bool parse(const std::string &s, VersionRange *vr) {
207 std::vector<std::string> v = SplitString(s, '-');
208 if (v.size() != 1 && v.size() != 2) {
209 return false;
210 }
211 Version minVer;
212 if (!parse(v[0], &minVer)) {
213 return false;
214 }
215 if (v.size() == 1) {
216 *vr = VersionRange(minVer.majorVer, minVer.minorVer);
217 } else {
218 size_t maxMinor;
219 if (!ParseUint(v[1], &maxMinor)) {
220 return false;
221 }
222 *vr = VersionRange(minVer.majorVer, minVer.minorVer, maxMinor);
223 }
224 return true;
225}
226
227std::ostream &operator<<(std::ostream &os, const VersionRange &vr) {
228 if (vr.isSingleVersion()) {
229 return os << vr.minVer();
230 }
231 return os << vr.minVer() << "-" << vr.maxMinor;
232}
233
Yifan Honga04e1472017-04-05 13:15:34 -0700234bool parse(const std::string &s, VndkVersionRange *vr) {
235 std::vector<std::string> v = SplitString(s, '-');
236 if (v.size() != 1 && v.size() != 2) {
237 return false;
238 }
239 std::vector<std::string> minVector = SplitString(v[0], '.');
240 if (minVector.size() != 3) {
241 return false;
242 }
243 if (!ParseUint(minVector[0], &vr->sdk) ||
244 !ParseUint(minVector[1], &vr->vndk) ||
245 !ParseUint(minVector[2], &vr->patchMin)) {
246 return false;
247 }
248 if (v.size() == 1) {
249 vr->patchMax = vr->patchMin;
250 return true;
251 } else {
252 return ParseUint(v[1], &vr->patchMax);
253 }
254}
255
256std::ostream &operator<<(std::ostream &os, const VndkVersionRange &vr) {
257 os << vr.sdk << "." << vr.vndk << "." << vr.patchMin;
258 if (!vr.isSingleVersion()) {
259 os << "-" << vr.patchMax;
260 }
261 return os;
262}
263
Yifan Hong3f5489a2017-02-08 11:14:21 -0800264bool parse(const std::string &s, KernelVersion *kernelVersion) {
265 std::vector<std::string> v = SplitString(s, '.');
266 if (v.size() != 3) {
267 return false;
268 }
269 size_t version, major, minor;
270 if (!ParseUint(v[0], &version)) {
271 return false;
272 }
273 if (!ParseUint(v[1], &major)) {
274 return false;
275 }
276 if (!ParseUint(v[2], &minor)) {
277 return false;
278 }
279 *kernelVersion = KernelVersion(version, major, minor);
280 return true;
281}
282
Yifan Hongc54d32c2017-03-07 19:12:26 -0800283std::ostream &operator<<(std::ostream &os, const TransportArch &ta) {
284 return os << to_string(ta.transport) << to_string(ta.arch);
285}
286
287bool parse(const std::string &s, TransportArch *ta) {
288 bool transportSet = false;
289 bool archSet = false;
290 for (size_t i = 0; i < gTransportStrings.size(); ++i) {
291 if (s.find(gTransportStrings.at(i)) != std::string::npos) {
292 ta->transport = static_cast<Transport>(i);
293 transportSet = true;
294 break;
295 }
296 }
297 if (!transportSet) {
298 return false;
299 }
300 for (size_t i = 0; i < gArchStrings.size(); ++i) {
301 if (s.find(gArchStrings.at(i)) != std::string::npos) {
302 ta->arch = static_cast<Arch>(i);
303 archSet = true;
304 break;
305 }
306 }
307 if (!archSet) {
308 return false;
309 }
310 return ta->isValid();
311}
312
Yifan Hong3f5489a2017-02-08 11:14:21 -0800313std::ostream &operator<<(std::ostream &os, const KernelVersion &ver) {
314 return os << ver.version << "." << ver.majorRev << "." << ver.minorRev;
315}
316
Yifan Hong676447a2016-11-15 12:57:23 -0800317bool parse(const std::string &s, ManifestHal *hal) {
318 std::vector<std::string> v = SplitString(s, '/');
Yifan Hong974ad9c2017-04-04 15:37:39 -0700319 if (v.size() != 4) {
Yifan Hong676447a2016-11-15 12:57:23 -0800320 return false;
321 }
322 if (!parse(v[0], &hal->format)) {
323 return false;
324 }
325 hal->name = v[1];
Yifan Hongc54d32c2017-03-07 19:12:26 -0800326 if (!parse(v[2], &hal->transportArch)) {
Yifan Hong676447a2016-11-15 12:57:23 -0800327 return false;
328 }
Yifan Hong974ad9c2017-04-04 15:37:39 -0700329 if (!parse(v[3], &hal->versions)) {
Yifan Hong676447a2016-11-15 12:57:23 -0800330 return false;
331 }
Yifan Hong5a06ef72017-01-24 19:54:24 -0800332 return hal->isValid();
Yifan Hong676447a2016-11-15 12:57:23 -0800333}
334
335std::ostream &operator<<(std::ostream &os, const ManifestHal &hal) {
336 return os << hal.format << "/"
337 << hal.name << "/"
Yifan Hongc54d32c2017-03-07 19:12:26 -0800338 << hal.transportArch << "/"
Yifan Hong676447a2016-11-15 12:57:23 -0800339 << hal.versions;
340}
341
342bool parse(const std::string &s, MatrixHal *req) {
343 std::vector<std::string> v = SplitString(s, '/');
344 if (v.size() != 4) {
345 return false;
346 }
347 if (!parse(v[0], &req->format)) {
348 return false;
349 }
350 req->name = v[1];
351 if (!parse(v[2], &req->versionRanges)) {
352 return false;
353 }
354 if (v[3] != kRequired || v[3] != kOptional) {
355 return false;
356 }
357 req->optional = (v[3] == kOptional);
358 return true;
359}
360
361std::ostream &operator<<(std::ostream &os, const MatrixHal &req) {
362 return os << req.format << "/"
363 << req.name << "/"
364 << req.versionRanges << "/"
365 << (req.optional ? kOptional : kRequired);
366}
367
Yifan Hong558380a2017-02-09 15:37:32 -0800368
369std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv){
370 return os << ksv.value;
371}
372
373bool parse(const std::string &s, KernelSepolicyVersion *ksv){
374 return ParseUint(s, &ksv->value);
375}
376
Yifan Hongd2b7e642017-02-17 10:15:32 -0800377std::string dump(const HalManifest &vm) {
Yifan Hong676447a2016-11-15 12:57:23 -0800378 std::ostringstream oss;
379 bool first = true;
Yifan Hongef6d4d32017-01-23 14:12:28 -0800380 for (const auto &hal : vm.getHals()) {
Yifan Hong676447a2016-11-15 12:57:23 -0800381 if (!first) {
382 oss << ":";
383 }
384 oss << hal;
385 first = false;
386 }
387 return oss.str();
388}
389
Yifan Honga7201e72017-02-17 10:09:59 -0800390std::string dump(const RuntimeInfo &ki) {
Yifan Hongccf967b2017-01-18 11:04:19 -0800391 std::ostringstream oss;
392
393 oss << "kernel = "
394 << ki.osName() << "/"
395 << ki.nodeName() << "/"
396 << ki.osRelease() << "/"
397 << ki.osVersion() << "/"
398 << ki.hardwareId() << ";"
Yifan Hong881a9e452017-04-27 19:31:13 -0700399 << ki.mBootAvbVersion << "/"
400 << ki.mBootVbmetaAvbVersion << ";"
Yifan Hong3477f042017-05-08 14:02:22 -0700401 << "kernelSepolicyVersion = " << ki.kernelSepolicyVersion()
402 << ";\n\ncpu info:\n"
403 << ki.cpuInfo()
404 << "\n#CONFIG's loaded = " << ki.mKernelConfigs.size() << ";\n";
Yifan Hongf1af7522017-02-16 18:00:55 -0800405 for (const auto &pair : ki.mKernelConfigs) {
Yifan Hongccf967b2017-01-18 11:04:19 -0800406 oss << pair.first << "=" << pair.second << "\n";
407 }
408
409 return oss.str();
410}
411
Yifan Hong676447a2016-11-15 12:57:23 -0800412} // namespace vintf
413} // namespace android