1 /* 2 * Copyright (C) 2014 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 #include <androidfw/ResourceTypes.h> 18 #include <utils/String8.h> 19 20 #include "AaptXml.h" 21 22 using namespace android; 23 24 namespace AaptXml { 25 26 static String8 getStringAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex, 27 String8* outError) { 28 Res_value value; 29 if (tree.getAttributeValue(attrIndex, &value) < 0) { 30 if (outError != NULL) { 31 *outError = "could not find attribute at index"; 32 } 33 return String8(); 34 } 35 36 if (value.dataType != Res_value::TYPE_STRING) { 37 if (outError != NULL) { 38 *outError = "attribute is not a string value"; 39 } 40 return String8(); 41 } 42 43 size_t len; 44 const char16_t* str = tree.getAttributeStringValue(attrIndex, &len); 45 return str ? String8(str, len) : String8(); 46 } 47 48 static int32_t getIntegerAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex, 49 int32_t defValue, String8* outError) { 50 Res_value value; 51 if (tree.getAttributeValue(attrIndex, &value) < 0) { 52 if (outError != NULL) { 53 *outError = "could not find attribute at index"; 54 } 55 return defValue; 56 } 57 58 if (value.dataType < Res_value::TYPE_FIRST_INT 59 || value.dataType > Res_value::TYPE_LAST_INT) { 60 if (outError != NULL) { 61 *outError = "attribute is not an integer value"; 62 } 63 return defValue; 64 } 65 return value.data; 66 } 67 68 69 ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes) { 70 size_t attrCount = tree.getAttributeCount(); 71 for (size_t i = 0; i < attrCount; i++) { 72 if (tree.getAttributeNameResID(i) == attrRes) { 73 return (ssize_t)i; 74 } 75 } 76 return -1; 77 } 78 79 String8 getAttribute(const ResXMLTree& tree, const char* ns, 80 const char* attr, String8* outError) { 81 ssize_t idx = tree.indexOfAttribute(ns, attr); 82 if (idx < 0) { 83 return String8(); 84 } 85 return getStringAttributeAtIndex(tree, idx, outError); 86 } 87 88 String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) { 89 ssize_t idx = indexOfAttribute(tree, attrRes); 90 if (idx < 0) { 91 return String8(); 92 } 93 return getStringAttributeAtIndex(tree, idx, outError); 94 } 95 96 String8 getResolvedAttribute(const ResTable& resTable, const ResXMLTree& tree, 97 uint32_t attrRes, String8* outError) { 98 ssize_t idx = indexOfAttribute(tree, attrRes); 99 if (idx < 0) { 100 return String8(); 101 } 102 Res_value value; 103 if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 104 if (value.dataType == Res_value::TYPE_STRING) { 105 size_t len; 106 const char16_t* str = tree.getAttributeStringValue(idx, &len); 107 return str ? String8(str, len) : String8(); 108 } 109 resTable.resolveReference(&value, 0); 110 if (value.dataType != Res_value::TYPE_STRING) { 111 if (outError != NULL) { 112 *outError = "attribute is not a string value"; 113 } 114 return String8(); 115 } 116 } 117 size_t len; 118 const Res_value* value2 = &value; 119 const char16_t* str = resTable.valueToString(value2, 0, NULL, &len); 120 return str ? String8(str, len) : String8(); 121 } 122 123 int32_t getIntegerAttribute(const ResXMLTree& tree, const char* ns, 124 const char* attr, int32_t defValue, String8* outError) { 125 ssize_t idx = tree.indexOfAttribute(ns, attr); 126 if (idx < 0) { 127 return defValue; 128 } 129 return getIntegerAttributeAtIndex(tree, idx, defValue, outError); 130 } 131 132 int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, int32_t defValue, 133 String8* outError) { 134 ssize_t idx = indexOfAttribute(tree, attrRes); 135 if (idx < 0) { 136 return defValue; 137 } 138 return getIntegerAttributeAtIndex(tree, idx, defValue, outError); 139 } 140 141 int32_t getResolvedIntegerAttribute(const ResTable& resTable, const ResXMLTree& tree, 142 uint32_t attrRes, int32_t defValue, String8* outError) { 143 ssize_t idx = indexOfAttribute(tree, attrRes); 144 if (idx < 0) { 145 return defValue; 146 } 147 Res_value value; 148 if (tree.getAttributeValue(idx, &value) != NO_ERROR) { 149 if (value.dataType == Res_value::TYPE_REFERENCE) { 150 resTable.resolveReference(&value, 0); 151 } 152 if (value.dataType < Res_value::TYPE_FIRST_INT 153 || value.dataType > Res_value::TYPE_LAST_INT) { 154 if (outError != NULL) { 155 *outError = "attribute is not an integer value"; 156 } 157 return defValue; 158 } 159 } 160 return value.data; 161 } 162 163 void getResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree, 164 uint32_t attrRes, Res_value* outValue, String8* outError) { 165 ssize_t idx = indexOfAttribute(tree, attrRes); 166 if (idx < 0) { 167 if (outError != NULL) { 168 *outError = "attribute could not be found"; 169 } 170 return; 171 } 172 if (tree.getAttributeValue(idx, outValue) != NO_ERROR) { 173 if (outValue->dataType == Res_value::TYPE_REFERENCE) { 174 resTable.resolveReference(outValue, 0); 175 } 176 // The attribute was found and was resolved if need be. 177 return; 178 } 179 if (outError != NULL) { 180 *outError = "error getting resolved resource attribute"; 181 } 182 } 183 184 } // namespace AaptXml 185