Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/intl/icu/source/i18n/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 13 kB image not shown  

Quelle  formattedval_sbimpl.cpp   Sprache: C

 
// © 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 "unicode/ustring.h"
#include "formattedval_impl.h"
#include "number_types.h"
#include "formatted_string_builder.h"
#include "number_utils.h"
#include "static_unicode_sets.h"
#include "unicode/listformatter.h"

U_NAMESPACE_BEGIN


typedef FormattedStringBuilder::Field Field;


FormattedValueStringBuilderImpl::FormattedValueStringBuilderImpl(Field numericField)
        : fNumericField(numericField) {
}

FormattedValueStringBuilderImpl::~FormattedValueStringBuilderImpl() {
}


UnicodeString FormattedValueStringBuilderImpl::toString(UErrorCode&) const {
    return fString.toUnicodeString();
}

UnicodeString FormattedValueStringBuilderImpl::toTempString(UErrorCode&) const {
    return fString.toTempUnicodeString();
}

Appendable& FormattedValueStringBuilderImpl::appendTo(Appendable& appendable, UErrorCode&) const {
    appendable.appendString(fString.chars(), fString.length());
    return appendable;
}

UBool FormattedValueStringBuilderImpl::nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const {
    // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
    return nextPositionImpl(cfpos, fNumericField, status) ? true : false;
}

UBool FormattedValueStringBuilderImpl::nextFieldPosition(FieldPosition& fp, UErrorCode& status) const {
    int32_t rawField = fp.getField();

    if (rawField == FieldPosition::DONT_CARE) {
        return false;
    }

    if (rawField < 0 || rawField >= UNUM_FIELD_COUNT) {
        status = U_ILLEGAL_ARGUMENT_ERROR;
        return false;
    }

    ConstrainedFieldPosition cfpos;
    cfpos.constrainField(UFIELD_CATEGORY_NUMBER, rawField);
    cfpos.setState(UFIELD_CATEGORY_NUMBER, rawField, fp.getBeginIndex(), fp.getEndIndex());
    if (nextPositionImpl(cfpos, kUndefinedField, status)) {
        fp.setBeginIndex(cfpos.getStart());
        fp.setEndIndex(cfpos.getLimit());
        return true;
    }

    // Special case: fraction should start after integer if fraction is not present
    if (rawField == UNUM_FRACTION_FIELD && fp.getEndIndex() == 0) {
        bool inside = false;
        int32_t i = fString.fZero;
        for (; i < fString.fZero + fString.fLength; i++) {
            if (isIntOrGroup(fString.getFieldPtr()[i]) || fString.getFieldPtr()[i] == Field(UFIELD_CATEGORY_NUMBER, UNUM_DECIMAL_SEPARATOR_FIELD)) {
                inside = true;
            } else if (inside) {
                break;
            }
        }
        fp.setBeginIndex(i - fString.fZero);
        fp.setEndIndex(i - fString.fZero);
    }

    return false;
}

void FormattedValueStringBuilderImpl::getAllFieldPositions(FieldPositionIteratorHandler& fpih,
                                               UErrorCode& status) const {
    ConstrainedFieldPosition cfpos;
    while (nextPositionImpl(cfpos, kUndefinedField, status)) {
        fpih.addAttribute(cfpos.getField(), cfpos.getStart(), cfpos.getLimit());
    }
}

void FormattedValueStringBuilderImpl::resetString() {
    fString.clear();
    spanIndicesCount = 0;
}

// Signal the end of the string using a field that doesn't exist and that is
// different from kUndefinedField, which is used for "null field".
static constexpr Field kEndField = Field(0xf, 0xf);

bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition&&nbsp;cfpos, Field numericField, UErrorCode& /*status*/) const {
    int32_t fieldStart = -1;
    Field currField = kUndefinedField;
    bool prevIsSpan = false;
    int32_t nextSpanStart = -1;
    if (spanIndicesCount > 0) {
        int64_t si = cfpos.getInt64IterationContext();
        U_ASSERT(si <= spanIndicesCount);
        if (si < spanIndicesCount) {
            nextSpanStart = spanIndices[si].start;
        }
        if (si > 0) {
            prevIsSpan = cfpos.getCategory() == spanIndices[si-1].category
                && cfpos.getField() == spanIndices[si-1].spanValue;
        }
    }
    bool prevIsNumeric = false;
    if (numericField != kUndefinedField) {
        prevIsNumeric = cfpos.getCategory() == numericField.getCategory()
            && cfpos.getField() == numericField.getField();
    }
    bool prevIsInteger = cfpos.getCategory() == UFIELD_CATEGORY_NUMBER
        && cfpos.getField() == UNUM_INTEGER_FIELD;

    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;
                // Grouping separators can be whitespace; don't throw them out!
                if (isTrimmable(currField)) {
                    end = trimBack(i - fString.fZero);
                }
                if (end <= fieldStart) {
                    // Entire field position is ignorable; skip.
                    fieldStart = -1;
                    currField = kUndefinedField;
                    i--;  // look at this index again
                    continue;
                }
                int32_t start = fieldStart;
                if (isTrimmable(currField)) {
                    start = trimFront(start);
                }
                cfpos.setState(currField.getCategory(), currField.getField(), start, end);
                return true;
            }
            continue;
        }
        // Special case: emit normalField if we are pointing at the end of spanField.
        if (i > fString.fZero && prevIsSpan) {
            int64_t si = cfpos.getInt64IterationContext() - 1;
            U_ASSERT(si >= 0);
            int32_t previ = i - spanIndices[si].length;
            U_ASSERT(previ >= fString.fZero);
            Field prevField = fString.getFieldPtr()[previ];
            if (prevField == Field(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD)) {
                // Special handling for ULISTFMT_ELEMENT_FIELD
                if (cfpos.matchesField(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD)) {
                    fieldStart = i - fString.fZero - spanIndices[si].length;
                    int32_t end = fieldStart + spanIndices[si].length;
                    cfpos.setState(
                        UFIELD_CATEGORY_LIST,
                        ULISTFMT_ELEMENT_FIELD,
                        fieldStart,
                        end);
                    return true;
                } else {
                    prevIsSpan = false;
                }
            } else {
                // Re-wind, since there may be multiple fields in the span.
                i = previ;
                _field = prevField;
            }
        }
        // Special case: coalesce the INTEGER if we are pointing at the end of the INTEGER.
        if (cfpos.matchesField(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD)
                && i > fString.fZero
                && !prevIsInteger
                && !prevIsNumeric
                && isIntOrGroup(fString.getFieldPtr()[i - 1])
                && !isIntOrGroup(_field)) {
            int j = i - 1;
            for (; j >= fString.fZero && isIntOrGroup(fString.getFieldPtr()[j]); j--) {}
            cfpos.setState(
                UFIELD_CATEGORY_NUMBER,
                UNUM_INTEGER_FIELD,
                j - fString.fZero + 1,
                i - fString.fZero);
            return true;
        }
        // Special case: coalesce NUMERIC if we are pointing at the end of the NUMERIC.
        if (numericField != kUndefinedField
                && cfpos.matchesField(numericField.getCategory(), numericField.getField())
                && i > fString.fZero
                && !prevIsNumeric
                && fString.getFieldPtr()[i - 1].isNumeric()
                && !_field.isNumeric()) {
            // 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(),
                numericField.getField(),
                j - fString.fZero + 1,
                i - fString.fZero);
            return true;
        }
        // Check for span field
        if (!prevIsSpan && (
                _field == Field(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD) ||
                i - fString.fZero == nextSpanStart)) {
            int64_t si = cfpos.getInt64IterationContext();
            if (si >= spanIndicesCount) {
                break;
            }
            UFieldCategory spanCategory = spanIndices[si].category;
            int32_t spanValue = spanIndices[si].spanValue;
            int32_t length = spanIndices[si].length;
            cfpos.setInt64IterationContext(si + 1);
            if (si + 1 < spanIndicesCount) {
                nextSpanStart = spanIndices[si + 1].start;
            }
            if (length == 0) {
                // ICU-21871: Don't return fields on empty spans
                i--;
                continue;
            }
            if (cfpos.matchesField(spanCategory, spanValue)) {
                fieldStart = i - fString.fZero;
                int32_t end = fieldStart + length;
                cfpos.setState(
                    spanCategory,
                    spanValue,
                    fieldStart,
                    end);
                return true;
            } else if (_field == Field(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD)) {
                // Special handling for ULISTFMT_ELEMENT_FIELD
                if (cfpos.matchesField(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD)) {
                    fieldStart = i - fString.fZero;
                    int32_t end = fieldStart + length;
                    cfpos.setState(
                        UFIELD_CATEGORY_LIST,
                        ULISTFMT_ELEMENT_FIELD,
                        fieldStart,
                        end);
                    return true;
                } else {
                    // Failed to match; jump ahead
                    i += length - 1;
                    // goto loopend
                }
            }
        }
        // Special case: skip over INTEGER; will be coalesced later.
        else if (_field == Field(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD)) {
            _field = kUndefinedField;
        }
        // No field starting at this position.
        else if (_field.isUndefined() || _field == kEndField) {
            // goto loopend
        }
        // No SpanField
        else if (cfpos.matchesField(_field.getCategory(), _field.getField())) {
            fieldStart = i - fString.fZero;
            currField = _field;
        }
        // loopend:
        prevIsSpan = false;
        prevIsNumeric = false;
        prevIsInteger = false;
    }

    U_ASSERT(currField == kUndefinedField);
    // Always set the position to the end so that we don't revisit previous sections
    cfpos.setState(
        cfpos.getCategory(),
        cfpos.getField(),
        fString.fLength,
        fString.fLength);
    return false;
}

