OLD | NEW |
| (Empty) |
1 /* | |
2 ******************************************************************************* | |
3 * Copyright (C) 2015, International Business Machines Corporation and * | |
4 * others. All Rights Reserved. * | |
5 ******************************************************************************* | |
6 */ | |
7 | |
8 #include "numberformattesttuple.h" | |
9 | |
10 #if !UCONFIG_NO_FORMATTING | |
11 | |
12 #include "ustrfmt.h" | |
13 #include "charstr.h" | |
14 #include "cstring.h" | |
15 #include "cmemory.h" | |
16 #include "digitlst.h" | |
17 | |
18 static NumberFormatTestTuple *gNullPtr = NULL; | |
19 | |
20 #define FIELD_OFFSET(fieldName) ((int32_t) (((char *) &gNullPtr->fieldName) - ((
char *) gNullPtr))) | |
21 #define FIELD_FLAG_OFFSET(fieldName) ((int32_t) (((char *) &gNullPtr->fieldName#
#Flag) - ((char *) gNullPtr))) | |
22 | |
23 #define FIELD_INIT(fieldName, fieldType) {#fieldName, FIELD_OFFSET(fieldName), F
IELD_FLAG_OFFSET(fieldName), fieldType} | |
24 | |
25 struct Numberformattesttuple_EnumConversion { | |
26 const char *str; | |
27 int32_t value; | |
28 }; | |
29 | |
30 static Numberformattesttuple_EnumConversion gRoundingEnum[] = { | |
31 {"ceiling", DecimalFormat::kRoundCeiling}, | |
32 {"floor", DecimalFormat::kRoundFloor}, | |
33 {"down", DecimalFormat::kRoundDown}, | |
34 {"up", DecimalFormat::kRoundUp}, | |
35 {"halfEven", DecimalFormat::kRoundHalfEven}, | |
36 {"halfDown", DecimalFormat::kRoundHalfDown}, | |
37 {"halfUp", DecimalFormat::kRoundHalfUp}, | |
38 {"unnecessary", DecimalFormat::kRoundUnnecessary}}; | |
39 | |
40 static Numberformattesttuple_EnumConversion gCurrencyUsageEnum[] = { | |
41 {"standard", UCURR_USAGE_STANDARD}, | |
42 {"cash", UCURR_USAGE_CASH}}; | |
43 | |
44 static Numberformattesttuple_EnumConversion gPadPositionEnum[] = { | |
45 {"beforePrefix", DecimalFormat::kPadBeforePrefix}, | |
46 {"afterPrefix", DecimalFormat::kPadAfterPrefix}, | |
47 {"beforeSuffix", DecimalFormat::kPadBeforeSuffix}, | |
48 {"afterSuffix", DecimalFormat::kPadAfterSuffix}}; | |
49 | |
50 static Numberformattesttuple_EnumConversion gFormatStyleEnum[] = { | |
51 {"patternDecimal", UNUM_PATTERN_DECIMAL}, | |
52 {"decimal", UNUM_DECIMAL}, | |
53 {"currency", UNUM_CURRENCY}, | |
54 {"percent", UNUM_PERCENT}, | |
55 {"scientific", UNUM_SCIENTIFIC}, | |
56 {"spellout", UNUM_SPELLOUT}, | |
57 {"ordinal", UNUM_ORDINAL}, | |
58 {"duration", UNUM_DURATION}, | |
59 {"numberingSystem", UNUM_NUMBERING_SYSTEM}, | |
60 {"patternRuleBased", UNUM_PATTERN_RULEBASED}, | |
61 {"currencyIso", UNUM_CURRENCY_ISO}, | |
62 {"currencyPlural", UNUM_CURRENCY_PLURAL}, | |
63 {"currencyAccounting", UNUM_CURRENCY_ACCOUNTING}, | |
64 {"cashCurrency", UNUM_CASH_CURRENCY}, | |
65 {"default", UNUM_DEFAULT}, | |
66 {"ignore", UNUM_IGNORE}}; | |
67 | |
68 static int32_t toEnum( | |
69 const Numberformattesttuple_EnumConversion *table, | |
70 int32_t tableLength, | |
71 const UnicodeString &str, | |
72 UErrorCode &status) { | |
73 if (U_FAILURE(status)) { | |
74 return 0; | |
75 } | |
76 CharString cstr; | |
77 cstr.appendInvariantChars(str, status); | |
78 if (U_FAILURE(status)) { | |
79 return 0; | |
80 } | |
81 for (int32_t i = 0; i < tableLength; ++i) { | |
82 if (uprv_strcmp(cstr.data(), table[i].str) == 0) { | |
83 return table[i].value; | |
84 } | |
85 } | |
86 status = U_ILLEGAL_ARGUMENT_ERROR; | |
87 return 0; | |
88 } | |
89 | |
90 static void fromEnum( | |
91 const Numberformattesttuple_EnumConversion *table, | |
92 int32_t tableLength, | |
93 int32_t val, | |
94 UnicodeString &appendTo) { | |
95 for (int32_t i = 0; i < tableLength; ++i) { | |
96 if (table[i].value == val) { | |
97 appendTo.append(table[i].str); | |
98 } | |
99 } | |
100 } | |
101 | |
102 static void identVal( | |
103 const UnicodeString &str, void *strPtr, UErrorCode & /*status*/) { | |
104 *static_cast<UnicodeString *>(strPtr) = str; | |
105 } | |
106 | |
107 static void identStr( | |
108 const void *strPtr, UnicodeString &appendTo) { | |
109 appendTo.append(*static_cast<const UnicodeString *>(strPtr)); | |
110 } | |
111 | |
112 static void strToLocale( | |
113 const UnicodeString &str, void *localePtr, UErrorCode &status) { | |
114 if (U_FAILURE(status)) { | |
115 return; | |
116 } | |
117 CharString localeStr; | |
118 localeStr.appendInvariantChars(str, status); | |
119 *static_cast<Locale *>(localePtr) = Locale(localeStr.data()); | |
120 } | |
121 | |
122 static void localeToStr( | |
123 const void *localePtr, UnicodeString &appendTo) { | |
124 appendTo.append( | |
125 UnicodeString( | |
126 static_cast<const Locale *>(localePtr)->getName())); | |
127 } | |
128 | |
129 static void strToInt( | |
130 const UnicodeString &str, void *intPtr, UErrorCode &status) { | |
131 if (U_FAILURE(status)) { | |
132 return; | |
133 } | |
134 int32_t len = str.length(); | |
135 int32_t start = 0; | |
136 UBool neg = FALSE; | |
137 if (len > 0 && str[0] == 0x2D) { // negative | |
138 neg = TRUE; | |
139 start = 1; | |
140 } | |
141 if (start == len) { | |
142 status = U_ILLEGAL_ARGUMENT_ERROR; | |
143 return; | |
144 } | |
145 int32_t value = 0; | |
146 for (int32_t i = start; i < len; ++i) { | |
147 UChar ch = str[i]; | |
148 if (ch < 0x30 || ch > 0x39) { | |
149 status = U_ILLEGAL_ARGUMENT_ERROR; | |
150 return; | |
151 } | |
152 value = value * 10 - 0x30 + (int32_t) ch; | |
153 } | |
154 if (neg) { | |
155 value = -value; | |
156 } | |
157 *static_cast<int32_t *>(intPtr) = value; | |
158 } | |
159 | |
160 static void intToStr( | |
161 const void *intPtr, UnicodeString &appendTo) { | |
162 UChar buffer[20]; | |
163 int32_t x = *static_cast<const int32_t *>(intPtr); | |
164 UBool neg = FALSE; | |
165 if (x < 0) { | |
166 neg = TRUE; | |
167 x = -x; | |
168 } | |
169 if (neg) { | |
170 appendTo.append(0x2D); | |
171 } | |
172 int32_t len = uprv_itou(buffer, UPRV_LENGTHOF(buffer), (uint32_t) x, 10, 1); | |
173 appendTo.append(buffer, 0, len); | |
174 } | |
175 | |
176 static void strToDouble( | |
177 const UnicodeString &str, void *doublePtr, UErrorCode &status) { | |
178 if (U_FAILURE(status)) { | |
179 return; | |
180 } | |
181 CharString buffer; | |
182 buffer.appendInvariantChars(str, status); | |
183 if (U_FAILURE(status)) { | |
184 return; | |
185 } | |
186 *static_cast<double *>(doublePtr) = atof(buffer.data()); | |
187 } | |
188 | |
189 static void doubleToStr( | |
190 const void *doublePtr, UnicodeString &appendTo) { | |
191 char buffer[256]; | |
192 double x = *static_cast<const double *>(doublePtr); | |
193 sprintf(buffer, "%f", x); | |
194 appendTo.append(buffer); | |
195 } | |
196 | |
197 static void strToERounding( | |
198 const UnicodeString &str, void *roundPtr, UErrorCode &status) { | |
199 int32_t val = toEnum( | |
200 gRoundingEnum, UPRV_LENGTHOF(gRoundingEnum), str, status); | |
201 *static_cast<DecimalFormat::ERoundingMode *>(roundPtr) = (DecimalFormat::ERo
undingMode) val; | |
202 } | |
203 | |
204 static void eRoundingToStr( | |
205 const void *roundPtr, UnicodeString &appendTo) { | |
206 DecimalFormat::ERoundingMode rounding = | |
207 *static_cast<const DecimalFormat::ERoundingMode *>(roundPtr); | |
208 fromEnum( | |
209 gRoundingEnum, | |
210 UPRV_LENGTHOF(gRoundingEnum), | |
211 rounding, | |
212 appendTo); | |
213 } | |
214 | |
215 static void strToCurrencyUsage( | |
216 const UnicodeString &str, void *currencyUsagePtr, UErrorCode &status) { | |
217 int32_t val = toEnum( | |
218 gCurrencyUsageEnum, UPRV_LENGTHOF(gCurrencyUsageEnum), str, status); | |
219 *static_cast<UCurrencyUsage *>(currencyUsagePtr) = (UCurrencyUsage) val; | |
220 } | |
221 | |
222 static void currencyUsageToStr( | |
223 const void *currencyUsagePtr, UnicodeString &appendTo) { | |
224 UCurrencyUsage currencyUsage = | |
225 *static_cast<const UCurrencyUsage *>(currencyUsagePtr); | |
226 fromEnum( | |
227 gCurrencyUsageEnum, | |
228 UPRV_LENGTHOF(gCurrencyUsageEnum), | |
229 currencyUsage, | |
230 appendTo); | |
231 } | |
232 | |
233 static void strToEPadPosition( | |
234 const UnicodeString &str, void *padPositionPtr, UErrorCode &status) { | |
235 int32_t val = toEnum( | |
236 gPadPositionEnum, UPRV_LENGTHOF(gPadPositionEnum), str, status); | |
237 *static_cast<DecimalFormat::EPadPosition *>(padPositionPtr) = | |
238 (DecimalFormat::EPadPosition) val; | |
239 } | |
240 | |
241 static void ePadPositionToStr( | |
242 const void *padPositionPtr, UnicodeString &appendTo) { | |
243 DecimalFormat::EPadPosition padPosition = | |
244 *static_cast<const DecimalFormat::EPadPosition *>(padPositionPtr); | |
245 fromEnum( | |
246 gPadPositionEnum, | |
247 UPRV_LENGTHOF(gPadPositionEnum), | |
248 padPosition, | |
249 appendTo); | |
250 } | |
251 | |
252 static void strToFormatStyle( | |
253 const UnicodeString &str, void *formatStylePtr, UErrorCode &status) { | |
254 int32_t val = toEnum( | |
255 gFormatStyleEnum, UPRV_LENGTHOF(gFormatStyleEnum), str, status); | |
256 *static_cast<UNumberFormatStyle *>(formatStylePtr) = (UNumberFormatStyle) va
l; | |
257 } | |
258 | |
259 static void formatStyleToStr( | |
260 const void *formatStylePtr, UnicodeString &appendTo) { | |
261 UNumberFormatStyle formatStyle = | |
262 *static_cast<const UNumberFormatStyle *>(formatStylePtr); | |
263 fromEnum( | |
264 gFormatStyleEnum, | |
265 UPRV_LENGTHOF(gFormatStyleEnum), | |
266 formatStyle, | |
267 appendTo); | |
268 } | |
269 | |
270 struct NumberFormatTestTupleFieldOps { | |
271 void (*toValue)(const UnicodeString &str, void *valPtr, UErrorCode &); | |
272 void (*toString)(const void *valPtr, UnicodeString &appendTo); | |
273 }; | |
274 | |
275 const NumberFormatTestTupleFieldOps gStrOps = {identVal, identStr}; | |
276 const NumberFormatTestTupleFieldOps gIntOps = {strToInt, intToStr}; | |
277 const NumberFormatTestTupleFieldOps gLocaleOps = {strToLocale, localeToStr}; | |
278 const NumberFormatTestTupleFieldOps gDoubleOps = {strToDouble, doubleToStr}; | |
279 const NumberFormatTestTupleFieldOps gERoundingOps = {strToERounding, eRoundingTo
Str}; | |
280 const NumberFormatTestTupleFieldOps gCurrencyUsageOps = {strToCurrencyUsage, cur
rencyUsageToStr}; | |
281 const NumberFormatTestTupleFieldOps gEPadPositionOps = {strToEPadPosition, ePadP
ositionToStr}; | |
282 const NumberFormatTestTupleFieldOps gFormatStyleOps = {strToFormatStyle, formatS
tyleToStr}; | |
283 | |
284 struct NumberFormatTestTupleFieldData { | |
285 const char *name; | |
286 int32_t offset; | |
287 int32_t flagOffset; | |
288 const NumberFormatTestTupleFieldOps *ops; | |
289 }; | |
290 | |
291 // Order must correspond to ENumberFormatTestTupleField | |
292 const NumberFormatTestTupleFieldData gFieldData[] = { | |
293 FIELD_INIT(locale, &gLocaleOps), | |
294 FIELD_INIT(currency, &gStrOps), | |
295 FIELD_INIT(pattern, &gStrOps), | |
296 FIELD_INIT(format, &gStrOps), | |
297 FIELD_INIT(output, &gStrOps), | |
298 FIELD_INIT(comment, &gStrOps), | |
299 FIELD_INIT(minIntegerDigits, &gIntOps), | |
300 FIELD_INIT(maxIntegerDigits, &gIntOps), | |
301 FIELD_INIT(minFractionDigits, &gIntOps), | |
302 FIELD_INIT(maxFractionDigits, &gIntOps), | |
303 FIELD_INIT(minGroupingDigits, &gIntOps), | |
304 FIELD_INIT(breaks, &gStrOps), | |
305 FIELD_INIT(useSigDigits, &gIntOps), | |
306 FIELD_INIT(minSigDigits, &gIntOps), | |
307 FIELD_INIT(maxSigDigits, &gIntOps), | |
308 FIELD_INIT(useGrouping, &gIntOps), | |
309 FIELD_INIT(multiplier, &gIntOps), | |
310 FIELD_INIT(roundingIncrement, &gDoubleOps), | |
311 FIELD_INIT(formatWidth, &gIntOps), | |
312 FIELD_INIT(padCharacter, &gStrOps), | |
313 FIELD_INIT(useScientific, &gIntOps), | |
314 FIELD_INIT(grouping, &gIntOps), | |
315 FIELD_INIT(grouping2, &gIntOps), | |
316 FIELD_INIT(roundingMode, &gERoundingOps), | |
317 FIELD_INIT(currencyUsage, &gCurrencyUsageOps), | |
318 FIELD_INIT(minimumExponentDigits, &gIntOps), | |
319 FIELD_INIT(exponentSignAlwaysShown, &gIntOps), | |
320 FIELD_INIT(decimalSeparatorAlwaysShown, &gIntOps), | |
321 FIELD_INIT(padPosition, &gEPadPositionOps), | |
322 FIELD_INIT(positivePrefix, &gStrOps), | |
323 FIELD_INIT(positiveSuffix, &gStrOps), | |
324 FIELD_INIT(negativePrefix, &gStrOps), | |
325 FIELD_INIT(negativeSuffix, &gStrOps), | |
326 FIELD_INIT(localizedPattern, &gStrOps), | |
327 FIELD_INIT(toPattern, &gStrOps), | |
328 FIELD_INIT(toLocalizedPattern, &gStrOps), | |
329 FIELD_INIT(style, &gFormatStyleOps), | |
330 FIELD_INIT(parse, &gStrOps), | |
331 FIELD_INIT(lenient, &gIntOps), | |
332 FIELD_INIT(plural, &gStrOps), | |
333 FIELD_INIT(parseIntegerOnly, &gIntOps), | |
334 FIELD_INIT(decimalPatternMatchRequired, &gIntOps), | |
335 FIELD_INIT(parseNoExponent, &gIntOps), | |
336 FIELD_INIT(outputCurrency, &gStrOps) | |
337 }; | |
338 | |
339 UBool | |
340 NumberFormatTestTuple::setField( | |
341 ENumberFormatTestTupleField fieldId, | |
342 const UnicodeString &fieldValue, | |
343 UErrorCode &status) { | |
344 if (U_FAILURE(status)) { | |
345 return FALSE; | |
346 } | |
347 if (fieldId == kNumberFormatTestTupleFieldCount) { | |
348 status = U_ILLEGAL_ARGUMENT_ERROR; | |
349 return FALSE; | |
350 } | |
351 gFieldData[fieldId].ops->toValue( | |
352 fieldValue, getMutableFieldAddress(fieldId), status); | |
353 if (U_FAILURE(status)) { | |
354 return FALSE; | |
355 } | |
356 setFlag(fieldId, TRUE); | |
357 return TRUE; | |
358 } | |
359 | |
360 UBool | |
361 NumberFormatTestTuple::clearField( | |
362 ENumberFormatTestTupleField fieldId, | |
363 UErrorCode &status) { | |
364 if (U_FAILURE(status)) { | |
365 return FALSE; | |
366 } | |
367 if (fieldId == kNumberFormatTestTupleFieldCount) { | |
368 status = U_ILLEGAL_ARGUMENT_ERROR; | |
369 return FALSE; | |
370 } | |
371 setFlag(fieldId, FALSE); | |
372 return TRUE; | |
373 } | |
374 | |
375 void | |
376 NumberFormatTestTuple::clear() { | |
377 for (int32_t i = 0; i < kNumberFormatTestTupleFieldCount; ++i) { | |
378 setFlag(i, FALSE); | |
379 } | |
380 } | |
381 | |
382 UnicodeString & | |
383 NumberFormatTestTuple::toString( | |
384 UnicodeString &appendTo) const { | |
385 appendTo.append("{"); | |
386 UBool first = TRUE; | |
387 for (int32_t i = 0; i < kNumberFormatTestTupleFieldCount; ++i) { | |
388 if (!isFlag(i)) { | |
389 continue; | |
390 } | |
391 if (!first) { | |
392 appendTo.append(", "); | |
393 } | |
394 first = FALSE; | |
395 appendTo.append(gFieldData[i].name); | |
396 appendTo.append(": "); | |
397 gFieldData[i].ops->toString(getFieldAddress(i), appendTo); | |
398 } | |
399 appendTo.append("}"); | |
400 return appendTo; | |
401 } | |
402 | |
403 ENumberFormatTestTupleField | |
404 NumberFormatTestTuple::getFieldByName( | |
405 const UnicodeString &name) { | |
406 CharString buffer; | |
407 UErrorCode status = U_ZERO_ERROR; | |
408 buffer.appendInvariantChars(name, status); | |
409 if (U_FAILURE(status)) { | |
410 return kNumberFormatTestTupleFieldCount; | |
411 } | |
412 int32_t result = -1; | |
413 for (int32_t i = 0; i < UPRV_LENGTHOF(gFieldData); ++i) { | |
414 if (uprv_strcmp(gFieldData[i].name, buffer.data()) == 0) { | |
415 result = i; | |
416 break; | |
417 } | |
418 } | |
419 if (result == -1) { | |
420 return kNumberFormatTestTupleFieldCount; | |
421 } | |
422 return (ENumberFormatTestTupleField) result; | |
423 } | |
424 | |
425 const void * | |
426 NumberFormatTestTuple::getFieldAddress(int32_t fieldId) const { | |
427 return reinterpret_cast<const char *>(this) + gFieldData[fieldId].offset; | |
428 } | |
429 | |
430 void * | |
431 NumberFormatTestTuple::getMutableFieldAddress(int32_t fieldId) { | |
432 return reinterpret_cast<char *>(this) + gFieldData[fieldId].offset; | |
433 } | |
434 | |
435 void | |
436 NumberFormatTestTuple::setFlag(int32_t fieldId, UBool value) { | |
437 void *flagAddr = reinterpret_cast<char *>(this) + gFieldData[fieldId].flagOf
fset; | |
438 *static_cast<UBool *>(flagAddr) = value; | |
439 } | |
440 | |
441 UBool | |
442 NumberFormatTestTuple::isFlag(int32_t fieldId) const { | |
443 const void *flagAddr = reinterpret_cast<const char *>(this) + gFieldData[fie
ldId].flagOffset; | |
444 return *static_cast<const UBool *>(flagAddr); | |
445 } | |
446 | |
447 #endif /* !UCONFIG_NO_FORMATTING */ | |
OLD | NEW |