From c674d38c8cea475cd29f7b0835e9864a2424b646 Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Fri, 31 Mar 2023 22:37:42 +0000 Subject: Add additional check on float precision after parsing, only compile the value to a float when the difference between float and double parsed from same raw string is smaller than 1. Bug: b/69347762 Test: Verified affected atests pass and added new atest Change-Id: I25da0baccba580484db39aa2d0a1bb765706635d --- tools/aapt2/ResourceValues.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'tools/aapt2/ResourceValues.cpp') diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp index a5754e0d168f..166b01bd9154 100644 --- a/tools/aapt2/ResourceValues.cpp +++ b/tools/aapt2/ResourceValues.cpp @@ -439,6 +439,21 @@ static std::string ComplexToString(uint32_t complex_value, bool fraction) { return str; } +// This function is designed to using different specifier to print different floats, +// which can print more accurate format rather than using %g only. +const char* BinaryPrimitive::DecideFormat(float f) { + // if the float is either too big or too tiny, print it in scientific notation. + // eg: "10995116277760000000000" to 1.099512e+22, "0.00000000001" to 1.000000e-11 + if (fabs(f) > std::numeric_limits::max() || fabs(f) < 1e-10) { + return "%e"; + // Else if the number is an integer exactly, print it without trailing zeros. + // eg: "1099511627776" to 1099511627776 + } else if (int64_t(f) == f) { + return "%.0f"; + } + return "%g"; +} + void BinaryPrimitive::PrettyPrint(Printer* printer) const { using ::android::Res_value; switch (value.dataType) { @@ -470,7 +485,9 @@ void BinaryPrimitive::PrettyPrint(Printer* printer) const { break; case Res_value::TYPE_FLOAT: - printer->Print(StringPrintf("%g", *reinterpret_cast(&value.data))); + float f; + f = *reinterpret_cast(&value.data); + printer->Print(StringPrintf(DecideFormat(f), f)); break; case Res_value::TYPE_DIMENSION: -- cgit v1.2.3-59-g8ed1b