]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/nfrs.cpp
ICU-511.32.tar.gz
[apple/icu.git] / icuSources / i18n / nfrs.cpp
index ccf42b890d7140c889d645b1e413716ffc7e18ed..de42d8868e7e2400e9e0a29608984bb9669648a1 100644 (file)
@@ -1,6 +1,6 @@
 /*
 ******************************************************************************
-*   Copyright (C) 1997-2005, International Business Machines
+*   Copyright (C) 1997-2012, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 ******************************************************************************
 *   file name:  nfrs.cpp
 #include "unicode/uchar.h"
 #include "nfrule.h"
 #include "nfrlist.h"
+#include "patternprops.h"
 
 #ifdef RBNF_DEBUG
 #include "cmemory.h"
 #endif
 
-#include "util.h"
-
 U_NAMESPACE_BEGIN
 
 #if 0
@@ -114,12 +113,18 @@ static const UChar gPercentPercent[] =
     0x25, 0x25, 0
 }; /* "%%" */
 
+static const UChar gNoparse[] =
+{
+    0x40, 0x6E, 0x6F, 0x70, 0x61, 0x72, 0x73, 0x65, 0
+}; /* "@noparse" */
+
 NFRuleSet::NFRuleSet(UnicodeString* descriptions, int32_t index, UErrorCode& status)
   : name()
   , rules(0)
   , negativeNumberRule(NULL)
   , fIsFractionRuleSet(FALSE)
   , fIsPublic(FALSE)
+  , fIsParseable(TRUE)
   , fRecursionCount(0)
 {
     for (int i = 0; i < 3; ++i) {
@@ -149,7 +154,7 @@ NFRuleSet::NFRuleSet(UnicodeString* descriptions, int32_t index, UErrorCode& sta
             status = U_PARSE_ERROR;
         } else {
             name.setTo(description, 0, pos);
-            while (pos < description.length() && uprv_isRuleWhiteSpace(description.charAt(++pos))) {
+            while (pos < description.length() && PatternProps::isWhiteSpace(description.charAt(++pos))) {
             }
             description.remove(0, pos);
         }
@@ -162,7 +167,12 @@ NFRuleSet::NFRuleSet(UnicodeString* descriptions, int32_t index, UErrorCode& sta
         status = U_PARSE_ERROR;
     }
 
-    fIsPublic = name.indexOf(gPercentPercent) != 0;
+    fIsPublic = name.indexOf(gPercentPercent, 2, 0) != 0;
+
+    if ( name.endsWith(gNoparse,8) ) {
+        fIsParseable = FALSE;
+        name.truncate(name.length()-8); // remove the @noparse from the name
+    }
 
     // all of the other members of NFRuleSet are initialized
     // by parseRules()
@@ -180,6 +190,9 @@ NFRuleSet::parseRules(UnicodeString& description, const RuleBasedNumberFormat* o
         return;
     }
 
+    // ensure we are starting with an empty rule list
+    rules.deleteAll();
+
     // dlf - the original code kept a separate description array for no reason,
     // so I got rid of it.  The loop was too complex so I simplified it.
 
@@ -225,24 +238,36 @@ NFRuleSet::parseRules(UnicodeString& description, const RuleBasedNumberFormat* o
             // if it's the negative-number rule, copy it into its own
             // data member and delete it from the list
         case NFRule::kNegativeNumberRule:
+            if (negativeNumberRule) {
+                delete negativeNumberRule;
+            }
             negativeNumberRule = rules.remove(i);
             break;
 
             // if it's the improper fraction rule, copy it into the
             // correct element of fractionRules
         case NFRule::kImproperFractionRule:
+            if (fractionRules[0]) {
+                delete fractionRules[0];
+            }
             fractionRules[0] = rules.remove(i);
             break;
 
             // if it's the proper fraction rule, copy it into the
             // correct element of fractionRules
         case NFRule::kProperFractionRule:
+            if (fractionRules[1]) {
+                delete fractionRules[1];
+            }
             fractionRules[1] = rules.remove(i);
             break;
 
             // if it's the master rule, copy it into the
             // correct element of fractionRules
         case NFRule::kMasterRule:
+            if (fractionRules[2]) {
+                delete fractionRules[2];
+            }
             fractionRules[2] = rules.remove(i);
             break;
 
@@ -378,6 +403,14 @@ NFRuleSet::findDoubleRule(double number) const
         return fractionRules[2];
     }
 
+    // always use the last rule for infinity.  It is likely that rule
+    // has a DecimalFormat that will do the right thing with infinity even
+    // if the rule's base value is strange, i.e. something larger than what 
+    // util64_fromDouble produces below.
+    if (uprv_isInfinite(number) && (rules.size() > 0)) {
+        return rules[rules.size() - 1];
+    }
+
     // and if we haven't yet returned a rule, use findNormalRule()
     // to find the applicable rule
     int64_t r = util64_fromDouble(number + 0.5);
@@ -572,15 +605,17 @@ NFRuleSet::findFractionRuleSetRule(double number) const
 static void dumpUS(FILE* f, const UnicodeString& us) {
   int len = us.length();
   char* buf = (char *)uprv_malloc((len+1)*sizeof(char)); //new char[len+1];
-  us.extract(0, len, buf);
-  buf[len] = 0;
-  fprintf(f, "%s", buf);
-  uprv_free(buf); //delete[] buf;
+  if (buf != NULL) {
+         us.extract(0, len, buf);
+         buf[len] = 0;
+         fprintf(f, "%s", buf);
+         uprv_free(buf); //delete[] buf;
+  }
 }
 #endif
 
 UBool
-NFRuleSet::parse(const UnicodeString& text, ParsePosition& pos, double upperBound, Formattable& result) const
+NFRuleSet::parse(const UnicodeString& text, ParsePosition& pos, double upperBound, Formattable& result, UBool lenient) const
 {
     // try matching each rule in the rule set against the text being
     // parsed.  Whichever one matches the most characters is the one
@@ -631,7 +666,7 @@ NFRuleSet::parse(const UnicodeString& text, ParsePosition& pos, double upperBoun
         for (int i = 0; i < 3; i++) {
             if (fractionRules[i]) {
                 Formattable tempResult;
-                UBool success = fractionRules[i]->doParse(text, workingPos, 0, upperBound, tempResult);
+                UBool success = fractionRules[i]->doParse(text, workingPos, 0, upperBound, tempResult, lenient || isDecimalFormatRuleParseable() );
                 if (success && (workingPos.getIndex() > highWaterMark.getIndex())) {
                     result = tempResult;
                     highWaterMark = workingPos;
@@ -700,14 +735,14 @@ NFRuleSet::appendRules(UnicodeString& result) const
 
     // followed by the regular rules...
     for (uint32_t i = 0; i < rules.size(); i++) {
-        result.append(gFourSpaces);
+        result.append(gFourSpaces, 4);
         rules[i]->_appendRuleText(result);
         result.append(gLineFeed);
     }
 
     // followed by the special rules (if they exist)
     if (negativeNumberRule) {
-        result.append(gFourSpaces);
+        result.append(gFourSpaces, 4);
         negativeNumberRule->_appendRuleText(result);
         result.append(gLineFeed);
     }
@@ -715,7 +750,7 @@ NFRuleSet::appendRules(UnicodeString& result) const
     {
         for (uint32_t i = 0; i < 3; ++i) {
             if (fractionRules[i]) {
-                result.append(gFourSpaces);
+                result.append(gFourSpaces, 4);
                 fractionRules[i]->_appendRuleText(result);
                 result.append(gLineFeed);
             }