1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
5 * Copyright (c) 1997-2012, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 * Copyright (C) 2010 , Yahoo! Inc.
8 ********************************************************************
12 * Modification History:
14 * Date Name Description
15 * 11/11/09 kirtig Finished first cut of implementation.
16 * 11/16/09 kirtig Improved version
17 ********************************************************************/
19 #include "utypeinfo.h" // for 'typeid' to work
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"
30 #include "messageimpl.h"
31 #include "patternprops.h"
32 #include "selfmtimpl.h"
38 #if !UCONFIG_NO_FORMATTING
42 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SelectFormat
)
44 static const UChar SELECT_KEYWORD_OTHER
[] = {LOW_O
, LOW_T
, LOW_H
, LOW_E
, LOW_R
, 0};
46 SelectFormat::SelectFormat(const UnicodeString
& pat
,
47 UErrorCode
& status
) : msgPattern(status
) {
48 applyPattern(pat
, status
);
51 SelectFormat::SelectFormat(const SelectFormat
& other
) : Format(other
),
52 msgPattern(other
.msgPattern
) {
55 SelectFormat::~SelectFormat() {
59 SelectFormat::applyPattern(const UnicodeString
& newPattern
, UErrorCode
& status
) {
60 if (U_FAILURE(status
)) {
64 msgPattern
.parseSelectStyle(newPattern
, NULL
, status
);
65 if (U_FAILURE(status
)) {
71 SelectFormat::format(const Formattable
& obj
,
72 UnicodeString
& appendTo
,
74 UErrorCode
& status
) const
76 if (U_FAILURE(status
)) {
79 if (obj
.getType() == Formattable::kString
) {
80 return format(obj
.getString(status
), appendTo
, pos
, status
);
82 status
= U_ILLEGAL_ARGUMENT_ERROR
;
88 SelectFormat::format(const UnicodeString
& keyword
,
89 UnicodeString
& appendTo
,
90 FieldPosition
& /*pos */,
91 UErrorCode
& status
) const {
92 if (U_FAILURE(status
)) {
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.
99 if (msgPattern
.countParts() == 0) {
100 status
= U_INVALID_STATE_ERROR
;
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(),
109 msgPattern
.getPatternIndex(msgLimit
) - patternStart
);
112 // JDK compatibility mode: Remove SKIP_SYNTAX.
113 return MessageImpl::appendSubMessageWithoutSkipSyntax(msgPattern
, msgStart
, appendTo
);
117 SelectFormat::toPattern(UnicodeString
& appendTo
) {
118 if (0 == msgPattern
.countParts()) {
119 appendTo
.setToBogus();
121 appendTo
.append(msgPattern
.getPatternString());
127 int32_t SelectFormat::findSubMessage(const MessagePattern
& pattern
, int32_t partIndex
,
128 const UnicodeString
& keyword
, UErrorCode
& ec
) {
132 UnicodeString
other(FALSE
, SELECT_KEYWORD_OTHER
, 5);
133 int32_t count
= pattern
.countParts();
135 // Iterate over (ARG_SELECTOR, message) pairs until ARG_LIMIT or end of select-only pattern.
137 const MessagePattern::Part
& part
=pattern
.getPart(partIndex
++);
138 const UMessagePatternPartType type
=part
.getType();
139 if(type
==UMSGPAT_PART_TYPE_ARG_LIMIT
) {
142 // part is an ARG_SELECTOR followed by a message
143 if(pattern
.partSubstringMatches(part
, keyword
)) {
146 } else if(msgStart
==0 && pattern
.partSubstringMatches(part
, other
)) {
149 partIndex
=pattern
.getLimitPartIndex(partIndex
);
150 } while(++partIndex
<count
);
154 Format
* SelectFormat::clone() const
156 return new SelectFormat(*this);
160 SelectFormat::operator=(const SelectFormat
& other
) {
161 if (this != &other
) {
162 msgPattern
= other
.msgPattern
;
168 SelectFormat::operator==(const Format
& other
) const {
169 if (this == &other
) {
172 if (!Format::operator==(other
)) {
175 const SelectFormat
& o
= (const SelectFormat
&)other
;
176 return msgPattern
== o
.msgPattern
;
180 SelectFormat::operator!=(const Format
& other
) const {
181 return !operator==(other
);
185 SelectFormat::parseObject(const UnicodeString
& /*source*/,
186 Formattable
& /*result*/,
187 ParsePosition
& pos
) const
189 // Parsing not supported.
190 pos
.setErrorIndex(pos
.getIndex());
195 #endif /* #if !UCONFIG_NO_FORMATTING */