00596d3027
- Use move assignment for fields->formatter (LocalizedNumberFormatter) instead of creating new heap object every time. - Add test cases for DecimalFormat object in invalid state. - Protect against self-assignment in assignment operator. - Fix segmentation fault when attempting to compare valid and invalid DecimalFormat objects. - Changes based on review feedback from Shane. - Fix minor typos in the public header file.
153 lines
5.7 KiB
C++
153 lines
5.7 KiB
C++
// © 2017 and later: Unicode, Inc. and others.
|
|
// License & terms of use: http://www.unicode.org/copyright.html
|
|
|
|
#include "unicode/utypes.h"
|
|
|
|
#if !UCONFIG_NO_FORMATTING
|
|
|
|
#include "number_decimfmtprops.h"
|
|
#include "umutex.h"
|
|
|
|
using namespace icu;
|
|
using namespace icu::number;
|
|
using namespace icu::number::impl;
|
|
|
|
|
|
namespace {
|
|
|
|
alignas(DecimalFormatProperties)
|
|
char kRawDefaultProperties[sizeof(DecimalFormatProperties)];
|
|
|
|
icu::UInitOnce gDefaultPropertiesInitOnce = U_INITONCE_INITIALIZER;
|
|
|
|
void U_CALLCONV initDefaultProperties(UErrorCode&) {
|
|
// can't fail, uses placement new into staticly allocated space.
|
|
new(kRawDefaultProperties) DecimalFormatProperties(); // set to the default instance
|
|
}
|
|
|
|
}
|
|
|
|
|
|
DecimalFormatProperties::DecimalFormatProperties() {
|
|
clear();
|
|
}
|
|
|
|
void DecimalFormatProperties::clear() {
|
|
compactStyle.nullify();
|
|
currency.nullify();
|
|
currencyPluralInfo.fPtr.adoptInstead(nullptr);
|
|
currencyUsage.nullify();
|
|
decimalPatternMatchRequired = false;
|
|
decimalSeparatorAlwaysShown = false;
|
|
exponentSignAlwaysShown = false;
|
|
formatFailIfMoreThanMaxDigits = false;
|
|
formatWidth = -1;
|
|
groupingSize = -1;
|
|
groupingUsed = true;
|
|
magnitudeMultiplier = 0;
|
|
maximumFractionDigits = -1;
|
|
maximumIntegerDigits = -1;
|
|
maximumSignificantDigits = -1;
|
|
minimumExponentDigits = -1;
|
|
minimumFractionDigits = -1;
|
|
minimumGroupingDigits = -1;
|
|
minimumIntegerDigits = -1;
|
|
minimumSignificantDigits = -1;
|
|
multiplier = 1;
|
|
multiplierScale = 0;
|
|
negativePrefix.setToBogus();
|
|
negativePrefixPattern.setToBogus();
|
|
negativeSuffix.setToBogus();
|
|
negativeSuffixPattern.setToBogus();
|
|
padPosition.nullify();
|
|
padString.setToBogus();
|
|
parseCaseSensitive = false;
|
|
parseIntegerOnly = false;
|
|
parseMode.nullify();
|
|
parseNoExponent = false;
|
|
parseToBigDecimal = false;
|
|
parseAllInput = UNUM_MAYBE;
|
|
positivePrefix.setToBogus();
|
|
positivePrefixPattern.setToBogus();
|
|
positiveSuffix.setToBogus();
|
|
positiveSuffixPattern.setToBogus();
|
|
roundingIncrement = 0.0;
|
|
roundingMode.nullify();
|
|
secondaryGroupingSize = -1;
|
|
signAlwaysShown = false;
|
|
}
|
|
|
|
bool
|
|
DecimalFormatProperties::_equals(const DecimalFormatProperties& other, bool ignoreForFastFormat) const {
|
|
bool eq = true;
|
|
|
|
// Properties that must be equal both normally and for fast-path formatting
|
|
eq = eq && compactStyle == other.compactStyle;
|
|
eq = eq && currency == other.currency;
|
|
eq = eq && currencyPluralInfo.fPtr.getAlias() == other.currencyPluralInfo.fPtr.getAlias();
|
|
eq = eq && currencyUsage == other.currencyUsage;
|
|
eq = eq && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown;
|
|
eq = eq && exponentSignAlwaysShown == other.exponentSignAlwaysShown;
|
|
eq = eq && formatFailIfMoreThanMaxDigits == other.formatFailIfMoreThanMaxDigits;
|
|
eq = eq && formatWidth == other.formatWidth;
|
|
eq = eq && magnitudeMultiplier == other.magnitudeMultiplier;
|
|
eq = eq && maximumSignificantDigits == other.maximumSignificantDigits;
|
|
eq = eq && minimumExponentDigits == other.minimumExponentDigits;
|
|
eq = eq && minimumGroupingDigits == other.minimumGroupingDigits;
|
|
eq = eq && minimumSignificantDigits == other.minimumSignificantDigits;
|
|
eq = eq && multiplier == other.multiplier;
|
|
eq = eq && multiplierScale == other.multiplierScale;
|
|
eq = eq && negativePrefix == other.negativePrefix;
|
|
eq = eq && negativeSuffix == other.negativeSuffix;
|
|
eq = eq && padPosition == other.padPosition;
|
|
eq = eq && padString == other.padString;
|
|
eq = eq && positivePrefix == other.positivePrefix;
|
|
eq = eq && positiveSuffix == other.positiveSuffix;
|
|
eq = eq && roundingIncrement == other.roundingIncrement;
|
|
eq = eq && roundingMode == other.roundingMode;
|
|
eq = eq && secondaryGroupingSize == other.secondaryGroupingSize;
|
|
eq = eq && signAlwaysShown == other.signAlwaysShown;
|
|
|
|
if (ignoreForFastFormat) {
|
|
return eq;
|
|
}
|
|
|
|
// Properties ignored by fast-path formatting
|
|
// Formatting (special handling required):
|
|
eq = eq && groupingSize == other.groupingSize;
|
|
eq = eq && groupingUsed == other.groupingUsed;
|
|
eq = eq && minimumFractionDigits == other.minimumFractionDigits;
|
|
eq = eq && maximumFractionDigits == other.maximumFractionDigits;
|
|
eq = eq && maximumIntegerDigits == other.maximumIntegerDigits;
|
|
eq = eq && minimumIntegerDigits == other.minimumIntegerDigits;
|
|
eq = eq && negativePrefixPattern == other.negativePrefixPattern;
|
|
eq = eq && negativeSuffixPattern == other.negativeSuffixPattern;
|
|
eq = eq && positivePrefixPattern == other.positivePrefixPattern;
|
|
eq = eq && positiveSuffixPattern == other.positiveSuffixPattern;
|
|
|
|
// Parsing (always safe to ignore):
|
|
eq = eq && decimalPatternMatchRequired == other.decimalPatternMatchRequired;
|
|
eq = eq && parseCaseSensitive == other.parseCaseSensitive;
|
|
eq = eq && parseIntegerOnly == other.parseIntegerOnly;
|
|
eq = eq && parseMode == other.parseMode;
|
|
eq = eq && parseNoExponent == other.parseNoExponent;
|
|
eq = eq && parseToBigDecimal == other.parseToBigDecimal;
|
|
eq = eq && parseAllInput == other.parseAllInput;
|
|
|
|
return eq;
|
|
}
|
|
|
|
bool DecimalFormatProperties::equalsDefaultExceptFastFormat() const {
|
|
UErrorCode localStatus = U_ZERO_ERROR;
|
|
umtx_initOnce(gDefaultPropertiesInitOnce, &initDefaultProperties, localStatus);
|
|
return _equals(*reinterpret_cast<DecimalFormatProperties*>(kRawDefaultProperties), true);
|
|
}
|
|
|
|
const DecimalFormatProperties& DecimalFormatProperties::getDefault() {
|
|
UErrorCode localStatus = U_ZERO_ERROR;
|
|
umtx_initOnce(gDefaultPropertiesInitOnce, &initDefaultProperties, localStatus);
|
|
return *reinterpret_cast<const DecimalFormatProperties*>(kRawDefaultProperties);
|
|
}
|
|
|
|
#endif /* #if !UCONFIG_NO_FORMATTING */
|