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  messageformat2_formatter.cpp   Sprache: C

 
// © 2024 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#if !UCONFIG_NO_MF2

#include "unicode/messageformat2.h"
#include "messageformat2_allocation.h"
#include "messageformat2_checker.h"
#include "messageformat2_errors.h"
#include "messageformat2_evaluation.h"
#include "messageformat2_function_registry_internal.h"
#include "messageformat2_macros.h"
#include "messageformat2_parser.h"
#include "messageformat2_serializer.h"
#include "uvector.h" // U_ASSERT

U_NAMESPACE_BEGIN

namespace message2 {

    // MessageFormatter::Builder

    // -------------------------------------
    // Creates a MessageFormat instance based on the pattern.

    void MessageFormatter::Builder::clearState() {
        normalizedInput.remove();
        delete errors;
        errors = nullptr;
    }

    MessageFormatter::Builder& MessageFormatter::Builder::setPattern(const UnicodeString& pat,
                                                                     UParseError& parseError,
                                                                     UErrorCode& errorCode) {
        clearState();
        // Create errors
        errors = create<StaticErrors>(StaticErrors(errorCode), errorCode);
        THIS_ON_ERROR(errorCode);

        // Parse the pattern
        MFDataModel::Builder tree(errorCode);
        Parser(pat, tree, *errors, normalizedInput).parse(parseError, errorCode);

        // Fail on syntax errors
        if (errors->hasSyntaxError()) {
            errors->checkErrors(errorCode);
            // Check that the checkErrors() method set the error code
            U_ASSERT(U_FAILURE(errorCode));
        }

        // Build the data model based on what was parsed
        dataModel = tree.build(errorCode);
        hasDataModel = true;
        hasPattern = true;
        pattern = pat;

        return *this;
    }

    // Precondition: `reg` is non-null
    // Does not adopt `reg`
    MessageFormatter::Builder& MessageFormatter::Builder::setFunctionRegistry(const MFFunctionRegistry& reg) {
        customMFFunctionRegistry = ®
        return *this;
    }

    MessageFormatter::Builder& MessageFormatter::Builder::setLocale(const Locale&&nbsp;loc) {
        locale = loc;
        return *this;
    }

    MessageFormatter::Builder& MessageFormatter::Builder::setDataModel(MFDataModel&& newDataModel) {
        clearState();
        hasPattern = false;
        hasDataModel = true;
        dataModel = std::move(newDataModel);

        return *this;
    }

    MessageFormatter::Builder&
        MessageFormatter::Builder::setErrorHandlingBehavior(
           MessageFormatter::UMFErrorHandlingBehavior type) {
               signalErrors = type == U_MF_STRICT;
               return *this;
    }

    /*
      This build() method is non-destructive, which entails the risk that
      its borrowed MFFunctionRegistry and (if the setDataModel() method was called)
      MFDataModel pointers could become invalidated.
    */

    MessageFormatter MessageFormatter::Builder::build(UErrorCode& errorCode) const {
        return MessageFormatter(*this, errorCode);
    }

    MessageFormatter::Builder::Builder(UErrorCode& errorCode) : locale(Locale::getDefault()), customMFFunctionRegistry(nullptr) {
        // Initialize errors
        errors = new StaticErrors(errorCode);
        CHECK_ERROR(errorCode);
        if (errors == nullptr) {
            errorCode = U_MEMORY_ALLOCATION_ERROR;
        }
    }

    MessageFormatter::Builder::~Builder() {
        if (errors != nullptr) {
            delete errors;
            errors = nullptr;
        }
    }

    // MessageFormatter

