blob: b93e6d889ad0ce070365ca9c4113b0255d54ec61 [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 Lesinskie78fd612015-10-22 12:48:43 -070021#include "util/Util.h"
22#include "flatten/ResourceTypeExtensions.h"
23
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 {
50 outValue->dataType = ExtendedTypes::TYPE_RAW_STRING;
51 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));
194 fr->mComment = mComment;
195 fr->mSource = mSource;
196 return fr;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800197}
198
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700199void FileReference::print(std::ostream* out) const {
200 *out << "(file) " << *path;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800201}
202
203BinaryPrimitive::BinaryPrimitive(const android::Res_value& val) : value(val) {
204}
205
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700206BinaryPrimitive::BinaryPrimitive(uint8_t dataType, uint32_t data) {
207 value.dataType = dataType;
208 value.data = data;
209}
210
211bool BinaryPrimitive::flatten(android::Res_value* outValue) const {
212 outValue->dataType = value.dataType;
213 outValue->data = util::hostToDevice32(value.data);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800214 return true;
215}
216
Adam Lesinski769de982015-04-10 19:43:55 -0700217BinaryPrimitive* BinaryPrimitive::clone(StringPool* /*newPool*/) const {
Adam Lesinski467f1712015-11-16 17:35:44 -0800218 return new BinaryPrimitive(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800219}
220
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700221void BinaryPrimitive::print(std::ostream* out) const {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800222 switch (value.dataType) {
223 case android::Res_value::TYPE_NULL:
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700224 *out << "(null)";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800225 break;
226 case android::Res_value::TYPE_INT_DEC:
Adam Lesinskia5870652015-11-20 15:32:30 -0800227 *out << "(integer) " << static_cast<int32_t>(value.data);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800228 break;
229 case android::Res_value::TYPE_INT_HEX:
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700230 *out << "(integer) " << std::hex << value.data << std::dec;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800231 break;
232 case android::Res_value::TYPE_INT_BOOLEAN:
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700233 *out << "(boolean) " << (value.data != 0 ? "true" : "false");
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800234 break;
235 case android::Res_value::TYPE_INT_COLOR_ARGB8:
236 case android::Res_value::TYPE_INT_COLOR_RGB8:
237 case android::Res_value::TYPE_INT_COLOR_ARGB4:
238 case android::Res_value::TYPE_INT_COLOR_RGB4:
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700239 *out << "(color) #" << std::hex << value.data << std::dec;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800240 break;
241 default:
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700242 *out << "(unknown 0x" << std::hex << (int) value.dataType << ") 0x"
243 << std::hex << value.data << std::dec;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800244 break;
245 }
246}
247
Adam Lesinskia5870652015-11-20 15:32:30 -0800248Attribute::Attribute(bool w, uint32_t t) :
Adam Lesinski393b5f02015-12-17 13:03:11 -0800249 typeMask(t),
Adam Lesinskia5870652015-11-20 15:32:30 -0800250 minInt(std::numeric_limits<int32_t>::min()),
251 maxInt(std::numeric_limits<int32_t>::max()) {
Adam Lesinski393b5f02015-12-17 13:03:11 -0800252 mWeak = w;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800253}
254
Adam Lesinski769de982015-04-10 19:43:55 -0700255Attribute* Attribute::clone(StringPool* /*newPool*/) const {
Adam Lesinski467f1712015-11-16 17:35:44 -0800256 return new Attribute(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800257}
258
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700259void Attribute::printMask(std::ostream* out) const {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800260 if (typeMask == android::ResTable_map::TYPE_ANY) {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700261 *out << "any";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800262 return;
263 }
264
265 bool set = false;
266 if ((typeMask & android::ResTable_map::TYPE_REFERENCE) != 0) {
267 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800268 set = true;
269 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700270 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800271 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700272 *out << "reference";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800273 }
274
275 if ((typeMask & android::ResTable_map::TYPE_STRING) != 0) {
276 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800277 set = true;
278 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700279 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800280 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700281 *out << "string";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800282 }
283
284 if ((typeMask & android::ResTable_map::TYPE_INTEGER) != 0) {
285 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800286 set = true;
287 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700288 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800289 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700290 *out << "integer";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800291 }
292
293 if ((typeMask & android::ResTable_map::TYPE_BOOLEAN) != 0) {
294 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800295 set = true;
296 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700297 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800298 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700299 *out << "boolean";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800300 }
301
302 if ((typeMask & android::ResTable_map::TYPE_COLOR) != 0) {
303 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800304 set = true;
305 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700306 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800307 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700308 *out << "color";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800309 }
310
311 if ((typeMask & android::ResTable_map::TYPE_FLOAT) != 0) {
312 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800313 set = true;
314 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700315 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800316 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700317 *out << "float";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800318 }
319
320 if ((typeMask & android::ResTable_map::TYPE_DIMENSION) != 0) {
321 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800322 set = true;
323 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700324 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800325 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700326 *out << "dimension";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800327 }
328
329 if ((typeMask & android::ResTable_map::TYPE_FRACTION) != 0) {
330 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800331 set = true;
332 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700333 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800334 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700335 *out << "fraction";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800336 }
337
338 if ((typeMask & android::ResTable_map::TYPE_ENUM) != 0) {
339 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800340 set = true;
341 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700342 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800343 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700344 *out << "enum";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800345 }
346
347 if ((typeMask & android::ResTable_map::TYPE_FLAGS) != 0) {
348 if (!set) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800349 set = true;
350 } else {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700351 *out << "|";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800352 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700353 *out << "flags";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800354 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700355}
356
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700357void Attribute::print(std::ostream* out) const {
358 *out << "(attr) ";
Adam Lesinski330edcd2015-05-04 17:40:56 -0700359 printMask(out);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800360
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700361 if (!symbols.empty()) {
362 *out << " ["
363 << util::joiner(symbols.begin(), symbols.end(), ", ")
364 << "]";
365 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800366
Adam Lesinski393b5f02015-12-17 13:03:11 -0800367 if (isWeak()) {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700368 *out << " [weak]";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800369 }
370}
371
Adam Lesinskia5870652015-11-20 15:32:30 -0800372static void buildAttributeMismatchMessage(DiagMessage* msg, const Attribute* attr,
373 const Item* value) {
374 *msg << "expected";
375 if (attr->typeMask & android::ResTable_map::TYPE_BOOLEAN) {
376 *msg << " boolean";
377 }
378
379 if (attr->typeMask & android::ResTable_map::TYPE_COLOR) {
380 *msg << " color";
381 }
382
383 if (attr->typeMask & android::ResTable_map::TYPE_DIMENSION) {
384 *msg << " dimension";
385 }
386
387 if (attr->typeMask & android::ResTable_map::TYPE_ENUM) {
388 *msg << " enum";
389 }
390
391 if (attr->typeMask & android::ResTable_map::TYPE_FLAGS) {
392 *msg << " flags";
393 }
394
395 if (attr->typeMask & android::ResTable_map::TYPE_FLOAT) {
396 *msg << " float";
397 }
398
399 if (attr->typeMask & android::ResTable_map::TYPE_FRACTION) {
400 *msg << " fraction";
401 }
402
403 if (attr->typeMask & android::ResTable_map::TYPE_INTEGER) {
404 *msg << " integer";
405 }
406
407 if (attr->typeMask & android::ResTable_map::TYPE_REFERENCE) {
408 *msg << " reference";
409 }
410
411 if (attr->typeMask & android::ResTable_map::TYPE_STRING) {
412 *msg << " string";
413 }
414
415 *msg << " but got " << *value;
416}
417
418bool Attribute::matches(const Item* item, DiagMessage* outMsg) const {
419 android::Res_value val = {};
420 item->flatten(&val);
421
422 // Always allow references.
423 const uint32_t mask = typeMask | android::ResTable_map::TYPE_REFERENCE;
424 if (!(mask & ResourceUtils::androidTypeToAttributeTypeMask(val.dataType))) {
425 if (outMsg) {
426 buildAttributeMismatchMessage(outMsg, this, item);
427 }
428 return false;
429
430 } else if (ResourceUtils::androidTypeToAttributeTypeMask(val.dataType) &
431 android::ResTable_map::TYPE_INTEGER) {
432 if (static_cast<int32_t>(util::deviceToHost32(val.data)) < minInt) {
433 if (outMsg) {
434 *outMsg << *item << " is less than minimum integer " << minInt;
435 }
436 return false;
437 } else if (static_cast<int32_t>(util::deviceToHost32(val.data)) > maxInt) {
438 if (outMsg) {
439 *outMsg << *item << " is greater than maximum integer " << maxInt;
440 }
441 return false;
442 }
443 }
444 return true;
445}
446
Adam Lesinski769de982015-04-10 19:43:55 -0700447Style* Style::clone(StringPool* newPool) const {
Adam Lesinskibdaa0922015-05-08 20:16:23 -0700448 Style* style = new Style();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800449 style->parent = parent;
Adam Lesinskibdaa0922015-05-08 20:16:23 -0700450 style->parentInferred = parentInferred;
Adam Lesinskib274e352015-11-06 15:14:35 -0800451 style->mComment = mComment;
452 style->mSource = mSource;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800453 for (auto& entry : entries) {
454 style->entries.push_back(Entry{
455 entry.key,
Adam Lesinski769de982015-04-10 19:43:55 -0700456 std::unique_ptr<Item>(entry.value->clone(newPool))
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800457 });
458 }
459 return style;
460}
461
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700462void Style::print(std::ostream* out) const {
463 *out << "(style) ";
464 if (parent && parent.value().name) {
Adam Lesinski24b8ff02015-12-16 14:01:57 -0800465 if (parent.value().privateReference) {
466 *out << "*";
467 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700468 *out << parent.value().name.value();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800469 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700470 *out << " ["
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800471 << util::joiner(entries.begin(), entries.end(), ", ")
472 << "]";
473}
474
475static ::std::ostream& operator<<(::std::ostream& out, const Style::Entry& value) {
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700476 if (value.key.name) {
477 out << value.key.name.value();
478 } else {
479 out << "???";
480 }
481 out << " = ";
482 value.value->print(&out);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800483 return out;
484}
485
Adam Lesinski769de982015-04-10 19:43:55 -0700486Array* Array::clone(StringPool* newPool) const {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800487 Array* array = new Array();
Adam Lesinskib274e352015-11-06 15:14:35 -0800488 array->mComment = mComment;
489 array->mSource = mSource;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800490 for (auto& item : items) {
Adam Lesinski769de982015-04-10 19:43:55 -0700491 array->items.emplace_back(std::unique_ptr<Item>(item->clone(newPool)));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800492 }
493 return array;
494}
495
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700496void Array::print(std::ostream* out) const {
497 *out << "(array) ["
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800498 << util::joiner(items.begin(), items.end(), ", ")
499 << "]";
500}
501
Adam Lesinski769de982015-04-10 19:43:55 -0700502Plural* Plural::clone(StringPool* newPool) const {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800503 Plural* p = new Plural();
Adam Lesinskib274e352015-11-06 15:14:35 -0800504 p->mComment = mComment;
505 p->mSource = mSource;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800506 const size_t count = values.size();
507 for (size_t i = 0; i < count; i++) {
508 if (values[i]) {
Adam Lesinski769de982015-04-10 19:43:55 -0700509 p->values[i] = std::unique_ptr<Item>(values[i]->clone(newPool));
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800510 }
511 }
512 return p;
513}
514
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700515void Plural::print(std::ostream* out) const {
516 *out << "(plural)";
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800517}
518
519static ::std::ostream& operator<<(::std::ostream& out, const std::unique_ptr<Item>& item) {
520 return out << *item;
521}
522
Adam Lesinski769de982015-04-10 19:43:55 -0700523Styleable* Styleable::clone(StringPool* /*newPool*/) const {
Adam Lesinski467f1712015-11-16 17:35:44 -0800524 return new Styleable(*this);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800525}
526
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700527void Styleable::print(std::ostream* out) const {
528 *out << "(styleable) " << " ["
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800529 << util::joiner(entries.begin(), entries.end(), ", ")
530 << "]";
531}
532
533} // namespace aapt