blob: b75d576574daad21f91d3eb0ee7606254c8116c3 [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
86bool parse(const std::string &s, HalFormat *hf) {
87 return parseEnum(s, hf, gHalFormatStrings);
88}
89
90std::ostream &operator<<(std::ostream &os, HalFormat hf) {
91 return os << gHalFormatStrings.at(static_cast<size_t>(hf));
92}
93
94bool parse(const std::string &s, ImplLevel *il) {
95 return parseEnum(s, il, gImplLevelStrings);
96}
97
98std::ostream &operator<<(std::ostream &os, ImplLevel il) {
99 return os << gImplLevelStrings.at(static_cast<size_t>(il));
100}
101
102bool parse(const std::string &s, Transport *tr) {
103 return parseEnum(s, tr, gTransportStrings);
104}
105
Yifan Hong3f5489a2017-02-08 11:14:21 -0800106std::ostream &operator<<(std::ostream &os, Transport tr) {
107 return os << gTransportStrings.at(static_cast<size_t>(tr));
108}
109
110bool parse(const std::string &s, KernelConfigType *kc) {
111 return parseEnum(s, kc, gKernelConfigTypeStrings);
112}
113
114std::ostream &operator<<(std::ostream &os, KernelConfigType kc) {
115 return os << gKernelConfigTypeStrings.at(static_cast<size_t>(kc));
116}
117
118bool parse(const std::string &s, Tristate *kc) {
119 return parseEnum(s, kc, gTristateStrings);
120}
121
122std::ostream &operator<<(std::ostream &os, Tristate kc) {
123 return os << gTristateStrings.at(static_cast<size_t>(kc));
124}
125
126std::ostream &operator<<(std::ostream &os, const KernelConfigTypedValue &kctv) {
127 switch (kctv.mType) {
128 case KernelConfigType::STRING:
129 return os << kctv.mStringValue;
130 case KernelConfigType::INTEGER:
131 return os << to_string(kctv.mIntegerValue);
132 case KernelConfigType::RANGE:
133 return os << to_string(kctv.mRangeValue.first) << "-"
134 << to_string(kctv.mRangeValue.second);
135 case KernelConfigType::TRISTATE:
136 return os << to_string(kctv.mTristateValue);
137 }
138}
139
140// Notice that strtoull is used even though KernelConfigIntValue is signed int64_t,
141// because strtoull can accept negative values as well.
142// Notice that according to man strtoul, strtoull can actually accept
143// -2^64 + 1 to 2^64 - 1, with the 65th bit truncated.
144// ParseInt / ParseUint are not used because they do not handle signed hex very well.
145template <typename T>
146bool parseKernelConfigIntHelper(const std::string &s, T *i) {
147 char *end;
148 errno = 0;
149 unsigned long long int ulli = strtoull(s.c_str(), &end, 0 /* base */);
150 // It is implementation defined that what value will be returned by strtoull
151 // in the error case, so we are checking errno directly here.
152 if (errno == 0 && s.c_str() != end && *end == '\0') {
153 *i = static_cast<T>(ulli);
154 return true;
155 }
156 return false;
157}
158
159bool parseKernelConfigInt(const std::string &s, int64_t *i) {
160 return parseKernelConfigIntHelper(s, i);
161}
162
163bool parseKernelConfigInt(const std::string &s, uint64_t *i) {
164 return parseKernelConfigIntHelper(s, i);
165}
166
167bool parseRange(const std::string &s, KernelConfigRangeValue *range) {
168 auto pos = s.find('-');
169 if (pos == std::string::npos) {
170 return false;
171 }
172 return parseKernelConfigInt(s.substr(0, pos), &range->first)
173 && parseKernelConfigInt(s.substr(pos + 1), &range->second);
174}
175
176bool parse(const std::string &s, KernelConfigKey *key) {
177 *key = s;
178 return true;
179}
180
181bool parseKernelConfigValue(const std::string &s, KernelConfigTypedValue *kctv) {
182 switch (kctv->mType) {
183 case KernelConfigType::STRING:
184 kctv->mStringValue = s;
185 return true;
186 case KernelConfigType::INTEGER:
187 return parseKernelConfigInt(s, &kctv->mIntegerValue);
188 case KernelConfigType::RANGE:
189 return parseRange(s, &kctv->mRangeValue);
190 case KernelConfigType::TRISTATE:
191 return parse(s, &kctv->mTristateValue);
192 }
Yifan Hong676447a2016-11-15 12:57:23 -0800193}
194
195bool parse(const std::string &s, Version *ver) {
196 std::vector<std::string> v = SplitString(s, '.');
197 if (v.size() != 2) {
198 return false;
199 }
200 size_t major, minor;
201 if (!ParseUint(v[0], &major)) {
202 return false;
203 }
204 if (!ParseUint(v[1], &minor)) {
205 return false;
206 }
207 *ver = Version(major, minor);
208 return true;
209}
210
211std::ostream &operator<<(std::ostream &os, const Version &ver) {
212 return os << ver.majorVer << "." << ver.minorVer;
213}
214
215bool parse(const std::string &s, VersionRange *vr) {
216 std::vector<std::string> v = SplitString(s, '-');
217 if (v.size() != 1 && v.size() != 2) {
218 return false;
219 }
220 Version minVer;
221 if (!parse(v[0], &minVer)) {
222 return false;
223 }
224 if (v.size() == 1) {
225 *vr = VersionRange(minVer.majorVer, minVer.minorVer);
226 } else {
227 size_t maxMinor;
228 if (!ParseUint(v[1], &maxMinor)) {
229 return false;
230 }
231 *vr = VersionRange(minVer.majorVer, minVer.minorVer, maxMinor);
232 }
233 return true;
234}
235
236std::ostream &operator<<(std::ostream &os, const VersionRange &vr) {
237 if (vr.isSingleVersion()) {
238 return os << vr.minVer();
239 }
240 return os << vr.minVer() << "-" << vr.maxMinor;
241}
242
Yifan Hong3f5489a2017-02-08 11:14:21 -0800243bool parse(const std::string &s, KernelVersion *kernelVersion) {
244 std::vector<std::string> v = SplitString(s, '.');
245 if (v.size() != 3) {
246 return false;
247 }
248 size_t version, major, minor;
249 if (!ParseUint(v[0], &version)) {
250 return false;
251 }
252 if (!ParseUint(v[1], &major)) {
253 return false;
254 }
255 if (!ParseUint(v[2], &minor)) {
256 return false;
257 }
258 *kernelVersion = KernelVersion(version, major, minor);
259 return true;
260}
261
262std::ostream &operator<<(std::ostream &os, const KernelVersion &ver) {
263 return os << ver.version << "." << ver.majorRev << "." << ver.minorRev;
264}
265
Yifan Hong676447a2016-11-15 12:57:23 -0800266bool parse(const std::string &s, ManifestHal *hal) {
267 std::vector<std::string> v = SplitString(s, '/');
268 if (v.size() != 5) {
269 return false;
270 }
271 if (!parse(v[0], &hal->format)) {
272 return false;
273 }
274 hal->name = v[1];
275 if (!parse(v[2], &hal->transport)) {
276 return false;
277 }
278 if (!parse(v[3], &hal->impl.implLevel)) {
279 return false;
280 }
281 hal->impl.impl = v[4];
282 if (!parse(v[5], &hal->versions)) {
283 return false;
284 }
Yifan Hong5a06ef72017-01-24 19:54:24 -0800285 return hal->isValid();
Yifan Hong676447a2016-11-15 12:57:23 -0800286}
287
288std::ostream &operator<<(std::ostream &os, const ManifestHal &hal) {
289 return os << hal.format << "/"
290 << hal.name << "/"
291 << hal.transport << "/"
292 << hal.impl.implLevel << "/"
293 << hal.impl.impl << "/"
294 << hal.versions;
295}
296
297bool parse(const std::string &s, MatrixHal *req) {
298 std::vector<std::string> v = SplitString(s, '/');
299 if (v.size() != 4) {
300 return false;
301 }
302 if (!parse(v[0], &req->format)) {
303 return false;
304 }
305 req->name = v[1];
306 if (!parse(v[2], &req->versionRanges)) {
307 return false;
308 }
309 if (v[3] != kRequired || v[3] != kOptional) {
310 return false;
311 }
312 req->optional = (v[3] == kOptional);
313 return true;
314}
315
316std::ostream &operator<<(std::ostream &os, const MatrixHal &req) {
317 return os << req.format << "/"
318 << req.name << "/"
319 << req.versionRanges << "/"
320 << (req.optional ? kOptional : kRequired);
321}
322
Yifan Hong558380a2017-02-09 15:37:32 -0800323
324std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv){
325 return os << ksv.value;
326}
327
328bool parse(const std::string &s, KernelSepolicyVersion *ksv){
329 return ParseUint(s, &ksv->value);
330}
331
332std::ostream &operator<<(std::ostream &os, const SepolicyVersion &sv){
333 return os << sv.minVer << "-" << sv.maxVer;
334}
335
336bool parse(const std::string &s, SepolicyVersion *sv){
337 std::vector<std::string> v = SplitString(s, '-');
338 if (v.size() != 2) {
339 return false;
340 }
341 if (!ParseUint(v[0], &sv->minVer)) {
342 return false;
343 }
344 if (!ParseUint(v[1], &sv->maxVer)) {
345 return false;
346 }
347 return true;
348}
349
Yifan Hong676447a2016-11-15 12:57:23 -0800350std::string dump(const VendorManifest &vm) {
351 std::ostringstream oss;
352 bool first = true;
Yifan Hongef6d4d32017-01-23 14:12:28 -0800353 for (const auto &hal : vm.getHals()) {
Yifan Hong676447a2016-11-15 12:57:23 -0800354 if (!first) {
355 oss << ":";
356 }
357 oss << hal;
358 first = false;
359 }
360 return oss.str();
361}
362
Yifan Hongccf967b2017-01-18 11:04:19 -0800363std::string dump(const KernelInfo &ki) {
364 std::ostringstream oss;
365
366 oss << "kernel = "
367 << ki.osName() << "/"
368 << ki.nodeName() << "/"
369 << ki.osRelease() << "/"
370 << ki.osVersion() << "/"
371 << ki.hardwareId() << ";"
372 << "kernelSepolicyVersion = " << ki.kernelSepolicyVersion() << ";"
Yifan Hongf1af7522017-02-16 18:00:55 -0800373 << "#CONFIG's loaded = " << ki.mKernelConfigs.size() << ";\n";
374 for (const auto &pair : ki.mKernelConfigs) {
Yifan Hongccf967b2017-01-18 11:04:19 -0800375 oss << pair.first << "=" << pair.second << "\n";
376 }
377
378 return oss.str();
379}
380
Yifan Hong676447a2016-11-15 12:57:23 -0800381} // namespace vintf
382} // namespace android