ICU-1282 add C APIs for rule based number format

X-SVN-Rev: 14698
This commit is contained in:
Doug Felt 2004-03-12 20:15:13 +00:00
parent 8e6b43b20d
commit ed4dc729f1
8 changed files with 545 additions and 136 deletions

View File

@ -422,6 +422,17 @@ RuleBasedNumberFormat::setDefaultRuleSet(const UnicodeString& ruleSetName, UErro
}
}
UnicodeString
RuleBasedNumberFormat::getDefaultRuleSetName() {
UnicodeString result;
if (defaultRuleSet && defaultRuleSet->isPublic()) {
defaultRuleSet->getName(result);
} else {
result.setToBogus();
}
return result;
}
void
RuleBasedNumberFormat::initDefaultRuleSet()
{

View File

@ -782,11 +782,19 @@ public:
* to the initial default rule set. If the rule set is not a public rule set name,
* U_ILLEGAL_ARGUMENT_ERROR is returned in status.
* @param ruleSetName the name of the rule set, or null to reset the initial default.
* @param status Output param set to failure code when a problem occurs.
* @param status set to failure code when a problem occurs.
* @draft ICU 2.6
*/
virtual void setDefaultRuleSet(const UnicodeString& ruleSetName, UErrorCode& status);
/**
* Return the name of the current default rule set. If the current rule set is
* not public, returns a bogus (and empty) UnicodeString.
* @return the name of the current default rule set
* @draft ICU 3.0
*/
virtual UnicodeString getDefaultRuleSetName();
public:
/**
* ICU "poor man's RTTI", returns a UClassID for this class.

View File

@ -100,9 +100,13 @@
* to get a format for displaying percentages. With this format, a
* fraction from 0.53 is displayed as 53%.
* <P>
* Use a pattern to create either a DecimalFormat or a RuleBasedNumberFormat
* formatter. The pattern must conform to the syntax defined for those
* formatters.
* <P>
* You can also control the display of numbers with such function as
* unum_getAttribues() and unum_setAtributes(). where in you can set the
* miminum fraction digits, grouping used etc.
* unum_getAttribues() and unum_setAtributes(), which let you set the
* miminum fraction digits, grouping, etc.
* @see UNumberFormatAttributes for more details
* <P>
* You can also use forms of the parse and format methods with
@ -127,8 +131,11 @@ typedef void* UNumberFormat;
* @stable ICU 2.0
*/
typedef enum UNumberFormatStyle {
/** Pattern-based format */
UNUM_PATTERN=0,
/**
* Decimal format defined by pattern
* @draft ICU 3.0
*/
UNUM_PATTERN_DECIMAL=0,
/** Decimal format */
UNUM_DECIMAL=1,
/** Currency format */
@ -137,12 +144,27 @@ typedef enum UNumberFormatStyle {
UNUM_PERCENT,
/** Scientific format */
UNUM_SCIENTIFIC,
/** Spellout format */
/** Spellout rule-based format */
UNUM_SPELLOUT,
/**
* Ordinal rule-based format
* @draft ICU 3.0
*/
UNUM_ORDINAL,
/**
* Duration rule-based format
* @draft ICU 3.0
*/
UNUM_DURATION,
/**
* Rule-based format defined by pattern
* @draft ICU 3.0
*/
UNUM_PATTERN_RULEBASED,
/** Default format */
UNUM_DEFAULT = UNUM_DECIMAL,
/** (Alias for UNUM_PATTERN) */
UNUM_IGNORE=UNUM_PATTERN
/** (Alias for UNUM_PATTERN_DECIMAL) */
UNUM_IGNORE = UNUM_PATTERN_DECIMAL,
} UNumberFormatStyle;
/** The possible number format rounding modes.
@ -175,14 +197,15 @@ typedef enum UNumberFormatPadPosition {
* The caller must call \Ref{unum_close} when done to release resources
* used by this object.
* @param style The type of number format to open: one of
* UNUM_DECIMAL, UNUM_CURRENCY, UNUM_PERCENT, UNUM_SPELLOUT,
* UNUM_DEFAULT or UNUM_PATTERN. If UNUM_PATTERN is passed then the
* number format is opened using the given pattern.
* @param pattern A pattern specifying the format to use. The pattern
* given must be a DecimalFormat pattern. RuleBasedNumberFormat
* patterns ("spellout" patterns) are currently not supported through
* this API. This parameter is ignored unless the style is
* UNUM_PATTERN.
* UNUM_DECIMAL, UNUM_CURRENCY, UNUM_PERCENT, UNUM_SCIENTIFIC, UNUM_SPELLOUT,
* UNUM_PATTERN_DECIMAL, UNUM_PATTERN_RULEBASED, or UNUM_DEFAULT.
* If UNUM_PATTERN_DECIMAL or UNUM_PATTERN_RULEBASED is passed then the
* number format is opened using the given pattern, which must conform
* to the syntax described in DecimalFormat or RuleBasedNumberFormat,
* respectively.
* @param pattern A pattern specifying the format to use.
* This parameter is ignored unless the style is
* UNUM_PATTERN_DECIMAL or UNUM_PATTERN_RULEBASED.
* @param patternLength The number of characters in the pattern, or -1
* if null-terminated. This parameter is ignored unless the style is
* UNUM_PATTERN.
@ -388,10 +411,10 @@ unum_parseDouble( const UNumberFormat* fmt,
UErrorCode *status);
/**
* Set the pattern used by an UNumberFormat. The pattern should
* follow the DecimalFormat pattern syntax.
* @param format The formatter to set. This must _not_ be a formatter
* opened using UNUM_SPELLOUT.
* Set the pattern used by a UNumberFormat. This can only be used
* on a DecimalFormat, other formats return U_ILLEGAL_ARGUMENT_ERROR
* in the status.
* @param format The formatter to set.
* @param localized TRUE if the pattern is localized, FALSE otherwise.
* @param pattern The new pattern
* @param patternLength The length of pattern, or -1 if null-terminated.
@ -413,9 +436,10 @@ unum_applyPattern( UNumberFormat *format,
);
/**
* Get a locale for which number formatting patterns are available.
* Get a locale for which decimal formatting patterns are available.
* A UNumberFormat in a locale returned by this function will perform the correct
* formatting and parsing for the locale.
* formatting and parsing for the locale. The results of this call are not
* valid for rule-based number formats.
* @param index The index of the desired locale.
* @return A locale for which number formatting patterns are available, or 0 if none.
* @see unum_countAvailable
@ -425,10 +449,11 @@ U_CAPI const char* U_EXPORT2
unum_getAvailable(int32_t index);
/**
* Determine how many locales have number formatting patterns available.
* This function is most useful as determining the loop ending condition for
* Determine how many locales have decimal formatting patterns available. The
* results of this call are not valid for rule-based number formats.
* This function is useful for determining the loop ending condition for
* calls to \Ref{unum_getAvailable}.
* @return The number of locales for which number formatting patterns are available.
* @return The number of locales for which decimal formatting patterns are available.
* @see unum_getAvailable
* @stable ICU 2.0
*/
@ -468,7 +493,11 @@ typedef enum UNumberFormatAttribute {
/** The position at which padding will take place. */
UNUM_PADDING_POSITION,
/** Secondary grouping size */
UNUM_SECONDARY_GROUPING_SIZE
UNUM_SECONDARY_GROUPING_SIZE,
/** Lenient parse mode used by rule-based formats.
* @draft ICU 3.0
*/
UNUM_LENIENT_PARSE,
} UNumberFormatAttribute;
/**
@ -493,12 +522,15 @@ unum_getAttribute(const UNumberFormat* fmt,
/**
* Set a numeric attribute associated with a UNumberFormat.
* An example of a numeric attribute is the number of integer digits a formatter will produce.
* An example of a numeric attribute is the number of integer digits a formatter will produce. If the
* formatter does not understand the attribute, the call is ignored. Rule-based formatters only understand
* the lenient-parse attribute.
* @param fmt The formatter to set.
* @param attr The attribute to set; one of UNUM_PARSE_INT_ONLY, UNUM_GROUPING_USED,
* UNUM_DECIMAL_ALWAYS_SHOWN, UNUM_MAX_INTEGER_DIGITS, UNUM_MIN_INTEGER_DIGITS, UNUM_INTEGER_DIGITS,
* UNUM_MAX_FRACTION_DIGITS, UNUM_MIN_FRACTION_DIGITS, UNUM_FRACTION_DIGITS, UNUM_MULTIPLIER,
* UNUM_GROUPING_SIZE, UNUM_ROUNDING_MODE, UNUM_FORMAT_WIDTH, UNUM_PADDING_POSITION, UNUM_SECONDARY_GROUPING_SIZE.
* UNUM_GROUPING_SIZE, UNUM_ROUNDING_MODE, UNUM_FORMAT_WIDTH, UNUM_PADDING_POSITION, UNUM_SECONDARY_GROUPING_SIZE,
* or UNUM_LENIENT_PARSE.
* @param newValue The new value of attr.
* @see unum_getAttribute
* @see unum_getDoubleAttribute
@ -516,6 +548,7 @@ unum_setAttribute( UNumberFormat* fmt,
/**
* Get a numeric attribute associated with a UNumberFormat.
* An example of a numeric attribute is the number of integer digits a formatter will produce.
* If the formatter does not understand the attribute, -1 is returned.
* @param fmt The formatter to query.
* @param attr The attribute to query; e.g. UNUM_ROUNDING_INCREMENT.
* @return The value of attr.
@ -533,6 +566,7 @@ unum_getDoubleAttribute(const UNumberFormat* fmt,
/**
* Set a numeric attribute associated with a UNumberFormat.
* An example of a numeric attribute is the number of integer digits a formatter will produce.
* If the formatter does not understand the attribute, this call is ignored.
* @param fmt The formatter to set.
* @param attr The attribute to set; e.g. UNUM_ROUNDING_INCREMENT.
* @param newValue The new value of attr.
@ -561,15 +595,30 @@ typedef enum UNumberFormatTextAttribute {
/** The character used to pad to the format width. */
UNUM_PADDING_CHARACTER,
/** The ISO currency code */
UNUM_CURRENCY_CODE
UNUM_CURRENCY_CODE,
/**
* The default rule set. This is only available with rule-based formatters.
* @draft ICU 3.0
*/
UNUM_DEFAULT_RULESET,
/**
* The public rule sets. This is only available with rule-based formatters.
* This is a read-only attribute. The public rulesets are returned as a
* single string, with each ruleset name delimited by ';' (semicolon).
* @draft ICU 3.0
*/
UNUM_PUBLIC_RULESETS,
} UNumberFormatTextAttribute;
/**
* Get a text attribute associated with a UNumberFormat.
* An example of a text attribute is the suffix for positive numbers.
* An example of a text attribute is the suffix for positive numbers. If the formatter
* does not understand the attributre, U_UNSUPPORTED_ERROR is returned as the status.
* Rule-based formatters only understand UNUM_DEFAULT_RULESET and UNUM_PUBLIC_RULESETS.
* @param fmt The formatter to query.
* @param tag The attribute to query; one of UNUM_POSITIVE_PREFIX, UNUM_POSITIVE_SUFFIX,
* UNUM_NEGATIVE_PREFIX, UNUM_NEGATIVE_SUFFIX
* UNUM_NEGATIVE_PREFIX, UNUM_NEGATIVE_SUFFIX, UNUM_PADDING_CHARACTER, UNUM_CURRENCY_CODE,
* UNUM_DEFAULT_RULESET, or UNUM_PUBLIC_RULESETS.
* @param result A pointer to a buffer to receive the attribute.
* @param resultLength The maximum size of result.
* @param status A pointer to an UErrorCode to receive any errors
@ -588,10 +637,12 @@ unum_getTextAttribute( const UNumberFormat* fmt,
/**
* Set a text attribute associated with a UNumberFormat.
* An example of a text attribute is the suffix for positive numbers.
* An example of a text attribute is the suffix for positive numbers. Rule-based formatters
* only understand UNUM_DEFAULT_RULESET.
* @param fmt The formatter to set.
* @param tag The attribute to set; one of UNUM_POSITIVE_PREFIX, UNUM_POSITIVE_SUFFIX,
* UNUM_NEGATIVE_PREFIX, UNUM_NEGATIVE_SUFFIX
* UNUM_NEGATIVE_PREFIX, UNUM_NEGATIVE_SUFFIX, UNUM_PADDING_CHARACTER, UNUM_CURRENCY_CODE,
* or UNUM_DEFAULT_RULESET.
* @param newValue The new value of attr.
* @param newValueLength The length of newValue, or -1 if null-terminated.
* @param status A pointer to an UErrorCode to receive any errors
@ -610,10 +661,10 @@ unum_setTextAttribute( UNumberFormat* fmt,
/**
* Extract the pattern from a UNumberFormat. The pattern will follow
* the DecimalFormat pattern syntax.
* @param fmt The formatter to query. This must _not_ be a formatter
* opened using UNUM_SPELLOUT.
* @param fmt The formatter to query.
* @param isPatternLocalized TRUE if the pattern should be localized,
* FALSE otherwise.
* FALSE otherwise. This is ignored if the formatter is a rule-based
* formatter.
* @param result A pointer to a buffer to receive the pattern.
* @param resultLength The maximum size of result.
* @param status A pointer to an input-output UErrorCode.
@ -677,7 +728,8 @@ typedef enum UNumberFormatSymbol {
/**
* Get a symbol associated with a UNumberFormat.
* A UNumberFormat uses symbols to represent the special locale-dependent
* characters in a number, for example the percent sign.
* characters in a number, for example the percent sign. This API is not
* supported for rule-based formatters.
* @param fmt The formatter to query.
* @param symbol The UNumberFormatSymbol constant for the symbol to get
* @param buffer The string buffer that will receive the symbol string;
@ -699,7 +751,8 @@ unum_getSymbol(UNumberFormat *fmt,
/**
* Set a symbol associated with a UNumberFormat.
* A UNumberFormat uses symbols to represent the special locale-dependent
* characters in a number, for example the percent sign.
* characters in a number, for example the percent sign. This API is not
* supported for rule-based formatters.
* @param fmt The formatter to set.
* @param symbol The UNumberFormatSymbol constant for the symbol to set
* @param value The string to set the symbol to

View File

@ -42,61 +42,43 @@ unum_open( UNumberFormatStyle style,
{
return 0;
}
if(style!=UNUM_PATTERN){
UNumberFormat *retVal = 0;
UNumberFormat *retVal = 0;
switch(style) {
case UNUM_DECIMAL:
if(locale == 0)
retVal = (UNumberFormat*)NumberFormat::createInstance(*status);
else
retVal = (UNumberFormat*)NumberFormat::createInstance(Locale(locale),
*status);
break;
switch(style) {
case UNUM_DECIMAL:
if(locale == 0)
retVal = (UNumberFormat*)NumberFormat::createInstance(*status);
else
retVal = (UNumberFormat*)NumberFormat::createInstance(Locale(locale),
*status);
break;
case UNUM_CURRENCY:
if(locale == 0)
retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(*status);
else
retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(Locale(locale),
*status);
break;
case UNUM_CURRENCY:
if(locale == 0)
retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(*status);
else
retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(Locale(locale),
*status);
break;
case UNUM_PERCENT:
if(locale == 0)
retVal = (UNumberFormat*)NumberFormat::createPercentInstance(*status);
else
retVal = (UNumberFormat*)NumberFormat::createPercentInstance(Locale(locale),
*status);
break;
case UNUM_PERCENT:
if(locale == 0)
retVal = (UNumberFormat*)NumberFormat::createPercentInstance(*status);
else
retVal = (UNumberFormat*)NumberFormat::createPercentInstance(Locale(locale),
*status);
break;
case UNUM_SCIENTIFIC:
if(locale == 0)
retVal = (UNumberFormat*)NumberFormat::createScientificInstance(*status);
else
retVal = (UNumberFormat*)NumberFormat::createScientificInstance(Locale(locale),
*status);
break;
case UNUM_SPELLOUT:
#if U_HAVE_RBNF
return (UNumberFormat*)new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status);
#else
// fall through
#endif
default:
*status = U_UNSUPPORTED_ERROR;
return 0;
}
if(retVal == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
return 0;
}
return retVal;
}else{
/* we don't support RBNF patterns yet */
case UNUM_SCIENTIFIC:
if(locale == 0)
retVal = (UNumberFormat*)NumberFormat::createScientificInstance(*status);
else
retVal = (UNumberFormat*)NumberFormat::createScientificInstance(Locale(locale),
*status);
break;
case UNUM_PATTERN_DECIMAL: {
UParseError tErr;
/* UnicodeString can handle the case when patternLength = -1. */
const UnicodeString pat(pattern, patternLength);
@ -109,24 +91,55 @@ unum_open( UNumberFormatStyle style,
if(locale == 0)
syms = new DecimalFormatSymbols(*status);
else
syms = new DecimalFormatSymbols(Locale(locale),
*status);
syms = new DecimalFormatSymbols(Locale(locale), *status);
if(syms == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
return 0;
}
DecimalFormat *fmt = 0;
fmt = new DecimalFormat(pat, syms, *parseErr, *status);
if(fmt == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
retVal = (UNumberFormat*)new DecimalFormat(pat, syms, *parseErr, *status);
if(retVal == 0) {
delete syms;
return 0;
}
} break;
#if U_HAVE_RBNF
case UNUM_PATTERN_RULEBASED: {
UParseError tErr;
/* UnicodeString can handle the case when patternLength = -1. */
const UnicodeString pat(pattern, patternLength);
if(parseErr==NULL){
parseErr = &tErr;
}
return (UNumberFormat*) fmt;
retVal = (UNumberFormat*)new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status);
} break;
case UNUM_SPELLOUT:
retVal = (UNumberFormat*)new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status);
break;
case UNUM_ORDINAL:
retVal = (UNumberFormat*)new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status);
break;
case UNUM_DURATION:
retVal = (UNumberFormat*)new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status);
break;
#endif
default:
*status = U_UNSUPPORTED_ERROR;
return 0;
}
if(retVal == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
}
return retVal;
}
U_CAPI void U_EXPORT2
@ -142,8 +155,13 @@ unum_clone(const UNumberFormat *fmt,
if(U_FAILURE(*status))
return 0;
Format *res = ((DecimalFormat*)fmt)->clone();
Format *res = 0;
if (((NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
res = ((DecimalFormat*)fmt)->clone();
} else {
res = ((RuleBasedNumberFormat*)fmt)->clone();
}
if(res == 0) {
*status = U_MEMORY_ALLOCATION_ERROR;
return 0;
@ -311,6 +329,7 @@ U_CAPI int32_t U_EXPORT2
unum_getAttribute(const UNumberFormat* fmt,
UNumberFormatAttribute attr)
{
if (((NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
switch(attr) {
case UNUM_PARSE_INT_ONLY:
return ((NumberFormat*)fmt)->isParseIntegerOnly();
@ -360,7 +379,13 @@ unum_getAttribute(const UNumberFormat* fmt,
default:
break;
}
return -1;
} else {
if (attr == UNUM_LENIENT_PARSE) {
return ((RuleBasedNumberFormat*)fmt)->isLenient();
}
}
return -1;
}
U_CAPI void U_EXPORT2
@ -368,6 +393,7 @@ unum_setAttribute( UNumberFormat* fmt,
UNumberFormatAttribute attr,
int32_t newValue)
{
if (((NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
switch(attr) {
case UNUM_PARSE_INT_ONLY:
((NumberFormat*)fmt)->setParseIntegerOnly((UBool)newValue);
@ -436,13 +462,19 @@ unum_setAttribute( UNumberFormat* fmt,
/* Shouldn't get here anyway */
break;
}
} else {
if (attr == UNUM_LENIENT_PARSE) {
((RuleBasedNumberFormat*)fmt)->setLenient((UBool)newValue);
}
}
}
U_CAPI double U_EXPORT2
unum_getDoubleAttribute(const UNumberFormat* fmt,
UNumberFormatAttribute attr)
{
if (attr == UNUM_ROUNDING_INCREMENT) {
if (((NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID() &&
attr == UNUM_ROUNDING_INCREMENT) {
return ((DecimalFormat*)fmt)->getRoundingIncrement();
} else {
return -1.0;
@ -454,7 +486,8 @@ unum_setDoubleAttribute( UNumberFormat* fmt,
UNumberFormatAttribute attr,
double newValue)
{
if (attr == UNUM_ROUNDING_INCREMENT) {
if (((NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID() &&
attr == UNUM_ROUNDING_INCREMENT) {
((DecimalFormat*)fmt)->setRoundingIncrement(newValue);
}
}
@ -476,34 +509,50 @@ unum_getTextAttribute(const UNumberFormat* fmt,
res.setTo(result, 0, resultLength);
}
switch(tag) {
case UNUM_POSITIVE_PREFIX:
if (((NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
switch(tag) {
case UNUM_POSITIVE_PREFIX:
((DecimalFormat*)fmt)->getPositivePrefix(res);
break;
case UNUM_POSITIVE_SUFFIX:
case UNUM_POSITIVE_SUFFIX:
((DecimalFormat*)fmt)->getPositiveSuffix(res);
break;
case UNUM_NEGATIVE_PREFIX:
case UNUM_NEGATIVE_PREFIX:
((DecimalFormat*)fmt)->getNegativePrefix(res);
break;
case UNUM_NEGATIVE_SUFFIX:
case UNUM_NEGATIVE_SUFFIX:
((DecimalFormat*)fmt)->getNegativeSuffix(res);
break;
case UNUM_PADDING_CHARACTER:
case UNUM_PADDING_CHARACTER:
res = ((DecimalFormat*)fmt)->getPadCharacterString();
break;
case UNUM_CURRENCY_CODE:
case UNUM_CURRENCY_CODE:
res = UnicodeString(((DecimalFormat*)fmt)->getCurrency());
break;
default:
default:
*status = U_UNSUPPORTED_ERROR;
return -1;
}
} else {
RuleBasedNumberFormat* rbnf = (RuleBasedNumberFormat*)fmt;
if (tag == UNUM_DEFAULT_RULESET) {
res = rbnf->getDefaultRuleSetName();
} else if (tag == UNUM_PUBLIC_RULESETS) {
int32_t count = rbnf->getNumberOfRuleSetNames();
for (int i = 0; i < count; ++i) {
res += rbnf->getRuleSetName(i);
res += (UChar)0x003b; // semicolon
}
} else {
*status = U_UNSUPPORTED_ERROR;
return -1;
}
}
return res.extract(result, resultLength, *status);
@ -522,34 +571,42 @@ unum_setTextAttribute( UNumberFormat* fmt,
int32_t len = (newValueLength == -1 ? u_strlen(newValue) : newValueLength);
const UnicodeString val((UChar*)newValue, len, len);
switch(tag) {
case UNUM_POSITIVE_PREFIX:
if (((NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
switch(tag) {
case UNUM_POSITIVE_PREFIX:
((DecimalFormat*)fmt)->setPositivePrefix(val);
break;
case UNUM_POSITIVE_SUFFIX:
case UNUM_POSITIVE_SUFFIX:
((DecimalFormat*)fmt)->setPositiveSuffix(val);
break;
case UNUM_NEGATIVE_PREFIX:
case UNUM_NEGATIVE_PREFIX:
((DecimalFormat*)fmt)->setNegativePrefix(val);
break;
case UNUM_NEGATIVE_SUFFIX:
case UNUM_NEGATIVE_SUFFIX:
((DecimalFormat*)fmt)->setNegativeSuffix(val);
break;
case UNUM_PADDING_CHARACTER:
case UNUM_PADDING_CHARACTER:
((DecimalFormat*)fmt)->setPadCharacter(*newValue);
break;
case UNUM_CURRENCY_CODE:
case UNUM_CURRENCY_CODE:
((DecimalFormat*)fmt)->setCurrency(newValue, *status);
break;
default:
default:
*status = U_UNSUPPORTED_ERROR;
break;
}
} else {
if (tag == UNUM_DEFAULT_RULESET) {
((RuleBasedNumberFormat*)fmt)->setDefaultRuleSet(newValue, *status);
} else {
*status = U_UNSUPPORTED_ERROR;
}
}
}
@ -569,12 +626,15 @@ unum_toPattern( const UNumberFormat* fmt,
// otherwise, alias the destination buffer
pat.setTo(result, 0, resultLength);
}
if(isPatternLocalized)
if (((NumberFormat*)fmt)->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
if(isPatternLocalized)
((DecimalFormat*)fmt)->toLocalizedPattern(pat);
else
else
((DecimalFormat*)fmt)->toPattern(pat);
} else {
pat = ((RuleBasedNumberFormat*)fmt)->getRules();
}
return pat.extract(result, resultLength, *status);
}
@ -594,6 +654,11 @@ unum_getSymbol(UNumberFormat *fmt,
return 0;
}
if (((NumberFormat*)fmt)->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
*status = U_UNSUPPORTED_ERROR;
return 0;
}
return ((const DecimalFormat *)fmt)->
getDecimalFormatSymbols()->
getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol).
@ -616,6 +681,11 @@ unum_setSymbol(UNumberFormat *fmt,
return;
}
if (((NumberFormat*)fmt)->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
*status = U_UNSUPPORTED_ERROR;
return;
}
DecimalFormatSymbols symbols(*((DecimalFormat *)fmt)->getDecimalFormatSymbols());
symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol,
UnicodeString(value, length)); /* UnicodeString can handle the case when length = -1. */
@ -645,15 +715,16 @@ unum_applyPattern( UNumberFormat *format,
const UnicodeString pat((UChar*)pattern, len, len);
// Verify if the object passed is a DecimalFormat object
if(((NumberFormat*)format)->getDynamicClassID()!= DecimalFormat::getStaticClassID()){
*status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
if(localized)
if (((NumberFormat*)format)->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
if(localized) {
((DecimalFormat*)format)->applyLocalizedPattern(pat,*parseError, *status);
else
} else {
((DecimalFormat*)format)->applyPattern(pat,*parseError, *status);
}
} else {
*status = U_UNSUPPORTED_ERROR;
return;
}
}
U_CAPI const char* U_EXPORT2

View File

@ -39,6 +39,7 @@ void addNumForTest(TestNode** root)
addTest(root, &TestNumberFormat, "tsformat/cnumtst/TestNumberFormat");
addTest(root, &TestNumberFormatPadding, "tsformat/cnumtst/TestNumberFormatPadding");
addTest(root, &TestInt64Format, "tsformat/cnumtst/TestInt64Format");
addTest(root, &TestRBNFFormat, "tsformat/cnumtst/TestRBNFFormat");
}
/** copy src to dst with unicode-escapes for values < 0x20 and > 0x7e, null terminate if possible */
@ -909,4 +910,244 @@ static void TestInt64Format() {
unum_close(fmt);
}
void test_fmt(UNumberFormat* fmt, UBool isDecimal) {
UChar buffer[512];
int BUFSIZE = sizeof(buffer)/sizeof(buffer[0]);
char temp[512];
double vals[] = {
-.2, 0, .2, 5.5, 15.2, 250, 123456789
};
int i;
for (i = 0; i < sizeof(vals)/sizeof(vals[0]); ++i) {
UErrorCode status = U_ZERO_ERROR;
unum_formatDouble(fmt, vals[i], buffer, BUFSIZE, NULL, &status);
if (U_FAILURE(status)) {
log_err("failed to format: %g, returned %s\n", vals[i], u_errorName(status));
} else {
u_austrcpy(temp, buffer);
log_verbose("formatting %g returned '%s'\n", vals[i], temp);
}
}
// check APIs now
{
UChar temp[128];
UErrorCode status = U_ZERO_ERROR;
UParseError perr;
u_uastrcpy(temp, "#,##0.0#");
unum_applyPattern(fmt, FALSE, temp, -1, &perr, &status);
if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) {
log_err("got unexpected error for applyPattern: '%s'\n", u_errorName(status));
}
}
{
int isLenient = unum_getAttribute(fmt, UNUM_LENIENT_PARSE);
log_verbose("lenient: 0x%x\n", isLenient);
if (isDecimal ? (isLenient != -1) : (isLenient == TRUE)) {
log_err("didn't expect lenient value: %d\n", isLenient);
}
unum_setAttribute(fmt, UNUM_LENIENT_PARSE, TRUE);
isLenient = unum_getAttribute(fmt, UNUM_LENIENT_PARSE);
if (isDecimal ? (isLenient != -1) : (isLenient == FALSE)) {
log_err("didn't expect lenient value after set: %d\n", isLenient);
}
}
{
double val2;
double val = unum_getDoubleAttribute(fmt, UNUM_LENIENT_PARSE);
if (val != -1) {
log_err("didn't expect double attribute\n");
}
val = unum_getDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT);
if ((val == -1) == isDecimal) {
log_err("didn't expect -1 rounding increment\n");
}
unum_setDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT, val+.5);
val2 = unum_getDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT);
if (isDecimal && (val2 - val != .5)) {
log_err("set rounding increment had no effect on decimal format");
}
}
{
UErrorCode status = U_ZERO_ERROR;
char temp[512];
UChar buffer[512];
int BUFSIZE = sizeof(buffer)/sizeof(buffer[0]);
int len = unum_getTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, BUFSIZE, &status);
if (isDecimal ? (status != U_UNSUPPORTED_ERROR) : U_FAILURE(status)) {
log_err("got unexpected error for get default ruleset: '%s'\n", u_errorName(status));
}
if (U_SUCCESS(status)) {
u_austrcpy(temp, buffer);
log_verbose("default ruleset: '%s'\n", temp);
}
status = U_ZERO_ERROR;
len = unum_getTextAttribute(fmt, UNUM_PUBLIC_RULESETS, buffer, BUFSIZE, &status);
if (isDecimal ? (status != U_UNSUPPORTED_ERROR) : U_FAILURE(status)) {
log_err("got unexpected error for get public rulesets: '%s'\n", u_errorName(status));
}
if (U_SUCCESS(status)) {
u_austrcpy(temp, buffer);
log_verbose("public rulesets: '%s'\n", temp);
// set the default ruleset to the first one found, and retry
if (len > 0) {
int i;
for (i = 0; i < len && temp[i] != ';'; ++i){};
if (i < len) {
buffer[i] = 0;
unum_setTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, -1, &status);
if (U_FAILURE(status)) {
log_err("unexpected error setting default ruleset: '%s'\n", u_errorName(status));
} else {
int len2 = unum_getTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, BUFSIZE, &status);
if (U_FAILURE(status)) {
log_err("could not fetch default ruleset: '%s'\n", u_errorName(status));
} else if (len2 != i) {
u_austrcpy(temp, buffer);
log_err("unexpected ruleset len: %d ex: %d val: %s\n", len2, i, temp);
} else {
for (i = 0; i < sizeof(vals)/sizeof(vals[0]); ++i) {
UErrorCode status = U_ZERO_ERROR;
unum_formatDouble(fmt, vals[i], buffer, BUFSIZE, NULL, &status);
if (U_FAILURE(status)) {
log_err("failed to format: %g, returned %s\n", vals[i], u_errorName(status));
} else {
u_austrcpy(temp, buffer);
log_verbose("formatting %g returned '%s'\n", vals[i], temp);
}
}
}
}
}
}
}
}
{
UErrorCode status = U_ZERO_ERROR;
int len = unum_toPattern(fmt, FALSE, buffer, BUFSIZE, &status);
if (U_SUCCESS(status)) {
u_austrcpy(temp, buffer);
log_verbose("pattern: '%s'\n", temp);
} else if (status != U_BUFFER_OVERFLOW_ERROR) {
log_err("toPattern failed unexpectedly: %s\n", u_errorName(status));
} else {
log_verbose("pattern too long to display\n");
}
}
{
UErrorCode status = U_ZERO_ERROR;
int len = unum_getSymbol(fmt, UNUM_CURRENCY_SYMBOL, buffer, BUFSIZE, &status);
if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) {
log_err("unexpected error getting symbol: '%s'\n", u_errorName(status));
}
unum_setSymbol(fmt, UNUM_CURRENCY_SYMBOL, buffer, len, &status);
if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) {
log_err("unexpected error setting symbol: '%s'\n", u_errorName(status));
}
}
}
static void TestRBNFFormat() {
int status;
UParseError perr;
UChar temp[768];
UNumberFormat *formats[5];
int COUNT = sizeof(formats)/sizeof(formats[0]);
int i;
const char* pat;
for (i = 0; i < COUNT; ++i) {
formats[i] = 0;
}
// instantiation
status = U_ZERO_ERROR;
u_uastrcpy(temp, "#,##0.0#;(#,##0.0#)");
formats[0] = unum_open(UNUM_PATTERN_DECIMAL, temp, -1, "en_US", &perr, &status);
if (U_FAILURE(status)) {
log_err("unable to open decimal pattern");
}
status = U_ZERO_ERROR;
formats[1] = unum_open(UNUM_SPELLOUT, NULL, 0, "en_US", &perr, &status);
if (U_FAILURE(status)) {
log_err("unable to open spellout");
}
status = U_ZERO_ERROR;
formats[2] = unum_open(UNUM_ORDINAL, NULL, 0, "en_US", &perr, &status);
if (U_FAILURE(status)) {
log_err("unable to open ordinal");
}
status = U_ZERO_ERROR;
formats[3] = unum_open(UNUM_DURATION, NULL, 0, "en_US", &perr, &status);
if (U_FAILURE(status)) {
log_err("unable to open duration");
}
status = U_ZERO_ERROR;
pat =
"%standard:\n"
"-x: minus >>;\n"
"x.x: << point >>;\n"
"zero; one; two; three; four; five; six; seven; eight; nine;\n"
"ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n"
"seventeen; eighteen; nineteen;\n"
"20: twenty[->>];\n"
"30: thirty[->>];\n"
"40: forty[->>];\n"
"50: fifty[->>];\n"
"60: sixty[->>];\n"
"70: seventy[->>];\n"
"80: eighty[->>];\n"
"90: ninety[->>];\n"
"100: =#,##0=;\n"
"%simple:\n"
"=%standard=;\n"
"20: twenty[ and change];\n"
"30: thirty[ and change];\n"
"40: forty[ and change];\n"
"50: fifty[ and change];\n"
"60: sixty[ and change];\n"
"70: seventy[ and change];\n"
"80: eighty[ and change];\n"
"90: ninety[ and change];\n"
"100: =#,##0=;\n"
"%bogus:\n"
"0.x: tiny;\n"
"x.x: << point something;\n"
"=%standard=;\n"
"20: some reasonable number;\n"
"100: some substantial number;\n"
"100,000,000: some huge number;\n";
u_uastrcpy(temp, pat);
formats[4] = unum_open(UNUM_PATTERN_RULEBASED, temp, -1, "en_US", &perr, &status);
if (U_FAILURE(status)) {
log_err("unable to open rulebased pattern");
}
for (i = 0; i < COUNT; ++i) {
log_verbose("\n\ntesting format %d\n", i);
test_fmt(formats[i], i == 0);
}
for (i = 0; i < COUNT; ++i) {
unum_close(formats[i]);
}
}
#endif /* #if !UCONFIG_NO_FORMATTING */

View File

@ -38,6 +38,11 @@
**/
static void TestInt64Format(void);
/**
* Test RBNF access through unumfmt APIs.
**/
static void TestRBNFFormat(void);
#endif /* #if !UCONFIG_NO_FORMATTING */
#endif

View File

@ -5,8 +5,8 @@
*******************************************************************************
*
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/text/NFRuleSet.java,v $
* $Date: 2002/07/31 17:37:08 $
* $Revision: 1.7 $
* $Date: 2004/03/12 20:15:13 $
* $Revision: 1.8 $
*
*****************************************************************************************
*/
@ -24,7 +24,7 @@ import java.util.Vector;
* appropriate rule for formatting a particular number and dispatch
* control to it, and to arbitrate between different rules when parsing
* a number.
* $RCSfile: NFRuleSet.java,v $ $Revision: 1.7 $ $Date: 2002/07/31 17:37:08 $
* $RCSfile: NFRuleSet.java,v $ $Revision: 1.8 $ $Date: 2004/03/12 20:15:13 $
*/
final class NFRuleSet {
//-----------------------------------------------------------------------
@ -359,7 +359,7 @@ final class NFRuleSet {
return isFractionRuleSet;
}
/*
/**
* Returns the rule set's name
* @return The rule set's name
*/
@ -367,6 +367,14 @@ final class NFRuleSet {
return name;
}
/**
* Return true if the rule set is public.
* @return true if the rule set is public
*/
public boolean isPublic() {
return !name.startsWith("%%");
}
//-----------------------------------------------------------------------
// formatting
//-----------------------------------------------------------------------

View File

@ -5,8 +5,8 @@
*******************************************************************************
*
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/text/RuleBasedNumberFormat.java,v $
* $Date: 2004/01/29 19:29:05 $
* $Revision: 1.20 $
* $Date: 2004/03/12 20:15:13 $
* $Revision: 1.21 $
*
*****************************************************************************************
*/
@ -475,7 +475,7 @@ import java.util.ResourceBundle;
* using these features.</p>
*
* @author Richard Gillam
* $RCSfile: RuleBasedNumberFormat.java,v $ $Revision: 1.20 $ $Date: 2004/01/29 19:29:05 $
* $RCSfile: RuleBasedNumberFormat.java,v $ $Revision: 1.21 $ $Date: 2004/03/12 20:15:13 $
* @see NumberFormat
* @see DecimalFormat
* @stable ICU 2.0
@ -1040,6 +1040,18 @@ public final class RuleBasedNumberFormat extends NumberFormat {
}
}
/**
* Return the name of the current default rule set.
* @retrurn the name of the current default rule set, if it is public, else the empty string.
* @draft ICU 3.0
*/
public String getDefaultRuleSetName() {
if (defaultRuleSet != null && defaultRuleSet.isPublic()) {
return defaultRuleSet.getName();
}
return "";
}
//-----------------------------------------------------------------------
// package-internal API
//-----------------------------------------------------------------------