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 #ifndef __NUMBER_MICROPROPS_H__ 8 #define __NUMBER_MICROPROPS_H__ 9 10 // TODO: minimize includes 11 #include "unicode/numberformatter.h" 12 #include "number_types.h" 13 #include "number_decimalquantity.h" 14 #include "number_scientific.h" 15 #include "number_patternstring.h" 16 #include "number_modifiers.h" 17 #include "number_multiplier.h" 18 #include "number_roundingutils.h" 19 #include "decNumber.h" 20 #include "charstr.h" 21 22 U_NAMESPACE_BEGIN namespace number { 23 namespace impl { 24 25 /** 26 * A copyable container for the integer values of mixed unit measurements. 27 * 28 * If memory allocation fails during copying, no values are copied and status is 29 * set to U_MEMORY_ALLOCATION_ERROR. 30 */ 31 class IntMeasures : public MaybeStackArray<int64_t, 2> { 32 public: 33 /** 34 * Default constructor initializes with internal T[stackCapacity] buffer. 35 * 36 * Stack Capacity: most mixed units are expected to consist of two or three 37 * subunits, so one or two integer measures should be enough. 38 */ IntMeasures()39 IntMeasures() : MaybeStackArray<int64_t, 2>() { 40 } 41 42 /** 43 * Copy constructor. 44 * 45 * If memory allocation fails during copying, no values are copied and 46 * status is set to U_MEMORY_ALLOCATION_ERROR. 47 */ IntMeasures(const IntMeasures & other)48 IntMeasures(const IntMeasures &other) : MaybeStackArray<int64_t, 2>() { 49 this->operator=(other); 50 } 51 52 // Assignment operator 53 IntMeasures &operator=(const IntMeasures &rhs) { 54 if (this == &rhs) { 55 return *this; 56 } 57 copyFrom(rhs, status); 58 return *this; 59 } 60 61 /** Move constructor */ 62 IntMeasures(IntMeasures &&src) = default; 63 64 /** Move assignment */ 65 IntMeasures &operator=(IntMeasures &&src) = default; 66 67 UErrorCode status = U_ZERO_ERROR; 68 }; 69 70 /** 71 * MicroProps is the first MicroPropsGenerator that should be should be called, 72 * producing an initialized MicroProps instance that will be passed on and 73 * modified throughout the rest of the chain of MicroPropsGenerator instances. 74 */ 75 struct MicroProps : public MicroPropsGenerator { 76 77 // NOTE: All of these fields are properly initialized in NumberFormatterImpl. 78 RoundingImpl rounder; 79 Grouper grouping; 80 Padder padding; 81 IntegerWidth integerWidth; 82 UNumberSignDisplay sign; 83 UNumberDecimalSeparatorDisplay decimal; 84 bool useCurrency; 85 char nsName[9]; 86 87 // Note: This struct has no direct ownership of the following pointers. 88 const DecimalFormatSymbols* symbols; 89 90 // Pointers to Modifiers provided by the number formatting pipeline (when 91 // the value is known): 92 93 // A Modifier provided by LongNameHandler, used for currency long names and 94 // units. If there is no LongNameHandler needed, this should be an 95 // EmptyModifier. (This is typically the third modifier applied.) 96 const Modifier* modOuter; 97 // A Modifier for short currencies and compact notation. (This is typically 98 // the second modifier applied.) 99 const Modifier* modMiddle = nullptr; 100 // A Modifier provided by ScientificHandler, used for scientific notation. 101 // This is typically the first modifier applied. 102 const Modifier* modInner; 103 104 // The following "helper" fields may optionally be used during the MicroPropsGenerator. 105 // They live here to retain memory. 106 struct { 107 // The ScientificModifier for which ScientificHandler is responsible. 108 // ScientificHandler::processQuantity() modifies this Modifier. 109 ScientificModifier scientificModifier; 110 // EmptyModifier used for modOuter 111 EmptyModifier emptyWeakModifier{false}; 112 // EmptyModifier used for modInner 113 EmptyModifier emptyStrongModifier{true}; 114 MultiplierFormatHandler multiplier; 115 // A Modifier used for Mixed Units. When formatting mixed units, 116 // LongNameHandler assigns this Modifier. 117 SimpleModifier mixedUnitModifier; 118 } helpers; 119 120 // The MeasureUnit with which the output is represented. May also have 121 // UMEASURE_UNIT_MIXED complexity, in which case mixedMeasures comes into 122 // play. 123 MeasureUnit outputUnit; 124 125 // In the case of mixed units, this is the set of integer-only units 126 // *preceding* the final unit. 127 IntMeasures mixedMeasures; 128 // Number of mixedMeasures that have been populated 129 int32_t mixedMeasuresCount = 0; 130 131 MicroProps() = default; 132 133 MicroProps(const MicroProps& other) = default; 134 135 MicroProps& operator=(const MicroProps& other) = default; 136 137 /** 138 * As MicroProps is the "base instance", this implementation of 139 * MicroPropsGenerator::processQuantity() just ensures that the output 140 * `micros` is correctly initialized. 141 * 142 * For the "safe" invocation of this function, micros must not be *this, 143 * such that a copy of the base instance is made. For the "unsafe" path, 144 * this function can be used only once, because the base MicroProps instance 145 * will be modified and thus not be available for re-use. 146 * 147 * @param quantity The quantity for consideration and optional mutation. 148 * @param micros The MicroProps instance to populate. If this parameter is 149 * not already `*this`, it will be overwritten with a copy of `*this`. 150 */ processQuantityMicroProps151 void processQuantity(DecimalQuantity &quantity, MicroProps µs, 152 UErrorCode &status) const U_OVERRIDE { 153 (void) quantity; 154 (void) status; 155 if (this == µs) { 156 // Unsafe path: no need to perform a copy. 157 U_ASSERT(!exhausted); 158 micros.exhausted = true; 159 U_ASSERT(exhausted); 160 } else { 161 // Safe path: copy self into the output micros. 162 U_ASSERT(!exhausted); 163 micros = *this; 164 } 165 } 166 167 private: 168 // Internal fields: 169 bool exhausted = false; 170 }; 171 172 } // namespace impl 173 } // namespace number 174 U_NAMESPACE_END 175 176 #endif // __NUMBER_MICROPROPS_H__ 177 178 #endif /* #if !UCONFIG_NO_FORMATTING */ 179