blob: 6801a4ec7325901360aaa4be67bcfcdf04658f5b [file] [log] [blame]
Adam Lesinskiad2d07d2014-08-27 16:21:08 -07001/*
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
22using namespace android;
23
24namespace AaptXml {
25
26static 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;
Adam Lesinski4bf58102014-11-03 11:21:19 -080044 const char16_t* str = tree.getAttributeStringValue(attrIndex, &len);
Adam Lesinskiad2d07d2014-08-27 16:21:08 -070045 return str ? String8(str, len) : String8();
46}
47
48static 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
69ssize_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
79String8 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
88String8 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
96String8 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 }
Adam Lesinski3b8e9e22017-08-25 17:29:47 -0700102
Adam Lesinskiad2d07d2014-08-27 16:21:08 -0700103 Res_value value;
Adam Lesinski3b8e9e22017-08-25 17:29:47 -0700104 if (tree.getAttributeValue(idx, &value) == BAD_TYPE) {
105 if (outError != NULL) {
106 *outError = "attribute value is corrupt";
Adam Lesinskiad2d07d2014-08-27 16:21:08 -0700107 }
Adam Lesinski3b8e9e22017-08-25 17:29:47 -0700108 return String8();
Adam Lesinskiad2d07d2014-08-27 16:21:08 -0700109 }
Adam Lesinski3b8e9e22017-08-25 17:29:47 -0700110
111 // Check if the string is inline in the XML.
112 if (value.dataType == Res_value::TYPE_STRING) {
113 size_t len;
114 const char16_t* str = tree.getAttributeStringValue(idx, &len);
115 return str ? String8(str, len) : String8();
116 }
117
118 // Resolve the reference if there is one.
119 ssize_t block = resTable.resolveReference(&value, 0);
120 if (block < 0) {
121 if (outError != NULL) {
122 *outError = "attribute value reference does not exist";
123 }
124 return String8();
125 }
126
127 if (value.dataType != Res_value::TYPE_STRING) {
128 if (outError != NULL) {
129 *outError = "attribute is not a string value";
130 }
131 return String8();
132 }
133
Adam Lesinskiad2d07d2014-08-27 16:21:08 -0700134 size_t len;
Adam Lesinski3b8e9e22017-08-25 17:29:47 -0700135 const char16_t* str = resTable.valueToString(&value, static_cast<size_t>(block), NULL, &len);
Adam Lesinskiad2d07d2014-08-27 16:21:08 -0700136 return str ? String8(str, len) : String8();
137}
138
139int32_t getIntegerAttribute(const ResXMLTree& tree, const char* ns,
140 const char* attr, int32_t defValue, String8* outError) {
141 ssize_t idx = tree.indexOfAttribute(ns, attr);
142 if (idx < 0) {
143 return defValue;
144 }
145 return getIntegerAttributeAtIndex(tree, idx, defValue, outError);
146}
147
148int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, int32_t defValue,
149 String8* outError) {
150 ssize_t idx = indexOfAttribute(tree, attrRes);
151 if (idx < 0) {
152 return defValue;
153 }
154 return getIntegerAttributeAtIndex(tree, idx, defValue, outError);
155}
156
157int32_t getResolvedIntegerAttribute(const ResTable& resTable, const ResXMLTree& tree,
158 uint32_t attrRes, int32_t defValue, String8* outError) {
159 ssize_t idx = indexOfAttribute(tree, attrRes);
160 if (idx < 0) {
161 return defValue;
162 }
163 Res_value value;
164 if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
165 if (value.dataType == Res_value::TYPE_REFERENCE) {
166 resTable.resolveReference(&value, 0);
167 }
168 if (value.dataType < Res_value::TYPE_FIRST_INT
169 || value.dataType > Res_value::TYPE_LAST_INT) {
170 if (outError != NULL) {
171 *outError = "attribute is not an integer value";
172 }
173 return defValue;
174 }
175 }
176 return value.data;
177}
178
179void getResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
180 uint32_t attrRes, Res_value* outValue, String8* outError) {
181 ssize_t idx = indexOfAttribute(tree, attrRes);
182 if (idx < 0) {
183 if (outError != NULL) {
184 *outError = "attribute could not be found";
185 }
186 return;
187 }
188 if (tree.getAttributeValue(idx, outValue) != NO_ERROR) {
189 if (outValue->dataType == Res_value::TYPE_REFERENCE) {
190 resTable.resolveReference(outValue, 0);
191 }
192 // The attribute was found and was resolved if need be.
193 return;
194 }
195 if (outError != NULL) {
196 *outError = "error getting resolved resource attribute";
197 }
198}
199
200} // namespace AaptXml