blob: 60ef1a8e4d0a4181da97ccf560978ad12f9515ab [file] [log] [blame]
Adam Lesinski6f6ceb72014-11-14 14:48:12 -08001/*
2 * Copyright (C) 2015 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 "Resource.h"
18#include "ResourceTypeExtensions.h"
19#include "ResourceValues.h"
20#include "Util.h"
21
22#include <androidfw/ResourceTypes.h>
23#include <limits>
24
25namespace aapt {
26
27bool Value::isItem() const {
28 return false;
29}
30
31bool Value::isWeak() const {
32 return false;
33}
34
35bool Item::isItem() const {
36 return true;
37}
38
39RawString::RawString(const StringPool::Ref& ref) : value(ref) {
40}
41
42RawString* RawString::clone() const {
43 return new RawString(value);
44}
45
46bool RawString::flatten(android::Res_value& outValue) const {
47 outValue.dataType = ExtendedTypes::TYPE_RAW_STRING;
48 outValue.data = static_cast<uint32_t>(value.getIndex());
49 return true;
50}
51
52void RawString::print(std::ostream& out) const {
53 out << "(raw string) " << *value;
54}
55
56Reference::Reference() : referenceType(Reference::Type::kResource) {
57}
58
59Reference::Reference(const ResourceNameRef& n, Type t) :
60 name(n.toResourceName()), referenceType(t) {
61}
62
63Reference::Reference(const ResourceId& i, Type type) : id(i), referenceType(type) {
64}
65
66bool Reference::flatten(android::Res_value& outValue) const {
67 outValue.dataType = (referenceType == Reference::Type::kResource)
68 ? android::Res_value::TYPE_REFERENCE
69 : android::Res_value::TYPE_ATTRIBUTE;
70 outValue.data = id.id;
71 return true;
72}
73
74Reference* Reference::clone() const {
75 Reference* ref = new Reference();
76 ref->referenceType = referenceType;
77 ref->name = name;
78 ref->id = id;
79 return ref;
80}
81
82void Reference::print(std::ostream& out) const {
83 out << "(reference) ";
84 if (referenceType == Reference::Type::kResource) {
85 out << "@";
86 } else {
87 out << "?";
88 }
89
90 if (name.isValid()) {
91 out << name;
92 }
93
94 if (id.isValid() || Res_INTERNALID(id.id)) {
95 out << " " << id;
96 }
97}
98
99bool Id::isWeak() const {
100 return true;
101}
102
103bool Id::flatten(android::Res_value& out) const {
104 out.dataType = android::Res_value::TYPE_NULL;
105 out.data = android::Res_value::DATA_NULL_UNDEFINED;
106 return true;
107}
108
109Id* Id::clone() const {
110 return new Id();
111}
112
113void Id::print(std::ostream& out) const {
114 out << "(id)";
115}
116
117String::String(const StringPool::Ref& ref) : value(ref) {
118}
119
120bool String::flatten(android::Res_value& outValue) const {
121 // Verify that our StringPool index is within encodeable limits.
122 if (value.getIndex() > std::numeric_limits<uint32_t>::max()) {
123 return false;
124 }
125
126 outValue.dataType = android::Res_value::TYPE_STRING;
127 outValue.data = static_cast<uint32_t>(value.getIndex());
128 return true;
129}
130
131String* String::clone() const {
132 return new String(value);
133}
134
135void String::print(std::ostream& out) const {
136 out << "(string) \"" << *value << "\"";
137}
138
139StyledString::StyledString(const StringPool::StyleRef& ref) : value(ref) {
140}
141
142bool StyledString::flatten(android::Res_value& outValue) const {
143 if (value.getIndex() > std::numeric_limits<uint32_t>::max()) {
144 return false;
145 }
146
147 outValue.dataType = android::Res_value::TYPE_STRING;
148 outValue.data = static_cast<uint32_t>(value.getIndex());
149 return true;
150}
151
152StyledString* StyledString::clone() const {
153 return new StyledString(value);
154}
155
156void StyledString::print(std::ostream& out) const {
157 out << "(styled string) \"" << *value->str << "\"";
158}
159
160FileReference::FileReference(const StringPool::Ref& _path) : path(_path) {
161}
162
163bool FileReference::flatten(android::Res_value& outValue) const {
164 if (path.getIndex() > std::numeric_limits<uint32_t>::max()) {
165 return false;
166 }
167
168 outValue.dataType = android::Res_value::TYPE_STRING;
169 outValue.data = static_cast<uint32_t>(path.getIndex());
170 return true;
171}
172
173FileReference* FileReference::clone() const {
174 return new FileReference(path);
175}
176
177void FileReference::print(std::ostream& out) const {
178 out << "(file) " << *path;
179}
180
181BinaryPrimitive::BinaryPrimitive(const android::Res_value& val) : value(val) {
182}
183
184bool BinaryPrimitive::flatten(android::Res_value& outValue) const {
185 outValue = value;
186 return true;
187}
188
189BinaryPrimitive* BinaryPrimitive::clone() const {
190 return new BinaryPrimitive(value);
191}
192
193void BinaryPrimitive::print(std::ostream& out) const {
194 switch (value.dataType) {
195 case android::Res_value::TYPE_NULL:
196 out << "(null)";
197 break;
198 case android::Res_value::TYPE_INT_DEC:
199 out << "(integer) " << value.data;
200 break;
201 case android::Res_value::TYPE_INT_HEX:
202 out << "(integer) " << std::hex << value.data << std::dec;
203 break;
204 case android::Res_value::TYPE_INT_BOOLEAN:
205 out << "(boolean) " << (value.data != 0 ? "true" : "false");
206 break;
207 case android::Res_value::TYPE_INT_COLOR_ARGB8:
208 case android::Res_value::TYPE_INT_COLOR_RGB8:
209 case android::Res_value::TYPE_INT_COLOR_ARGB4:
210 case android::Res_value::TYPE_INT_COLOR_RGB4:
211 out << "(color) #" << std::hex << value.data << std::dec;
212 break;
213 default:
214 out << "(unknown 0x" << std::hex << (int) value.dataType << ") 0x"
215 << std::hex << value.data << std::dec;
216 break;
217 }
218}
219
220bool Sentinel::isWeak() const {
221 return true;
222}
223
224bool Sentinel::flatten(android::Res_value& outValue) const {
225 outValue.dataType = ExtendedTypes::TYPE_SENTINEL;
226 outValue.data = 0;
227 return true;
228}
229
230Sentinel* Sentinel::clone() const {
231 return new Sentinel();
232}
233
234void Sentinel::print(std::ostream& out) const {
235 out << "(sentinel)";
236 return;
237}
238
239Attribute::Attribute(bool w, uint32_t t) : weak(w), typeMask(t) {
240}
241
242bool Attribute::isWeak() const {
243 return weak;
244}
245
246Attribute* Attribute::clone() const {
247 Attribute* attr = new Attribute(weak);
248 attr->typeMask = typeMask;
249 std::copy(symbols.begin(), symbols.end(), std::back_inserter(attr->symbols));
250 return attr;
251}
252
253void Attribute::print(std::ostream& out) const {
254 out << "(attr)";
255 if (typeMask == android::ResTable_map::TYPE_ANY) {
256 out << " any";
257 return;
258 }
259
260 bool set = false;
261 if ((typeMask & android::ResTable_map::TYPE_REFERENCE) != 0) {
262 if (!set) {
263 out << " ";
264 set = true;
265 } else {
266 out << "|";
267 }
268 out << "reference";
269 }
270
271 if ((typeMask & android::ResTable_map::TYPE_STRING) != 0) {
272 if (!set) {
273 out << " ";
274 set = true;
275 } else {
276 out << "|";
277 }
278 out << "string";
279 }
280
281 if ((typeMask & android::ResTable_map::TYPE_INTEGER) != 0) {
282 if (!set) {
283 out << " ";
284 set = true;
285 } else {
286 out << "|";
287 }
288 out << "integer";
289 }
290
291 if ((typeMask & android::ResTable_map::TYPE_BOOLEAN) != 0) {
292 if (!set) {
293 out << " ";
294 set = true;
295 } else {
296 out << "|";
297 }
298 out << "boolean";
299 }
300
301 if ((typeMask & android::ResTable_map::TYPE_COLOR) != 0) {
302 if (!set) {
303 out << " ";
304 set = true;
305 } else {
306 out << "|";
307 }
308 out << "color";
309 }
310
311 if ((typeMask & android::ResTable_map::TYPE_FLOAT) != 0) {
312 if (!set) {
313 out << " ";
314 set = true;
315 } else {
316 out << "|";
317 }
318 out << "float";
319 }
320
321 if ((typeMask & android::ResTable_map::TYPE_DIMENSION) != 0) {
322 if (!set) {
323 out << " ";
324 set = true;
325 } else {
326 out << "|";
327 }
328 out << "dimension";
329 }
330
331 if ((typeMask & android::ResTable_map::TYPE_FRACTION) != 0) {
332 if (!set) {
333 out << " ";
334 set = true;
335 } else {
336 out << "|";
337 }
338 out << "fraction";
339 }
340
341 if ((typeMask & android::ResTable_map::TYPE_ENUM) != 0) {
342 if (!set) {
343 out << " ";
344 set = true;
345 } else {
346 out << "|";
347 }
348 out << "enum";
349 }
350
351 if ((typeMask & android::ResTable_map::TYPE_FLAGS) != 0) {
352 if (!set) {
353 out << " ";
354 set = true;
355 } else {
356 out << "|";
357 }
358 out << "flags";
359 }
360
361 out << " ["
362 << util::joiner(symbols.begin(), symbols.end(), ", ")
363 << "]";
364
365 if (weak) {
366 out << " [weak]";
367 }
368}
369
370static ::std::ostream& operator<<(::std::ostream& out, const Attribute::Symbol& s) {
371 return out << s.symbol.name.entry << "=" << s.value;
372}
373
374Style* Style::clone() const {
375 Style* style = new Style();
376 style->parent = parent;
377 for (auto& entry : entries) {
378 style->entries.push_back(Entry{
379 entry.key,
380 std::unique_ptr<Item>(entry.value->clone())
381 });
382 }
383 return style;
384}
385
386void Style::print(std::ostream& out) const {
387 out << "(style) ";
388 if (!parent.name.entry.empty()) {
389 out << parent.name;
390 }
391 out << " ["
392 << util::joiner(entries.begin(), entries.end(), ", ")
393 << "]";
394}
395
396static ::std::ostream& operator<<(::std::ostream& out, const Style::Entry& value) {
397 out << value.key.name << " = ";
398 value.value->print(out);
399 return out;
400}
401
402Array* Array::clone() const {
403 Array* array = new Array();
404 for (auto& item : items) {
405 array->items.emplace_back(std::unique_ptr<Item>(item->clone()));
406 }
407 return array;
408}
409
410void Array::print(std::ostream& out) const {
411 out << "(array) ["
412 << util::joiner(items.begin(), items.end(), ", ")
413 << "]";
414}
415
416Plural* Plural::clone() const {
417 Plural* p = new Plural();
418 const size_t count = values.size();
419 for (size_t i = 0; i < count; i++) {
420 if (values[i]) {
421 p->values[i] = std::unique_ptr<Item>(values[i]->clone());
422 }
423 }
424 return p;
425}
426
427void Plural::print(std::ostream& out) const {
428 out << "(plural)";
429}
430
431static ::std::ostream& operator<<(::std::ostream& out, const std::unique_ptr<Item>& item) {
432 return out << *item;
433}
434
435Styleable* Styleable::clone() const {
436 Styleable* styleable = new Styleable();
437 std::copy(entries.begin(), entries.end(), std::back_inserter(styleable->entries));
438 return styleable;
439}
440
441void Styleable::print(std::ostream& out) const {
442 out << "(styleable) " << " ["
443 << util::joiner(entries.begin(), entries.end(), ", ")
444 << "]";
445}
446
447} // namespace aapt