164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// Copyright (C) 2016 and later: Unicode, Inc. and others.
264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
559d709d503bab6e2b61931737e662dd293b40578ccornelius* Copyright (C) 1997-2013, International Business Machines Corporation and    *
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* others. All Rights Reserved.                                                *
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* File CHOICFMT.CPP
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Modification History:
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Date        Name        Description
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   02/19/97    aliu        Converted from java.
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   03/20/97    helena      Finished first cut of implementation and got rid
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*                           of nextDouble/previousDouble and replaced with
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*                           boolean array.
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   4/10/97     aliu        Clean up.  Modified to work on AIX.
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   06/04/97    helena      Fixed applyPattern(), toPattern() and not to include
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*                           wchar.h.
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   07/09/97    helena      Made ParsePosition into a class.
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   08/06/97    nos         removed overloaded constructor, fixed 'format(array)'
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   07/22/98    stephen     JDK 1.2 Sync - removed UBool array (doubleFlags)
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   02/22/99    stephen     Removed character literals for EBCDIC safety
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************************
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/choicfmt.h"
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/numfmt.h"
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/locid.h"
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cpputils.h"
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cstring.h"
37b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "messageimpl.h"
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "putilimp.h"
39b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "uassert.h"
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdio.h>
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <float.h>
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// *****************************************************************************
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// class ChoiceFormat
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// *****************************************************************************
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(ChoiceFormat)
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Special characters used by ChoiceFormat.  There are two characters
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// used interchangeably to indicate <=.  Either is parsed, but only
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// LESS_EQUAL is generated by toPattern().
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SINGLE_QUOTE ((UChar)0x0027)   /*'*/
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define LESS_THAN    ((UChar)0x003C)   /*<*/
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define LESS_EQUAL   ((UChar)0x0023)   /*#*/
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define LESS_EQUAL2  ((UChar)0x2264)
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define VERTICAL_BAR ((UChar)0x007C)   /*|*/
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define MINUS        ((UChar)0x002D)   /*-*/
6085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
61b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar LEFT_CURLY_BRACE = 0x7B;     /*{*/
62b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar RIGHT_CURLY_BRACE = 0x7D;    /*}*/
63b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
6485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#ifdef INFINITY
6585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#undef INFINITY
6685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#endif
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define INFINITY     ((UChar)0x221E)
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
6954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//static const UChar gPositiveInfinity[] = {INFINITY, 0};
7054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius//static const UChar gNegativeInfinity[] = {MINUS, INFINITY, 0};
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define POSITIVE_INF_STRLEN 1
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define NEGATIVE_INF_STRLEN 2
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Creates a ChoiceFormat instance based on the pattern.
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::ChoiceFormat(const UnicodeString& newPattern,
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           UErrorCode& status)
79b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: constructorErrorCode(status),
80b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  msgPattern(status)
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    applyPattern(newPattern, status);
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Creates a ChoiceFormat instance with the limit array and
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// format strings for each limit.
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::ChoiceFormat(const double* limits,
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           const UnicodeString* formats,
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           int32_t cnt )
92b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: constructorErrorCode(U_ZERO_ERROR),
93b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  msgPattern(constructorErrorCode)
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
95b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    setChoices(limits, NULL, formats, cnt, constructorErrorCode);
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::ChoiceFormat(const double* limits,
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           const UBool* closures,
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           const UnicodeString* formats,
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           int32_t cnt )
104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: constructorErrorCode(U_ZERO_ERROR),
105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  msgPattern(constructorErrorCode)
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    setChoices(limits, closures, formats, cnt, constructorErrorCode);
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// copy constructor
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::ChoiceFormat(const    ChoiceFormat&   that)
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru: NumberFormat(that),
115b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  constructorErrorCode(that.constructorErrorCode),
116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  msgPattern(that.msgPattern)
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Private constructor that creates a
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ChoiceFormat instance based on the
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// pattern and populates UParseError
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::ChoiceFormat(const UnicodeString& newPattern,
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           UParseError& parseError,
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           UErrorCode& status)
128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: constructorErrorCode(status),
129b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  msgPattern(status)
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    applyPattern(newPattern,parseError, status);
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::operator==(const Format& that) const
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (this == &that) return TRUE;
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!NumberFormat::operator==(that)) return FALSE;
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ChoiceFormat& thatAlias = (ChoiceFormat&)that;
141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return msgPattern == thatAlias.msgPattern;
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// copy constructor
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst ChoiceFormat&
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::operator=(const   ChoiceFormat& that)
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (this != &that) {
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        NumberFormat::operator=(that);
152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        constructorErrorCode = that.constructorErrorCode;
153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        msgPattern = that.msgPattern;
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return *this;
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::~ChoiceFormat()
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Convert a double value to a string without the overhead of NumberFormat.
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::dtos(double value,
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                   UnicodeString& string)
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Buffer to contain the digits and any extra formatting stuff. */
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char temp[DBL_DIG + 16];
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char *itrPtr = temp;
17685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    char *expPtr;
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
17885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    sprintf(temp, "%.*g", DBL_DIG, value);
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Find and convert the decimal point.
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru       Using setlocale on some machines will cause sprintf to use a comma for certain locales.
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (*itrPtr && (*itrPtr == '-' || isdigit(*itrPtr))) {
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        itrPtr++;
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
18685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (*itrPtr != 0 && *itrPtr != 'e') {
18785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* We reached something that looks like a decimal point.
18885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        In case someone used setlocale(), which changes the decimal point. */
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        *itrPtr = '.';
19085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        itrPtr++;
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
19285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    /* Search for the exponent */
19385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    while (*itrPtr && *itrPtr != 'e') {
19485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        itrPtr++;
19585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
19685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (*itrPtr == 'e') {
19785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        itrPtr++;
19885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* Verify the exponent sign */
19985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (*itrPtr == '+' || *itrPtr == '-') {
20085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            itrPtr++;
20185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
20285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        /* Remove leading zeros. You will see this on Windows machines. */
20385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        expPtr = itrPtr;
20485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        while (*itrPtr == '0') {
20585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            itrPtr++;
20685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
20785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (*itrPtr && expPtr != itrPtr) {
20885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            /* Shift the exponent without zeros. */
20985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            while (*itrPtr) {
21085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                *(expPtr++)  = *(itrPtr++);
21185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
21285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            // NULL terminate
21385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            *expPtr = 0;
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
21685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    string = UnicodeString(temp, -1, US_INV);    /* invariant codepage */
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return string;
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// calls the overloaded applyPattern method.
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::applyPattern(const UnicodeString& pattern,
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           UErrorCode& status)
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
228b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    msgPattern.parseChoiceStyle(pattern, NULL, status);
229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    constructorErrorCode = status;
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Applies the pattern to this ChoiceFormat instance.
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::applyPattern(const UnicodeString& pattern,
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           UParseError& parseError,
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           UErrorCode& status)
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
240b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    msgPattern.parseChoiceStyle(pattern, &parseError, status);
241b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    constructorErrorCode = status;
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Returns the input pattern string.
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::toPattern(UnicodeString& result) const
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
249b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return result = msgPattern.getPatternString();
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Sets the limit and format arrays.
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::setChoices(  const double* limits,
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           const UnicodeString* formats,
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           int32_t cnt )
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
259b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode errorCode = U_ZERO_ERROR;
260b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    setChoices(limits, NULL, formats, cnt, errorCode);
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Sets the limit and format arrays.
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::setChoices(  const double* limits,
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           const UBool* closures,
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           const UnicodeString* formats,
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           int32_t cnt )
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
271b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode errorCode = U_ZERO_ERROR;
272b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    setChoices(limits, closures, formats, cnt, errorCode);
273b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
275b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
276b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoChoiceFormat::setChoices(const double* limits,
277b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                         const UBool* closures,
278b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                         const UnicodeString* formats,
279b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                         int32_t count,
280b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                         UErrorCode &errorCode) {
281b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(errorCode)) {
282b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
28385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
284b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (limits == NULL || formats == NULL) {
285b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errorCode = U_ILLEGAL_ARGUMENT_ERROR;
286b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
28785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
288b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Reconstruct the original input pattern.
289b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Modified version of the pre-ICU 4.8 toPattern() implementation.
290b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString result;
291b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t i = 0; i < count; ++i) {
292b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (i != 0) {
293b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            result += VERTICAL_BAR;
29485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
295b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString buf;
296b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (uprv_isPositiveInfinity(limits[i])) {
297b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            result += INFINITY;
298b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if (uprv_isNegativeInfinity(limits[i])) {
299b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            result += MINUS;
300b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            result += INFINITY;
301b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            result += dtos(limits[i], buf);
30385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
304b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (closures != NULL && closures[i]) {
305b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            result += LESS_THAN;
306b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            result += LESS_EQUAL;
30885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
309b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Append formats[i], using quotes if there are special
310b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // characters.  Single quotes themselves must be escaped in
311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // either case.
312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UnicodeString& text = formats[i];
313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t textLength = text.length();
314b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t nestingLevel = 0;
315b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t j = 0; j < textLength; ++j) {
316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UChar c = text[j];
317b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (c == SINGLE_QUOTE && nestingLevel == 0) {
318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // Double each top-level apostrophe.
319b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                result.append(c);
320b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if (c == VERTICAL_BAR && nestingLevel == 0) {
321b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // Surround each pipe symbol with apostrophes for quoting.
322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // If the next character is an apostrophe, then that will be doubled,
323b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // and although the parser will see the apostrophe pairs beginning
324b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // and ending one character earlier than our doubling, the result
325b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // is as desired.
326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                //   | -> '|'
327b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                //   |' -> '|'''
328b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                //   |'' -> '|''''' etc.
329b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                result.append(SINGLE_QUOTE).append(c).append(SINGLE_QUOTE);
330b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                continue;  // Skip the append(c) at the end of the loop body.
331b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if (c == LEFT_CURLY_BRACE) {
332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ++nestingLevel;
333b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if (c == RIGHT_CURLY_BRACE && nestingLevel > 0) {
334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                --nestingLevel;
335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            result.append(c);
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
339b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Apply the reconstructed pattern.
340b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    applyPattern(result, errorCode);
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Gets the limit array.
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst double*
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::getLimits(int32_t& cnt) const
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
349b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    cnt = 0;
350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return NULL;
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Gets the closures array.
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst UBool*
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::getClosures(int32_t& cnt) const
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
359b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    cnt = 0;
360b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return NULL;
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Gets the format array.
365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst UnicodeString*
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::getFormats(int32_t& cnt) const
368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    cnt = 0;
370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return NULL;
371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Formats an int64 number, it's actually formatted as
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// a double.  The returned format string may differ
376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// from the input number because of this.
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::format(int64_t number,
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     UnicodeString& appendTo,
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     FieldPosition& status) const
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return format((double) number, appendTo, status);
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Formats an int32_t number, it's actually formatted as
388b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// a double.
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::format(int32_t number,
392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     UnicodeString& appendTo,
393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     FieldPosition& status) const
394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return format((double) number, appendTo, status);
396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Formats a double number.
400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::format(double number,
403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     UnicodeString& appendTo,
404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     FieldPosition& /*pos*/) const
405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
406b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (msgPattern.countParts() == 0) {
407b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // No pattern was applied, or it failed.
408b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return appendTo;
409b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
410b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Get the appropriate sub-message.
411b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t msgStart = findSubMessage(msgPattern, 0, number);
412b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (!MessageImpl::jdkAposMode(msgPattern)) {
413b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t patternStart = msgPattern.getPart(msgStart).getLimit();
414b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t msgLimit = msgPattern.getLimitPartIndex(msgStart);
415b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        appendTo.append(msgPattern.getPatternString(),
416b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        patternStart,
417b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        msgPattern.getPatternIndex(msgLimit) - patternStart);
418b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return appendTo;
419b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
420b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // JDK compatibility mode: Remove SKIP_SYNTAX.
421b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return MessageImpl::appendSubMessageWithoutSkipSyntax(msgPattern, msgStart, appendTo);
422b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
423b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
424b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
425b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoChoiceFormat::findSubMessage(const MessagePattern &pattern, int32_t partIndex, double number) {
426b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t count = pattern.countParts();
427b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t msgStart;
428b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Iterate over (ARG_INT|DOUBLE, ARG_SELECTOR, message) tuples
429b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // until ARG_LIMIT or end of choice-only pattern.
430b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Ignore the first number and selector and start the loop on the first message.
431b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    partIndex += 2;
432b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (;;) {
433b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Skip but remember the current sub-message.
434b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        msgStart = partIndex;
435b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        partIndex = pattern.getLimitPartIndex(partIndex);
436b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (++partIndex >= count) {
437b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Reached the end of the choice-only pattern.
438b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Return with the last sub-message.
439b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
440b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
441b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const MessagePattern::Part &part = pattern.getPart(partIndex++);
442b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UMessagePatternPartType type = part.getType();
443b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (type == UMSGPAT_PART_TYPE_ARG_LIMIT) {
444b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Reached the end of the ChoiceFormat style.
445b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Return with the last sub-message.
446b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
447b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
448b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // part is an ARG_INT or ARG_DOUBLE
449b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        U_ASSERT(MessagePattern::Part::hasNumericValue(type));
450b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        double boundary = pattern.getNumericValue(part);
451b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Fetch the ARG_SELECTOR character.
452b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t selectorIndex = pattern.getPatternIndex(partIndex++);
453b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UChar boundaryChar = pattern.getPatternString().charAt(selectorIndex);
454b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (boundaryChar == LESS_THAN ? !(number > boundary) : !(number >= boundary)) {
455b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // The number is in the interval between the previous boundary and the current one.
456b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Return with the sub-message between them.
457b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // The !(a>b) and !(a>=b) comparisons are equivalent to
458b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // (a<=b) and (a<b) except they "catch" NaN.
459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
462b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return msgStart;
463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Formats an array of objects. Checks if the data type of the objects
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// to get the right value for formatting.
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::format(const Formattable* objs,
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     int32_t cnt,
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     UnicodeString& appendTo,
473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     FieldPosition& pos,
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     UErrorCode& status) const
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(cnt < 0) {
477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_ILLEGAL_ARGUMENT_ERROR;
478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return appendTo;
479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
480b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (msgPattern.countParts() == 0) {
481b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_INVALID_STATE_ERROR;
482b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return appendTo;
483b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int32_t i = 0; i < cnt; i++) {
486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        double objDouble = objs[i].getDouble(status);
487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_SUCCESS(status)) {
488b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            format(objDouble, appendTo, pos);
489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return appendTo;
493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::parse(const UnicodeString& text,
499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    Formattable& result,
500b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    ParsePosition& pos) const
501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
502b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    result.setDouble(parseArgument(msgPattern, 0, text, pos));
503b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
504b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
505b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehodouble
506b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoChoiceFormat::parseArgument(
507b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const MessagePattern &pattern, int32_t partIndex,
508b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UnicodeString &source, ParsePosition &pos) {
509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // find the best number (defined as the one with the longest parse)
510b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t start = pos.getIndex();
511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t furthest = start;
512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    double bestNumber = uprv_getNaN();
513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    double tempNumber = 0.0;
514b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t count = pattern.countParts();
515b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    while (partIndex < count && pattern.getPartType(partIndex) != UMSGPAT_PART_TYPE_ARG_LIMIT) {
516b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tempNumber = pattern.getNumericValue(pattern.getPart(partIndex));
517b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        partIndex += 2;  // skip the numeric part and ignore the ARG_SELECTOR
518b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t msgLimit = pattern.getLimitPartIndex(partIndex);
519b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t len = matchStringUntilLimitPart(pattern, partIndex, msgLimit, source, start);
520b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (len >= 0) {
521b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t newIndex = start + len;
522b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (newIndex > furthest) {
523b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                furthest = newIndex;
524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                bestNumber = tempNumber;
525b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (furthest == source.length()) {
526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
527b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
530b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        partIndex = msgLimit + 1;
531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
532b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (furthest == start) {
533b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        pos.setErrorIndex(start);
534b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
535b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        pos.setIndex(furthest);
536b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
537b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return bestNumber;
538b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
539b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
540b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
541b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoChoiceFormat::matchStringUntilLimitPart(
542b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const MessagePattern &pattern, int32_t partIndex, int32_t limitPartIndex,
543b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UnicodeString &source, int32_t sourceOffset) {
544b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t matchingSourceLength = 0;
545b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UnicodeString &msgString = pattern.getPatternString();
546b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t prevIndex = pattern.getPart(partIndex).getLimit();
547b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (;;) {
548b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const MessagePattern::Part &part = pattern.getPart(++partIndex);
549b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (partIndex == limitPartIndex || part.getType() == UMSGPAT_PART_TYPE_SKIP_SYNTAX) {
550b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t index = part.getIndex();
551b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t length = index - prevIndex;
552b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (length != 0 && 0 != source.compare(sourceOffset, length, msgString, prevIndex, length)) {
553b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return -1;  // mismatch
554b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
555b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            matchingSourceLength += length;
556b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (partIndex == limitPartIndex) {
557b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return matchingSourceLength;
558b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
559b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            prevIndex = part.getLimit();  // SKIP_SYNTAX
560b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruFormat*
567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruChoiceFormat::clone() const
568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ChoiceFormat *aCopy = new ChoiceFormat(*this);
570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return aCopy;
571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//eof
578