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