/*
*******************************************************************************
-* Copyright (C) 1997-2010, International Business Machines Corporation
+* Copyright (C) 1997-2012, International Business Machines Corporation
* and others. All Rights Reserved.
*******************************************************************************
*/
-#include <typeinfo> // for 'typeid' to work
+#include "utypeinfo.h" // for 'typeid' to work
#include "unicode/rbnf.h"
#include "cmemory.h"
#include "cstring.h"
-#include "util.h"
+#include "patternprops.h"
#include "uresimp.h"
// debugging
#define kHalfMaxDouble (double)(1 << kSomeNumberOfBitsDiv2)
#define kMaxDouble (kHalfMaxDouble * kHalfMaxDouble)
-// Temporary workaround - when noParse is true, do noting in parse.
-// TODO: We need a real fix - see #6895/#6896
-static const char *NO_SPELLOUT_PARSE_LANGUAGES[] = { "ga", NULL };
-
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedNumberFormat)
*/
class LocalizationInfo : public UMemory {
protected:
- virtual ~LocalizationInfo() {};
+ virtual ~LocalizationInfo();
uint32_t refcount;
public:
// static UClassID getStaticClassID(void);
};
+LocalizationInfo::~LocalizationInfo() {}
+
//UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(LocalizationInfo)
// if both strings are NULL, this returns TRUE
void inc(void) { ++p; ch = 0xffff; }
UBool checkInc(UChar c) { if (p < e && (ch == c || *p == c)) { inc(); return TRUE; } return FALSE; }
UBool check(UChar c) { return p < e && (ch == c || *p == c); }
- void skipWhitespace(void) { while (p < e && uprv_isRuleWhiteSpace(ch != 0xffff ? ch : *p)) inc();}
+ void skipWhitespace(void) { while (p < e && PatternProps::isWhiteSpace(ch != 0xffff ? ch : *p)) inc();}
UBool inList(UChar c, const UChar* list) const {
- if (*list == SPACE && uprv_isRuleWhiteSpace(c)) return TRUE;
+ if (*list == SPACE && PatternProps::isWhiteSpace(c)) return TRUE;
while (*list && *list != c) ++list; return *list == c;
}
void parseError(const char* msg);
const UnicodeString& locs,
const Locale& alocale, UParseError& perror, UErrorCode& status)
: ruleSets(NULL)
+ , ruleSetDescriptions(NULL)
+ , numRuleSets(0)
, defaultRuleSet(NULL)
, locale(alocale)
, collator(NULL)
, lenient(FALSE)
, lenientParseRules(NULL)
, localizations(NULL)
- , noParse(FALSE) //TODO: to be removed after #6895
{
LocalizationInfo* locinfo = StringLocalizationInfo::create(locs, perror, status);
init(description, locinfo, perror, status);
const UnicodeString& locs,
UParseError& perror, UErrorCode& status)
: ruleSets(NULL)
+ , ruleSetDescriptions(NULL)
+ , numRuleSets(0)
, defaultRuleSet(NULL)
, locale(Locale::getDefault())
, collator(NULL)
, lenient(FALSE)
, lenientParseRules(NULL)
, localizations(NULL)
- , noParse(FALSE) //TODO: to be removed after #6895
{
LocalizationInfo* locinfo = StringLocalizationInfo::create(locs, perror, status);
init(description, locinfo, perror, status);
LocalizationInfo* info,
const Locale& alocale, UParseError& perror, UErrorCode& status)
: ruleSets(NULL)
+ , ruleSetDescriptions(NULL)
+ , numRuleSets(0)
, defaultRuleSet(NULL)
, locale(alocale)
, collator(NULL)
, lenient(FALSE)
, lenientParseRules(NULL)
, localizations(NULL)
- , noParse(FALSE) //TODO: to be removed after #6895
{
init(description, info, perror, status);
}
UParseError& perror,
UErrorCode& status)
: ruleSets(NULL)
+ , ruleSetDescriptions(NULL)
+ , numRuleSets(0)
, defaultRuleSet(NULL)
, locale(Locale::getDefault())
, collator(NULL)
, lenient(FALSE)
, lenientParseRules(NULL)
, localizations(NULL)
- , noParse(FALSE) //TODO: to be removed after #6895
{
init(description, NULL, perror, status);
}
UParseError& perror,
UErrorCode& status)
: ruleSets(NULL)
+ , ruleSetDescriptions(NULL)
+ , numRuleSets(0)
, defaultRuleSet(NULL)
, locale(aLocale)
, collator(NULL)
, lenient(FALSE)
, lenientParseRules(NULL)
, localizations(NULL)
- , noParse(FALSE) //TODO: to be removed after #6895
{
init(description, NULL, perror, status);
}
RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale& alocale, UErrorCode& status)
: ruleSets(NULL)
+ , ruleSetDescriptions(NULL)
+ , numRuleSets(0)
, defaultRuleSet(NULL)
, locale(alocale)
, collator(NULL)
// TODO: read localization info from resource
LocalizationInfo* locinfo = NULL;
- int32_t len = 0;
UResourceBundle* nfrb = ures_open(U_ICUDATA_RBNF, locale.getName(), &status);
if (U_SUCCESS(status)) {
setLocaleIDs(ures_getLocaleByType(nfrb, ULOC_VALID_LOCALE, &status),
ures_close(nfrb);
return;
}
-
+
UnicodeString desc;
while (ures_hasNext(ruleSets)) {
- const UChar* currentString = ures_getNextString(ruleSets,&len,NULL,&status);
- desc.append(currentString);
+ desc.append(ures_getNextUnicodeString(ruleSets,NULL,&status));
}
UParseError perror;
-
init (desc, locinfo, perror, status);
- //TODO: we need a real fix - see #6895 / #6896
- noParse = FALSE;
- if (tag == URBNF_SPELLOUT) {
- const char *lang = alocale.getLanguage();
- for (int32_t i = 0; NO_SPELLOUT_PARSE_LANGUAGES[i] != NULL; i++) {
- if (uprv_strcmp(lang, NO_SPELLOUT_PARSE_LANGUAGES[i]) == 0) {
- noParse = TRUE;
- break;
- }
- }
- }
- //TODO: end
-
ures_close(ruleSets);
ures_close(rbnfRules);
}
RuleBasedNumberFormat::RuleBasedNumberFormat(const RuleBasedNumberFormat& rhs)
: NumberFormat(rhs)
, ruleSets(NULL)
+ , ruleSetDescriptions(NULL)
+ , numRuleSets(0)
, defaultRuleSet(NULL)
, locale(rhs.locale)
, collator(NULL)
UParseError perror;
init(rules, rhs.localizations ? rhs.localizations->ref() : NULL, perror, status);
- //TODO: remove below when we fix the parse bug - See #6895 / #6896
- noParse = rhs.noParse;
-
return *this;
}
result = 0;
} else {
result->lenient = lenient;
-
- //TODO: remove below when we fix the parse bug - See #6895 / #6896
- result->noParse = noParse;
}
return result;
}
{
// return format((int64_t)number, ruleSetName, toAppendTo, pos, status);
if (U_SUCCESS(status)) {
- if (ruleSetName.indexOf(gPercentPercent) == 0) {
+ if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) {
// throw new IllegalArgumentException("Can't use internal rule set");
status = U_ILLEGAL_ARGUMENT_ERROR;
} else {
UErrorCode& status) const
{
if (U_SUCCESS(status)) {
- if (ruleSetName.indexOf(gPercentPercent) == 0) {
+ if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) {
// throw new IllegalArgumentException("Can't use internal rule set");
status = U_ILLEGAL_ARGUMENT_ERROR;
} else {
UErrorCode& status) const
{
if (U_SUCCESS(status)) {
- if (ruleSetName.indexOf(gPercentPercent) == 0) {
+ if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) {
// throw new IllegalArgumentException("Can't use internal rule set");
status = U_ILLEGAL_ARGUMENT_ERROR;
} else {
Formattable& result,
ParsePosition& parsePosition) const
{
- //TODO: We need a real fix. See #6895 / #6896
- if (noParse) {
- // skip parsing
- parsePosition.setErrorIndex(0);
- return;
- }
-
if (!ruleSets) {
parsePosition.setErrorIndex(0);
return;
// is, pull them out into our temporary holding place for them,
// and delete them from the description before the real desciption-
// parsing code sees them
- int32_t lp = description.indexOf(gLenientParse);
+ int32_t lp = description.indexOf(gLenientParse, -1, 0);
if (lp != -1) {
// we've got to make sure we're not in the middle of a rule
// (where "%%lenient-parse" would actually get treated as
// locate the beginning and end of the actual collation
// rules (there may be whitespace between the name and
// the first token in the description)
- int lpEnd = description.indexOf(gSemiPercent, lp);
+ int lpEnd = description.indexOf(gSemiPercent, 2, lp);
if (lpEnd == -1) {
lpEnd = description.length() - 1;
}
int lpStart = lp + u_strlen(gLenientParse);
- while (uprv_isRuleWhiteSpace(description.charAt(lpStart))) {
+ while (PatternProps::isWhiteSpace(description.charAt(lpStart))) {
++lpStart;
}
// pre-flight parsing the description and count the number of
// rule sets (";%" marks the end of one rule set and the beginning
// of the next)
- int numRuleSets = 0;
- for (int32_t p = description.indexOf(gSemiPercent); p != -1; p = description.indexOf(gSemiPercent, p)) {
+ numRuleSets = 0;
+ for (int32_t p = description.indexOf(gSemiPercent, 2, 0); p != -1; p = description.indexOf(gSemiPercent, 2, p)) {
++numRuleSets;
++p;
}
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
- UnicodeString* ruleSetDescriptions = new UnicodeString[numRuleSets];
+
+ ruleSetDescriptions = new UnicodeString[numRuleSets];
if (ruleSetDescriptions == 0) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
{
int curRuleSet = 0;
int32_t start = 0;
- for (int32_t p = description.indexOf(gSemiPercent); p != -1; p = description.indexOf(gSemiPercent, start)) {
+ for (int32_t p = description.indexOf(gSemiPercent, 2, 0); p != -1; p = description.indexOf(gSemiPercent, 2, start)) {
ruleSetDescriptions[curRuleSet].setTo(description, start, p + 1 - start);
ruleSets[curRuleSet] = new NFRuleSet(ruleSetDescriptions, curRuleSet, status);
if (ruleSets[curRuleSet] == 0) {
status = U_MEMORY_ALLOCATION_ERROR;
- goto cleanup;
+ return;
}
++curRuleSet;
start = p + 1;
ruleSets[curRuleSet] = new NFRuleSet(ruleSetDescriptions, curRuleSet, status);
if (ruleSets[curRuleSet] == 0) {
status = U_MEMORY_ALLOCATION_ERROR;
- goto cleanup;
+ return;
}
}
} else {
defaultRuleSet = getDefaultRuleSet();
}
-
-cleanup:
- delete[] ruleSetDescriptions;
}
void
while (start != -1 && start < description.length()) {
// seek to the first non-whitespace character...
while (start < description.length()
- && uprv_isRuleWhiteSpace(description.charAt(start))) {
+ && PatternProps::isWhiteSpace(description.charAt(start))) {
++start;
}
ruleSets = NULL;
}
+ if (ruleSetDescriptions) {
+ delete [] ruleSetDescriptions;
+ }
+
#if !UCONFIG_NO_COLLATION
delete collator;
#endif
return decimalFormatSymbols;
}
+// De-owning the current localized symbols and adopt the new symbols.
+void
+RuleBasedNumberFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt)
+{
+ if (symbolsToAdopt == NULL) {
+ return; // do not allow caller to set decimalFormatSymbols to NULL
+ }
+
+ if (decimalFormatSymbols != NULL) {
+ delete decimalFormatSymbols;
+ }
+
+ decimalFormatSymbols = symbolsToAdopt;
+
+ {
+ // Apply the new decimalFormatSymbols by reparsing the rulesets
+ UErrorCode status = U_ZERO_ERROR;
+
+ for (int32_t i = 0; i < numRuleSets; i++) {
+ ruleSets[i]->parseRules(ruleSetDescriptions[i], this, status);
+ }
+ }
+}
+
+// Setting the symbols is equlivalent to adopting a newly created localized symbols.
+void
+RuleBasedNumberFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols)
+{
+ adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols));
+}
+
U_NAMESPACE_END
/* U_HAVE_RBNF */