150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/********************************************************************
227f654740f2a26ad62a5c155af9199af9e69b889claireho * COPYRIGHT:
354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius * Copyright (c) 1997-2012, International Business Machines Corporation and
450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * others. All Rights Reserved.
527f654740f2a26ad62a5c155af9199af9e69b889claireho * Copyright (C) 2010 , Yahoo! Inc.
650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ********************************************************************
750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *
850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * File SELFMT.CPP
950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *
1050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Modification History:
1150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *
1250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *   Date        Name        Description
1350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *   11/11/09    kirtig      Finished first cut of implementation.
1427f654740f2a26ad62a5c155af9199af9e69b889claireho *   11/16/09    kirtig      Improved version
1550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ********************************************************************/
1650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "utypeinfo.h"  // for 'typeid' to work
1827f654740f2a26ad62a5c155af9199af9e69b889claireho
19b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/messagepattern.h"
20b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/rbnf.h"
21b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/selfmt.h"
2250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/uchar.h"
23b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/ucnv_err.h"
2450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/umsg.h"
25b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/ustring.h"
26b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/utypes.h"
2750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "cmemory.h"
28b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "messageimpl.h"
29b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "patternprops.h"
30b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "selfmtimpl.h"
3150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "uassert.h"
3250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "ustrfmt.h"
33b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "util.h"
3450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "uvector.h"
3550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
3650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if !UCONFIG_NO_FORMATTING
3750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
3850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_NAMESPACE_BEGIN
3950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
4050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUOBJECT_DEFINE_RTTI_IMPLEMENTATION(SelectFormat)
4150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
4250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const UChar SELECT_KEYWORD_OTHER[] = {LOW_O, LOW_T, LOW_H, LOW_E, LOW_R, 0};
4350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
44b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoSelectFormat::SelectFormat(const UnicodeString& pat,
45b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                           UErrorCode& status) : msgPattern(status) {
4650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho   applyPattern(pat, status);
4750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
4850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
49b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoSelectFormat::SelectFormat(const SelectFormat& other) : Format(other),
50b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                                        msgPattern(other.msgPattern) {
5150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
5250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
5350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::~SelectFormat() {
5427f654740f2a26ad62a5c155af9199af9e69b889claireho}
5550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
5650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid
5750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::applyPattern(const UnicodeString& newPattern, UErrorCode& status) {
5850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if (U_FAILURE(status)) {
5950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      return;
6027f654740f2a26ad62a5c155af9199af9e69b889claireho    }
6150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
62b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    msgPattern.parseSelectStyle(newPattern, NULL, status);
63b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
64b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        msgPattern.clear();
6550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
6650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
6750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
6850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString&
6950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::format(const Formattable& obj,
7050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                   UnicodeString& appendTo,
7150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                   FieldPosition& pos,
7250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                   UErrorCode& status) const
7350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{
74b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
75b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return appendTo;
76b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
77b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (obj.getType() == Formattable::kString) {
78b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return format(obj.getString(status), appendTo, pos, status);
79b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
80b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_ILLEGAL_ARGUMENT_ERROR;
8150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return appendTo;
8250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
8350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
8450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
8550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString&
8650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::format(const UnicodeString& keyword,
8727f654740f2a26ad62a5c155af9199af9e69b889claireho                     UnicodeString& appendTo,
8827f654740f2a26ad62a5c155af9199af9e69b889claireho                     FieldPosition& /*pos */,
8950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                     UErrorCode& status) const {
90b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
9150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return appendTo;
9250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
93b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Check for the validity of the keyword
94b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (!PatternProps::isIdentifier(keyword.getBuffer(), keyword.length())) {
95b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_ILLEGAL_ARGUMENT_ERROR;  // Invalid formatting argument.
96b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
97b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (msgPattern.countParts() == 0) {
98b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_INVALID_STATE_ERROR;
9950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return appendTo;
10050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
101b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t msgStart = findSubMessage(msgPattern, 0, keyword, status);
102b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (!MessageImpl::jdkAposMode(msgPattern)) {
103b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t patternStart = msgPattern.getPart(msgStart).getLimit();
104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t msgLimit = msgPattern.getLimitPartIndex(msgStart);
105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        appendTo.append(msgPattern.getPatternString(),
106b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        patternStart,
107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        msgPattern.getPatternIndex(msgLimit) - patternStart);
108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return appendTo;
10950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // JDK compatibility mode: Remove SKIP_SYNTAX.
111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return MessageImpl::appendSubMessageWithoutSkipSyntax(msgPattern, msgStart, appendTo);
11250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
11350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
11450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString&
11550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::toPattern(UnicodeString& appendTo) {
116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (0 == msgPattern.countParts()) {
117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        appendTo.setToBogus();
118b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
119b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        appendTo.append(msgPattern.getPatternString());
12050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return appendTo;
12250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
12350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
12450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t SelectFormat::findSubMessage(const MessagePattern& pattern, int32_t partIndex,
126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                     const UnicodeString& keyword, UErrorCode& ec) {
127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(ec)) {
128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
12950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
130b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString other(FALSE, SELECT_KEYWORD_OTHER, 5);
131b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t count = pattern.countParts();
132b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t msgStart=0;
133b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Iterate over (ARG_SELECTOR, message) pairs until ARG_LIMIT or end of select-only pattern.
134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    do {
135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const MessagePattern::Part& part=pattern.getPart(partIndex++);
136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UMessagePatternPartType type=part.getType();
137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(type==UMSGPAT_PART_TYPE_ARG_LIMIT) {
138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
13950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // part is an ARG_SELECTOR followed by a message
141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(pattern.partSubstringMatches(part, keyword)) {
142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // keyword matches
143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return partIndex;
144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if(msgStart==0 && pattern.partSubstringMatches(part, other)) {
145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            msgStart=partIndex;
146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        partIndex=pattern.getLimitPartIndex(partIndex);
148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } while(++partIndex<count);
149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return msgStart;
15050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
15150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
15250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoFormat* SelectFormat::clone() const
15350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{
15450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return new SelectFormat(*this);
15550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
15650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
15750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat&
15850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::operator=(const SelectFormat& other) {
15950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if (this != &other) {
160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        msgPattern = other.msgPattern;
16150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
16250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return *this;
16350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
16450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
16550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUBool
16650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::operator==(const Format& other) const {
167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (this == &other) {
16850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return TRUE;
16950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
170b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (!Format::operator==(other)) {
17150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return FALSE;
172b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
173b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const SelectFormat& o = (const SelectFormat&)other;
174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return msgPattern == o.msgPattern;
17550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
17650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
17750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUBool
17850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::operator!=(const Format& other) const {
17950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return  !operator==(other);
18050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
18150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
18250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid
18350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoSelectFormat::parseObject(const UnicodeString& /*source*/,
18450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        Formattable& /*result*/,
18550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        ParsePosition& pos) const
18650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{
187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Parsing not supported.
18850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    pos.setErrorIndex(pos.getIndex());
18950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
19050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
19150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_NAMESPACE_END
19250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
19350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif /* #if !UCONFIG_NO_FORMATTING */
19450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
19550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho//eof
196