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