numparse_scientific.cpp [plain text]
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
#define UNISTR_FROM_STRING_EXPLICIT
#include "numparse_types.h"
#include "numparse_scientific.h"
#include "static_unicode_sets.h"
using namespace icu;
using namespace icu::numparse;
using namespace icu::numparse::impl;
namespace {
inline const UnicodeSet& minusSignSet() {
return *unisets::get(unisets::MINUS_SIGN);
}
inline const UnicodeSet& plusSignSet() {
return *unisets::get(unisets::PLUS_SIGN);
}
inline const UnicodeSet& ignorablesSet() { return *unisets::get(unisets::STRICT_IGNORABLES);
}
}
ScientificMatcher::ScientificMatcher(const DecimalFormatSymbols& dfs, const Grouper& grouper)
: fExponentSeparatorString(dfs.getConstSymbol(DecimalFormatSymbols::kExponentialSymbol)),
fExponentMatcher(dfs, grouper, PARSE_FLAG_INTEGER_ONLY | PARSE_FLAG_GROUPING_DISABLED) {
const UnicodeString& minusSign = dfs.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
if (minusSignSet().contains(minusSign)) {
fCustomMinusSign.setToBogus();
} else {
fCustomMinusSign = minusSign;
}
const UnicodeString& plusSign = dfs.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
if (plusSignSet().contains(plusSign)) {
fCustomPlusSign.setToBogus();
} else {
fCustomPlusSign = plusSign;
}
}
bool ScientificMatcher::match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const {
if (!result.seenNumber()) {
return false;
}
if (0 != (result.flags & FLAG_HAS_EXPONENT)) {
return false;
}
int overlap1 = segment.getCommonPrefixLength(fExponentSeparatorString);
if (overlap1 == fExponentSeparatorString.length()) {
int32_t exponentStart = segment.getOffset();
if (segment.length() == overlap1) {
return true;
}
segment.adjustOffset(overlap1);
while (segment.length() > 0 && segment.startsWith(ignorablesSet())) { segment.adjustOffsetByCodePoint();
}
int8_t exponentSign = 1;
if (segment.startsWith(minusSignSet())) {
exponentSign = -1;
segment.adjustOffsetByCodePoint();
} else if (segment.startsWith(plusSignSet())) {
segment.adjustOffsetByCodePoint();
} else if (segment.startsWith(fCustomMinusSign)) {
int32_t overlap2 = segment.getCommonPrefixLength(fCustomMinusSign);
if (overlap2 != fCustomMinusSign.length()) {
segment.setOffset(exponentStart);
return true;
}
exponentSign = -1;
segment.adjustOffset(overlap2);
} else if (segment.startsWith(fCustomPlusSign)) {
int32_t overlap2 = segment.getCommonPrefixLength(fCustomPlusSign);
if (overlap2 != fCustomPlusSign.length()) {
segment.setOffset(exponentStart);
return true;
}
segment.adjustOffset(overlap2);
}
while (segment.length() > 0 && segment.startsWith(ignorablesSet())) { segment.adjustOffsetByCodePoint();
}
bool wasBogus = result.quantity.bogus;
result.quantity.bogus = false;
int digitsOffset = segment.getOffset();
bool digitsReturnValue = fExponentMatcher.match(segment, result, exponentSign, status);
result.quantity.bogus = wasBogus;
if (segment.getOffset() != digitsOffset) {
result.flags |= FLAG_HAS_EXPONENT;
} else {
segment.setOffset(exponentStart);
}
return digitsReturnValue;
} else if (overlap1 == segment.length()) {
return true;
}
return false;
}
bool ScientificMatcher::smokeTest(const StringSegment& segment) const {
return segment.startsWith(fExponentSeparatorString);
}
UnicodeString ScientificMatcher::toString() const {
return u"<Scientific>";
}
#endif