10596faeddefbf198de137d5e893708495ab1584cFredrik Roubert// © 2016 and later: Unicode, Inc. and others. 264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html 350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/******************************************************************** 427f654740f2a26ad62a5c155af9199af9e69b889claireho * COPYRIGHT: 554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius * Copyright (c) 1997-2012, International Business Machines Corporation and 650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * others. All Rights Reserved. 727f654740f2a26ad62a5c155af9199af9e69b889claireho * Copyright (C) 2010 , Yahoo! Inc. 850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ******************************************************************** 950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * 1050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * File SELFMT.CPP 1150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * 1250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Modification History: 1350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * 1450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Date Name Description 1550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * 11/11/09 kirtig Finished first cut of implementation. 1627f654740f2a26ad62a5c155af9199af9e69b889claireho * 11/16/09 kirtig Improved version 1750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ********************************************************************/ 1850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 1954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "utypeinfo.h" // for 'typeid' to work 2027f654740f2a26ad62a5c155af9199af9e69b889claireho 21b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/messagepattern.h" 22b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/rbnf.h" 23b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/selfmt.h" 2450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/uchar.h" 25b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/ucnv_err.h" 2650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/umsg.h" 27b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/ustring.h" 28b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/utypes.h" 2950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "cmemory.h" 30b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "messageimpl.h" 31b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "patternprops.h" 32b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "selfmtimpl.h" 3350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "uassert.h" 3450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "ustrfmt.h" 35b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "util.h" 3650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "uvector.h" 3750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 3850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if !UCONFIG_NO_FORMATTING 3950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_NAMESPACE_BEGIN 4150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUOBJECT_DEFINE_RTTI_IMPLEMENTATION(SelectFormat) 4350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const UChar SELECT_KEYWORD_OTHER[] = {LOW_O, LOW_T, LOW_H, LOW_E, LOW_R, 0}; 4550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 46b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoSelectFormat::SelectFormat(const UnicodeString& pat, 47b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UErrorCode& status) : msgPattern(status) { 4850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho applyPattern(pat, status); 4950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 5050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 51b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoSelectFormat::SelectFormat(const SelectFormat& other) : Format(other), 52b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho msgPattern(other.msgPattern) { 5350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 5450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 5550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::~SelectFormat() { 5627f654740f2a26ad62a5c155af9199af9e69b889claireho} 5750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 5850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 5950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::applyPattern(const UnicodeString& newPattern, UErrorCode& status) { 6050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 6150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 6227f654740f2a26ad62a5c155af9199af9e69b889claireho } 6350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 64b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho msgPattern.parseSelectStyle(newPattern, NULL, status); 65b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 66b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho msgPattern.clear(); 6750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 6850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 6950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 7050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString& 7150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::format(const Formattable& obj, 7250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UnicodeString& appendTo, 7350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho FieldPosition& pos, 7450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode& status) const 7550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{ 76b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 77b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return appendTo; 78b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 79b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (obj.getType() == Formattable::kString) { 80b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return format(obj.getString(status), appendTo, pos, status); 81b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 82b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_ILLEGAL_ARGUMENT_ERROR; 8350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return appendTo; 8450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 8550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 8650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 8750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString& 8850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::format(const UnicodeString& keyword, 8927f654740f2a26ad62a5c155af9199af9e69b889claireho UnicodeString& appendTo, 9027f654740f2a26ad62a5c155af9199af9e69b889claireho FieldPosition& /*pos */, 9150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode& status) const { 92b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 9350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return appendTo; 9450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 95b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Check for the validity of the keyword 96b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!PatternProps::isIdentifier(keyword.getBuffer(), keyword.length())) { 97b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_ILLEGAL_ARGUMENT_ERROR; // Invalid formatting argument. 98b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 99b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (msgPattern.countParts() == 0) { 100b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_INVALID_STATE_ERROR; 10150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return appendTo; 10250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 103b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t msgStart = findSubMessage(msgPattern, 0, keyword, status); 104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!MessageImpl::jdkAposMode(msgPattern)) { 105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t patternStart = msgPattern.getPart(msgStart).getLimit(); 106b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t msgLimit = msgPattern.getLimitPartIndex(msgStart); 107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho appendTo.append(msgPattern.getPatternString(), 108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho patternStart, 109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho msgPattern.getPatternIndex(msgLimit) - patternStart); 110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return appendTo; 11150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 112b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // JDK compatibility mode: Remove SKIP_SYNTAX. 113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return MessageImpl::appendSubMessageWithoutSkipSyntax(msgPattern, msgStart, appendTo); 11450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 11550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 11650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString& 11750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::toPattern(UnicodeString& appendTo) { 118b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (0 == msgPattern.countParts()) { 119b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho appendTo.setToBogus(); 120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho appendTo.append(msgPattern.getPatternString()); 12250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 123b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return appendTo; 12450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 12550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 12650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t SelectFormat::findSubMessage(const MessagePattern& pattern, int32_t partIndex, 128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UnicodeString& keyword, UErrorCode& ec) { 129b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(ec)) { 130b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return 0; 13150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 132b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString other(FALSE, SELECT_KEYWORD_OTHER, 5); 133b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t count = pattern.countParts(); 134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t msgStart=0; 135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Iterate over (ARG_SELECTOR, message) pairs until ARG_LIMIT or end of select-only pattern. 136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho do { 137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const MessagePattern::Part& part=pattern.getPart(partIndex++); 138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UMessagePatternPartType type=part.getType(); 139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if(type==UMSGPAT_PART_TYPE_ARG_LIMIT) { 140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 14150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // part is an ARG_SELECTOR followed by a message 143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if(pattern.partSubstringMatches(part, keyword)) { 144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // keyword matches 145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return partIndex; 146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else if(msgStart==0 && pattern.partSubstringMatches(part, other)) { 147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho msgStart=partIndex; 148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho partIndex=pattern.getLimitPartIndex(partIndex); 150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } while(++partIndex<count); 151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return msgStart; 15250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 15350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 15450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoFormat* SelectFormat::clone() const 15550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{ 15650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return new SelectFormat(*this); 15750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 15850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 15950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat& 16050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::operator=(const SelectFormat& other) { 16150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (this != &other) { 162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho msgPattern = other.msgPattern; 16350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 16450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return *this; 16550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 16650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 16750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUBool 16850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::operator==(const Format& other) const { 169b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (this == &other) { 17050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return TRUE; 17150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 172b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!Format::operator==(other)) { 17350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const SelectFormat& o = (const SelectFormat&)other; 176b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return msgPattern == o.msgPattern; 17750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 17850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 17950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUBool 18050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::operator!=(const Format& other) const { 18150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return !operator==(other); 18250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 18350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 18450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 18550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::parseObject(const UnicodeString& /*source*/, 18650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Formattable& /*result*/, 18750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ParsePosition& pos) const 18850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{ 189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Parsing not supported. 19050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pos.setErrorIndex(pos.getIndex()); 19150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 19250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 19350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_NAMESPACE_END 19450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 19550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif /* #if !UCONFIG_NO_FORMATTING */ 19650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 19750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho//eof 198