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
19 static NumberFormatTestTuple
*gNullPtr
= NULL
;
21 #define FIELD_OFFSET(fieldName) ((int32_t) (((char *) &gNullPtr->fieldName) - ((char *) gNullPtr)))
22 #define FIELD_FLAG_OFFSET(fieldName) ((int32_t) (((char *) &gNullPtr->fieldName##Flag) - ((char *) gNullPtr)))
24 #define FIELD_INIT(fieldName, fieldType) {#fieldName, FIELD_OFFSET(fieldName), FIELD_FLAG_OFFSET(fieldName), fieldType}
26 struct Numberformattesttuple_EnumConversion
{
31 static Numberformattesttuple_EnumConversion gRoundingEnum
[] = {
32 {"ceiling", DecimalFormat::kRoundCeiling
},
33 {"floor", DecimalFormat::kRoundFloor
},
34 {"down", DecimalFormat::kRoundDown
},
35 {"up", DecimalFormat::kRoundUp
},
36 {"halfEven", DecimalFormat::kRoundHalfEven
},
37 {"halfDown", DecimalFormat::kRoundHalfDown
},
38 {"halfUp", DecimalFormat::kRoundHalfUp
},
39 {"unnecessary", DecimalFormat::kRoundUnnecessary
}};
41 static Numberformattesttuple_EnumConversion gCurrencyUsageEnum
[] = {
42 {"standard", UCURR_USAGE_STANDARD
},
43 {"cash", UCURR_USAGE_CASH
}};
45 static Numberformattesttuple_EnumConversion gPadPositionEnum
[] = {
46 {"beforePrefix", DecimalFormat::kPadBeforePrefix
},
47 {"afterPrefix", DecimalFormat::kPadAfterPrefix
},
48 {"beforeSuffix", DecimalFormat::kPadBeforeSuffix
},
49 {"afterSuffix", DecimalFormat::kPadAfterSuffix
}};
51 static Numberformattesttuple_EnumConversion gFormatStyleEnum
[] = {
52 {"patternDecimal", UNUM_PATTERN_DECIMAL
},
53 {"decimal", UNUM_DECIMAL
},
54 {"currency", UNUM_CURRENCY
},
55 {"percent", UNUM_PERCENT
},
56 {"scientific", UNUM_SCIENTIFIC
},
57 {"spellout", UNUM_SPELLOUT
},
58 {"ordinal", UNUM_ORDINAL
},
59 {"duration", UNUM_DURATION
},
60 {"numberingSystem", UNUM_NUMBERING_SYSTEM
},
61 {"patternRuleBased", UNUM_PATTERN_RULEBASED
},
62 {"currencyIso", UNUM_CURRENCY_ISO
},
63 {"currencyPlural", UNUM_CURRENCY_PLURAL
},
64 {"currencyAccounting", UNUM_CURRENCY_ACCOUNTING
},
65 {"cashCurrency", UNUM_CASH_CURRENCY
},
66 {"default", UNUM_DEFAULT
},
67 {"ignore", UNUM_IGNORE
}};
69 static int32_t toEnum(
70 const Numberformattesttuple_EnumConversion
*table
,
72 const UnicodeString
&str
,
74 if (U_FAILURE(status
)) {
78 cstr
.appendInvariantChars(str
, status
);
79 if (U_FAILURE(status
)) {
82 for (int32_t i
= 0; i
< tableLength
; ++i
) {
83 if (uprv_strcmp(cstr
.data(), table
[i
].str
) == 0) {
84 return table
[i
].value
;
87 status
= U_ILLEGAL_ARGUMENT_ERROR
;
92 const Numberformattesttuple_EnumConversion
*table
,
95 UnicodeString
&appendTo
) {
96 for (int32_t i
= 0; i
< tableLength
; ++i
) {
97 if (table
[i
].value
== val
) {
98 appendTo
.append(table
[i
].str
);
103 static void identVal(
104 const UnicodeString
&str
, void *strPtr
, UErrorCode
& /*status*/) {
105 *static_cast<UnicodeString
*>(strPtr
) = str
;
108 static void identStr(
109 const void *strPtr
, UnicodeString
&appendTo
) {
110 appendTo
.append(*static_cast<const UnicodeString
*>(strPtr
));
113 static void strToLocale(
114 const UnicodeString
&str
, void *localePtr
, UErrorCode
&status
) {
115 if (U_FAILURE(status
)) {
118 CharString localeStr
;
119 localeStr
.appendInvariantChars(str
, status
);
120 *static_cast<Locale
*>(localePtr
) = Locale(localeStr
.data());
123 static void localeToStr(
124 const void *localePtr
, UnicodeString
&appendTo
) {
127 static_cast<const Locale
*>(localePtr
)->getName()));
130 static void strToInt(
131 const UnicodeString
&str
, void *intPtr
, UErrorCode
&status
) {
132 if (U_FAILURE(status
)) {
135 int32_t len
= str
.length();
138 if (len
> 0 && str
[0] == 0x2D) { // negative
143 status
= U_ILLEGAL_ARGUMENT_ERROR
;
147 for (int32_t i
= start
; i
< len
; ++i
) {
149 if (ch
< 0x30 || ch
> 0x39) {
150 status
= U_ILLEGAL_ARGUMENT_ERROR
;
153 value
= value
* 10 - 0x30 + (int32_t) ch
;
155 int32_t signedValue
= neg
? static_cast<int32_t>(-value
) : static_cast<int32_t>(value
);
156 *static_cast<int32_t *>(intPtr
) = signedValue
;
159 static void intToStr(
160 const void *intPtr
, UnicodeString
&appendTo
) {
162 // int64_t such that all int32_t values can be negated
163 int64_t xSigned
= *static_cast<const int32_t *>(intPtr
);
166 appendTo
.append((UChar
)0x2D);
167 x
= static_cast<uint32_t>(-xSigned
);
169 x
= static_cast<uint32_t>(xSigned
);
171 int32_t len
= uprv_itou(buffer
, UPRV_LENGTHOF(buffer
), x
, 10, 1);
172 appendTo
.append(buffer
, 0, len
);
175 static void strToDouble(
176 const UnicodeString
&str
, void *doublePtr
, UErrorCode
&status
) {
177 if (U_FAILURE(status
)) {
181 buffer
.appendInvariantChars(str
, status
);
182 if (U_FAILURE(status
)) {
185 *static_cast<double *>(doublePtr
) = atof(buffer
.data());
188 static void doubleToStr(
189 const void *doublePtr
, UnicodeString
&appendTo
) {
191 double x
= *static_cast<const double *>(doublePtr
);
192 sprintf(buffer
, "%f", x
);
193 appendTo
.append(buffer
);
196 static void strToERounding(
197 const UnicodeString
&str
, void *roundPtr
, UErrorCode
&status
) {
198 int32_t val
= toEnum(
199 gRoundingEnum
, UPRV_LENGTHOF(gRoundingEnum
), str
, status
);
200 *static_cast<DecimalFormat::ERoundingMode
*>(roundPtr
) = (DecimalFormat::ERoundingMode
) val
;
203 static void eRoundingToStr(
204 const void *roundPtr
, UnicodeString
&appendTo
) {
205 DecimalFormat::ERoundingMode rounding
=
206 *static_cast<const DecimalFormat::ERoundingMode
*>(roundPtr
);
209 UPRV_LENGTHOF(gRoundingEnum
),
214 static void strToCurrencyUsage(
215 const UnicodeString
&str
, void *currencyUsagePtr
, UErrorCode
&status
) {
216 int32_t val
= toEnum(
217 gCurrencyUsageEnum
, UPRV_LENGTHOF(gCurrencyUsageEnum
), str
, status
);
218 *static_cast<UCurrencyUsage
*>(currencyUsagePtr
) = (UCurrencyUsage
) val
;
221 static void currencyUsageToStr(
222 const void *currencyUsagePtr
, UnicodeString
&appendTo
) {
223 UCurrencyUsage currencyUsage
=
224 *static_cast<const UCurrencyUsage
*>(currencyUsagePtr
);
227 UPRV_LENGTHOF(gCurrencyUsageEnum
),
232 static void strToEPadPosition(
233 const UnicodeString
&str
, void *padPositionPtr
, UErrorCode
&status
) {
234 int32_t val
= toEnum(
235 gPadPositionEnum
, UPRV_LENGTHOF(gPadPositionEnum
), str
, status
);
236 *static_cast<DecimalFormat::EPadPosition
*>(padPositionPtr
) =
237 (DecimalFormat::EPadPosition
) val
;
240 static void ePadPositionToStr(
241 const void *padPositionPtr
, UnicodeString
&appendTo
) {
242 DecimalFormat::EPadPosition padPosition
=
243 *static_cast<const DecimalFormat::EPadPosition
*>(padPositionPtr
);
246 UPRV_LENGTHOF(gPadPositionEnum
),
251 static void strToFormatStyle(
252 const UnicodeString
&str
, void *formatStylePtr
, UErrorCode
&status
) {
253 int32_t val
= toEnum(
254 gFormatStyleEnum
, UPRV_LENGTHOF(gFormatStyleEnum
), str
, status
);
255 *static_cast<UNumberFormatStyle
*>(formatStylePtr
) = (UNumberFormatStyle
) val
;
258 static void formatStyleToStr(
259 const void *formatStylePtr
, UnicodeString
&appendTo
) {
260 UNumberFormatStyle formatStyle
=
261 *static_cast<const UNumberFormatStyle
*>(formatStylePtr
);
264 UPRV_LENGTHOF(gFormatStyleEnum
),
269 struct NumberFormatTestTupleFieldOps
{
270 void (*toValue
)(const UnicodeString
&str
, void *valPtr
, UErrorCode
&);
271 void (*toString
)(const void *valPtr
, UnicodeString
&appendTo
);
274 const NumberFormatTestTupleFieldOps gStrOps
= {identVal
, identStr
};
275 const NumberFormatTestTupleFieldOps gIntOps
= {strToInt
, intToStr
};
276 const NumberFormatTestTupleFieldOps gLocaleOps
= {strToLocale
, localeToStr
};
277 const NumberFormatTestTupleFieldOps gDoubleOps
= {strToDouble
, doubleToStr
};
278 const NumberFormatTestTupleFieldOps gERoundingOps
= {strToERounding
, eRoundingToStr
};
279 const NumberFormatTestTupleFieldOps gCurrencyUsageOps
= {strToCurrencyUsage
, currencyUsageToStr
};
280 const NumberFormatTestTupleFieldOps gEPadPositionOps
= {strToEPadPosition
, ePadPositionToStr
};
281 const NumberFormatTestTupleFieldOps gFormatStyleOps
= {strToFormatStyle
, formatStyleToStr
};
283 struct NumberFormatTestTupleFieldData
{
287 const NumberFormatTestTupleFieldOps
*ops
;
290 // Order must correspond to ENumberFormatTestTupleField
291 const NumberFormatTestTupleFieldData gFieldData
[] = {
292 FIELD_INIT(locale
, &gLocaleOps
),
293 FIELD_INIT(currency
, &gStrOps
),
294 FIELD_INIT(pattern
, &gStrOps
),
295 FIELD_INIT(format
, &gStrOps
),
296 FIELD_INIT(output
, &gStrOps
),
297 FIELD_INIT(comment
, &gStrOps
),
298 FIELD_INIT(minIntegerDigits
, &gIntOps
),
299 FIELD_INIT(maxIntegerDigits
, &gIntOps
),
300 FIELD_INIT(minFractionDigits
, &gIntOps
),
301 FIELD_INIT(maxFractionDigits
, &gIntOps
),
302 FIELD_INIT(minGroupingDigits
, &gIntOps
),
303 FIELD_INIT(breaks
, &gStrOps
),
304 FIELD_INIT(useSigDigits
, &gIntOps
),
305 FIELD_INIT(minSigDigits
, &gIntOps
),
306 FIELD_INIT(maxSigDigits
, &gIntOps
),
307 FIELD_INIT(useGrouping
, &gIntOps
),
308 FIELD_INIT(multiplier
, &gIntOps
),
309 FIELD_INIT(roundingIncrement
, &gDoubleOps
),
310 FIELD_INIT(formatWidth
, &gIntOps
),
311 FIELD_INIT(padCharacter
, &gStrOps
),
312 FIELD_INIT(useScientific
, &gIntOps
),
313 FIELD_INIT(grouping
, &gIntOps
),
314 FIELD_INIT(grouping2
, &gIntOps
),
315 FIELD_INIT(roundingMode
, &gERoundingOps
),
316 FIELD_INIT(currencyUsage
, &gCurrencyUsageOps
),
317 FIELD_INIT(minimumExponentDigits
, &gIntOps
),
318 FIELD_INIT(exponentSignAlwaysShown
, &gIntOps
),
319 FIELD_INIT(decimalSeparatorAlwaysShown
, &gIntOps
),
320 FIELD_INIT(padPosition
, &gEPadPositionOps
),
321 FIELD_INIT(positivePrefix
, &gStrOps
),
322 FIELD_INIT(positiveSuffix
, &gStrOps
),
323 FIELD_INIT(negativePrefix
, &gStrOps
),
324 FIELD_INIT(negativeSuffix
, &gStrOps
),
325 FIELD_INIT(signAlwaysShown
, &gIntOps
),
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(parseCaseSensitive
, &gIntOps
),
337 FIELD_INIT(outputCurrency
, &gStrOps
)
341 NumberFormatTestTuple::setField(
342 ENumberFormatTestTupleField fieldId
,
343 const UnicodeString
&fieldValue
,
344 UErrorCode
&status
) {
345 if (U_FAILURE(status
)) {
348 if (fieldId
== kNumberFormatTestTupleFieldCount
) {
349 status
= U_ILLEGAL_ARGUMENT_ERROR
;
352 gFieldData
[fieldId
].ops
->toValue(
353 fieldValue
, getMutableFieldAddress(fieldId
), status
);
354 if (U_FAILURE(status
)) {
357 setFlag(fieldId
, TRUE
);
362 NumberFormatTestTuple::clearField(
363 ENumberFormatTestTupleField fieldId
,
364 UErrorCode
&status
) {
365 if (U_FAILURE(status
)) {
368 if (fieldId
== kNumberFormatTestTupleFieldCount
) {
369 status
= U_ILLEGAL_ARGUMENT_ERROR
;
372 setFlag(fieldId
, FALSE
);
377 NumberFormatTestTuple::clear() {
378 for (int32_t i
= 0; i
< kNumberFormatTestTupleFieldCount
; ++i
) {
384 NumberFormatTestTuple::toString(
385 UnicodeString
&appendTo
) const {
386 appendTo
.append("{");
388 for (int32_t i
= 0; i
< kNumberFormatTestTupleFieldCount
; ++i
) {
393 appendTo
.append(", ");
396 appendTo
.append(gFieldData
[i
].name
);
397 appendTo
.append(": ");
398 gFieldData
[i
].ops
->toString(getFieldAddress(i
), appendTo
);
400 appendTo
.append("}");
404 ENumberFormatTestTupleField
405 NumberFormatTestTuple::getFieldByName(
406 const UnicodeString
&name
) {
408 UErrorCode status
= U_ZERO_ERROR
;
409 buffer
.appendInvariantChars(name
, status
);
410 if (U_FAILURE(status
)) {
411 return kNumberFormatTestTupleFieldCount
;
414 for (int32_t i
= 0; i
< UPRV_LENGTHOF(gFieldData
); ++i
) {
415 if (uprv_strcmp(gFieldData
[i
].name
, buffer
.data()) == 0) {
421 return kNumberFormatTestTupleFieldCount
;
423 return (ENumberFormatTestTupleField
) result
;
427 NumberFormatTestTuple::getFieldAddress(int32_t fieldId
) const {
428 return reinterpret_cast<const char *>(this) + gFieldData
[fieldId
].offset
;
432 NumberFormatTestTuple::getMutableFieldAddress(int32_t fieldId
) {
433 return reinterpret_cast<char *>(this) + gFieldData
[fieldId
].offset
;
437 NumberFormatTestTuple::setFlag(int32_t fieldId
, UBool value
) {
438 void *flagAddr
= reinterpret_cast<char *>(this) + gFieldData
[fieldId
].flagOffset
;
439 *static_cast<UBool
*>(flagAddr
) = value
;
443 NumberFormatTestTuple::isFlag(int32_t fieldId
) const {
444 const void *flagAddr
= reinterpret_cast<const char *>(this) + gFieldData
[fieldId
].flagOffset
;
445 return *static_cast<const UBool
*>(flagAddr
);
448 #endif /* !UCONFIG_NO_FORMATTING */