tor-browser

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

formattedval_impl.h (10705B)


      1 // © 2018 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 
      4 #ifndef __FORMVAL_IMPL_H__
      5 #define __FORMVAL_IMPL_H__
      6 
      7 #include "unicode/utypes.h"
      8 #if !UCONFIG_NO_FORMATTING
      9 
     10 // This file contains compliant implementations of FormattedValue which can be
     11 // leveraged by ICU formatters.
     12 //
     13 // Each implementation is defined in its own cpp file in order to split
     14 // dependencies more modularly.
     15 
     16 #include "unicode/formattedvalue.h"
     17 #include "capi_helper.h"
     18 #include "fphdlimp.h"
     19 #include "util.h"
     20 #include "uvectr32.h"
     21 #include "formatted_string_builder.h"
     22 
     23 
     24 /**
     25 * Represents the type of constraint for ConstrainedFieldPosition.
     26 *
     27 * Constraints are used to control the behavior of iteration in FormattedValue.
     28 *
     29 * @internal
     30 */
     31 typedef enum UCFPosConstraintType {
     32    /**
     33     * Represents the lack of a constraint.
     34     *
     35     * This is the value of fConstraint if no "constrain" methods were called.
     36     *
     37     * @internal
     38     */
     39    UCFPOS_CONSTRAINT_NONE = 0,
     40 
     41    /**
     42     * Represents that the field category is constrained.
     43     *
     44     * This is the value of fConstraint if constraintCategory was called.
     45     *
     46     * FormattedValue implementations should not change the field category
     47     * while this constraint is active.
     48     *
     49     * @internal
     50     */
     51    UCFPOS_CONSTRAINT_CATEGORY,
     52 
     53    /**
     54     * Represents that the field and field category are constrained.
     55     *
     56     * This is the value of fConstraint if constraintField was called.
     57     *
     58     * FormattedValue implementations should not change the field or field category
     59     * while this constraint is active.
     60     *
     61     * @internal
     62     */
     63    UCFPOS_CONSTRAINT_FIELD
     64 } UCFPosConstraintType;
     65 
     66 
     67 U_NAMESPACE_BEGIN
     68 
     69 
     70 /**
     71 * Implementation of FormattedValue using FieldPositionHandler to accept fields.
     72 *
     73 * TODO(ICU-20897): This class is unused. If it is not needed when fixing ICU-20897,
     74 * it should be deleted.
     75 */
     76 class FormattedValueFieldPositionIteratorImpl : public UMemory, public FormattedValue {
     77 public:
     78 
     79    /** @param initialFieldCapacity Initially allocate space for this many fields. */
     80    FormattedValueFieldPositionIteratorImpl(int32_t initialFieldCapacity, UErrorCode& status);
     81 
     82    virtual ~FormattedValueFieldPositionIteratorImpl();
     83 
     84    // Implementation of FormattedValue (const):
     85 
     86    UnicodeString toString(UErrorCode& status) const override;
     87    UnicodeString toTempString(UErrorCode& status) const override;
     88    Appendable& appendTo(Appendable& appendable, UErrorCode& status) const override;
     89    UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const override;
     90 
     91    // Additional methods used during construction phase only (non-const):
     92 
     93    FieldPositionIteratorHandler getHandler(UErrorCode& status);
     94    void appendString(UnicodeString string, UErrorCode& status);
     95 
     96    /**
     97     * Computes the spans for duplicated values.
     98     * For example, if the string has fields:
     99     * 
    100     *     ...aa..[b.cc]..d.[bb.e.c]..a..
    101     *
    102     * then the spans will be the bracketed regions.
    103     *
    104     * Assumes that the currently known fields are sorted
    105     * and all in the same category.
    106     */
    107    void addOverlapSpans(UFieldCategory spanCategory, int8_t firstIndex, UErrorCode& status);
    108 
    109    /**
    110     * Sorts the fields: start index first, length second.
    111     */
    112    void sort();
    113 
    114 private:
    115    UnicodeString fString;
    116    UVector32 fFields;
    117 };
    118 
    119 
    120 // Internal struct that must be exported for MSVC
    121 struct U_I18N_API SpanInfo {
    122    UFieldCategory category;
    123    int32_t spanValue;
    124    int32_t start;
    125    int32_t length;
    126 };
    127 
    128 /**
    129 * Implementation of FormattedValue based on FormattedStringBuilder.
    130 *
    131 * The implementation currently revolves around numbers and number fields.
    132 * However, it can be generalized in the future when there is a need.
    133 *
    134 * @author sffc (Shane Carr)
    135 */
    136 // Exported as U_I18N_API_CLASS for tests
    137 class U_I18N_API_CLASS FormattedValueStringBuilderImpl : public UMemory, public FormattedValue {
    138 public:
    139    U_I18N_API FormattedValueStringBuilderImpl(FormattedStringBuilder::Field numericField);
    140 
    141    U_I18N_API virtual ~FormattedValueStringBuilderImpl();
    142 
    143    FormattedValueStringBuilderImpl(FormattedValueStringBuilderImpl&&) = default;
    144    FormattedValueStringBuilderImpl& operator=(FormattedValueStringBuilderImpl&&) = default;
    145 
    146    // Implementation of FormattedValue (const):
    147 
    148    UnicodeString toString(UErrorCode& status) const override;
    149    UnicodeString toTempString(UErrorCode& status) const override;
    150    Appendable& appendTo(Appendable& appendable, UErrorCode& status) const override;
    151    UBool nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const override;
    152 
    153    // Additional helper functions:
    154    U_I18N_API UBool nextFieldPosition(FieldPosition& fp, UErrorCode& status) const;
    155    U_I18N_API void getAllFieldPositions(FieldPositionIteratorHandler& fpih, UErrorCode& status) const;
    156    inline FormattedStringBuilder& getStringRef() {
    157        return fString;
    158    }
    159    inline const FormattedStringBuilder& getStringRef() const {
    160        return fString;
    161    }
    162    void resetString();
    163 
    164    /**
    165     * Adds additional metadata used for span fields.
    166     *
    167     * category: the category to use for the span field.
    168     * spanValue: the value of the span field: index of the list item, for example.
    169     * start: the start position within the string of the span. -1 if unknown.
    170     * length: the length of the span, used to split adjacent fields.
    171     */
    172    void appendSpanInfo(UFieldCategory category, int32_t spanValue, int32_t start, int32_t length, UErrorCode& status);
    173    void prependSpanInfo(UFieldCategory category, int32_t spanValue, int32_t start, int32_t length, UErrorCode& status);
    174 
    175 private:
    176    FormattedStringBuilder fString;
    177    FormattedStringBuilder::Field fNumericField;
    178    MaybeStackArray<SpanInfo, 8> spanIndices;
    179    int32_t spanIndicesCount = 0;
    180 
    181    bool nextPositionImpl(ConstrainedFieldPosition& cfpos, FormattedStringBuilder::Field numericField, UErrorCode& status) const;
    182    static bool isIntOrGroup(FormattedStringBuilder::Field field);
    183    static bool isTrimmable(FormattedStringBuilder::Field field);
    184    int32_t trimBack(int32_t limit) const;
    185    int32_t trimFront(int32_t start) const;
    186 };
    187 
    188 
    189 // C API Helpers for FormattedValue
    190 // Magic number as ASCII == "UFV"
    191 struct UFormattedValueImpl;
    192 typedef IcuCApiHelper<UFormattedValue, UFormattedValueImpl, 0x55465600> UFormattedValueApiHelper;
    193 struct UFormattedValueImpl : public UMemory, public UFormattedValueApiHelper {
    194    // This pointer should be set by the child class.
    195    FormattedValue* fFormattedValue = nullptr;
    196 };
    197 
    198 
    199 /** Boilerplate to check for valid status before dereferencing the fData pointer. */
    200 #define UPRV_FORMATTED_VALUE_METHOD_GUARD(returnExpression) \
    201    if (U_FAILURE(status)) { \
    202        return returnExpression; \
    203    } \
    204    if (fData == nullptr) { \
    205        status = fErrorCode; \
    206        return returnExpression; \
    207    } \
    208 
    209 
    210 /** Implementation of the methods from U_FORMATTED_VALUE_SUBCLASS_AUTO. */
    211 #define UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(Name) \
    212    Name::Name(Name&& src) noexcept \
    213            : fData(src.fData), fErrorCode(src.fErrorCode) { \
    214        src.fData = nullptr; \
    215        src.fErrorCode = U_INVALID_STATE_ERROR; \
    216    } \
    217    Name::~Name() { \
    218        delete fData; \
    219        fData = nullptr; \
    220    } \
    221    Name& Name::operator=(Name&& src) noexcept { \
    222        delete fData; \
    223        fData = src.fData; \
    224        src.fData = nullptr; \
    225        fErrorCode = src.fErrorCode; \
    226        src.fErrorCode = U_INVALID_STATE_ERROR; \
    227        return *this; \
    228    } \
    229    UnicodeString Name::toString(UErrorCode& status) const { \
    230        UPRV_FORMATTED_VALUE_METHOD_GUARD(ICU_Utility::makeBogusString()) \
    231        return fData->toString(status); \
    232    } \
    233    UnicodeString Name::toTempString(UErrorCode& status) const { \
    234        UPRV_FORMATTED_VALUE_METHOD_GUARD(ICU_Utility::makeBogusString()) \
    235        return fData->toTempString(status); \
    236    } \
    237    Appendable& Name::appendTo(Appendable& appendable, UErrorCode& status) const { \
    238        UPRV_FORMATTED_VALUE_METHOD_GUARD(appendable) \
    239        return fData->appendTo(appendable, status); \
    240    } \
    241    UBool Name::nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const { \
    242        UPRV_FORMATTED_VALUE_METHOD_GUARD(false) \
    243        return fData->nextPosition(cfpos, status); \
    244    }
    245 
    246 
    247 /** Like UPRV_FORMATTED_VALUE_CAPI_AUTO_IMPL but without impl type declarations. */
    248 #define UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(CType, ImplType, HelperType, Prefix) \
    249    U_CAPI CType* U_EXPORT2 \
    250    Prefix ## _openResult (UErrorCode* ec) { \
    251        if (U_FAILURE(*ec)) { \
    252            return nullptr; \
    253        } \
    254        ImplType* impl = new ImplType(); \
    255        if (impl == nullptr) { \
    256            *ec = U_MEMORY_ALLOCATION_ERROR; \
    257            return nullptr; \
    258        } \
    259        return static_cast<HelperType*>(impl)->exportForC(); \
    260    } \
    261    U_CAPI const UFormattedValue* U_EXPORT2 \
    262    Prefix ## _resultAsValue (const CType* uresult, UErrorCode* ec) { \
    263        const ImplType* result = HelperType::validate(uresult, *ec); \
    264        if (U_FAILURE(*ec)) { return nullptr; } \
    265        return static_cast<const UFormattedValueApiHelper*>(result)->exportConstForC(); \
    266    } \
    267    U_CAPI void U_EXPORT2 \
    268    Prefix ## _closeResult (CType* uresult) { \
    269        UErrorCode localStatus = U_ZERO_ERROR; \
    270        const ImplType* impl = HelperType::validate(uresult, localStatus); \
    271        delete impl; \
    272    }
    273 
    274 
    275 /**
    276 * Implementation of the standard methods for a UFormattedValue "subclass" C API.
    277 * @param CPPType The public C++ type, like FormattedList
    278 * @param CType The public C type, like UFormattedList
    279 * @param ImplType A name to use for the implementation class
    280 * @param HelperType A name to use for the "mixin" typedef for C API conversion
    281 * @param Prefix The C API prefix, like ulistfmt
    282 * @param MagicNumber A unique 32-bit number to use to identify this type
    283 */
    284 #define UPRV_FORMATTED_VALUE_CAPI_AUTO_IMPL(CPPType, CType, ImplType, HelperType, Prefix, MagicNumber) \
    285    U_NAMESPACE_BEGIN \
    286    class ImplType; \
    287    typedef IcuCApiHelper<CType, ImplType, MagicNumber> HelperType; \
    288    class ImplType : public UFormattedValueImpl, public HelperType { \
    289    public: \
    290        ImplType(); \
    291        ~ImplType(); \
    292        CPPType fImpl; \
    293    }; \
    294    ImplType::ImplType() { \
    295        fFormattedValue = &fImpl; \
    296    } \
    297    ImplType::~ImplType() {} \
    298    U_NAMESPACE_END \
    299    UPRV_FORMATTED_VALUE_CAPI_NO_IMPLTYPE_AUTO_IMPL(CType, ImplType, HelperType, Prefix)
    300 
    301 
    302 U_NAMESPACE_END
    303 
    304 #endif /* #if !UCONFIG_NO_FORMATTING */
    305 #endif // __FORMVAL_IMPL_H__