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 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> 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> 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> 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 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> 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 134 bool parseKernelConfigInt(const std::string &s, int64_t *i) { 135 return parseKernelConfigIntHelper(s, i); 136 } 137 138 bool parseKernelConfigInt(const std::string &s, uint64_t *i) { 139 return parseKernelConfigIntHelper(s, i); 140 } 141 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 151 bool parse(const std::string &s, KernelConfigKey *key) { 152 *key = s; 153 return true; 154 } 155 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 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 186 std::ostream &operator<<(std::ostream &os, const Version &ver) { 187 return os << ver.majorVer << "." << ver.minorVer; 188 } 189 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 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 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 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 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 267 std::ostream &operator<<(std::ostream &os, const TransportArch &ta) { 268 return os << to_string(ta.transport) << to_string(ta.arch); 269 } 270 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 297 std::ostream &operator<<(std::ostream &os, const KernelVersion &ver) { 298 return os << ver.version << "." << ver.majorRev << "." << ver.minorRev; 299 } 300 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 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 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 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 353 std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv){ 354 return os << ksv.value; 355 } 356 357 bool parse(const std::string &s, KernelSepolicyVersion *ksv){ 358 return ParseUint(s, &ksv->value); 359 } 360 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 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