/* * 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 <androidfw/ResourceTypes.h> #include <utils/String8.h> #include "AaptXml.h" using namespace android; namespace AaptXml { static String8 getStringAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex, String8* outError) { Res_value value; if (tree.getAttributeValue(attrIndex, &value) < 0) { if (outError != NULL) { *outError = "could not find attribute at index"; } return String8(); } if (value.dataType != Res_value::TYPE_STRING) { if (outError != NULL) { *outError = "attribute is not a string value"; } return String8(); } size_t len; const char16_t* str = tree.getAttributeStringValue(attrIndex, &len); return str ? String8(str, len) : String8(); } static int32_t getIntegerAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex, int32_t defValue, String8* outError) { Res_value value; if (tree.getAttributeValue(attrIndex, &value) < 0) { if (outError != NULL) { *outError = "could not find attribute at index"; } return defValue; } if (value.dataType < Res_value::TYPE_FIRST_INT || value.dataType > Res_value::TYPE_LAST_INT) { if (outError != NULL) { *outError = "attribute is not an integer value"; } return defValue; } return value.data; } ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes) { size_t attrCount = tree.getAttributeCount(); for (size_t i = 0; i < attrCount; i++) { if (tree.getAttributeNameResID(i) == attrRes) { return (ssize_t)i; } } return -1; } String8 getAttribute(const ResXMLTree& tree, const char* ns, const char* attr, String8* outError) { ssize_t idx = tree.indexOfAttribute(ns, attr); if (idx < 0) { return String8(); } return getStringAttributeAtIndex(tree, idx, outError); } String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) { ssize_t idx = indexOfAttribute(tree, attrRes); if (idx < 0) { return String8(); } return getStringAttributeAtIndex(tree, idx, outError); } String8 getResolvedAttribute(const ResTable& resTable, const ResXMLTree& tree, uint32_t attrRes, String8* outError) { ssize_t idx = indexOfAttribute(tree, attrRes); if (idx < 0) { return String8(); } Res_value value; if (tree.getAttributeValue(idx, &value) != NO_ERROR) { if (value.dataType == Res_value::TYPE_STRING) { size_t len; const char16_t* str = tree.getAttributeStringValue(idx, &len); return str ? String8(str, len) : String8(); } resTable.resolveReference(&value, 0); if (value.dataType != Res_value::TYPE_STRING) { if (outError != NULL) { *outError = "attribute is not a string value"; } return String8(); } } size_t len; const Res_value* value2 = &value; const char16_t* str = resTable.valueToString(value2, 0, NULL, &len); return str ? String8(str, len) : String8(); } int32_t getIntegerAttribute(const ResXMLTree& tree, const char* ns, const char* attr, int32_t defValue, String8* outError) { ssize_t idx = tree.indexOfAttribute(ns, attr); if (idx < 0) { return defValue; } return getIntegerAttributeAtIndex(tree, idx, defValue, outError); } int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, int32_t defValue, String8* outError) { ssize_t idx = indexOfAttribute(tree, attrRes); if (idx < 0) { return defValue; } return getIntegerAttributeAtIndex(tree, idx, defValue, outError); } int32_t getResolvedIntegerAttribute(const ResTable& resTable, const ResXMLTree& tree, uint32_t attrRes, int32_t defValue, String8* outError) { ssize_t idx = indexOfAttribute(tree, attrRes); if (idx < 0) { return defValue; } Res_value value; if (tree.getAttributeValue(idx, &value) != NO_ERROR) { if (value.dataType == Res_value::TYPE_REFERENCE) { resTable.resolveReference(&value, 0); } if (value.dataType < Res_value::TYPE_FIRST_INT || value.dataType > Res_value::TYPE_LAST_INT) { if (outError != NULL) { *outError = "attribute is not an integer value"; } return defValue; } } return value.data; } void getResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree, uint32_t attrRes, Res_value* outValue, String8* outError) { ssize_t idx = indexOfAttribute(tree, attrRes); if (idx < 0) { if (outError != NULL) { *outError = "attribute could not be found"; } return; } if (tree.getAttributeValue(idx, outValue) != NO_ERROR) { if (outValue->dataType == Res_value::TYPE_REFERENCE) { resTable.resolveReference(outValue, 0); } // The attribute was found and was resolved if need be. return; } if (outError != NULL) { *outError = "error getting resolved resource attribute"; } } } // namespace AaptXml