ResourceValues.cpp revision 769de98f2dd41bfe39a1c9f76aefd1ad58942733
1/* 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(StringPool* newPool) const { 43 return new RawString(newPool->makeRef(*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(StringPool* /*newPool*/) 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(StringPool* /*newPool*/) 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(StringPool* newPool) const { 132 return new String(newPool->makeRef(*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(StringPool* newPool) const { 153 return new StyledString(newPool->makeRef(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(StringPool* newPool) const { 174 return new FileReference(newPool->makeRef(*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(StringPool* /*newPool*/) 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(StringPool* /*newPool*/) 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(StringPool* /*newPool*/) 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(bool weak) : weak(weak) { 375} 376 377bool Style::isWeak() const { 378 return weak; 379} 380 381Style* Style::clone(StringPool* newPool) const { 382 Style* style = new Style(weak); 383 style->parent = parent; 384 for (auto& entry : entries) { 385 style->entries.push_back(Entry{ 386 entry.key, 387 std::unique_ptr<Item>(entry.value->clone(newPool)) 388 }); 389 } 390 return style; 391} 392 393void Style::print(std::ostream& out) const { 394 out << "(style) "; 395 if (!parent.name.entry.empty()) { 396 out << parent.name; 397 } 398 out << " [" 399 << util::joiner(entries.begin(), entries.end(), ", ") 400 << "]"; 401} 402 403static ::std::ostream& operator<<(::std::ostream& out, const Style::Entry& value) { 404 out << value.key.name << " = "; 405 value.value->print(out); 406 return out; 407} 408 409Array* Array::clone(StringPool* newPool) const { 410 Array* array = new Array(); 411 for (auto& item : items) { 412 array->items.emplace_back(std::unique_ptr<Item>(item->clone(newPool))); 413 } 414 return array; 415} 416 417void Array::print(std::ostream& out) const { 418 out << "(array) [" 419 << util::joiner(items.begin(), items.end(), ", ") 420 << "]"; 421} 422 423Plural* Plural::clone(StringPool* newPool) const { 424 Plural* p = new Plural(); 425 const size_t count = values.size(); 426 for (size_t i = 0; i < count; i++) { 427 if (values[i]) { 428 p->values[i] = std::unique_ptr<Item>(values[i]->clone(newPool)); 429 } 430 } 431 return p; 432} 433 434void Plural::print(std::ostream& out) const { 435 out << "(plural)"; 436} 437 438static ::std::ostream& operator<<(::std::ostream& out, const std::unique_ptr<Item>& item) { 439 return out << *item; 440} 441 442Styleable* Styleable::clone(StringPool* /*newPool*/) const { 443 Styleable* styleable = new Styleable(); 444 std::copy(entries.begin(), entries.end(), std::back_inserter(styleable->entries)); 445 return styleable; 446} 447 448void Styleable::print(std::ostream& out) const { 449 out << "(styleable) " << " [" 450 << util::joiner(entries.begin(), entries.end(), ", ") 451 << "]"; 452} 453 454} // namespace aapt 455