// © 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(cfpos.getInt64IterationContext()); for (; i < numFields; i++) { UFieldCategory category = static_cast(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 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 */