diff options
Diffstat (limited to 'deps/icu-small/source/i18n/formattedval_sbimpl.cpp')
-rw-r--r-- | deps/icu-small/source/i18n/formattedval_sbimpl.cpp | 75 |
1 files changed, 72 insertions, 3 deletions
diff --git a/deps/icu-small/source/i18n/formattedval_sbimpl.cpp b/deps/icu-small/source/i18n/formattedval_sbimpl.cpp index dfe3af6686..b2ae4c34c0 100644 --- a/deps/icu-small/source/i18n/formattedval_sbimpl.cpp +++ b/deps/icu-small/source/i18n/formattedval_sbimpl.cpp @@ -15,6 +15,7 @@ #include "formatted_string_builder.h" #include "number_utils.h" #include "static_unicode_sets.h" +#include "unicode/listformatter.h" U_NAMESPACE_BEGIN @@ -102,14 +103,25 @@ static constexpr Field kEndField = Field(0xf, 0xf); bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition& cfpos, Field numericField, UErrorCode& /*status*/) const { int32_t fieldStart = -1; Field currField = kUndefinedField; + UFieldCategory spanCategory = UFIELD_CATEGORY_UNDEFINED; + int32_t spanValue; for (int32_t i = fString.fZero + cfpos.getLimit(); i <= fString.fZero + fString.fLength; i++) { Field _field = (i < fString.fZero + fString.fLength) ? fString.getFieldPtr()[i] : kEndField; // Case 1: currently scanning a field. if (currField != kUndefinedField) { if (currField != _field) { int32_t end = i - fString.fZero; + // Handle span fields; don't trim them + if (spanCategory != UFIELD_CATEGORY_UNDEFINED) { + cfpos.setState( + spanCategory, + spanValue, + fieldStart, + end); + return true; + } // Grouping separators can be whitespace; don't throw them out! - if (currField != Field(UFIELD_CATEGORY_NUMBER, UNUM_GROUPING_SEPARATOR_FIELD)) { + if (isTrimmable(currField)) { end = trimBack(i - fString.fZero); } if (end <= fieldStart) { @@ -120,7 +132,7 @@ bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition& continue; } int32_t start = fieldStart; - if (currField != Field(UFIELD_CATEGORY_NUMBER, UNUM_GROUPING_SEPARATOR_FIELD)) { + if (isTrimmable(currField)) { start = trimFront(start); } cfpos.setState(currField.getCategory(), currField.getField(), start, end); @@ -154,7 +166,8 @@ bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition& || cfpos.getField() != numericField.getField()) && fString.getFieldPtr()[i - 1].isNumeric() && !_field.isNumeric()) { - int j = i - 1; + // Re-wind to the beginning of the field and then emit it + int32_t j = i - 1; for (; j >= fString.fZero && fString.getFieldPtr()[j].isNumeric(); j--) {} cfpos.setState( numericField.getCategory(), @@ -163,6 +176,23 @@ bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition& i - fString.fZero); return true; } + // Special case: emit normalField if we are pointing at the end of spanField. + if (i > fString.fZero) { + auto elementField = fString.getFieldPtr()[i-1]; + if (elementField == Field(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD) + && cfpos.matchesField(elementField.getCategory(), elementField.getField()) + && (cfpos.getLimit() < i - fString.fZero || cfpos.getCategory() != elementField.getCategory())) { + // Re-wind to the beginning of the field and then emit it + int32_t j = i - 1; + for (; j >= fString.fZero && fString.getFieldPtr()[j] == fString.getFieldPtr()[i-1]; j--) {} + cfpos.setState( + elementField.getCategory(), + elementField.getField(), + j - fString.fZero + 1, + i - fString.fZero); + return true; + } + } // Special case: skip over INTEGER; will be coalesced later. if (_field == Field(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD)) { _field = kUndefinedField; @@ -172,6 +202,23 @@ bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition& continue; } // Case 3: check for field starting at this position + // Case 3a: Need to add a SpanField + if (_field == Field(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD) + // don't return the same field twice in a row: + && (i == fString.fZero + || fString.getFieldPtr()[i-1].getCategory() != UFIELD_CATEGORY_LIST + || fString.getFieldPtr()[i-1].getField() != ULISTFMT_ELEMENT_FIELD)) { + int64_t si = cfpos.getInt64IterationContext(); + spanValue = spanIndices[si]; + cfpos.setInt64IterationContext(si + 1); + if (cfpos.matchesField(UFIELD_CATEGORY_LIST_SPAN, spanValue)) { + spanCategory = UFIELD_CATEGORY_LIST_SPAN; + fieldStart = i - fString.fZero; + currField = _field; + continue; + } + } + // Case 3b: No SpanField or SpanField did not match if (cfpos.matchesField(_field.getCategory(), _field.getField())) { fieldStart = i - fString.fZero; currField = _field; @@ -182,11 +229,33 @@ bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition& return false; } +void FormattedValueStringBuilderImpl::appendSpanIndex(int32_t position) { + if (spanIndices.getCapacity() <= position) { + spanIndices.resize(position * 2); + } + spanIndices[position] = position; +} + +void FormattedValueStringBuilderImpl::prependSpanIndex(int32_t position) { + if (spanIndices.getCapacity() <= position) { + spanIndices.resize(position * 2); + } + for (int32_t i = 0; i < position; i++) { + spanIndices[i+1] = spanIndices[i]; + } + spanIndices[0] = position; +} + bool FormattedValueStringBuilderImpl::isIntOrGroup(Field field) { return field == Field(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD) || field == Field(UFIELD_CATEGORY_NUMBER, UNUM_GROUPING_SEPARATOR_FIELD); } +bool FormattedValueStringBuilderImpl::isTrimmable(Field field) { + return field != Field(UFIELD_CATEGORY_NUMBER, UNUM_GROUPING_SEPARATOR_FIELD) + && field.getCategory() != UFIELD_CATEGORY_LIST; +} + int32_t FormattedValueStringBuilderImpl::trimBack(int32_t limit) const { return unisets::get(unisets::DEFAULT_IGNORABLES)->spanBack( fString.getCharPtr() + fString.fZero, |