1 // © 2022 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3
4 #ifndef __FORMATTEDNUMBER_H__
5 #define __FORMATTEDNUMBER_H__
6
7 #include "unicode/utypes.h"
8
9 #if U_SHOW_CPLUSPLUS_API
10
11 #if !UCONFIG_NO_FORMATTING
12
13 #include "unicode/uobject.h"
14 #include "unicode/formattedvalue.h"
15 #include "unicode/measunit.h"
16 #include "unicode/udisplayoptions.h"
17
18 /**
19 * \file
20 * \brief C API: Formatted number result from various number formatting functions.
21 *
22 * See also {@link icu::FormattedValue} for additional things you can do with a FormattedNumber.
23 */
24
25 U_NAMESPACE_BEGIN
26
27 class FieldPositionIteratorHandler;
28 class SimpleDateFormat;
29
30 namespace number { // icu::number
31
32 namespace impl {
33 class DecimalQuantity;
34 class UFormattedNumberData;
35 struct UFormattedNumberImpl;
36 } // icu::number::impl
37
38
39
40 /**
41 * The result of a number formatting operation. This class allows the result to be exported in several data types,
42 * including a UnicodeString and a FieldPositionIterator.
43 *
44 * Instances of this class are immutable and thread-safe.
45 *
46 * @stable ICU 60
47 */
48 class U_I18N_API FormattedNumber : public UMemory, public FormattedValue {
49 public:
50
51 /**
52 * Default constructor; makes an empty FormattedNumber.
53 * @stable ICU 64
54 */
FormattedNumber()55 FormattedNumber()
56 : fData(nullptr), fErrorCode(U_INVALID_STATE_ERROR) {}
57
58 /**
59 * Move constructor: Leaves the source FormattedNumber in an undefined state.
60 * @stable ICU 62
61 */
62 FormattedNumber(FormattedNumber&& src) noexcept;
63
64 /**
65 * Destruct an instance of FormattedNumber.
66 * @stable ICU 60
67 */
68 virtual ~FormattedNumber() override;
69
70 /** Copying not supported; use move constructor instead. */
71 FormattedNumber(const FormattedNumber&) = delete;
72
73 /** Copying not supported; use move assignment instead. */
74 FormattedNumber& operator=(const FormattedNumber&) = delete;
75
76 /**
77 * Move assignment: Leaves the source FormattedNumber in an undefined state.
78 * @stable ICU 62
79 */
80 FormattedNumber& operator=(FormattedNumber&& src) noexcept;
81
82 // Copybrief: this method is older than the parent method
83 /**
84 * @copybrief FormattedValue::toString()
85 *
86 * For more information, see FormattedValue::toString()
87 *
88 * @stable ICU 62
89 */
90 UnicodeString toString(UErrorCode& status) const override;
91
92 // Copydoc: this method is new in ICU 64
93 /** @copydoc FormattedValue::toTempString() */
94 UnicodeString toTempString(UErrorCode& status) const override;
95
96 // Copybrief: this method is older than the parent method
97 /**
98 * @copybrief FormattedValue::appendTo()
99 *
100 * For more information, see FormattedValue::appendTo()
101 *
102 * @stable ICU 62
103 */
104 Appendable &appendTo(Appendable& appendable, UErrorCode& status) const override;
105
106 // Copydoc: this method is new in ICU 64
107 /** @copydoc FormattedValue::nextPosition() */
108 UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const override;
109
110 /**
111 * Export the formatted number as a "numeric string" conforming to the
112 * syntax defined in the Decimal Arithmetic Specification, available at
113 * http://speleotrove.com/decimal
114 *
115 * This endpoint is useful for obtaining the exact number being printed
116 * after scaling and rounding have been applied by the number formatter.
117 *
118 * Example call site:
119 *
120 * auto decimalNumber = fn.toDecimalNumber<std::string>(status);
121 *
122 * @tparam StringClass A string class compatible with StringByteSink;
123 * for example, std::string.
124 * @param status Set if an error occurs.
125 * @return A StringClass containing the numeric string.
126 * @stable ICU 65
127 */
128 template<typename StringClass>
129 inline StringClass toDecimalNumber(UErrorCode& status) const;
130
131 /**
132 * Gets the resolved output unit.
133 *
134 * The output unit is dependent upon the localized preferences for the usage
135 * specified via NumberFormatterSettings::usage(), and may be a unit with
136 * UMEASURE_UNIT_MIXED unit complexity (MeasureUnit::getComplexity()), such
137 * as "foot-and-inch" or "hour-and-minute-and-second".
138 *
139 * @return `MeasureUnit`.
140 * @stable ICU 68
141 */
142 MeasureUnit getOutputUnit(UErrorCode& status) const;
143
144 /**
145 * Gets the noun class of the formatted output. Returns `UNDEFINED` when the noun class
146 * is not supported yet.
147 *
148 * @return UDisplayOptionsNounClass
149 * @stable ICU 72
150 */
151 UDisplayOptionsNounClass getNounClass(UErrorCode &status) const;
152
153 #ifndef U_HIDE_INTERNAL_API
154
155 /**
156 * Gets the raw DecimalQuantity for plural rule selection.
157 * @internal
158 */
159 void getDecimalQuantity(impl::DecimalQuantity& output, UErrorCode& status) const;
160
161 /**
162 * Populates the mutable builder type FieldPositionIteratorHandler.
163 * @internal
164 */
165 void getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih, UErrorCode& status) const;
166
167 #endif /* U_HIDE_INTERNAL_API */
168
169 private:
170 // Can't use LocalPointer because UFormattedNumberData is forward-declared
171 impl::UFormattedNumberData *fData;
172
173 // Error code for the terminal methods
174 UErrorCode fErrorCode;
175
176 /**
177 * Internal constructor from data type. Adopts the data pointer.
178 * @internal (private)
179 */
FormattedNumber(impl::UFormattedNumberData * results)180 explicit FormattedNumber(impl::UFormattedNumberData *results)
181 : fData(results), fErrorCode(U_ZERO_ERROR) {}
182
FormattedNumber(UErrorCode errorCode)183 explicit FormattedNumber(UErrorCode errorCode)
184 : fData(nullptr), fErrorCode(errorCode) {}
185
186 void toDecimalNumber(ByteSink& sink, UErrorCode& status) const;
187
188 // To give LocalizedNumberFormatter format methods access to this class's constructor:
189 friend class LocalizedNumberFormatter;
190 friend class SimpleNumberFormatter;
191
192 // To give C API access to internals
193 friend struct impl::UFormattedNumberImpl;
194
195 // To give access to the data pointer for non-heap allocation
196 friend class icu::SimpleDateFormat;
197 };
198
199 template<typename StringClass>
toDecimalNumber(UErrorCode & status)200 StringClass FormattedNumber::toDecimalNumber(UErrorCode& status) const {
201 StringClass result;
202 StringByteSink<StringClass> sink(&result);
203 toDecimalNumber(sink, status);
204 return result;
205 }
206
207 } // namespace number
208 U_NAMESPACE_END
209
210 #endif /* #if !UCONFIG_NO_FORMATTING */
211
212 #endif /* U_SHOW_CPLUSPLUS_API */
213
214 #endif // __FORMATTEDNUMBER_H__
215
216