Line data Source code
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 0 : UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SelectFormat)
43 :
44 : static const UChar SELECT_KEYWORD_OTHER[] = {LOW_O, LOW_T, LOW_H, LOW_E, LOW_R, 0};
45 :
46 0 : SelectFormat::SelectFormat(const UnicodeString& pat,
47 0 : UErrorCode& status) : msgPattern(status) {
48 0 : applyPattern(pat, status);
49 0 : }
50 :
51 0 : SelectFormat::SelectFormat(const SelectFormat& other) : Format(other),
52 0 : msgPattern(other.msgPattern) {
53 0 : }
54 :
55 0 : SelectFormat::~SelectFormat() {
56 0 : }
57 :
58 : void
59 0 : SelectFormat::applyPattern(const UnicodeString& newPattern, UErrorCode& status) {
60 0 : if (U_FAILURE(status)) {
61 0 : return;
62 : }
63 :
64 0 : msgPattern.parseSelectStyle(newPattern, NULL, status);
65 0 : if (U_FAILURE(status)) {
66 0 : msgPattern.clear();
67 : }
68 : }
69 :
70 : UnicodeString&
71 0 : SelectFormat::format(const Formattable& obj,
72 : UnicodeString& appendTo,
73 : FieldPosition& pos,
74 : UErrorCode& status) const
75 : {
76 0 : if (U_FAILURE(status)) {
77 0 : return appendTo;
78 : }
79 0 : if (obj.getType() == Formattable::kString) {
80 0 : return format(obj.getString(status), appendTo, pos, status);
81 : } else {
82 0 : status = U_ILLEGAL_ARGUMENT_ERROR;
83 0 : return appendTo;
84 : }
85 : }
86 :
87 : UnicodeString&
88 0 : SelectFormat::format(const UnicodeString& keyword,
89 : UnicodeString& appendTo,
90 : FieldPosition& /*pos */,
91 : UErrorCode& status) const {
92 0 : if (U_FAILURE(status)) {
93 0 : return appendTo;
94 : }
95 : // Check for the validity of the keyword
96 0 : if (!PatternProps::isIdentifier(keyword.getBuffer(), keyword.length())) {
97 0 : status = U_ILLEGAL_ARGUMENT_ERROR; // Invalid formatting argument.
98 : }
99 0 : if (msgPattern.countParts() == 0) {
100 0 : status = U_INVALID_STATE_ERROR;
101 0 : return appendTo;
102 : }
103 0 : int32_t msgStart = findSubMessage(msgPattern, 0, keyword, status);
104 0 : if (!MessageImpl::jdkAposMode(msgPattern)) {
105 0 : int32_t patternStart = msgPattern.getPart(msgStart).getLimit();
106 0 : int32_t msgLimit = msgPattern.getLimitPartIndex(msgStart);
107 : appendTo.append(msgPattern.getPatternString(),
108 : patternStart,
109 0 : msgPattern.getPatternIndex(msgLimit) - patternStart);
110 0 : return appendTo;
111 : }
112 : // JDK compatibility mode: Remove SKIP_SYNTAX.
113 0 : return MessageImpl::appendSubMessageWithoutSkipSyntax(msgPattern, msgStart, appendTo);
114 : }
115 :
116 : UnicodeString&
117 0 : SelectFormat::toPattern(UnicodeString& appendTo) {
118 0 : if (0 == msgPattern.countParts()) {
119 0 : appendTo.setToBogus();
120 : } else {
121 0 : appendTo.append(msgPattern.getPatternString());
122 : }
123 0 : return appendTo;
124 : }
125 :
126 :
127 0 : int32_t SelectFormat::findSubMessage(const MessagePattern& pattern, int32_t partIndex,
128 : const UnicodeString& keyword, UErrorCode& ec) {
129 0 : if (U_FAILURE(ec)) {
130 0 : return 0;
131 : }
132 0 : UnicodeString other(FALSE, SELECT_KEYWORD_OTHER, 5);
133 0 : int32_t count = pattern.countParts();
134 0 : int32_t msgStart=0;
135 : // Iterate over (ARG_SELECTOR, message) pairs until ARG_LIMIT or end of select-only pattern.
136 0 : do {
137 0 : const MessagePattern::Part& part=pattern.getPart(partIndex++);
138 0 : const UMessagePatternPartType type=part.getType();
139 0 : if(type==UMSGPAT_PART_TYPE_ARG_LIMIT) {
140 0 : break;
141 : }
142 : // part is an ARG_SELECTOR followed by a message
143 0 : if(pattern.partSubstringMatches(part, keyword)) {
144 : // keyword matches
145 0 : return partIndex;
146 0 : } else if(msgStart==0 && pattern.partSubstringMatches(part, other)) {
147 0 : msgStart=partIndex;
148 : }
149 0 : partIndex=pattern.getLimitPartIndex(partIndex);
150 : } while(++partIndex<count);
151 0 : return msgStart;
152 : }
153 :
154 0 : Format* SelectFormat::clone() const
155 : {
156 0 : return new SelectFormat(*this);
157 : }
158 :
159 : SelectFormat&
160 0 : SelectFormat::operator=(const SelectFormat& other) {
161 0 : if (this != &other) {
162 0 : msgPattern = other.msgPattern;
163 : }
164 0 : return *this;
165 : }
166 :
167 : UBool
168 0 : SelectFormat::operator==(const Format& other) const {
169 0 : if (this == &other) {
170 0 : return TRUE;
171 : }
172 0 : if (!Format::operator==(other)) {
173 0 : return FALSE;
174 : }
175 0 : const SelectFormat& o = (const SelectFormat&)other;
176 0 : return msgPattern == o.msgPattern;
177 : }
178 :
179 : UBool
180 0 : SelectFormat::operator!=(const Format& other) const {
181 0 : return !operator==(other);
182 : }
183 :
184 : void
185 0 : SelectFormat::parseObject(const UnicodeString& /*source*/,
186 : Formattable& /*result*/,
187 : ParsePosition& pos) const
188 : {
189 : // Parsing not supported.
190 0 : pos.setErrorIndex(pos.getIndex());
191 0 : }
192 :
193 : U_NAMESPACE_END
194 :
195 : #endif /* #if !UCONFIG_NO_FORMATTING */
196 :
197 : //eof
|