blob: b04a55d91b9c299d0515f23db01c9d95b1060f02 [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 }
102 Res_value value;
103 if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
104 if (value.dataType == Res_value::TYPE_STRING) {
105 size_t len;
Adam Lesinski4bf58102014-11-03 11:21:19 -0800106 const char16_t* str = tree.getAttributeStringValue(idx, &len);
Adam Lesinskiad2d07d2014-08-27 16:21:08 -0700107 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
123int32_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
132int32_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
141int32_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
163void 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