AaptXml.cpp revision ad2d07d2d98a46babb2a9472413fe9ce5080ca76
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
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;
44    const uint16_t* str = tree.getAttributeStringValue(attrIndex, &len);
45    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;
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
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
185