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