| /* | |
| * Copyright (C) 2014 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #include "SplitDescription.h" | |
| #include "aapt/AaptConfig.h" | |
| #include "aapt/AaptUtil.h" | |
| #include <utils/String8.h> | |
| #include <utils/Vector.h> | |
| using namespace android; | |
| namespace split { | |
| SplitDescription::SplitDescription() | |
| : abi(abi::Variant_none) { | |
| } | |
| int SplitDescription::compare(const SplitDescription& rhs) const { | |
| int cmp; | |
| cmp = (int)abi - (int)rhs.abi; | |
| if (cmp != 0) return cmp; | |
| return config.compareLogical(rhs.config); | |
| } | |
| bool SplitDescription::isBetterThan(const SplitDescription& o, const SplitDescription& target) const { | |
| if (abi != abi::Variant_none || o.abi != abi::Variant_none) { | |
| abi::Family family = abi::getFamily(abi); | |
| abi::Family oFamily = abi::getFamily(o.abi); | |
| if (family != oFamily) { | |
| return family != abi::Family_none; | |
| } | |
| if (int(target.abi) - int(abi) < int(target.abi) - int(o.abi)) { | |
| return true; | |
| } | |
| } | |
| return config.isBetterThan(o.config, &target.config); | |
| } | |
| bool SplitDescription::match(const SplitDescription& o) const { | |
| if (abi != abi::Variant_none) { | |
| abi::Family family = abi::getFamily(abi); | |
| abi::Family oFamily = abi::getFamily(o.abi); | |
| if (family != oFamily) { | |
| return false; | |
| } | |
| if (int(abi) > int(o.abi)) { | |
| return false; | |
| } | |
| } | |
| return config.match(o.config); | |
| } | |
| String8 SplitDescription::toString() const { | |
| String8 extension; | |
| if (abi != abi::Variant_none) { | |
| if (extension.empty()) { | |
| extension.append(":"); | |
| } else { | |
| extension.append("-"); | |
| } | |
| extension.append(abi::toString(abi)); | |
| } | |
| String8 str(config.toString()); | |
| str.append(extension); | |
| return str; | |
| } | |
| ssize_t parseAbi(const Vector<String8>& parts, const ssize_t index, | |
| SplitDescription* outSplit) { | |
| const ssize_t N = parts.size(); | |
| abi::Variant abi = abi::Variant_none; | |
| ssize_t endIndex = index; | |
| if (parts[endIndex] == "arm64") { | |
| endIndex++; | |
| if (endIndex < N) { | |
| if (parts[endIndex] == "v8a") { | |
| endIndex++; | |
| abi = abi::Variant_arm64_v8a; | |
| } | |
| } | |
| } else if (parts[endIndex] == "armeabi") { | |
| endIndex++; | |
| abi = abi::Variant_armeabi; | |
| if (endIndex < N) { | |
| if (parts[endIndex] == "v7a") { | |
| endIndex++; | |
| abi = abi::Variant_armeabi_v7a; | |
| } | |
| } | |
| } else if (parts[endIndex] == "x86") { | |
| endIndex++; | |
| abi = abi::Variant_x86; | |
| } else if (parts[endIndex] == "x86_64") { | |
| endIndex++; | |
| abi = abi::Variant_x86_64; | |
| } else if (parts[endIndex] == "mips") { | |
| endIndex++; | |
| abi = abi::Variant_mips; | |
| } else if (parts[endIndex] == "mips64") { | |
| endIndex++; | |
| abi = abi::Variant_mips64; | |
| } | |
| if (abi == abi::Variant_none && endIndex != index) { | |
| return -1; | |
| } | |
| if (outSplit != NULL) { | |
| outSplit->abi = abi; | |
| } | |
| return endIndex; | |
| } | |
| bool SplitDescription::parse(const String8& str, SplitDescription* outSplit) { | |
| ssize_t index = str.find(":"); | |
| String8 configStr; | |
| String8 extensionStr; | |
| if (index >= 0) { | |
| configStr = String8(str.c_str(), index); | |
| extensionStr = (str.c_str() + index + 1); | |
| } else { | |
| configStr = str; | |
| } | |
| SplitDescription split; | |
| if (!AaptConfig::parse(configStr, &split.config)) { | |
| return false; | |
| } | |
| Vector<String8> parts = AaptUtil::splitAndLowerCase(extensionStr, '-'); | |
| const ssize_t N = parts.size(); | |
| index = 0; | |
| if (extensionStr.length() == 0) { | |
| goto success; | |
| } | |
| index = parseAbi(parts, index, &split); | |
| if (index < 0) { | |
| return false; | |
| } else { | |
| if (index == N) { | |
| goto success; | |
| } | |
| } | |
| // Unrecognized | |
| return false; | |
| success: | |
| if (outSplit != NULL) { | |
| *outSplit = split; | |
| } | |
| return true; | |
| } | |
| } // namespace split |