1 /*
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 
22 namespace android {
23 using base::ParseUint;
24 
25 namespace vintf {
26 
27 static const std::string kRequired("required");
28 static const std::string kOptional("optional");
29 static const std::string kConfigPrefix("CONFIG_");
30 
SplitString(const std::string & s,char c)31 std::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 
47 template <typename T>
operator <<(std::ostream & os,const std::vector<T> objs)48 std::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 
60 template <typename T>
parse(const std::string & s,std::vector<T> * objs)61 bool 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 
75 template<typename E, typename Array>
parseEnum(const std::string & s,E * e,const Array & strings)76 bool 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 
86 #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     }                                                              \
93 
94 DEFINE_PARSE_STREAMIN_FOR_ENUM(HalFormat);
95 DEFINE_PARSE_STREAMIN_FOR_ENUM(Transport);
96 DEFINE_PARSE_STREAMIN_FOR_ENUM(Arch);
97 DEFINE_PARSE_STREAMIN_FOR_ENUM(KernelConfigType);
98 DEFINE_PARSE_STREAMIN_FOR_ENUM(Tristate);
99 DEFINE_PARSE_STREAMIN_FOR_ENUM(SchemaType);
100 
operator <<(std::ostream & os,const KernelConfigTypedValue & kctv)101 std::ostream &operator<<(std::ostream &os, const KernelConfigTypedValue &kctv) {
102     switch (kctv.mType) {
103         case KernelConfigType::STRING:
104             return os << kctv.mStringValue;
105         case KernelConfigType::INTEGER:
106             return os << to_string(kctv.mIntegerValue);
107         case KernelConfigType::RANGE:
108             return os << to_string(kctv.mRangeValue.first) << "-"
109                       << to_string(kctv.mRangeValue.second);
110         case KernelConfigType::TRISTATE:
111             return os << to_string(kctv.mTristateValue);
112     }
113 }
114 
115 // Notice that strtoull is used even though KernelConfigIntValue is signed int64_t,
116 // because strtoull can accept negative values as well.
117 // Notice that according to man strtoul, strtoull can actually accept
118 // -2^64 + 1 to 2^64 - 1, with the 65th bit truncated.
119 // ParseInt / ParseUint are not used because they do not handle signed hex very well.
120 template <typename T>
parseKernelConfigIntHelper(const std::string & s,T * i)121 bool parseKernelConfigIntHelper(const std::string &s, T *i) {
122     char *end;
123     errno = 0;
124     unsigned long long int ulli = strtoull(s.c_str(), &end, 0 /* base */);
125     // It is implementation defined that what value will be returned by strtoull
126     // in the error case, so we are checking errno directly here.
127     if (errno == 0 && s.c_str() != end && *end == '\0') {
128         *i = static_cast<T>(ulli);
129         return true;
130     }
131     return false;
132 }
133 
parseKernelConfigInt(const std::string & s,int64_t * i)134 bool parseKernelConfigInt(const std::string &s, int64_t *i) {
135     return parseKernelConfigIntHelper(s, i);
136 }
137 
parseKernelConfigInt(const std::string & s,uint64_t * i)138 bool parseKernelConfigInt(const std::string &s, uint64_t *i) {
139     return parseKernelConfigIntHelper(s, i);
140 }
141 
parseRange(const std::string & s,KernelConfigRangeValue * range)142 bool parseRange(const std::string &s, KernelConfigRangeValue *range) {
143     auto pos = s.find('-');
144     if (pos == std::string::npos) {
145         return false;
146     }
147     return parseKernelConfigInt(s.substr(0, pos),  &range->first)
148         && parseKernelConfigInt(s.substr(pos + 1), &range->second);
149 }
150 
parse(const std::string & s,KernelConfigKey * key)151 bool parse(const std::string &s, KernelConfigKey *key) {
152     *key = s;
153     return true;
154 }
155 
parseKernelConfigValue(const std::string & s,KernelConfigTypedValue * kctv)156 bool parseKernelConfigValue(const std::string &s, KernelConfigTypedValue *kctv) {
157     switch (kctv->mType) {
158         case KernelConfigType::STRING:
159             kctv->mStringValue = s;
160             return true;
161         case KernelConfigType::INTEGER:
162             return parseKernelConfigInt(s, &kctv->mIntegerValue);
163         case KernelConfigType::RANGE:
164             return parseRange(s, &kctv->mRangeValue);
165         case KernelConfigType::TRISTATE:
166             return parse(s, &kctv->mTristateValue);
167     }
168 }
169 
parse(const std::string & s,Version * ver)170 bool parse(const std::string &s, Version *ver) {
171     std::vector<std::string> v = SplitString(s, '.');
172     if (v.size() != 2) {
173         return false;
174     }
175     size_t major, minor;
176     if (!ParseUint(v[0], &major)) {
177         return false;
178     }
179     if (!ParseUint(v[1], &minor)) {
180         return false;
181     }
182     *ver = Version(major, minor);
183     return true;
184 }
185 
operator <<(std::ostream & os,const Version & ver)186 std::ostream &operator<<(std::ostream &os, const Version &ver) {
187     return os << ver.majorVer << "." << ver.minorVer;
188 }
189 
parse(const std::string & s,VersionRange * vr)190 bool parse(const std::string &s, VersionRange *vr) {
191     std::vector<std::string> v = SplitString(s, '-');
192     if (v.size() != 1 && v.size() != 2) {
193         return false;
194     }
195     Version minVer;
196     if (!parse(v[0], &minVer)) {
197         return false;
198     }
199     if (v.size() == 1) {
200         *vr = VersionRange(minVer.majorVer, minVer.minorVer);
201     } else {
202         size_t maxMinor;
203         if (!ParseUint(v[1], &maxMinor)) {
204             return false;
205         }
206         *vr = VersionRange(minVer.majorVer, minVer.minorVer, maxMinor);
207     }
208     return true;
209 }
210 
operator <<(std::ostream & os,const VersionRange & vr)211 std::ostream &operator<<(std::ostream &os, const VersionRange &vr) {
212     if (vr.isSingleVersion()) {
213         return os << vr.minVer();
214     }
215     return os << vr.minVer() << "-" << vr.maxMinor;
216 }
217 
parse(const std::string & s,VndkVersionRange * vr)218 bool parse(const std::string &s, VndkVersionRange *vr) {
219     std::vector<std::string> v = SplitString(s, '-');
220     if (v.size() != 1 && v.size() != 2) {
221         return false;
222     }
223     std::vector<std::string> minVector = SplitString(v[0], '.');
224     if (minVector.size() != 3) {
225         return false;
226     }
227     if (!ParseUint(minVector[0], &vr->sdk) ||
228         !ParseUint(minVector[1], &vr->vndk) ||
229         !ParseUint(minVector[2], &vr->patchMin)) {
230         return false;
231     }
232     if (v.size() == 1) {
233         vr->patchMax = vr->patchMin;
234         return true;
235     } else {
236         return ParseUint(v[1], &vr->patchMax);
237     }
238 }
239 
operator <<(std::ostream & os,const VndkVersionRange & vr)240 std::ostream &operator<<(std::ostream &os, const VndkVersionRange &vr) {
241     os << vr.sdk << "." << vr.vndk << "." << vr.patchMin;
242     if (!vr.isSingleVersion()) {
243         os << "-" << vr.patchMax;
244     }
245     return os;
246 }
247 
parse(const std::string & s,KernelVersion * kernelVersion)248 bool parse(const std::string &s, KernelVersion *kernelVersion) {
249     std::vector<std::string> v = SplitString(s, '.');
250     if (v.size() != 3) {
251         return false;
252     }
253     size_t version, major, minor;
254     if (!ParseUint(v[0], &version)) {
255         return false;
256     }
257     if (!ParseUint(v[1], &major)) {
258         return false;
259     }
260     if (!ParseUint(v[2], &minor)) {
261         return false;
262     }
263     *kernelVersion = KernelVersion(version, major, minor);
264     return true;
265 }
266 
operator <<(std::ostream & os,const TransportArch & ta)267 std::ostream &operator<<(std::ostream &os, const TransportArch &ta) {
268     return os << to_string(ta.transport) << to_string(ta.arch);
269 }
270 
parse(const std::string & s,TransportArch * ta)271 bool parse(const std::string &s, TransportArch *ta) {
272     bool transportSet = false;
273     bool archSet = false;
274     for (size_t i = 0; i < gTransportStrings.size(); ++i) {
275         if (s.find(gTransportStrings.at(i)) != std::string::npos) {
276             ta->transport = static_cast<Transport>(i);
277             transportSet = true;
278             break;
279         }
280     }
281     if (!transportSet) {
282         return false;
283     }
284     for (size_t i = 0; i < gArchStrings.size(); ++i) {
285         if (s.find(gArchStrings.at(i)) != std::string::npos) {
286             ta->arch = static_cast<Arch>(i);
287             archSet = true;
288             break;
289         }
290     }
291     if (!archSet) {
292         return false;
293     }
294     return ta->isValid();
295 }
296 
operator <<(std::ostream & os,const KernelVersion & ver)297 std::ostream &operator<<(std::ostream &os, const KernelVersion &ver) {
298     return os << ver.version << "." << ver.majorRev << "." << ver.minorRev;
299 }
300 
parse(const std::string & s,ManifestHal * hal)301 bool parse(const std::string &s, ManifestHal *hal) {
302     std::vector<std::string> v = SplitString(s, '/');
303     if (v.size() != 4) {
304         return false;
305     }
306     if (!parse(v[0], &hal->format)) {
307         return false;
308     }
309     hal->name = v[1];
310     if (!parse(v[2], &hal->transportArch)) {
311         return false;
312     }
313     if (!parse(v[3], &hal->versions)) {
314         return false;
315     }
316     return hal->isValid();
317 }
318 
operator <<(std::ostream & os,const ManifestHal & hal)319 std::ostream &operator<<(std::ostream &os, const ManifestHal &hal) {
320     return os << hal.format << "/"
321               << hal.name << "/"
322               << hal.transportArch << "/"
323               << hal.versions;
324 }
325 
parse(const std::string & s,MatrixHal * req)326 bool parse(const std::string &s, MatrixHal *req) {
327     std::vector<std::string> v = SplitString(s, '/');
328     if (v.size() != 4) {
329         return false;
330     }
331     if (!parse(v[0], &req->format)) {
332         return false;
333     }
334     req->name = v[1];
335     if (!parse(v[2], &req->versionRanges)) {
336         return false;
337     }
338     if (v[3] != kRequired || v[3] != kOptional) {
339         return false;
340     }
341     req->optional = (v[3] == kOptional);
342     return true;
343 }
344 
operator <<(std::ostream & os,const MatrixHal & req)345 std::ostream &operator<<(std::ostream &os, const MatrixHal &req) {
346     return os << req.format << "/"
347               << req.name << "/"
348               << req.versionRanges << "/"
349               << (req.optional ? kOptional : kRequired);
350 }
351 
352 
operator <<(std::ostream & os,KernelSepolicyVersion ksv)353 std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv){
354     return os << ksv.value;
355 }
356 
parse(const std::string & s,KernelSepolicyVersion * ksv)357 bool parse(const std::string &s, KernelSepolicyVersion *ksv){
358     return ParseUint(s, &ksv->value);
359 }
360 
dump(const HalManifest & vm)361 std::string dump(const HalManifest &vm) {
362     std::ostringstream oss;
363     bool first = true;
364     for (const auto &hal : vm.getHals()) {
365         if (!first) {
366             oss << ":";
367         }
368         oss << hal;
369         first = false;
370     }
371     return oss.str();
372 }
373 
dump(const RuntimeInfo & ki)374 std::string dump(const RuntimeInfo &ki) {
375     std::ostringstream oss;
376 
377     oss << "kernel = "
378         << ki.osName() << "/"
379         << ki.nodeName() << "/"
380         << ki.osRelease() << "/"
381         << ki.osVersion() << "/"
382         << ki.hardwareId() << ";"
383         << ki.mBootAvbVersion << "/"
384         << ki.mBootVbmetaAvbVersion << ";"
385         << "kernelSepolicyVersion = " << ki.kernelSepolicyVersion()
386         << ";\n\ncpu info:\n"
387         << ki.cpuInfo()
388         << "\n#CONFIG's loaded = " << ki.mKernelConfigs.size() << ";\n";
389     for (const auto &pair : ki.mKernelConfigs) {
390         oss << pair.first << "=" << pair.second << "\n";
391     }
392 
393     return oss.str();
394 }
395 
396 } // namespace vintf
397 } // namespace android
398