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 #include "util.h" 22 23 U_NAMESPACE_BEGIN namespace number { 24 namespace impl { 25 26 /** 27 * A copyable container for the integer values of mixed unit measurements. 28 * 29 * If memory allocation fails during copying, no values are copied and status is 30 * set to U_MEMORY_ALLOCATION_ERROR. 31 */ 32 class IntMeasures : public MaybeStackArray<int64_t, 2> { 33 public: 34 /** 35 * Default constructor initializes with internal T[stackCapacity] buffer. 36 * 37 * Stack Capacity: most mixed units are expected to consist of two or three 38 * subunits, so one or two integer measures should be enough. 39 */ IntMeasures()40 IntMeasures() : MaybeStackArray<int64_t, 2>() {} 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 // Currency symbol to be used as the decimal separator 88 UnicodeString currencyAsDecimal = ICU_Utility::makeBogusString(); 89 90 // No ownership: must point at a string which will outlive MicroProps 91 // instances, e.g. a string with static storage duration, or just a string 92 // that will never be deallocated or modified. 93 const char *gender; 94 95 // Note: This struct has no direct ownership of the following pointers. 96 const DecimalFormatSymbols* symbols; 97 98 // Pointers to Modifiers provided by the number formatting pipeline (when 99 // the value is known): 100 101 // A Modifier provided by LongNameHandler, used for currency long names and 102 // units. If there is no LongNameHandler needed, this should be an 103 // EmptyModifier. (This is typically the third modifier applied.) 104 const Modifier* modOuter; 105 // A Modifier for short currencies and compact notation. (This is typically 106 // the second modifier applied.) 107 const Modifier* modMiddle = nullptr; 108 // A Modifier provided by ScientificHandler, used for scientific notation. 109 // This is typically the first modifier applied. 110 const Modifier* modInner; 111 112 // The following "helper" fields may optionally be used during the MicroPropsGenerator. 113 // They live here to retain memory. 114 struct { 115 // The ScientificModifier for which ScientificHandler is responsible. 116 // ScientificHandler::processQuantity() modifies this Modifier. 117 ScientificModifier scientificModifier; 118 // EmptyModifier used for modOuter 119 EmptyModifier emptyWeakModifier{false}; 120 // EmptyModifier used for modInner 121 EmptyModifier emptyStrongModifier{true}; 122 MultiplierFormatHandler multiplier; 123 // A Modifier used for Mixed Units. When formatting mixed units, 124 // LongNameHandler assigns this Modifier. 125 SimpleModifier mixedUnitModifier; 126 } helpers; 127 128 // The MeasureUnit with which the output is represented. May also have 129 // UMEASURE_UNIT_MIXED complexity, in which case mixedMeasures comes into 130 // play. 131 MeasureUnit outputUnit; 132 133 // Contains all the values of each unit in mixed units. For quantity (which is the floating value of 134 // the smallest unit in the mixed unit), the value stores in `quantity`. 135 // NOTE: the value of quantity in `mixedMeasures` will be left unset. 136 IntMeasures mixedMeasures; 137 138 // Points to quantity position, -1 if the position is not set yet. 139 int32_t indexOfQuantity = -1; 140 141 // Number of mixedMeasures that have been populated 142 int32_t mixedMeasuresCount = 0; 143 144 MicroProps() = default; 145 146 MicroProps(const MicroProps& other) = default; 147 148 MicroProps& operator=(const MicroProps& other) = default; 149 150 /** 151 * As MicroProps is the "base instance", this implementation of 152 * MicroPropsGenerator::processQuantity() just ensures that the output 153 * `micros` is correctly initialized. 154 * 155 * For the "safe" invocation of this function, micros must not be *this, 156 * such that a copy of the base instance is made. For the "unsafe" path, 157 * this function can be used only once, because the base MicroProps instance 158 * will be modified and thus not be available for re-use. 159 * 160 * @param quantity The quantity for consideration and optional mutation. 161 * @param micros The MicroProps instance to populate. If this parameter is 162 * not already `*this`, it will be overwritten with a copy of `*this`. 163 */ processQuantityMicroProps164 void processQuantity(DecimalQuantity &quantity, MicroProps µs, 165 UErrorCode &status) const U_OVERRIDE { 166 (void) quantity; 167 (void) status; 168 if (this == µs) { 169 // Unsafe path: no need to perform a copy. 170 U_ASSERT(!exhausted); 171 micros.exhausted = true; 172 U_ASSERT(exhausted); 173 } else { 174 // Safe path: copy self into the output micros. 175 U_ASSERT(!exhausted); 176 micros = *this; 177 } 178 } 179 180 private: 181 // Internal fields: 182 bool exhausted = false; 183 }; 184 185 } // namespace impl 186 } // namespace number 187 U_NAMESPACE_END 188 189 #endif // __NUMBER_MICROPROPS_H__ 190 191 #endif /* #if !UCONFIG_NO_FORMATTING */ 192