• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SelectFormat(const UnicodeString & pat,UErrorCode & status)44 SelectFormat::SelectFormat(const UnicodeString& pat,
45                            UErrorCode& status) : msgPattern(status) {
46    applyPattern(pat, status);
47 }
48 
SelectFormat(const SelectFormat & other)49 SelectFormat::SelectFormat(const SelectFormat& other) : Format(other),
50                                                         msgPattern(other.msgPattern) {
51 }
52 
~SelectFormat()53 SelectFormat::~SelectFormat() {
54 }
55 
56 void
applyPattern(const UnicodeString & newPattern,UErrorCode & status)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&
format(const Formattable & obj,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const69 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&
format(const UnicodeString & keyword,UnicodeString & appendTo,FieldPosition &,UErrorCode & status) const86 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&
toPattern(UnicodeString & appendTo)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 
findSubMessage(const MessagePattern & pattern,int32_t partIndex,const UnicodeString & keyword,UErrorCode & ec)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 
clone() const152 Format* SelectFormat::clone() const
153 {
154     return new SelectFormat(*this);
155 }
156 
157 SelectFormat&
operator =(const SelectFormat & other)158 SelectFormat::operator=(const SelectFormat& other) {
159     if (this != &other) {
160         msgPattern = other.msgPattern;
161     }
162     return *this;
163 }
164 
165 UBool
operator ==(const Format & other) const166 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
operator !=(const Format & other) const178 SelectFormat::operator!=(const Format& other) const {
179     return  !operator==(other);
180 }
181 
182 void
parseObject(const UnicodeString &,Formattable &,ParsePosition & pos) const183 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
196