diff options
Diffstat (limited to 'tools/aapt2/ResourceValues.cpp')
-rw-r--r-- | tools/aapt2/ResourceValues.cpp | 246 |
1 files changed, 197 insertions, 49 deletions
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp index 082fd86604da..b38d259d6b25 100644 --- a/tools/aapt2/ResourceValues.cpp +++ b/tools/aapt2/ResourceValues.cpp @@ -17,9 +17,12 @@ #include "ResourceValues.h" #include <algorithm> +#include <cinttypes> #include <limits> #include <set> +#include <sstream> +#include "android-base/stringprintf.h" #include "androidfw/ResourceTypes.h" #include "Resource.h" @@ -27,8 +30,18 @@ #include "ValueVisitor.h" #include "util/Util.h" +using ::aapt::text::Printer; +using ::android::StringPiece; +using ::android::base::StringPrintf; + namespace aapt { +void Value::PrettyPrint(Printer* printer) const { + std::ostringstream str_stream; + Print(&str_stream); + printer->Print(str_stream.str()); +} + std::ostream& operator<<(std::ostream& out, const Value& value) { value.Print(&out); return out; @@ -155,6 +168,49 @@ void Reference::Print(std::ostream* out) const { } } +static void PrettyPrintReferenceImpl(const Reference& ref, bool print_package, Printer* printer) { + switch (ref.reference_type) { + case Reference::Type::kResource: + printer->Print("@"); + break; + + case Reference::Type::kAttribute: + printer->Print("?"); + break; + } + + if (!ref.name && !ref.id) { + printer->Print("null"); + return; + } + + if (ref.private_reference) { + printer->Print("*"); + } + + if (ref.name) { + const ResourceName& name = ref.name.value(); + if (print_package) { + printer->Print(name.to_string()); + } else { + printer->Print(to_string(name.type)); + printer->Print("/"); + printer->Print(name.entry); + } + } else if (ref.id && ref.id.value().is_valid_dynamic()) { + printer->Print(ref.id.value().to_string()); + } +} + +void Reference::PrettyPrint(Printer* printer) const { + PrettyPrintReferenceImpl(*this, true /*print_package*/, printer); +} + +void Reference::PrettyPrint(const StringPiece& package, Printer* printer) const { + const bool print_package = name ? package != name.value().package : true; + PrettyPrintReferenceImpl(*this, print_package, printer); +} + bool Id::Equals(const Value* value) const { return ValueCast<Id>(value) != nullptr; } @@ -165,11 +221,16 @@ bool Id::Flatten(android::Res_value* out) const { return true; } -Id* Id::Clone(StringPool* /*new_pool*/) const { return new Id(*this); } +Id* Id::Clone(StringPool* /*new_pool*/) const { + return new Id(*this); +} -void Id::Print(std::ostream* out) const { *out << "(id)"; } +void Id::Print(std::ostream* out) const { + *out << "(id)"; +} -String::String(const StringPool::Ref& ref) : value(ref) {} +String::String(const StringPool::Ref& ref) : value(ref) { +} bool String::Equals(const Value* value) const { const String* other = ValueCast<String>(value); @@ -218,7 +279,14 @@ void String::Print(std::ostream* out) const { *out << "(string) \"" << *value << "\""; } -StyledString::StyledString(const StringPool::StyleRef& ref) : value(ref) {} +void String::PrettyPrint(Printer* printer) const { + printer->Print("\""); + printer->Print(*value); + printer->Print("\""); +} + +StyledString::StyledString(const StringPool::StyleRef& ref) : value(ref) { +} bool StyledString::Equals(const Value* value) const { const StyledString* other = ValueCast<StyledString>(value); @@ -269,7 +337,8 @@ void StyledString::Print(std::ostream* out) const { } } -FileReference::FileReference(const StringPool::Ref& _path) : path(_path) {} +FileReference::FileReference(const StringPool::Ref& _path) : path(_path) { +} bool FileReference::Equals(const Value* value) const { const FileReference* other = ValueCast<FileReference>(value); @@ -302,7 +371,8 @@ void FileReference::Print(std::ostream* out) const { *out << "(file) " << *path; } -BinaryPrimitive::BinaryPrimitive(const android::Res_value& val) : value(val) {} +BinaryPrimitive::BinaryPrimitive(const android::Res_value& val) : value(val) { +} BinaryPrimitive::BinaryPrimitive(uint8_t dataType, uint32_t data) { value.dataType = dataType; @@ -318,7 +388,7 @@ bool BinaryPrimitive::Equals(const Value* value) const { this->value.data == other->value.data; } -bool BinaryPrimitive::Flatten(android::Res_value* out_value) const { +bool BinaryPrimitive::Flatten(::android::Res_value* out_value) const { out_value->dataType = value.dataType; out_value->data = util::HostToDevice32(value.data); return true; @@ -329,32 +399,110 @@ BinaryPrimitive* BinaryPrimitive::Clone(StringPool* /*new_pool*/) const { } void BinaryPrimitive::Print(std::ostream* out) const { + *out << StringPrintf("(primitive) type=0x%02x data=0x%08x", value.dataType, value.data); +} + +static std::string ComplexToString(uint32_t complex_value, bool fraction) { + using ::android::Res_value; + + constexpr std::array<int, 4> kRadixShifts = {{23, 16, 8, 0}}; + + // Determine the radix that was used. + const uint32_t radix = + (complex_value >> Res_value::COMPLEX_RADIX_SHIFT) & Res_value::COMPLEX_RADIX_MASK; + const uint64_t mantissa = uint64_t{(complex_value >> Res_value::COMPLEX_MANTISSA_SHIFT) & + Res_value::COMPLEX_MANTISSA_MASK} + << kRadixShifts[radix]; + const float value = mantissa * (1.0f / (1 << 23)); + + std::string str = StringPrintf("%f", value); + + const int unit_type = + (complex_value >> Res_value::COMPLEX_UNIT_SHIFT) & Res_value::COMPLEX_UNIT_MASK; + if (fraction) { + switch (unit_type) { + case Res_value::COMPLEX_UNIT_FRACTION: + str += "%"; + break; + case Res_value::COMPLEX_UNIT_FRACTION_PARENT: + str += "%p"; + break; + default: + str += "???"; + break; + } + } else { + switch (unit_type) { + case Res_value::COMPLEX_UNIT_PX: + str += "px"; + break; + case Res_value::COMPLEX_UNIT_DIP: + str += "dp"; + break; + case Res_value::COMPLEX_UNIT_SP: + str += "sp"; + break; + case Res_value::COMPLEX_UNIT_PT: + str += "pt"; + break; + case Res_value::COMPLEX_UNIT_IN: + str += "in"; + break; + case Res_value::COMPLEX_UNIT_MM: + str += "mm"; + break; + default: + str += "???"; + break; + } + } + return str; +} + +void BinaryPrimitive::PrettyPrint(Printer* printer) const { + using ::android::Res_value; switch (value.dataType) { - case android::Res_value::TYPE_NULL: - if (value.data == android::Res_value::DATA_NULL_EMPTY) { - *out << "(empty)"; + case Res_value::TYPE_NULL: + if (value.data == Res_value::DATA_NULL_EMPTY) { + printer->Print("@empty"); } else { - *out << "(null)"; + printer->Print("@null"); } break; - case android::Res_value::TYPE_INT_DEC: - *out << "(integer) " << static_cast<int32_t>(value.data); + + case Res_value::TYPE_INT_DEC: + printer->Print(StringPrintf("%" PRIi32, static_cast<int32_t>(value.data))); + break; + + case Res_value::TYPE_INT_HEX: + printer->Print(StringPrintf("0x%08x", value.data)); + break; + + case Res_value::TYPE_INT_BOOLEAN: + printer->Print(value.data != 0 ? "true" : "false"); + break; + + case Res_value::TYPE_INT_COLOR_ARGB8: + case Res_value::TYPE_INT_COLOR_RGB8: + case Res_value::TYPE_INT_COLOR_ARGB4: + case Res_value::TYPE_INT_COLOR_RGB4: + printer->Print(StringPrintf("#%08x", value.data)); break; - case android::Res_value::TYPE_INT_HEX: - *out << "(integer) 0x" << std::hex << value.data << std::dec; + + case Res_value::TYPE_FLOAT: + printer->Print(StringPrintf("%g", *reinterpret_cast<const float*>(&value.data))); break; - case android::Res_value::TYPE_INT_BOOLEAN: - *out << "(boolean) " << (value.data != 0 ? "true" : "false"); + + case Res_value::TYPE_DIMENSION: + printer->Print(ComplexToString(value.data, false /*fraction*/)); break; - case android::Res_value::TYPE_INT_COLOR_ARGB8: - case android::Res_value::TYPE_INT_COLOR_RGB8: - case android::Res_value::TYPE_INT_COLOR_ARGB4: - case android::Res_value::TYPE_INT_COLOR_RGB4: - *out << "(color) #" << std::hex << value.data << std::dec; + + case Res_value::TYPE_FRACTION: + printer->Print(ComplexToString(value.data, true /*fraction*/)); break; + default: - *out << "(unknown 0x" << std::hex << (int)value.dataType << ") 0x" - << std::hex << value.data << std::dec; + printer->Print(StringPrintf("(unknown 0x%02x) 0x%08x", value.dataType, value.data)); break; } } @@ -424,107 +572,107 @@ Attribute* Attribute::Clone(StringPool* /*new_pool*/) const { return new Attribute(*this); } -void Attribute::PrintMask(std::ostream* out) const { +std::string Attribute::MaskString() const { if (type_mask == android::ResTable_map::TYPE_ANY) { - *out << "any"; - return; + return "any"; } + std::ostringstream out; bool set = false; if ((type_mask & android::ResTable_map::TYPE_REFERENCE) != 0) { if (!set) { set = true; } else { - *out << "|"; + out << "|"; } - *out << "reference"; + out << "reference"; } if ((type_mask & android::ResTable_map::TYPE_STRING) != 0) { if (!set) { set = true; } else { - *out << "|"; + out << "|"; } - *out << "string"; + out << "string"; } if ((type_mask & android::ResTable_map::TYPE_INTEGER) != 0) { if (!set) { set = true; } else { - *out << "|"; + out << "|"; } - *out << "integer"; + out << "integer"; } if ((type_mask & android::ResTable_map::TYPE_BOOLEAN) != 0) { if (!set) { set = true; } else { - *out << "|"; + out << "|"; } - *out << "boolean"; + out << "boolean"; } if ((type_mask & android::ResTable_map::TYPE_COLOR) != 0) { if (!set) { set = true; } else { - *out << "|"; + out << "|"; } - *out << "color"; + out << "color"; } if ((type_mask & android::ResTable_map::TYPE_FLOAT) != 0) { if (!set) { set = true; } else { - *out << "|"; + out << "|"; } - *out << "float"; + out << "float"; } if ((type_mask & android::ResTable_map::TYPE_DIMENSION) != 0) { if (!set) { set = true; } else { - *out << "|"; + out << "|"; } - *out << "dimension"; + out << "dimension"; } if ((type_mask & android::ResTable_map::TYPE_FRACTION) != 0) { if (!set) { set = true; } else { - *out << "|"; + out << "|"; } - *out << "fraction"; + out << "fraction"; } if ((type_mask & android::ResTable_map::TYPE_ENUM) != 0) { if (!set) { set = true; } else { - *out << "|"; + out << "|"; } - *out << "enum"; + out << "enum"; } if ((type_mask & android::ResTable_map::TYPE_FLAGS) != 0) { if (!set) { set = true; } else { - *out << "|"; + out << "|"; } - *out << "flags"; + out << "flags"; } + return out.str(); } void Attribute::Print(std::ostream* out) const { - *out << "(attr) "; - PrintMask(out); + *out << "(attr) " << MaskString(); if (!symbols.empty()) { *out << " [" << util::Joiner(symbols, ", ") << "]"; |