diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
commit | 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch) | |
tree | a31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /intl/icu/source/i18n/formattedval_iterimpl.cpp | |
parent | Initial commit. (diff) | |
download | firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip |
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'intl/icu/source/i18n/formattedval_iterimpl.cpp')
-rw-r--r-- | intl/icu/source/i18n/formattedval_iterimpl.cpp | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/intl/icu/source/i18n/formattedval_iterimpl.cpp b/intl/icu/source/i18n/formattedval_iterimpl.cpp new file mode 100644 index 0000000000..ec770e2191 --- /dev/null +++ b/intl/icu/source/i18n/formattedval_iterimpl.cpp @@ -0,0 +1,176 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +// This file contains one implementation of FormattedValue. +// Other independent implementations should go into their own cpp file for +// better dependency modularization. + +#include "formattedval_impl.h" +#include "putilimp.h" + +U_NAMESPACE_BEGIN + + +FormattedValueFieldPositionIteratorImpl::FormattedValueFieldPositionIteratorImpl( + int32_t initialFieldCapacity, + UErrorCode& status) + : fFields(initialFieldCapacity * 4, status) { +} + +FormattedValueFieldPositionIteratorImpl::~FormattedValueFieldPositionIteratorImpl() = default; + +UnicodeString FormattedValueFieldPositionIteratorImpl::toString( + UErrorCode&) const { + return fString; +} + +UnicodeString FormattedValueFieldPositionIteratorImpl::toTempString( + UErrorCode&) const { + // The alias must point to memory owned by this object; + // fastCopyFrom doesn't do this when using a stack buffer. + return UnicodeString(true, fString.getBuffer(), fString.length()); +} + +Appendable& FormattedValueFieldPositionIteratorImpl::appendTo( + Appendable& appendable, + UErrorCode&) const { + appendable.appendString(fString.getBuffer(), fString.length()); + return appendable; +} + +UBool FormattedValueFieldPositionIteratorImpl::nextPosition( + ConstrainedFieldPosition& cfpos, + UErrorCode&) const { + U_ASSERT(fFields.size() % 4 == 0); + int32_t numFields = fFields.size() / 4; + int32_t i = static_cast<int32_t>(cfpos.getInt64IterationContext()); + for (; i < numFields; i++) { + UFieldCategory category = static_cast<UFieldCategory>(fFields.elementAti(i * 4)); + int32_t field = fFields.elementAti(i * 4 + 1); + if (cfpos.matchesField(category, field)) { + int32_t start = fFields.elementAti(i * 4 + 2); + int32_t limit = fFields.elementAti(i * 4 + 3); + cfpos.setState(category, field, start, limit); + break; + } + } + cfpos.setInt64IterationContext(i == numFields ? i : i + 1); + return i < numFields; +} + + +FieldPositionIteratorHandler FormattedValueFieldPositionIteratorImpl::getHandler( + UErrorCode& status) { + return FieldPositionIteratorHandler(&fFields, status); +} + +void FormattedValueFieldPositionIteratorImpl::appendString( + UnicodeString string, + UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } + fString.append(string); + // Make the string NUL-terminated + if (fString.getTerminatedBuffer() == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } +} + + +void FormattedValueFieldPositionIteratorImpl::addOverlapSpans( + UFieldCategory spanCategory, + int8_t firstIndex, + UErrorCode& status) { + // In order to avoid fancy data structures, this is an O(N^2) algorithm, + // which should be fine for all real-life applications of this function. + int32_t s1a = INT32_MAX; + int32_t s1b = 0; + int32_t s2a = INT32_MAX; + int32_t s2b = 0; + int32_t numFields = fFields.size() / 4; + for (int32_t i = 0; i<numFields; i++) { + int32_t field1 = fFields.elementAti(i * 4 + 1); + for (int32_t j = i + 1; j<numFields; j++) { + int32_t field2 = fFields.elementAti(j * 4 + 1); + if (field1 != field2) { + continue; + } + // Found a duplicate + s1a = uprv_min(s1a, fFields.elementAti(i * 4 + 2)); + s1b = uprv_max(s1b, fFields.elementAti(i * 4 + 3)); + s2a = uprv_min(s2a, fFields.elementAti(j * 4 + 2)); + s2b = uprv_max(s2b, fFields.elementAti(j * 4 + 3)); + break; + } + } + if (s1a != INT32_MAX) { + // Success: add the two span fields + fFields.addElement(spanCategory, status); + fFields.addElement(firstIndex, status); + fFields.addElement(s1a, status); + fFields.addElement(s1b, status); + fFields.addElement(spanCategory, status); + fFields.addElement(1 - firstIndex, status); + fFields.addElement(s2a, status); + fFields.addElement(s2b, status); + } +} + + +void FormattedValueFieldPositionIteratorImpl::sort() { + // Use bubble sort, O(N^2) but easy and no fancy data structures. + int32_t numFields = fFields.size() / 4; + while (true) { + bool isSorted = true; + for (int32_t i=0; i<numFields-1; i++) { + int32_t categ1 = fFields.elementAti(i*4 + 0); + int32_t field1 = fFields.elementAti(i*4 + 1); + int32_t start1 = fFields.elementAti(i*4 + 2); + int32_t limit1 = fFields.elementAti(i*4 + 3); + int32_t categ2 = fFields.elementAti(i*4 + 4); + int32_t field2 = fFields.elementAti(i*4 + 5); + int32_t start2 = fFields.elementAti(i*4 + 6); + int32_t limit2 = fFields.elementAti(i*4 + 7); + int64_t comparison = 0; + if (start1 != start2) { + // Higher start index -> higher rank + comparison = start2 - start1; + } else if (limit1 != limit2) { + // Higher length (end index) -> lower rank + comparison = limit1 - limit2; + } else if (categ1 != categ2) { + // Higher field category -> lower rank + comparison = categ1 - categ2; + } else if (field1 != field2) { + // Higher field -> higher rank + comparison = field2 - field1; + } + if (comparison < 0) { + // Perform a swap + isSorted = false; + fFields.setElementAt(categ2, i*4 + 0); + fFields.setElementAt(field2, i*4 + 1); + fFields.setElementAt(start2, i*4 + 2); + fFields.setElementAt(limit2, i*4 + 3); + fFields.setElementAt(categ1, i*4 + 4); + fFields.setElementAt(field1, i*4 + 5); + fFields.setElementAt(start1, i*4 + 6); + fFields.setElementAt(limit1, i*4 + 7); + } + } + if (isSorted) { + break; + } + } +} + + +U_NAMESPACE_END + +#endif /* #if !UCONFIG_NO_FORMATTING */ |