    MessageFormatter::MessageFormatter(const MessageFormatter::Builder& builder, UErrorCode &success) : locale(builder.locale), customMFFunctionRegistry(builder.customMFFunctionRegistry) {
        CHECK_ERROR(success);

        // Set up the standard function registry
        MFFunctionRegistry::Builder standardFunctionsBuilder(success);

        FormatterFactory* dateTime = StandardFunctions::DateTimeFactory::dateTime(success);
        FormatterFactory* date = StandardFunctions::DateTimeFactory::date(success);
        FormatterFactory* time = StandardFunctions::DateTimeFactory::time(success);
        FormatterFactory* number = new StandardFunctions::NumberFactory();
        FormatterFactory* integer = new StandardFunctions::IntegerFactory();
        standardFunctionsBuilder.adoptFormatter(FunctionName(UnicodeString("datetime")), dateTime, success)
            .adoptFormatter(FunctionName(UnicodeString("date")), date, success)
            .adoptFormatter(FunctionName(UnicodeString("time")), time, success)
            .adoptFormatter(FunctionName(UnicodeString("number")), number, success)
            .adoptFormatter(FunctionName(UnicodeString("integer")), integer, success)
            .adoptSelector(FunctionName(UnicodeString("number")), new StandardFunctions::PluralFactory(UPLURAL_TYPE_CARDINAL), success)
            .adoptSelector(FunctionName(UnicodeString("integer")), new StandardFunctions::PluralFactory(StandardFunctions::PluralFactory::integer()), success)
            .adoptSelector(FunctionName(UnicodeString("string")), new StandardFunctions::TextFactory(), success);
        CHECK_ERROR(success);
        standardMFFunctionRegistry = standardFunctionsBuilder.build();
        CHECK_ERROR(success);
        standardMFFunctionRegistry.checkStandard();

        normalizedInput = builder.normalizedInput;
        signalErrors = builder.signalErrors;

        // Build data model
        // First, check that there is a data model
        // (which might have been set by setDataModel(), or to
        // the data model parsed from the pattern by setPattern())

        if (!builder.hasDataModel) {
            success = U_INVALID_STATE_ERROR;
            return;
        }

        dataModel = builder.dataModel;
        if (builder.errors != nullptr) {
            errors = new StaticErrors(*builder.errors, success);
        } else {
            // Initialize errors
            LocalPointer<StaticErrors> errorsNew(new StaticErrors(success));
            CHECK_ERROR(success);
            errors = errorsNew.orphan();
        }

        // Note: we currently evaluate variables lazily,
        // without memoization. This call is still necessary
        // to check out-of-scope uses of local variables in
        // right-hand sides (unresolved variable errors can
        // only be checked when arguments are known)

        // Check for resolution errors
        Checker(dataModel, *errors).check(success);
    }

    void MessageFormatter::cleanup() noexcept {
        if (errors != nullptr) {
            delete errors;
            errors = nullptr;
        }
    }

    MessageFormatter& MessageFormatter::operator=(MessageFormatter&& other) noexcept {
        cleanup();

        locale = std::move(other.locale);
        standardMFFunctionRegistry = std::move(other.standardMFFunctionRegistry);
        customMFFunctionRegistry = other.customMFFunctionRegistry;
        dataModel = std::move(other.dataModel);
        normalizedInput = std::move(other.normalizedInput);
        signalErrors = other.signalErrors;
        errors = other.errors;
        other.errors = nullptr;
        return *this;
    }

    const MFDataModel& MessageFormatter::getDataModel() const { return dataModel; }

    UnicodeString MessageFormatter::getPattern() const {
        // Converts the current data model back to a string
        UnicodeString result;
        Serializer serializer(getDataModel(), result);
        serializer.serialize();
        return result;
    }

    // Precondition: custom function registry exists
    const MFFunctionRegistry& MessageFormatter::getCustomMFFunctionRegistry() const {
        U_ASSERT(hasCustomMFFunctionRegistry());
        return *customMFFunctionRegistry;
    }

    MessageFormatter::~MessageFormatter() {
        cleanup();
    }

    // Selector and formatter lookup
    // -----------------------------

    // Postcondition: selector != nullptr || U_FAILURE(status)
    Selector* MessageFormatter::getSelector(MessageContext& context, const FunctionName& functionName, UErrorCode& status) const {
        NULL_ON_ERROR(status);
        U_ASSERT(isSelector(functionName));

        const SelectorFactory* selectorFactory = lookupSelectorFactory(context, functionName, status);
        NULL_ON_ERROR(status);
        if (selectorFactory == nullptr) {
            status = U_MEMORY_ALLOCATION_ERROR;
            return nullptr;
        }
        // Create a specific instance of the selector
        auto result = selectorFactory->createSelector(getLocale(), status);
        NULL_ON_ERROR(status);
        return result;
    }

