1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
#include <_foundation_unicode/utypes.h>
#if !UCONFIG_NO_FORMATTING
#ifndef __NUMBER_MICROPROPS_H__
#define __NUMBER_MICROPROPS_H__
// TODO: minimize includes
#include <_foundation_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"
#include "util.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;
};
struct SimpleMicroProps : public UMemory {
Grouper grouping;
bool useCurrency = false;
UNumberDecimalSeparatorDisplay decimal = UNUM_DECIMAL_SEPARATOR_AUTO;
// Currency symbol to be used as the decimal separator
UnicodeString currencyAsDecimal = ICU_Utility::makeBogusString();
// Note: This struct has no direct ownership of the following pointer.
const DecimalFormatSymbols* symbols = nullptr;
};
/**
* 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 {
SimpleMicroProps simple;
// NOTE: All of these fields are properly initialized in NumberFormatterImpl.
RoundingImpl rounder;
Padder padding;
IntegerWidth integerWidth;
UNumberSignDisplay sign;
char nsName[9];
// No ownership: must point at a string which will outlive MicroProps
// instances, e.g. a string with static storage duration, or just a string
// that will never be deallocated or modified.
const char *gender;
// Note: This struct has no direct ownership of the following pointers.
// 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;
// Contains all the values of each unit in mixed units. For quantity (which is the floating value of
// the smallest unit in the mixed unit), the value stores in `quantity`.
// NOTE: the value of quantity in `mixedMeasures` will be left unset.
IntMeasures mixedMeasures;
// Points to quantity position, -1 if the position is not set yet.
int32_t indexOfQuantity = -1;
// 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 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 */
|