1 /********************************************************************
3 * Copyright (c) 1997-2012, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 * Copyright (C) 2010 , Yahoo! Inc.
6 ********************************************************************
10 * Modification History:
12 * Date Name Description
13 * 11/11/09 kirtig Finished first cut of implementation.
14 * 11/16/09 kirtig Improved version
15 ********************************************************************/
17 #include "utypeinfo.h" // for 'typeid' to work
19 #include "unicode/messagepattern.h"
20 #include "unicode/rbnf.h"
21 #include "unicode/selfmt.h"
22 #include "unicode/uchar.h"
23 #include "unicode/ucnv_err.h"
24 #include "unicode/umsg.h"
25 #include "unicode/ustring.h"
26 #include "unicode/utypes.h"
28 #include "messageimpl.h"
29 #include "patternprops.h"
30 #include "selfmtimpl.h"
36 #if !UCONFIG_NO_FORMATTING
40 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SelectFormat
)
42 static const UChar SELECT_KEYWORD_OTHER
[] = {LOW_O
, LOW_T
, LOW_H
, LOW_E
, LOW_R
, 0};
44 SelectFormat::SelectFormat(const UnicodeString
& pat
,
45 UErrorCode
& status
) : msgPattern(status
) {
46 applyPattern(pat
, status
);
49 SelectFormat::SelectFormat(const SelectFormat
& other
) : Format(other
),
50 msgPattern(other
.msgPattern
) {
53 SelectFormat::~SelectFormat() {
57 SelectFormat::applyPattern(const UnicodeString
& newPattern
, UErrorCode
& status
) {
58 if (U_FAILURE(status
)) {
62 msgPattern
.parseSelectStyle(newPattern
, NULL
, status
);
63 if (U_FAILURE(status
)) {
69 SelectFormat::format(const Formattable
& obj
,
70 UnicodeString
& appendTo
,
72 UErrorCode
& status
) const
74 if (U_FAILURE(status
)) {
77 if (obj
.getType() == Formattable::kString
) {
78 return format(obj
.getString(status
), appendTo
, pos
, status
);
80 status
= U_ILLEGAL_ARGUMENT_ERROR
;
86 SelectFormat::format(const UnicodeString
& keyword
,
87 UnicodeString
& appendTo
,
88 FieldPosition
& /*pos */,
89 UErrorCode
& status
) const {
90 if (U_FAILURE(status
)) {
93 // Check for the validity of the keyword
94 if (!PatternProps::isIdentifier(keyword
.getBuffer(), keyword
.length())) {
95 status
= U_ILLEGAL_ARGUMENT_ERROR
; // Invalid formatting argument.
97 if (msgPattern
.countParts() == 0) {
98 status
= U_INVALID_STATE_ERROR
;
101 int32_t msgStart
= findSubMessage(msgPattern
, 0, keyword
, status
);
102 if (!MessageImpl::jdkAposMode(msgPattern
)) {
103 int32_t patternStart
= msgPattern
.getPart(msgStart
).getLimit();
104 int32_t msgLimit
= msgPattern
.getLimitPartIndex(msgStart
);
105 appendTo
.append(msgPattern
.getPatternString(),
107 msgPattern
.getPatternIndex(msgLimit
) - patternStart
);
110 // JDK compatibility mode: Remove SKIP_SYNTAX.
111 return MessageImpl::appendSubMessageWithoutSkipSyntax(msgPattern
, msgStart
, appendTo
);
115 SelectFormat::toPattern(UnicodeString
& appendTo
) {
116 if (0 == msgPattern
.countParts()) {
117 appendTo
.setToBogus();
119 appendTo
.append(msgPattern
.getPatternString());
125 int32_t SelectFormat::findSubMessage(const MessagePattern
& pattern
, int32_t partIndex
,
126 const UnicodeString
& keyword
, UErrorCode
& ec
) {
130 UnicodeString
other(FALSE
, SELECT_KEYWORD_OTHER
, 5);
131 int32_t count
= pattern
.countParts();
133 // Iterate over (ARG_SELECTOR, message) pairs until ARG_LIMIT or end of select-only pattern.
135 const MessagePattern::Part
& part
=pattern
.getPart(partIndex
++);
136 const UMessagePatternPartType type
=part
.getType();
137 if(type
==UMSGPAT_PART_TYPE_ARG_LIMIT
) {
140 // part is an ARG_SELECTOR followed by a message
141 if(pattern
.partSubstringMatches(part
, keyword
)) {
144 } else if(msgStart
==0 && pattern
.partSubstringMatches(part
, other
)) {
147 partIndex
=pattern
.getLimitPartIndex(partIndex
);
148 } while(++partIndex
<count
);
152 Format
* SelectFormat::clone() const
154 return new SelectFormat(*this);
158 SelectFormat::operator=(const SelectFormat
& other
) {
159 if (this != &other
) {
160 msgPattern
= other
.msgPattern
;
166 SelectFormat::operator==(const Format
& other
) const {
167 if (this == &other
) {
170 if (!Format::operator==(other
)) {
173 const SelectFormat
& o
= (const SelectFormat
&)other
;
174 return msgPattern
== o
.msgPattern
;
178 SelectFormat::operator!=(const Format
& other
) const {
179 return !operator==(other
);
183 SelectFormat::parseObject(const UnicodeString
& /*source*/,
184 Formattable
& /*result*/,
185 ParsePosition
& pos
) const
187 // Parsing not supported.
188 pos
.setErrorIndex(pos
.getIndex());
193 #endif /* #if !UCONFIG_NO_FORMATTING */