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