Home | History | Annotate | Download | only in libvintf
      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