1/*
2*****************************************************************************************
3* Copyright (C) 2014 Apple Inc. All Rights Reserved.
4*****************************************************************************************
5*/
6
7#include "unicode/utypes.h"
8
9#if !UCONFIG_NO_FORMATTING
10
11#include "unicode/uatimeunitformat.h"
12#include "unicode/fieldpos.h"
13#include "unicode/localpointer.h"
14#include "unicode/numfmt.h"
15#include "unicode/measunit.h"
16#include "unicode/measure.h"
17#include "unicode/measfmt.h"
18#include "unicode/unistr.h"
19#include "unicode/unum.h"
20#include "unicode/ures.h"
21#include "uresimp.h"
22#include "ustr_imp.h"
23
24U_NAMESPACE_USE
25
26
27U_CAPI UATimeUnitFormat* U_EXPORT2
28uatmufmt_open(const char*  locale,
29              UATimeUnitStyle style,
30              UErrorCode*  status)
31{
32    return uatmufmt_openWithNumberFormat(locale, style, NULL, status);
33}
34
35
36U_CAPI UATimeUnitFormat* U_EXPORT2
37uatmufmt_openWithNumberFormat(const char*  locale,
38                            UATimeUnitStyle style,
39                            UNumberFormat*  nfToAdopt,
40                            UErrorCode*  status)
41{
42    if (U_FAILURE(*status)) {
43        return NULL;
44    }
45    UMeasureFormatWidth mfWidth = UMEASFMT_WIDTH_WIDE;
46    switch (style) {
47        case UATIMEUNITSTYLE_FULL:
48            break;
49        case UATIMEUNITSTYLE_ABBREVIATED:
50            mfWidth = UMEASFMT_WIDTH_SHORT; break;
51        case UATIMEUNITSTYLE_NARROW:
52            mfWidth = UMEASFMT_WIDTH_NARROW; break;
53        default:
54            *status = U_ILLEGAL_ARGUMENT_ERROR; return NULL;
55    }
56    LocalPointer<MeasureFormat> mfmt( new MeasureFormat(Locale(locale), mfWidth, (NumberFormat*)nfToAdopt, *status) );
57    if (U_FAILURE(*status)) {
58        return NULL;
59    }
60    return (UATimeUnitFormat*)mfmt.orphan();
61}
62
63
64U_CAPI void U_EXPORT2
65uatmufmt_close(UATimeUnitFormat *mfmt)
66{
67    delete (MeasureFormat*)mfmt;
68}
69
70
71U_CAPI void U_EXPORT2
72uatmufmt_setNumberFormat(UATimeUnitFormat* mfmt,
73                        UNumberFormat*  numfmt,
74                        UErrorCode*     status)
75{
76    if (U_FAILURE(*status)) {
77        return;
78    }
79    ((MeasureFormat*)mfmt)->adoptNumberFormat( (NumberFormat*)(((NumberFormat*)numfmt)->clone()), *status );
80}
81
82
83U_CAPI int32_t U_EXPORT2
84uatmufmt_format(const UATimeUnitFormat* mfmt,
85                double          value,
86                UATimeUnitField field,
87                UChar*          result,
88                int32_t         resultCapacity,
89                UErrorCode*     status)
90{
91    if (U_FAILURE(*status)) {
92        return 0;
93    }
94    if ( ((result==NULL)? resultCapacity!=0: resultCapacity<0) ) {
95        *status = U_ILLEGAL_ARGUMENT_ERROR;
96        return 0;
97    }
98    MeasureUnit * munit = NULL;
99    switch (field) {
100        case UATIMEUNITFIELD_YEAR:    munit = MeasureUnit::createYear(*status);    break;
101        case UATIMEUNITFIELD_MONTH:   munit = MeasureUnit::createMonth(*status);   break;
102        case UATIMEUNITFIELD_DAY:     munit = MeasureUnit::createDay(*status);     break;
103        case UATIMEUNITFIELD_WEEK:    munit = MeasureUnit::createWeek(*status);    break;
104        case UATIMEUNITFIELD_HOUR:    munit = MeasureUnit::createHour(*status);    break;
105        case UATIMEUNITFIELD_MINUTE:  munit = MeasureUnit::createMinute(*status);  break;
106        case UATIMEUNITFIELD_SECOND:  munit = MeasureUnit::createSecond(*status);  break;
107        default: *status = U_ILLEGAL_ARGUMENT_ERROR; break;
108    }
109    if (U_FAILURE(*status)) {
110        return 0;
111    }
112    LocalPointer<Measure> meas(new Measure(value, munit, *status));
113    if (U_FAILURE(*status)) {
114        return 0;
115    }
116    Formattable fmt;
117    fmt.adoptObject(meas.orphan());
118    UnicodeString res;
119    res.setTo(result, 0, resultCapacity);
120    FieldPosition pos(0);
121    ((MeasureFormat*)mfmt)->format(fmt, res, pos, *status);
122    return res.extract(result, resultCapacity, *status);
123}
124
125
126U_CAPI double U_EXPORT2
127uatmufmt_parse( const UATimeUnitFormat* mfmt,
128                const UChar*    text,
129                int32_t         textLength,
130                int32_t*        parsePos,
131                UATimeUnitField* field,
132                UErrorCode*     status)
133{
134    double doubleVal = 0.0;
135    if (U_FAILURE(*status)) {
136        return doubleVal;
137    }
138    *status = U_UNSUPPORTED_ERROR;
139    return doubleVal;
140}
141
142
143U_CAPI int32_t U_EXPORT2
144uatmufmt_getTimePattern(const char*     locale,
145                        UATimeUnitTimePattern type,
146                        UChar*          result,
147                        int32_t         resultCapacity,
148                        UErrorCode*     status)
149{
150    if (U_FAILURE(*status)) {
151        return 0;
152    }
153    if ( (result==NULL)? resultCapacity!=0: resultCapacity<0 ) {
154        *status = U_ILLEGAL_ARGUMENT_ERROR;
155        return 0;
156    }
157    const char* key = NULL;
158    switch (type) {
159        case UATIMEUNITTIMEPAT_HM:  { key = "hm"; break; }
160        case UATIMEUNITTIMEPAT_HMS: { key = "hms"; break; }
161        case UATIMEUNITTIMEPAT_MS:  { key = "ms"; break; }
162        default: { *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; }
163    }
164    int32_t resLen = 0;
165    const UChar* resPtr = NULL;
166    UResourceBundle* rb =  ures_open(NULL, locale, status);
167    rb = ures_getByKeyWithFallback(rb, "durationUnits", rb, status);
168    resPtr = ures_getStringByKeyWithFallback(rb, key, &resLen, status);
169    if (U_SUCCESS(*status)) {
170        u_strncpy(result, resPtr, resultCapacity);
171    }
172    ures_close(rb);
173    return u_terminateUChars(result, resultCapacity, resLen, status);
174}
175
176
177U_CAPI int32_t U_EXPORT2
178uatmufmt_getListPattern(const char*     locale,
179                        UATimeUnitStyle style,
180                        UATimeUnitListPattern type,
181                        UChar*          result,
182                        int32_t         resultCapacity,
183                        UErrorCode*     status)
184{
185    if (U_FAILURE(*status)) {
186        return 0;
187    }
188    if ( (result==NULL)? resultCapacity!=0: resultCapacity<0 ) {
189        *status = U_ILLEGAL_ARGUMENT_ERROR;
190        return 0;
191    }
192    const char* styleKey = NULL;
193    switch (style) {
194        case UATIMEUNITSTYLE_FULL:          { styleKey = "unit"; break; }
195        case UATIMEUNITSTYLE_ABBREVIATED:   { styleKey = "unit-short"; break; }
196        case UATIMEUNITSTYLE_NARROW:        { styleKey = "unit-narrow"; break; }
197        default: { *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; }
198    }
199    const char* typeKey = NULL;
200    switch (type) {
201        case UATIMEUNITLISTPAT_TWO_ONLY:        { typeKey = "2"; break; }
202        case UATIMEUNITLISTPAT_END_PIECE:       { typeKey = "end"; break; }
203        case UATIMEUNITLISTPAT_MIDDLE_PIECE:    { typeKey = "middle"; break; }
204        case UATIMEUNITLISTPAT_START_PIECE:     { typeKey = "start"; break; }
205        default: { *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; }
206    }
207    int32_t resLen = 0;
208    const UChar* resPtr = NULL;
209    UResourceBundle* rb =  ures_open(NULL, locale, status);
210    rb = ures_getByKeyWithFallback(rb, "listPattern", rb, status);
211    rb = ures_getByKeyWithFallback(rb, styleKey, rb, status);
212    resPtr = ures_getStringByKeyWithFallback(rb, typeKey, &resLen, status);
213    if (U_SUCCESS(*status)) {
214        u_strncpy(result, resPtr, resultCapacity);
215    }
216    ures_close(rb);
217    return u_terminateUChars(result, resultCapacity, resLen, status);
218}
219
220
221#endif /* #if !UCONFIG_NO_FORMATTING */
222