Index: source/test/intltest/numberformattesttuple.cpp |
diff --git a/source/test/intltest/numberformattesttuple.cpp b/source/test/intltest/numberformattesttuple.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..366b893c67ac7a228ae68c40203501f047dbfa77 |
--- /dev/null |
+++ b/source/test/intltest/numberformattesttuple.cpp |
@@ -0,0 +1,447 @@ |
+/* |
+******************************************************************************* |
+* Copyright (C) 2015, International Business Machines Corporation and * |
+* others. All Rights Reserved. * |
+******************************************************************************* |
+*/ |
+ |
+#include "numberformattesttuple.h" |
+ |
+#if !UCONFIG_NO_FORMATTING |
+ |
+#include "ustrfmt.h" |
+#include "charstr.h" |
+#include "cstring.h" |
+#include "cmemory.h" |
+#include "digitlst.h" |
+ |
+static NumberFormatTestTuple *gNullPtr = NULL; |
+ |
+#define FIELD_OFFSET(fieldName) ((int32_t) (((char *) &gNullPtr->fieldName) - ((char *) gNullPtr))) |
+#define FIELD_FLAG_OFFSET(fieldName) ((int32_t) (((char *) &gNullPtr->fieldName##Flag) - ((char *) gNullPtr))) |
+ |
+#define FIELD_INIT(fieldName, fieldType) {#fieldName, FIELD_OFFSET(fieldName), FIELD_FLAG_OFFSET(fieldName), fieldType} |
+ |
+struct Numberformattesttuple_EnumConversion { |
+ const char *str; |
+ int32_t value; |
+}; |
+ |
+static Numberformattesttuple_EnumConversion gRoundingEnum[] = { |
+ {"ceiling", DecimalFormat::kRoundCeiling}, |
+ {"floor", DecimalFormat::kRoundFloor}, |
+ {"down", DecimalFormat::kRoundDown}, |
+ {"up", DecimalFormat::kRoundUp}, |
+ {"halfEven", DecimalFormat::kRoundHalfEven}, |
+ {"halfDown", DecimalFormat::kRoundHalfDown}, |
+ {"halfUp", DecimalFormat::kRoundHalfUp}, |
+ {"unnecessary", DecimalFormat::kRoundUnnecessary}}; |
+ |
+static Numberformattesttuple_EnumConversion gCurrencyUsageEnum[] = { |
+ {"standard", UCURR_USAGE_STANDARD}, |
+ {"cash", UCURR_USAGE_CASH}}; |
+ |
+static Numberformattesttuple_EnumConversion gPadPositionEnum[] = { |
+ {"beforePrefix", DecimalFormat::kPadBeforePrefix}, |
+ {"afterPrefix", DecimalFormat::kPadAfterPrefix}, |
+ {"beforeSuffix", DecimalFormat::kPadBeforeSuffix}, |
+ {"afterSuffix", DecimalFormat::kPadAfterSuffix}}; |
+ |
+static Numberformattesttuple_EnumConversion gFormatStyleEnum[] = { |
+ {"patternDecimal", UNUM_PATTERN_DECIMAL}, |
+ {"decimal", UNUM_DECIMAL}, |
+ {"currency", UNUM_CURRENCY}, |
+ {"percent", UNUM_PERCENT}, |
+ {"scientific", UNUM_SCIENTIFIC}, |
+ {"spellout", UNUM_SPELLOUT}, |
+ {"ordinal", UNUM_ORDINAL}, |
+ {"duration", UNUM_DURATION}, |
+ {"numberingSystem", UNUM_NUMBERING_SYSTEM}, |
+ {"patternRuleBased", UNUM_PATTERN_RULEBASED}, |
+ {"currencyIso", UNUM_CURRENCY_ISO}, |
+ {"currencyPlural", UNUM_CURRENCY_PLURAL}, |
+ {"currencyAccounting", UNUM_CURRENCY_ACCOUNTING}, |
+ {"cashCurrency", UNUM_CASH_CURRENCY}, |
+ {"default", UNUM_DEFAULT}, |
+ {"ignore", UNUM_IGNORE}}; |
+ |
+static int32_t toEnum( |
+ const Numberformattesttuple_EnumConversion *table, |
+ int32_t tableLength, |
+ const UnicodeString &str, |
+ UErrorCode &status) { |
+ if (U_FAILURE(status)) { |
+ return 0; |
+ } |
+ CharString cstr; |
+ cstr.appendInvariantChars(str, status); |
+ if (U_FAILURE(status)) { |
+ return 0; |
+ } |
+ for (int32_t i = 0; i < tableLength; ++i) { |
+ if (uprv_strcmp(cstr.data(), table[i].str) == 0) { |
+ return table[i].value; |
+ } |
+ } |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return 0; |
+} |
+ |
+static void fromEnum( |
+ const Numberformattesttuple_EnumConversion *table, |
+ int32_t tableLength, |
+ int32_t val, |
+ UnicodeString &appendTo) { |
+ for (int32_t i = 0; i < tableLength; ++i) { |
+ if (table[i].value == val) { |
+ appendTo.append(table[i].str); |
+ } |
+ } |
+} |
+ |
+static void identVal( |
+ const UnicodeString &str, void *strPtr, UErrorCode & /*status*/) { |
+ *static_cast<UnicodeString *>(strPtr) = str; |
+} |
+ |
+static void identStr( |
+ const void *strPtr, UnicodeString &appendTo) { |
+ appendTo.append(*static_cast<const UnicodeString *>(strPtr)); |
+} |
+ |
+static void strToLocale( |
+ const UnicodeString &str, void *localePtr, UErrorCode &status) { |
+ if (U_FAILURE(status)) { |
+ return; |
+ } |
+ CharString localeStr; |
+ localeStr.appendInvariantChars(str, status); |
+ *static_cast<Locale *>(localePtr) = Locale(localeStr.data()); |
+} |
+ |
+static void localeToStr( |
+ const void *localePtr, UnicodeString &appendTo) { |
+ appendTo.append( |
+ UnicodeString( |
+ static_cast<const Locale *>(localePtr)->getName())); |
+} |
+ |
+static void strToInt( |
+ const UnicodeString &str, void *intPtr, UErrorCode &status) { |
+ if (U_FAILURE(status)) { |
+ return; |
+ } |
+ int32_t len = str.length(); |
+ int32_t start = 0; |
+ UBool neg = FALSE; |
+ if (len > 0 && str[0] == 0x2D) { // negative |
+ neg = TRUE; |
+ start = 1; |
+ } |
+ if (start == len) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return; |
+ } |
+ int32_t value = 0; |
+ for (int32_t i = start; i < len; ++i) { |
+ UChar ch = str[i]; |
+ if (ch < 0x30 || ch > 0x39) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return; |
+ } |
+ value = value * 10 - 0x30 + (int32_t) ch; |
+ } |
+ if (neg) { |
+ value = -value; |
+ } |
+ *static_cast<int32_t *>(intPtr) = value; |
+} |
+ |
+static void intToStr( |
+ const void *intPtr, UnicodeString &appendTo) { |
+ UChar buffer[20]; |
+ int32_t x = *static_cast<const int32_t *>(intPtr); |
+ UBool neg = FALSE; |
+ if (x < 0) { |
+ neg = TRUE; |
+ x = -x; |
+ } |
+ if (neg) { |
+ appendTo.append(0x2D); |
+ } |
+ int32_t len = uprv_itou(buffer, UPRV_LENGTHOF(buffer), (uint32_t) x, 10, 1); |
+ appendTo.append(buffer, 0, len); |
+} |
+ |
+static void strToDouble( |
+ const UnicodeString &str, void *doublePtr, UErrorCode &status) { |
+ if (U_FAILURE(status)) { |
+ return; |
+ } |
+ CharString buffer; |
+ buffer.appendInvariantChars(str, status); |
+ if (U_FAILURE(status)) { |
+ return; |
+ } |
+ *static_cast<double *>(doublePtr) = atof(buffer.data()); |
+} |
+ |
+static void doubleToStr( |
+ const void *doublePtr, UnicodeString &appendTo) { |
+ char buffer[256]; |
+ double x = *static_cast<const double *>(doublePtr); |
+ sprintf(buffer, "%f", x); |
+ appendTo.append(buffer); |
+} |
+ |
+static void strToERounding( |
+ const UnicodeString &str, void *roundPtr, UErrorCode &status) { |
+ int32_t val = toEnum( |
+ gRoundingEnum, UPRV_LENGTHOF(gRoundingEnum), str, status); |
+ *static_cast<DecimalFormat::ERoundingMode *>(roundPtr) = (DecimalFormat::ERoundingMode) val; |
+} |
+ |
+static void eRoundingToStr( |
+ const void *roundPtr, UnicodeString &appendTo) { |
+ DecimalFormat::ERoundingMode rounding = |
+ *static_cast<const DecimalFormat::ERoundingMode *>(roundPtr); |
+ fromEnum( |
+ gRoundingEnum, |
+ UPRV_LENGTHOF(gRoundingEnum), |
+ rounding, |
+ appendTo); |
+} |
+ |
+static void strToCurrencyUsage( |
+ const UnicodeString &str, void *currencyUsagePtr, UErrorCode &status) { |
+ int32_t val = toEnum( |
+ gCurrencyUsageEnum, UPRV_LENGTHOF(gCurrencyUsageEnum), str, status); |
+ *static_cast<UCurrencyUsage *>(currencyUsagePtr) = (UCurrencyUsage) val; |
+} |
+ |
+static void currencyUsageToStr( |
+ const void *currencyUsagePtr, UnicodeString &appendTo) { |
+ UCurrencyUsage currencyUsage = |
+ *static_cast<const UCurrencyUsage *>(currencyUsagePtr); |
+ fromEnum( |
+ gCurrencyUsageEnum, |
+ UPRV_LENGTHOF(gCurrencyUsageEnum), |
+ currencyUsage, |
+ appendTo); |
+} |
+ |
+static void strToEPadPosition( |
+ const UnicodeString &str, void *padPositionPtr, UErrorCode &status) { |
+ int32_t val = toEnum( |
+ gPadPositionEnum, UPRV_LENGTHOF(gPadPositionEnum), str, status); |
+ *static_cast<DecimalFormat::EPadPosition *>(padPositionPtr) = |
+ (DecimalFormat::EPadPosition) val; |
+} |
+ |
+static void ePadPositionToStr( |
+ const void *padPositionPtr, UnicodeString &appendTo) { |
+ DecimalFormat::EPadPosition padPosition = |
+ *static_cast<const DecimalFormat::EPadPosition *>(padPositionPtr); |
+ fromEnum( |
+ gPadPositionEnum, |
+ UPRV_LENGTHOF(gPadPositionEnum), |
+ padPosition, |
+ appendTo); |
+} |
+ |
+static void strToFormatStyle( |
+ const UnicodeString &str, void *formatStylePtr, UErrorCode &status) { |
+ int32_t val = toEnum( |
+ gFormatStyleEnum, UPRV_LENGTHOF(gFormatStyleEnum), str, status); |
+ *static_cast<UNumberFormatStyle *>(formatStylePtr) = (UNumberFormatStyle) val; |
+} |
+ |
+static void formatStyleToStr( |
+ const void *formatStylePtr, UnicodeString &appendTo) { |
+ UNumberFormatStyle formatStyle = |
+ *static_cast<const UNumberFormatStyle *>(formatStylePtr); |
+ fromEnum( |
+ gFormatStyleEnum, |
+ UPRV_LENGTHOF(gFormatStyleEnum), |
+ formatStyle, |
+ appendTo); |
+} |
+ |
+struct NumberFormatTestTupleFieldOps { |
+ void (*toValue)(const UnicodeString &str, void *valPtr, UErrorCode &); |
+ void (*toString)(const void *valPtr, UnicodeString &appendTo); |
+}; |
+ |
+const NumberFormatTestTupleFieldOps gStrOps = {identVal, identStr}; |
+const NumberFormatTestTupleFieldOps gIntOps = {strToInt, intToStr}; |
+const NumberFormatTestTupleFieldOps gLocaleOps = {strToLocale, localeToStr}; |
+const NumberFormatTestTupleFieldOps gDoubleOps = {strToDouble, doubleToStr}; |
+const NumberFormatTestTupleFieldOps gERoundingOps = {strToERounding, eRoundingToStr}; |
+const NumberFormatTestTupleFieldOps gCurrencyUsageOps = {strToCurrencyUsage, currencyUsageToStr}; |
+const NumberFormatTestTupleFieldOps gEPadPositionOps = {strToEPadPosition, ePadPositionToStr}; |
+const NumberFormatTestTupleFieldOps gFormatStyleOps = {strToFormatStyle, formatStyleToStr}; |
+ |
+struct NumberFormatTestTupleFieldData { |
+ const char *name; |
+ int32_t offset; |
+ int32_t flagOffset; |
+ const NumberFormatTestTupleFieldOps *ops; |
+}; |
+ |
+// Order must correspond to ENumberFormatTestTupleField |
+const NumberFormatTestTupleFieldData gFieldData[] = { |
+ FIELD_INIT(locale, &gLocaleOps), |
+ FIELD_INIT(currency, &gStrOps), |
+ FIELD_INIT(pattern, &gStrOps), |
+ FIELD_INIT(format, &gStrOps), |
+ FIELD_INIT(output, &gStrOps), |
+ FIELD_INIT(comment, &gStrOps), |
+ FIELD_INIT(minIntegerDigits, &gIntOps), |
+ FIELD_INIT(maxIntegerDigits, &gIntOps), |
+ FIELD_INIT(minFractionDigits, &gIntOps), |
+ FIELD_INIT(maxFractionDigits, &gIntOps), |
+ FIELD_INIT(minGroupingDigits, &gIntOps), |
+ FIELD_INIT(breaks, &gStrOps), |
+ FIELD_INIT(useSigDigits, &gIntOps), |
+ FIELD_INIT(minSigDigits, &gIntOps), |
+ FIELD_INIT(maxSigDigits, &gIntOps), |
+ FIELD_INIT(useGrouping, &gIntOps), |
+ FIELD_INIT(multiplier, &gIntOps), |
+ FIELD_INIT(roundingIncrement, &gDoubleOps), |
+ FIELD_INIT(formatWidth, &gIntOps), |
+ FIELD_INIT(padCharacter, &gStrOps), |
+ FIELD_INIT(useScientific, &gIntOps), |
+ FIELD_INIT(grouping, &gIntOps), |
+ FIELD_INIT(grouping2, &gIntOps), |
+ FIELD_INIT(roundingMode, &gERoundingOps), |
+ FIELD_INIT(currencyUsage, &gCurrencyUsageOps), |
+ FIELD_INIT(minimumExponentDigits, &gIntOps), |
+ FIELD_INIT(exponentSignAlwaysShown, &gIntOps), |
+ FIELD_INIT(decimalSeparatorAlwaysShown, &gIntOps), |
+ FIELD_INIT(padPosition, &gEPadPositionOps), |
+ FIELD_INIT(positivePrefix, &gStrOps), |
+ FIELD_INIT(positiveSuffix, &gStrOps), |
+ FIELD_INIT(negativePrefix, &gStrOps), |
+ FIELD_INIT(negativeSuffix, &gStrOps), |
+ FIELD_INIT(localizedPattern, &gStrOps), |
+ FIELD_INIT(toPattern, &gStrOps), |
+ FIELD_INIT(toLocalizedPattern, &gStrOps), |
+ FIELD_INIT(style, &gFormatStyleOps), |
+ FIELD_INIT(parse, &gStrOps), |
+ FIELD_INIT(lenient, &gIntOps), |
+ FIELD_INIT(plural, &gStrOps), |
+ FIELD_INIT(parseIntegerOnly, &gIntOps), |
+ FIELD_INIT(decimalPatternMatchRequired, &gIntOps), |
+ FIELD_INIT(parseNoExponent, &gIntOps), |
+ FIELD_INIT(outputCurrency, &gStrOps) |
+}; |
+ |
+UBool |
+NumberFormatTestTuple::setField( |
+ ENumberFormatTestTupleField fieldId, |
+ const UnicodeString &fieldValue, |
+ UErrorCode &status) { |
+ if (U_FAILURE(status)) { |
+ return FALSE; |
+ } |
+ if (fieldId == kNumberFormatTestTupleFieldCount) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return FALSE; |
+ } |
+ gFieldData[fieldId].ops->toValue( |
+ fieldValue, getMutableFieldAddress(fieldId), status); |
+ if (U_FAILURE(status)) { |
+ return FALSE; |
+ } |
+ setFlag(fieldId, TRUE); |
+ return TRUE; |
+} |
+ |
+UBool |
+NumberFormatTestTuple::clearField( |
+ ENumberFormatTestTupleField fieldId, |
+ UErrorCode &status) { |
+ if (U_FAILURE(status)) { |
+ return FALSE; |
+ } |
+ if (fieldId == kNumberFormatTestTupleFieldCount) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return FALSE; |
+ } |
+ setFlag(fieldId, FALSE); |
+ return TRUE; |
+} |
+ |
+void |
+NumberFormatTestTuple::clear() { |
+ for (int32_t i = 0; i < kNumberFormatTestTupleFieldCount; ++i) { |
+ setFlag(i, FALSE); |
+ } |
+} |
+ |
+UnicodeString & |
+NumberFormatTestTuple::toString( |
+ UnicodeString &appendTo) const { |
+ appendTo.append("{"); |
+ UBool first = TRUE; |
+ for (int32_t i = 0; i < kNumberFormatTestTupleFieldCount; ++i) { |
+ if (!isFlag(i)) { |
+ continue; |
+ } |
+ if (!first) { |
+ appendTo.append(", "); |
+ } |
+ first = FALSE; |
+ appendTo.append(gFieldData[i].name); |
+ appendTo.append(": "); |
+ gFieldData[i].ops->toString(getFieldAddress(i), appendTo); |
+ } |
+ appendTo.append("}"); |
+ return appendTo; |
+} |
+ |
+ENumberFormatTestTupleField |
+NumberFormatTestTuple::getFieldByName( |
+ const UnicodeString &name) { |
+ CharString buffer; |
+ UErrorCode status = U_ZERO_ERROR; |
+ buffer.appendInvariantChars(name, status); |
+ if (U_FAILURE(status)) { |
+ return kNumberFormatTestTupleFieldCount; |
+ } |
+ int32_t result = -1; |
+ for (int32_t i = 0; i < UPRV_LENGTHOF(gFieldData); ++i) { |
+ if (uprv_strcmp(gFieldData[i].name, buffer.data()) == 0) { |
+ result = i; |
+ break; |
+ } |
+ } |
+ if (result == -1) { |
+ return kNumberFormatTestTupleFieldCount; |
+ } |
+ return (ENumberFormatTestTupleField) result; |
+} |
+ |
+const void * |
+NumberFormatTestTuple::getFieldAddress(int32_t fieldId) const { |
+ return reinterpret_cast<const char *>(this) + gFieldData[fieldId].offset; |
+} |
+ |
+void * |
+NumberFormatTestTuple::getMutableFieldAddress(int32_t fieldId) { |
+ return reinterpret_cast<char *>(this) + gFieldData[fieldId].offset; |
+} |
+ |
+void |
+NumberFormatTestTuple::setFlag(int32_t fieldId, UBool value) { |
+ void *flagAddr = reinterpret_cast<char *>(this) + gFieldData[fieldId].flagOffset; |
+ *static_cast<UBool *>(flagAddr) = value; |
+} |
+ |
+UBool |
+NumberFormatTestTuple::isFlag(int32_t fieldId) const { |
+ const void *flagAddr = reinterpret_cast<const char *>(this) + gFieldData[fieldId].flagOffset; |
+ return *static_cast<const UBool *>(flagAddr); |
+} |
+ |
+#endif /* !UCONFIG_NO_FORMATTING */ |