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