tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

messageformat2_evaluation.h (8251B)


      1 // © 2024 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 
      4 #include "unicode/utypes.h"
      5 
      6 #ifndef U_HIDE_DEPRECATED_API
      7 
      8 #ifndef MESSAGEFORMAT2_EVALUATION_H
      9 #define MESSAGEFORMAT2_EVALUATION_H
     10 
     11 #if U_SHOW_CPLUSPLUS_API
     12 
     13 /**
     14 * \file
     15 * \brief C++ API: Formats messages using the draft MessageFormat 2.0.
     16 */
     17 #if !UCONFIG_NO_NORMALIZATION
     18 
     19 #if !UCONFIG_NO_FORMATTING
     20 
     21 #if !UCONFIG_NO_MF2
     22 
     23 #include "unicode/messageformat2_arguments.h"
     24 #include "unicode/messageformat2_data_model.h"
     25 #include "unicode/messageformat2_function_registry.h"
     26 #include "messageformat2_errors.h"
     27 
     28 // Auxiliary data structures used during formatting a message
     29 
     30 U_NAMESPACE_BEGIN
     31 
     32 namespace message2 {
     33 
     34    namespace functions {
     35    static constexpr std::u16string_view DATETIME = u"datetime";
     36    static constexpr std::u16string_view DATE = u"date";
     37    static constexpr std::u16string_view TIME = u"time";
     38    static constexpr std::u16string_view NUMBER = u"number";
     39    static constexpr std::u16string_view INTEGER = u"integer";
     40    static constexpr std::u16string_view TEST_FUNCTION = u"test:function";
     41    static constexpr std::u16string_view TEST_FORMAT = u"test:format";
     42    static constexpr std::u16string_view TEST_SELECT = u"test:select";
     43    static constexpr std::u16string_view STRING = u"string";
     44    }
     45 
     46    using namespace data_model;
     47 
     48    // PrioritizedVariant
     49 
     50    // For how this class is used, see the references to (integer, variant) tuples
     51    // in https://github.com/unicode-org/message-format-wg/blob/main/spec/formatting.md#pattern-selection
     52    class PrioritizedVariant : public UObject {
     53    public:
     54        PrioritizedVariant() = default;
     55        PrioritizedVariant(PrioritizedVariant&&) = default;
     56        PrioritizedVariant& operator=(PrioritizedVariant&&) noexcept = default;
     57        UBool operator<(const PrioritizedVariant&) const;
     58        int32_t priority;
     59        /* const */ SelectorKeys keys;
     60        /* const */ Pattern pat;
     61        PrioritizedVariant(uint32_t p,
     62                           const SelectorKeys& k,
     63                           const Pattern& pattern) noexcept : priority(p), keys(k), pat(pattern) {}
     64        virtual ~PrioritizedVariant();
     65    }; // class PrioritizedVariant
     66 
     67    static inline int32_t comparePrioritizedVariants(UElement left, UElement right) {
     68        const PrioritizedVariant& tuple1 = *(static_cast<const PrioritizedVariant*>(left.pointer));
     69        const PrioritizedVariant& tuple2 = *(static_cast<const PrioritizedVariant*>(right.pointer));
     70        if (tuple1 < tuple2) {
     71            return -1;
     72        }
     73        if (tuple1.priority == tuple2.priority) {
     74            return 0;
     75        }
     76        return 1;
     77    }
     78 
     79    // Closures and environments
     80    // -------------------------
     81 
     82    class Environment;
     83 
     84    // A closure represents the right-hand side of a variable
     85    // declaration, along with an environment giving values
     86    // to its free variables
     87    class Closure : public UMemory {
     88    public:
     89        const Expression& getExpr() const {
     90            return expr;
     91        }
     92        const Environment& getEnv() const {
     93            return env;
     94        }
     95        Closure(const Expression& expression, const Environment& environment) : expr(expression), env(environment) {}
     96        Closure(Closure&&) = default;
     97 
     98        virtual ~Closure();
     99    private:
    100 
    101        // An unevaluated expression
    102        const Expression& expr;
    103        // The environment mapping names used in this
    104        // expression to other expressions
    105        const Environment& env;
    106    };
    107 
    108    // An environment is represented as a linked chain of
    109    // non-empty environments, terminating at an empty environment.
    110    // It's searched using linear search.
    111    class Environment : public UMemory {
    112    public:
    113        virtual bool has(const VariableName&) const = 0;
    114        virtual const Closure& lookup(const VariableName&) const = 0;
    115        static Environment* create(UErrorCode&);
    116        static Environment* create(const VariableName&, Closure&&, Environment*, UErrorCode&);
    117        virtual ~Environment();
    118    };
    119 
    120    class NonEmptyEnvironment;
    121    class EmptyEnvironment : public Environment {
    122    public:
    123        EmptyEnvironment() = default;
    124        virtual ~EmptyEnvironment();
    125 
    126    private:
    127        friend class Environment;
    128 
    129        bool has(const VariableName&) const override;
    130        const Closure& lookup(const VariableName&) const override;
    131        static EmptyEnvironment* create(UErrorCode&);
    132        static NonEmptyEnvironment* create(const VariableName&, Closure&&, Environment*, UErrorCode&);
    133    };
    134 
    135    class NonEmptyEnvironment : public Environment {
    136    private:
    137        friend class Environment;
    138 
    139        bool has(const VariableName&) const override;
    140        const Closure& lookup(const VariableName&) const override;
    141        static NonEmptyEnvironment* create(const VariableName&, Closure&&, const Environment*, UErrorCode&);
    142        virtual ~NonEmptyEnvironment();
    143    private:
    144        friend class Environment;
    145 
    146        NonEmptyEnvironment(const VariableName& v, Closure&& c, Environment* e) : var(v), rhs(std::move(c)), parent(e) {}
    147 
    148        // Maps VariableName onto Closure*
    149        // Chain of linked environments
    150        VariableName var;
    151        Closure rhs;
    152        const LocalPointer<Environment> parent;
    153    };
    154 
    155    // The context contains all the information needed to process
    156    // an entire message: arguments, formatter cache, and error list
    157 
    158    class MessageFormatter;
    159 
    160    class MessageContext : public UMemory {
    161    public:
    162        MessageContext(const MessageArguments&, const StaticErrors&, UErrorCode&);
    163 
    164        const Formattable* getGlobal(const VariableName&, UErrorCode&) const;
    165 
    166        // If any errors were set, update `status` accordingly
    167        void checkErrors(UErrorCode& status) const;
    168        DynamicErrors& getErrors() { return errors; }
    169 
    170        virtual ~MessageContext();
    171 
    172    private:
    173 
    174        const MessageArguments& arguments; // External message arguments
    175        // Errors accumulated during parsing/formatting
    176        DynamicErrors errors;
    177 
    178    }; // class MessageContext
    179 
    180    // InternalValue
    181    // ----------------
    182 
    183    class InternalValue : public UObject {
    184    public:
    185        const FunctionName& getFunctionName() const { return name; }
    186        bool canSelect() const { return selector != nullptr; }
    187        const Selector* getSelector(UErrorCode&) const;
    188        FormattedPlaceholder forceFormatting(DynamicErrors& errs,
    189                                             UErrorCode& errorCode);
    190        void forceSelection(DynamicErrors& errs,
    191                            const UnicodeString* keys,
    192                            int32_t keysLen,
    193                            UnicodeString* prefs,
    194                            int32_t& prefsLen,
    195                            UErrorCode& errorCode);
    196        // Needs to be deep-copyable and movable
    197        virtual ~InternalValue();
    198        InternalValue(FormattedPlaceholder&&);
    199        // Formatter and selector may be null
    200        InternalValue(InternalValue*, FunctionOptions&&, const FunctionName&, const Formatter*,
    201                      const Selector*);
    202        const UnicodeString& getFallback() const;
    203        bool isFallback() const;
    204        bool hasNullOperand() const;
    205        // Can't be used anymore after calling this
    206        FormattedPlaceholder takeArgument(UErrorCode& errorCode);
    207        InternalValue(InternalValue&& other) { *this = std::move(other); }
    208        InternalValue& operator=(InternalValue&& other) noexcept;
    209    private:
    210        // InternalValue is owned (if present)
    211        std::variant<InternalValue*, FormattedPlaceholder> argument;
    212        FunctionOptions options;
    213        FunctionName name;
    214        const Selector* selector; // May be null
    215        const Formatter* formatter; // May be null, but one or the other should be non-null unless argument is a FormattedPlaceholder
    216        bool checkSelectOption() const;
    217    }; // class InternalValue
    218 
    219 } // namespace message2
    220 
    221 U_NAMESPACE_END
    222 
    223 #endif /* #if !UCONFIG_NO_MF2 */
    224 
    225 #endif /* #if !UCONFIG_NO_FORMATTING */
    226 
    227 #endif /* #if !UCONFIG_NO_NORMALIZATION */
    228 
    229 #endif /* U_SHOW_CPLUSPLUS_API */
    230 
    231 #endif // MESSAGEFORMAT2_EVALUATION_H
    232 
    233 #endif // U_HIDE_DEPRECATED_API
    234 // eof