Imported Upstream version 58.1
[platform/upstream/icu.git] / source / test / intltest / fldset.cpp
1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 ************************************************************************
5 * Copyright (c) 2007-2011, International Business Machines
6 * Corporation and others.  All Rights Reserved.
7 ************************************************************************
8 */
9
10 #include "fldset.h"
11 #include "intltest.h"
12
13 #if !UCONFIG_NO_FORMATTING
14 #include "unicode/regex.h"
15
16
17 FieldsSet::FieldsSet() {
18     // NOTREACHED
19 }
20
21 FieldsSet::FieldsSet(int32_t fieldCount) {
22     construct((UDebugEnumType)-1, fieldCount);
23 }
24
25 FieldsSet::FieldsSet(UDebugEnumType field) {
26     construct(field, udbg_enumCount(field));
27 }
28
29 FieldsSet::~FieldsSet() {
30     
31 }
32
33 int32_t FieldsSet::fieldCount() const {
34     return fFieldCount;
35 }
36
37 void FieldsSet::construct(UDebugEnumType field, int32_t fieldCount) {
38     fEnum = field;
39     if(fieldCount > U_FIELDS_SET_MAX) {
40         fieldCount = U_FIELDS_SET_MAX;
41     }
42     fFieldCount = fieldCount;
43     clear();
44 }
45
46 UnicodeString FieldsSet::diffFrom(const FieldsSet& other, UErrorCode& status) const {
47     UnicodeString str;
48     if(!isSameType(other)) {
49         status = U_ILLEGAL_ARGUMENT_ERROR;
50         return UnicodeString("U_ILLEGAL_ARGUMENT_ERROR: FieldsSet of a different type!");
51     }
52     for (int i=0; i<fieldCount(); i++) {
53         if (isSet((UCalendarDateFields)i)) {
54             int32_t myVal = get(i);
55             int32_t theirVal = other.get(i);
56             
57             if(fEnum != -1) {
58                 const UnicodeString& fieldName = udbg_enumString(
59                         fEnum, i);
60
61                 str = str + fieldName + UnicodeString("=")+myVal+UnicodeString(" not ")+theirVal+UnicodeString(", ");
62             } else {
63                 str = str + UnicodeString("some field") + "=" + myVal+" not " + theirVal+", ";
64             }
65         }
66     }
67     return str;
68 }
69
70 static UnicodeString *split(const UnicodeString &src, UChar ch, int32_t &splits)
71 {
72     int32_t offset = -1;
73
74     splits = 1;
75     while((offset = src.indexOf(ch, offset + 1)) >= 0) {
76         splits += 1;
77     }
78
79     UnicodeString *result = new UnicodeString[splits];
80
81     int32_t start = 0;
82     int32_t split = 0;
83     int32_t end;
84
85     while((end = src.indexOf(ch, start)) >= 0) {
86         src.extractBetween(start, end, result[split++]);
87         start = end + 1;
88     }
89
90     src.extractBetween(start, src.length(), result[split]);
91
92     return result;
93 }
94
95 int32_t FieldsSet::parseFrom(const UnicodeString& str, const 
96         FieldsSet* inheritFrom, UErrorCode& status) {
97
98     int goodFields = 0;
99
100     if(U_FAILURE(status)) {
101         return -1;
102     }
103
104     int32_t destCount = 0;
105     UnicodeString *dest = split(str, 0x002C /* ',' */, destCount);
106
107     for(int i = 0; i < destCount; i += 1) {
108         int32_t dc = 0;
109         UnicodeString *kv = split(dest[i], 0x003D /* '=' */, dc);
110
111         if(dc != 2) {
112             it_errln(UnicodeString("dc == ") + dc + UnicodeString("?"));
113         }
114
115         int32_t field = handleParseName(inheritFrom, kv[0], kv[1], status);
116
117         if(U_FAILURE(status)) {
118             char ch[256];
119             const UChar *u = kv[0].getBuffer();
120             int32_t len = kv[0].length();
121             u_UCharsToChars(u, ch, len);
122             ch[len] = 0; /* include terminating \0 */
123             it_errln(UnicodeString("Parse Failed: Field ") + UnicodeString(ch) + UnicodeString(", err ") + UnicodeString(u_errorName(status)));
124             delete[] kv;
125             delete[] dest;
126             return -1;
127         }
128
129         if(field != -1) {
130             handleParseValue(inheritFrom, field, kv[1], status);
131
132             if(U_FAILURE(status)) {
133                 char ch[256];
134                 const UChar *u = kv[1].getBuffer();
135                 int32_t len = kv[1].length();
136                 u_UCharsToChars(u, ch, len);
137                 ch[len] = 0; /* include terminating \0 */
138                 it_errln(UnicodeString("Parse Failed: Value ") + UnicodeString(ch) + UnicodeString(", err ") + UnicodeString(u_errorName(status)));
139                 delete[] kv;
140                 delete[] dest;
141                 return -1;
142             }
143
144             goodFields += 1;
145         }
146
147         delete[] kv;
148     }
149
150     delete[] dest;
151
152     return goodFields;
153 }
154
155 UBool FieldsSet::isSameType(const FieldsSet& other) const {
156     return((&other==this)||
157            ((other.fFieldCount==fFieldCount) && (other.fEnum==fEnum)));  
158 }
159
160 void FieldsSet::clear() {
161     for (int i=0; i<fieldCount(); i++) {
162         fValue[i]=-1;
163         fIsSet[i]=FALSE;
164     }
165 }
166
167 void FieldsSet::clear(int32_t field) {
168     if (field<0|| field>=fieldCount()) {
169         return;
170     }
171     fValue[field] = -1;
172     fIsSet[field] = FALSE;
173 }
174 void FieldsSet::set(int32_t field, int32_t amount) {
175     if (field<0|| field>=fieldCount()) {
176         return;
177     }
178     fValue[field] = amount;
179     fIsSet[field] = TRUE;
180 }
181
182 UBool FieldsSet::isSet(int32_t field) const {
183     if (field<0|| field>=fieldCount()) {
184         return FALSE;
185     }
186     return fIsSet[field];
187 }
188 int32_t FieldsSet::get(int32_t field) const {
189     if (field<0|| field>=fieldCount()) {
190         return -1;
191     }
192     return fValue[field];
193 }
194
195
196 int32_t FieldsSet::handleParseName(const FieldsSet* /* inheritFrom */, const UnicodeString& name, const UnicodeString& /* substr*/ , UErrorCode& status) {
197     if(fEnum > -1) {
198         int32_t which = udbg_enumByString(fEnum, name);
199         if(which == UDBG_INVALID_ENUM) {
200             status = U_UNSUPPORTED_ERROR;
201         }
202         return which;
203     } else {
204         status = U_UNSUPPORTED_ERROR;
205         return -1;
206     }
207 }
208
209 void FieldsSet::parseValueDefault(const FieldsSet* inheritFrom, int32_t field, const UnicodeString& substr, UErrorCode& status) {
210     int32_t value = -1;
211     if(substr.length()==0) { // inherit requested
212         // inherit
213         if((inheritFrom == NULL) || !inheritFrom->isSet((UCalendarDateFields)field)) {
214             // couldn't inherit from field 
215             it_errln(UnicodeString("Parse Failed: Couldn't inherit field ") + field + UnicodeString(" [") + UnicodeString(udbg_enumName(fEnum, field)) + UnicodeString("]"));
216             status = U_ILLEGAL_ARGUMENT_ERROR;
217             return;
218         }
219         value = inheritFrom->get((UCalendarDateFields)field);
220     } else {        
221         value = udbg_stoi(substr);
222     }
223     set(field, value);
224 }
225
226 void FieldsSet::parseValueEnum(UDebugEnumType type, const FieldsSet* inheritFrom, int32_t field, const UnicodeString& substr, UErrorCode& status) {
227     int32_t value = udbg_enumByString(type, substr);
228     if(value>=0) {
229         set(field, value);
230     } else {
231         // fallback
232         parseValueDefault(inheritFrom,field,substr,status);
233     }
234 }
235
236 void FieldsSet::handleParseValue(const FieldsSet* inheritFrom, int32_t field, const UnicodeString& substr, UErrorCode& status) {
237     parseValueDefault(inheritFrom, field, substr, status);
238 }
239
240 /// CAL FIELDS
241
242
243 CalendarFieldsSet::CalendarFieldsSet() :
244 FieldsSet(UDBG_UCalendarDateFields) {
245     // base class will call clear.
246 }
247
248 CalendarFieldsSet::~CalendarFieldsSet() {
249 }
250
251 void CalendarFieldsSet::handleParseValue(const FieldsSet* inheritFrom, int32_t field, const UnicodeString& substr, UErrorCode& status) {
252     if(field==UCAL_MONTH) {
253         parseValueEnum(UDBG_UCalendarMonths, inheritFrom, field, substr, status);
254         // will fallback to default.
255     } else {
256         parseValueDefault(inheritFrom, field, substr, status);
257     }
258 }
259
260 /**
261  * set the specified fields on this calendar. Doesn't clear first. Returns any errors the caller 
262  */
263 void CalendarFieldsSet::setOnCalendar(Calendar *cal, UErrorCode& /*status*/) const {
264     for (int i=0; i<UDAT_FIELD_COUNT; i++) {
265         if (isSet((UCalendarDateFields)i)) {
266             int32_t value = get((UCalendarDateFields)i);
267             cal->set((UCalendarDateFields)i, value);
268         }
269     }
270 }
271
272 /**
273  * return true if the calendar matches in these fields
274  */
275 UBool CalendarFieldsSet::matches(Calendar *cal, CalendarFieldsSet &diffSet,
276         UErrorCode& status) const {
277     UBool match = TRUE;
278     if (U_FAILURE(status)) {
279         return FALSE;
280     }
281     for (int i=0; i<UDAT_FIELD_COUNT; i++) {
282         if (isSet((UCalendarDateFields)i)) {
283             int32_t calVal = cal->get((UCalendarDateFields)i, status);
284             if (U_FAILURE(status))
285                 return FALSE;
286             if (calVal != get((UCalendarDateFields)i)) {
287                 match = FALSE;
288                 diffSet.set((UCalendarDateFields)i, calVal);
289                 //fprintf(stderr, "match failed: %s#%d=%d != %d\n",udbg_enumName(UDBG_UCalendarDateFields,i),i,cal->get((UCalendarDateFields)i,status), get((UCalendarDateFields)i));;
290             }
291         }
292     }
293     return match;
294 }
295
296
297 /**
298  * DateTimeStyleSet has two 'fields' -- date, and time.
299  */
300 enum DateTimeStyleSetFields {
301     DTS_DATE = 0,  /** Field one: the date (long, medium, short, etc). */
302     DTS_TIME,      /** Field two: the time (long, medium, short, etc). */
303     DTS_COUNT      /** The number of fields */
304 };
305
306 /**
307  * DateTimeSet 
308  * */
309 DateTimeStyleSet::DateTimeStyleSet() :
310     FieldsSet(DTS_COUNT) {
311 }
312
313 DateTimeStyleSet::~DateTimeStyleSet() {
314     
315 }
316
317 UDateFormatStyle DateTimeStyleSet::getDateStyle() const {
318     if(!isSet(DTS_DATE)) {
319         return UDAT_NONE;
320     } else {
321         return (UDateFormatStyle)get(DTS_DATE);
322     }
323 }
324
325
326 UDateFormatStyle DateTimeStyleSet::getTimeStyle() const {
327     if(!isSet(DTS_TIME)) {
328         return UDAT_NONE;
329     } else {
330         return (UDateFormatStyle)get(DTS_TIME);
331     }
332 }
333
334 void DateTimeStyleSet::handleParseValue(const FieldsSet* inheritFrom, int32_t field, const UnicodeString& substr, UErrorCode& status) {
335     UnicodeString kRELATIVE_("RELATIVE_");
336     if(substr.startsWith(kRELATIVE_)) {
337         UnicodeString relativeas(substr,kRELATIVE_.length());
338         parseValueEnum(UDBG_UDateFormatStyle, inheritFrom, field, relativeas, status);
339         // fix relative value
340         if(isSet(field) && U_SUCCESS(status)) {
341             set(field, get(field) | UDAT_RELATIVE);
342         }
343     } else {
344         parseValueEnum(UDBG_UDateFormatStyle, inheritFrom, field, substr, status);
345     }
346 }
347
348 int32_t DateTimeStyleSet::handleParseName(const FieldsSet* /* inheritFrom */, const UnicodeString& name, const UnicodeString& /* substr */, UErrorCode& status) {
349     UnicodeString kDATE("DATE"); // TODO: static
350     UnicodeString kTIME("TIME"); // TODO: static
351     if(name == kDATE ) { 
352         return DTS_DATE;
353     } else if(name == kTIME) {
354         return DTS_TIME;
355     } else {
356         status = U_ILLEGAL_ARGUMENT_ERROR;
357         return -1;   
358     }
359 }
360
361 #endif /*!UCONFIG_NO_FORMAT*/