| @@ -797,10 +797,10 @@ static struct ParameterAdapterTests final : public UnitTest | |||
| expectEquals (adapter.getTextForDenormalisedValue (value), expected); | |||
| }; | |||
| test ({ -100, 100 }, 0, "0.0"); | |||
| test ({ -2.5, 12.5 }, 10, "10.0"); | |||
| test ({ -20, -10 }, -15, "-15.0"); | |||
| test ({ 0, 7.5 }, 2.5, "2.5"); | |||
| test ({ -100, 100 }, 0, "0.00"); | |||
| test ({ -2.5, 12.5 }, 10, "10.00"); | |||
| test ({ -20, -10 }, -15, "-15.00"); | |||
| test ({ 0, 7.5 }, 2.5, "2.50"); | |||
| } | |||
| beginTest ("Text can be converted to floats"); | |||
| @@ -469,30 +469,7 @@ namespace NumberToStringConverters | |||
| o << n; | |||
| } | |||
| return findLengthWithoutTrailingZeros (pbase(), pptr()); | |||
| } | |||
| static size_t findLengthWithoutTrailingZeros (const char* const start, | |||
| const char* const end) | |||
| { | |||
| for (auto e = end; e > start + 1; --e) | |||
| { | |||
| auto lastChar = *(e - 1); | |||
| if (lastChar != '0') | |||
| { | |||
| if (lastChar == '.') | |||
| return (size_t) (e + 1 - start); | |||
| for (auto s = start; s < e; ++s) | |||
| if (*s == '.') | |||
| return (size_t) (e - start); | |||
| break; | |||
| } | |||
| } | |||
| return (size_t) (end - start); | |||
| return (size_t) (pptr() - pbase()); | |||
| } | |||
| }; | |||
| @@ -505,14 +482,7 @@ namespace NumberToStringConverters | |||
| auto v = (int64) (std::pow (10.0, numDecPlaces) * std::abs (n) + 0.5); | |||
| *--t = (char) 0; | |||
| // skip trailing zeros | |||
| while (numDecPlaces > 1 && (v % 10) == 0) | |||
| { | |||
| v /= 10; | |||
| --numDecPlaces; | |||
| } | |||
| while (v > 0 || numDecPlaces >= 0) | |||
| while (numDecPlaces >= 0 || v > 0) | |||
| { | |||
| if (numDecPlaces == 0) | |||
| *--t = '.'; | |||
| @@ -2523,14 +2493,7 @@ public: | |||
| expect (String::toHexString (data, 8, 1).equalsIgnoreCase ("01 02 03 04 0a 0b 0c 0d")); | |||
| expect (String::toHexString (data, 8, 2).equalsIgnoreCase ("0102 0304 0a0b 0c0d")); | |||
| expectEquals (String (2589410.5894, 7), String ("2589410.5894")); | |||
| expectEquals (String (2589410.5894, 4), String ("2589410.5894")); | |||
| expectEquals (String (100000.0, 1), String ("100000.0")); | |||
| expectEquals (String (100000.0, 10), String ("100000.0")); | |||
| expectEquals (String (100000.001, 8), String ("100000.001")); | |||
| expectEquals (String (100000.001, 4), String ("100000.001")); | |||
| expectEquals (String (100000.001, 3), String ("100000.001")); | |||
| expectEquals (String (100000.001, 2), String ("100000.0")); | |||
| expectEquals (String (2589410.5894, 7), String ("2589410.5894000")); | |||
| beginTest ("Subsections"); | |||
| String s3; | |||
| @@ -962,23 +962,23 @@ public: | |||
| /** Creates a string representing this floating-point number. | |||
| @param floatValue the value to convert to a string | |||
| @param maxNumberOfDecimalPlaces if this is > 0, it will format the number using no more | |||
| decimal places than this amount, and will not use exponent | |||
| notation. If 0 or less, it will use a default format, and | |||
| @param numberOfDecimalPlaces if this is > 0, it will format the number using that many | |||
| decimal places, adding trailing zeros as required, and | |||
| will not use exponent notation. If 0 or less, it will use | |||
| exponent notation if necessary. | |||
| @see getDoubleValue, getIntValue | |||
| */ | |||
| String (float floatValue, int maxNumberOfDecimalPlaces); | |||
| String (float floatValue, int numberOfDecimalPlaces); | |||
| /** Creates a string representing this floating-point number. | |||
| @param doubleValue the value to convert to a string | |||
| @param maxNumberOfDecimalPlaces if this is > 0, it will format the number using no more | |||
| decimal places than this amount, and will not use exponent | |||
| notation. If 0 or less, it will use a default format, and | |||
| @param numberOfDecimalPlaces if this is > 0, it will format the number using that many | |||
| decimal places, adding trailing zeros as required, and | |||
| will not use exponent notation. If 0 or less, it will use | |||
| exponent notation if necessary. | |||
| @see getFloatValue, getIntValue | |||
| */ | |||
| String (double doubleValue, int maxNumberOfDecimalPlaces); | |||
| String (double doubleValue, int numberOfDecimalPlaces); | |||
| // Automatically creating a String from a bool opens up lots of nasty type conversion edge cases. | |||
| // If you want a String representation of a bool you can cast the bool to an int first. | |||
| @@ -578,9 +578,26 @@ void XmlElement::setAttribute (const Identifier& attributeName, const int number | |||
| setAttribute (attributeName, String (number)); | |||
| } | |||
| static String trimTrailingZeros (const String& input) | |||
| { | |||
| auto pointPos = input.indexOfChar ('.'); | |||
| if (pointPos == -1) | |||
| return input; | |||
| auto start = input.getCharPointer(); | |||
| auto minPos = start + pointPos + 1; | |||
| auto ptr = start + input.length() - 1; | |||
| while (ptr != minPos && *ptr == '0') | |||
| --ptr; | |||
| return input.substring (0, (int) (ptr - start) + 1); | |||
| } | |||
| void XmlElement::setAttribute (const Identifier& attributeName, const double number) | |||
| { | |||
| setAttribute (attributeName, String (number, 20)); | |||
| setAttribute (attributeName, trimTrailingZeros ({ number, 20 })); | |||
| } | |||
| void XmlElement::removeAttribute (const Identifier& attributeName) noexcept | |||
| @@ -923,4 +940,30 @@ void XmlElement::deleteAllTextElements() noexcept | |||
| } | |||
| } | |||
| //============================================================================== | |||
| #if JUCE_UNIT_TESTS | |||
| class XmlElementTests : public UnitTest | |||
| { | |||
| public: | |||
| XmlElementTests() : UnitTest ("XmlElement", "XML") {} | |||
| void runTest() override | |||
| { | |||
| { | |||
| beginTest ("Trailing zeros"); | |||
| auto element = std::make_unique<XmlElement> ("test"); | |||
| Identifier d ("d"); | |||
| element->setAttribute (d, 3.0); | |||
| expectEquals (element->getStringAttribute (d), String ("3.0")); | |||
| } | |||
| } | |||
| }; | |||
| static XmlElementTests xmlElementTests; | |||
| #endif | |||
| } // namespace juce | |||