/*
*******************************************************************************
* Copyright (C) 1997-2014, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
* File DECIMFMT.CPP
*
* Modification History:
*
* Date Name Description
* 02/19/97 aliu Converted from java.
* 03/20/97 clhuang Implemented with new APIs.
* 03/31/97 aliu Moved isLONG_MIN to DigitList, and fixed it.
* 04/3/97 aliu Rewrote parsing and formatting completely, and
* cleaned up and debugged. Actually works now.
* Implemented NAN and INF handling, for both parsing
* and formatting. Extensive testing & debugging.
* 04/10/97 aliu Modified to compile on AIX.
* 04/16/97 aliu Rewrote to use DigitList, which has been resurrected.
* Changed DigitCount to int per code review.
* 07/09/97 helena Made ParsePosition into a class.
* 08/26/97 aliu Extensive changes to applyPattern; completely
* rewritten from the Java.
* 09/09/97 aliu Ported over support for exponential formats.
* 07/20/98 stephen JDK 1.2 sync up.
* Various instances of '0' replaced with 'NULL'
* Check for grouping size in subFormat()
* Brought subParse() in line with Java 1.2
* Added method appendAffix()
* 08/24/1998 srl Removed Mutex calls. This is not a thread safe class!
* 02/22/99 stephen Removed character literals for EBCDIC safety
* 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes
* 06/28/99 stephen Fixed bugs in toPattern().
* 06/29/99 stephen Fixed operator= to copy fFormatWidth, fPad,
* fPadPosition
********************************************************************************
*/
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
#include "fphdlimp.h"
#include "unicode/decimfmt.h"
#include "unicode/choicfmt.h"
#include "unicode/ucurr.h"
#include "unicode/ustring.h"
#include "unicode/dcfmtsym.h"
#include "unicode/ures.h"
#include "unicode/uchar.h"
#include "unicode/uniset.h"
#include "unicode/curramt.h"
#include "unicode/currpinf.h"
#include "unicode/plurrule.h"
#include "unicode/utf16.h"
#include "unicode/numsys.h"
#include "unicode/localpointer.h"
#include "uresimp.h"
#include "ucurrimp.h"
#include "charstr.h"
#include "cmemory.h"
#include "patternprops.h"
#include "digitlst.h"
#include "cstring.h"
#include "umutex.h"
#include "uassert.h"
#include "putilimp.h"
#include <math.h>
#include "hash.h"
#include "decfmtst.h"
#include "dcfmtimp.h"
#include "plurrule_impl.h"
#include "decimalformatpattern.h"
/*
* On certain platforms, round is a macro defined in math.h
* This undefine is to avoid conflict between the macro and
* the function defined below.
*/
#ifdef round
#undef round
#endif
U_NAMESPACE_BEGIN
#ifdef FMT_DEBUG
#include <stdio.h>
static void _debugout(const char *f, int l, const UnicodeString& s) {
char buf[2000];
s.extract((int32_t) 0, s.length(), buf, "utf-8");
printf("%s:%d: %s\n", f,l, buf);
}
#define debugout(x) _debugout(__FILE__,__LINE__,x)
#define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x);
static const UnicodeString dbg_null("<NULL>","");
#define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null))
#else
#define debugout(x)
#define debug(x)
#endif
/* == Fastpath calculation. ==
*/
#if UCONFIG_FORMAT_FASTPATHS_49
inline DecimalFormatInternal& internalData(uint8_t *reserved) {
return *reinterpret_cast<DecimalFormatInternal*>(reserved);
}
inline const DecimalFormatInternal& internalData(const uint8_t *reserved) {
return *reinterpret_cast<const DecimalFormatInternal*>(reserved);
}
#else
#endif
/* For currency parsing purose,
* Need to remember all prefix patterns and suffix patterns of
* every currency format pattern,
* including the pattern of default currecny style
* and plural currency style. And the patterns are set through applyPattern.
*/
struct AffixPatternsForCurrency : public UMemory {
// negative prefix pattern
UnicodeString negPrefixPatternForCurrency;
// negative suffix pattern
UnicodeString negSuffixPatternForCurrency;
// positive prefix pattern
UnicodeString posPrefixPatternForCurrency;
// positive suffix pattern
UnicodeString posSuffixPatternForCurrency;
int8_t patternType;
AffixPatternsForCurrency(const UnicodeString& negPrefix,
const UnicodeString& negSuffix,
const UnicodeString& posPrefix,
const UnicodeString& posSuffix,
int8_t type) {
negPrefixPatternForCurrency = negPrefix;
negSuffixPatternForCurrency = negSuffix;
posPrefixPatternForCurrency = posPrefix;
posSuffixPatternForCurrency = posSuffix;
patternType = type;
}
#ifdef FMT_DEBUG
void dump() const {
debugout( UnicodeString("AffixPatternsForCurrency( -=\"") +
negPrefixPatternForCurrency + (UnicodeString)"\"/\"" +
negSuffixPatternForCurrency + (UnicodeString)"\" +=\"" +
posPrefixPatternForCurrency + (UnicodeString)"\"/\"" +
posSuffixPatternForCurrency + (UnicodeString)"\" )");
}
#endif
};
/* affix for currency formatting when the currency sign in the pattern
* equals to 3, such as the pattern contains 3 currency sign or
* the formatter style is currency plural format style.
*/
struct AffixesForCurrency : public UMemory {
// negative prefix
UnicodeString negPrefixForCurrency;
// negative suffix
UnicodeString negSuffixForCurrency;
// positive prefix
UnicodeString posPrefixForCurrency;
// positive suffix
UnicodeString posSuffixForCurrency;
int32_t formatWidth;
AffixesForCurrency(const UnicodeString& negPrefix,
const UnicodeString& negSuffix,
const UnicodeString& posPrefix,
const UnicodeString& posSuffix) {
negPrefixForCurrency = negPrefix;
negSuffixForCurrency = negSuffix;
posPrefixForCurrency = posPrefix;
posSuffixForCurrency = posSuffix;
}
#ifdef FMT_DEBUG
void dump() const {
debugout( UnicodeString("AffixesForCurrency( -=\"") +
negPrefixForCurrency + (UnicodeString)"\"/\"" +
negSuffixForCurrency + (UnicodeString)"\" +=\"" +
posPrefixForCurrency + (UnicodeString)"\"/\"" +
posSuffixForCurrency + (UnicodeString)"\" )");
}
#endif
};
U_CDECL_BEGIN
/**
* @internal ICU 4.2
*/
static UBool U_CALLCONV decimfmtAffixValueComparator(UHashTok val1, UHashTok val2);
/**
* @internal ICU 4.2
*/
static UBool U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2);
static UBool
U_CALLCONV decimfmtAffixValueComparator(UHashTok val1, UHashTok val2) {
const AffixesForCurrency* affix_1 =
(AffixesForCurrency*)val1.pointer;
const AffixesForCurrency* affix_2 =
(AffixesForCurrency*)val2.pointer;
return affix_1->negPrefixForCurrency == affix_2->negPrefixForCurrency &&
affix_1->negSuffixForCurrency == affix_2->negSuffixForCurrency &&
affix_1->posPrefixForCurrency == affix_2->posPrefixForCurrency &&
affix_1->posSuffixForCurrency == affix_2->posSuffixForCurrency;
}
static UBool
U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2) {
const AffixPatternsForCurrency* affix_1 =
(AffixPatternsForCurrency*)val1.pointer;
const AffixPatternsForCurrency* affix_2 =
(AffixPatternsForCurrency*)val2.pointer;
return affix_1->negPrefixPatternForCurrency ==
affix_2->negPrefixPatternForCurrency &&
affix_1->negSuffixPatternForCurrency ==
affix_2->negSuffixPatternForCurrency &&
affix_1->posPrefixPatternForCu