1// Copyright (C) 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/*
4**********************************************************************
5* Copyright (c) 2004-2016, International Business Machines
6* Corporation and others.  All Rights Reserved.
7**********************************************************************
8* Author: Alan Liu
9* Created: April 20, 2004
10* Since: ICU 3.0
11**********************************************************************
12*/
13#ifndef MEASUREFORMAT_H
14#define MEASUREFORMAT_H
15
16#include "unicode/utypes.h"
17
18#if !UCONFIG_NO_FORMATTING
19
20#include "unicode/format.h"
21#include "unicode/udat.h"
22
23/**
24 * \file
25 * \brief C++ API: Formatter for measure objects.
26 */
27
28/**
29 * Constants for various widths.
30 * There are 4 widths: Wide, Short, Narrow, Numeric.
31 * For example, for English, when formatting "3 hours"
32 * Wide is "3 hours"; short is "3 hrs"; narrow is "3h";
33 * formatting "3 hours 17 minutes" as numeric give "3:17"
34 * @stable ICU 53
35 */
36enum UMeasureFormatWidth {
37
38    // Wide, short, and narrow must be first and in this order.
39    /**
40     * Spell out measure units.
41     * @stable ICU 53
42     */
43    UMEASFMT_WIDTH_WIDE,
44
45    /**
46     * Abbreviate measure units.
47     * @stable ICU 53
48     */
49    UMEASFMT_WIDTH_SHORT,
50
51    /**
52     * Use symbols for measure units when possible.
53     * @stable ICU 53
54     */
55    UMEASFMT_WIDTH_NARROW,
56
57    /**
58     * Completely omit measure units when possible. For example, format
59     * '5 hours, 37 minutes' as '5:37'
60     * @stable ICU 53
61     */
62    UMEASFMT_WIDTH_NUMERIC,
63
64#ifndef U_HIDE_DEPRECATED_API
65    /**
66     * One more than the highest normal UMeasureFormatWidth value.
67     * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
68     */
69    UMEASFMT_WIDTH_COUNT = 4
70#endif  // U_HIDE_DEPRECATED_API
71};
72/** @stable ICU 53 */
73typedef enum UMeasureFormatWidth UMeasureFormatWidth;
74
75U_NAMESPACE_BEGIN
76
77class Measure;
78class MeasureUnit;
79class NumberFormat;
80class PluralRules;
81class MeasureFormatCacheData;
82class SharedNumberFormat;
83class SharedPluralRules;
84class QuantityFormatter;
85class SimpleFormatter;
86class ListFormatter;
87class DateFormat;
88
89/**
90 *
91 * A formatter for measure objects.
92 *
93 * @see Format
94 * @author Alan Liu
95 * @stable ICU 3.0
96 */
97class U_I18N_API MeasureFormat : public Format {
98 public:
99    using Format::parseObject;
100    using Format::format;
101
102    /**
103     * Constructor.
104     * @stable ICU 53
105     */
106    MeasureFormat(
107            const Locale &locale, UMeasureFormatWidth width, UErrorCode &status);
108
109    /**
110     * Constructor.
111     * @stable ICU 53
112     */
113    MeasureFormat(
114            const Locale &locale,
115            UMeasureFormatWidth width,
116            NumberFormat *nfToAdopt,
117            UErrorCode &status);
118
119    /**
120     * Copy constructor.
121     * @stable ICU 3.0
122     */
123    MeasureFormat(const MeasureFormat &other);
124
125    /**
126     * Assignment operator.
127     * @stable ICU 3.0
128     */
129    MeasureFormat &operator=(const MeasureFormat &rhs);
130
131    /**
132     * Destructor.
133     * @stable ICU 3.0
134     */
135    virtual ~MeasureFormat();
136
137    /**
138     * Return true if given Format objects are semantically equal.
139     * @stable ICU 53
140     */
141    virtual UBool operator==(const Format &other) const;
142
143    /**
144     * Clones this object polymorphically.
145     * @stable ICU 53
146     */
147    virtual Format *clone() const;
148
149    /**
150     * Formats object to produce a string.
151     * @stable ICU 53
152     */
153    virtual UnicodeString &format(
154            const Formattable &obj,
155            UnicodeString &appendTo,
156            FieldPosition &pos,
157            UErrorCode &status) const;
158
159    /**
160     * Parse a string to produce an object. This implementation sets
161     * status to U_UNSUPPORTED_ERROR.
162     *
163     * @draft ICU 53
164     */
165    virtual void parseObject(
166            const UnicodeString &source,
167            Formattable &reslt,
168            ParsePosition &pos) const;
169
170    /**
171     * Formats measure objects to produce a string. An example of such a
172     * formatted string is 3 meters, 3.5 centimeters. Measure objects appear
173     * in the formatted string in the same order they appear in the "measures"
174     * array. The NumberFormat of this object is used only to format the amount
175     * of the very last measure. The other amounts are formatted with zero
176     * decimal places while rounding toward zero.
177     * @param measures array of measure objects.
178     * @param measureCount the number of measure objects.
179     * @param appendTo formatted string appended here.
180     * @param pos the field position.
181     * @param status the error.
182     * @return appendTo reference
183     *
184     * @stable ICU 53
185     */
186    UnicodeString &formatMeasures(
187            const Measure *measures,
188            int32_t measureCount,
189            UnicodeString &appendTo,
190            FieldPosition &pos,
191            UErrorCode &status) const;
192
193    /**
194     * Formats a single measure per unit. An example of such a
195     * formatted string is 3.5 meters per second.
196     * @param measure The measure object. In above example, 3.5 meters.
197     * @param perUnit The per unit. In above example, it is
198     *        *MeasureUnit::createSecond(status).
199     * @param appendTo formatted string appended here.
200     * @param pos the field position.
201     * @param status the error.
202     * @return appendTo reference
203     *
204     * @stable ICU 55
205     */
206    UnicodeString &formatMeasurePerUnit(
207            const Measure &measure,
208            const MeasureUnit &perUnit,
209            UnicodeString &appendTo,
210            FieldPosition &pos,
211            UErrorCode &status) const;
212
213#ifndef U_HIDE_DRAFT_API
214    /**
215     * Gets the display name of the specified {@link MeasureUnit} corresponding to the current
216     * locale and format width.
217     * @param unit  The unit for which to get a display name.
218     * @param status the error.
219     * @return  The display name in the locale and width specified in
220     *          {@link MeasureFormat#getInstance}, or null if there is no display name available
221     *          for the specified unit.
222     *
223     * @draft ICU 58
224     */
225    UnicodeString getUnitDisplayName(const MeasureUnit& unit, UErrorCode &status) const;
226#endif /* U_HIDE_DRAFT_API */
227
228
229    /**
230     * Return a formatter for CurrencyAmount objects in the given
231     * locale.
232     * @param locale desired locale
233     * @param ec input-output error code
234     * @return a formatter object, or NULL upon error
235     * @stable ICU 3.0
236     */
237    static MeasureFormat* U_EXPORT2 createCurrencyFormat(const Locale& locale,
238                                               UErrorCode& ec);
239
240    /**
241     * Return a formatter for CurrencyAmount objects in the default
242     * locale.
243     * @param ec input-output error code
244     * @return a formatter object, or NULL upon error
245     * @stable ICU 3.0
246     */
247    static MeasureFormat* U_EXPORT2 createCurrencyFormat(UErrorCode& ec);
248
249    /**
250     * Return the class ID for this class. This is useful only for comparing to
251     * a return value from getDynamicClassID(). For example:
252     * <pre>
253     * .   Base* polymorphic_pointer = createPolymorphicObject();
254     * .   if (polymorphic_pointer->getDynamicClassID() ==
255     * .       erived::getStaticClassID()) ...
256     * </pre>
257     * @return          The class ID for all objects of this class.
258     * @stable ICU 53
259     */
260    static UClassID U_EXPORT2 getStaticClassID(void);
261
262    /**
263     * Returns a unique class ID POLYMORPHICALLY. Pure virtual override. This
264     * method is to implement a simple version of RTTI, since not all C++
265     * compilers support genuine RTTI. Polymorphic operator==() and clone()
266     * methods call this method.
267     *
268     * @return          The class ID for this object. All objects of a
269     *                  given class have the same class ID.  Objects of
270     *                  other classes have different class IDs.
271     * @stable ICU 53
272     */
273    virtual UClassID getDynamicClassID(void) const;
274
275 protected:
276    /**
277     * Default constructor.
278     * @stable ICU 3.0
279     */
280    MeasureFormat();
281
282#ifndef U_HIDE_INTERNAL_API
283
284    /**
285     * ICU use only.
286     * Initialize or change MeasureFormat class from subclass.
287     * @internal.
288     */
289    void initMeasureFormat(
290            const Locale &locale,
291            UMeasureFormatWidth width,
292            NumberFormat *nfToAdopt,
293            UErrorCode &status);
294    /**
295     * ICU use only.
296     * Allows subclass to change locale. Note that this method also changes
297     * the NumberFormat object. Returns TRUE if locale changed; FALSE if no
298     * change was made.
299     * @internal.
300     */
301    UBool setMeasureFormatLocale(const Locale &locale, UErrorCode &status);
302
303    /**
304     * ICU use only.
305     * Let subclass change NumberFormat.
306     * @internal.
307     */
308    void adoptNumberFormat(NumberFormat *nfToAdopt, UErrorCode &status);
309
310    /**
311     * ICU use only.
312     * @internal.
313     */
314    const NumberFormat &getNumberFormat() const;
315
316    /**
317     * ICU use only.
318     * @internal.
319     */
320    const PluralRules &getPluralRules() const;
321
322    /**
323     * ICU use only.
324     * @internal.
325     */
326    Locale getLocale(UErrorCode &status) const;
327
328    /**
329     * ICU use only.
330     * @internal.
331     */
332    const char *getLocaleID(UErrorCode &status) const;
333
334#endif /* U_HIDE_INTERNAL_API */
335
336 private:
337    const MeasureFormatCacheData *cache;
338    const SharedNumberFormat *numberFormat;
339    const SharedPluralRules *pluralRules;
340    UMeasureFormatWidth width;
341
342    // Declared outside of MeasureFormatSharedData because ListFormatter
343    // objects are relatively cheap to copy; therefore, they don't need to be
344    // shared across instances.
345    ListFormatter *listFormatter;
346
347    const SimpleFormatter *getFormatterOrNull(
348            const MeasureUnit &unit, UMeasureFormatWidth width, int32_t index) const;
349
350    const SimpleFormatter *getFormatter(
351            const MeasureUnit &unit, UMeasureFormatWidth width, int32_t index,
352            UErrorCode &errorCode) const;
353
354    const SimpleFormatter *getPluralFormatter(
355            const MeasureUnit &unit, UMeasureFormatWidth width, int32_t index,
356            UErrorCode &errorCode) const;
357
358    const SimpleFormatter *getPerFormatter(
359            UMeasureFormatWidth width,
360            UErrorCode &status) const;
361
362    int32_t withPerUnitAndAppend(
363        const UnicodeString &formatted,
364        const MeasureUnit &perUnit,
365        UnicodeString &appendTo,
366        UErrorCode &status) const;
367
368    UnicodeString &formatMeasure(
369        const Measure &measure,
370        const NumberFormat &nf,
371        UnicodeString &appendTo,
372        FieldPosition &pos,
373        UErrorCode &status) const;
374
375    UnicodeString &formatMeasuresSlowTrack(
376        const Measure *measures,
377        int32_t measureCount,
378        UnicodeString& appendTo,
379        FieldPosition& pos,
380        UErrorCode& status) const;
381
382    UnicodeString &formatNumeric(
383        const Formattable *hms,  // always length 3: [0] is hour; [1] is
384                                 // minute; [2] is second.
385        int32_t bitMap,   // 1=hour set, 2=minute set, 4=second set
386        UnicodeString &appendTo,
387        UErrorCode &status) const;
388
389    UnicodeString &formatNumeric(
390        UDate date,
391        const DateFormat &dateFmt,
392        UDateFormatField smallestField,
393        const Formattable &smallestAmount,
394        UnicodeString &appendTo,
395        UErrorCode &status) const;
396};
397
398U_NAMESPACE_END
399
400#endif // #if !UCONFIG_NO_FORMATTING
401#endif // #ifndef MEASUREFORMAT_H
402