Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 1 | // © 2016 and later: Unicode, Inc. and others. |
| 2 | // License & terms of use: http://www.unicode.org/copyright.html |
| 3 | /* |
| 4 | ******************************************************************************* |
| 5 | * Copyright (C) 2015, International Business Machines Corporation and * |
| 6 | * others. All Rights Reserved. * |
| 7 | ******************************************************************************* |
| 8 | */ |
| 9 | |
| 10 | #include "numberformattesttuple.h" |
| 11 | |
| 12 | #if !UCONFIG_NO_FORMATTING |
| 13 | |
| 14 | #include "unicode/testlog.h" |
| 15 | #include "ustrfmt.h" |
| 16 | #include "charstr.h" |
| 17 | #include "cstring.h" |
| 18 | #include "cmemory.h" |
| 19 | |
| 20 | static NumberFormatTestTuple emptyObject; |
| 21 | |
| 22 | static NumberFormatTestTuple *gNullPtr = &emptyObject; |
| 23 | |
| 24 | #define FIELD_OFFSET(fieldName) ((int32_t) (((char *) &gNullPtr->fieldName) - ((char *) gNullPtr))) |
| 25 | #define FIELD_FLAG_OFFSET(fieldName) ((int32_t) (((char *) &gNullPtr->fieldName##Flag) - ((char *) gNullPtr))) |
| 26 | |
| 27 | #define FIELD_INIT(fieldName, fieldType) {#fieldName, FIELD_OFFSET(fieldName), FIELD_FLAG_OFFSET(fieldName), fieldType} |
| 28 | |
| 29 | struct Numberformattesttuple_EnumConversion { |
| 30 | const char *str; |
| 31 | int32_t value; |
| 32 | }; |
| 33 | |
| 34 | static Numberformattesttuple_EnumConversion gRoundingEnum[] = { |
| 35 | {"ceiling", DecimalFormat::kRoundCeiling}, |
| 36 | {"floor", DecimalFormat::kRoundFloor}, |
| 37 | {"down", DecimalFormat::kRoundDown}, |
| 38 | {"up", DecimalFormat::kRoundUp}, |
| 39 | {"halfEven", DecimalFormat::kRoundHalfEven}, |
| 40 | {"halfDown", DecimalFormat::kRoundHalfDown}, |
| 41 | {"halfUp", DecimalFormat::kRoundHalfUp}, |
| 42 | {"unnecessary", DecimalFormat::kRoundUnnecessary}}; |
| 43 | |
| 44 | static Numberformattesttuple_EnumConversion gCurrencyUsageEnum[] = { |
| 45 | {"standard", UCURR_USAGE_STANDARD}, |
| 46 | {"cash", UCURR_USAGE_CASH}}; |
| 47 | |
| 48 | static Numberformattesttuple_EnumConversion gPadPositionEnum[] = { |
| 49 | {"beforePrefix", DecimalFormat::kPadBeforePrefix}, |
| 50 | {"afterPrefix", DecimalFormat::kPadAfterPrefix}, |
| 51 | {"beforeSuffix", DecimalFormat::kPadBeforeSuffix}, |
| 52 | {"afterSuffix", DecimalFormat::kPadAfterSuffix}}; |
| 53 | |
| 54 | static Numberformattesttuple_EnumConversion gFormatStyleEnum[] = { |
| 55 | {"patternDecimal", UNUM_PATTERN_DECIMAL}, |
| 56 | {"decimal", UNUM_DECIMAL}, |
| 57 | {"currency", UNUM_CURRENCY}, |
| 58 | {"percent", UNUM_PERCENT}, |
| 59 | {"scientific", UNUM_SCIENTIFIC}, |
| 60 | {"spellout", UNUM_SPELLOUT}, |
| 61 | {"ordinal", UNUM_ORDINAL}, |
| 62 | {"duration", UNUM_DURATION}, |
| 63 | {"numberingSystem", UNUM_NUMBERING_SYSTEM}, |
| 64 | {"patternRuleBased", UNUM_PATTERN_RULEBASED}, |
| 65 | {"currencyIso", UNUM_CURRENCY_ISO}, |
| 66 | {"currencyPlural", UNUM_CURRENCY_PLURAL}, |
| 67 | {"currencyAccounting", UNUM_CURRENCY_ACCOUNTING}, |
| 68 | {"cashCurrency", UNUM_CASH_CURRENCY}, |
| 69 | {"default", UNUM_DEFAULT}, |
| 70 | {"ignore", UNUM_IGNORE}}; |
| 71 | |
| 72 | static int32_t toEnum( |
| 73 | const Numberformattesttuple_EnumConversion *table, |
| 74 | int32_t tableLength, |
| 75 | const UnicodeString &str, |
| 76 | UErrorCode &status) { |
| 77 | if (U_FAILURE(status)) { |
| 78 | return 0; |
| 79 | } |
| 80 | CharString cstr; |
| 81 | cstr.appendInvariantChars(str, status); |
| 82 | if (U_FAILURE(status)) { |
| 83 | return 0; |
| 84 | } |
| 85 | for (int32_t i = 0; i < tableLength; ++i) { |
| 86 | if (uprv_strcmp(cstr.data(), table[i].str) == 0) { |
| 87 | return table[i].value; |
| 88 | } |
| 89 | } |
| 90 | status = U_ILLEGAL_ARGUMENT_ERROR; |
| 91 | return 0; |
| 92 | } |
| 93 | |
| 94 | static void fromEnum( |
| 95 | const Numberformattesttuple_EnumConversion *table, |
| 96 | int32_t tableLength, |
| 97 | int32_t val, |
| 98 | UnicodeString &appendTo) { |
| 99 | for (int32_t i = 0; i < tableLength; ++i) { |
| 100 | if (table[i].value == val) { |
| 101 | appendTo.append(table[i].str); |
| 102 | } |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | static void identVal( |
| 107 | const UnicodeString &str, void *strPtr, UErrorCode & /*status*/) { |
| 108 | *static_cast<UnicodeString *>(strPtr) = str; |
| 109 | } |
| 110 | |
| 111 | static void identStr( |
| 112 | const void *strPtr, UnicodeString &appendTo) { |
| 113 | appendTo.append(*static_cast<const UnicodeString *>(strPtr)); |
| 114 | } |
| 115 | |
| 116 | static void strToLocale( |
| 117 | const UnicodeString &str, void *localePtr, UErrorCode &status) { |
| 118 | if (U_FAILURE(status)) { |
| 119 | return; |
| 120 | } |
| 121 | CharString localeStr; |
| 122 | localeStr.appendInvariantChars(str, status); |
| 123 | *static_cast<Locale *>(localePtr) = Locale(localeStr.data()); |
| 124 | } |
| 125 | |
| 126 | static void localeToStr( |
| 127 | const void *localePtr, UnicodeString &appendTo) { |
| 128 | appendTo.append( |
| 129 | UnicodeString( |
| 130 | static_cast<const Locale *>(localePtr)->getName())); |
| 131 | } |
| 132 | |
| 133 | static void strToInt( |
| 134 | const UnicodeString &str, void *intPtr, UErrorCode &status) { |
| 135 | if (U_FAILURE(status)) { |
| 136 | return; |
| 137 | } |
| 138 | int32_t len = str.length(); |
| 139 | int32_t start = 0; |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 140 | UBool neg = false; |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 141 | if (len > 0 && str[0] == 0x2D) { // negative |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 142 | neg = true; |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 143 | start = 1; |
| 144 | } |
| 145 | if (start == len) { |
| 146 | status = U_ILLEGAL_ARGUMENT_ERROR; |
| 147 | return; |
| 148 | } |
| 149 | int64_t value = 0; |
| 150 | for (int32_t i = start; i < len; ++i) { |
| 151 | UChar ch = str[i]; |
| 152 | if (ch < 0x30 || ch > 0x39) { |
| 153 | status = U_ILLEGAL_ARGUMENT_ERROR; |
| 154 | return; |
| 155 | } |
| 156 | value = value * 10 - 0x30 + (int32_t) ch; |
| 157 | } |
| 158 | int32_t signedValue = neg ? static_cast<int32_t>(-value) : static_cast<int32_t>(value); |
| 159 | *static_cast<int32_t *>(intPtr) = signedValue; |
| 160 | } |
| 161 | |
| 162 | static void intToStr( |
| 163 | const void *intPtr, UnicodeString &appendTo) { |
| 164 | UChar buffer[20]; |
| 165 | // int64_t such that all int32_t values can be negated |
| 166 | int64_t xSigned = *static_cast<const int32_t *>(intPtr); |
| 167 | uint32_t x; |
| 168 | if (xSigned < 0) { |
| 169 | appendTo.append((UChar)0x2D); |
| 170 | x = static_cast<uint32_t>(-xSigned); |
| 171 | } else { |
| 172 | x = static_cast<uint32_t>(xSigned); |
| 173 | } |
| 174 | int32_t len = uprv_itou(buffer, UPRV_LENGTHOF(buffer), x, 10, 1); |
| 175 | appendTo.append(buffer, 0, len); |
| 176 | } |
| 177 | |
| 178 | static void strToDouble( |
| 179 | const UnicodeString &str, void *doublePtr, UErrorCode &status) { |
| 180 | if (U_FAILURE(status)) { |
| 181 | return; |
| 182 | } |
| 183 | CharString buffer; |
| 184 | buffer.appendInvariantChars(str, status); |
| 185 | if (U_FAILURE(status)) { |
| 186 | return; |
| 187 | } |
| 188 | *static_cast<double *>(doublePtr) = atof(buffer.data()); |
| 189 | } |
| 190 | |
| 191 | static void doubleToStr( |
| 192 | const void *doublePtr, UnicodeString &appendTo) { |
| 193 | char buffer[256]; |
| 194 | double x = *static_cast<const double *>(doublePtr); |
| 195 | sprintf(buffer, "%f", x); |
| 196 | appendTo.append(buffer); |
| 197 | } |
| 198 | |
| 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; |
| 204 | } |
| 205 | |
| 206 | static void eRoundingToStr( |
| 207 | const void *roundPtr, UnicodeString &appendTo) { |
| 208 | DecimalFormat::ERoundingMode rounding = |
| 209 | *static_cast<const DecimalFormat::ERoundingMode *>(roundPtr); |
| 210 | fromEnum( |
| 211 | gRoundingEnum, |
| 212 | UPRV_LENGTHOF(gRoundingEnum), |
| 213 | rounding, |
| 214 | appendTo); |
| 215 | } |
| 216 | |
| 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; |
| 222 | } |
| 223 | |
| 224 | static void currencyUsageToStr( |
| 225 | const void *currencyUsagePtr, UnicodeString &appendTo) { |
| 226 | UCurrencyUsage currencyUsage = |
| 227 | *static_cast<const UCurrencyUsage *>(currencyUsagePtr); |
| 228 | fromEnum( |
| 229 | gCurrencyUsageEnum, |
| 230 | UPRV_LENGTHOF(gCurrencyUsageEnum), |
| 231 | currencyUsage, |
| 232 | appendTo); |
| 233 | } |
| 234 | |
| 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; |
| 241 | } |
| 242 | |
| 243 | static void ePadPositionToStr( |
| 244 | const void *padPositionPtr, UnicodeString &appendTo) { |
| 245 | DecimalFormat::EPadPosition padPosition = |
| 246 | *static_cast<const DecimalFormat::EPadPosition *>(padPositionPtr); |
| 247 | fromEnum( |
| 248 | gPadPositionEnum, |
| 249 | UPRV_LENGTHOF(gPadPositionEnum), |
| 250 | padPosition, |
| 251 | appendTo); |
| 252 | } |
| 253 | |
| 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; |
| 259 | } |
| 260 | |
| 261 | static void formatStyleToStr( |
| 262 | const void *formatStylePtr, UnicodeString &appendTo) { |
| 263 | UNumberFormatStyle formatStyle = |
| 264 | *static_cast<const UNumberFormatStyle *>(formatStylePtr); |
| 265 | fromEnum( |
| 266 | gFormatStyleEnum, |
| 267 | UPRV_LENGTHOF(gFormatStyleEnum), |
| 268 | formatStyle, |
| 269 | appendTo); |
| 270 | } |
| 271 | |
| 272 | struct NumberFormatTestTupleFieldOps { |
| 273 | void (*toValue)(const UnicodeString &str, void *valPtr, UErrorCode &); |
| 274 | void (*toString)(const void *valPtr, UnicodeString &appendTo); |
| 275 | }; |
| 276 | |
| 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}; |
| 285 | |
| 286 | struct NumberFormatTestTupleFieldData { |
| 287 | const char *name; |
| 288 | int32_t offset; |
| 289 | int32_t flagOffset; |
| 290 | const NumberFormatTestTupleFieldOps *ops; |
| 291 | }; |
| 292 | |
| 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(signAlwaysShown, &gIntOps), |
| 329 | FIELD_INIT(localizedPattern, &gStrOps), |
| 330 | FIELD_INIT(toPattern, &gStrOps), |
| 331 | FIELD_INIT(toLocalizedPattern, &gStrOps), |
| 332 | FIELD_INIT(style, &gFormatStyleOps), |
| 333 | FIELD_INIT(parse, &gStrOps), |
| 334 | FIELD_INIT(lenient, &gIntOps), |
| 335 | FIELD_INIT(plural, &gStrOps), |
| 336 | FIELD_INIT(parseIntegerOnly, &gIntOps), |
| 337 | FIELD_INIT(decimalPatternMatchRequired, &gIntOps), |
| 338 | FIELD_INIT(parseNoExponent, &gIntOps), |
| 339 | FIELD_INIT(parseCaseSensitive, &gIntOps), |
| 340 | FIELD_INIT(outputCurrency, &gStrOps) |
| 341 | }; |
| 342 | |
| 343 | UBool |
| 344 | NumberFormatTestTuple::setField( |
| 345 | ENumberFormatTestTupleField fieldId, |
| 346 | const UnicodeString &fieldValue, |
| 347 | UErrorCode &status) { |
| 348 | if (U_FAILURE(status)) { |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 349 | return false; |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 350 | } |
| 351 | if (fieldId == kNumberFormatTestTupleFieldCount) { |
| 352 | status = U_ILLEGAL_ARGUMENT_ERROR; |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 353 | return false; |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 354 | } |
| 355 | gFieldData[fieldId].ops->toValue( |
| 356 | fieldValue, getMutableFieldAddress(fieldId), status); |
| 357 | if (U_FAILURE(status)) { |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 358 | return false; |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 359 | } |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 360 | setFlag(fieldId, true); |
| 361 | return true; |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 362 | } |
| 363 | |
| 364 | UBool |
| 365 | NumberFormatTestTuple::clearField( |
| 366 | ENumberFormatTestTupleField fieldId, |
| 367 | UErrorCode &status) { |
| 368 | if (U_FAILURE(status)) { |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 369 | return false; |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 370 | } |
| 371 | if (fieldId == kNumberFormatTestTupleFieldCount) { |
| 372 | status = U_ILLEGAL_ARGUMENT_ERROR; |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 373 | return false; |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 374 | } |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 375 | setFlag(fieldId, false); |
| 376 | return true; |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 377 | } |
| 378 | |
| 379 | void |
| 380 | NumberFormatTestTuple::clear() { |
| 381 | for (int32_t i = 0; i < kNumberFormatTestTupleFieldCount; ++i) { |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 382 | setFlag(i, false); |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 383 | } |
| 384 | } |
| 385 | |
| 386 | UnicodeString & |
| 387 | NumberFormatTestTuple::toString( |
| 388 | UnicodeString &appendTo) const { |
| 389 | appendTo.append("{"); |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 390 | UBool first = true; |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 391 | for (int32_t i = 0; i < kNumberFormatTestTupleFieldCount; ++i) { |
| 392 | if (!isFlag(i)) { |
| 393 | continue; |
| 394 | } |
| 395 | if (!first) { |
| 396 | appendTo.append(", "); |
| 397 | } |
Frank Tang | 1f164ee | 2022-11-08 12:31:27 -0800 | [diff] [blame^] | 398 | first = false; |
Frank Tang | 3e05d9d | 2021-11-08 14:04:04 -0800 | [diff] [blame] | 399 | appendTo.append(gFieldData[i].name); |
| 400 | appendTo.append(": "); |
| 401 | gFieldData[i].ops->toString(getFieldAddress(i), appendTo); |
| 402 | } |
| 403 | appendTo.append("}"); |
| 404 | return appendTo; |
| 405 | } |
| 406 | |
| 407 | ENumberFormatTestTupleField |
| 408 | NumberFormatTestTuple::getFieldByName( |
| 409 | const UnicodeString &name) { |
| 410 | CharString buffer; |
| 411 | UErrorCode status = U_ZERO_ERROR; |
| 412 | buffer.appendInvariantChars(name, status); |
| 413 | if (U_FAILURE(status)) { |
| 414 | return kNumberFormatTestTupleFieldCount; |
| 415 | } |
| 416 | int32_t result = -1; |
| 417 | for (int32_t i = 0; i < UPRV_LENGTHOF(gFieldData); ++i) { |
| 418 | if (uprv_strcmp(gFieldData[i].name, buffer.data()) == 0) { |
| 419 | result = i; |
| 420 | break; |
| 421 | } |
| 422 | } |
| 423 | if (result == -1) { |
| 424 | return kNumberFormatTestTupleFieldCount; |
| 425 | } |
| 426 | return (ENumberFormatTestTupleField) result; |
| 427 | } |
| 428 | |
| 429 | const void * |
| 430 | NumberFormatTestTuple::getFieldAddress(int32_t fieldId) const { |
| 431 | return reinterpret_cast<const char *>(this) + gFieldData[fieldId].offset; |
| 432 | } |
| 433 | |
| 434 | void * |
| 435 | NumberFormatTestTuple::getMutableFieldAddress(int32_t fieldId) { |
| 436 | return reinterpret_cast<char *>(this) + gFieldData[fieldId].offset; |
| 437 | } |
| 438 | |
| 439 | void |
| 440 | NumberFormatTestTuple::setFlag(int32_t fieldId, UBool value) { |
| 441 | void *flagAddr = reinterpret_cast<char *>(this) + gFieldData[fieldId].flagOffset; |
| 442 | *static_cast<UBool *>(flagAddr) = value; |
| 443 | } |
| 444 | |
| 445 | UBool |
| 446 | NumberFormatTestTuple::isFlag(int32_t fieldId) const { |
| 447 | const void *flagAddr = reinterpret_cast<const char *>(this) + gFieldData[fieldId].flagOffset; |
| 448 | return *static_cast<const UBool *>(flagAddr); |
| 449 | } |
| 450 | |
| 451 | #endif /* !UCONFIG_NO_FORMATTING */ |