void FormattedValueStringBuilderImpl::appendSpanInfo(UFieldCategory category, int32_t spanValue, int32_t start, int32_t length, UErrorCode& status) {
    if (U_FAILURE(status)) { return; }
    U_ASSERT(spanIndices.getCapacity() >= spanIndicesCount);
    if (spanIndices.getCapacity() == spanIndicesCount) {
        if (!spanIndices.resize(spanIndicesCount * 2, spanIndicesCount)) {
            status = U_MEMORY_ALLOCATION_ERROR;
            return;
        }
    }
    spanIndices[spanIndicesCount] = {category, spanValue, start, length};
    spanIndicesCount++;
}

void FormattedValueStringBuilderImpl::prependSpanInfo(UFieldCategory category, int32_t spanValue, int32_t start, int32_t length, UErrorCode& status) {
    if (U_FAILURE(status)) { return; }
    U_ASSERT(spanIndices.getCapacity() >= spanIndicesCount);
    if (spanIndices.getCapacity() == spanIndicesCount) {
        if (!spanIndices.resize(spanIndicesCount * 2, spanIndicesCount)) {
            status = U_MEMORY_ALLOCATION_ERROR;
            return;
        }
    }
    for (int32_t i = spanIndicesCount - 1; i >= 0; i--) {
        spanIndices[i+1] = spanIndices[i];
    }
    spanIndices[0] = {category, spanValue, start, length};
    spanIndicesCount++;
}

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,
        limit,
        USET_SPAN_CONTAINED);
}

int32_t FormattedValueStringBuilderImpl::trimFront(int32_t start) const {
    return start + unisets::get(unisets::DEFAULT_IGNORABLES)->span(
        fString.getCharPtr() + fString.fZero + start,
        fString.fLength - start,
        USET_SPAN_CONTAINED);
}


U_NAMESPACE_END

#endif /* #if !UCONFIG_NO_FORMATTING */

Messung V0.5
C=91 H=91 G=90

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.