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
getStringAttributeAtIndex(const ResXMLTree & tree,ssize_t attrIndex,String8 * outError)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 uint16_t* str = tree.getAttributeStringValue(attrIndex, &len);
45 return str ? String8(str, len) : String8();
46 }
47
getIntegerAttributeAtIndex(const ResXMLTree & tree,ssize_t attrIndex,int32_t defValue,String8 * outError)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
indexOfAttribute(const ResXMLTree & tree,uint32_t attrRes)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
getAttribute(const ResXMLTree & tree,const char * ns,const char * attr,String8 * outError)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
getAttribute(const ResXMLTree & tree,uint32_t attrRes,String8 * outError)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
getResolvedAttribute(const ResTable & resTable,const ResXMLTree & tree,uint32_t attrRes,String8 * outError)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 uint16_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
getIntegerAttribute(const ResXMLTree & tree,const char * ns,const char * attr,int32_t defValue,String8 * outError)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
getIntegerAttribute(const ResXMLTree & tree,uint32_t attrRes,int32_t defValue,String8 * outError)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
getResolvedIntegerAttribute(const ResTable & resTable,const ResXMLTree & tree,uint32_t attrRes,int32_t defValue,String8 * outError)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
getResolvedResourceAttribute(const ResTable & resTable,const ResXMLTree & tree,uint32_t attrRes,Res_value * outValue,String8 * outError)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