mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 07:39:16 +00:00
ICU-6192 add support for getting field positions to NumberFormat and DateFormat
X-SVN-Rev: 27093
This commit is contained in:
parent
8a58804ef1
commit
52c23e0a47
22 changed files with 1465 additions and 177 deletions
|
@ -83,7 +83,7 @@ wintzimpl.o windtfmt.o winnmfmt.o basictz.o dtrule.o rbtz.o tzrule.o tztrans.o v
|
|||
zonemeta.o zstrfmt.o plurrule.o plurfmt.o dtitvfmt.o dtitvinf.o \
|
||||
tmunit.o tmutamt.o tmutfmt.o colldata.o bmsearch.o bms.o currpinf.o \
|
||||
uspoof.o uspoof_impl.o uspoof_build.o uspoof_conf.o uspoof_wsconf.o \
|
||||
ztrans.o zrule.o vzone.o
|
||||
ztrans.o zrule.o vzone.o fphdlimp.o fpositer.o
|
||||
|
||||
## Header files to install
|
||||
HEADERS = $(srcdir)/unicode/*.h
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1997-2008, International Business Machines Corporation and *
|
||||
* Copyright (C) 1997-2009, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -141,6 +141,55 @@ DateFormat::format(const Formattable& obj,
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
UnicodeString&
|
||||
DateFormat::format(const Formattable& obj,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
if (U_FAILURE(status)) return appendTo;
|
||||
|
||||
// if the type of the Formattable is double or long, treat it as if it were a Date
|
||||
UDate date = 0;
|
||||
switch (obj.getType())
|
||||
{
|
||||
case Formattable::kDate:
|
||||
date = obj.getDate();
|
||||
break;
|
||||
case Formattable::kDouble:
|
||||
date = (UDate)obj.getDouble();
|
||||
break;
|
||||
case Formattable::kLong:
|
||||
date = (UDate)obj.getLong();
|
||||
break;
|
||||
default:
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
// Is this right?
|
||||
//if (fieldPosition.getBeginIndex() == fieldPosition.getEndIndex())
|
||||
// status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
|
||||
return format(date, appendTo, posIter, status);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Default implementation for backwards compatibility, subclasses should implement.
|
||||
UnicodeString&
|
||||
DateFormat::format(Calendar& /* unused cal */,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& /* unused posIter */,
|
||||
UErrorCode& status) const {
|
||||
if (U_SUCCESS(status)) {
|
||||
status = U_UNSUPPORTED_ERROR;
|
||||
}
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
UnicodeString&
|
||||
DateFormat::format(UDate date, UnicodeString& appendTo, FieldPosition& fieldPosition) const {
|
||||
if (fCalendar != NULL) {
|
||||
|
@ -156,6 +205,20 @@ DateFormat::format(UDate date, UnicodeString& appendTo, FieldPosition& fieldPosi
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
UnicodeString&
|
||||
DateFormat::format(UDate date, UnicodeString& appendTo, FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const {
|
||||
if (fCalendar != NULL) {
|
||||
fCalendar->setTime(date, status);
|
||||
if (U_SUCCESS(status)) {
|
||||
return format(*fCalendar, appendTo, posIter, status);
|
||||
}
|
||||
}
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
UnicodeString&
|
||||
DateFormat::format(UDate date, UnicodeString& appendTo) const
|
||||
{
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "fphdlimp.h"
|
||||
#include "unicode/decimfmt.h"
|
||||
#include "unicode/choicfmt.h"
|
||||
#include "unicode/ucurr.h"
|
||||
|
@ -125,6 +126,8 @@ static void debugout(UnicodeString s) {
|
|||
#define debug(x)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// class DecimalFormat
|
||||
// *****************************************************************************
|
||||
|
@ -983,6 +986,15 @@ DecimalFormat::format(int32_t number,
|
|||
{
|
||||
return format((int64_t)number, appendTo, fieldPosition);
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
DecimalFormat::format(int32_t number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
return format((int64_t)number, appendTo, posIter, status);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
@ -991,11 +1003,26 @@ DecimalFormat::format(int64_t number,
|
|||
UnicodeString& appendTo,
|
||||
FieldPosition& fieldPosition) const
|
||||
{
|
||||
DigitList digits;
|
||||
FieldPositionOnlyHandler handler(fieldPosition);
|
||||
return _format(number, appendTo, handler);
|
||||
}
|
||||
|
||||
// Clears field positions.
|
||||
fieldPosition.setBeginIndex(0);
|
||||
fieldPosition.setEndIndex(0);
|
||||
UnicodeString&
|
||||
DecimalFormat::format(int64_t number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
FieldPositionIteratorHandler handler(posIter, status);
|
||||
return _format(number, appendTo, handler);
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
DecimalFormat::_format(int64_t number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionHandler& handler) const
|
||||
{
|
||||
DigitList digits;
|
||||
|
||||
// If we are to do rounding, we need to move into the BigDecimal
|
||||
// domain in order to do divide/multiply correctly.
|
||||
|
@ -1020,7 +1047,7 @@ DecimalFormat::format(int64_t number,
|
|||
digits.set(number * fMultiplier, precision(TRUE));
|
||||
}
|
||||
|
||||
return subformat(appendTo, fieldPosition, digits, TRUE);
|
||||
return subformat(appendTo, handler, digits, TRUE);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -1030,23 +1057,35 @@ DecimalFormat::format( double number,
|
|||
UnicodeString& appendTo,
|
||||
FieldPosition& fieldPosition) const
|
||||
{
|
||||
// Clears field positions.
|
||||
fieldPosition.setBeginIndex(0);
|
||||
fieldPosition.setEndIndex(0);
|
||||
FieldPositionOnlyHandler handler(fieldPosition);
|
||||
return _format(number, appendTo, handler);
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
DecimalFormat::format( double number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
FieldPositionIteratorHandler handler(posIter, status);
|
||||
return _format(number, appendTo, handler);
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
DecimalFormat::_format( double number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionHandler& handler) const
|
||||
{
|
||||
// Special case for NaN, sets the begin and end index to be the
|
||||
// the string length of localized name of NaN.
|
||||
if (uprv_isNaN(number))
|
||||
{
|
||||
if (fieldPosition.getField() == NumberFormat::kIntegerField)
|
||||
fieldPosition.setBeginIndex(appendTo.length());
|
||||
|
||||
int begin = appendTo.length();
|
||||
appendTo += getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
|
||||
|
||||
if (fieldPosition.getField() == NumberFormat::kIntegerField)
|
||||
fieldPosition.setEndIndex(appendTo.length());
|
||||
handler.addAttribute(kIntegerField, begin, appendTo.length());
|
||||
|
||||
addPadding(appendTo, fieldPosition, 0, 0);
|
||||
addPadding(appendTo, handler, 0, 0);
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
|
@ -1082,19 +1121,16 @@ DecimalFormat::format( double number,
|
|||
// Special case for INFINITE,
|
||||
if (uprv_isInfinite(number))
|
||||
{
|
||||
int32_t prefixLen = appendAffix(appendTo, number, isNegative, TRUE);
|
||||
|
||||
if (fieldPosition.getField() == NumberFormat::kIntegerField)
|
||||
fieldPosition.setBeginIndex(appendTo.length());
|
||||
int32_t prefixLen = appendAffix(appendTo, number, handler, isNegative, TRUE);
|
||||
|
||||
int begin = appendTo.length();
|
||||
appendTo += getConstSymbol(DecimalFormatSymbols::kInfinitySymbol);
|
||||
|
||||
if (fieldPosition.getField() == NumberFormat::kIntegerField)
|
||||
fieldPosition.setEndIndex(appendTo.length());
|
||||
handler.addAttribute(kIntegerField, begin, appendTo.length());
|
||||
|
||||
int32_t suffixLen = appendAffix(appendTo, number, isNegative, FALSE);
|
||||
int32_t suffixLen = appendAffix(appendTo, number, handler, isNegative, FALSE);
|
||||
|
||||
addPadding(appendTo, fieldPosition, prefixLen, suffixLen);
|
||||
addPadding(appendTo, handler, prefixLen, suffixLen);
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
|
@ -1108,7 +1144,7 @@ DecimalFormat::format( double number,
|
|||
digits.set(number, precision(FALSE),
|
||||
!fUseExponentialNotation && !areSignificantDigitsUsed());
|
||||
|
||||
return subformat(appendTo, fieldPosition, digits, FALSE);
|
||||
return subformat(appendTo, handler, digits, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1179,16 +1215,15 @@ UBool DecimalFormat::isGroupingPosition(int32_t pos) const {
|
|||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* Complete the formatting of a finite number. On entry, the fDigitList must
|
||||
* be filled in with the correct digits.
|
||||
*/
|
||||
UnicodeString&
|
||||
DecimalFormat::subformat(UnicodeString& appendTo,
|
||||
FieldPosition& fieldPosition,
|
||||
FieldPositionHandler& handler,
|
||||
DigitList& digits,
|
||||
UBool isInteger) const
|
||||
UBool isInteger) const
|
||||
{
|
||||
// Gets the localized zero Unicode character.
|
||||
UChar32 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
|
||||
|
@ -1222,20 +1257,14 @@ DecimalFormat::subformat(UnicodeString& appendTo,
|
|||
|
||||
// Appends the prefix.
|
||||
double doubleValue = digits.getDouble();
|
||||
int32_t prefixLen = appendAffix(appendTo, doubleValue, !digits.fIsPositive, TRUE);
|
||||
int32_t prefixLen = appendAffix(appendTo, doubleValue, handler, !digits.fIsPositive, TRUE);
|
||||
|
||||
if (fUseExponentialNotation)
|
||||
{
|
||||
// Record field information for caller.
|
||||
if (fieldPosition.getField() == NumberFormat::kIntegerField)
|
||||
{
|
||||
fieldPosition.setBeginIndex(appendTo.length());
|
||||
fieldPosition.setEndIndex(-1);
|
||||
}
|
||||
else if (fieldPosition.getField() == NumberFormat::kFractionField)
|
||||
{
|
||||
fieldPosition.setBeginIndex(-1);
|
||||
}
|
||||
int currentLength = appendTo.length();
|
||||
int intBegin = currentLength;
|
||||
int intEnd = -1;
|
||||
int fracBegin = -1;
|
||||
|
||||
int32_t minFracDig = 0;
|
||||
if (useSigDig) {
|
||||
|
@ -1299,15 +1328,13 @@ DecimalFormat::subformat(UnicodeString& appendTo,
|
|||
{
|
||||
if (i == integerDigits)
|
||||
{
|
||||
// Record field information for caller.
|
||||
if (fieldPosition.getField() == NumberFormat::kIntegerField)
|
||||
fieldPosition.setEndIndex(appendTo.length());
|
||||
intEnd = appendTo.length();
|
||||
handler.addAttribute(kIntegerField, intBegin, intEnd);
|
||||
|
||||
appendTo += *decimal;
|
||||
|
||||
// Record field information for caller.
|
||||
if (fieldPosition.getField() == NumberFormat::kFractionField)
|
||||
fieldPosition.setBeginIndex(appendTo.length());
|
||||
fracBegin = appendTo.length();
|
||||
handler.addAttribute(kDecimalSeparatorField, fracBegin - 1, fracBegin);
|
||||
}
|
||||
// Restores the digit character or pads the buffer with zeros.
|
||||
UChar32 c = (UChar32)((i < digits.fCount) ?
|
||||
|
@ -1316,17 +1343,13 @@ DecimalFormat::subformat(UnicodeString& appendTo,
|
|||
appendTo += c;
|
||||
}
|
||||
|
||||
// Record field information
|
||||
if (fieldPosition.getField() == NumberFormat::kIntegerField)
|
||||
{
|
||||
if (fieldPosition.getEndIndex() < 0)
|
||||
fieldPosition.setEndIndex(appendTo.length());
|
||||
currentLength = appendTo.length();
|
||||
|
||||
if (intEnd < 0) {
|
||||
handler.addAttribute(kIntegerField, intBegin, currentLength);
|
||||
}
|
||||
else if (fieldPosition.getField() == NumberFormat::kFractionField)
|
||||
{
|
||||
if (fieldPosition.getBeginIndex() < 0)
|
||||
fieldPosition.setBeginIndex(appendTo.length());
|
||||
fieldPosition.setEndIndex(appendTo.length());
|
||||
if (fracBegin > 0) {
|
||||
handler.addAttribute(kFractionField, fracBegin, currentLength);
|
||||
}
|
||||
|
||||
// The exponent is output using the pattern-specified minimum
|
||||
|
@ -1335,6 +1358,9 @@ DecimalFormat::subformat(UnicodeString& appendTo,
|
|||
// unacceptable inaccuracy.
|
||||
appendTo += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
|
||||
|
||||
handler.addAttribute(kExponentSymbolField, currentLength, appendTo.length());
|
||||
currentLength = appendTo.length();
|
||||
|
||||
// For zero values, we force the exponent to zero. We
|
||||
// must do this here, and not earlier, because the value
|
||||
// is used to determine integer digit count above.
|
||||
|
@ -1343,10 +1369,14 @@ DecimalFormat::subformat(UnicodeString& appendTo,
|
|||
|
||||
if (exponent < 0) {
|
||||
appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
|
||||
handler.addAttribute(kExponentSignField, currentLength, appendTo.length());
|
||||
} else if (fExponentSignAlwaysShown) {
|
||||
appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
|
||||
handler.addAttribute(kExponentSignField, currentLength, appendTo.length());
|
||||
}
|
||||
|
||||
currentLength = appendTo.length();
|
||||
|
||||
DigitList expDigits;
|
||||
expDigits.set(exponent);
|
||||
{
|
||||
|
@ -1363,12 +1393,13 @@ DecimalFormat::subformat(UnicodeString& appendTo,
|
|||
(expDigits.fDigits[i] + zeroDelta) : zero);
|
||||
appendTo += c;
|
||||
}
|
||||
|
||||
handler.addAttribute(kExponentField, currentLength, appendTo.length());
|
||||
}
|
||||
else // Not using exponential notation
|
||||
{
|
||||
// Record field information for caller.
|
||||
if (fieldPosition.getField() == NumberFormat::kIntegerField)
|
||||
fieldPosition.setBeginIndex(appendTo.length());
|
||||
int currentLength = appendTo.length();
|
||||
int intBegin = currentLength;
|
||||
|
||||
int32_t sigCount = 0;
|
||||
int32_t minSigDig = getMinimumSignificantDigits();
|
||||
|
@ -1421,13 +1452,17 @@ DecimalFormat::subformat(UnicodeString& appendTo,
|
|||
|
||||
// Output grouping separator if necessary.
|
||||
if (isGroupingPosition(i)) {
|
||||
currentLength = appendTo.length();
|
||||
appendTo.append(*grouping);
|
||||
handler.addAttribute(kGroupingSeparatorField, currentLength, appendTo.length());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(dlf): this looks like it was a bug, we marked the int field as ending
|
||||
// before the zero was generated.
|
||||
// Record field information for caller.
|
||||
if (fieldPosition.getField() == NumberFormat::kIntegerField)
|
||||
fieldPosition.setEndIndex(appendTo.length());
|
||||
// if (fieldPosition.getField() == NumberFormat::kIntegerField)
|
||||
// fieldPosition.setEndIndex(appendTo.length());
|
||||
|
||||
// Determine whether or not there are any printable fractional
|
||||
// digits. If we've used up the digits we know there aren't.
|
||||
|
@ -1440,13 +1475,17 @@ DecimalFormat::subformat(UnicodeString& appendTo,
|
|||
if (!fractionPresent && appendTo.length() == sizeBeforeIntegerPart)
|
||||
appendTo += (zero);
|
||||
|
||||
// Output the decimal separator if we always do so.
|
||||
if (fDecimalSeparatorAlwaysShown || fractionPresent)
|
||||
appendTo += *decimal;
|
||||
currentLength = appendTo.length();
|
||||
handler.addAttribute(kIntegerField, intBegin, currentLength);
|
||||
|
||||
// Record field information for caller.
|
||||
if (fieldPosition.getField() == NumberFormat::kFractionField)
|
||||
fieldPosition.setBeginIndex(appendTo.length());
|
||||
// Output the decimal separator if we always do so.
|
||||
if (fDecimalSeparatorAlwaysShown || fractionPresent) {
|
||||
appendTo += *decimal;
|
||||
handler.addAttribute(kDecimalSeparatorField, currentLength, appendTo.length());
|
||||
currentLength = appendTo.length();
|
||||
}
|
||||
|
||||
int fracBegin = currentLength;
|
||||
|
||||
count = useSigDig ? INT32_MAX : getMaximumFractionDigits();
|
||||
if (useSigDig && (sigCount == maxSigDig ||
|
||||
|
@ -1495,14 +1534,12 @@ DecimalFormat::subformat(UnicodeString& appendTo,
|
|||
}
|
||||
}
|
||||
|
||||
// Record field information for caller.
|
||||
if (fieldPosition.getField() == NumberFormat::kFractionField)
|
||||
fieldPosition.setEndIndex(appendTo.length());
|
||||
handler.addAttribute(kFractionField, fracBegin, appendTo.length());
|
||||
}
|
||||
|
||||
int32_t suffixLen = appendAffix(appendTo, doubleValue, !digits.fIsPositive, FALSE);
|
||||
int32_t suffixLen = appendAffix(appendTo, doubleValue, handler, !digits.fIsPositive, FALSE);
|
||||
|
||||
addPadding(appendTo, fieldPosition, prefixLen, suffixLen);
|
||||
addPadding(appendTo, handler, prefixLen, suffixLen);
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
|
@ -1511,7 +1548,7 @@ DecimalFormat::subformat(UnicodeString& appendTo,
|
|||
* @param result the string to be padded
|
||||
*/
|
||||
void DecimalFormat::addPadding(UnicodeString& appendTo,
|
||||
FieldPosition& fieldPosition,
|
||||
FieldPositionHandler& handler,
|
||||
int32_t prefixLen,
|
||||
int32_t suffixLen) const
|
||||
{
|
||||
|
@ -1536,10 +1573,8 @@ void DecimalFormat::addPadding(UnicodeString& appendTo,
|
|||
appendTo += padding;
|
||||
break;
|
||||
}
|
||||
if (fPadPosition == kPadBeforePrefix ||
|
||||
fPadPosition == kPadAfterPrefix) {
|
||||
fieldPosition.setBeginIndex(len + fieldPosition.getBeginIndex());
|
||||
fieldPosition.setEndIndex(len + fieldPosition.getEndIndex());
|
||||
if (fPadPosition == kPadBeforePrefix || fPadPosition == kPadAfterPrefix) {
|
||||
handler.shiftLast(len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2974,17 +3009,18 @@ DecimalFormat::toLocalizedPattern(UnicodeString& result) const
|
|||
* In all other cases, the 'pluralCount' is null, which means it is not needed.
|
||||
*/
|
||||
void DecimalFormat::expandAffixes(const UnicodeString* pluralCount) {
|
||||
FieldPositionHandler none;
|
||||
if (fPosPrefixPattern != 0) {
|
||||
expandAffix(*fPosPrefixPattern, fPositivePrefix, 0, FALSE, pluralCount);
|
||||
expandAffix(*fPosPrefixPattern, fPositivePrefix, 0, none, FALSE, pluralCount);
|
||||
}
|
||||
if (fPosSuffixPattern != 0) {
|
||||
expandAffix(*fPosSuffixPattern, fPositiveSuffix, 0, FALSE, pluralCount);
|
||||
expandAffix(*fPosSuffixPattern, fPositiveSuffix, 0, none, FALSE, pluralCount);
|
||||
}
|
||||
if (fNegPrefixPattern != 0) {
|
||||
expandAffix(*fNegPrefixPattern, fNegativePrefix, 0, FALSE, pluralCount);
|
||||
expandAffix(*fNegPrefixPattern, fNegativePrefix, 0, none, FALSE, pluralCount);
|
||||
}
|
||||
if (fNegSuffixPattern != 0) {
|
||||
expandAffix(*fNegSuffixPattern, fNegativeSuffix, 0, FALSE, pluralCount);
|
||||
expandAffix(*fNegSuffixPattern, fNegativeSuffix, 0, none, FALSE, pluralCount);
|
||||
}
|
||||
#ifdef FMT_DEBUG
|
||||
UnicodeString s;
|
||||
|
@ -3041,6 +3077,7 @@ void DecimalFormat::expandAffixes(const UnicodeString* pluralCount) {
|
|||
void DecimalFormat::expandAffix(const UnicodeString& pattern,
|
||||
UnicodeString& affix,
|
||||
double number,
|
||||
FieldPositionHandler& handler,
|
||||
UBool doFormat,
|
||||
const UnicodeString* pluralCount) const {
|
||||
affix.remove();
|
||||
|
@ -3050,6 +3087,7 @@ void DecimalFormat::expandAffix(const UnicodeString& pattern,
|
|||
if (c == kQuote) {
|
||||
c = pattern.char32At(i);
|
||||
i += U16_LENGTH(c);
|
||||
int beginIdx = affix.length();
|
||||
switch (c) {
|
||||
case kCurrencySign: {
|
||||
// As of ICU 2.2 we use the currency object, and
|
||||
|
@ -3090,14 +3128,17 @@ void DecimalFormat::expandAffix(const UnicodeString& pattern,
|
|||
Locale::getDefault().getName(), &isChoiceFormat,
|
||||
pluralCountChar, &len, &ec);
|
||||
affix += UnicodeString(s, len);
|
||||
handler.addAttribute(kCurrencyField, beginIdx, affix.length());
|
||||
} else if(intl) {
|
||||
affix += currencyUChars;
|
||||
handler.addAttribute(kCurrencyField, beginIdx, affix.length());
|
||||
} else {
|
||||
int32_t len;
|
||||
UBool isChoiceFormat;
|
||||
// If fSymbols is NULL, use default locale
|
||||
const UChar* s = ucurr_getName(currencyUChars, fSymbols != NULL ? fSymbols->getLocale().getName() : Locale::getDefault().getName(),
|
||||
UCURR_SYMBOL_NAME, &isChoiceFormat, &len, &ec);
|
||||
const UChar* s = ucurr_getName(currencyUChars,
|
||||
fSymbols != NULL ? fSymbols->getLocale().getName() : Locale::getDefault().getName(),
|
||||
UCURR_SYMBOL_NAME, &isChoiceFormat, &len, &ec);
|
||||
if (isChoiceFormat) {
|
||||
// Two modes here: If doFormat is false, we set up
|
||||
// currencyChoice. If doFormat is true, we use the
|
||||
|
@ -3141,11 +3182,13 @@ void DecimalFormat::expandAffix(const UnicodeString& pattern,
|
|||
// We only arrive here if the currency choice
|
||||
// format in the locale data is INVALID.
|
||||
affix += currencyUChars;
|
||||
handler.addAttribute(kCurrencyField, beginIdx, affix.length());
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
affix += UnicodeString(s, len);
|
||||
handler.addAttribute(kCurrencyField, beginIdx, affix.length());
|
||||
}
|
||||
} else {
|
||||
if(intl) {
|
||||
|
@ -3153,20 +3196,25 @@ void DecimalFormat::expandAffix(const UnicodeString& pattern,
|
|||
} else {
|
||||
affix += getConstSymbol(DecimalFormatSymbols::kCurrencySymbol);
|
||||
}
|
||||
handler.addAttribute(kCurrencyField, beginIdx, affix.length());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kPatternPercent:
|
||||
affix += getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
|
||||
handler.addAttribute(kPercentField, beginIdx, affix.length());
|
||||
break;
|
||||
case kPatternPerMill:
|
||||
affix += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
|
||||
handler.addAttribute(kPermillField, beginIdx, affix.length());
|
||||
break;
|
||||
case kPatternPlus:
|
||||
affix += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
|
||||
handler.addAttribute(kSignField, beginIdx, affix.length());
|
||||
break;
|
||||
case kPatternMinus:
|
||||
affix += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
|
||||
handler.addAttribute(kSignField, beginIdx, affix.length());
|
||||
break;
|
||||
default:
|
||||
affix.append(c);
|
||||
|
@ -3186,6 +3234,7 @@ void DecimalFormat::expandAffix(const UnicodeString& pattern,
|
|||
* @param isPrefix
|
||||
*/
|
||||
int32_t DecimalFormat::appendAffix(UnicodeString& buf, double number,
|
||||
FieldPositionHandler& handler,
|
||||
UBool isNegative, UBool isPrefix) const {
|
||||
// plural format precedes choice format
|
||||
if (fCurrencyChoice != 0 &&
|
||||
|
@ -3198,7 +3247,7 @@ int32_t DecimalFormat::appendAffix(UnicodeString& buf, double number,
|
|||
}
|
||||
if (affixPat) {
|
||||
UnicodeString affixBuf;
|
||||
expandAffix(*affixPat, affixBuf, number, TRUE, NULL);
|
||||
expandAffix(*affixPat, affixBuf, number, handler, TRUE, NULL);
|
||||
buf.append(affixBuf);
|
||||
return affixBuf.length();
|
||||
}
|
||||
|
@ -3228,7 +3277,42 @@ int32_t DecimalFormat::appendAffix(UnicodeString& buf, double number,
|
|||
affix = isNegative ? &fNegativeSuffix : &fPositiveSuffix;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t begin = (int) buf.length();
|
||||
|
||||
buf.append(*affix);
|
||||
|
||||
if (handler.isRecording()) {
|
||||
int32_t offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol));
|
||||
if (offset > -1) {
|
||||
UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kCurrencySymbol);
|
||||
handler.addAttribute(kCurrencyField, begin + offset, begin + offset + aff.length());
|
||||
}
|
||||
|
||||
offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
|
||||
if (offset > -1) {
|
||||
UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
|
||||
handler.addAttribute(kCurrencyField, begin + offset, begin + offset + aff.length());
|
||||
}
|
||||
|
||||
offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol));
|
||||
if (offset > -1) {
|
||||
UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
|
||||
handler.addAttribute(kSignField, begin + offset, begin + offset + aff.length());
|
||||
}
|
||||
|
||||
offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol));
|
||||
if (offset > -1) {
|
||||
UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
|
||||
handler.addAttribute(kPercentField, begin + offset, begin + offset + aff.length());
|
||||
}
|
||||
|
||||
offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol));
|
||||
if (offset > -1) {
|
||||
UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
|
||||
handler.addAttribute(kPermillField, begin + offset, begin + offset + aff.length());
|
||||
}
|
||||
}
|
||||
return affix->length();
|
||||
}
|
||||
|
||||
|
@ -4568,7 +4652,6 @@ DecimalFormat::copyHashForAffix(const Hashtable* source,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1997-2007, International Business Machines Corporation and *
|
||||
* Copyright (C) 1997-2009, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -108,7 +108,23 @@ Format::format(const Formattable& obj,
|
|||
|
||||
return format(obj, toAppendTo, pos, status);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------
|
||||
// Default implementation sets unsupported error; subclasses should
|
||||
// override.
|
||||
|
||||
UnicodeString&
|
||||
Format::format(const Formattable& /* unused obj */,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPositionIterator& /* unused posIter */,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
if (!U_FAILURE(status)) {
|
||||
status = U_UNSUPPORTED_ERROR;
|
||||
}
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Parses the source string and create the corresponding
|
||||
// result object. Checks the parse position for errors.
|
||||
|
|
110
icu4c/source/i18n/fphdlimp.cpp
Normal file
110
icu4c/source/i18n/fphdlimp.cpp
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
#if !UCONFIG_NO_FORMAT
|
||||
|
||||
#include "fphdlimp.h"
|
||||
|
||||
// utility FieldPositionHandler
|
||||
// base class, null implementation
|
||||
|
||||
FieldPositionHandler::~FieldPositionHandler() {
|
||||
}
|
||||
|
||||
void
|
||||
FieldPositionHandler::addAttribute(int32_t, int32_t, int32_t) {
|
||||
}
|
||||
|
||||
void
|
||||
FieldPositionHandler::shiftLast(int32_t) {
|
||||
}
|
||||
|
||||
UBool
|
||||
FieldPositionHandler::isRecording(void) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
// utility subclass FieldPositionOnlyHandler
|
||||
|
||||
FieldPositionOnlyHandler::FieldPositionOnlyHandler(FieldPosition& _pos)
|
||||
: pos(_pos) {
|
||||
}
|
||||
|
||||
FieldPositionOnlyHandler::~FieldPositionOnlyHandler() {
|
||||
}
|
||||
|
||||
void
|
||||
FieldPositionOnlyHandler::addAttribute(int32_t id, int32_t start, int32_t limit) {
|
||||
if (pos.getField() == id) {
|
||||
pos.setBeginIndex(start);
|
||||
pos.setEndIndex(limit);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FieldPositionOnlyHandler::shiftLast(int32_t delta) {
|
||||
if (delta != 0 && pos.getField() != FieldPosition::DONT_CARE && pos.getBeginIndex() != -1) {
|
||||
pos.setBeginIndex(delta + pos.getBeginIndex());
|
||||
pos.setEndIndex(delta + pos.getEndIndex());
|
||||
}
|
||||
}
|
||||
|
||||
UBool
|
||||
FieldPositionOnlyHandler::isRecording(void) {
|
||||
return pos.getField() != FieldPosition::DONT_CARE;
|
||||
}
|
||||
|
||||
|
||||
// utility subclass FieldPositionIteratorHandler
|
||||
|
||||
FieldPositionIteratorHandler::FieldPositionIteratorHandler(FieldPositionIterator& posIter,
|
||||
UErrorCode& _status)
|
||||
: iter(posIter), vec(NULL), status(_status) {
|
||||
if (U_SUCCESS(status)) {
|
||||
vec = new UVector32(status);
|
||||
}
|
||||
}
|
||||
|
||||
FieldPositionIteratorHandler::~FieldPositionIteratorHandler() {
|
||||
// setData adopts the vec regardless of status, so it's safe to null it
|
||||
iter.setData(vec, status);
|
||||
vec = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
FieldPositionIteratorHandler::addAttribute(int32_t id, int32_t start, int32_t limit) {
|
||||
if (U_SUCCESS(status) && start < limit) {
|
||||
int32_t size = vec->size();
|
||||
vec->addElement(id, status);
|
||||
vec->addElement(start, status);
|
||||
vec->addElement(limit, status);
|
||||
if (!U_SUCCESS(status)) {
|
||||
vec->setSize(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FieldPositionIteratorHandler::shiftLast(int32_t delta) {
|
||||
if (U_SUCCESS(status) && delta != 0) {
|
||||
int32_t i = vec->size();
|
||||
if (i > 0) {
|
||||
--i;
|
||||
vec->setElementAt(delta + vec->elementAti(i), i);
|
||||
--i;
|
||||
vec->setElementAt(delta + vec->elementAti(i), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UBool
|
||||
FieldPositionIteratorHandler::isRecording(void) {
|
||||
return U_SUCCESS(status);
|
||||
}
|
||||
|
||||
#endif /* !UCONFIG_NO_FORMAT */
|
72
icu4c/source/i18n/fphdlimp.h
Normal file
72
icu4c/source/i18n/fphdlimp.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef FPHDLIMP_H
|
||||
#define FPHDLIMP_H
|
||||
|
||||
#if !UCONFIG_NO_FORMAT
|
||||
|
||||
#include "unicode/fieldpos.h"
|
||||
#include "unicode/fpositer.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
// utility FieldPositionHandler
|
||||
// base class, null implementation
|
||||
|
||||
class FieldPositionHandler {
|
||||
public:
|
||||
virtual ~FieldPositionHandler();
|
||||
virtual void addAttribute(int32_t id, int32_t start, int32_t limit);
|
||||
virtual void shiftLast(int32_t delta);
|
||||
virtual UBool isRecording(void);
|
||||
};
|
||||
|
||||
|
||||
// utility subclass FieldPositionOnlyHandler
|
||||
|
||||
class FieldPositionOnlyHandler : public FieldPositionHandler {
|
||||
FieldPosition& pos;
|
||||
|
||||
public:
|
||||
FieldPositionOnlyHandler(FieldPosition& pos);
|
||||
virtual ~FieldPositionOnlyHandler();
|
||||
|
||||
virtual void addAttribute(int32_t id, int32_t start, int32_t limit);
|
||||
virtual void shiftLast(int32_t delta);
|
||||
virtual UBool isRecording(void);
|
||||
};
|
||||
|
||||
|
||||
// utility subclass FieldPositionIteratorHandler
|
||||
|
||||
class FieldPositionIteratorHandler : public FieldPositionHandler {
|
||||
FieldPositionIterator& iter;
|
||||
UVector32* vec;
|
||||
UErrorCode status;
|
||||
|
||||
// Note, we keep a reference to status, so if status is on the stack, we have
|
||||
// to be destroyed before status goes out of scope. Easiest thing is to
|
||||
// allocate us on the stack in the same (or narrower) scope as status has.
|
||||
// This attempts to encourage that by blocking heap allocation.
|
||||
void *operator new(size_t s);
|
||||
void *operator new[](size_t s);
|
||||
|
||||
public:
|
||||
FieldPositionIteratorHandler(FieldPositionIterator& posIter, UErrorCode& status);
|
||||
~FieldPositionIteratorHandler();
|
||||
|
||||
virtual void addAttribute(int32_t id, int32_t start, int32_t limit);
|
||||
virtual void shiftLast(int32_t delta);
|
||||
virtual UBool isRecording(void);
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* !UCONFIG_NO_FORMAT */
|
||||
|
||||
#endif /* FPHDLIMP_H */
|
85
icu4c/source/i18n/fpositer.cpp
Normal file
85
icu4c/source/i18n/fpositer.cpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 2009, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
******************************************************************************
|
||||
* Date Name Description
|
||||
* 12/14/09 doug Creation.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "unicode/fpositer.h"
|
||||
#include "cmemory.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(FieldPositionIterator)
|
||||
|
||||
FieldPositionIterator::~FieldPositionIterator() {
|
||||
delete data;
|
||||
data = NULL;
|
||||
pos = -1;
|
||||
}
|
||||
|
||||
FieldPositionIterator::FieldPositionIterator()
|
||||
: data(NULL), pos(-1) {
|
||||
}
|
||||
|
||||
FieldPositionIterator::FieldPositionIterator(const FieldPositionIterator &rhs)
|
||||
: UObject(rhs), data(NULL), pos(rhs.pos) {
|
||||
|
||||
if (rhs.data) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
data = new UVector32(status);
|
||||
data->assign(*rhs.data, status);
|
||||
if (status != U_ZERO_ERROR) {
|
||||
delete data;
|
||||
data = NULL;
|
||||
pos = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UBool FieldPositionIterator::operator==(const FieldPositionIterator &rhs) const {
|
||||
if (rhs == *this) {
|
||||
return TRUE;
|
||||
}
|
||||
if (pos != rhs.pos) {
|
||||
return FALSE;
|
||||
}
|
||||
if (!data) {
|
||||
return rhs.data == NULL;
|
||||
}
|
||||
return rhs.data ? data->operator==(*rhs.data) : FALSE;
|
||||
}
|
||||
|
||||
void FieldPositionIterator::setData(UVector32 *adopt, UErrorCode& status) {
|
||||
// Verify that adopt has valid data, and update status if it doesn't.
|
||||
if (U_SUCCESS(status)) {
|
||||
if (adopt) {
|
||||
if ((adopt->size() % 3) != 0) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
} else {
|
||||
for (int i = 1; i < adopt->size(); i += 3) {
|
||||
if (adopt->elementAti(i) >= adopt->elementAti(i+1)) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We own the data, even if status is in error, so we need to delete it now
|
||||
// if we're not keeping track of it.
|
||||
if (!U_SUCCESS(status)) {
|
||||
delete adopt;
|
||||
return;
|
||||
}
|
||||
|
||||
delete data;
|
||||
data = adopt;
|
||||
pos = adopt == NULL ? -1 : 0;
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
|
@ -1362,6 +1362,58 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\fphdlimp.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\fphdlimp.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\fpositer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\unicode\fpositer.h"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="copy "$(InputPath)" ..\..\include\unicode
"
|
||||
Outputs="..\..\include\unicode\$(InputFileName)"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="copy "$(InputPath)" ..\..\include\unicode
"
|
||||
Outputs="..\..\include\unicode\$(InputFileName)"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="copy "$(InputPath)" ..\..\include\unicode
"
|
||||
Outputs="..\..\include\unicode\$(InputFileName)"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="copy "$(InputPath)" ..\..\include\unicode
"
|
||||
Outputs="..\..\include\unicode\$(InputFileName)"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\decimfmt.cpp"
|
||||
>
|
||||
|
|
|
@ -273,10 +273,105 @@ NumberFormat::operator==(const Format& that) const
|
|||
u_strcmp(fCurrency, other->fCurrency) == 0)));
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Default implementation sets unsupported error; subclasses should
|
||||
// override.
|
||||
|
||||
UnicodeString&
|
||||
NumberFormat::format(double /* unused number */,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPositionIterator& /* unused posIter */,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
if (!U_FAILURE(status)) {
|
||||
status = U_UNSUPPORTED_ERROR;
|
||||
}
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Default implementation sets unsupported error; subclasses should
|
||||
// override.
|
||||
|
||||
UnicodeString&
|
||||
NumberFormat::format(int32_t /* unused number */,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPositionIterator& /* unused posIter */,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
if (!U_FAILURE(status)) {
|
||||
status = U_UNSUPPORTED_ERROR;
|
||||
}
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Default implementation sets unsupported error; subclasses should
|
||||
// override.
|
||||
|
||||
UnicodeString&
|
||||
NumberFormat::format(int64_t /* unused number */,
|
||||
UnicodeString& toAppendTo,
|
||||
FieldPositionIterator& /* unused posIter */,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
if (!U_FAILURE(status)) {
|
||||
status = U_UNSUPPORTED_ERROR;
|
||||
}
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
// -------------------------------------x
|
||||
// Formats the number object and save the format
|
||||
// result in the toAppendTo string buffer.
|
||||
|
||||
// utility to save/restore state, used in two overloads
|
||||
// of format(const Formattable&...) below.
|
||||
|
||||
class ArgExtractor {
|
||||
NumberFormat *ncnf;
|
||||
const Formattable* num;
|
||||
UBool setCurr;
|
||||
UChar save[4];
|
||||
|
||||
public:
|
||||
ArgExtractor(const NumberFormat& nf, const Formattable& obj, UErrorCode& status);
|
||||
~ArgExtractor();
|
||||
|
||||
const Formattable* number(void) const;
|
||||
};
|
||||
|
||||
inline const Formattable*
|
||||
ArgExtractor::number(void) const {
|
||||
return num;
|
||||
}
|
||||
|
||||
ArgExtractor::ArgExtractor(const NumberFormat& nf, const Formattable& obj, UErrorCode& status)
|
||||
: ncnf((NumberFormat*) &nf), num(&obj), setCurr(FALSE) {
|
||||
|
||||
const UObject* o = obj.getObject(); // most commonly o==NULL
|
||||
if (o != NULL &&
|
||||
o->getDynamicClassID() == CurrencyAmount::getStaticClassID()) {
|
||||
// getISOCurrency() returns a pointer to internal storage, so we
|
||||
// copy it to retain it across the call to setCurrency().
|
||||
const CurrencyAmount* amt = (const CurrencyAmount*) o;
|
||||
const UChar* curr = amt->getISOCurrency();
|
||||
u_strcpy(save, nf.getCurrency());
|
||||
setCurr = (u_strcmp(curr, save) != 0);
|
||||
if (setCurr) {
|
||||
ncnf->setCurrency(curr, status);
|
||||
}
|
||||
num = &amt->getNumber();
|
||||
}
|
||||
}
|
||||
|
||||
ArgExtractor::~ArgExtractor() {
|
||||
if (setCurr) {
|
||||
UErrorCode ok = U_ZERO_ERROR;
|
||||
ncnf->setCurrency(save, ok); // always restore currency
|
||||
}
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
NumberFormat::format(const Formattable& obj,
|
||||
UnicodeString& appendTo,
|
||||
|
@ -285,25 +380,8 @@ NumberFormat::format(const Formattable& obj,
|
|||
{
|
||||
if (U_FAILURE(status)) return appendTo;
|
||||
|
||||
NumberFormat* nonconst = (NumberFormat*) this;
|
||||
const Formattable* n = &obj;
|
||||
|
||||
UChar save[4];
|
||||
UBool setCurr = FALSE;
|
||||
const UObject* o = obj.getObject(); // most commonly o==NULL
|
||||
if (o != NULL &&
|
||||
o->getDynamicClassID() == CurrencyAmount::getStaticClassID()) {
|
||||
// getISOCurrency() returns a pointer to internal storage, so we
|
||||
// copy it to retain it across the call to setCurrency().
|
||||
const CurrencyAmount* amt = (const CurrencyAmount*) o;
|
||||
const UChar* curr = amt->getISOCurrency();
|
||||
u_strcpy(save, getCurrency());
|
||||
setCurr = (u_strcmp(curr, save) != 0);
|
||||
if (setCurr) {
|
||||
nonconst->setCurrency(curr, status);
|
||||
}
|
||||
n = &amt->getNumber();
|
||||
}
|
||||
ArgExtractor arg(*this, obj, status);
|
||||
const Formattable *n = arg.number();
|
||||
|
||||
switch (n->getType()) {
|
||||
case Formattable::kDouble:
|
||||
|
@ -320,10 +398,39 @@ NumberFormat::format(const Formattable& obj,
|
|||
break;
|
||||
}
|
||||
|
||||
if (setCurr) {
|
||||
UErrorCode ok = U_ZERO_ERROR;
|
||||
nonconst->setCurrency(save, ok); // always restore currency
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
// -------------------------------------x
|
||||
// Formats the number object and save the format
|
||||
// result in the toAppendTo string buffer.
|
||||
|
||||
UnicodeString&
|
||||
NumberFormat::format(const Formattable& obj,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
if (U_FAILURE(status)) return appendTo;
|
||||
|
||||
ArgExtractor arg(*this, obj, status);
|
||||
const Formattable *n = arg.number();
|
||||
|
||||
switch (n->getType()) {
|
||||
case Formattable::kDouble:
|
||||
format(n->getDouble(), appendTo, posIter, status);
|
||||
break;
|
||||
case Formattable::kLong:
|
||||
format(n->getLong(), appendTo, posIter, status);
|
||||
break;
|
||||
case Formattable::kInt64:
|
||||
format(n->getInt64(), appendTo, posIter, status);
|
||||
break;
|
||||
default:
|
||||
status = U_INVALID_FORMAT_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,8 @@
|
|||
#include "unicode/vtzone.h"
|
||||
#include "olsontz.h"
|
||||
#include "util.h"
|
||||
#include "gregoimp.h"
|
||||
#include "fphdlimp.h"
|
||||
#include "gregoimp.h"
|
||||
#include "hebrwcal.h"
|
||||
#include "cstring.h"
|
||||
#include "uassert.h"
|
||||
|
@ -741,10 +742,27 @@ void SimpleDateFormat::parseAmbiguousDatesAsAfter(UDate startDate, UErrorCode& s
|
|||
UnicodeString&
|
||||
SimpleDateFormat::format(Calendar& cal, UnicodeString& appendTo, FieldPosition& pos) const
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
pos.setBeginIndex(0);
|
||||
pos.setEndIndex(0);
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
FieldPositionOnlyHandler handler(pos);
|
||||
return _format(cal, appendTo, handler, status);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
UnicodeString&
|
||||
SimpleDateFormat::format(Calendar& cal, UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter, UErrorCode& status) const
|
||||
{
|
||||
FieldPositionIteratorHandler handler(posIter, status);
|
||||
return _format(cal, appendTo, handler, status);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
UnicodeString&
|
||||
SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo, FieldPositionHandler& handler,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
Calendar *workCal = &cal;
|
||||
TimeZone *backupTZ = NULL;
|
||||
if (&cal != fCalendar && uprv_strcmp(cal.getType(), fCalendar->getType()) != 0) {
|
||||
|
@ -769,7 +787,7 @@ SimpleDateFormat::format(Calendar& cal, UnicodeString& appendTo, FieldPosition&
|
|||
// Use subFormat() to format a repeated pattern character
|
||||
// when a different pattern or non-pattern character is seen
|
||||
if (ch != prevCh && count > 0) {
|
||||
subFormat(appendTo, prevCh, count, pos, *workCal, status);
|
||||
subFormat(appendTo, prevCh, count, handler, *workCal, status);
|
||||
count = 0;
|
||||
}
|
||||
if (ch == QUOTE) {
|
||||
|
@ -797,7 +815,7 @@ SimpleDateFormat::format(Calendar& cal, UnicodeString& appendTo, FieldPosition&
|
|||
|
||||
// Format the last item in the pattern, if any
|
||||
if (count > 0) {
|
||||
subFormat(appendTo, prevCh, count, pos, *workCal, status);
|
||||
subFormat(appendTo, prevCh, count, handler, *workCal, status);
|
||||
}
|
||||
|
||||
if (backupTZ != NULL) {
|
||||
|
@ -805,30 +823,9 @@ SimpleDateFormat::format(Calendar& cal, UnicodeString& appendTo, FieldPosition&
|
|||
fCalendar->adoptTimeZone(backupTZ);
|
||||
}
|
||||
|
||||
// and if something failed (e.g., an invalid format character), reset our FieldPosition
|
||||
// to (0, 0) to show that
|
||||
// {sfb} look at this later- are these being set correctly?
|
||||
if (U_FAILURE(status)) {
|
||||
pos.setBeginIndex(0);
|
||||
pos.setEndIndex(0);
|
||||
}
|
||||
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
SimpleDateFormat::format(const Formattable& obj,
|
||||
UnicodeString& appendTo,
|
||||
FieldPosition& pos,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
// this is just here to get around the hiding problem
|
||||
// (the previous format() override would hide the version of
|
||||
// format() on DateFormat that this function correspond to, so we
|
||||
// have to redefine it here)
|
||||
return DateFormat::format(obj, appendTo, pos, status);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/* Map calendar field into calendar field level.
|
||||
|
@ -1435,7 +1432,7 @@ void
|
|||
SimpleDateFormat::subFormat(UnicodeString &appendTo,
|
||||
UChar ch,
|
||||
int32_t count,
|
||||
FieldPosition& pos,
|
||||
FieldPositionHandler& handler,
|
||||
Calendar& cal,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
|
@ -1493,9 +1490,9 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
|
|||
case UDAT_YEAR_FIELD:
|
||||
case UDAT_YEAR_WOY_FIELD:
|
||||
if(count == 2)
|
||||
zeroPaddingNumber(currentNumberFormat,appendTo, value, 2, 2);
|
||||
zeroPaddingNumber(currentNumberFormat, appendTo, value, 2, 2);
|
||||
else
|
||||
zeroPaddingNumber(currentNumberFormat,appendTo, value, count, maxIntCount);
|
||||
zeroPaddingNumber(currentNumberFormat, appendTo, value, count, maxIntCount);
|
||||
break;
|
||||
|
||||
// for "MMMM", write out the whole month name, for "MMM", write out the month
|
||||
|
@ -1727,14 +1724,9 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo,
|
|||
break;
|
||||
}
|
||||
|
||||
// if the field we're formatting is the one the FieldPosition says it's interested
|
||||
// in, fill in the FieldPosition with this field's positions
|
||||
if (pos.getBeginIndex() == pos.getEndIndex() &&
|
||||
pos.getField() == fgPatternIndexToDateFormatField[patternCharIndex]) {
|
||||
pos.setBeginIndex(beginOffset);
|
||||
pos.setEndIndex(appendTo.length());
|
||||
}
|
||||
handler.addAttribute(fgPatternIndexToDateFormatField[patternCharIndex], beginOffset, appendTo.length());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
NumberFormat *
|
||||
|
@ -1748,7 +1740,8 @@ SimpleDateFormat::getNumberFormat(UDateFormatField index) const {
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
void
|
||||
SimpleDateFormat::zeroPaddingNumber(NumberFormat *currentNumberFormat,UnicodeString &appendTo, int32_t value, int32_t minDigits, int32_t maxDigits) const
|
||||
SimpleDateFormat::zeroPaddingNumber(NumberFormat *currentNumberFormat,UnicodeString &appendTo,
|
||||
int32_t value, int32_t minDigits, int32_t maxDigits) const
|
||||
{
|
||||
if (currentNumberFormat!=NULL) {
|
||||
FieldPosition pos(0);
|
||||
|
|
|
@ -38,6 +38,50 @@ static void verifyIsSimpleDateFormat(const UDateFormat* fmt, UErrorCode *status)
|
|||
}
|
||||
}
|
||||
|
||||
// This mirrors the correspondence between the
|
||||
// SimpleDateFormat::fgPatternIndexToDateFormatField and
|
||||
// SimpleDateFormat::fgPatternIndexToCalendarField arrays.
|
||||
static UCalendarDateFields gDateFieldMapping[] = {
|
||||
UCAL_ERA, // UDAT_ERA_FIELD = 0
|
||||
UCAL_YEAR, // UDAT_YEAR_FIELD = 1
|
||||
UCAL_MONTH, // UDAT_MONTH_FIELD = 2
|
||||
UCAL_DATE, // UDAT_DATE_FIELD = 3
|
||||
UCAL_HOUR_OF_DAY, // UDAT_HOUR_OF_DAY1_FIELD = 4
|
||||
UCAL_HOUR_OF_DAY, // UDAT_HOUR_OF_DAY0_FIELD = 5
|
||||
UCAL_MINUTE, // UDAT_MINUTE_FIELD = 6
|
||||
UCAL_SECOND, // UDAT_SECOND_FIELD = 7
|
||||
UCAL_MILLISECOND, // UDAT_FRACTIONAL_SECOND_FIELD = 8
|
||||
UCAL_DAY_OF_WEEK, // UDAT_DAY_OF_WEEK_FIELD = 9
|
||||
UCAL_DAY_OF_YEAR, // UDAT_DAY_OF_YEAR_FIELD = 10
|
||||
UCAL_DAY_OF_WEEK_IN_MONTH, // UDAT_DAY_OF_WEEK_IN_MONTH_FIELD = 11
|
||||
UCAL_WEEK_OF_YEAR, // UDAT_WEEK_OF_YEAR_FIELD = 12
|
||||
UCAL_WEEK_OF_MONTH, // UDAT_WEEK_OF_MONTH_FIELD = 13
|
||||
UCAL_AM_PM, // UDAT_AM_PM_FIELD = 14
|
||||
UCAL_HOUR, // UDAT_HOUR1_FIELD = 15
|
||||
UCAL_HOUR, // UDAT_HOUR0_FIELD = 16
|
||||
UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_FIELD = 17
|
||||
UCAL_YEAR_WOY, // UDAT_YEAR_WOY_FIELD = 18
|
||||
UCAL_DOW_LOCAL, // UDAT_DOW_LOCAL_FIELD = 19
|
||||
UCAL_EXTENDED_YEAR, // UDAT_EXTENDED_YEAR_FIELD = 20
|
||||
UCAL_JULIAN_DAY, // UDAT_JULIAN_DAY_FIELD = 21
|
||||
UCAL_MILLISECONDS_IN_DAY, // UDAT_MILLISECONDS_IN_DAY_FIELD = 22
|
||||
UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_RFC_FIELD = 23
|
||||
// UCAL_DST_OFFSET also
|
||||
UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_GENERIC_FIELD = 24
|
||||
UCAL_DOW_LOCAL, // UDAT_STANDALONE_DAY_FIELD = 25
|
||||
UCAL_MONTH, // UDAT_STANDALONE_MONTH_FIELD = 26
|
||||
UCAL_MONTH, // UDAT_QUARTER_FIELD = 27
|
||||
UCAL_MONTH, // UDAT_STANDALONE_QUARTER_FIELD = 28
|
||||
UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_SPECIAL_FIELD = 29
|
||||
UCAL_FIELD_COUNT, // UDAT_FIELD_COUNT = 30
|
||||
// UCAL_IS_LEAP_MONTH is not the target of a mapping
|
||||
};
|
||||
|
||||
U_CAPI UCalendarDateFields U_EXPORT2
|
||||
udat_toCalendarDateField(UDateFormatField field) {
|
||||
return gDateFieldMapping[field];
|
||||
}
|
||||
|
||||
U_CAPI UDateFormat* U_EXPORT2
|
||||
udat_open(UDateFormatStyle timeStyle,
|
||||
UDateFormatStyle dateStyle,
|
||||
|
|
|
@ -230,6 +230,25 @@ public:
|
|||
FieldPosition& pos,
|
||||
UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Format an object to produce a string. This method handles Formattable
|
||||
* objects with a UDate type. If a the Formattable object type is not a Date,
|
||||
* then it returns a failing UErrorCode.
|
||||
*
|
||||
* @param obj The object to format. Must be a Date.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call. Field values
|
||||
* are defined in UDateFormatField.
|
||||
* @param status Output param filled with success/failure status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
virtual UnicodeString& format(const Formattable& obj,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const;
|
||||
/**
|
||||
* Formats a date into a date/time string. This is an abstract method which
|
||||
* concrete subclasses must implement.
|
||||
|
@ -267,6 +286,28 @@ public:
|
|||
UnicodeString& appendTo,
|
||||
FieldPosition& fieldPosition) const = 0;
|
||||
|
||||
/**
|
||||
* Formats a date into a date/time string. Subclasses should implement this method.
|
||||
*
|
||||
* @param cal Calendar set to the date and time to be formatted
|
||||
* into a date/time string. When the calendar type is
|
||||
* different from the internal calendar held by this
|
||||
* DateFormat instance, the date and the time zone will
|
||||
* be inherited from the input calendar, but other calendar
|
||||
* field values will be calculated by the internal calendar.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call. Field values
|
||||
* are defined in UDateFormatField.
|
||||
* @param status error status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
virtual UnicodeString& format(Calendar& cal,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const;
|
||||
/**
|
||||
* Formats a UDate into a date/time string.
|
||||
* <P>
|
||||
|
@ -298,6 +339,23 @@ public:
|
|||
UnicodeString& appendTo,
|
||||
FieldPosition& fieldPosition) const;
|
||||
|
||||
/**
|
||||
* Formats a UDate into a date/time string.
|
||||
*
|
||||
* @param date UDate to be formatted into a date/time string.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call. Field values
|
||||
* are defined in UDateFormatField.
|
||||
* @param status error status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
UnicodeString& format(UDate date,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const;
|
||||
/**
|
||||
* Formats a UDate into a date/time string. If there is a problem, you won't
|
||||
* know, using this method. Use the overloaded format() method which takes a
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "unicode/dcfmtsym.h"
|
||||
#include "unicode/numfmt.h"
|
||||
#include "unicode/locid.h"
|
||||
#include "unicode/fpositer.h"
|
||||
|
||||
union UHashTok;
|
||||
|
||||
|
@ -58,6 +59,7 @@ class DigitList;
|
|||
class ChoiceFormat;
|
||||
class CurrencyPluralInfo;
|
||||
class Hashtable;
|
||||
class FieldPositionHandler;
|
||||
|
||||
/**
|
||||
* DecimalFormat is a concrete subclass of NumberFormat that formats decimal
|
||||
|
@ -848,6 +850,24 @@ public:
|
|||
virtual UnicodeString& format(double number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPosition& pos) const;
|
||||
|
||||
/**
|
||||
* Format a double or long number using base-10 representation.
|
||||
*
|
||||
* @param number The value to be formatted.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call.
|
||||
* @param status Output param filled with success/failure status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @draft 4.4
|
||||
*/
|
||||
virtual UnicodeString& format(double number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Format a long number using base-10 representation.
|
||||
*
|
||||
|
@ -862,6 +882,24 @@ public:
|
|||
virtual UnicodeString& format(int32_t number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPosition& pos) const;
|
||||
|
||||
/**
|
||||
* Format a long number using base-10 representation.
|
||||
*
|
||||
* @param number The value to be formatted.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call.
|
||||
* @param status Output param filled with success/failure status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @draft 4.4
|
||||
*/
|
||||
virtual UnicodeString& format(int32_t number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Format an int64 number using base-10 representation.
|
||||
*
|
||||
|
@ -877,6 +915,23 @@ public:
|
|||
UnicodeString& appendTo,
|
||||
FieldPosition& pos) const;
|
||||
|
||||
/**
|
||||
* Format an int64 number using base-10 representation.
|
||||
*
|
||||
* @param number The value to be formatted.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call.
|
||||
* @param status Output param filled with success/failure status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @draft 4.4
|
||||
*/
|
||||
virtual UnicodeString& format(int64_t number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Format a Formattable using base-10 representation.
|
||||
*
|
||||
|
@ -1804,16 +1859,15 @@ private:
|
|||
*
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param fieldPosition On input: an alignment field, if desired.
|
||||
* On output: the offsets of the alignment field.
|
||||
* @param handler Records information about field positions.
|
||||
* @param digits the digits to be formatted.
|
||||
* @param isInteger if TRUE format the digits as Integer.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
*/
|
||||
UnicodeString& subformat(UnicodeString& appendTo,
|
||||
FieldPosition& fieldPosition,
|
||||
DigitList& digits,
|
||||
UBool isInteger) const;
|
||||
FieldPositionHandler& handler,
|
||||
DigitList& digits,
|
||||
UBool isInteger) const;
|
||||
|
||||
|
||||
void parse(const UnicodeString& text,
|
||||
|
@ -1884,8 +1938,11 @@ private:
|
|||
*/
|
||||
inline const UnicodeString &getConstSymbol(DecimalFormatSymbols::ENumberFormatSymbol symbol) const;
|
||||
|
||||
int32_t appendAffix(UnicodeString& buf, double number,
|
||||
UBool isNegative, UBool isPrefix) const;
|
||||
int32_t appendAffix(UnicodeString& buf,
|
||||
double number,
|
||||
FieldPositionHandler& handler,
|
||||
UBool isNegative,
|
||||
UBool isPrefix) const;
|
||||
|
||||
/**
|
||||
* Append an affix to the given UnicodeString, using quotes if
|
||||
|
@ -1902,6 +1959,7 @@ private:
|
|||
void expandAffix(const UnicodeString& pattern,
|
||||
UnicodeString& affix,
|
||||
double number,
|
||||
FieldPositionHandler& handler,
|
||||
UBool doFormat,
|
||||
const UnicodeString* pluralCount) const;
|
||||
|
||||
|
@ -1910,7 +1968,7 @@ private:
|
|||
static double round(double a, ERoundingMode mode, UBool isNegative);
|
||||
|
||||
void addPadding(UnicodeString& appendTo,
|
||||
FieldPosition& fieldPosition,
|
||||
FieldPositionHandler& handler,
|
||||
int32_t prefixLen, int32_t suffixLen) const;
|
||||
|
||||
UBool isGroupingPosition(int32_t pos) const;
|
||||
|
@ -1950,6 +2008,13 @@ private:
|
|||
void copyHashForAffix(const Hashtable* source,
|
||||
Hashtable* target, UErrorCode& status);
|
||||
|
||||
UnicodeString& _format(int64_t number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionHandler& handler) const;
|
||||
UnicodeString& _format(double number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionHandler& handler) const;
|
||||
|
||||
// currency sign count
|
||||
enum {
|
||||
fgCurrencySignCountZero,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
********************************************************************************
|
||||
* Copyright (C) 1997-2006, International Business Machines Corporation and others.
|
||||
* Copyright (C) 1997-2009, International Business Machines Corporation and others.
|
||||
* All Rights Reserved.
|
||||
********************************************************************************
|
||||
*
|
||||
|
@ -34,6 +34,7 @@
|
|||
#include "unicode/unistr.h"
|
||||
#include "unicode/fmtable.h"
|
||||
#include "unicode/fieldpos.h"
|
||||
#include "unicode/fpositer.h"
|
||||
#include "unicode/parsepos.h"
|
||||
#include "unicode/parseerr.h"
|
||||
#include "unicode/locid.h"
|
||||
|
@ -159,6 +160,26 @@ public:
|
|||
UnicodeString& appendTo,
|
||||
FieldPosition& pos,
|
||||
UErrorCode& status) const = 0;
|
||||
/**
|
||||
* Format an object to produce a string. Subclasses should override this
|
||||
* method. This method allows polymorphic formatting of Formattable objects.
|
||||
* If a subclass of Format receives a Formattable object type it doesn't
|
||||
* handle (e.g., if a numeric Formattable is passed to a DateFormat object)
|
||||
* then it returns a failing UErrorCode.
|
||||
*
|
||||
* @param obj The object to format.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call.
|
||||
* @param status Output param filled with success/failure status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @stable draft 4.4
|
||||
*/
|
||||
virtual UnicodeString& format(const Formattable& obj,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Parse a string to produce an object. This is a pure virtual
|
||||
|
|
142
icu4c/source/i18n/unicode/fpositer.h
Normal file
142
icu4c/source/i18n/unicode/fpositer.h
Normal file
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
********************************************************************************
|
||||
* Copyright (C) 2009, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
********************************************************************************
|
||||
*
|
||||
* File attiter.h
|
||||
*
|
||||
* Modification History:
|
||||
*
|
||||
* Date Name Description
|
||||
* 12/15/2009 dougfelt Created
|
||||
********************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef FPOSITER_H
|
||||
#define FPOSITER_H
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/uobject.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \brief C++ API: FieldPosition Iterator.
|
||||
*/
|
||||
|
||||
#if UCONFIG_NO_FORMATTING
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
/*
|
||||
* Allow the declaration of APIs with pointers to FieldPositionIterator
|
||||
* even when formatting is removed from the build.
|
||||
*/
|
||||
class FieldPositionIterator;
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#else
|
||||
|
||||
#include "unicode/fieldpos.h"
|
||||
#include "unicode/umisc.h"
|
||||
#include "uvectr32.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* FieldPositionIterator returns the field ids and their start/limit positions generated
|
||||
* by a call to Format::format. See Format, NumberFormat, DecimalFormat.
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
class U_I18N_API FieldPositionIterator : public UObject {
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
~FieldPositionIterator();
|
||||
|
||||
/**
|
||||
* Constructs a new, empty iterator.
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
FieldPositionIterator(void);
|
||||
|
||||
/**
|
||||
* Copy constructor. If the copy failed for some reason, the new iterator will
|
||||
* be empty.
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
FieldPositionIterator(const FieldPositionIterator&);
|
||||
|
||||
/**
|
||||
* Return true if another object is semantically equal to this
|
||||
* one.
|
||||
* <p>
|
||||
* Return true if this FieldPositionIterator is at the same position in an
|
||||
* equal array of run values.
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
UBool operator==(const FieldPositionIterator&) const;
|
||||
|
||||
/**
|
||||
* Returns the complement of the result of operator==
|
||||
* @param rhs The FieldPositionIterator to be compared for inequality
|
||||
* @return the complement of the result of operator==
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
UBool operator!=(const FieldPositionIterator& rhs) const { return !operator==(rhs); }
|
||||
|
||||
/**
|
||||
* If the current position is valid, updates the FieldPosition values, advances the iterator,
|
||||
* and returns TRUE, otherwise returns FALSE.
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
UBool next(FieldPosition& fp);
|
||||
|
||||
/**
|
||||
* ICU "poor man's RTTI", returns a UClassID for this class.
|
||||
*/
|
||||
static UClassID U_EXPORT2 getStaticClassID();
|
||||
|
||||
/**
|
||||
* ICU "poor man's RTTI", returns a UClassID for the actual class.
|
||||
*/
|
||||
virtual UClassID getDynamicClassID() const;
|
||||
|
||||
private:
|
||||
friend class FieldPositionIteratorHandler;
|
||||
|
||||
/**
|
||||
* Sets the data used by the iterator, and resets the position.
|
||||
* Returns U_ILLEGAL_ARGUMENT_ERROR in status if the data is not valid
|
||||
* (length is not a multiple of 3, or start >= limit for any run).
|
||||
*/
|
||||
void setData(UVector32 *adopt, UErrorCode& status);
|
||||
|
||||
UVector32 *data;
|
||||
int32_t pos;
|
||||
};
|
||||
|
||||
inline UBool FieldPositionIterator::next(FieldPosition& fp) {
|
||||
if (pos == -1) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fp.setField(data->elementAti(pos++));
|
||||
fp.setBeginIndex(data->elementAti(pos++));
|
||||
fp.setEndIndex(data->elementAti(pos++));
|
||||
|
||||
if (pos == data->size()) {
|
||||
pos = -1;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
||||
#endif // FPOSITER_H
|
|
@ -190,13 +190,25 @@ public:
|
|||
* Signifies that the position of the integer part or fraction part of
|
||||
* a formatted number should be returned.
|
||||
*
|
||||
* Note: as of ICU 4.4, the values in this enum have been extended to
|
||||
* support identification of all number format fields, not just those
|
||||
* pertaining to alignment.
|
||||
*
|
||||
* @see FieldPosition
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
enum EAlignmentFields {
|
||||
kIntegerField,
|
||||
kFractionField,
|
||||
|
||||
kDecimalSeparatorField,
|
||||
kExponentSymbolField,
|
||||
kExponentSignField,
|
||||
kExponentField,
|
||||
kGroupingSeparatorField,
|
||||
kCurrencyField,
|
||||
kPercentField,
|
||||
kPermillField,
|
||||
kSignField,
|
||||
|
||||
/**
|
||||
* These constants are provided for backwards compatibility only.
|
||||
|
@ -241,6 +253,26 @@ public:
|
|||
FieldPosition& pos,
|
||||
UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Format an object to produce a string. This method handles
|
||||
* Formattable objects with numeric types. If the Formattable
|
||||
* object type is not a numeric type, then it returns a failing
|
||||
* UErrorCode.
|
||||
*
|
||||
* @param obj The object to format.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call.
|
||||
* @param status Output param filled with success/failure status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @draft 4.4
|
||||
*/
|
||||
virtual UnicodeString& format(const Formattable& obj,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Parse a string to produce an object. This methods handles
|
||||
* parsing of numeric strings into Formattable objects with numeric
|
||||
|
@ -327,6 +359,23 @@ public:
|
|||
virtual UnicodeString& format(double number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPosition& pos) const = 0;
|
||||
/**
|
||||
* Format a double number. Subclasses must implement
|
||||
* this method.
|
||||
*
|
||||
* @param number The value to be formatted.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call.
|
||||
* @param status Output param filled with success/failure status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @draft 4.4
|
||||
*/
|
||||
virtual UnicodeString& format(double number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const;
|
||||
/**
|
||||
* Format a long number. Concrete subclasses must implement
|
||||
* these pure virtual methods.
|
||||
|
@ -343,6 +392,23 @@ public:
|
|||
UnicodeString& appendTo,
|
||||
FieldPosition& pos) const = 0;
|
||||
|
||||
/**
|
||||
* Format an int32 number. Subclasses must implement
|
||||
* this method.
|
||||
*
|
||||
* @param number The value to be formatted.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call.
|
||||
* @param status Output param filled with success/failure status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @draft 4.4
|
||||
*/
|
||||
virtual UnicodeString& format(int32_t number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const;
|
||||
/**
|
||||
* Format an int64 number. (Not abstract to retain compatibility
|
||||
* with earlier releases, however subclasses should override this
|
||||
|
@ -359,6 +425,23 @@ public:
|
|||
virtual UnicodeString& format(int64_t number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPosition& pos) const;
|
||||
/**
|
||||
* Format an int64 number. Subclasses must implement
|
||||
* this method.
|
||||
*
|
||||
* @param number The value to be formatted.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call.
|
||||
* @param status Output param filled with success/failure status.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @draft 4.4
|
||||
*/
|
||||
virtual UnicodeString& format(int64_t number,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const;
|
||||
/**
|
||||
* Redeclared Format method.
|
||||
* @param obj The object to be formatted.
|
||||
|
|
|
@ -39,6 +39,7 @@ U_NAMESPACE_BEGIN
|
|||
class DateFormatSymbols;
|
||||
class DateFormat;
|
||||
class MessageFormat;
|
||||
class FieldPositionHandler;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -385,6 +386,29 @@ public:
|
|||
UnicodeString& appendTo,
|
||||
FieldPosition& pos) const;
|
||||
|
||||
/**
|
||||
* Format a date or time, which is the standard millis since 24:00 GMT, Jan
|
||||
* 1, 1970. Overrides DateFormat pure virtual method.
|
||||
* <P>
|
||||
* Example: using the US locale: "yyyy.MM.dd e 'at' HH:mm:ss zzz" ->>
|
||||
* 1996.07.10 AD at 15:08:56 PDT
|
||||
*
|
||||
* @param cal Calendar set to the date and time to be formatted
|
||||
* into a date/time string.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call. Field values
|
||||
* are defined in UDateFormatField.
|
||||
* @param status Input/output param set to success/failure code.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
virtual UnicodeString& format( Calendar& cal,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Format a date or time, which is the standard millis since 24:00 GMT, Jan
|
||||
* 1, 1970. Overrides DateFormat pure virtual method.
|
||||
|
@ -400,7 +424,7 @@ public:
|
|||
* Result is appended to existing contents.
|
||||
* @param pos The formatting position. On input: an alignment field,
|
||||
* if desired. On output: the offsets of the alignment field.
|
||||
* @param status Output param set to success/faulure code.
|
||||
* @param status Input/output param set to success/failure code.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
|
@ -409,6 +433,31 @@ public:
|
|||
FieldPosition& pos,
|
||||
UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Format a date or time, which is the standard millis since 24:00 GMT, Jan
|
||||
* 1, 1970. Overrides DateFormat pure virtual method.
|
||||
* <P>
|
||||
* Example: using the US locale: "yyyy.MM.dd e 'at' HH:mm:ss zzz" ->>
|
||||
* 1996.07.10 AD at 15:08:56 PDT
|
||||
*
|
||||
* @param obj A Formattable containing the date-time value to be formatted
|
||||
* into a date-time string. If the type of the Formattable
|
||||
* is a numeric type, it is treated as if it were an
|
||||
* instance of Date.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call. Field values
|
||||
* are defined in UDateFormatField.
|
||||
* @param status Input/output param set to success/failure code.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
virtual UnicodeString& format( const Formattable& obj,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Redeclared DateFormat method.
|
||||
* @param date the Date value to be formatted.
|
||||
|
@ -423,6 +472,23 @@ public:
|
|||
UnicodeString& appendTo,
|
||||
FieldPosition& fieldPosition) const;
|
||||
|
||||
/**
|
||||
* Redeclared DateFormat method.
|
||||
* @param date the Date value to be formatted.
|
||||
* @param appendTo Output parameter to receive result.
|
||||
* Result is appended to existing contents.
|
||||
* @param posIter On return, can be used to iterate over positions
|
||||
* of fields generated by this format call. Field values
|
||||
* are defined in UDateFormatField.
|
||||
* @param status Input/output param set to success/failure code.
|
||||
* @return Reference to 'appendTo' parameter.
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
UnicodeString& format(UDate date,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Redeclared DateFormat method.
|
||||
* @param obj Object to be formatted.
|
||||
|
@ -724,6 +790,12 @@ private:
|
|||
*/
|
||||
SimpleDateFormat(const Locale& locale, UErrorCode& status); // Use default pattern
|
||||
|
||||
/**
|
||||
* Hook called by format(... FieldPosition& ...) and format(...FieldPositionIterator&...)
|
||||
*/
|
||||
UnicodeString& _format(Calendar& cal, UnicodeString& appendTo, FieldPositionHandler& handler,
|
||||
UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* Called by format() to format a single field.
|
||||
*
|
||||
|
@ -733,19 +805,16 @@ private:
|
|||
* @param count Number of characters in the current pattern symbol (e.g.,
|
||||
* "yyyy" in the pattern would result in a call to this function
|
||||
* with ch equal to 'y' and count equal to 4)
|
||||
* @param pos The FieldPosition being filled in by the format() call. If
|
||||
* this function is formatting the field specfied by pos, it
|
||||
* will fill in pos with the beginning and ending offsets of the
|
||||
* field.
|
||||
* @param handler Records information about field positions.
|
||||
* @param status Receives a status code, which will be U_ZERO_ERROR if the operation
|
||||
* succeeds.
|
||||
*/
|
||||
void subFormat( UnicodeString &appendTo,
|
||||
UChar ch,
|
||||
int32_t count,
|
||||
FieldPosition& pos,
|
||||
Calendar& cal,
|
||||
UErrorCode& status) const; // in case of illegal argument
|
||||
void subFormat(UnicodeString &appendTo,
|
||||
UChar ch,
|
||||
int32_t count,
|
||||
FieldPositionHandler& handler,
|
||||
Calendar& cal,
|
||||
UErrorCode& status) const; // in case of illegal argument
|
||||
|
||||
/**
|
||||
* Used by subFormat() to format a numeric value.
|
||||
|
@ -759,11 +828,11 @@ private:
|
|||
* @param minDigits Minimum number of digits the result should have
|
||||
* @param maxDigits Maximum number of digits the result should have
|
||||
*/
|
||||
void zeroPaddingNumber( NumberFormat *currentNumberFormat,
|
||||
UnicodeString &appendTo,
|
||||
int32_t value,
|
||||
int32_t minDigits,
|
||||
int32_t maxDigits) const;
|
||||
void zeroPaddingNumber(NumberFormat *currentNumberFormat,
|
||||
UnicodeString &appendTo,
|
||||
int32_t value,
|
||||
int32_t minDigits,
|
||||
int32_t maxDigits) const;
|
||||
|
||||
/**
|
||||
* Return true if the given format character, occuring count
|
||||
|
@ -1081,6 +1150,28 @@ SimpleDateFormat::format(const Formattable& obj,
|
|||
return DateFormat::format(obj, appendTo, status);
|
||||
}
|
||||
|
||||
inline UnicodeString&
|
||||
SimpleDateFormat::format(const Formattable& obj,
|
||||
UnicodeString& appendTo,
|
||||
FieldPosition& pos,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
// Don't use Format:: - use immediate base class only,
|
||||
// in case immediate base modifies behavior later.
|
||||
return DateFormat::format(obj, appendTo, pos, status);
|
||||
}
|
||||
|
||||
inline UnicodeString&
|
||||
SimpleDateFormat::format(const Formattable& obj,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
// Don't use Format:: - use immediate base class only,
|
||||
// in case immediate base modifies behavior later.
|
||||
return DateFormat::format(obj, appendTo, posIter, status);
|
||||
}
|
||||
|
||||
inline UnicodeString&
|
||||
SimpleDateFormat::format(UDate date,
|
||||
UnicodeString& appendTo,
|
||||
|
@ -1090,6 +1181,16 @@ SimpleDateFormat::format(UDate date,
|
|||
return DateFormat::format(date, appendTo, fieldPosition);
|
||||
}
|
||||
|
||||
inline UnicodeString&
|
||||
SimpleDateFormat::format(UDate date,
|
||||
UnicodeString& appendTo,
|
||||
FieldPositionIterator& posIter,
|
||||
UErrorCode& status) const {
|
||||
// Don't use Format:: - use immediate base class only,
|
||||
// in case immediate base modifies behavior later.
|
||||
return DateFormat::format(date, appendTo, posIter, status);
|
||||
}
|
||||
|
||||
inline UnicodeString&
|
||||
SimpleDateFormat::format(UDate date, UnicodeString& appendTo) const {
|
||||
return DateFormat::format(date, appendTo);
|
||||
|
|
|
@ -444,15 +444,15 @@ typedef enum UDateFormatField {
|
|||
UDAT_TIMEZONE_GENERIC_FIELD = 24,
|
||||
/**
|
||||
* FieldPosition selector for 'c' field alignment,
|
||||
* corresponding to the {@link #UCAL_DATE} field.
|
||||
* corresponding to the {@link #UCAL_DOW_LOCAL} field.
|
||||
* This displays the stand alone day name, if available.
|
||||
* @stable ICU 3.4
|
||||
*/
|
||||
UDAT_STANDALONE_DAY_FIELD = 25,
|
||||
|
||||
|
||||
/**
|
||||
* FieldPosition selector for 'L' field alignment,
|
||||
* corresponding to the {@link #UCAL_MONTH} field.
|
||||
* corresponding to the {@link #UCAL_MONTH} field.
|
||||
* This displays the stand alone month name, if available.
|
||||
* @stable ICU 3.4
|
||||
*/
|
||||
|
@ -484,7 +484,7 @@ typedef enum UDateFormatField {
|
|||
UDAT_TIMEZONE_SPECIAL_FIELD = 29,
|
||||
|
||||
/**
|
||||
* Number of FieldPosition and UFieldPosition selectors for
|
||||
* Number of FieldPosition and UFieldPosition selectors for
|
||||
* DateFormat and UDateFormat.
|
||||
* Valid selectors range from 0 to UDAT_FIELD_COUNT-1.
|
||||
* This value is subject to change if new fields are defined
|
||||
|
@ -495,6 +495,19 @@ typedef enum UDateFormatField {
|
|||
|
||||
} UDateFormatField;
|
||||
|
||||
|
||||
/**
|
||||
* Maps from a UDateFormatField to the corresponding UCalendarDateFields.
|
||||
* Note: since the mapping is many-to-one, there is no inverse mapping.
|
||||
* @param field the UDateFormatField.
|
||||
* @return the UCalendarDateField. This will be UCAL_FIELD_COUNT in case
|
||||
* of error (e.g., the input field is UDAT_FIELD_COUNT).
|
||||
* @draft ICU 4.4
|
||||
*/
|
||||
U_DRAFT UCalendarDateFields U_EXPORT2
|
||||
udat_toCalendarDateField(UDateFormatField field);
|
||||
|
||||
|
||||
/**
|
||||
* Open a new UDateFormat for formatting and parsing dates and times.
|
||||
* A UDateFormat may be used to format dates in calls to {@link #udat_format },
|
||||
|
@ -977,6 +990,7 @@ udat_applyPatternRelative(UDateFormat *format,
|
|||
int32_t timePatternLength,
|
||||
UErrorCode *status);
|
||||
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -407,6 +407,7 @@ void DateFormatTest::TestFieldPosition() {
|
|||
}
|
||||
logln((UnicodeString)" Result = " + df->format(aug13, buf.remove()));
|
||||
|
||||
int32_t expBase = exp; // save for later
|
||||
for (i = 0; i < UDAT_FIELD_COUNT; ++i, ++exp) {
|
||||
FieldPosition pos(i);
|
||||
buf.remove();
|
||||
|
@ -416,6 +417,24 @@ void DateFormatTest::TestFieldPosition() {
|
|||
assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
|
||||
ctou(EXPECTED[exp]), field);
|
||||
}
|
||||
|
||||
// test FieldPositionIterator API
|
||||
logln("FieldPositionIterator");
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
FieldPositionIterator posIter;
|
||||
FieldPosition fp;
|
||||
|
||||
buf.remove();
|
||||
df->format(aug13, buf, posIter, status);
|
||||
while (posIter.next(fp)) {
|
||||
int32_t i = fp.getField();
|
||||
UnicodeString field;
|
||||
buf.extractBetween(fp.getBeginIndex(), fp.getEndIndex(), field);
|
||||
assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
|
||||
ctou(EXPECTED[expBase + i]), field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<COUNT; ++i) {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "caltztst.h"
|
||||
|
||||
/**
|
||||
* Performs many different tests for DataeFormat and SimpleDateFormat
|
||||
* Performs many different tests for DateFormat and SimpleDateFormat
|
||||
**/
|
||||
class DateFormatTest: public CalendarTimeZoneTest {
|
||||
// IntlTest override
|
||||
|
|
|
@ -109,6 +109,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n
|
|||
CASE(42,TestCurrencyIsoPluralFormat);
|
||||
CASE(43,TestCurrencyParsing);
|
||||
CASE(44,TestParseCurrencyInUCurr);
|
||||
CASE(45,TestFormatAttributes);
|
||||
default: name = ""; break;
|
||||
}
|
||||
}
|
||||
|
@ -5780,4 +5781,156 @@ NumberFormatTest::TestParseCurrencyInUCurr() {
|
|||
}
|
||||
}
|
||||
|
||||
const char* attrString(int32_t);
|
||||
|
||||
// UnicodeString s;
|
||||
// std::string ss;
|
||||
// std::cout << s.toUTF8String(ss)
|
||||
void NumberFormatTest::expectPositions(FieldPositionIterator& iter, int32_t *values, int32_t tupleCount,
|
||||
const UnicodeString& str) {
|
||||
UBool found[10];
|
||||
FieldPosition fp;
|
||||
|
||||
if (tupleCount > 10) {
|
||||
assertTrue("internal error, tupleCount too large", FALSE);
|
||||
} else {
|
||||
for (int i = 0; i < tupleCount; ++i) {
|
||||
found[i] = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
logln(str);
|
||||
while (iter.next(fp)) {
|
||||
UBool ok = FALSE;
|
||||
int32_t id = fp.getField();
|
||||
int32_t start = fp.getBeginIndex();
|
||||
int32_t limit = fp.getEndIndex();
|
||||
|
||||
// is there a logln using printf?
|
||||
char buf[128];
|
||||
sprintf(buf, "%24s %3d %3d %3d", attrString(id), id, start, limit);
|
||||
logln(buf);
|
||||
|
||||
for (int i = 0; i < tupleCount; ++i) {
|
||||
if (found[i]) {
|
||||
continue;
|
||||
}
|
||||
if (values[i*3] == id &&
|
||||
values[i*3+1] == start &&
|
||||
values[i*3+2] == limit) {
|
||||
found[i] = ok = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue((UnicodeString)"found [" + id + "," + start + "," + limit + "]", ok);
|
||||
}
|
||||
|
||||
// check that all were found
|
||||
UBool ok = TRUE;
|
||||
for (int i = 0; i < tupleCount; ++i) {
|
||||
if (!found[i]) {
|
||||
ok = FALSE;
|
||||
assertTrue((UnicodeString) "missing [" + values[i*3] + "," + values[i*3+1] + "," + values[i*3+2] + "]", found[i]);
|
||||
}
|
||||
}
|
||||
assertTrue("no expected values were missing", ok);
|
||||
}
|
||||
|
||||
void NumberFormatTest::expectPosition(FieldPosition& pos, int32_t id, int32_t start, int32_t limit,
|
||||
const UnicodeString& str) {
|
||||
logln(str);
|
||||
assertTrue((UnicodeString)"id " + id + " == " + pos.getField(), id == pos.getField());
|
||||
assertTrue((UnicodeString)"begin " + start + " == " + pos.getBeginIndex(), start == pos.getBeginIndex());
|
||||
assertTrue((UnicodeString)"end " + limit + " == " + pos.getEndIndex(), limit == pos.getEndIndex());
|
||||
}
|
||||
|
||||
void NumberFormatTest::TestFormatAttributes() {
|
||||
Locale locale("en_US");
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, NumberFormat::kCurrencyStyle, status);
|
||||
double val = 12345.67;
|
||||
|
||||
{
|
||||
int32_t expected[] = {
|
||||
NumberFormat::kCurrencyField, 0, 1,
|
||||
NumberFormat::kGroupingSeparatorField, 3, 4,
|
||||
NumberFormat::kIntegerField, 1, 7,
|
||||
NumberFormat::kDecimalSeparatorField, 7, 8,
|
||||
NumberFormat::kFractionField, 8, 10,
|
||||
};
|
||||
int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
|
||||
|
||||
FieldPositionIterator posIter;
|
||||
UnicodeString result;
|
||||
decFmt->format(val, result, posIter, status);
|
||||
expectPositions(posIter, expected, tupleCount, result);
|
||||
}
|
||||
{
|
||||
FieldPosition fp(NumberFormat::kIntegerField);
|
||||
UnicodeString result;
|
||||
decFmt->format(val, result, fp);
|
||||
expectPosition(fp, NumberFormat::kIntegerField, 1, 7, result);
|
||||
}
|
||||
{
|
||||
FieldPosition fp(NumberFormat::kFractionField);
|
||||
UnicodeString result;
|
||||
decFmt->format(val, result, fp);
|
||||
expectPosition(fp, NumberFormat::kFractionField, 8, 10, result);
|
||||
}
|
||||
delete decFmt;
|
||||
|
||||
decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, NumberFormat::kScientificStyle, status);
|
||||
val = -0.0000123;
|
||||
{
|
||||
int32_t expected[] = {
|
||||
NumberFormat::kSignField, 0, 1,
|
||||
NumberFormat::kIntegerField, 1, 2,
|
||||
NumberFormat::kDecimalSeparatorField, 2, 3,
|
||||
NumberFormat::kFractionField, 3, 5,
|
||||
NumberFormat::kExponentSymbolField, 5, 6,
|
||||
NumberFormat::kExponentSignField, 6, 7,
|
||||
NumberFormat::kExponentField, 7, 8
|
||||
};
|
||||
int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected));
|
||||
|
||||
FieldPositionIterator posIter;
|
||||
UnicodeString result;
|
||||
decFmt->format(val, result, posIter, status);
|
||||
expectPositions(posIter, expected, tupleCount, result);
|
||||
}
|
||||
{
|
||||
FieldPosition fp(NumberFormat::kIntegerField);
|
||||
UnicodeString result;
|
||||
decFmt->format(val, result, fp);
|
||||
expectPosition(fp, NumberFormat::kIntegerField, 1, 2, result);
|
||||
}
|
||||
{
|
||||
FieldPosition fp(NumberFormat::kFractionField);
|
||||
UnicodeString result;
|
||||
decFmt->format(val, result, fp);
|
||||
expectPosition(fp, NumberFormat::kFractionField, 3, 5, result);
|
||||
}
|
||||
delete decFmt;
|
||||
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
const char* attrString(int32_t attrId) {
|
||||
switch (attrId) {
|
||||
case NumberFormat::kIntegerField: return "integer";
|
||||
case NumberFormat::kFractionField: return "fraction";
|
||||
case NumberFormat::kDecimalSeparatorField: return "decimal separator";
|
||||
case NumberFormat::kExponentSymbolField: return "exponent symbol";
|
||||
case NumberFormat::kExponentSignField: return "exponent sign";
|
||||
case NumberFormat::kExponentField: return "exponent";
|
||||
case NumberFormat::kGroupingSeparatorField: return "grouping separator";
|
||||
case NumberFormat::kCurrencyField: return "currency";
|
||||
case NumberFormat::kPercentField: return "percent";
|
||||
case NumberFormat::kPermillField: return "permille";
|
||||
case NumberFormat::kSignField: return "sign";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
|
@ -142,11 +142,18 @@ class NumberFormatTest: public CalendarTimeZoneTest {
|
|||
void TestCurrencyIsoPluralFormat();
|
||||
void TestCurrencyParsing();
|
||||
void TestParseCurrencyInUCurr();
|
||||
void TestFormatAttributes();
|
||||
|
||||
private:
|
||||
|
||||
static UBool equalValue(const Formattable& a, const Formattable& b);
|
||||
|
||||
void expectPositions(FieldPositionIterator& iter, int32_t *values, int32_t tupleCount,
|
||||
const UnicodeString& str);
|
||||
|
||||
void expectPosition(FieldPosition& pos, int32_t id, int32_t start, int32_t limit,
|
||||
const UnicodeString& str);
|
||||
|
||||
void expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str);
|
||||
|
||||
void expect3(NumberFormat& fmt, const Formattable& n, const UnicodeString& str);
|
||||
|
|
Loading…
Add table
Reference in a new issue