tor-browser

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

selfmt.cpp (5824B)


      1 // © 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /********************************************************************
      4 * COPYRIGHT:
      5 * Copyright (c) 1997-2012, International Business Machines Corporation and
      6 * others. All Rights Reserved.
      7 * Copyright (C) 2010 , Yahoo! Inc.
      8 ********************************************************************
      9 *
     10 * File SELFMT.CPP
     11 *
     12 * Modification History:
     13 *
     14 *   Date        Name        Description
     15 *   11/11/09    kirtig      Finished first cut of implementation.
     16 *   11/16/09    kirtig      Improved version
     17 ********************************************************************/
     18 
     19 #include "utypeinfo.h"  // for 'typeid' to work
     20 
     21 #include "unicode/messagepattern.h"
     22 #include "unicode/rbnf.h"
     23 #include "unicode/selfmt.h"
     24 #include "unicode/uchar.h"
     25 #include "unicode/ucnv_err.h"
     26 #include "unicode/umsg.h"
     27 #include "unicode/ustring.h"
     28 #include "unicode/utypes.h"
     29 #include "cmemory.h"
     30 #include "messageimpl.h"
     31 #include "patternprops.h"
     32 #include "selfmtimpl.h"
     33 #include "uassert.h"
     34 #include "ustrfmt.h"
     35 #include "util.h"
     36 #include "uvector.h"
     37 
     38 #if !UCONFIG_NO_FORMATTING
     39 
     40 U_NAMESPACE_BEGIN
     41 
     42 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SelectFormat)
     43 
     44 static const char16_t SELECT_KEYWORD_OTHER[] = {LOW_O, LOW_T, LOW_H, LOW_E, LOW_R, 0};
     45 
     46 SelectFormat::SelectFormat(const UnicodeString& pat,
     47                           UErrorCode& status) : msgPattern(status) {
     48   applyPattern(pat, status);
     49 }
     50 
     51 SelectFormat::SelectFormat(const SelectFormat& other) : Format(other),
     52                                                        msgPattern(other.msgPattern) {
     53 }
     54 
     55 SelectFormat::~SelectFormat() {
     56 }
     57 
     58 void
     59 SelectFormat::applyPattern(const UnicodeString& newPattern, UErrorCode& status) {
     60    if (U_FAILURE(status)) {
     61      return;
     62    }
     63 
     64    msgPattern.parseSelectStyle(newPattern, nullptr, status);
     65    if (U_FAILURE(status)) {
     66        msgPattern.clear();
     67    }
     68 }
     69 
     70 UnicodeString&
     71 SelectFormat::format(const Formattable& obj,
     72                   UnicodeString& appendTo,
     73                   FieldPosition& pos,
     74                   UErrorCode& status) const
     75 {
     76    if (U_FAILURE(status)) {
     77        return appendTo;
     78    }
     79    if (obj.getType() == Formattable::kString) {
     80        return format(obj.getString(status), appendTo, pos, status);
     81    } else {
     82        status = U_ILLEGAL_ARGUMENT_ERROR;
     83        return appendTo;
     84    }
     85 }
     86 
     87 UnicodeString&
     88 SelectFormat::format(const UnicodeString& keyword,
     89                     UnicodeString& appendTo,
     90                     FieldPosition& /*pos */,
     91                     UErrorCode& status) const {
     92    if (U_FAILURE(status)) {
     93        return appendTo;
     94    }
     95    // Check for the validity of the keyword
     96    if (!PatternProps::isIdentifier(keyword.getBuffer(), keyword.length())) {
     97        status = U_ILLEGAL_ARGUMENT_ERROR;  // Invalid formatting argument.
     98    }
     99    if (msgPattern.countParts() == 0) {
    100        status = U_INVALID_STATE_ERROR;
    101        return appendTo;
    102    }
    103    int32_t msgStart = findSubMessage(msgPattern, 0, keyword, status);
    104    if (!MessageImpl::jdkAposMode(msgPattern)) {
    105        int32_t patternStart = msgPattern.getPart(msgStart).getLimit();
    106        int32_t msgLimit = msgPattern.getLimitPartIndex(msgStart);
    107        appendTo.append(msgPattern.getPatternString(),
    108                        patternStart,
    109                        msgPattern.getPatternIndex(msgLimit) - patternStart);
    110        return appendTo;
    111    }
    112    // JDK compatibility mode: Remove SKIP_SYNTAX.
    113    return MessageImpl::appendSubMessageWithoutSkipSyntax(msgPattern, msgStart, appendTo);
    114 }
    115 
    116 UnicodeString&
    117 SelectFormat::toPattern(UnicodeString& appendTo) {
    118    if (0 == msgPattern.countParts()) {
    119        appendTo.setToBogus();
    120    } else {
    121        appendTo.append(msgPattern.getPatternString());
    122    }
    123    return appendTo;
    124 }
    125 
    126 
    127 int32_t SelectFormat::findSubMessage(const MessagePattern& pattern, int32_t partIndex,
    128                                     const UnicodeString& keyword, UErrorCode& ec) {
    129    if (U_FAILURE(ec)) {
    130        return 0;
    131    }
    132    UnicodeString other(false, SELECT_KEYWORD_OTHER, 5);
    133    int32_t count = pattern.countParts();
    134    int32_t msgStart=0;
    135    // Iterate over (ARG_SELECTOR, message) pairs until ARG_LIMIT or end of select-only pattern.
    136    do {
    137        const MessagePattern::Part& part=pattern.getPart(partIndex++);
    138        const UMessagePatternPartType type=part.getType();
    139        if(type==UMSGPAT_PART_TYPE_ARG_LIMIT) {
    140            break;
    141        }
    142        // part is an ARG_SELECTOR followed by a message
    143        if(pattern.partSubstringMatches(part, keyword)) {
    144            // keyword matches
    145            return partIndex;
    146        } else if(msgStart==0 && pattern.partSubstringMatches(part, other)) {
    147            msgStart=partIndex;
    148        }
    149        partIndex=pattern.getLimitPartIndex(partIndex);
    150    } while(++partIndex<count);
    151    return msgStart;
    152 }
    153 
    154 SelectFormat* SelectFormat::clone() const
    155 {
    156    return new SelectFormat(*this);
    157 }
    158 
    159 SelectFormat&
    160 SelectFormat::operator=(const SelectFormat& other) {
    161    if (this != &other) {
    162        msgPattern = other.msgPattern;
    163    }
    164    return *this;
    165 }
    166 
    167 bool
    168 SelectFormat::operator==(const Format& other) const {
    169    if (this == &other) {
    170        return true;
    171    }
    172    if (!Format::operator==(other)) {
    173        return false;
    174    }
    175    const SelectFormat& o = static_cast<const SelectFormat&>(other);
    176    return msgPattern == o.msgPattern;
    177 }
    178 
    179 bool
    180 SelectFormat::operator!=(const Format& other) const {
    181    return  !operator==(other);
    182 }
    183 
    184 void
    185 SelectFormat::parseObject(const UnicodeString& /*source*/,
    186                        Formattable& /*result*/,
    187                        ParsePosition& pos) const
    188 {
    189    // Parsing not supported.
    190    pos.setErrorIndex(pos.getIndex());
    191 }
    192 
    193 U_NAMESPACE_END
    194 
    195 #endif /* #if !UCONFIG_NO_FORMATTING */
    196 
    197 //eof