    // Returns an owned pointer
    Formatter* MessageFormatter::getFormatter(const FunctionName& functionName, UErrorCode& status) const {
        NULL_ON_ERROR(status);

        // Create the formatter

        // First, look up the formatter factory for this function
        FormatterFactory* formatterFactory = lookupFormatterFactory(functionName, status);
        NULL_ON_ERROR(status);

        U_ASSERT(formatterFactory != nullptr);

        // Create a specific instance of the formatter
        Formatter* formatter = formatterFactory->createFormatter(locale, status);
        NULL_ON_ERROR(status);
        if (formatter == nullptr) {
            status = U_MEMORY_ALLOCATION_ERROR;
            return nullptr;
        }
        return formatter;
    }

    bool MessageFormatter::getDefaultFormatterNameByType(const UnicodeString& type, FunctionName& name) const {
        U_ASSERT(hasCustomMFFunctionRegistry());
        const MFFunctionRegistry& reg = getCustomMFFunctionRegistry();
        return reg.getDefaultFormatterNameByType(type, name);
    }

    // ---------------------------------------------------
    // Function registry

    bool MessageFormatter::isBuiltInSelector(const FunctionName& functionName) const {
        return standardMFFunctionRegistry.hasSelector(functionName);
    }

    bool MessageFormatter::isBuiltInFormatter(const FunctionName& functionName) const {
        return standardMFFunctionRegistry.hasFormatter(functionName);
    }

    // https://github.com/unicode-org/message-format-wg/issues/409
    // Unknown function = unknown function error
    // Formatter used as selector  = selector error
    // Selector used as formatter = formatting error
    const SelectorFactory* MessageFormatter::lookupSelectorFactory(MessageContext& context, const FunctionName& functionName, UErrorCode& status) const {
        DynamicErrors& err = context.getErrors();

        if (isBuiltInSelector(functionName)) {
            return standardMFFunctionRegistry.getSelector(functionName);
        }
        if (isBuiltInFormatter(functionName)) {
            err.setSelectorError(functionName, status);
            return nullptr;
        }
        if (hasCustomMFFunctionRegistry()) {
            const MFFunctionRegistry& customMFFunctionRegistry = getCustomMFFunctionRegistry();
            const SelectorFactory* selectorFactory = customMFFunctionRegistry.getSelector(functionName);
            if (selectorFactory != nullptr) {
                return selectorFactory;
            }
            if (customMFFunctionRegistry.getFormatter(functionName) != nullptr) {
                err.setSelectorError(functionName, status);
                return nullptr;
            }
        }
        // Either there is no custom function registry and the function
        // isn't built-in, or the function doesn't exist in either the built-in
        // or custom registry.
        // Unknown function error
        err.setUnknownFunction(functionName, status);
        return nullptr;
    }

    FormatterFactory* MessageFormatter::lookupFormatterFactory(const FunctionName& functionName,
                                                               UErrorCode& status) const {
        NULL_ON_ERROR(status);

        if (isBuiltInFormatter(functionName)) {
            return standardMFFunctionRegistry.getFormatter(functionName);
        }
        if (isBuiltInSelector(functionName)) {
            status = U_MF_FORMATTING_ERROR;
            return nullptr;
        }
        if (hasCustomMFFunctionRegistry()) {
            const MFFunctionRegistry& customMFFunctionRegistry = getCustomMFFunctionRegistry();
            FormatterFactory* formatterFactory = customMFFunctionRegistry.getFormatter(functionName);
            if (formatterFactory != nullptr) {
                return formatterFactory;
            }
            if (customMFFunctionRegistry.getSelector(functionName) != nullptr) {
                status = U_MF_FORMATTING_ERROR;
                return nullptr;
            }
        }
        // Either there is no custom function registry and the function
        // isn't built-in, or the function doesn't exist in either the built-in
        // or custom registry.
        // Unknown function error
        status = U_MF_UNKNOWN_FUNCTION_ERROR;
        return nullptr;
    }

    bool MessageFormatter::isCustomFormatter(const FunctionName& fn) const {
        return hasCustomMFFunctionRegistry() && getCustomMFFunctionRegistry().getFormatter(fn) != nullptr;
    }


    bool MessageFormatter::isCustomSelector(const FunctionName& fn) const {
        return hasCustomMFFunctionRegistry() && getCustomMFFunctionRegistry().getSelector(fn) != nullptr;
    }

// namespace message2

U_NAMESPACE_END

#endif /* #if !UCONFIG_NO_MF2 */

#endif /* #if !UCONFIG_NO_FORMATTING */

Messung V0.5
C=85 H=100 G=92

¤ Dauer der Verarbeitung: 0.19 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.