void ParsedNumber::populateFormattable(Formattable& output, parse_flags_t parseFlags) const { bool sawNaN = 0 != (flags & FLAG_NAN); bool sawInfinity = 0 != (flags & FLAG_INFINITY); bool integerOnly = 0 != (parseFlags & PARSE_FLAG_INTEGER_ONLY); // Check for NaN, infinity, and -0.0 if (sawNaN) { // Can't use NAN or std::nan because the byte pattern is platform-dependent; // MSVC sets the sign bit, but Clang and GCC do not output.setDouble(uprv_getNaN()); return; } if (sawInfinity) { if (0 != (flags & FLAG_NEGATIVE)) { output.setDouble(-INFINITY); return; } else { output.setDouble(INFINITY); return; } } U_ASSERT(!quantity.bogus); if (quantity.isZero() && quantity.isNegative() && !integerOnly) { output.setDouble(-0.0); return; } // All other numbers output.adoptDecimalQuantity(new DecimalQuantity(quantity)); }
/** * If this is a >>> substitution, match only against ruleToUse. * Otherwise, use the superclass function. * @param text The string to parse * @param parsePosition Ignored on entry, updated on exit to point to * the first unmatched character. * @param baseValue The partial parse result prior to calling this * routine. */ UBool ModulusSubstitution::doParse(const UnicodeString& text, ParsePosition& parsePosition, double baseValue, double upperBound, UBool lenientParse, Formattable& result) const { // if this isn't a >>> substitution, we can just use the // inherited parse() routine to do the parsing if (ruleToUse == NULL) { return NFSubstitution::doParse(text, parsePosition, baseValue, upperBound, lenientParse, result); // but if it IS a >>> substitution, we have to do it here: we // use the specific rule's doParse() method, and then we have to // do some of the other work of NFRuleSet.parse() } else { ruleToUse->doParse(text, parsePosition, FALSE, upperBound, result); if (parsePosition.getIndex() != 0) { UErrorCode status = U_ZERO_ERROR; double tempResult = result.getDouble(status); tempResult = composeRuleValue(tempResult, baseValue); result.setDouble(tempResult); } return TRUE; } }
void ChoiceFormat::parse(const UnicodeString& text, Formattable& result, ParsePosition& status) const { // find the best number (defined as the one with the longest parse) int32_t start = status.getIndex(); int32_t furthest = start; double bestNumber = uprv_getNaN(); double tempNumber = 0.0; for (int i = 0; i < fCount; ++i) { int32_t len = fChoiceFormats[i].length(); if (text.compare(start, len, fChoiceFormats[i]) == 0) { status.setIndex(start + len); tempNumber = fChoiceLimits[i]; if (status.getIndex() > furthest) { furthest = status.getIndex(); bestNumber = tempNumber; if (furthest == text.length()) break; } } } status.setIndex(furthest); if (status.getIndex() == start) { status.setErrorIndex(furthest); } result.setDouble(bestNumber); }
virtual UBool doParse(const UnicodeString& /*text*/, ParsePosition& /*parsePosition*/, double baseValue, double /*upperBound*/, UBool /*lenientParse*/, Formattable& result) const { result.setDouble(baseValue); return TRUE; }
void ChoiceFormat::parse(const UnicodeString& text, Formattable& result, ParsePosition& pos) const { result.setDouble(parseArgument(msgPattern, 0, text, pos)); }
/** * Parses a string using the rule set or DecimalFormat belonging * to this substitution. If there's a match, a mathematical * operation (the inverse of the one used in formatting) is * performed on the result of the parse and the value passed in * and returned as the result. The parse position is updated to * point to the first unmatched character in the string. * @param text The string to parse * @param parsePosition On entry, ignored, but assumed to be 0. * On exit, this is updated to point to the first unmatched * character (or 0 if the substitution didn't match) * @param baseValue A partial parse result that should be * combined with the result of this parse * @param upperBound When searching the rule set for a rule * matching the string passed in, only rules with base values * lower than this are considered * @param lenientParse If true and matching against rules fails, * the substitution will also try matching the text against * numerals using a default-costructed NumberFormat. If false, * no extra work is done. (This value is false whenever the * formatter isn't in lenient-parse mode, but is also false * under some conditions even when the formatter _is_ in * lenient-parse mode.) * @return If there's a match, this is the result of composing * baseValue with whatever was returned from matching the * characters. This will be either a Long or a Double. If there's * no match this is new Long(0) (not null), and parsePosition * is left unchanged. */ UBool NFSubstitution::doParse(const UnicodeString& text, ParsePosition& parsePosition, double baseValue, double upperBound, UBool lenientParse, Formattable& result) const { #ifdef RBNF_DEBUG fprintf(stderr, "<nfsubs> %x bv: %g ub: %g\n", this, baseValue, upperBound); #endif // figure out the highest base value a rule can have and match // the text being parsed (this varies according to the type of // substitutions: multiplier, modulus, and numerator substitutions // restrict the search to rules with base values lower than their // own; same-value substitutions leave the upper bound wherever // it was, and the others allow any rule to match upperBound = calcUpperBound(upperBound); // use our rule set to parse the text. If that fails and // lenient parsing is enabled (this is always false if the // formatter's lenient-parsing mode is off, but it may also // be false even when the formatter's lenient-parse mode is // on), then also try parsing the text using a default- // constructed NumberFormat if (ruleSet != NULL) { ruleSet->parse(text, parsePosition, upperBound, result); if (lenientParse && !ruleSet->isFractionRuleSet() && parsePosition.getIndex() == 0) { UErrorCode status = U_ZERO_ERROR; NumberFormat* fmt = NumberFormat::createInstance(status); if (U_SUCCESS(status)) { fmt->parse(text, result, parsePosition); } delete fmt; } // ...or use our DecimalFormat to parse the text } else if (numberFormat != NULL) { numberFormat->parse(text, result, parsePosition); } // if the parse was successful, we've already advanced the caller's // parse position (this is the one function that doesn't have one // of its own). Derive a parse result and return it as a Long, // if possible, or a Double if (parsePosition.getIndex() != 0) { UErrorCode status = U_ZERO_ERROR; double tempResult = result.getDouble(status); // composeRuleValue() produces a full parse result from // the partial parse result passed to this function from // the caller (this is either the owning rule's base value // or the partial result obtained from composing the // owning rule's base value with its other substitution's // parse result) and the partial parse result obtained by // matching the substitution (which will be the same value // the caller would get by parsing just this part of the // text with RuleBasedNumberFormat.parse() ). How the two // values are used to derive the full parse result depends // on the types of substitutions: For a regular rule, the // ultimate result is its multiplier substitution's result // times the rule's divisor (or the rule's base value) plus // the modulus substitution's result (which will actually // supersede part of the rule's base value). For a negative- // number rule, the result is the negative of its substitution's // result. For a fraction rule, it's the sum of its two // substitution results. For a rule in a fraction rule set, // it's the numerator substitution's result divided by // the rule's base value. Results from same-value substitutions // propagate back upard, and null substitutions don't affect // the result. tempResult = composeRuleValue(tempResult, baseValue); result.setDouble(tempResult); return TRUE; // if the parse was UNsuccessful, return 0 } else { result.setLong(0); return FALSE; } }
UBool NumeratorSubstitution::doParse(const UnicodeString& text, ParsePosition& parsePosition, double baseValue, double upperBound, UBool /*lenientParse*/, Formattable& result) const { // we don't have to do anything special to do the parsing here, // but we have to turn lenient parsing off-- if we leave it on, // it SERIOUSLY messes up the algorithm // if withZeros is true, we need to count the zeros // and use that to adjust the parse result UErrorCode status = U_ZERO_ERROR; int32_t zeroCount = 0; UnicodeString workText(text); if (withZeros) { ParsePosition workPos(1); Formattable temp; while (workText.length() > 0 && workPos.getIndex() != 0) { workPos.setIndex(0); getRuleSet()->parse(workText, workPos, 1, temp); // parse zero or nothing at all if (workPos.getIndex() == 0) { // we failed, either there were no more zeros, or the number was formatted with digits // either way, we're done break; } ++zeroCount; parsePosition.setIndex(parsePosition.getIndex() + workPos.getIndex()); workText.remove(0, workPos.getIndex()); while (workText.length() > 0 && workText.charAt(0) == gSpace) { workText.remove(0, 1); parsePosition.setIndex(parsePosition.getIndex() + 1); } } workText = text; workText.remove(0, (int32_t)parsePosition.getIndex()); parsePosition.setIndex(0); } // we've parsed off the zeros, now let's parse the rest from our current position NFSubstitution::doParse(workText, parsePosition, withZeros ? 1 : baseValue, upperBound, FALSE, result); if (withZeros) { // any base value will do in this case. is there a way to // force this to not bother trying all the base values? // compute the 'effective' base and prescale the value down int64_t n = result.getLong(status); // force conversion! int64_t d = 1; int32_t pow = 0; while (d <= n) { d *= 10; ++pow; } // now add the zeros while (zeroCount > 0) { d *= 10; --zeroCount; } // d is now our true denominator result.setDouble((double)n/(double)d); } return TRUE; }
UBool FractionalPartSubstitution::doParse(const UnicodeString& text, ParsePosition& parsePosition, double baseValue, double /*upperBound*/, UBool lenientParse, Formattable& resVal) const { // if we're not in byDigits mode, we can just use the inherited // doParse() if (!byDigits) { return NFSubstitution::doParse(text, parsePosition, baseValue, 0, lenientParse, resVal); // if we ARE in byDigits mode, parse the text one digit at a time // using this substitution's owning rule set (we do this by setting // upperBound to 10 when calling doParse() ) until we reach // nonmatching text } else { UnicodeString workText(text); ParsePosition workPos(1); double result = 0; int32_t digit; // double p10 = 0.1; DigitList dl; NumberFormat* fmt = NULL; while (workText.length() > 0 && workPos.getIndex() != 0) { workPos.setIndex(0); Formattable temp; getRuleSet()->parse(workText, workPos, 10, temp); UErrorCode status = U_ZERO_ERROR; digit = temp.getLong(status); // digit = temp.getType() == Formattable::kLong ? // temp.getLong() : // (int32_t)temp.getDouble(); if (lenientParse && workPos.getIndex() == 0) { if (!fmt) { status = U_ZERO_ERROR; fmt = NumberFormat::createInstance(status); if (U_FAILURE(status)) { delete fmt; fmt = NULL; } } if (fmt) { fmt->parse(workText, temp, workPos); digit = temp.getLong(status); } } if (workPos.getIndex() != 0) { dl.append((char)('0' + digit)); // result += digit * p10; // p10 /= 10; parsePosition.setIndex(parsePosition.getIndex() + workPos.getIndex()); workText.removeBetween(0, workPos.getIndex()); while (workText.length() > 0 && workText.charAt(0) == gSpace) { workText.removeBetween(0, 1); parsePosition.setIndex(parsePosition.getIndex() + 1); } } } delete fmt; result = dl.fCount == 0 ? 0 : dl.getDouble(); result = composeRuleValue(result, baseValue); resVal.setDouble(result); return TRUE; } }