1 // © 2017 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 4 #include "unicode/utypes.h" 5 6 #if !UCONFIG_NO_FORMATTING 7 8 #include "number_decimfmtprops.h" 9 #include "umutex.h" 10 11 using namespace icu; 12 using namespace icu::number; 13 using namespace icu::number::impl; 14 15 16 namespace { 17 18 alignas(DecimalFormatProperties) 19 char kRawDefaultProperties[sizeof(DecimalFormatProperties)]; 20 21 icu::UInitOnce gDefaultPropertiesInitOnce {}; 22 initDefaultProperties(UErrorCode &)23void U_CALLCONV initDefaultProperties(UErrorCode&) { 24 // can't fail, uses placement new into statically allocated space. 25 new(kRawDefaultProperties) DecimalFormatProperties(); // set to the default instance 26 } 27 28 } 29 30 DecimalFormatProperties()31DecimalFormatProperties::DecimalFormatProperties() { 32 clear(); 33 } 34 clear()35void DecimalFormatProperties::clear() { 36 compactStyle.nullify(); 37 currency.nullify(); 38 currencyPluralInfo.fPtr.adoptInstead(nullptr); 39 currencyUsage.nullify(); 40 decimalPatternMatchRequired = false; 41 decimalSeparatorAlwaysShown = false; 42 exponentSignAlwaysShown = false; 43 currencyAsDecimal = false; 44 formatFailIfMoreThanMaxDigits = false; 45 formatWidth = -1; 46 groupingSize = -1; 47 groupingUsed = true; 48 magnitudeMultiplier = 0; 49 maximumFractionDigits = -1; 50 maximumIntegerDigits = -1; 51 maximumSignificantDigits = -1; 52 minimumExponentDigits = -1; 53 minimumFractionDigits = -1; 54 minimumGroupingDigits = -1; 55 minimumIntegerDigits = -1; 56 minimumSignificantDigits = -1; 57 multiplier = 1; 58 multiplierScale = 0; 59 negativePrefix.setToBogus(); 60 negativePrefixPattern.setToBogus(); 61 negativeSuffix.setToBogus(); 62 negativeSuffixPattern.setToBogus(); 63 padPosition.nullify(); 64 padString.setToBogus(); 65 parseCaseSensitive = false; 66 parseIntegerOnly = false; 67 parseMode.nullify(); 68 parseNoExponent = false; 69 parseToBigDecimal = false; 70 parseAllInput = UNUM_MAYBE; 71 positivePrefix.setToBogus(); 72 positivePrefixPattern.setToBogus(); 73 positiveSuffix.setToBogus(); 74 positiveSuffixPattern.setToBogus(); 75 roundingIncrement = 0.0; 76 roundingMode.nullify(); 77 secondaryGroupingSize = -1; 78 signAlwaysShown = false; 79 } 80 81 bool _equals(const DecimalFormatProperties & other,bool ignoreForFastFormat) const82DecimalFormatProperties::_equals(const DecimalFormatProperties& other, bool ignoreForFastFormat) const { 83 bool eq = true; 84 85 // Properties that must be equal both normally and for fast-path formatting 86 eq = eq && compactStyle == other.compactStyle; 87 eq = eq && currency == other.currency; 88 eq = eq && currencyPluralInfo.fPtr.getAlias() == other.currencyPluralInfo.fPtr.getAlias(); 89 eq = eq && currencyUsage == other.currencyUsage; 90 eq = eq && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown; 91 eq = eq && exponentSignAlwaysShown == other.exponentSignAlwaysShown; 92 eq = eq && currencyAsDecimal == other.currencyAsDecimal; 93 eq = eq && formatFailIfMoreThanMaxDigits == other.formatFailIfMoreThanMaxDigits; 94 eq = eq && formatWidth == other.formatWidth; 95 eq = eq && magnitudeMultiplier == other.magnitudeMultiplier; 96 eq = eq && maximumSignificantDigits == other.maximumSignificantDigits; 97 eq = eq && minimumExponentDigits == other.minimumExponentDigits; 98 eq = eq && minimumGroupingDigits == other.minimumGroupingDigits; 99 eq = eq && minimumSignificantDigits == other.minimumSignificantDigits; 100 eq = eq && multiplier == other.multiplier; 101 eq = eq && multiplierScale == other.multiplierScale; 102 eq = eq && negativePrefix == other.negativePrefix; 103 eq = eq && negativeSuffix == other.negativeSuffix; 104 eq = eq && padPosition == other.padPosition; 105 eq = eq && padString == other.padString; 106 eq = eq && positivePrefix == other.positivePrefix; 107 eq = eq && positiveSuffix == other.positiveSuffix; 108 eq = eq && roundingIncrement == other.roundingIncrement; 109 eq = eq && roundingMode == other.roundingMode; 110 eq = eq && secondaryGroupingSize == other.secondaryGroupingSize; 111 eq = eq && signAlwaysShown == other.signAlwaysShown; 112 113 if (ignoreForFastFormat) { 114 return eq; 115 } 116 117 // Properties ignored by fast-path formatting 118 // Formatting (special handling required): 119 eq = eq && groupingSize == other.groupingSize; 120 eq = eq && groupingUsed == other.groupingUsed; 121 eq = eq && minimumFractionDigits == other.minimumFractionDigits; 122 eq = eq && maximumFractionDigits == other.maximumFractionDigits; 123 eq = eq && maximumIntegerDigits == other.maximumIntegerDigits; 124 eq = eq && minimumIntegerDigits == other.minimumIntegerDigits; 125 eq = eq && negativePrefixPattern == other.negativePrefixPattern; 126 eq = eq && negativeSuffixPattern == other.negativeSuffixPattern; 127 eq = eq && positivePrefixPattern == other.positivePrefixPattern; 128 eq = eq && positiveSuffixPattern == other.positiveSuffixPattern; 129 130 // Parsing (always safe to ignore): 131 eq = eq && decimalPatternMatchRequired == other.decimalPatternMatchRequired; 132 eq = eq && parseCaseSensitive == other.parseCaseSensitive; 133 eq = eq && parseIntegerOnly == other.parseIntegerOnly; 134 eq = eq && parseMode == other.parseMode; 135 eq = eq && parseNoExponent == other.parseNoExponent; 136 eq = eq && parseToBigDecimal == other.parseToBigDecimal; 137 eq = eq && parseAllInput == other.parseAllInput; 138 139 return eq; 140 } 141 equalsDefaultExceptFastFormat() const142bool DecimalFormatProperties::equalsDefaultExceptFastFormat() const { 143 UErrorCode localStatus = U_ZERO_ERROR; 144 umtx_initOnce(gDefaultPropertiesInitOnce, &initDefaultProperties, localStatus); 145 return _equals(*reinterpret_cast<DecimalFormatProperties*>(kRawDefaultProperties), true); 146 } 147 getDefault()148const DecimalFormatProperties& DecimalFormatProperties::getDefault() { 149 UErrorCode localStatus = U_ZERO_ERROR; 150 umtx_initOnce(gDefaultPropertiesInitOnce, &initDefaultProperties, localStatus); 151 return *reinterpret_cast<const DecimalFormatProperties*>(kRawDefaultProperties); 152 } 153 154 #endif /* #if !UCONFIG_NO_FORMATTING */ 155