blob: dd7ff013e524689943d12d01e49177a1cd941a4f [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"
Adam Lesinskia5870652015-11-20 15:32:30 -080018#include "ResourceUtils.h"
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080019#include "ResourceValues.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070020#include "ValueVisitor.h"
Adam Lesinski355f2852016-02-13 20:26:45 -080021#include "io/File.h"
Adam Lesinskie78fd612015-10-22 12:48:43 -070022#include "util/Util.h"
Adam Lesinskie78fd612015-10-22 12:48:43 -070023
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080024#include <androidfw/ResourceTypes.h>
25#include <limits>
26
27namespace aapt {
28
Adam Lesinski1ab598f2015-08-14 14:26:04 -070029template <typename Derived>
30void BaseValue<Derived>::accept(RawValueVisitor* visitor) {
31 visitor->visit(static_cast<Derived*>(this));
32}
33
34template <typename Derived>
35void BaseItem<Derived>::accept(RawValueVisitor* visitor) {
36 visitor->visit(static_cast<Derived*>(this));
37}
38
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080039RawString::RawString(const StringPool::Ref& ref) : value(ref) {
40}
41
Adam Lesinski769de982015-04-10 19:43:55 -070042RawString* RawString::clone(StringPool* newPool) const {
Adam Lesinskib274e352015-11-06 15:14:35 -080043 RawString* rs = new RawString(newPool->makeRef(*value));
44 rs->mComment = mComment;
45 rs->mSource = mSource;
46 return rs;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080047}
48
Adam Lesinski1ab598f2015-08-14 14:26:04 -070049bool RawString::flatten(android::Res_value* outValue) const {
Adam Lesinski59e04c62016-02-04 15:59:23 -080050 outValue->dataType = android::Res_value::TYPE_STRING;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070051 outValue->data = util::hostToDevice32(static_cast<uint32_t>(value.getIndex()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080052 return true;
53}
54
Adam Lesinski1ab598f2015-08-14 14:26:04 -070055void RawString::print(std::ostream* out) const {
56 *out << "(raw string) " << *value;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080057}
58
59Reference::Reference() : referenceType(Reference::Type::kResource) {
60}
61
62Reference::Reference(const ResourceNameRef& n, Type t) :
63 name(n.toResourceName()), referenceType(t) {
64}
65
66Reference::Reference(const ResourceId& i, Type type) : id(i), referenceType(type) {
67}
68
Adam Lesinski1ab598f2015-08-14 14:26:04 -070069bool Reference::flatten(android::Res_value* outValue) const {
Adam Lesinski467f1712015-11-16 17:35:44 -080070 outValue->dataType = (referenceType == Reference::Type::kResource) ?
71 android::Res_value::TYPE_REFERENCE : android::Res_value::TYPE_ATTRIBUTE;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070072 outValue->data = util::hostToDevice32(id ? id.value().id : 0);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080073 return true;
74}
75
Adam Lesinski769de982015-04-10 19:43:55 -070076Reference* Reference::clone(StringPool* /*newPool*/) const {
Adam Lesinski467f1712015-11-16 17:35:44 -080077 return new Reference(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080078}
79
Adam Lesinski1ab598f2015-08-14 14:26:04 -070080void Reference::print(std::ostream* out) const {
81 *out << "(reference) ";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080082 if (referenceType == Reference::Type::kResource) {
Adam Lesinski1ab598f2015-08-14 14:26:04 -070083 *out << "@";
Adam Lesinski467f1712015-11-16 17:35:44 -080084 if (privateReference) {
85 *out << "*";
86 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080087 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -070088 *out << "?";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080089 }
90
Adam Lesinski1ab598f2015-08-14 14:26:04 -070091 if (name) {
92 *out << name.value();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080093 }
94
Adam Lesinski1ab598f2015-08-14 14:26:04 -070095 if (id && !Res_INTERNALID(id.value().id)) {
96 *out << " " << id.value();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080097 }
98}
99
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700100bool Id::flatten(android::Res_value* out) const {
101 out->dataType = android::Res_value::TYPE_INT_BOOLEAN;
102 out->data = util::hostToDevice32(0);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800103 return true;
104}
105
Adam Lesinski769de982015-04-10 19:43:55 -0700106Id* Id::clone(StringPool* /*newPool*/) const {
Adam Lesinski467f1712015-11-16 17:35:44 -0800107 return new Id(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800108}
109
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700110void Id::print(std::ostream* out) const {
111 *out << "(id)";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800112}
113
Adam Lesinski393b5f02015-12-17 13:03:11 -0800114String::String(const StringPool::Ref& ref) : value(ref), mTranslateable(true) {
115}
116
117void String::setTranslateable(bool val) {
118 mTranslateable = val;
119}
120
121bool String::isTranslateable() const {
122 return mTranslateable;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800123}
124
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700125bool String::flatten(android::Res_value* outValue) const {
126 // Verify that our StringPool index is within encode-able limits.
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800127 if (value.getIndex() > std::numeric_limits<uint32_t>::max()) {
128 return false;
129 }
130
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700131 outValue->dataType = android::Res_value::TYPE_STRING;
132 outValue->data = util::hostToDevice32(static_cast<uint32_t>(value.getIndex()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800133 return true;
134}
135
Adam Lesinski769de982015-04-10 19:43:55 -0700136String* String::clone(StringPool* newPool) const {
Adam Lesinskib274e352015-11-06 15:14:35 -0800137 String* str = new String(newPool->makeRef(*value));
138 str->mComment = mComment;
139 str->mSource = mSource;
140 return str;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800141}
142
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700143void String::print(std::ostream* out) const {
144 *out << "(string) \"" << *value << "\"";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800145}
146
Adam Lesinski393b5f02015-12-17 13:03:11 -0800147StyledString::StyledString(const StringPool::StyleRef& ref) : value(ref), mTranslateable(true) {
148}
149
150void StyledString::setTranslateable(bool val) {
151 mTranslateable = val;
152}
153
154bool StyledString::isTranslateable() const {
155 return mTranslateable;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800156}
157
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700158bool StyledString::flatten(android::Res_value* outValue) const {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800159 if (value.getIndex() > std::numeric_limits<uint32_t>::max()) {
160 return false;
161 }
162
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700163 outValue->dataType = android::Res_value::TYPE_STRING;
164 outValue->data = util::hostToDevice32(static_cast<uint32_t>(value.getIndex()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800165 return true;
166}
167
Adam Lesinski769de982015-04-10 19:43:55 -0700168StyledString* StyledString::clone(StringPool* newPool) const {
Adam Lesinskib274e352015-11-06 15:14:35 -0800169 StyledString* str = new StyledString(newPool->makeRef(value));
170 str->mComment = mComment;
171 str->mSource = mSource;
172 return str;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800173}
174
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700175void StyledString::print(std::ostream* out) const {
176 *out << "(styled string) \"" << *value->str << "\"";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800177}
178
179FileReference::FileReference(const StringPool::Ref& _path) : path(_path) {
180}
181
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700182bool FileReference::flatten(android::Res_value* outValue) const {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800183 if (path.getIndex() > std::numeric_limits<uint32_t>::max()) {
184 return false;
185 }
186
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700187 outValue->dataType = android::Res_value::TYPE_STRING;
188 outValue->data = util::hostToDevice32(static_cast<uint32_t>(path.getIndex()));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800189 return true;
190}
191
Adam Lesinski769de982015-04-10 19:43:55 -0700192FileReference* FileReference::clone(StringPool* newPool) const {
Adam Lesinskib274e352015-11-06 15:14:35 -0800193 FileReference* fr = new FileReference(newPool->makeRef(*path));
Adam Lesinski355f2852016-02-13 20:26:45 -0800194 fr->file = file;
Adam Lesinskib274e352015-11-06 15:14:35 -0800195 fr->mComment = mComment;
196 fr->mSource = mSource;
197 return fr;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800198}
199
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700200void FileReference::print(std::ostream* out) const {
201 *out << "(file) " << *path;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800202}
203
204BinaryPrimitive::BinaryPrimitive(const android::Res_value& val) : value(val) {
205}
206
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700207BinaryPrimitive::BinaryPrimitive(uint8_t dataType, uint32_t data) {
208 value.dataType = dataType;
209 value.data = data;
210}
211
212bool BinaryPrimitive::flatten(android::Res_value* outValue) const {
213 outValue->dataType = value.dataType;
214 outValue->data = util::hostToDevice32(value.data);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800215 return true;
216}
217
Adam Lesinski769de982015-04-10 19:43:55 -0700218BinaryPrimitive* BinaryPrimitive::clone(StringPool* /*newPool*/) const {
Adam Lesinski467f1712015-11-16 17:35:44 -0800219 return new BinaryPrimitive(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800220}
221
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700222void BinaryPrimitive::print(std::ostream* out) const {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800223 switch (value.dataType) {
224 case android::Res_value::TYPE_NULL:
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700225 *out << "(null)";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800226 break;
227 case android::Res_value::TYPE_INT_DEC:
Adam Lesinskia5870652015-11-20 15:32:30 -0800228 *out << "(integer) " << static_cast<int32_t>(value.data);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800229 break;
230 case android::Res_value::TYPE_INT_HEX:
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700231 *out << "(integer) " << std::hex << value.data << std::dec;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800232 break;
233 case android::Res_value::TYPE_INT_BOOLEAN:
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700234 *out << "(boolean) " << (value.data != 0 ? "true" : "false");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800235 break;
236 case android::Res_value::TYPE_INT_COLOR_ARGB8:
237 case android::Res_value::TYPE_INT_COLOR_RGB8:
238 case android::Res_value::TYPE_INT_COLOR_ARGB4:
239 case android::Res_value::TYPE_INT_COLOR_RGB4:
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700240 *out << "(color) #" << std::hex << value.data << std::dec;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800241 break;
242 default:
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700243 *out << "(unknown 0x" << std::hex << (int) value.dataType << ") 0x"
244 << std::hex << value.data << std::dec;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800245 break;
246 }
247}
248
Adam Lesinskia5870652015-11-20 15:32:30 -0800249Attribute::Attribute(bool w, uint32_t t) :
Adam Lesinski393b5f02015-12-17 13:03:11 -0800250 typeMask(t),
Adam Lesinskia5870652015-11-20 15:32:30 -0800251 minInt(std::numeric_limits<int32_t>::min()),
252 maxInt(std::numeric_limits<int32_t>::max()) {
Adam Lesinski393b5f02015-12-17 13:03:11 -0800253 mWeak = w;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800254}
255
Adam Lesinski769de982015-04-10 19:43:55 -0700256Attribute* Attribute::clone(StringPool* /*newPool*/) const {
Adam Lesinski467f1712015-11-16 17:35:44 -0800257 return new Attribute(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800258}
259
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700260void Attribute::printMask(std::ostream* out) const {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800261 if (typeMask == android::ResTable_map::TYPE_ANY) {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700262 *out << "any";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800263 return;
264 }
265
266 bool set = false;
267 if ((typeMask & android::ResTable_map::TYPE_REFERENCE) != 0) {
268 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800269 set = true;
270 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700271 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800272 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700273 *out << "reference";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800274 }
275
276 if ((typeMask & android::ResTable_map::TYPE_STRING) != 0) {
277 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800278 set = true;
279 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700280 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800281 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700282 *out << "string";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800283 }
284
285 if ((typeMask & android::ResTable_map::TYPE_INTEGER) != 0) {
286 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800287 set = true;
288 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700289 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800290 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700291 *out << "integer";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800292 }
293
294 if ((typeMask & android::ResTable_map::TYPE_BOOLEAN) != 0) {
295 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800296 set = true;
297 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700298 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800299 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700300 *out << "boolean";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800301 }
302
303 if ((typeMask & android::ResTable_map::TYPE_COLOR) != 0) {
304 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800305 set = true;
306 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700307 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800308 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700309 *out << "color";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800310 }
311
312 if ((typeMask & android::ResTable_map::TYPE_FLOAT) != 0) {
313 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800314 set = true;
315 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700316 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800317 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700318 *out << "float";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800319 }
320
321 if ((typeMask & android::ResTable_map::TYPE_DIMENSION) != 0) {
322 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800323 set = true;
324 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700325 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800326 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700327 *out << "dimension";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800328 }
329
330 if ((typeMask & android::ResTable_map::TYPE_FRACTION) != 0) {
331 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800332 set = true;
333 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700334 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800335 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700336 *out << "fraction";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800337 }
338
339 if ((typeMask & android::ResTable_map::TYPE_ENUM) != 0) {
340 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800341 set = true;
342 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700343 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800344 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700345 *out << "enum";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800346 }
347
348 if ((typeMask & android::ResTable_map::TYPE_FLAGS) != 0) {
349 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800350 set = true;
351 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700352 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800353 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700354 *out << "flags";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800355 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700356}
357
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700358void Attribute::print(std::ostream* out) const {
359 *out << "(attr) ";
Adam Lesinski330edcd2015-05-04 17:40:56 -0700360 printMask(out);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800361
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700362 if (!symbols.empty()) {
363 *out << " ["
364 << util::joiner(symbols.begin(), symbols.end(), ", ")
365 << "]";
366 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800367
Adam Lesinski393b5f02015-12-17 13:03:11 -0800368 if (isWeak()) {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700369 *out << " [weak]";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800370 }
371}
372
Adam Lesinskia5870652015-11-20 15:32:30 -0800373static void buildAttributeMismatchMessage(DiagMessage* msg, const Attribute* attr,
374 const Item* value) {
375 *msg << "expected";
376 if (attr->typeMask & android::ResTable_map::TYPE_BOOLEAN) {
377 *msg << " boolean";
378 }
379
380 if (attr->typeMask & android::ResTable_map::TYPE_COLOR) {
381 *msg << " color";
382 }
383
384 if (attr->typeMask & android::ResTable_map::TYPE_DIMENSION) {
385 *msg << " dimension";
386 }
387
388 if (attr->typeMask & android::ResTable_map::TYPE_ENUM) {
389 *msg << " enum";
390 }
391
392 if (attr->typeMask & android::ResTable_map::TYPE_FLAGS) {
393 *msg << " flags";
394 }
395
396 if (attr->typeMask & android::ResTable_map::TYPE_FLOAT) {
397 *msg << " float";
398 }
399
400 if (attr->typeMask & android::ResTable_map::TYPE_FRACTION) {
401 *msg << " fraction";
402 }
403
404 if (attr->typeMask & android::ResTable_map::TYPE_INTEGER) {
405 *msg << " integer";
406 }
407
408 if (attr->typeMask & android::ResTable_map::TYPE_REFERENCE) {
409 *msg << " reference";
410 }
411
412 if (attr->typeMask & android::ResTable_map::TYPE_STRING) {
413 *msg << " string";
414 }
415
416 *msg << " but got " << *value;
417}
418
419bool Attribute::matches(const Item* item, DiagMessage* outMsg) const {
420 android::Res_value val = {};
421 item->flatten(&val);
422
423 // Always allow references.
424 const uint32_t mask = typeMask | android::ResTable_map::TYPE_REFERENCE;
425 if (!(mask & ResourceUtils::androidTypeToAttributeTypeMask(val.dataType))) {
426 if (outMsg) {
427 buildAttributeMismatchMessage(outMsg, this, item);
428 }
429 return false;
430
431 } else if (ResourceUtils::androidTypeToAttributeTypeMask(val.dataType) &
432 android::ResTable_map::TYPE_INTEGER) {
433 if (static_cast<int32_t>(util::deviceToHost32(val.data)) < minInt) {
434 if (outMsg) {
435 *outMsg << *item << " is less than minimum integer " << minInt;
436 }
437 return false;
438 } else if (static_cast<int32_t>(util::deviceToHost32(val.data)) > maxInt) {
439 if (outMsg) {
440 *outMsg << *item << " is greater than maximum integer " << maxInt;
441 }
442 return false;
443 }
444 }
445 return true;
446}
447
Adam Lesinski769de982015-04-10 19:43:55 -0700448Style* Style::clone(StringPool* newPool) const {
Adam Lesinskibdaa0922015-05-08 20:16:23 -0700449 Style* style = new Style();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800450 style->parent = parent;
Adam Lesinskibdaa0922015-05-08 20:16:23 -0700451 style->parentInferred = parentInferred;
Adam Lesinskib274e352015-11-06 15:14:35 -0800452 style->mComment = mComment;
453 style->mSource = mSource;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800454 for (auto& entry : entries) {
455 style->entries.push_back(Entry{
456 entry.key,
Adam Lesinski769de982015-04-10 19:43:55 -0700457 std::unique_ptr<Item>(entry.value->clone(newPool))
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800458 });
459 }
460 return style;
461}
462
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700463void Style::print(std::ostream* out) const {
464 *out << "(style) ";
465 if (parent && parent.value().name) {
Adam Lesinski24b8ff02015-12-16 14:01:57 -0800466 if (parent.value().privateReference) {
467 *out << "*";
468 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700469 *out << parent.value().name.value();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800470 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700471 *out << " ["
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800472 << util::joiner(entries.begin(), entries.end(), ", ")
473 << "]";
474}
475
476static ::std::ostream& operator<<(::std::ostream& out, const Style::Entry& value) {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700477 if (value.key.name) {
478 out << value.key.name.value();
479 } else {
480 out << "???";
481 }
482 out << " = ";
483 value.value->print(&out);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800484 return out;
485}
486
Adam Lesinski769de982015-04-10 19:43:55 -0700487Array* Array::clone(StringPool* newPool) const {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800488 Array* array = new Array();
Adam Lesinskib274e352015-11-06 15:14:35 -0800489 array->mComment = mComment;
490 array->mSource = mSource;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800491 for (auto& item : items) {
Adam Lesinski769de982015-04-10 19:43:55 -0700492 array->items.emplace_back(std::unique_ptr<Item>(item->clone(newPool)));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800493 }
494 return array;
495}
496
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700497void Array::print(std::ostream* out) const {
498 *out << "(array) ["
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800499 << util::joiner(items.begin(), items.end(), ", ")
500 << "]";
501}
502
Adam Lesinski769de982015-04-10 19:43:55 -0700503Plural* Plural::clone(StringPool* newPool) const {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800504 Plural* p = new Plural();
Adam Lesinskib274e352015-11-06 15:14:35 -0800505 p->mComment = mComment;
506 p->mSource = mSource;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800507 const size_t count = values.size();
508 for (size_t i = 0; i < count; i++) {
509 if (values[i]) {
Adam Lesinski769de982015-04-10 19:43:55 -0700510 p->values[i] = std::unique_ptr<Item>(values[i]->clone(newPool));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800511 }
512 }
513 return p;
514}
515
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700516void Plural::print(std::ostream* out) const {
517 *out << "(plural)";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800518}
519
520static ::std::ostream& operator<<(::std::ostream& out, const std::unique_ptr<Item>& item) {
521 return out << *item;
522}
523
Adam Lesinski769de982015-04-10 19:43:55 -0700524Styleable* Styleable::clone(StringPool* /*newPool*/) const {
Adam Lesinski467f1712015-11-16 17:35:44 -0800525 return new Styleable(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800526}
527
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700528void Styleable::print(std::ostream* out) const {
529 *out << "(styleable) " << " ["
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800530 << util::joiner(entries.begin(), entries.end(), ", ")
531 << "]";
532}
533
534} // namespace aapt