case STEM_NOTATION_SIMPLE:
return Notation::simple();
default:
- U_ASSERT(false);
- return Notation::simple(); // return a value: silence compiler warning
+ UPRV_UNREACHABLE;
}
}
// Slicing is okay
return NoUnit::permille(); // NOLINT
default:
- U_ASSERT(false);
- return {}; // return a value: silence compiler warning
+ UPRV_UNREACHABLE;
}
}
case STEM_PRECISION_CURRENCY_CASH:
return Precision::currency(UCURR_USAGE_CASH);
default:
- U_ASSERT(false);
- return Precision::integer(); // return a value: silence compiler warning
+ UPRV_UNREACHABLE;
}
}
case STEM_ROUNDING_MODE_UNNECESSARY:
return UNUM_ROUND_UNNECESSARY;
default:
- U_ASSERT(false);
- return UNUM_ROUND_UNNECESSARY;
+ UPRV_UNREACHABLE;
}
}
-UGroupingStrategy stem_to_object::groupingStrategy(skeleton::StemEnum stem) {
+UNumberGroupingStrategy stem_to_object::groupingStrategy(skeleton::StemEnum stem) {
switch (stem) {
case STEM_GROUP_OFF:
return UNUM_GROUPING_OFF;
sb.append(u"rounding-mode-unnecessary", -1);
break;
default:
- U_ASSERT(false);
+ UPRV_UNREACHABLE;
}
}
-void enum_to_stem_string::groupingStrategy(UGroupingStrategy value, UnicodeString& sb) {
+void enum_to_stem_string::groupingStrategy(UNumberGroupingStrategy value, UnicodeString& sb) {
switch (value) {
case UNUM_GROUPING_OFF:
sb.append(u"group-off", -1);
sb.append(u"group-thousands", -1);
break;
default:
- U_ASSERT(false);
+ UPRV_UNREACHABLE;
}
}
sb.append(u"unit-width-hidden", -1);
break;
default:
- U_ASSERT(false);
+ UPRV_UNREACHABLE;
}
}
sb.append(u"sign-accounting-except-zero", -1);
break;
default:
- U_ASSERT(false);
+ UPRV_UNREACHABLE;
}
}
sb.append(u"decimal-always", -1);
break;
default:
- U_ASSERT(false);
+ UPRV_UNREACHABLE;
}
}
-UnlocalizedNumberFormatter skeleton::create(const UnicodeString& skeletonString, UErrorCode& status) {
+UnlocalizedNumberFormatter skeleton::create(
+ const UnicodeString& skeletonString, UParseError* perror, UErrorCode& status) {
+
+ // Initialize perror
+ if (perror != nullptr) {
+ perror->line = 0;
+ perror->offset = -1;
+ perror->preContext[0] = 0;
+ perror->postContext[0] = 0;
+ }
+
umtx_initOnce(gNumberSkeletonsInitOnce, &initNumberSkeletons, status);
- MacroProps macros = parseSkeleton(skeletonString, status);
- return NumberFormatter::with().macros(macros);
+ if (U_FAILURE(status)) {
+ return {};
+ }
+
+ int32_t errOffset;
+ MacroProps macros = parseSkeleton(skeletonString, errOffset, status);
+ if (U_SUCCESS(status)) {
+ return NumberFormatter::with().macros(macros);
+ }
+
+ if (perror == nullptr) {
+ return {};
+ }
+
+ // Populate the UParseError with the error location
+ perror->offset = errOffset;
+ int32_t contextStart = uprv_max(0, errOffset - U_PARSE_CONTEXT_LEN + 1);
+ int32_t contextEnd = uprv_min(skeletonString.length(), errOffset + U_PARSE_CONTEXT_LEN - 1);
+ skeletonString.extract(contextStart, errOffset - contextStart, perror->preContext, 0);
+ perror->preContext[errOffset - contextStart] = 0;
+ skeletonString.extract(errOffset, contextEnd - errOffset, perror->postContext, 0);
+ perror->postContext[contextEnd - errOffset] = 0;
+ return {};
}
UnicodeString skeleton::generate(const MacroProps& macros, UErrorCode& status) {
return sb;
}
-MacroProps skeleton::parseSkeleton(const UnicodeString& skeletonString, UErrorCode& status) {
- if (U_FAILURE(status)) { return MacroProps(); }
+MacroProps skeleton::parseSkeleton(
+ const UnicodeString& skeletonString, int32_t& errOffset, UErrorCode& status) {
+ U_ASSERT(U_SUCCESS(status));
// Add a trailing whitespace to the end of the skeleton string to make code cleaner.
UnicodeString tempSkeletonString(skeletonString);
stem = parseOption(stem, segment, macros, status);
}
segment.resetLength();
- if (U_FAILURE(status)) { return macros; }
+ if (U_FAILURE(status)) {
+ errOffset = segment.getOffset();
+ return macros;
+ }
// Consume the segment:
segment.adjustOffset(offset);
// segment.setLength(U16_LENGTH(cp)); // for error message
// throw new SkeletonSyntaxException("Unexpected separator character", segment);
status = U_NUMBER_SKELETON_SYNTAX_ERROR;
+ errOffset = segment.getOffset();
return macros;
} else {
// segment.setLength(U16_LENGTH(cp)); // for error message
// throw new SkeletonSyntaxException("Unexpected option separator", segment);
status = U_NUMBER_SKELETON_SYNTAX_ERROR;
+ errOffset = segment.getOffset();
return macros;
}
// segment.setLength(U16_LENGTH(cp)); // for error message
// throw new SkeletonSyntaxException("Stem requires an option", segment);
status = U_NUMBER_SKELETON_SYNTAX_ERROR;
+ errOffset = segment.getOffset();
return macros;
default:
break;
return STATE_SCALE;
default:
- U_ASSERT(false);
- return STATE_NULL; // return a value: silence compiler warning
+ UPRV_UNREACHABLE;
}
}
} else if (macros.precision.fType == Precision::RND_SIGNIFICANT) {
const Precision::FractionSignificantSettings& impl = macros.precision.fUnion.fracSig;
blueprint_helpers::generateDigitsStem(impl.fMinSig, impl.fMaxSig, sb, status);
+ } else if (macros.precision.fType == Precision::RND_INCREMENT_SIGNIFICANT) { // Apple rdar://52538227
+ const Precision::IncrementSignificantSettings& impl = macros.precision.fUnion.incrSig;
+ blueprint_helpers::generateDigitsStem(impl.fMinSig, impl.fMaxSig, sb, status);
} else if (macros.precision.fType == Precision::RND_FRACTION_SIGNIFICANT) {
const Precision::FractionSignificantSettings& impl = macros.precision.fUnion.fracSig;
blueprint_helpers::generateFractionStem(impl.fMinFrac, impl.fMaxFrac, sb, status);
} else {
blueprint_helpers::generateDigitsStem(impl.fMinSig, -1, sb, status);
}
- } else if (macros.precision.fType == Precision::RND_INCREMENT) {
+ } else if (macros.precision.fType == Precision::RND_INCREMENT
+ || macros.precision.fType == Precision::RND_INCREMENT_ONE
+ || macros.precision.fType == Precision::RND_INCREMENT_FIVE) {
const Precision::IncrementSettings& impl = macros.precision.fUnion.increment;
sb.append(u"precision-increment/", -1);
blueprint_helpers::generateIncrementOption(