1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
5 * Copyright (C) 2015, International Business Machines Corporation and *
6 * others. All Rights Reserved. *
7 *******************************************************************************
10 #include "numberformattesttuple.h"
12 #if !UCONFIG_NO_FORMATTING
20 static NumberFormatTestTuple
*gNullPtr
= NULL
;
22 #define FIELD_OFFSET(fieldName) ((int32_t) (((char *) &gNullPtr->fieldName) - ((char *) gNullPtr)))
23 #define FIELD_FLAG_OFFSET(fieldName) ((int32_t) (((char *) &gNullPtr->fieldName##Flag) - ((char *) gNullPtr)))
25 #define FIELD_INIT(fieldName, fieldType) {#fieldName, FIELD_OFFSET(fieldName), FIELD_FLAG_OFFSET(fieldName), fieldType}
27 struct Numberformattesttuple_EnumConversion
{
32 static Numberformattesttuple_EnumConversion gRoundingEnum
[] = {
33 {"ceiling", DecimalFormat::kRoundCeiling
},
34 {"floor", DecimalFormat::kRoundFloor
},
35 {"down", DecimalFormat::kRoundDown
},
36 {"up", DecimalFormat::kRoundUp
},
37 {"halfEven", DecimalFormat::kRoundHalfEven
},
38 {"halfDown", DecimalFormat::kRoundHalfDown
},
39 {"halfUp", DecimalFormat::kRoundHalfUp
},
40 {"unnecessary", DecimalFormat::kRoundUnnecessary
}};
42 static Numberformattesttuple_EnumConversion gCurrencyUsageEnum
[] = {
43 {"standard", UCURR_USAGE_STANDARD
},
44 {"cash", UCURR_USAGE_CASH
}};
46 static Numberformattesttuple_EnumConversion gPadPositionEnum
[] = {
47 {"beforePrefix", DecimalFormat::kPadBeforePrefix
},
48 {"afterPrefix", DecimalFormat::kPadAfterPrefix
},
49 {"beforeSuffix", DecimalFormat::kPadBeforeSuffix
},
50 {"afterSuffix", DecimalFormat::kPadAfterSuffix
}};
52 static Numberformattesttuple_EnumConversion gFormatStyleEnum
[] = {
53 {"patternDecimal", UNUM_PATTERN_DECIMAL
},
54 {"decimal", UNUM_DECIMAL
},
55 {"currency", UNUM_CURRENCY
},
56 {"percent", UNUM_PERCENT
},
57 {"scientific", UNUM_SCIENTIFIC
},
58 {"spellout", UNUM_SPELLOUT
},
59 {"ordinal", UNUM_ORDINAL
},
60 {"duration", UNUM_DURATION
},
61 {"numberingSystem", UNUM_NUMBERING_SYSTEM
},
62 {"patternRuleBased", UNUM_PATTERN_RULEBASED
},
63 {"currencyIso", UNUM_CURRENCY_ISO
},
64 {"currencyPlural", UNUM_CURRENCY_PLURAL
},
65 {"currencyAccounting", UNUM_CURRENCY_ACCOUNTING
},
66 {"cashCurrency", UNUM_CASH_CURRENCY
},
67 {"default", UNUM_DEFAULT
},
68 {"ignore", UNUM_IGNORE
}};
70 static int32_t toEnum(
71 const Numberformattesttuple_EnumConversion
*table
,
73 const UnicodeString
&str
,
75 if (U_FAILURE(status
)) {
79 cstr
.appendInvariantChars(str
, status
);
80 if (U_FAILURE(status
)) {
83 for (int32_t i
= 0; i
< tableLength
; ++i
) {
84 if (uprv_strcmp(cstr
.data(), table
[i
].str
) == 0) {
85 return table
[i
].value
;
88 status
= U_ILLEGAL_ARGUMENT_ERROR
;
93 const Numberformattesttuple_EnumConversion
*table
,
96 UnicodeString
&appendTo
) {
97 for (int32_t i
= 0; i
< tableLength
; ++i
) {
98 if (table
[i
].value
== val
) {
99 appendTo
.append(table
[i
].str
);
104 static void identVal(
105 const UnicodeString
&str
, void *strPtr
, UErrorCode
& /*status*/) {
106 *static_cast<UnicodeString
*>(strPtr
) = str
;
109 static void identStr(
110 const void *strPtr
, UnicodeString
&appendTo
) {
111 appendTo
.append(*static_cast<const UnicodeString
*>(strPtr
));
114 static void strToLocale(
115 const UnicodeString
&str
, void *localePtr
, UErrorCode
&status
) {
116 if (U_FAILURE(status
)) {
119 CharString localeStr
;
120 localeStr
.appendInvariantChars(str
, status
);
121 *static_cast<Locale
*>(localePtr
) = Locale(localeStr
.data());
124 static void localeToStr(
125 const void *localePtr
, UnicodeString
&appendTo
) {
128 static_cast<const Locale
*>(localePtr
)->getName()));
131 static void strToInt(
132 const UnicodeString
&str
, void *intPtr
, UErrorCode
&status
) {
133 if (U_FAILURE(status
)) {
136 int32_t len
= str
.length();
139 if (len
> 0 && str
[0] == 0x2D) { // negative
144 status
= U_ILLEGAL_ARGUMENT_ERROR
;
148 for (int32_t i
= start
; i
< len
; ++i
) {
150 if (ch
< 0x30 || ch
> 0x39) {
151 status
= U_ILLEGAL_ARGUMENT_ERROR
;
154 value
= value
* 10 - 0x30 + (int32_t) ch
;
159 *static_cast<int32_t *>(intPtr
) = value
;
162 static void intToStr(
163 const void *intPtr
, UnicodeString
&appendTo
) {
165 int32_t x
= *static_cast<const int32_t *>(intPtr
);
172 appendTo
.append((UChar
)0x2D);
174 int32_t len
= uprv_itou(buffer
, UPRV_LENGTHOF(buffer
), (uint32_t) x
, 10, 1);
175 appendTo
.append(buffer
, 0, len
);
178 static void strToDouble(
179 const UnicodeString
&str
, void *doublePtr
, UErrorCode
&status
) {
180 if (U_FAILURE(status
)) {
184 buffer
.appendInvariantChars(str
, status
);
185 if (U_FAILURE(status
)) {
188 *static_cast<double *>(doublePtr
) = atof(buffer
.data());
191 static void doubleToStr(
192 const void *doublePtr
, UnicodeString
&appendTo
) {
194 double x
= *static_cast<const double *>(doublePtr
);
195 sprintf(buffer
, "%f", x
);
196 appendTo
.append(buffer
);
199 static void strToERounding(
200 const UnicodeString
&str
, void *roundPtr
, UErrorCode
&status
) {
201 int32_t val
= toEnum(
202 gRoundingEnum
, UPRV_LENGTHOF(gRoundingEnum
), str
, status
);
203 *static_cast<DecimalFormat::ERoundingMode
*>(roundPtr
) = (DecimalFormat::ERoundingMode
) val
;
206 static void eRoundingToStr(
207 const void *roundPtr
, UnicodeString
&appendTo
) {
208 DecimalFormat::ERoundingMode rounding
=
209 *static_cast<const DecimalFormat::ERoundingMode
*>(roundPtr
);
212 UPRV_LENGTHOF(gRoundingEnum
),
217 static void strToCurrencyUsage(
218 const UnicodeString
&str
, void *currencyUsagePtr
, UErrorCode
&status
) {
219 int32_t val
= toEnum(
220 gCurrencyUsageEnum
, UPRV_LENGTHOF(gCurrencyUsageEnum
), str
, status
);
221 *static_cast<UCurrencyUsage
*>(currencyUsagePtr
) = (UCurrencyUsage
) val
;
224 static void currencyUsageToStr(
225 const void *currencyUsagePtr
, UnicodeString
&appendTo
) {
226 UCurrencyUsage currencyUsage
=
227 *static_cast<const UCurrencyUsage
*>(currencyUsagePtr
);
230 UPRV_LENGTHOF(gCurrencyUsageEnum
),
235 static void strToEPadPosition(
236 const UnicodeString
&str
, void *padPositionPtr
, UErrorCode
&status
) {
237 int32_t val
= toEnum(
238 gPadPositionEnum
, UPRV_LENGTHOF(gPadPositionEnum
), str
, status
);
239 *static_cast<DecimalFormat::EPadPosition
*>(padPositionPtr
) =
240 (DecimalFormat::EPadPosition
) val
;
243 static void ePadPositionToStr(
244 const void *padPositionPtr
, UnicodeString
&appendTo
) {
245 DecimalFormat::EPadPosition padPosition
=
246 *static_cast<const DecimalFormat::EPadPosition
*>(padPositionPtr
);
249 UPRV_LENGTHOF(gPadPositionEnum
),
254 static void strToFormatStyle(
255 const UnicodeString
&str
, void *formatStylePtr
, UErrorCode
&status
) {
256 int32_t val
= toEnum(
257 gFormatStyleEnum
, UPRV_LENGTHOF(gFormatStyleEnum
), str
, status
);
258 *static_cast<UNumberFormatStyle
*>(formatStylePtr
) = (UNumberFormatStyle
) val
;
261 static void formatStyleToStr(
262 const void *formatStylePtr
, UnicodeString
&appendTo
) {
263 UNumberFormatStyle formatStyle
=
264 *static_cast<const UNumberFormatStyle
*>(formatStylePtr
);
267 UPRV_LENGTHOF(gFormatStyleEnum
),
272 struct NumberFormatTestTupleFieldOps
{
273 void (*toValue
)(const UnicodeString
&str
, void *valPtr
, UErrorCode
&);
274 void (*toString
)(const void *valPtr
, UnicodeString
&appendTo
);
277 const NumberFormatTestTupleFieldOps gStrOps
= {identVal
, identStr
};
278 const NumberFormatTestTupleFieldOps gIntOps
= {strToInt
, intToStr
};
279 const NumberFormatTestTupleFieldOps gLocaleOps
= {strToLocale
, localeToStr
};
280 const NumberFormatTestTupleFieldOps gDoubleOps
= {strToDouble
, doubleToStr
};
281 const NumberFormatTestTupleFieldOps gERoundingOps
= {strToERounding
, eRoundingToStr
};
282 const NumberFormatTestTupleFieldOps gCurrencyUsageOps
= {strToCurrencyUsage
, currencyUsageToStr
};
283 const NumberFormatTestTupleFieldOps gEPadPositionOps
= {strToEPadPosition
, ePadPositionToStr
};
284 const NumberFormatTestTupleFieldOps gFormatStyleOps
= {strToFormatStyle
, formatStyleToStr
};
286 struct NumberFormatTestTupleFieldData
{
290 const NumberFormatTestTupleFieldOps
*ops
;
293 // Order must correspond to ENumberFormatTestTupleField
294 const NumberFormatTestTupleFieldData gFieldData
[] = {
295 FIELD_INIT(locale
, &gLocaleOps
),
296 FIELD_INIT(currency
, &gStrOps
),
297 FIELD_INIT(pattern
, &gStrOps
),
298 FIELD_INIT(format
, &gStrOps
),
299 FIELD_INIT(output
, &gStrOps
),
300 FIELD_INIT(comment
, &gStrOps
),
301 FIELD_INIT(minIntegerDigits
, &gIntOps
),
302 FIELD_INIT(maxIntegerDigits
, &gIntOps
),
303 FIELD_INIT(minFractionDigits
, &gIntOps
),
304 FIELD_INIT(maxFractionDigits
, &gIntOps
),
305 FIELD_INIT(minGroupingDigits
, &gIntOps
),
306 FIELD_INIT(breaks
, &gStrOps
),
307 FIELD_INIT(useSigDigits
, &gIntOps
),
308 FIELD_INIT(minSigDigits
, &gIntOps
),
309 FIELD_INIT(maxSigDigits
, &gIntOps
),
310 FIELD_INIT(useGrouping
, &gIntOps
),
311 FIELD_INIT(multiplier
, &gIntOps
),
312 FIELD_INIT(roundingIncrement
, &gDoubleOps
),
313 FIELD_INIT(formatWidth
, &gIntOps
),
314 FIELD_INIT(padCharacter
, &gStrOps
),
315 FIELD_INIT(useScientific
, &gIntOps
),
316 FIELD_INIT(grouping
, &gIntOps
),
317 FIELD_INIT(grouping2
, &gIntOps
),
318 FIELD_INIT(roundingMode
, &gERoundingOps
),
319 FIELD_INIT(currencyUsage
, &gCurrencyUsageOps
),
320 FIELD_INIT(minimumExponentDigits
, &gIntOps
),
321 FIELD_INIT(exponentSignAlwaysShown
, &gIntOps
),
322 FIELD_INIT(decimalSeparatorAlwaysShown
, &gIntOps
),
323 FIELD_INIT(padPosition
, &gEPadPositionOps
),
324 FIELD_INIT(positivePrefix
, &gStrOps
),
325 FIELD_INIT(positiveSuffix
, &gStrOps
),
326 FIELD_INIT(negativePrefix
, &gStrOps
),
327 FIELD_INIT(negativeSuffix
, &gStrOps
),
328 FIELD_INIT(localizedPattern
, &gStrOps
),
329 FIELD_INIT(toPattern
, &gStrOps
),
330 FIELD_INIT(toLocalizedPattern
, &gStrOps
),
331 FIELD_INIT(style
, &gFormatStyleOps
),
332 FIELD_INIT(parse
, &gStrOps
),
333 FIELD_INIT(lenient
, &gIntOps
),
334 FIELD_INIT(plural
, &gStrOps
),
335 FIELD_INIT(parseIntegerOnly
, &gIntOps
),
336 FIELD_INIT(decimalPatternMatchRequired
, &gIntOps
),
337 FIELD_INIT(parseNoExponent
, &gIntOps
),
338 FIELD_INIT(outputCurrency
, &gStrOps
)
342 NumberFormatTestTuple::setField(
343 ENumberFormatTestTupleField fieldId
,
344 const UnicodeString
&fieldValue
,
345 UErrorCode
&status
) {
346 if (U_FAILURE(status
)) {
349 if (fieldId
== kNumberFormatTestTupleFieldCount
) {
350 status
= U_ILLEGAL_ARGUMENT_ERROR
;
353 gFieldData
[fieldId
].ops
->toValue(
354 fieldValue
, getMutableFieldAddress(fieldId
), status
);
355 if (U_FAILURE(status
)) {
358 setFlag(fieldId
, TRUE
);
363 NumberFormatTestTuple::clearField(
364 ENumberFormatTestTupleField fieldId
,
365 UErrorCode
&status
) {
366 if (U_FAILURE(status
)) {
369 if (fieldId
== kNumberFormatTestTupleFieldCount
) {
370 status
= U_ILLEGAL_ARGUMENT_ERROR
;
373 setFlag(fieldId
, FALSE
);
378 NumberFormatTestTuple::clear() {
379 for (int32_t i
= 0; i
< kNumberFormatTestTupleFieldCount
; ++i
) {
385 NumberFormatTestTuple::toString(
386 UnicodeString
&appendTo
) const {
387 appendTo
.append("{");
389 for (int32_t i
= 0; i
< kNumberFormatTestTupleFieldCount
; ++i
) {
394 appendTo
.append(", ");
397 appendTo
.append(gFieldData
[i
].name
);
398 appendTo
.append(": ");
399 gFieldData
[i
].ops
->toString(getFieldAddress(i
), appendTo
);
401 appendTo
.append("}");
405 ENumberFormatTestTupleField
406 NumberFormatTestTuple::getFieldByName(
407 const UnicodeString
&name
) {
409 UErrorCode status
= U_ZERO_ERROR
;
410 buffer
.appendInvariantChars(name
, status
);
411 if (U_FAILURE(status
)) {
412 return kNumberFormatTestTupleFieldCount
;
415 for (int32_t i
= 0; i
< UPRV_LENGTHOF(gFieldData
); ++i
) {
416 if (uprv_strcmp(gFieldData
[i
].name
, buffer
.data()) == 0) {
422 return kNumberFormatTestTupleFieldCount
;
424 return (ENumberFormatTestTupleField
) result
;
428 NumberFormatTestTuple::getFieldAddress(int32_t fieldId
) const {
429 return reinterpret_cast<const char *>(this) + gFieldData
[fieldId
].offset
;
433 NumberFormatTestTuple::getMutableFieldAddress(int32_t fieldId
) {
434 return reinterpret_cast<char *>(this) + gFieldData
[fieldId
].offset
;
438 NumberFormatTestTuple::setFlag(int32_t fieldId
, UBool value
) {
439 void *flagAddr
= reinterpret_cast<char *>(this) + gFieldData
[fieldId
].flagOffset
;
440 *static_cast<UBool
*>(flagAddr
) = value
;
444 NumberFormatTestTuple::isFlag(int32_t fieldId
) const {
445 const void *flagAddr
= reinterpret_cast<const char *>(this) + gFieldData
[fieldId
].flagOffset
;
446 return *static_cast<const UBool
*>(flagAddr
);
449 #endif /* !UCONFIG_NO_FORMATTING */