| // © 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 |
| #ifndef __NUMBER_MICROPROPS_H__ |
| #define __NUMBER_MICROPROPS_H__ |
| |
| // TODO: minimize includes |
| #include "unicode/numberformatter.h" |
| #include "number_types.h" |
| #include "number_decimalquantity.h" |
| #include "number_scientific.h" |
| #include "number_patternstring.h" |
| #include "number_modifiers.h" |
| #include "number_multiplier.h" |
| #include "number_roundingutils.h" |
| #include "decNumber.h" |
| #include "charstr.h" |
| |
| U_NAMESPACE_BEGIN namespace number { |
| namespace impl { |
| |
| /** |
| * A copyable container for the integer values of mixed unit measurements. |
| * |
| * If memory allocation fails during copying, no values are copied and status is |
| * set to U_MEMORY_ALLOCATION_ERROR. |
| */ |
| class IntMeasures : public MaybeStackArray<int64_t, 2> { |
| public: |
| /** |
| * Default constructor initializes with internal T[stackCapacity] buffer. |
| * |
| * Stack Capacity: most mixed units are expected to consist of two or three |
| * subunits, so one or two integer measures should be enough. |
| */ |
| IntMeasures() : MaybeStackArray<int64_t, 2>() { |
| } |
| |
| /** |
| * Copy constructor. |
| * |
| * If memory allocation fails during copying, no values are copied and |
| * status is set to U_MEMORY_ALLOCATION_ERROR. |
| */ |
| IntMeasures(const IntMeasures &other) : MaybeStackArray<int64_t, 2>() { |
| this->operator=(other); |
| } |
| |
| // Assignment operator |
| IntMeasures &operator=(const IntMeasures &rhs) { |
| if (this == &rhs) { |
| return *this; |
| } |
| copyFrom(rhs, status); |
| return *this; |
| } |
| |
| /** Move constructor */ |
| IntMeasures(IntMeasures &&src) = default; |
| |
| /** Move assignment */ |
| IntMeasures &operator=(IntMeasures &&src) = default; |
| |
| UErrorCode status = U_ZERO_ERROR; |
| }; |
| |
| /** |
| * MicroProps is the first MicroPropsGenerator that should be should be called, |
| * producing an initialized MicroProps instance that will be passed on and |
| * modified throughout the rest of the chain of MicroPropsGenerator instances. |
| */ |
| struct MicroProps : public MicroPropsGenerator { |
| |
| // NOTE: All of these fields are properly initialized in NumberFormatterImpl. |
| RoundingImpl rounder; |
| Grouper grouping; |
| Padder padding; |
| IntegerWidth integerWidth; |
| UNumberSignDisplay sign; |
| UNumberDecimalSeparatorDisplay decimal; |
| bool useCurrency; |
| char nsName[9]; |
| |
| // Note: This struct has no direct ownership of the following pointers. |
| const DecimalFormatSymbols* symbols; |
| |
| // Pointers to Modifiers provided by the number formatting pipeline (when |
| // the value is known): |
| |
| // A Modifier provided by LongNameHandler, used for currency long names and |
| // units. If there is no LongNameHandler needed, this should be an |
| // EmptyModifier. (This is typically the third modifier applied.) |
| const Modifier* modOuter; |
| // A Modifier for short currencies and compact notation. (This is typically |
| // the second modifier applied.) |
| const Modifier* modMiddle = nullptr; |
| // A Modifier provided by ScientificHandler, used for scientific notation. |
| // This is typically the first modifier applied. |
| const Modifier* modInner; |
| |
| // The following "helper" fields may optionally be used during the MicroPropsGenerator. |
| // They live here to retain memory. |
| struct { |
| // The ScientificModifier for which ScientificHandler is responsible. |
| // ScientificHandler::processQuantity() modifies this Modifier. |
| ScientificModifier scientificModifier; |
| // EmptyModifier used for modOuter |
| EmptyModifier emptyWeakModifier{false}; |
| // EmptyModifier used for modInner |
| EmptyModifier emptyStrongModifier{true}; |
| MultiplierFormatHandler multiplier; |
| // A Modifier used for Mixed Units. When formatting mixed units, |
| // LongNameHandler assigns this Modifier. |
| SimpleModifier mixedUnitModifier; |
| } helpers; |
| |
| // The MeasureUnit with which the output is represented. May also have |
| // UMEASURE_UNIT_MIXED complexity, in which case mixedMeasures comes into |
| // play. |
| MeasureUnit outputUnit; |
| |
| // In the case of mixed units, this is the set of integer-only units |
| // *preceding* the final unit. |
| IntMeasures mixedMeasures; |
| // Number of mixedMeasures that have been populated |
| int32_t mixedMeasuresCount = 0; |
| |
| MicroProps() = default; |
| |
| MicroProps(const MicroProps& other) = default; |
| |
| MicroProps& operator=(const MicroProps& other) = default; |
| |
| /** |
| * As MicroProps is the "base instance", this implementation of |
| * MicroPropsGenerator::processQuantity() just ensures that the output |
| * `micros` is correctly initialized. |
| * |
| * For the "safe" invocation of this function, micros must not be *this, |
| * such that a copy of the base instance is made. For the "unsafe" path, |
| * this function can be used only once, because the base MicroProps instance |
| * will be modified and thus not be available for re-use. |
| * |
| * @param quantity The quantity for consideration and optional mutation. |
| * @param micros The MicroProps instance to populate. If this parameter is |
| * not already `*this`, it will be overwritten with a copy of `*this`. |
| */ |
| void processQuantity(DecimalQuantity &quantity, MicroProps µs, |
| UErrorCode &status) const U_OVERRIDE { |
| (void) quantity; |
| (void) status; |
| if (this == µs) { |
| // Unsafe path: no need to perform a copy. |
| U_ASSERT(!exhausted); |
| micros.exhausted = true; |
| U_ASSERT(exhausted); |
| } else { |
| // Safe path: copy self into the output micros. |
| U_ASSERT(!exhausted); |
| micros = *this; |
| } |
| } |
| |
| private: |
| // Internal fields: |
| bool exhausted = false; |
| }; |
| |
| } // namespace impl |
| } // namespace number |
| U_NAMESPACE_END |
| |
| #endif // __NUMBER_MICROPROPS_H__ |
| |
| #endif /* #if !UCONFIG_NO_FORMATTING */ |