164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// Copyright (C) 2016 and later: Unicode, Inc. and others.
264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
58de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert* Copyright (C) 2007-2016, International Business Machines Corporation and
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* others. All Rights Reserved.
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* File DTPTNGEN.CPP
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/datefmt.h"
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/decimfmt.h"
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/dtfmtsym.h"
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/dtptngen.h"
218de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#include "unicode/simpleformatter.h"
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/smpdtfmt.h"
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/udat.h"
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/udatpg.h"
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/uniset.h"
26b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/uloc.h"
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ures.h"
28b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/ustring.h"
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/rep.h"
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cpputils.h"
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "mutex.h"
328de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#include "umutex.h"
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "locbased.h"
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "hash.h"
378de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#include "uhash.h"
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uresimp.h"
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "dtptngen_impl.h"
408de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#include "ucln_in.h"
418de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#include "charstr.h"
4264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert#include "uassert.h"
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
44c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#if U_CHARSET_FAMILY==U_EBCDIC_FAMILY
45c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru/**
46b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * If we are on EBCDIC, use an iterator which will
47c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * traverse the bundles in ASCII order.
48c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru */
49c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#define U_USE_ASCII_BUNDLE_ITERATOR
50c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#define U_SORT_ASCII_BUNDLE_ITERATOR
51c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
52c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
53c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#if defined(U_USE_ASCII_BUNDLE_ITERATOR)
54c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
55c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "unicode/ustring.h"
56c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "uarrsort.h"
57c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
58c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustruct UResAEntry {
59c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UChar *key;
60c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UResourceBundle *item;
61c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru};
62c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
63c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustruct UResourceBundleAIterator {
64c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UResourceBundle  *bund;
65c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UResAEntry *entries;
66c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t num;
67c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t cursor;
68c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru};
69c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
70b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* Must be C linkage to pass function pointer to the sort function */
71b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
72103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CDECL_BEGIN
73103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
7450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int32_t U_CALLCONV
75c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruures_a_codepointSort(const void *context, const void *left, const void *right) {
76c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    //CompareContext *cmp=(CompareContext *)context;
77c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return u_strcmp(((const UResAEntry *)left)->key,
78c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    ((const UResAEntry *)right)->key);
79c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
80c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
81103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CDECL_END
82c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
83c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic void ures_a_open(UResourceBundleAIterator *aiter, UResourceBundle *bund, UErrorCode *status) {
84c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(U_FAILURE(*status)) {
85c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
86c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
87c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    aiter->bund = bund;
88c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    aiter->num = ures_getSize(aiter->bund);
89c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    aiter->cursor = 0;
90c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#if !defined(U_SORT_ASCII_BUNDLE_ITERATOR)
91c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    aiter->entries = NULL;
92c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#else
93c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    aiter->entries = (UResAEntry*)uprv_malloc(sizeof(UResAEntry)*aiter->num);
94c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for(int i=0;i<aiter->num;i++) {
95c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        aiter->entries[i].item = ures_getByIndex(aiter->bund, i, NULL, status);
96c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        const char *akey = ures_getKey(aiter->entries[i].item);
97c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t len = uprv_strlen(akey)+1;
98c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        aiter->entries[i].key = (UChar*)uprv_malloc(len*sizeof(UChar));
99c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        u_charsToUChars(akey, aiter->entries[i].key, len);
100c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
101c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    uprv_sortArray(aiter->entries, aiter->num, sizeof(UResAEntry), ures_a_codepointSort, NULL, TRUE, status);
102c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
103c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
104c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
105c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic void ures_a_close(UResourceBundleAIterator *aiter) {
106c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#if defined(U_SORT_ASCII_BUNDLE_ITERATOR)
107c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for(int i=0;i<aiter->num;i++) {
108c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        uprv_free(aiter->entries[i].key);
109c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        ures_close(aiter->entries[i].item);
110c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
111c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
112c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
113c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
114c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic const UChar *ures_a_getNextString(UResourceBundleAIterator *aiter, int32_t *len, const char **key, UErrorCode *err) {
115c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#if !defined(U_SORT_ASCII_BUNDLE_ITERATOR)
116c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return ures_getNextString(aiter->bund, len, key, err);
117c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#else
118c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(U_FAILURE(*err)) return NULL;
119c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UResourceBundle *item = aiter->entries[aiter->cursor].item;
120c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const UChar* ret = ures_getString(item, len, err);
121c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    *key = ures_getKey(item);
122c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    aiter->cursor++;
123c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return ret;
124c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#endif
125c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
126c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// *****************************************************************************
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// class DateTimePatternGenerator
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// *****************************************************************************
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar Canonical_Items[] = {
13727f654740f2a26ad62a5c155af9199af9e69b889claireho    // GyQMwWEdDFHmsSv
13827f654740f2a26ad62a5c155af9199af9e69b889claireho    CAP_G, LOW_Y, CAP_Q, CAP_M, LOW_W, CAP_W, CAP_E, LOW_D, CAP_D, CAP_F,
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CAP_H, LOW_M, LOW_S, CAP_S, LOW_V, 0
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const dtTypeElem dtTypes[] = {
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // patternChar, field, type, minLen, weight
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_G, UDATPG_ERA_FIELD, DT_SHORT, 1, 3,},
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_G, UDATPG_ERA_FIELD, DT_LONG, 4, 0},
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_Y, UDATPG_YEAR_FIELD, DT_NUMERIC, 1, 20},
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_Y, UDATPG_YEAR_FIELD, DT_NUMERIC + DT_DELTA, 1, 20},
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_U, UDATPG_YEAR_FIELD, DT_NUMERIC + 2*DT_DELTA, 1, 20},
149fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    {LOW_R, UDATPG_YEAR_FIELD, DT_NUMERIC + 3*DT_DELTA, 1, 20},
150103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    {CAP_U, UDATPG_YEAR_FIELD, DT_SHORT, 1, 3},
151103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    {CAP_U, UDATPG_YEAR_FIELD, DT_LONG, 4, 0},
152103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    {CAP_U, UDATPG_YEAR_FIELD, DT_NARROW, 5, 0},
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_Q, UDATPG_QUARTER_FIELD, DT_NUMERIC, 1, 2},
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_Q, UDATPG_QUARTER_FIELD, DT_SHORT, 3, 0},
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_Q, UDATPG_QUARTER_FIELD, DT_LONG, 4, 0},
156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {LOW_Q, UDATPG_QUARTER_FIELD, DT_NUMERIC + DT_DELTA, 1, 2},
157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {LOW_Q, UDATPG_QUARTER_FIELD, DT_SHORT + DT_DELTA, 3, 0},
158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {LOW_Q, UDATPG_QUARTER_FIELD, DT_LONG + DT_DELTA, 4, 0},
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_M, UDATPG_MONTH_FIELD, DT_NUMERIC, 1, 2},
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_M, UDATPG_MONTH_FIELD, DT_SHORT, 3, 0},
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_M, UDATPG_MONTH_FIELD, DT_LONG, 4, 0},
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_M, UDATPG_MONTH_FIELD, DT_NARROW, 5, 0},
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_L, UDATPG_MONTH_FIELD, DT_NUMERIC + DT_DELTA, 1, 2},
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_L, UDATPG_MONTH_FIELD, DT_SHORT - DT_DELTA, 3, 0},
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_L, UDATPG_MONTH_FIELD, DT_LONG - DT_DELTA, 4, 0},
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_L, UDATPG_MONTH_FIELD, DT_NARROW - DT_DELTA, 5, 0},
167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {LOW_L, UDATPG_MONTH_FIELD, DT_NUMERIC + DT_DELTA, 1, 1},
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_W, UDATPG_WEEK_OF_YEAR_FIELD, DT_NUMERIC, 1, 2},
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_W, UDATPG_WEEK_OF_MONTH_FIELD, DT_NUMERIC + DT_DELTA, 1, 0},
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_E, UDATPG_WEEKDAY_FIELD, DT_SHORT, 1, 3},
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_E, UDATPG_WEEKDAY_FIELD, DT_LONG, 4, 0},
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_E, UDATPG_WEEKDAY_FIELD, DT_NARROW, 5, 0},
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_C, UDATPG_WEEKDAY_FIELD, DT_NUMERIC + 2*DT_DELTA, 1, 2},
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_C, UDATPG_WEEKDAY_FIELD, DT_SHORT - 2*DT_DELTA, 3, 0},
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_C, UDATPG_WEEKDAY_FIELD, DT_LONG - 2*DT_DELTA, 4, 0},
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_C, UDATPG_WEEKDAY_FIELD, DT_NARROW - 2*DT_DELTA, 5, 0},
17727f654740f2a26ad62a5c155af9199af9e69b889claireho    {LOW_E, UDATPG_WEEKDAY_FIELD, DT_NUMERIC + DT_DELTA, 1, 2}, // LOW_E is currently not used in CLDR data, should not be canonical
17827f654740f2a26ad62a5c155af9199af9e69b889claireho    {LOW_E, UDATPG_WEEKDAY_FIELD, DT_SHORT - DT_DELTA, 3, 0},
17927f654740f2a26ad62a5c155af9199af9e69b889claireho    {LOW_E, UDATPG_WEEKDAY_FIELD, DT_LONG - DT_DELTA, 4, 0},
18027f654740f2a26ad62a5c155af9199af9e69b889claireho    {LOW_E, UDATPG_WEEKDAY_FIELD, DT_NARROW - DT_DELTA, 5, 0},
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_D, UDATPG_DAY_FIELD, DT_NUMERIC, 1, 2},
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_D, UDATPG_DAY_OF_YEAR_FIELD, DT_NUMERIC + DT_DELTA, 1, 3},
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_F, UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD, DT_NUMERIC + 2*DT_DELTA, 1, 0},
184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {LOW_G, UDATPG_DAY_FIELD, DT_NUMERIC + 3*DT_DELTA, 1, 20}, // really internal use, so we don't care
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_A, UDATPG_DAYPERIOD_FIELD, DT_SHORT, 1, 0},
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_H, UDATPG_HOUR_FIELD, DT_NUMERIC + 10*DT_DELTA, 1, 2}, // 24 hour
18759d709d503bab6e2b61931737e662dd293b40578ccornelius    {LOW_K, UDATPG_HOUR_FIELD, DT_NUMERIC + 11*DT_DELTA, 1, 2}, // 24 hour
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_H, UDATPG_HOUR_FIELD, DT_NUMERIC, 1, 2}, // 12 hour
18959d709d503bab6e2b61931737e662dd293b40578ccornelius    {CAP_K, UDATPG_HOUR_FIELD, DT_NUMERIC + DT_DELTA, 1, 2}, // 12 hour
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_M, UDATPG_MINUTE_FIELD, DT_NUMERIC, 1, 2},
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_S, UDATPG_SECOND_FIELD, DT_NUMERIC, 1, 2},
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_S, UDATPG_FRACTIONAL_SECOND_FIELD, DT_NUMERIC + DT_DELTA, 1, 1000},
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_A, UDATPG_SECOND_FIELD, DT_NUMERIC + 2*DT_DELTA, 1, 1000},
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_V, UDATPG_ZONE_FIELD, DT_SHORT - 2*DT_DELTA, 1, 0},
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_V, UDATPG_ZONE_FIELD, DT_LONG - 2*DT_DELTA, 4, 0},
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_Z, UDATPG_ZONE_FIELD, DT_SHORT, 1, 3},
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {LOW_Z, UDATPG_ZONE_FIELD, DT_LONG, 4, 0},
19859d709d503bab6e2b61931737e662dd293b40578ccornelius    {CAP_Z, UDATPG_ZONE_FIELD, DT_NARROW - DT_DELTA, 1, 3},
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {CAP_Z, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 4, 0},
20059d709d503bab6e2b61931737e662dd293b40578ccornelius    {CAP_Z, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 5, 0},
20159d709d503bab6e2b61931737e662dd293b40578ccornelius    {CAP_O, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 1, 0},
20259d709d503bab6e2b61931737e662dd293b40578ccornelius    {CAP_O, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 4, 0},
20359d709d503bab6e2b61931737e662dd293b40578ccornelius    {CAP_V, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 1, 0},
20459d709d503bab6e2b61931737e662dd293b40578ccornelius    {CAP_V, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 2, 0},
20559d709d503bab6e2b61931737e662dd293b40578ccornelius    {CAP_X, UDATPG_ZONE_FIELD, DT_NARROW - DT_DELTA, 1, 0},
20659d709d503bab6e2b61931737e662dd293b40578ccornelius    {CAP_X, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 2, 0},
20759d709d503bab6e2b61931737e662dd293b40578ccornelius    {CAP_X, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 4, 0},
20859d709d503bab6e2b61931737e662dd293b40578ccornelius    {LOW_X, UDATPG_ZONE_FIELD, DT_NARROW - DT_DELTA, 1, 0},
20959d709d503bab6e2b61931737e662dd293b40578ccornelius    {LOW_X, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 2, 0},
21059d709d503bab6e2b61931737e662dd293b40578ccornelius    {LOW_X, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 4, 0},
2118de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    {LOW_J, UDATPG_HOUR_FIELD, DT_NUMERIC, 1, 2}, // 12/24 hour
2128de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    {CAP_J, UDATPG_HOUR_FIELD, DT_NUMERIC, 1, 2}, // 12/24 hour no AM/PM
213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    {0, UDATPG_FIELD_COUNT, 0, 0, 0} , // last row of dtTypes[]
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru };
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
216c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic const char* const CLDR_FIELD_APPEND[] = {
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "Era", "Year", "Quarter", "Month", "Week", "*", "Day-Of-Week", "Day", "*", "*", "*",
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "Hour", "Minute", "Second", "*", "Timezone"
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
221c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic const char* const CLDR_FIELD_NAME[] = {
22259d709d503bab6e2b61931737e662dd293b40578ccornelius    "era", "year", "quarter", "month", "week", "*", "weekday", "*", "*", "day", "dayperiod",
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    "hour", "minute", "second", "*", "zone"
224b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru};
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// For appendItems
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar UDATPG_ItemFormat[]= {0x7B, 0x30, 0x7D, 0x20, 0x251C, 0x7B, 0x32, 0x7D, 0x3A,
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    0x20, 0x7B, 0x31, 0x7D, 0x2524, 0};  // {0} \u251C{2}: {1}\u2524
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
23054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//static const UChar repeatedPatterns[6]={CAP_G, CAP_E, LOW_Z, LOW_V, CAP_Q, 0}; // "GEzvQ"
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char DT_DateTimePatternsTag[]="DateTimePatterns";
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char DT_DateTimeCalendarTag[]="calendar";
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char DT_DateTimeGregorianTag[]="gregorian";
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char DT_DateTimeAppendItemsTag[]="appendItems";
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char DT_DateTimeFieldsTag[]="fields";
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char DT_DateTimeAvailableFormatsTag[]="availableFormats";
238c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru//static const UnicodeString repeatedPattern=UnicodeString(repeatedPatterns);
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateTimePatternGenerator)
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(DTSkeletonEnumeration)
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(DTRedundantEnumeration)
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator*  U_EXPORT2
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::createInstance(UErrorCode& status) {
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return createInstance(Locale::getDefault(), status);
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator* U_EXPORT2
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::createInstance(const Locale& locale, UErrorCode& status) {
251c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (U_FAILURE(status)) {
2521b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        return NULL;
253c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
254c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    LocalPointer<DateTimePatternGenerator> result(
255c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            new DateTimePatternGenerator(locale, status), status);
256c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    return U_SUCCESS(status) ? result.orphan() : NULL;
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator*  U_EXPORT2
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::createEmptyInstance(UErrorCode& status) {
261c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    DateTimePatternGenerator *result = new DateTimePatternGenerator(status);
262c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (result == NULL) {
263c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
264c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
265c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (U_FAILURE(status)) {
266c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete result;
267c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        result = NULL;
268c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
269c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return result;
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
272b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruDateTimePatternGenerator::DateTimePatternGenerator(UErrorCode &status) :
273c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    skipMatcher(NULL),
274c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fAvailableFormatKeyHash(NULL)
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fp = new FormatParser();
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dtMatcher = new DateTimeMatcher();
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    distanceInfo = new DistanceInfo();
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    patternMap = new PatternMap();
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fp == NULL || dtMatcher == NULL || distanceInfo == NULL || patternMap == NULL) {
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
285c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateTimePatternGenerator::DateTimePatternGenerator(const Locale& locale, UErrorCode &status) :
286c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    skipMatcher(NULL),
287c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fAvailableFormatKeyHash(NULL)
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fp = new FormatParser();
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dtMatcher = new DateTimeMatcher();
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    distanceInfo = new DistanceInfo();
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    patternMap = new PatternMap();
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fp == NULL || dtMatcher == NULL || distanceInfo == NULL || patternMap == NULL) {
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
297c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        initData(locale, status);
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruDateTimePatternGenerator::DateTimePatternGenerator(const DateTimePatternGenerator& other) :
302c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UObject(),
303c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    skipMatcher(NULL),
304c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    fAvailableFormatKeyHash(NULL)
305c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fp = new FormatParser();
307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    dtMatcher = new DateTimeMatcher();
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    distanceInfo = new DistanceInfo();
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    patternMap = new PatternMap();
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *this=other;
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator&
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::operator=(const DateTimePatternGenerator& other) {
3151b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // reflexive case
3161b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    if (&other == this) {
3171b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        return *this;
3181b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLocale = other.pLocale;
320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    fDefaultHourFormatChar = other.fDefaultHourFormatChar;
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *fp = *(other.fp);
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dtMatcher->copyFrom(other.dtMatcher->skeleton);
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *distanceInfo = *(other.distanceInfo);
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dateTimeFormat = other.dateTimeFormat;
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    decimal = other.decimal;
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // NUL-terminate for the C API.
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dateTimeFormat.getTerminatedBuffer();
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    decimal.getTerminatedBuffer();
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete skipMatcher;
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ( other.skipMatcher == NULL ) {
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        skipMatcher = NULL;
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        skipMatcher = new DateTimeMatcher(*other.skipMatcher);
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=0; i< UDATPG_FIELD_COUNT; ++i ) {
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        appendItemFormats[i] = other.appendItemFormats[i];
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        appendItemNames[i] = other.appendItemNames[i];
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // NUL-terminate for the C API.
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        appendItemFormats[i].getTerminatedBuffer();
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        appendItemNames[i].getTerminatedBuffer();
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
343c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
344c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    patternMap->copyFrom(*other.patternMap, status);
345c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    copyHashtable(other.fAvailableFormatKeyHash, status);
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::operator==(const DateTimePatternGenerator& other) const {
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (this == &other) {
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((pLocale==other.pLocale) && (patternMap->equals(*other.patternMap)) &&
356b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        (dateTimeFormat==other.dateTimeFormat) && (decimal==other.decimal)) {
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for ( int32_t i=0 ; i<UDATPG_FIELD_COUNT; ++i ) {
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           if ((appendItemFormats[i] != other.appendItemFormats[i]) ||
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               (appendItemNames[i] != other.appendItemNames[i]) ) {
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               return FALSE;
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           }
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::operator!=(const DateTimePatternGenerator& other) const {
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return  !operator==(other);
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::~DateTimePatternGenerator() {
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fAvailableFormatKeyHash!=NULL) {
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete fAvailableFormatKeyHash;
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
379b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
380b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (fp != NULL) delete fp;
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (dtMatcher != NULL) delete dtMatcher;
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (distanceInfo != NULL) delete distanceInfo;
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (patternMap != NULL) delete patternMap;
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (skipMatcher != NULL) delete skipMatcher;
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
3878de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubertnamespace {
3888de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
3898de051c3d18a56cc126f0f44e368495a52f9148cFredrik RoubertUInitOnce initOnce = U_INITONCE_INITIALIZER;
3908de051c3d18a56cc126f0f44e368495a52f9148cFredrik RoubertUHashtable *localeToAllowedHourFormatsMap = NULL;
3918de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
3928de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert// Value deleter for hashmap.
39364339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertU_CFUNC void U_CALLCONV deleteAllowedHourFormats(void *ptr) {
3948de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    uprv_free(ptr);
3958de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert}
3968de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
3978de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert// Close hashmap at cleanup.
39864339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertU_CFUNC UBool U_CALLCONV allowedHourFormatsCleanup() {
3998de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    uhash_close(localeToAllowedHourFormatsMap);
4008de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    return TRUE;
4018de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert}
4028de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
4038de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubertenum AllowedHourFormat{
4048de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    ALLOWED_HOUR_FORMAT_UNKNOWN = -1,
4058de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    ALLOWED_HOUR_FORMAT_h,
4068de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    ALLOWED_HOUR_FORMAT_H,
4078de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    ALLOWED_HOUR_FORMAT_hb,
4088de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    ALLOWED_HOUR_FORMAT_Hb,
4098de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    ALLOWED_HOUR_FORMAT_hB,
4108de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    ALLOWED_HOUR_FORMAT_HB
4118de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert};
4128de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
4138de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert}  // namespace
4148de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
416c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateTimePatternGenerator::initData(const Locale& locale, UErrorCode &status) {
417b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    //const char *baseLangName = locale.getBaseName(); // unused
418b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    skipMatcher = NULL;
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fAvailableFormatKeyHash=NULL;
42164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    addCanonicalItems(status);
422c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    addICUPatterns(locale, status);
4236d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru    addCLDRData(locale, status);
424c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setDateTimeFromCalendar(locale, status);
425c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    setDecimalSymbols(locale, status);
4268de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    umtx_initOnce(initOnce, loadAllowedHourFormatsData, status);
4278de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    getAllowedHourFormats(locale, status);
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} // DateTimePatternGenerator::initData
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
4308de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubertnamespace {
4318de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
43264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertstruct AllowedHourFormatsSink : public ResourceSink {
4338de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    // Initialize sub-sinks.
43464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    AllowedHourFormatsSink() {}
4358de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    virtual ~AllowedHourFormatsSink();
4368de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
43764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    virtual void put(const char *key, ResourceValue &value, UBool /*noFallback*/,
43864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                     UErrorCode &errorCode) {
43964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        ResourceTable timeData = value.getTable(errorCode);
44064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if (U_FAILURE(errorCode)) { return; }
44164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        for (int32_t i = 0; timeData.getKeyAndValue(i, key, value); ++i) {
44264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            const char *regionOrLocale = key;
44364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            ResourceTable formatList = value.getTable(errorCode);
44464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            if (U_FAILURE(errorCode)) { return; }
44564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            for (int32_t j = 0; formatList.getKeyAndValue(j, key, value); ++j) {
44664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                if (uprv_strcmp(key, "allowed") == 0) {  // Ignore "preferred" list.
44764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    LocalMemory<int32_t> list;
44864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    int32_t length;
44964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    if (value.getType() == URES_STRING) {
45064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                        if (list.allocateInsteadAndReset(2) == NULL) {
45164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                            errorCode = U_MEMORY_ALLOCATION_ERROR;
45264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                            return;
45364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                        }
45464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                        list[0] = getHourFormatFromUnicodeString(value.getUnicodeString(errorCode));
45564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                        length = 1;
45664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    }
45764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    else {
45864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                        ResourceArray allowedFormats = value.getArray(errorCode);
45964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                        length = allowedFormats.getSize();
46064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                        if (list.allocateInsteadAndReset(length + 1) == NULL) {
46164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                            errorCode = U_MEMORY_ALLOCATION_ERROR;
46264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                            return;
46364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                        }
46464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                        for (int32_t k = 0; k < length; ++k) {
46564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                            allowedFormats.getValue(k, value);
46664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                            list[k] = getHourFormatFromUnicodeString(value.getUnicodeString(errorCode));
46764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                        }
46864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    }
46964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    list[length] = ALLOWED_HOUR_FORMAT_UNKNOWN;
47064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    uhash_put(localeToAllowedHourFormatsMap,
47164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                              const_cast<char *>(regionOrLocale), list.orphan(), &errorCode);
47264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    if (U_FAILURE(errorCode)) { return; }
4738de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                }
4748de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            }
4758de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        }
47664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    }
4778de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
4788de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    AllowedHourFormat getHourFormatFromUnicodeString(UnicodeString s) {
4798de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        if (s.length() == 1) {
4808de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            if (s[0] == LOW_H) { return ALLOWED_HOUR_FORMAT_h; }
4818de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            if (s[0] == CAP_H) { return ALLOWED_HOUR_FORMAT_H; }
4828de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        } else if (s.length() == 2) {
4838de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            if (s[0] == LOW_H && s[1] == LOW_B) { return ALLOWED_HOUR_FORMAT_hb; }
4848de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            if (s[0] == CAP_H && s[1] == LOW_B) { return ALLOWED_HOUR_FORMAT_Hb; }
4858de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            if (s[0] == LOW_H && s[1] == CAP_B) { return ALLOWED_HOUR_FORMAT_hB; }
4868de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            if (s[0] == CAP_H && s[1] == CAP_B) { return ALLOWED_HOUR_FORMAT_HB; }
4878de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        }
4888de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
4898de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        return ALLOWED_HOUR_FORMAT_UNKNOWN;
4908de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    }
4918de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert};
4928de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
4938de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert}  // namespace
4948de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
4958de051c3d18a56cc126f0f44e368495a52f9148cFredrik RoubertAllowedHourFormatsSink::~AllowedHourFormatsSink() {}
4968de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
49764339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertU_CFUNC void U_CALLCONV DateTimePatternGenerator::loadAllowedHourFormatsData(UErrorCode &status) {
4988de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (U_FAILURE(status)) { return; }
4998de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    localeToAllowedHourFormatsMap = uhash_open(
5008de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        uhash_hashChars, uhash_compareChars, NULL, &status);
5018de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    uhash_setValueDeleter(localeToAllowedHourFormatsMap, deleteAllowedHourFormats);
5028de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    LocalUResourceBundlePointer rb(ures_openDirect(NULL, "supplementalData", &status));
5038de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
5048de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    AllowedHourFormatsSink sink;
5058de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    // TODO: Currently in the enumeration each table allocates a new array.
5068de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    // Try to reduce the number of memory allocations. Consider storing a
5078de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    // UVector32 with the concatenation of all of the sub-arrays, put the start index
5088de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    // into the hashmap, store 6 single-value sub-arrays right at the beginning of the
5098de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    // vector (at index enum*2) for easy data sharing, copy sub-arrays into runtime
5108de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    // object. Remember to clean up the vector, too.
51164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    ures_getAllItemsWithFallback(rb.getAlias(), "timeData", sink, status);
5128de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
5138de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    ucln_i18n_registerCleanup(UCLN_I18N_ALLOWED_HOUR_FORMATS, allowedHourFormatsCleanup);
5148de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert}
5158de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
5168de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubertvoid DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErrorCode &status) {
5178de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (U_FAILURE(status)) { return; }
5188de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    const char *localeID = locale.getName();
5198de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    char maxLocaleID[ULOC_FULLNAME_CAPACITY];
5208de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    int32_t length = uloc_addLikelySubtags(localeID, maxLocaleID, ULOC_FULLNAME_CAPACITY, &status);
5218de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (U_FAILURE(status)) {
5228de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        return;
5238de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    } else if (length == ULOC_FULLNAME_CAPACITY) {  // no room for NUL
5248de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        status = U_BUFFER_OVERFLOW_ERROR;
5258de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        return;
5268de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    }
5278de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    Locale maxLocale = Locale(maxLocaleID);
5288de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
5298de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    const char *country = maxLocale.getCountry();
5308de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (*country == '\0') { country = "001"; }
5318de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    const char *language = maxLocale.getLanguage();
5328de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
5338de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    CharString langCountry;
5348de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    langCountry.append(language, uprv_strlen(language), status);
5358de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    langCountry.append('_', status);
5368de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    langCountry.append(country, uprv_strlen(country), status);
5378de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
5388de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    int32_t *allowedFormats;
5398de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    allowedFormats = (int32_t *)uhash_get(localeToAllowedHourFormatsMap, langCountry.data());
5408de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (allowedFormats == NULL) {
5418de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        allowedFormats = (int32_t *)uhash_get(localeToAllowedHourFormatsMap, const_cast<char *>(country));
5428de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    }
5438de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
5448de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    if (allowedFormats != NULL) {  // Lookup is successful
5458de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        for (int32_t i = 0; i < UPRV_LENGTHOF(fAllowedHourFormats); ++i) {
5468de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            fAllowedHourFormats[i] = allowedFormats[i];
5478de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            if (allowedFormats[i] == ALLOWED_HOUR_FORMAT_UNKNOWN) {
5488de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                break;
5498de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            }
5508de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        }
5518de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    } else {  // Lookup failed, twice
5528de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        fAllowedHourFormats[0] = ALLOWED_HOUR_FORMAT_H;
5538de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        fAllowedHourFormats[1] = ALLOWED_HOUR_FORMAT_UNKNOWN;
5548de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    }
5558de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert}
5568de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
5578de051c3d18a56cc126f0f44e368495a52f9148cFredrik RoubertUnicodeString
5588de051c3d18a56cc126f0f44e368495a52f9148cFredrik RoubertDateTimePatternGenerator::getSkeleton(const UnicodeString& pattern, UErrorCode&
5598de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert/*status*/) {
5608de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    FormatParser fp;
5618de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    DateTimeMatcher matcher;
5628de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    PtnSkeleton localSkeleton;
5638de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    matcher.set(pattern, &fp, localSkeleton);
5648de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    return localSkeleton.getSkeleton();
5658de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert}
5668de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString
568c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDateTimePatternGenerator::staticGetSkeleton(
569c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        const UnicodeString& pattern, UErrorCode& /*status*/) {
570c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    FormatParser fp;
571c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    DateTimeMatcher matcher;
572c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    PtnSkeleton localSkeleton;
573c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    matcher.set(pattern, &fp, localSkeleton);
574c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    return localSkeleton.getSkeleton();
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString
5788de051c3d18a56cc126f0f44e368495a52f9148cFredrik RoubertDateTimePatternGenerator::getBaseSkeleton(const UnicodeString& pattern, UErrorCode& /*status*/) {
5798de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    FormatParser fp;
5808de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    DateTimeMatcher matcher;
5818de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    PtnSkeleton localSkeleton;
5828de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    matcher.set(pattern, &fp, localSkeleton);
5838de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    return localSkeleton.getBaseSkeleton();
5848de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert}
5858de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
5868de051c3d18a56cc126f0f44e368495a52f9148cFredrik RoubertUnicodeString
587c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertDateTimePatternGenerator::staticGetBaseSkeleton(
588c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        const UnicodeString& pattern, UErrorCode& /*status*/) {
589c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    FormatParser fp;
590c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    DateTimeMatcher matcher;
591c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    PtnSkeleton localSkeleton;
592c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    matcher.set(pattern, &fp, localSkeleton);
593c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    return localSkeleton.getBaseSkeleton();
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::addICUPatterns(const Locale& locale, UErrorCode& status) {
59864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (U_FAILURE(status)) { return; }
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString dfPattern;
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString conflictingString;
601c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    DateFormat* df;
602c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Load with ICU patterns
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=DateFormat::kFull; i<=DateFormat::kShort; i++) {
605c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        DateFormat::EStyle style = (DateFormat::EStyle)i;
606c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        df = DateFormat::createDateInstance(style, locale);
60727f654740f2a26ad62a5c155af9199af9e69b889claireho        SimpleDateFormat* sdf;
60827f654740f2a26ad62a5c155af9199af9e69b889claireho        if (df != NULL && (sdf = dynamic_cast<SimpleDateFormat*>(df)) != NULL) {
60964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            sdf->toPattern(dfPattern);
61064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            addPattern(dfPattern, FALSE, conflictingString, status);
611c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
612c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // TODO Maybe we should return an error when the date format isn't simple.
613c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete df;
61464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if (U_FAILURE(status)) { return; }
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
616c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        df = DateFormat::createTimeInstance(style, locale);
61727f654740f2a26ad62a5c155af9199af9e69b889claireho        if (df != NULL && (sdf = dynamic_cast<SimpleDateFormat*>(df)) != NULL) {
61864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            sdf->toPattern(dfPattern);
61964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            addPattern(dfPattern, FALSE, conflictingString, status);
62064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
62164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            // TODO: C++ and Java are inconsistent (see #12568).
62264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            // C++ uses MEDIUM, but Java uses SHORT.
62364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            if ( i==DateFormat::kShort && !dfPattern.isEmpty() ) {
62464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                consumeShortTimePattern(dfPattern, status);
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
627c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // TODO Maybe we should return an error when the date format isn't simple.
628c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete df;
62964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if (U_FAILURE(status)) { return; }
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::hackTimes(const UnicodeString& hackPattern, UErrorCode& status)  {
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString conflictingString;
636b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fp->set(hackPattern);
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString mmss;
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool gotMm=FALSE;
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=0; i<fp->itemNumber; ++i) {
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UnicodeString field = fp->items[i];
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( fp->isQuoteLiteral(field) ) {
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ( gotMm ) {
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               UnicodeString quoteLiteral;
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               fp->getQuoteLiteral(quoteLiteral, &i);
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               mmss += quoteLiteral;
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (fp->isPatternSeparator(field) && gotMm) {
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                mmss+=field;
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else {
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UChar ch=field.charAt(0);
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (ch==LOW_M) {
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    gotMm=TRUE;
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    mmss+=field;
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                else {
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (ch==LOW_S) {
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (!gotMm) {
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            break;
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        mmss+= field;
665103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                        addPattern(mmss, FALSE, conflictingString, status);
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    else {
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        if (gotMm || ch==LOW_Z || ch==CAP_Z || ch==LOW_V || ch==CAP_V) {
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            break;
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
679b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define ULOC_LOCALE_IDENTIFIER_CAPACITY (ULOC_FULLNAME_CAPACITY + 1 + ULOC_KEYWORD_AND_VALUES_CAPACITY)
680b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
681b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const UChar hourFormatChars[] = { CAP_H, LOW_H, CAP_K, LOW_K, 0 }; // HhKk, the hour format characters
682b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
68464339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDateTimePatternGenerator::getCalendarTypeToUse(const Locale& locale, CharString& destination, UErrorCode& err) {
68564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    destination.clear().append(DT_DateTimeGregorianTag, -1, err); // initial default
686b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if ( U_SUCCESS(err) ) {
68764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        char localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY];
688b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // obtain a locale that always has the calendar key value that should be used
68964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        ures_getFunctionalEquivalent(
69064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            localeWithCalendarKey,
69164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            ULOC_LOCALE_IDENTIFIER_CAPACITY,
69264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            NULL,
69364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            "calendar",
69464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            "calendar",
69564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            locale.getName(),
69664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            NULL,
69764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            FALSE,
69864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            &err);
699b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination
700b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        // now get the calendar key value from that locale
70164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        char calendarType[ULOC_KEYWORDS_CAPACITY];
70264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        int32_t calendarTypeLen = uloc_getKeywordValue(
70364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            localeWithCalendarKey,
70464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            "calendar",
70564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            calendarType,
70664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            ULOC_KEYWORDS_CAPACITY,
70764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            &err);
708b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (U_SUCCESS(err) && calendarTypeLen < ULOC_KEYWORDS_CAPACITY) {
70964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            destination.clear().append(calendarType, -1, err);
71064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            if (U_FAILURE(err)) { return; }
711b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
712b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        err = U_ZERO_ERROR;
713b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
71464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
71664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertvoid
71764339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDateTimePatternGenerator::consumeShortTimePattern(const UnicodeString& shortTimePattern,
71864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        UErrorCode& status) {
71964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
72064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // set fDefaultHourFormatChar to the hour format character from this pattern
72164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    int32_t tfIdx, tfLen = shortTimePattern.length();
72264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    UBool ignoreChars = FALSE;
72364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    for (tfIdx = 0; tfIdx < tfLen; tfIdx++) {
72464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        UChar tfChar = shortTimePattern.charAt(tfIdx);
72564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if ( tfChar == SINGLE_QUOTE ) {
72664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            ignoreChars = !ignoreChars; // toggle (handle quoted literals & '' for single quote)
72764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        } else if ( !ignoreChars && u_strchr(hourFormatChars, tfChar) != NULL ) {
72864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            fDefaultHourFormatChar = tfChar;
72964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            break;
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
7316d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru    }
732b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
73364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // HACK for hh:ss
73464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    hackTimes(shortTimePattern, status);
73564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
73664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
73764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertstruct DateTimePatternGenerator::AppendItemFormatsSink : public ResourceSink {
73864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
73964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // Destination for data, modified via setters.
74064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    DateTimePatternGenerator& dtpg;
74164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
74264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    AppendItemFormatsSink(DateTimePatternGenerator& _dtpg) : dtpg(_dtpg) {}
74364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    virtual ~AppendItemFormatsSink();
74464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
74564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    virtual void put(const char *key, ResourceValue &value, UBool /*noFallback*/,
74664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            UErrorCode &errorCode) {
74764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        ResourceTable itemsTable = value.getTable(errorCode);
74864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if (U_FAILURE(errorCode)) { return; }
74964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        for (int32_t i = 0; itemsTable.getKeyAndValue(i, key, value); ++i) {
75064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            UDateTimePatternField field = dtpg.getAppendFormatNumber(key);
75164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            if (field == UDATPG_FIELD_COUNT) { continue; }
75264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            const UnicodeString& valueStr = value.getUnicodeString(errorCode);
75364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            if (dtpg.getAppendItemFormat(field).isEmpty() && !valueStr.isEmpty()) {
75464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                dtpg.setAppendItemFormat(field, valueStr);
75564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            }
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
758b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
75964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    void fillInMissing() {
76064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        UnicodeString defaultItemFormat(TRUE, UDATPG_ItemFormat, UPRV_LENGTHOF(UDATPG_ItemFormat)-1);  // Read-only alias.
76164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        for (int32_t i = 0; i < UDATPG_FIELD_COUNT; i++) {
76264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            UDateTimePatternField field = (UDateTimePatternField)i;
76364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            if (dtpg.getAppendItemFormat(field).isEmpty()) {
76464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                dtpg.setAppendItemFormat(field, defaultItemFormat);
76564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            }
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
76864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert};
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
77064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertstruct DateTimePatternGenerator::AppendItemNamesSink : public ResourceSink {
77164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
77264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // Destination for data, modified via setters.
77364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    DateTimePatternGenerator& dtpg;
77464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
77564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    AppendItemNamesSink(DateTimePatternGenerator& _dtpg) : dtpg(_dtpg) {}
77664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    virtual ~AppendItemNamesSink();
77764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
77864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    virtual void put(const char *key, ResourceValue &value, UBool /*noFallback*/,
77964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            UErrorCode &errorCode) {
78064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        ResourceTable itemsTable = value.getTable(errorCode);
78164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if (U_FAILURE(errorCode)) { return; }
78264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        for (int32_t i = 0; itemsTable.getKeyAndValue(i, key, value); ++i) {
78364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            UDateTimePatternField field = dtpg.getAppendNameNumber(key);
78464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            if (field == UDATPG_FIELD_COUNT) { continue; }
78564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            ResourceTable detailsTable = value.getTable(errorCode);
78664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            if (U_FAILURE(errorCode)) { return; }
78764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            for (int32_t j = 0; detailsTable.getKeyAndValue(j, key, value); ++j) {
78864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                if (uprv_strcmp(key, "dn") != 0) { continue; }
78964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                const UnicodeString& valueStr = value.getUnicodeString(errorCode);
79064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                if (dtpg.getAppendItemName(field).isEmpty() && !valueStr.isEmpty()) {
79164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    dtpg.setAppendItemName(field, valueStr);
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
79364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                break;
794103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            }
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
79664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    }
79764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
79864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    void fillInMissing() {
79964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        for (int32_t i = 0; i < UDATPG_FIELD_COUNT; i++) {
80064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            UDateTimePatternField field = (UDateTimePatternField)i;
80164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            UnicodeString& valueStr = dtpg.getMutableAppendItemName(field);
80264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            if (valueStr.isEmpty()) {
80364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                valueStr = CAP_F;
80464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                U_ASSERT(i < 20);
80564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                if (i < 10) {
80664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    // F0, F1, ..., F9
80764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    valueStr += (UChar)(i+0x30);
80864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                } else {
80964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    // F10, F11, ...
81064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    valueStr += (UChar)0x31;
81164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    valueStr += (UChar)(i-10 + 0x30);
81264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                }
81364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                // NUL-terminate for the C API.
81464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                valueStr.getTerminatedBuffer();
815103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            }
816103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
81764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    }
81864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert};
81964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
82064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertstruct DateTimePatternGenerator::AvailableFormatsSink : public ResourceSink {
82164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
82264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // Destination for data, modified via setters.
82364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    DateTimePatternGenerator& dtpg;
82464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
82564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // Temporary variable, required for calling addPatternWithSkeleton.
82664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    UnicodeString conflictingPattern;
82764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
82864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    AvailableFormatsSink(DateTimePatternGenerator& _dtpg) : dtpg(_dtpg) {}
82964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    virtual ~AvailableFormatsSink();
83064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
83164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    virtual void put(const char *key, ResourceValue &value, UBool isRoot,
83264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            UErrorCode &errorCode) {
83364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        ResourceTable itemsTable = value.getTable(errorCode);
83464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if (U_FAILURE(errorCode)) { return; }
83564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        for (int32_t i = 0; itemsTable.getKeyAndValue(i, key, value); ++i) {
83664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            const UnicodeString formatKey(key, -1, US_INV);
83764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            if (!dtpg.isAvailableFormatSet(formatKey) ) {
83864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                dtpg.setAvailableFormat(formatKey, errorCode);
83964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                // Add pattern with its associated skeleton. Override any duplicate
84064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                // derived from std patterns, but not a previous availableFormats entry:
84164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                const UnicodeString& formatValue = value.getUnicodeString(errorCode);
84264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                conflictingPattern.remove();
84364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                dtpg.addPatternWithSkeleton(formatValue, &formatKey, !isRoot, conflictingPattern, errorCode);
844103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            }
845103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
8468de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    }
84764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert};
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
84964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// Virtual destructors must be defined out of line.
85064339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDateTimePatternGenerator::AppendItemFormatsSink::~AppendItemFormatsSink() {}
85164339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDateTimePatternGenerator::AppendItemNamesSink::~AppendItemNamesSink() {}
85264339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDateTimePatternGenerator::AvailableFormatsSink::~AvailableFormatsSink() {}
85364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
85464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertvoid
85564339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDateTimePatternGenerator::addCLDRData(const Locale& locale, UErrorCode& errorCode) {
85664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (U_FAILURE(errorCode)) { return; }
85764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    UnicodeString rbPattern, value, field;
85864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    CharString path;
85964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
86064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    LocalUResourceBundlePointer rb(ures_open(NULL, locale.getName(), &errorCode));
86164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (U_FAILURE(errorCode)) { return; }
86264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
86364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    CharString calendarTypeToUse; // to be filled in with the type to use, if all goes well
86464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    getCalendarTypeToUse(locale, calendarTypeToUse, errorCode);
86564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (U_FAILURE(errorCode)) { return; }
86664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
86764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // Local err to ignore resource not found exceptions
86864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    UErrorCode err = U_ZERO_ERROR;
86964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
87064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // Load append item formats.
87164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    AppendItemFormatsSink appendItemFormatsSink(*this);
87264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    path.clear()
87364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        .append(DT_DateTimeCalendarTag, errorCode)
87464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        .append('/', errorCode)
87564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        .append(calendarTypeToUse, errorCode)
87664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        .append('/', errorCode)
87764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        .append(DT_DateTimeAppendItemsTag, errorCode); // i.e., calendar/xxx/appendItems
87864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (U_FAILURE(errorCode)) { return; }
87964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    ures_getAllItemsWithFallback(rb.getAlias(), path.data(), appendItemFormatsSink, err);
88064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    appendItemFormatsSink.fillInMissing();
88164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
88264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // Load CLDR item names.
88364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    err = U_ZERO_ERROR;
88464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    AppendItemNamesSink appendItemNamesSink(*this);
88564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    ures_getAllItemsWithFallback(rb.getAlias(), DT_DateTimeFieldsTag, appendItemNamesSink, err);
88664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    appendItemNamesSink.fillInMissing();
88764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
88864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // Load the available formats from CLDR.
88964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    err = U_ZERO_ERROR;
89064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    initHashtable(errorCode);
89164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (U_FAILURE(errorCode)) { return; }
89264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    AvailableFormatsSink availableFormatsSink(*this);
89364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    path.clear()
89464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        .append(DT_DateTimeCalendarTag, errorCode)
89564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        .append('/', errorCode)
89664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        .append(calendarTypeToUse, errorCode)
89764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        .append('/', errorCode)
89864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        .append(DT_DateTimeAvailableFormatsTag, errorCode); // i.e., calendar/xxx/availableFormats
89964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (U_FAILURE(errorCode)) { return; }
90064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    ures_getAllItemsWithFallback(rb.getAlias(), path.data(), availableFormatsSink, err);
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::initHashtable(UErrorCode& err) {
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fAvailableFormatKeyHash!=NULL) {
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((fAvailableFormatKeyHash = new Hashtable(FALSE, err))==NULL) {
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        err=U_MEMORY_ALLOCATION_ERROR;
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::setAppendItemFormat(UDateTimePatternField field, const UnicodeString& value) {
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    appendItemFormats[field] = value;
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // NUL-terminate for the C API.
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    appendItemFormats[field].getTerminatedBuffer();
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UnicodeString&
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::getAppendItemFormat(UDateTimePatternField field) const {
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return appendItemFormats[field];
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::setAppendItemName(UDateTimePatternField field, const UnicodeString& value) {
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    appendItemNames[field] = value;
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // NUL-terminate for the C API.
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    appendItemNames[field].getTerminatedBuffer();
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UnicodeString&
93464339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDateTimePatternGenerator::getAppendItemName(UDateTimePatternField field) const {
93564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    return appendItemNames[field];
93664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
93764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
93864339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertUnicodeString&
93964339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDateTimePatternGenerator::getMutableAppendItemName(UDateTimePatternField field) {
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return appendItemNames[field];
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::getAppendName(UDateTimePatternField field, UnicodeString& value) {
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    value = SINGLE_QUOTE;
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    value += appendItemNames[field];
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    value += SINGLE_QUOTE;
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::getBestPattern(const UnicodeString& patternForm, UErrorCode& status) {
95250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return getBestPattern(patternForm, UDATPG_MATCH_NO_OPTIONS, status);
95350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
95450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
95550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString
95650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDateTimePatternGenerator::getBestPattern(const UnicodeString& patternForm, UDateTimePatternMatchOptions options, UErrorCode& status) {
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UnicodeString *bestPattern=NULL;
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString dtFormat;
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString resultPattern;
96059d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t flags = kDTPGNoFlags;
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t dateMask=(1<<UDATPG_DAYPERIOD_FIELD) - 1;
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t timeMask=(1<<UDATPG_FIELD_COUNT) - 1 - dateMask;
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
9658de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    // Replace hour metacharacters 'j', 'C' and 'J', set flags as necessary
966b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UnicodeString patternFormCopy = UnicodeString(patternForm);
96759d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t patPos, patLen = patternFormCopy.length();
96859d709d503bab6e2b61931737e662dd293b40578ccornelius    UBool inQuoted = FALSE;
96959d709d503bab6e2b61931737e662dd293b40578ccornelius    for (patPos = 0; patPos < patLen; patPos++) {
97059d709d503bab6e2b61931737e662dd293b40578ccornelius        UChar patChr = patternFormCopy.charAt(patPos);
97159d709d503bab6e2b61931737e662dd293b40578ccornelius        if (patChr == SINGLE_QUOTE) {
97259d709d503bab6e2b61931737e662dd293b40578ccornelius            inQuoted = !inQuoted;
97359d709d503bab6e2b61931737e662dd293b40578ccornelius        } else if (!inQuoted) {
97459d709d503bab6e2b61931737e662dd293b40578ccornelius            if (patChr == LOW_J) {
97559d709d503bab6e2b61931737e662dd293b40578ccornelius                patternFormCopy.setCharAt(patPos, fDefaultHourFormatChar);
9768de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            } else if (patChr == CAP_C) {
9778de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                AllowedHourFormat preferred;
9788de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                if (fAllowedHourFormats[0] != ALLOWED_HOUR_FORMAT_UNKNOWN) {
9798de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                    preferred = (AllowedHourFormat)fAllowedHourFormats[0];
9808de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                } else {
9818de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                    status = U_INVALID_FORMAT_ERROR;
9828de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                    return UnicodeString();
9838de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                }
9848de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
9858de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                if (preferred == ALLOWED_HOUR_FORMAT_H || preferred == ALLOWED_HOUR_FORMAT_HB || preferred == ALLOWED_HOUR_FORMAT_Hb) {
9868de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                    patternFormCopy.setCharAt(patPos, CAP_H);
9878de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                } else {
9888de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                    patternFormCopy.setCharAt(patPos, LOW_H);
9898de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                }
9908de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
9918de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                if (preferred == ALLOWED_HOUR_FORMAT_HB || preferred == ALLOWED_HOUR_FORMAT_hB) {
9928de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                    flags |= kDTPGSkeletonUsesCapB;
9938de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                } else if (preferred == ALLOWED_HOUR_FORMAT_Hb || preferred == ALLOWED_HOUR_FORMAT_hb) {
9948de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                    flags |= kDTPGSkeletonUsesLowB;
9958de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                }
99659d709d503bab6e2b61931737e662dd293b40578ccornelius            } else if (patChr == CAP_J) {
99759d709d503bab6e2b61931737e662dd293b40578ccornelius                // Get pattern for skeleton with H, then replace H or k
99859d709d503bab6e2b61931737e662dd293b40578ccornelius                // with fDefaultHourFormatChar (if different)
99959d709d503bab6e2b61931737e662dd293b40578ccornelius                patternFormCopy.setCharAt(patPos, CAP_H);
100059d709d503bab6e2b61931737e662dd293b40578ccornelius                flags |= kDTPGSkeletonUsesCapJ;
100159d709d503bab6e2b61931737e662dd293b40578ccornelius            }
100259d709d503bab6e2b61931737e662dd293b40578ccornelius        }
100359d709d503bab6e2b61931737e662dd293b40578ccornelius    }
1004b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    resultPattern.remove();
1006b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    dtMatcher->set(patternFormCopy, fp);
1007b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const PtnSkeleton* specifiedSkeleton=NULL;
1008b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    bestPattern=getBestRaw(*dtMatcher, -1, distanceInfo, &specifiedSkeleton);
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ( distanceInfo->missingFieldMask==0 && distanceInfo->extraFieldMask==0 ) {
101059d709d503bab6e2b61931737e662dd293b40578ccornelius        resultPattern = adjustFieldTypes(*bestPattern, specifiedSkeleton, flags, options);
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return resultPattern;
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t neededFields = dtMatcher->getFieldMask();
101559d709d503bab6e2b61931737e662dd293b40578ccornelius    UnicodeString datePattern=getBestAppending(neededFields & dateMask, flags, options);
101659d709d503bab6e2b61931737e662dd293b40578ccornelius    UnicodeString timePattern=getBestAppending(neededFields & timeMask, flags, options);
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (datePattern.length()==0) {
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (timePattern.length()==0) {
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            resultPattern.remove();
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return timePattern;
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (timePattern.length()==0) {
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return datePattern;
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    resultPattern.remove();
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    status = U_ZERO_ERROR;
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dtFormat=getDateTimeFormat();
10318de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert    SimpleFormatter(dtFormat, 2, 2, status).format(timePattern, datePattern, resultPattern, status);
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return resultPattern;
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString
1036b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruDateTimePatternGenerator::replaceFieldTypes(const UnicodeString& pattern,
1037b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                            const UnicodeString& skeleton,
103850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                            UErrorCode& status) {
103950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return replaceFieldTypes(pattern, skeleton, UDATPG_MATCH_NO_OPTIONS, status);
104050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
104150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
104250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString
104350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoDateTimePatternGenerator::replaceFieldTypes(const UnicodeString& pattern,
104450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                            const UnicodeString& skeleton,
104550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                            UDateTimePatternMatchOptions options,
1046c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                            UErrorCode& /*status*/) {
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dtMatcher->set(skeleton, fp);
104859d709d503bab6e2b61931737e662dd293b40578ccornelius    UnicodeString result = adjustFieldTypes(pattern, NULL, kDTPGNoFlags, options);
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::setDecimal(const UnicodeString& newDecimal) {
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->decimal = newDecimal;
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // NUL-terminate for the C API.
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->decimal.getTerminatedBuffer();
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UnicodeString&
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::getDecimal() const {
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return decimal;
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
106564339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertDateTimePatternGenerator::addCanonicalItems(UErrorCode& status) {
106664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (U_FAILURE(status)) { return; }
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString  conflictingPattern;
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=0; i<UDATPG_FIELD_COUNT; i++) {
107064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if (Canonical_Items[i] > 0) {
107164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            addPattern(UnicodeString(Canonical_Items[i]), FALSE, conflictingPattern, status);
107264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        }
107364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if (U_FAILURE(status)) { return; }
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::setDateTimeFormat(const UnicodeString& dtFormat) {
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dateTimeFormat = dtFormat;
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // NUL-terminate for the C API.
1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    dateTimeFormat.getTerminatedBuffer();
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UnicodeString&
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::getDateTimeFormat() const {
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return dateTimeFormat;
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::setDateTimeFromCalendar(const Locale& locale, UErrorCode& status) {
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar *resStr;
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t resStrLen = 0;
1093b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Calendar* fCalendar = Calendar::createInstance(locale, status);
109564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (U_FAILURE(status)) { return; }
109664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
109764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    LocalUResourceBundlePointer calData(ures_open(NULL, locale.getBaseName(), &status));
109864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    ures_getByKey(calData.getAlias(), DT_DateTimeCalendarTag, calData.getAlias(), &status);
109964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
110064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    LocalUResourceBundlePointer dateTimePatterns;
110164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (fCalendar != NULL && fCalendar->getType() != NULL && *fCalendar->getType() != '\0'
110264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            && uprv_strcmp(fCalendar->getType(), DT_DateTimeGregorianTag) != 0) {
110364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        dateTimePatterns.adoptInstead(ures_getByKeyWithFallback(calData.getAlias(), fCalendar->getType(),
110464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                                                                NULL, &status));
110564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        ures_getByKeyWithFallback(dateTimePatterns.getAlias(), DT_DateTimePatternsTag,
110664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                                  dateTimePatterns.getAlias(), &status);
110764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    }
110864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
110964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (dateTimePatterns.isNull() || status == U_MISSING_RESOURCE_ERROR) {
111064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        status = U_ZERO_ERROR;
111164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        dateTimePatterns.adoptInstead(ures_getByKeyWithFallback(calData.getAlias(), DT_DateTimeGregorianTag,
111264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                                                                dateTimePatterns.orphan(), &status));
111364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        ures_getByKeyWithFallback(dateTimePatterns.getAlias(), DT_DateTimePatternsTag,
111464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                                  dateTimePatterns.getAlias(), &status);
111564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    }
111664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (U_FAILURE(status)) { return; }
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
111864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (ures_getSize(dateTimePatterns.getAlias()) <= DateFormat::kDateTime)
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_INVALID_FORMAT_ERROR;
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
112364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    resStr = ures_getStringByIndex(dateTimePatterns.getAlias(), (int32_t)DateFormat::kDateTime, &resStrLen, &status);
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    setDateTimeFormat(UnicodeString(TRUE, resStr, resStrLen));
1125b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete fCalendar;
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::setDecimalSymbols(const Locale& locale, UErrorCode& status) {
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DecimalFormatSymbols dfs = DecimalFormatSymbols(locale, status);
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_SUCCESS(status)) {
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        decimal = dfs.getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // NUL-terminate for the C API.
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        decimal.getTerminatedBuffer();
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUDateTimePatternConflict
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::addPattern(
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UnicodeString& pattern,
1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool override,
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString &conflictingPattern,
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode& status)
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return addPatternWithSkeleton(pattern, NULL, override, conflictingPattern, status);
1147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// For DateTimePatternGenerator::addPatternWithSkeleton -
1150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// If skeletonToUse is specified, then an availableFormats entry is being added. In this case:
1151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 1. We pass that skeleton to matcher.set instead of having it derive a skeleton from the pattern.
1152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 2. If the new entry's skeleton or basePattern does match an existing entry but that entry also had a skeleton specified
1153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// (i.e. it was also from availableFormats), then the new entry does not override it regardless of the value of the override
1154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// parameter. This prevents later availableFormats entries from a parent locale overriding earlier ones from the actual
1155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// specified locale. However, availableFormats entries *should* override entries with matching skeleton whose skeleton was
1156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// derived (i.e. entries derived from the standard date/time patters for the specified locale).
1157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// 3. When adding the pattern (patternMap->add), we set a new boolean to indicate that the added entry had a
1158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// specified skeleton (which sets a new field in the PtnElem in the PatternMap).
1159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUDateTimePatternConflict
1160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruDateTimePatternGenerator::addPatternWithSkeleton(
1161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const UnicodeString& pattern,
1162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const UnicodeString* skeletonToUse,
1163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UBool override,
1164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UnicodeString& conflictingPattern,
1165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UErrorCode& status)
1166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru{
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString basePattern;
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PtnSkeleton   skeleton;
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDateTimePatternConflict conflictingStatus = UDATPG_NO_CONFLICT;
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DateTimeMatcher matcher;
1173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if ( skeletonToUse == NULL ) {
1174b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        matcher.set(pattern, fp, skeleton);
1175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        matcher.getBasePattern(basePattern);
1176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    } else {
1177103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        matcher.set(*skeletonToUse, fp, skeleton); // no longer trims skeleton fields to max len 3, per #7930
1178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        matcher.getBasePattern(basePattern); // or perhaps instead: basePattern = *skeletonToUse;
1179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
11808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // We only care about base conflicts - and replacing the pattern associated with a base - if:
11818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // 1. the conflicting previous base pattern did *not* have an explicit skeleton; in that case the previous
11828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // base + pattern combination was derived from either (a) a canonical item, (b) a standard format, or
11838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // (c) a pattern specified programmatically with a previous call to addPattern (which would only happen
11848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // if we are getting here from a subsequent call to addPattern).
11858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // 2. a skeleton is specified for the current pattern, but override=false; in that case we are checking
11868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // availableFormats items from root, which should not override any previous entry with the same base.
1187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UBool entryHadSpecifiedSkeleton;
1188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const UnicodeString *duplicatePattern = patternMap->getPatternFromBasePattern(basePattern, entryHadSpecifiedSkeleton);
11898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (duplicatePattern != NULL && (!entryHadSpecifiedSkeleton || (skeletonToUse != NULL && !override))) {
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        conflictingStatus = UDATPG_BASE_CONFLICT;
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        conflictingPattern = *duplicatePattern;
11928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        if (!override) {
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return conflictingStatus;
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
11968393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // The only time we get here with override=true and skeletonToUse!=null is when adding availableFormats
11978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // items from CLDR data. In that case, we don't want an item from a parent locale to replace an item with
11988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // same skeleton from the specified locale, so skip the current item if skeletonWasSpecified is true for
11998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // the previously-specified conflicting item.
1200b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const PtnSkeleton* entrySpecifiedSkeleton = NULL;
1201b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    duplicatePattern = patternMap->getPatternFromSkeleton(skeleton, &entrySpecifiedSkeleton);
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (duplicatePattern != NULL ) {
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        conflictingStatus = UDATPG_CONFLICT;
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        conflictingPattern = *duplicatePattern;
1205b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (!override || (skeletonToUse != NULL && entrySpecifiedSkeleton != NULL)) {
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return conflictingStatus;
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    patternMap->add(basePattern, skeleton, pattern, skeletonToUse != NULL, status);
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(status)) {
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return conflictingStatus;
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return UDATPG_NO_CONFLICT;
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUDateTimePatternField
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::getAppendFormatNumber(const char* field) const {
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i ) {
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (uprv_strcmp(CLDR_FIELD_APPEND[i], field)==0) {
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return (UDateTimePatternField)i;
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return UDATPG_FIELD_COUNT;
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUDateTimePatternField
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::getAppendNameNumber(const char* field) const {
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i ) {
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (uprv_strcmp(CLDR_FIELD_NAME[i],field)==0) {
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return (UDateTimePatternField)i;
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return UDATPG_FIELD_COUNT;
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UnicodeString*
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::getBestRaw(DateTimeMatcher& source,
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     int32_t includeMask,
1241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                     DistanceInfo* missingFields,
1242b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                     const PtnSkeleton** specifiedSkeletonPtr) {
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t bestDistance = 0x7fffffff;
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DistanceInfo tempInfo;
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UnicodeString *bestPattern=NULL;
1246b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const PtnSkeleton* specifiedSkeleton=NULL;
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PatternMapIterator it;
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (it.set(*patternMap); it.hasNext(); ) {
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DateTimeMatcher trial = it.next();
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (trial.equals(skipMatcher)) {
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t distance=source.getDistance(trial, includeMask, tempInfo);
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (distance<bestDistance) {
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            bestDistance=distance;
1257b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            bestPattern=patternMap->getPatternFromSkeleton(*trial.getSkeletonPtr(), &specifiedSkeleton);
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            missingFields->setTo(tempInfo);
1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (distance==0) {
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // If the best raw match had a specified skeleton and that skeleton was requested by the caller,
1266b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // then return it too. This generally happens when the caller needs to pass that skeleton
1267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // through to adjustFieldTypes so the latter can do a better job.
1268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (bestPattern && specifiedSkeletonPtr) {
1269b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        *specifiedSkeletonPtr = specifiedSkeleton;
1270b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return bestPattern;
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::adjustFieldTypes(const UnicodeString& pattern,
1276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                           const PtnSkeleton* specifiedSkeleton,
127759d709d503bab6e2b61931737e662dd293b40578ccornelius                                           int32_t flags,
127850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                           UDateTimePatternMatchOptions options) {
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString newPattern;
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fp->set(pattern);
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=0; i < fp->itemNumber; i++) {
1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UnicodeString field = fp->items[i];
1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( fp->isQuoteLiteral(field) ) {
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UnicodeString quoteLiteral;
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fp->getQuoteLiteral(quoteLiteral, &i);
1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            newPattern += quoteLiteral;
1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
1290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (fp->isPatternSeparator(field)) {
1291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                newPattern+=field;
1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;
1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t canonicalIndex = fp->getCanonicalIndex(field);
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (canonicalIndex < 0) {
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                newPattern+=field;
1297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;  // don't adjust
1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const dtTypeElem *row = &dtTypes[canonicalIndex];
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t typeValue = row->field;
13018de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
13028de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            // Handle special day periods.
13038de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            if (typeValue == UDATPG_DAYPERIOD_FIELD && flags != 0) {
13048de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                UChar c = NONE;  // '0'
13058de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                if (flags & kDTPGSkeletonUsesCapB) { c = CAP_B; }
13068de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                if (flags & kDTPGSkeletonUsesLowB) { c = LOW_B; }
13078de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
13088de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                if (c != NONE) {
13098de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                    for (int32_t i = 0; i < field.length(); ++i)
13108de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                    field.setCharAt(i, c);
13118de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                }
13128de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            }
13138de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert
131459d709d503bab6e2b61931737e662dd293b40578ccornelius            if ((flags & kDTPGFixFractionalSeconds) != 0 && typeValue == UDATPG_SECOND_FIELD) {
131564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                field += decimal;
131664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                dtMatcher->skeleton.original.appendFieldTo(UDATPG_FRACTIONAL_SECOND_FIELD, field);
1317b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if (dtMatcher->skeleton.type[typeValue]!=0) {
1318b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // Here:
1319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // - "reqField" is the field from the originally requested skeleton, with length
1320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // "reqFieldLen".
1321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // - "field" is the field from the found pattern.
1322b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    //
1323b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // The adjusted field should consist of characters from the originally requested
132427f654740f2a26ad62a5c155af9199af9e69b889claireho                    // skeleton, except in the case of UDATPG_HOUR_FIELD or UDATPG_MONTH_FIELD or
1325103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    // UDATPG_WEEKDAY_FIELD or UDATPG_YEAR_FIELD, in which case it should consist
1326103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    // of characters from the  found pattern.
1327b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    //
1328b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    // The length of the adjusted field (adjFieldLen) should match that in the originally
132950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    // requested skeleton, except that in the following cases the length of the adjusted field
133050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    // should match that in the found pattern (i.e. the length of this pattern field should
133150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    // not be adjusted):
133250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    // 1. typeValue is UDATPG_HOUR_FIELD/MINUTE/SECOND and the corresponding bit in options is
133350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    //    not set (ticket #7180). Note, we may want to implement a similar change for other
133450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    //    numeric fields (MM, dd, etc.) so the default behavior is to get locale preference for
133550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    //    field length, but options bits can be used to override this.
133650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    // 2. There is a specified skeleton for the found pattern and one of the following is true:
133750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    //    a) The length of the field in the skeleton (skelFieldLen) is equal to reqFieldLen.
133850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    //    b) The pattern field is numeric and the skeleton field is not, or vice versa.
1339b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
134064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    UChar reqFieldChar = dtMatcher->skeleton.original.getFieldChar(typeValue);
134164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    int32_t reqFieldLen = dtMatcher->skeleton.original.getFieldLength(typeValue);
134264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    if (reqFieldChar == CAP_E && reqFieldLen < 3)
1343b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        reqFieldLen = 3; // 1-3 for E are equivalent to 3 for c,e
1344b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    int32_t adjFieldLen = reqFieldLen;
134550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    if ( (typeValue==UDATPG_HOUR_FIELD && (options & UDATPG_MATCH_HOUR_FIELD_LENGTH)==0) ||
134650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                         (typeValue==UDATPG_MINUTE_FIELD && (options & UDATPG_MATCH_MINUTE_FIELD_LENGTH)==0) ||
134750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                         (typeValue==UDATPG_SECOND_FIELD && (options & UDATPG_MATCH_SECOND_FIELD_LENGTH)==0) ) {
134850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                         adjFieldLen = field.length();
134950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    } else if (specifiedSkeleton) {
135064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                        int32_t skelFieldLen = specifiedSkeleton->original.getFieldLength(typeValue);
1351b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        UBool patFieldIsNumeric = (row->type > 0);
1352b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        UBool skelFieldIsNumeric = (specifiedSkeleton->type[typeValue] > 0);
1353b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        if (skelFieldLen == reqFieldLen || (patFieldIsNumeric && !skelFieldIsNumeric) || (skelFieldIsNumeric && !patFieldIsNumeric)) {
1354b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            // don't adjust the field length in the found pattern
1355b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            adjFieldLen = field.length();
1356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
1357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
135864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                    UChar c = (typeValue!= UDATPG_HOUR_FIELD
135964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                            && typeValue!= UDATPG_MONTH_FIELD
136064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                            && typeValue!= UDATPG_WEEKDAY_FIELD
136164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                            && (typeValue!= UDATPG_YEAR_FIELD || reqFieldChar==CAP_Y))
136264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                            ? reqFieldChar
136364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert                            : field.charAt(0);
136459d709d503bab6e2b61931737e662dd293b40578ccornelius                    if (typeValue == UDATPG_HOUR_FIELD && (flags & kDTPGSkeletonUsesCapJ) != 0) {
136559d709d503bab6e2b61931737e662dd293b40578ccornelius                        c = fDefaultHourFormatChar;
136659d709d503bab6e2b61931737e662dd293b40578ccornelius                    }
1367b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    field.remove();
1368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    for (int32_t i=adjFieldLen; i>0; --i) {
1369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        field+=c;
1370b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    }
1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1372b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            newPattern+=field;
1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return newPattern;
1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString
137959d709d503bab6e2b61931737e662dd293b40578ccorneliusDateTimePatternGenerator::getBestAppending(int32_t missingFields, int32_t flags, UDateTimePatternMatchOptions options) {
1380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString  resultPattern, tempPattern;
1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode err=U_ZERO_ERROR;
1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t lastMissingFieldMask=0;
1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (missingFields!=0) {
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        resultPattern=UnicodeString();
1385b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        const PtnSkeleton* specifiedSkeleton=NULL;
1386b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        tempPattern = *getBestRaw(*dtMatcher, missingFields, distanceInfo, &specifiedSkeleton);
138759d709d503bab6e2b61931737e662dd293b40578ccornelius        resultPattern = adjustFieldTypes(tempPattern, specifiedSkeleton, flags, options);
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( distanceInfo->missingFieldMask==0 ) {
1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return resultPattern;
1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (distanceInfo->missingFieldMask!=0) { // precondition: EVERY single field must work!
1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ( lastMissingFieldMask == distanceInfo->missingFieldMask ) {
1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;  // cannot find the proper missing field
1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (((distanceInfo->missingFieldMask & UDATPG_SECOND_AND_FRACTIONAL_MASK)==UDATPG_FRACTIONAL_MASK) &&
1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ((missingFields & UDATPG_SECOND_AND_FRACTIONAL_MASK) == UDATPG_SECOND_AND_FRACTIONAL_MASK)) {
139759d709d503bab6e2b61931737e662dd293b40578ccornelius                resultPattern = adjustFieldTypes(resultPattern, specifiedSkeleton, flags | kDTPGFixFractionalSeconds, options);
1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                distanceInfo->missingFieldMask &= ~UDATPG_FRACTIONAL_MASK;
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;
1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t startingMask = distanceInfo->missingFieldMask;
1402b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            tempPattern = *getBestRaw(*dtMatcher, distanceInfo->missingFieldMask, distanceInfo, &specifiedSkeleton);
140359d709d503bab6e2b61931737e662dd293b40578ccornelius            tempPattern = adjustFieldTypes(tempPattern, specifiedSkeleton, flags, options);
1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t foundMask=startingMask& ~distanceInfo->missingFieldMask;
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t topField=getTopBitNumber(foundMask);
1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UnicodeString appendName;
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            getAppendName((UDateTimePatternField)topField, appendName);
14088de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            const UnicodeString *values[3] = {
14098de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                &resultPattern,
14108de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                &tempPattern,
14118de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                &appendName
1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            };
14138de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            SimpleFormatter(appendItemFormats[topField], 2, 3, err).
14148de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert                    formatAndReplace(values, 3, resultPattern, NULL, 0, err);
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            lastMissingFieldMask = distanceInfo->missingFieldMask;
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1418b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return resultPattern;
1419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::getTopBitNumber(int32_t foundMask) {
1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ( foundMask==0 ) {
1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i=0;
1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while (foundMask!=0) {
1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        foundMask >>=1;
1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++i;
1430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (i-1 >UDATPG_ZONE_FIELD) {
1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return UDATPG_ZONE_FIELD;
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1434b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    else
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return i-1;
1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::setAvailableFormat(const UnicodeString &key, UErrorCode& err)
1440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fAvailableFormatKeyHash->puti(key, 1, err);
1442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::isAvailableFormatSet(const UnicodeString &key) const {
1446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UBool)(fAvailableFormatKeyHash->geti(key) == 1);
1447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1450c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruDateTimePatternGenerator::copyHashtable(Hashtable *other, UErrorCode &status) {
1451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (other == NULL) {
1453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1455c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (fAvailableFormatKeyHash != NULL) {
1456c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete fAvailableFormatKeyHash;
1457c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fAvailableFormatKeyHash = NULL;
1458c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1459c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    initHashtable(status);
1460c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if(U_FAILURE(status)){
1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
14631b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    int32_t pos = UHASH_FIRST;
1464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UHashElement* elem = NULL;
1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // walk through the hash table and create a deep clone
1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while((elem = other->nextElement(pos))!= NULL){
1467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const UHashTok otherKeyTok = elem->key;
1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UnicodeString* otherKey = (UnicodeString*)otherKeyTok.pointer;
1469c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fAvailableFormatKeyHash->puti(*otherKey, 1, status);
1470c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if(U_FAILURE(status)){
1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
1472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStringEnumeration*
1477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::getSkeletons(UErrorCode& status) const {
1478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    StringEnumeration* skeletonEnumerator = new DTSkeletonEnumeration(*patternMap, DT_SKELETON, status);
1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return skeletonEnumerator;
1480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UnicodeString&
1483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::getPatternForSkeleton(const UnicodeString& skeleton) const {
1484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PtnElem *curElem;
1485b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (skeleton.length() ==0) {
1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return emptyString;
1488b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    curElem = patternMap->getHeader(skeleton.charAt(0));
1490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while ( curElem != NULL ) {
1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( curElem->skeleton->getSkeleton()==skeleton ) {
1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return curElem->pattern;
1493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        curElem=curElem->next;
1495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return emptyString;
1497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStringEnumeration*
1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::getBaseSkeletons(UErrorCode& status) const {
1501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    StringEnumeration* baseSkeletonEnumerator = new DTSkeletonEnumeration(*patternMap, DT_BASESKELETON, status);
1502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return baseSkeletonEnumerator;
1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStringEnumeration*
1506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::getRedundants(UErrorCode& status) {
1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    StringEnumeration* output = new DTRedundantEnumeration();
1508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UnicodeString *pattern;
1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PatternMapIterator it;
1510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (it.set(*patternMap); it.hasNext(); ) {
1511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DateTimeMatcher current = it.next();
1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pattern = patternMap->getPatternFromSkeleton(*(it.getSkeleton()));
1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( isCanonicalItem(*pattern) ) {
1514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
1515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( skipMatcher == NULL ) {
1517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            skipMatcher = new DateTimeMatcher(current);
1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *skipMatcher = current;
1521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UnicodeString trial = getBestPattern(current.getPattern(), status);
1523b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (trial == *pattern) {
1524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ((DTRedundantEnumeration *)output)->add(*pattern, status);
1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (current.equals(skipMatcher)) {
1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
1528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return output;
1531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::isCanonicalItem(const UnicodeString& item) const {
1535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ( item.length() != 1 ) {
1536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i) {
1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (item.charAt(0)==Canonical_Items[i]) {
1540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return TRUE;
1541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
1544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator*
1548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimePatternGenerator::clone() const {
1549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return new DateTimePatternGenerator(*this);
1550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPatternMap::PatternMap() {
1553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   for (int32_t i=0; i < MAX_PATTERN_ENTRIES; ++i ) {
1554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      boot[i]=NULL;
1555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   }
1556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   isDupAllowed = TRUE;
1557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPatternMap::copyFrom(const PatternMap& other, UErrorCode& status) {
1561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->isDupAllowed = other.isDupAllowed;
1562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t bootIndex=0; bootIndex<MAX_PATTERN_ENTRIES; ++bootIndex ) {
1563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        PtnElem *curElem, *otherElem, *prevElem=NULL;
1564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        otherElem = other.boot[bootIndex];
1565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (otherElem!=NULL) {
1566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ((curElem = new PtnElem(otherElem->basePattern, otherElem->pattern))==NULL) {
1567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // out of memory
1568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                status = U_MEMORY_ALLOCATION_ERROR;
1569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
1570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ( this->boot[bootIndex]== NULL ) {
1572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                this->boot[bootIndex] = curElem;
1573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ((curElem->skeleton=new PtnSkeleton(*(otherElem->skeleton))) == NULL ) {
1575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // out of memory
1576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                status = U_MEMORY_ALLOCATION_ERROR;
1577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
1578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
15791b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert            curElem->skeletonWasSpecified = otherElem->skeletonWasSpecified;
1580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (prevElem!=NULL) {
1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                prevElem->next=curElem;
1582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            curElem->next=NULL;
1584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            prevElem = curElem;
1585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            otherElem = otherElem->next;
1586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1591b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruPtnElem*
1592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPatternMap::getHeader(UChar baseChar) {
1593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PtnElem* curElem;
1594b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ( (baseChar >= CAP_A) && (baseChar <= CAP_Z) ) {
1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         curElem = boot[baseChar-CAP_A];
1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( (baseChar >=LOW_A) && (baseChar <= LOW_Z) ) {
1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            curElem = boot[26+baseChar-LOW_A];
1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
1603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return NULL;
1604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return curElem;
1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1608b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPatternMap::~PatternMap() {
1610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   for (int32_t i=0; i < MAX_PATTERN_ENTRIES; ++i ) {
1611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       if (boot[i]!=NULL ) {
1612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           delete boot[i];
1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           boot[i]=NULL;
1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       }
1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   }
1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}  // PatternMap destructor
1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPatternMap::add(const UnicodeString& basePattern,
1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                const PtnSkeleton& skeleton,
1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                const UnicodeString& value,// mapped pattern value
1622b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                UBool skeletonWasSpecified,
1623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                UErrorCode &status) {
1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar baseChar = basePattern.charAt(0);
1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PtnElem *curElem, *baseElem;
1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    status = U_ZERO_ERROR;
1627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // the baseChar must be A-Z or a-z
1629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((baseChar >= CAP_A) && (baseChar <= CAP_Z)) {
1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        baseElem = boot[baseChar-CAP_A];
1631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((baseChar >=LOW_A) && (baseChar <= LOW_Z)) {
1634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            baseElem = boot[26+baseChar-LOW_A];
1635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         }
1636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         else {
1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             status = U_ILLEGAL_CHARACTER;
1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             return;
1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         }
1640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (baseElem == NULL) {
1643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((curElem = new PtnElem(basePattern, value)) == NULL ) {
1644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // out of memory
1645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            status = U_MEMORY_ALLOCATION_ERROR;
1646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
1647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (baseChar >= LOW_A) {
1649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            boot[26 + (baseChar-LOW_A)] = curElem;
1650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
1652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            boot[baseChar-CAP_A] = curElem;
1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        curElem->skeleton = new PtnSkeleton(skeleton);
1655b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        curElem->skeletonWasSpecified = skeletonWasSpecified;
1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ( baseElem != NULL ) {
1658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        curElem = getDuplicateElem(basePattern, skeleton, baseElem);
1659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (curElem == NULL) {
1661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // add new element to the list.
1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            curElem = baseElem;
1663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while( curElem -> next != NULL )
1664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
1665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                curElem = curElem->next;
1666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ((curElem->next = new PtnElem(basePattern, value)) == NULL ) {
1668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // out of memory
1669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                status = U_MEMORY_ALLOCATION_ERROR;
1670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            curElem=curElem->next;
1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            curElem->skeleton = new PtnSkeleton(skeleton);
1674b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            curElem->skeletonWasSpecified = skeletonWasSpecified;
1675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Pattern exists in the list already.
1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ( !isDupAllowed ) {
1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
1680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Overwrite the value.
1682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            curElem->pattern = value;
16838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            // It was a bug that we were not doing the following previously,
16848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            // though that bug hid other problems by making things partly work.
16858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            curElem->skeletonWasSpecified = skeletonWasSpecified;
1686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}  // PatternMap::add
1689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Find the pattern from the given basePattern string.
1691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UnicodeString *
1692b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruPatternMap::getPatternFromBasePattern(UnicodeString& basePattern, UBool& skeletonWasSpecified) { // key to search for
1693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   PtnElem *curElem;
1694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   if ((curElem=getHeader(basePattern.charAt(0)))==NULL) {
1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       return NULL;  // no match
1697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   }
1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   do  {
1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       if ( basePattern.compare(curElem->basePattern)==0 ) {
1701b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru          skeletonWasSpecified = curElem->skeletonWasSpecified;
1702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          return &(curElem->pattern);
1703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       }
1704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       curElem=curElem->next;
1705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   }while (curElem != NULL);
1706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   return NULL;
1708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}  // PatternMap::getFromBasePattern
1709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Find the pattern from the given skeleton.
1712b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// At least when this is called from getBestRaw & addPattern (in which case specifiedSkeletonPtr is non-NULL),
1713b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// the comparison should be based on skeleton.original (which is unique and tied to the distance measurement in bestRaw)
1714b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// and not skeleton.baseOriginal (which is not unique); otherwise we may pick a different skeleton than the one with the
1715b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// optimum distance value in getBestRaw. When this is called from public getRedundants (specifiedSkeletonPtr is NULL),
1716b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// for now it will continue to compare based on baseOriginal so as not to change the behavior unnecessarily.
1717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UnicodeString *
1718b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruPatternMap::getPatternFromSkeleton(PtnSkeleton& skeleton, const PtnSkeleton** specifiedSkeletonPtr) { // key to search for
1719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   PtnElem *curElem;
1720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1721b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   if (specifiedSkeletonPtr) {
1722b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru       *specifiedSkeletonPtr = NULL;
1723b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru   }
1724b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
1725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   // find boot entry
172664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert   UChar baseChar = skeleton.getFirstChar();
1727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   if ((curElem=getHeader(baseChar))==NULL) {
1728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       return NULL;  // no match
1729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   }
1730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   do  {
173264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert       UBool equal;
1733b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru       if (specifiedSkeletonPtr != NULL) { // called from DateTimePatternGenerator::getBestRaw or addPattern, use original
173464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert           equal = curElem->skeleton->original == skeleton.original;
1735b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru       } else { // called from DateTimePatternGenerator::getRedundants, use baseOriginal
173664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert           equal = curElem->skeleton->baseOriginal == skeleton.baseOriginal;
1737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       }
173864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert       if (equal) {
1739b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           if (specifiedSkeletonPtr && curElem->skeletonWasSpecified) {
1740b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru               *specifiedSkeletonPtr = curElem->skeleton;
1741b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru           }
1742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           return &(curElem->pattern);
1743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       }
1744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       curElem=curElem->next;
1745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   }while (curElem != NULL);
1746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   return NULL;
1748b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru}
1749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPatternMap::equals(const PatternMap& other) {
1752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ( this==&other ) {
1753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
1754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t bootIndex=0; bootIndex<MAX_PATTERN_ENTRIES; ++bootIndex ) {
1756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( boot[bootIndex]==other.boot[bootIndex] ) {
1757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
1758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( (boot[bootIndex]==NULL)||(other.boot[bootIndex]==NULL) ) {
1760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return FALSE;
1761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        PtnElem *otherElem = other.boot[bootIndex];
1763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        PtnElem *myElem = boot[bootIndex];
1764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while ((otherElem!=NULL) || (myElem!=NULL)) {
1765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ( myElem == otherElem ) {
1766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
1767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ((otherElem==NULL) || (myElem==NULL)) {
1769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return FALSE;
1770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ( (myElem->basePattern != otherElem->basePattern) ||
1772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                 (myElem->pattern != otherElem->pattern) ) {
1773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return FALSE;
1774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ((myElem->skeleton!=otherElem->skeleton)&&
1776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                !myElem->skeleton->equals(*(otherElem->skeleton))) {
1777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return FALSE;
1778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            myElem = myElem->next;
1780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            otherElem=otherElem->next;
1781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
1784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// find any key existing in the mapping table already.
1787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// return TRUE if there is an existing key, otherwise return FALSE.
1788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPtnElem*
1789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPatternMap::getDuplicateElem(
1790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const UnicodeString &basePattern,
1791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const PtnSkeleton &skeleton,
1792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            PtnElem *baseElem)  {
1793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   PtnElem *curElem;
1794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   if ( baseElem == (PtnElem *)NULL )  {
1796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         return (PtnElem*)NULL;
1797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   }
1798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   else {
1799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         curElem = baseElem;
1800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   }
1801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   do {
1802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     if ( basePattern.compare(curElem->basePattern)==0 ) {
1803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBool isEqual=TRUE;
1804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i) {
1805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (curElem->skeleton->type[i] != skeleton.type[i] ) {
1806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                isEqual=FALSE;
1807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
1808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (isEqual) {
1811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return curElem;
1812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     }
1814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     curElem = curElem->next;
1815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   } while( curElem != (PtnElem *)NULL );
1816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   // end of the list
1818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   return (PtnElem*)NULL;
1819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}  // PatternMap::getDuplicateElem
1821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimeMatcher::DateTimeMatcher(void) {
1823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1825103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusDateTimeMatcher::~DateTimeMatcher() {}
1826103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimeMatcher::DateTimeMatcher(const DateTimeMatcher& other) {
1828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    copyFrom(other.skeleton);
1829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimeMatcher::set(const UnicodeString& pattern, FormatParser* fp) {
1834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PtnSkeleton localSkeleton;
1835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return set(pattern, fp, localSkeleton);
1836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimeMatcher::set(const UnicodeString& pattern, FormatParser* fp, PtnSkeleton& skeletonResult) {
1840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i;
1841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (i=0; i<UDATPG_FIELD_COUNT; ++i) {
184264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        skeletonResult.type[i] = NONE;
1843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fp->set(pattern);
1845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (i=0; i < fp->itemNumber; i++) {
184664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        const UnicodeString& value = fp->items[i];
184764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if ( value.charAt(0) == LOW_A ) {
1848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;  // skip 'a'
1849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
185164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if ( fp->isQuoteLiteral(value) ) {
1852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UnicodeString quoteLiteral;
1853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fp->getQuoteLiteral(quoteLiteral, &i);
1854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
1855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
185664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        int32_t canonicalIndex = fp->getCanonicalIndex(value);
1857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (canonicalIndex < 0 ) {
1858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
1859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const dtTypeElem *row = &dtTypes[canonicalIndex];
186164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        int32_t field = row->field;
186264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        skeletonResult.original.populate(field, value);
1863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UChar repeatChar = row->patternChar;
1864103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        int32_t repeatCount = row->minLen; // #7930 removes cap at 3
186564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        skeletonResult.baseOriginal.populate(field, repeatChar, repeatCount);
186664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        int16_t subField = row->type;
1867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( row->type > 0) {
186864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            subField += value.length();
1869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
187064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        skeletonResult.type[field] = subField;
1871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    copyFrom(skeletonResult);
1873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimeMatcher::getBasePattern(UnicodeString &result ) {
1877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    result.remove(); // Reset the result first.
187864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    skeleton.baseOriginal.appendTo(result);
1879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString
1882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimeMatcher::getPattern() {
1883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString result;
188464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    return skeleton.original.appendTo(result);
1885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimeMatcher::getDistance(const DateTimeMatcher& other, int32_t includeMask, DistanceInfo& distanceInfo) {
1889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t result=0;
1890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    distanceInfo.clear();
1891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i ) {
1892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t myType = (includeMask&(1<<i))==0 ? 0 : skeleton.type[i];
1893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t otherType = other.skeleton.type[i];
1894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (myType==otherType) {
1895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
1896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (myType==0) {// and other is not
1898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            result += EXTRA_FIELD;
1899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            distanceInfo.addExtra(i);
1900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
1902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (otherType==0) {
1903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                result += MISSING_FIELD;
1904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                distanceInfo.addMissing(i);
1905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else {
1907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                result += abs(myType - otherType);
1908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimeMatcher::copyFrom(const PtnSkeleton& newSkeleton) {
191764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    skeleton.copyFrom(newSkeleton);
1918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimeMatcher::copyFrom() {
1922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // same as clear
192364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    skeleton.clear();
1924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
1927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimeMatcher::equals(const DateTimeMatcher* other) const {
192864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    if (other==NULL) { return FALSE; }
192964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    return skeleton.original == other->skeleton.original;
1930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
1933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimeMatcher::getFieldMask() {
1934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t result=0;
1935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i) {
1937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (skeleton.type[i]!=0) {
1938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            result |= (1<<i);
1939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPtnSkeleton*
1945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimeMatcher::getSkeletonPtr() {
1946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return &skeleton;
1947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruFormatParser::FormatParser () {
1950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    status = START;
1951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    itemNumber=0;
1952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruFormatParser::~FormatParser () {
1956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Find the next token with the starting position and length
1960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Note: the startPos may
1961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruFormatParser::TokenStatus
1962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruFormatParser::setTokens(const UnicodeString& pattern, int32_t startPos, int32_t *len) {
1963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t  curLoc = startPos;
1964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ( curLoc >= pattern.length()) {
1965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return DONE;
1966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // check the current char is between A-Z or a-z
1968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    do {
1969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UChar c=pattern.charAt(curLoc);
1970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( (c>=CAP_A && c<=CAP_Z) || (c>=LOW_A && c<=LOW_Z) ) {
1971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           curLoc++;
1972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
1974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               startPos = curLoc;
1975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               *len=1;
1976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               return ADD_TOKEN;
1977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( pattern.charAt(curLoc)!= pattern.charAt(startPos) ) {
1980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;  // not the same token
1981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } while(curLoc <= pattern.length());
1983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *len = curLoc-startPos;
1984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return ADD_TOKEN;
1985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
1988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruFormatParser::set(const UnicodeString& pattern) {
1989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t startPos=0;
1990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TokenStatus result=START;
1991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t len=0;
1992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    itemNumber =0;
1993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    do {
1995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        result = setTokens( pattern, startPos, &len );
1996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( result == ADD_TOKEN )
1997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
1998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            items[itemNumber++] = UnicodeString(pattern, startPos, len );
1999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            startPos += len;
2000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
2002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
2003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } while (result==ADD_TOKEN && itemNumber < MAX_DT_TOKEN);
2005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
2008b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruFormatParser::getCanonicalIndex(const UnicodeString& s, UBool strict) {
2009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t len = s.length();
2010b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (len == 0) {
2011b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        return -1;
2012b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
2013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar ch = s.charAt(0);
2014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2015b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    // Verify that all are the same character.
2016b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    for (int32_t l = 1; l < len; l++) {
2017b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (ch != s.charAt(l)) {
2018b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            return -1;
2019b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        }
2020b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    }
2021b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t i = 0;
2022b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t bestRow = -1;
202364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    while (dtTypes[i].patternChar != 0x0000) {
2024b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if ( dtTypes[i].patternChar != ch ) {
2025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++i;
2026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
2027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2028b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        bestRow = i;
2029b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        if (dtTypes[i].patternChar != dtTypes[i+1].patternChar) {
2030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return i;
2031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (dtTypes[i+1].minLen <= len) {
2033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++i;
2034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
2035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return i;
2037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2038b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    return strict ? -1 : bestRow;
2039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
2042c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertFormatParser::isQuoteLiteral(const UnicodeString& s) {
2043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UBool)(s.charAt(0)==SINGLE_QUOTE);
2044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// This function aussumes the current itemIndex points to the quote literal.
2047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Please call isQuoteLiteral prior to this function.
2048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
2049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruFormatParser::getQuoteLiteral(UnicodeString& quote, int32_t *itemIndex) {
2050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i=*itemIndex;
2051b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
2052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    quote.remove();
2053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (items[i].charAt(0)==SINGLE_QUOTE) {
2054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        quote += items[i];
2055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++i;
2056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while ( i < itemNumber ) {
2058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( items[i].charAt(0)==SINGLE_QUOTE ) {
2059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ( (i+1<itemNumber) && (items[i+1].charAt(0)==SINGLE_QUOTE)) {
2060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // two single quotes e.g. 'o''clock'
2061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                quote += items[i++];
2062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                quote += items[i++];
2063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;
2064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else {
2066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                quote += items[i];
2067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
2068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
2071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            quote += items[i];
2072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ++i;
2074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *itemIndex=i;
2076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
2079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruFormatParser::isPatternSeparator(UnicodeString& field) {
2080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=0; i<field.length(); ++i ) {
2081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UChar c= field.charAt(i);
2082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( (c==SINGLE_QUOTE) || (c==BACKSLASH) || (c==SPACE) || (c==COLON) ||
2083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             (c==QUOTATION_MARK) || (c==COMMA) || (c==HYPHEN) ||(items[i].charAt(0)==DOT) ) {
2084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            continue;
2085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
2087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return FALSE;
2088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
2091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2093103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusDistanceInfo::~DistanceInfo() {}
2094103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
2095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
2096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDistanceInfo::setTo(DistanceInfo &other) {
2097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    missingFieldMask = other.missingFieldMask;
2098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    extraFieldMask= other.extraFieldMask;
2099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPatternMapIterator::PatternMapIterator() {
2102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    bootIndex = 0;
2103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    nodePtr = NULL;
2104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    patternMap=NULL;
2105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    matcher= new DateTimeMatcher();
2106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPatternMapIterator::~PatternMapIterator() {
2110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete matcher;
2111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
2114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPatternMapIterator::set(PatternMap& newPatternMap) {
2115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    this->patternMap=&newPatternMap;
2116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruPtnSkeleton*
2119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPatternMapIterator::getSkeleton() {
2120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ( nodePtr == NULL ) {
2121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
2122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
2124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return nodePtr->skeleton;
2125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
2129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPatternMapIterator::hasNext() {
2130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t headIndex=bootIndex;
2131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PtnElem *curPtr=nodePtr;
2132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (patternMap==NULL) {
2134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
2135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while ( headIndex < MAX_PATTERN_ENTRIES ) {
2137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( curPtr != NULL ) {
2138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ( curPtr->next != NULL ) {
2139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return TRUE;
2140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else {
2142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                headIndex++;
2143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                curPtr=NULL;
2144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;
2145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
2148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ( patternMap->boot[headIndex] != NULL ) {
2149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return TRUE;
2150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else {
2152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                headIndex++;
2153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;
2154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
2159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDateTimeMatcher&
2162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPatternMapIterator::next() {
2163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while ( bootIndex < MAX_PATTERN_ENTRIES ) {
2164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ( nodePtr != NULL ) {
2165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ( nodePtr->next != NULL ) {
2166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                nodePtr = nodePtr->next;
2167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
2168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else {
2170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                bootIndex++;
2171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                nodePtr=NULL;
2172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;
2173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
2176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ( patternMap->boot[bootIndex] != NULL ) {
2177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                nodePtr = patternMap->boot[bootIndex];
2178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
2179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            else {
2181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                bootIndex++;
2182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;
2183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (nodePtr!=NULL) {
2187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        matcher->copyFrom(*nodePtr->skeleton);
2188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else {
2190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        matcher->copyFrom();
2191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *matcher;
2193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
219564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
219664339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertSkeletonFields::SkeletonFields() {
219764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    // Set initial values to zero
219864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    clear();
2199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
220164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertvoid SkeletonFields::clear() {
220264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    uprv_memset(chars, 0, sizeof(chars));
220364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    uprv_memset(lengths, 0, sizeof(lengths));
220464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
2205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
220664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertvoid SkeletonFields::copyFrom(const SkeletonFields& other) {
220764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    uprv_memcpy(chars, other.chars, sizeof(chars));
220864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    uprv_memcpy(lengths, other.lengths, sizeof(lengths));
220964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
221064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
221164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertvoid SkeletonFields::clearField(int32_t field) {
221264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    chars[field] = 0;
221364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    lengths[field] = 0;
221464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
221564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
221664339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertUChar SkeletonFields::getFieldChar(int32_t field) const {
221764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    return chars[field];
221864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
221964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
222064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertint32_t SkeletonFields::getFieldLength(int32_t field) const {
222164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    return lengths[field];
222264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
222364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
222464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertvoid SkeletonFields::populate(int32_t field, const UnicodeString& value) {
222564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    populate(field, value.charAt(0), value.length());
222664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
222764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
222864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertvoid SkeletonFields::populate(int32_t field, UChar ch, int32_t length) {
222964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    chars[field] = (int8_t) ch;
223064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    lengths[field] = (int8_t) length;
223164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
223264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
223364339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertUBool SkeletonFields::isFieldEmpty(int32_t field) const {
223464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    return lengths[field] == 0;
223564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
223664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
223764339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertUnicodeString& SkeletonFields::appendTo(UnicodeString& string) const {
223864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    for (int32_t i = 0; i < UDATPG_FIELD_COUNT; ++i) {
223964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        appendFieldTo(i, string);
2240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
224164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    return string;
2242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
224464339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertUnicodeString& SkeletonFields::appendFieldTo(int32_t field, UnicodeString& string) const {
224564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    UChar ch(chars[field]);
224664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    int32_t length = (int32_t) lengths[field];
224764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
224864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    for (int32_t i=0; i<length; i++) {
224964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        string += ch;
225064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    }
225164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    return string;
225264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
225364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
225464339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertUChar SkeletonFields::getFirstChar() const {
225564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    for (int32_t i = 0; i < UDATPG_FIELD_COUNT; ++i) {
225664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        if (lengths[i] != 0) {
225764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            return chars[i];
2258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
226064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    return '\0';
226164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
226264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
226364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
226464339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertPtnSkeleton::PtnSkeleton() {
226564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
226664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
226764339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertPtnSkeleton::PtnSkeleton(const PtnSkeleton& other) {
226864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    copyFrom(other);
226964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
227064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
227164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertvoid PtnSkeleton::copyFrom(const PtnSkeleton& other) {
227264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    uprv_memcpy(type, other.type, sizeof(type));
227364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    original.copyFrom(other.original);
227464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    baseOriginal.copyFrom(other.baseOriginal);
227564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
227664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
227764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubertvoid PtnSkeleton::clear() {
227864339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    uprv_memset(type, 0, sizeof(type));
227964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    original.clear();
228064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    baseOriginal.clear();
228164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
228264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
228364339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertUBool
228464339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertPtnSkeleton::equals(const PtnSkeleton& other) const  {
228564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    return (original == other.original)
228664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        && (baseOriginal == other.baseOriginal)
228764339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert        && (uprv_memcmp(type, other.type, sizeof(type)) == 0);
2288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString
229164339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertPtnSkeleton::getSkeleton() const {
2292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString result;
229364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    return original.appendTo(result);
2294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString
229764339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertPtnSkeleton::getBaseSkeleton() const {
2298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString result;
229964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    return baseOriginal.appendTo(result);
230064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert}
2301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
230264339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertUChar
230364339d36f8bd4db5025fe2988eda22b491a9219cFredrik RoubertPtnSkeleton::getFirstChar() const {
230464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    return baseOriginal.getFirstChar();
2305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPtnSkeleton::~PtnSkeleton() {
2308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruPtnElem::PtnElem(const UnicodeString &basePat, const UnicodeString &pat) :
2311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerubasePattern(basePat),
2312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruskeleton(NULL),
2313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupattern(pat),
2314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querunext(NULL)
2315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
2316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruPtnElem::~PtnElem() {
2319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (next!=NULL) {
2321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete next;
2322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete skeleton;
2324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDTSkeletonEnumeration::DTSkeletonEnumeration(PatternMap &patternMap, dtStrEnum type, UErrorCode& status) {
2327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PtnElem  *curElem;
2328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    PtnSkeleton *curSkeleton;
2329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString s;
2330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t bootIndex;
2331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pos=0;
2333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fSkeletons = new UVector(status);
2334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
2335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete fSkeletons;
2336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
2337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (bootIndex=0; bootIndex<MAX_PATTERN_ENTRIES; ++bootIndex ) {
2339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        curElem = patternMap.boot[bootIndex];
2340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while (curElem!=NULL) {
2341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            switch(type) {
2342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case DT_BASESKELETON:
2343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    s=curElem->basePattern;
2344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
2345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case DT_PATTERN:
2346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    s=curElem->pattern;
2347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
2348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case DT_SKELETON:
2349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    curSkeleton=curElem->skeleton;
2350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    s=curSkeleton->getSkeleton();
2351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
2352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ( !isCanonicalItem(s) ) {
2354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                fSkeletons->addElement(new UnicodeString(s), status);
2355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (U_FAILURE(status)) {
2356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    delete fSkeletons;
2357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    fSkeletons = NULL;
2358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return;
2359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
2360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
2361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            curElem = curElem->next;
2362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ((bootIndex==MAX_PATTERN_ENTRIES) && (curElem!=NULL) ) {
2365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_BUFFER_OVERFLOW_ERROR;
2366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UnicodeString*
2370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDTSkeletonEnumeration::snext(UErrorCode& status) {
2371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(status) && pos < fSkeletons->size()) {
2372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return (const UnicodeString*)fSkeletons->elementAt(pos++);
2373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return NULL;
2375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
2378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDTSkeletonEnumeration::reset(UErrorCode& /*status*/) {
2379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pos=0;
2380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
2383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDTSkeletonEnumeration::count(UErrorCode& /*status*/) const {
2384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   return (fSkeletons==NULL) ? 0 : fSkeletons->size();
2385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
2388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDTSkeletonEnumeration::isCanonicalItem(const UnicodeString& item) {
2389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ( item.length() != 1 ) {
2390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
2391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i) {
2393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (item.charAt(0)==Canonical_Items[i]) {
2394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return TRUE;
2395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
2398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDTSkeletonEnumeration::~DTSkeletonEnumeration() {
2401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString *s;
2402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=0; i<fSkeletons->size(); ++i) {
2403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((s=(UnicodeString *)fSkeletons->elementAt(i))!=NULL) {
2404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete s;
2405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete fSkeletons;
2408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDTRedundantEnumeration::DTRedundantEnumeration() {
2411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pos=0;
2412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fPatterns = NULL;
2413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
2416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDTRedundantEnumeration::add(const UnicodeString& pattern, UErrorCode& status) {
2417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) return;
2418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (fPatterns == NULL)  {
2419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fPatterns = new UVector(status);
2420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(status)) {
2421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete fPatterns;
2422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            fPatterns = NULL;
2423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
2424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       }
2425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fPatterns->addElement(new UnicodeString(pattern), status);
2427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
2428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete fPatterns;
2429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fPatterns = NULL;
2430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
2431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UnicodeString*
2435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDTRedundantEnumeration::snext(UErrorCode& status) {
2436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(status) && pos < fPatterns->size()) {
2437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return (const UnicodeString*)fPatterns->elementAt(pos++);
2438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return NULL;
2440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
2443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDTRedundantEnumeration::reset(UErrorCode& /*status*/) {
2444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pos=0;
2445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t
2448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDTRedundantEnumeration::count(UErrorCode& /*status*/) const {
2449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       return (fPatterns==NULL) ? 0 : fPatterns->size();
2450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
2453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDTRedundantEnumeration::isCanonicalItem(const UnicodeString& item) {
2454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if ( item.length() != 1 ) {
2455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
2456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i) {
2458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (item.charAt(0)==Canonical_Items[i]) {
2459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return TRUE;
2460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return FALSE;
2463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruDTRedundantEnumeration::~DTRedundantEnumeration() {
2466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString *s;
2467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i=0; i<fPatterns->size(); ++i) {
2468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if ((s=(UnicodeString *)fPatterns->elementAt(i))!=NULL) {
2469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete s;
2470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
2471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
2472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete fPatterns;
2473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
2474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
2476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
2479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//eof
2481