1/*
2*******************************************************************************
3*
4*   Copyright (C) 2009-2012,2014 International Business Machines
5*   Corporation and others.  All Rights Reserved.
6*
7*******************************************************************************
8*   file name:  udatpg.cpp
9*   encoding:   US-ASCII
10*   tab size:   8 (not used)
11*   indentation:4
12*
13*   created on: 2007jul30
14*   created by: Markus W. Scherer
15*/
16
17#include "unicode/utypes.h"
18
19#if !UCONFIG_NO_FORMATTING
20
21#include "unicode/udatpg.h"
22#include "unicode/uenum.h"
23#include "unicode/strenum.h"
24#include "unicode/dtptngen.h"
25#include "ustrenum.h"
26
27U_NAMESPACE_USE
28
29U_CAPI UDateTimePatternGenerator * U_EXPORT2
30udatpg_open(const char *locale, UErrorCode *pErrorCode) {
31    if(locale==NULL) {
32        return (UDateTimePatternGenerator *)DateTimePatternGenerator::createInstance(*pErrorCode);
33    } else {
34        return (UDateTimePatternGenerator *)DateTimePatternGenerator::createInstance(Locale(locale), *pErrorCode);
35    }
36}
37
38U_CAPI UDateTimePatternGenerator * U_EXPORT2
39udatpg_openEmpty(UErrorCode *pErrorCode) {
40    return (UDateTimePatternGenerator *)DateTimePatternGenerator::createEmptyInstance(*pErrorCode);
41}
42
43U_CAPI void U_EXPORT2
44udatpg_close(UDateTimePatternGenerator *dtpg) {
45    delete (DateTimePatternGenerator *)dtpg;
46}
47
48U_CAPI UDateTimePatternGenerator * U_EXPORT2
49udatpg_clone(const UDateTimePatternGenerator *dtpg, UErrorCode *pErrorCode) {
50    if(U_FAILURE(*pErrorCode)) {
51        return NULL;
52    }
53    return (UDateTimePatternGenerator *)(((const DateTimePatternGenerator *)dtpg)->clone());
54}
55
56U_CAPI int32_t U_EXPORT2
57udatpg_getBestPattern(UDateTimePatternGenerator *dtpg,
58                      const UChar *skeleton, int32_t length,
59                      UChar *bestPattern, int32_t capacity,
60                      UErrorCode *pErrorCode) {
61    return udatpg_getBestPatternWithOptions(dtpg, skeleton, length,
62                                            UDATPG_MATCH_NO_OPTIONS,
63                                            bestPattern, capacity, pErrorCode);
64}
65
66U_CAPI int32_t U_EXPORT2
67udatpg_getBestPatternWithOptions(UDateTimePatternGenerator *dtpg,
68                                 const UChar *skeleton, int32_t length,
69                                 UDateTimePatternMatchOptions options,
70                                 UChar *bestPattern, int32_t capacity,
71                                 UErrorCode *pErrorCode) {
72    if(U_FAILURE(*pErrorCode)) {
73        return 0;
74    }
75    if(skeleton==NULL && length!=0) {
76        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
77        return 0;
78    }
79    UnicodeString skeletonString((UBool)(length<0), skeleton, length);
80    UnicodeString result=((DateTimePatternGenerator *)dtpg)->getBestPattern(skeletonString, options, *pErrorCode);
81    return result.extract(bestPattern, capacity, *pErrorCode);
82}
83
84U_CAPI int32_t U_EXPORT2
85udatpg_getSkeleton(UDateTimePatternGenerator *dtpg,
86                   const UChar *pattern, int32_t length,
87                   UChar *skeleton, int32_t capacity,
88                   UErrorCode *pErrorCode) {
89    if(U_FAILURE(*pErrorCode)) {
90        return 0;
91    }
92    if(pattern==NULL && length!=0) {
93        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
94        return 0;
95    }
96    UnicodeString patternString((UBool)(length<0), pattern, length);
97    UnicodeString result=((DateTimePatternGenerator *)dtpg)->getSkeleton(patternString, *pErrorCode);
98    return result.extract(skeleton, capacity, *pErrorCode);
99}
100
101U_CAPI int32_t U_EXPORT2
102udatpg_getBaseSkeleton(UDateTimePatternGenerator *dtpg,
103                       const UChar *pattern, int32_t length,
104                       UChar *skeleton, int32_t capacity,
105                       UErrorCode *pErrorCode) {
106    if(U_FAILURE(*pErrorCode)) {
107        return 0;
108    }
109    if(pattern==NULL && length!=0) {
110        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
111        return 0;
112    }
113    UnicodeString patternString((UBool)(length<0), pattern, length);
114    UnicodeString result=((DateTimePatternGenerator *)dtpg)->getBaseSkeleton(patternString, *pErrorCode);
115    return result.extract(skeleton, capacity, *pErrorCode);
116}
117
118U_CAPI UDateTimePatternConflict U_EXPORT2
119udatpg_addPattern(UDateTimePatternGenerator *dtpg,
120                  const UChar *pattern, int32_t patternLength,
121                  UBool override,
122                  UChar *conflictingPattern, int32_t capacity, int32_t *pLength,
123                  UErrorCode *pErrorCode) {
124    if(U_FAILURE(*pErrorCode)) {
125        return UDATPG_NO_CONFLICT;
126    }
127    if(pattern==NULL && patternLength!=0) {
128        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
129        return UDATPG_NO_CONFLICT;
130    }
131    UnicodeString patternString((UBool)(patternLength<0), pattern, patternLength);
132    UnicodeString conflictingPatternString;
133    UDateTimePatternConflict result=((DateTimePatternGenerator *)dtpg)->
134            addPattern(patternString, override, conflictingPatternString, *pErrorCode);
135    int32_t length=conflictingPatternString.extract(conflictingPattern, capacity, *pErrorCode);
136    if(pLength!=NULL) {
137        *pLength=length;
138    }
139    return result;
140}
141
142U_CAPI void U_EXPORT2
143udatpg_setAppendItemFormat(UDateTimePatternGenerator *dtpg,
144                           UDateTimePatternField field,
145                           const UChar *value, int32_t length) {
146    UnicodeString valueString((UBool)(length<0), value, length);
147    ((DateTimePatternGenerator *)dtpg)->setAppendItemFormat(field, valueString);
148}
149
150U_CAPI const UChar * U_EXPORT2
151udatpg_getAppendItemFormat(const UDateTimePatternGenerator *dtpg,
152                           UDateTimePatternField field,
153                           int32_t *pLength) {
154    const UnicodeString &result=((const DateTimePatternGenerator *)dtpg)->getAppendItemFormat(field);
155    if(pLength!=NULL) {
156        *pLength=result.length();
157    }
158    return result.getBuffer();
159}
160
161U_CAPI void U_EXPORT2
162udatpg_setAppendItemName(UDateTimePatternGenerator *dtpg,
163                         UDateTimePatternField field,
164                         const UChar *value, int32_t length) {
165    UnicodeString valueString((UBool)(length<0), value, length);
166    ((DateTimePatternGenerator *)dtpg)->setAppendItemName(field, valueString);
167}
168
169U_CAPI const UChar * U_EXPORT2
170udatpg_getAppendItemName(const UDateTimePatternGenerator *dtpg,
171                         UDateTimePatternField field,
172                         int32_t *pLength) {
173    const UnicodeString &result=((const DateTimePatternGenerator *)dtpg)->getAppendItemName(field);
174    if(pLength!=NULL) {
175        *pLength=result.length();
176    }
177    return result.getBuffer();
178}
179
180U_CAPI void U_EXPORT2
181udatpg_setDateTimeFormat(const UDateTimePatternGenerator *dtpg,
182                         const UChar *dtFormat, int32_t length) {
183    UnicodeString dtFormatString((UBool)(length<0), dtFormat, length);
184    ((DateTimePatternGenerator *)dtpg)->setDateTimeFormat(dtFormatString);
185}
186
187U_CAPI const UChar * U_EXPORT2
188udatpg_getDateTimeFormat(const UDateTimePatternGenerator *dtpg,
189                         int32_t *pLength) {
190    const UnicodeString &result=((const DateTimePatternGenerator *)dtpg)->getDateTimeFormat();
191    if(pLength!=NULL) {
192        *pLength=result.length();
193    }
194    return result.getBuffer();
195}
196
197U_CAPI void U_EXPORT2
198udatpg_setDecimal(UDateTimePatternGenerator *dtpg,
199                  const UChar *decimal, int32_t length) {
200    UnicodeString decimalString((UBool)(length<0), decimal, length);
201    ((DateTimePatternGenerator *)dtpg)->setDecimal(decimalString);
202}
203
204U_CAPI const UChar * U_EXPORT2
205udatpg_getDecimal(const UDateTimePatternGenerator *dtpg,
206                  int32_t *pLength) {
207    const UnicodeString &result=((const DateTimePatternGenerator *)dtpg)->getDecimal();
208    if(pLength!=NULL) {
209        *pLength=result.length();
210    }
211    return result.getBuffer();
212}
213
214U_CAPI int32_t U_EXPORT2
215udatpg_replaceFieldTypes(UDateTimePatternGenerator *dtpg,
216                         const UChar *pattern, int32_t patternLength,
217                         const UChar *skeleton, int32_t skeletonLength,
218                         UChar *dest, int32_t destCapacity,
219                         UErrorCode *pErrorCode) {
220    return udatpg_replaceFieldTypesWithOptions(dtpg, pattern, patternLength, skeleton, skeletonLength,
221                                               UDATPG_MATCH_NO_OPTIONS,
222                                               dest, destCapacity, pErrorCode);
223}
224
225U_CAPI int32_t U_EXPORT2
226udatpg_replaceFieldTypesWithOptions(UDateTimePatternGenerator *dtpg,
227                                    const UChar *pattern, int32_t patternLength,
228                                    const UChar *skeleton, int32_t skeletonLength,
229                                    UDateTimePatternMatchOptions options,
230                                    UChar *dest, int32_t destCapacity,
231                                    UErrorCode *pErrorCode) {
232    if(U_FAILURE(*pErrorCode)) {
233        return 0;
234    }
235    if((pattern==NULL && patternLength!=0) || (skeleton==NULL && skeletonLength!=0)) {
236        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
237        return 0;
238    }
239    UnicodeString patternString((UBool)(patternLength<0), pattern, patternLength);
240    UnicodeString skeletonString((UBool)(skeletonLength<0), skeleton, skeletonLength);
241    UnicodeString result=((DateTimePatternGenerator *)dtpg)->replaceFieldTypes(patternString, skeletonString, options, *pErrorCode);
242    return result.extract(dest, destCapacity, *pErrorCode);
243}
244
245U_CAPI UEnumeration * U_EXPORT2
246udatpg_openSkeletons(const UDateTimePatternGenerator *dtpg, UErrorCode *pErrorCode) {
247    return uenum_openFromStringEnumeration(
248                ((DateTimePatternGenerator *)dtpg)->getSkeletons(*pErrorCode),
249                pErrorCode);
250}
251
252U_CAPI UEnumeration * U_EXPORT2
253udatpg_openBaseSkeletons(const UDateTimePatternGenerator *dtpg, UErrorCode *pErrorCode) {
254    return uenum_openFromStringEnumeration(
255                ((DateTimePatternGenerator *)dtpg)->getBaseSkeletons(*pErrorCode),
256                pErrorCode);
257}
258
259U_CAPI const UChar * U_EXPORT2
260udatpg_getPatternForSkeleton(const UDateTimePatternGenerator *dtpg,
261                             const UChar *skeleton, int32_t skeletonLength,
262                             int32_t *pLength) {
263    UnicodeString skeletonString((UBool)(skeletonLength<0), skeleton, skeletonLength);
264    const UnicodeString &result=((const DateTimePatternGenerator *)dtpg)->getPatternForSkeleton(skeletonString);
265    if(pLength!=NULL) {
266        *pLength=result.length();
267    }
268    return result.getBuffer();
269}
270
271U_CAPI int32_t U_EXPORT2
272uadatpg_remapPatternWithOptions(UDateTimePatternGenerator *dtpg,
273                                const UChar *pattern, int32_t patternLength,
274                                UDateTimePatternMatchOptions options,
275                                UChar *newPattern, int32_t newPatternCapacity,
276                                UErrorCode *pErrorCode) {
277    if (U_FAILURE(*pErrorCode)) {
278        return 0;
279    }
280    if ( pattern==NULL || ((newPattern==NULL)? newPatternCapacity!=0: newPatternCapacity<0) ) {
281        *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
282        return 0;
283    }
284    UnicodeString patternString((patternLength < 0), pattern, patternLength);
285    UBool force12 = ((options & UADATPG_FORCE_HOUR_CYCLE_MASK) == UADATPG_FORCE_12_HOUR_CYCLE);
286    UBool force24 = ((options & UADATPG_FORCE_HOUR_CYCLE_MASK) == UADATPG_FORCE_24_HOUR_CYCLE);
287    if (force12 || force24) {
288        UBool inQuoted = FALSE;
289        UBool inTimePat = FALSE;
290        UBool needReplacement = FALSE;
291        int32_t timePatStart = 0;
292        int32_t timePatLimit = 0;
293        UnicodeString skeleton;
294        int32_t patPos, patLen = patternString.length();
295        for (patPos = 0; patPos < patLen; patPos++) {
296            UChar patChr = patternString.charAt(patPos);
297            if (patChr == 0x27 /* ASCII-range single quote */) {
298                inQuoted = !inQuoted;
299            } else if (!inQuoted) {
300                if (patChr==0x61 || patChr==0x68 || patChr==0x48 || patChr==0x4B ||
301                    patChr==0x6B || patChr==0x6D || patChr==0x73 || patChr==0x53) { // ahHKkmsS
302                    // in a time pattern
303                    if (!inTimePat) {
304                        inTimePat = TRUE;
305                        timePatStart = patPos;
306                        skeleton.remove();
307                    }
308                    timePatLimit = patPos + 1;
309                    if (force12) {
310                        if (patChr==0x48 || patChr==0x6B) {
311                            patChr = 0x68;
312                            needReplacement = TRUE;
313                        }
314                    } else { // force24
315                        if (patChr==0x68 || patChr==0x4B) {
316                            patChr = 0x48;
317                            needReplacement = TRUE;
318                        }
319                    }
320                    skeleton.append(patChr);
321                } else if ((patChr >= 0x41 && patChr <= 0x5A) || (patChr >= 0x61 && patChr <= 0x7A)) {
322                    // a non-time pattern character, forces end of any time pattern
323                    if (inTimePat) {
324                        inTimePat = FALSE;
325                        if (needReplacement) {
326                            needReplacement = FALSE;
327                            // do replacement
328                            UnicodeString replacement=((DateTimePatternGenerator *)dtpg)->getBestPattern(skeleton, options, *pErrorCode);
329                            patternString.replaceBetween(timePatStart, timePatLimit, replacement);
330                            int32_t posAdjust = replacement.length() - (timePatLimit - timePatStart); // positive if replacement is longer
331                            patLen += posAdjust;
332                            patPos += posAdjust;
333                        }
334                    }
335                }
336            }
337        }
338        // end of string
339        if (inTimePat && needReplacement) {
340            // do replacement
341            UnicodeString replacement=((DateTimePatternGenerator *)dtpg)->getBestPattern(skeleton, options, *pErrorCode);
342            patternString.replaceBetween(timePatStart, timePatLimit, replacement);
343        }
344    }
345    return patternString.extract(newPattern, newPatternCapacity, *pErrorCode);
346}
347
348#endif
349