1b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
2b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*******************************************************************************
354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius*   Copyright (C) 2011-2012, International Business Machines
4b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   Corporation and others.  All Rights Reserved.
5b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*******************************************************************************
6b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   file name:  messagepattern.cpp
7b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   encoding:   US-ASCII
8b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   tab size:   8 (not used)
9b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   indentation:4
10b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*
11b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   created on: 2011mar14
12b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*   created by: Markus W. Scherer
13b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*/
14b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
15b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/utypes.h"
16b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
17b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#if !UCONFIG_NO_FORMATTING
18b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
19b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/messagepattern.h"
20b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/unistr.h"
21103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/utf16.h"
22b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "cmemory.h"
23b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "cstring.h"
24b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "messageimpl.h"
25b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "patternprops.h"
26b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "putilimp.h"
27b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "uassert.h"
28b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
29b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_NAMESPACE_BEGIN
30b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
31b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Unicode character/code point constants ---------------------------------- ***
32b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
33b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_pound=0x23;
34b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_apos=0x27;
35b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_plus=0x2B;
36b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_comma=0x2C;
37b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_minus=0x2D;
38b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_dot=0x2E;
39b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_colon=0x3A;
40b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_lessThan=0x3C;
41b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_equal=0x3D;
42b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_A=0x41;
43b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_C=0x43;
4454dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const UChar u_D=0x44;
45b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_E=0x45;
46b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_H=0x48;
47b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_I=0x49;
48b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_L=0x4C;
4954dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const UChar u_N=0x4E;
50b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_O=0x4F;
51b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_P=0x50;
52b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_R=0x52;
53b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_S=0x53;
54b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_T=0x54;
55b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_U=0x55;
56b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_Z=0x5A;
57b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_a=0x61;
58b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_c=0x63;
5954dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const UChar u_d=0x64;
60b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_e=0x65;
61b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_f=0x66;
62b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_h=0x68;
63b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_i=0x69;
64b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_l=0x6C;
6554dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic const UChar u_n=0x6E;
66b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_o=0x6F;
67b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_p=0x70;
68b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_r=0x72;
69b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_s=0x73;
70b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_t=0x74;
71b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_u=0x75;
72b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_z=0x7A;
73b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_leftCurlyBrace=0x7B;
74b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_pipe=0x7C;
75b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_rightCurlyBrace=0x7D;
76b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar u_lessOrEqual=0x2264;  // U+2264 is <=
77b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
78b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar kOffsetColon[]={  // "offset:"
79b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    u_o, u_f, u_f, u_s, u_e, u_t, u_colon
80b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
81b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
82b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar kOther[]={  // "other"
83b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    u_o, u_t, u_h, u_e, u_r
84b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
85b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
86b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// MessagePatternList ------------------------------------------------------ ***
87b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
88b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotemplate<typename T, int32_t stackCapacity>
89b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass MessagePatternList : public UMemory {
90b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic:
91b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MessagePatternList() {}
92b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void copyFrom(const MessagePatternList<T, stackCapacity> &other,
93b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  int32_t length,
94b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  UErrorCode &errorCode);
95b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool ensureCapacityForOneMore(int32_t oldLength, UErrorCode &errorCode);
9654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    UBool equals(const MessagePatternList<T, stackCapacity> &other, int32_t length) const {
9754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        for(int32_t i=0; i<length; ++i) {
9854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            if(a[i]!=other.a[i]) { return FALSE; }
9954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        }
10054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        return TRUE;
101b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
102b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
103b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MaybeStackArray<T, stackCapacity> a;
104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
106b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotemplate<typename T, int32_t stackCapacity>
107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePatternList<T, stackCapacity>::copyFrom(
109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const MessagePatternList<T, stackCapacity> &other,
110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t length,
111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UErrorCode &errorCode) {
112b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_SUCCESS(errorCode) && length>0) {
113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(length>a.getCapacity() && NULL==a.resize(length)) {
114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errorCode=U_MEMORY_ALLOCATION_ERROR;
115b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return;
116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uprv_memcpy(a.getAlias(), other.a.getAlias(), length*sizeof(T));
118b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
119b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotemplate<typename T, int32_t stackCapacity>
122b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
123b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePatternList<T, stackCapacity>::ensureCapacityForOneMore(int32_t oldLength, UErrorCode &errorCode) {
124b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(errorCode)) {
125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(a.getCapacity()>oldLength || a.resize(2*oldLength, oldLength)!=NULL) {
128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return TRUE;
129b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
130b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    errorCode=U_MEMORY_ALLOCATION_ERROR;
131b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return FALSE;
132b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
133b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// MessagePatternList specializations -------------------------------------- ***
135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass MessagePatternDoubleList : public MessagePatternList<double, 8> {
137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass MessagePatternPartsList : public MessagePatternList<MessagePattern::Part, 32> {
140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// MessagePattern constructors etc. ---------------------------------------- ***
143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::MessagePattern(UErrorCode &errorCode)
145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        : aposMode(UCONFIG_MSGPAT_DEFAULT_APOSTROPHE_MODE),
146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          partsList(NULL), parts(NULL), partsLength(0),
147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          numericValuesList(NULL), numericValues(NULL), numericValuesLength(0),
148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          hasArgNames(FALSE), hasArgNumbers(FALSE), needsAutoQuoting(FALSE) {
149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    init(errorCode);
150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::MessagePattern(UMessagePatternApostropheMode mode, UErrorCode &errorCode)
153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        : aposMode(mode),
154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          partsList(NULL), parts(NULL), partsLength(0),
155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          numericValuesList(NULL), numericValues(NULL), numericValuesLength(0),
156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          hasArgNames(FALSE), hasArgNumbers(FALSE), needsAutoQuoting(FALSE) {
157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    init(errorCode);
158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::MessagePattern(const UnicodeString &pattern, UParseError *parseError, UErrorCode &errorCode)
161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        : aposMode(UCONFIG_MSGPAT_DEFAULT_APOSTROPHE_MODE),
162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          partsList(NULL), parts(NULL), partsLength(0),
163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          numericValuesList(NULL), numericValues(NULL), numericValuesLength(0),
164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          hasArgNames(FALSE), hasArgNumbers(FALSE), needsAutoQuoting(FALSE) {
165b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(init(errorCode)) {
166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        parse(pattern, parseError, errorCode);
167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
168b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
169b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
170b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
171b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::init(UErrorCode &errorCode) {
172b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(errorCode)) {
173b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    partsList=new MessagePatternPartsList();
176b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(partsList==NULL) {
177b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errorCode=U_MEMORY_ALLOCATION_ERROR;
178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
179b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
180b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    parts=partsList->a.getAlias();
181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TRUE;
182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::MessagePattern(const MessagePattern &other)
18554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        : UObject(other), aposMode(other.aposMode), msg(other.msg),
186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          partsList(NULL), parts(NULL), partsLength(0),
187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          numericValuesList(NULL), numericValues(NULL), numericValuesLength(0),
188b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          hasArgNames(other.hasArgNames), hasArgNumbers(other.hasArgNumbers),
189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          needsAutoQuoting(other.needsAutoQuoting) {
190b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode errorCode=U_ZERO_ERROR;
191b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(!copyStorage(other, errorCode)) {
192b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        clear();
193b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
195b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
196b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern &
197b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::operator=(const MessagePattern &other) {
198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(this==&other) {
199b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return *this;
200b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    aposMode=other.aposMode;
202b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    msg=other.msg;
203b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    hasArgNames=other.hasArgNames;
204b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    hasArgNumbers=other.hasArgNumbers;
205b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    needsAutoQuoting=other.needsAutoQuoting;
206b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode errorCode=U_ZERO_ERROR;
207b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(!copyStorage(other, errorCode)) {
208b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        clear();
209b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
210b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return *this;
211b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
212b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
213b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
214b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::copyStorage(const MessagePattern &other, UErrorCode &errorCode) {
215b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(errorCode)) {
216b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
217b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
218b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    parts=NULL;
219b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    partsLength=0;
220b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    numericValues=NULL;
221b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    numericValuesLength=0;
222b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(partsList==NULL) {
223b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        partsList=new MessagePatternPartsList();
224b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(partsList==NULL) {
225b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errorCode=U_MEMORY_ALLOCATION_ERROR;
226b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return FALSE;
227b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
228b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        parts=partsList->a.getAlias();
229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
230b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(other.partsLength>0) {
231b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        partsList->copyFrom(*other.partsList, other.partsLength, errorCode);
232b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(U_FAILURE(errorCode)) {
233b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return FALSE;
234b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
235b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        parts=partsList->a.getAlias();
236b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        partsLength=other.partsLength;
237b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
238b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(other.numericValuesLength>0) {
239b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(numericValuesList==NULL) {
240b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            numericValuesList=new MessagePatternDoubleList();
241b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(numericValuesList==NULL) {
242b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errorCode=U_MEMORY_ALLOCATION_ERROR;
243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return FALSE;
244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
245b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            numericValues=numericValuesList->a.getAlias();
246b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
247b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        numericValuesList->copyFrom(
248b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            *other.numericValuesList, other.numericValuesLength, errorCode);
249b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(U_FAILURE(errorCode)) {
250b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return FALSE;
251b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
252b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        numericValues=numericValuesList->a.getAlias();
253b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        numericValuesLength=other.numericValuesLength;
254b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
255b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TRUE;
256b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
257b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
258b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::~MessagePattern() {
259b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    delete partsList;
260b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    delete numericValuesList;
261b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
262b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
263b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// MessagePattern API ------------------------------------------------------ ***
264b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
265b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern &
266b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::parse(const UnicodeString &pattern, UParseError *parseError, UErrorCode &errorCode) {
267b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    preParse(pattern, parseError, errorCode);
268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    parseMessage(0, 0, 0, UMSGPAT_ARG_TYPE_NONE, parseError, errorCode);
269b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    postParse();
270b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return *this;
271b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
272b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
273b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern &
274b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::parseChoiceStyle(const UnicodeString &pattern,
275b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                 UParseError *parseError, UErrorCode &errorCode) {
276b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    preParse(pattern, parseError, errorCode);
277b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    parseChoiceStyle(0, 0, parseError, errorCode);
278b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    postParse();
279b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return *this;
280b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
281b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
282b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern &
283b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::parsePluralStyle(const UnicodeString &pattern,
284b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                 UParseError *parseError, UErrorCode &errorCode) {
285b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    preParse(pattern, parseError, errorCode);
286b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    parsePluralOrSelectStyle(UMSGPAT_ARG_TYPE_PLURAL, 0, 0, parseError, errorCode);
287b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    postParse();
288b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return *this;
289b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
290b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
291b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern &
292b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::parseSelectStyle(const UnicodeString &pattern,
293b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                 UParseError *parseError, UErrorCode &errorCode) {
294b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    preParse(pattern, parseError, errorCode);
295b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    parsePluralOrSelectStyle(UMSGPAT_ARG_TYPE_SELECT, 0, 0, parseError, errorCode);
296b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    postParse();
297b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return *this;
298b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
299b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
300b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
301b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::clear() {
302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Mostly the same as preParse().
303b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    msg.remove();
304b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    hasArgNames=hasArgNumbers=FALSE;
305b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    needsAutoQuoting=FALSE;
306b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    partsLength=0;
307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    numericValuesLength=0;
308b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
309b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
310b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::operator==(const MessagePattern &other) const {
312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(this==&other) {
313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return TRUE;
314b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
315b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return
316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        aposMode==other.aposMode &&
317b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        msg==other.msg &&
318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // parts.equals(o.parts)
319b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        partsLength==other.partsLength &&
32054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        (partsLength==0 || partsList->equals(*other.partsList, partsLength));
321b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // No need to compare numericValues if msg and parts are the same.
322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
323b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
324b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
325b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::hashCode() const {
326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t hash=(aposMode*37+msg.hashCode())*37+partsLength;
327b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(int32_t i=0; i<partsLength; ++i) {
328b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        hash=hash*37+parts[i].hashCode();
329b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
330b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return hash;
331b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
333b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::validateArgumentName(const UnicodeString &name) {
335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(!PatternProps::isIdentifier(name.getBuffer(), name.length())) {
336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return UMSGPAT_ARG_NAME_NOT_VALID;
337b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
338b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return parseArgNumber(name, 0, name.length());
339b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
340b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString
342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::autoQuoteApostropheDeep() const {
343b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(!needsAutoQuoting) {
344b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return msg;
345b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString modified(msg);
347b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Iterate backward so that the insertion indexes do not change.
348b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t count=countParts();
349b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(int32_t i=count; i>0;) {
350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const Part &part=getPart(--i);
351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(part.getType()==UMSGPAT_PART_TYPE_INSERT_CHAR) {
352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho           modified.insert(part.index, (UChar)part.value);
353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
354b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
355b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return modified;
356b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
357b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
358b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehodouble
359b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::getNumericValue(const Part &part) const {
360b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UMessagePatternPartType type=part.type;
361b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(type==UMSGPAT_PART_TYPE_ARG_INT) {
362b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return part.value;
363b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if(type==UMSGPAT_PART_TYPE_ARG_DOUBLE) {
364b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return numericValues[part.value];
365b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
366b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return UMSGPAT_NO_NUMERIC_VALUE;
367b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
368b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  * Returns the "offset:" value of a PluralFormat argument, or 0 if none is specified.
372b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  * @param pluralStart the index of the first PluralFormat argument style part. (0..countParts()-1)
373b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  * @return the "offset:" value.
374b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  * @draft ICU 4.8
375b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  */
376b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehodouble
377b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::getPluralOffset(int32_t pluralStart) const {
378b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const Part &part=getPart(pluralStart);
379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(Part::hasNumericValue(part.type)) {
380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return getNumericValue(part);
381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// MessagePattern::Part ---------------------------------------------------- ***
387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
388b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
389b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::Part::operator==(const Part &other) const {
390b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(this==&other) {
391b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return TRUE;
392b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
393b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return
394b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        type==other.type &&
395b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        index==other.index &&
396b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        length==other.length &&
397b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        value==other.value &&
398b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        limitPartIndex==other.limitPartIndex;
399b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
400b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
401b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// MessagePattern parser --------------------------------------------------- ***
402b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
403b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
404b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::preParse(const UnicodeString &pattern, UParseError *parseError, UErrorCode &errorCode) {
405b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(errorCode)) {
406b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
407b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
408b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(parseError!=NULL) {
409b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        parseError->line=0;
410b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        parseError->offset=0;
411b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        parseError->preContext[0]=0;
412b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        parseError->postContext[0]=0;
413b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
414b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    msg=pattern;
415b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    hasArgNames=hasArgNumbers=FALSE;
416b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    needsAutoQuoting=FALSE;
417b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    partsLength=0;
418b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    numericValuesLength=0;
419b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
420b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
421b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
422b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::postParse() {
423b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(partsList!=NULL) {
424b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        parts=partsList->a.getAlias();
425b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
426b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(numericValuesList!=NULL) {
427b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        numericValues=numericValuesList->a.getAlias();
428b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
429b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
430b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
431b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
432b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::parseMessage(int32_t index, int32_t msgStartLength,
433b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                             int32_t nestingLevel, UMessagePatternArgType parentType,
434b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                             UParseError *parseError, UErrorCode &errorCode) {
435b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(errorCode)) {
436b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
437b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
438b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(nestingLevel>Part::MAX_VALUE) {
439b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
440b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
441b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
442b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t msgStart=partsLength;
443b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    addPart(UMSGPAT_PART_TYPE_MSG_START, index, msgStartLength, nestingLevel, errorCode);
444b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    index+=msgStartLength;
445b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(;;) {  // while(index<msg.length()) with U_FAILURE(errorCode) check
446b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(U_FAILURE(errorCode)) {
447b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
448b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
449b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(index>=msg.length()) {
450b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
451b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
452b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UChar c=msg.charAt(index++);
453b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(c==u_apos) {
454b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(index==msg.length()) {
455b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // The apostrophe is the last character in the pattern.
456b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // Add a Part for auto-quoting.
457b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                addPart(UMSGPAT_PART_TYPE_INSERT_CHAR, index, 0,
458b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        u_apos, errorCode);  // value=char to be inserted
459b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                needsAutoQuoting=TRUE;
460b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
461b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                c=msg.charAt(index);
462b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if(c==u_apos) {
463b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // double apostrophe, skip the second one
464b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    addPart(UMSGPAT_PART_TYPE_SKIP_SYNTAX, index++, 1, 0, errorCode);
465b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                } else if(
466b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    aposMode==UMSGPAT_APOS_DOUBLE_REQUIRED ||
467b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    c==u_leftCurlyBrace || c==u_rightCurlyBrace ||
468b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    (parentType==UMSGPAT_ARG_TYPE_CHOICE && c==u_pipe) ||
46954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                    (UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(parentType) && c==u_pound)
470b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ) {
471b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // skip the quote-starting apostrophe
472b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    addPart(UMSGPAT_PART_TYPE_SKIP_SYNTAX, index-1, 1, 0, errorCode);
473b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // find the end of the quoted literal text
474b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    for(;;) {
475b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        index=msg.indexOf(u_apos, index+1);
476b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        if(index>=0) {
477b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            if(/*(index+1)<msg.length() &&*/ msg.charAt(index+1)==u_apos) {
478b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                // double apostrophe inside quoted literal text
479b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                // still encodes a single apostrophe, skip the second one
480b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                addPart(UMSGPAT_PART_TYPE_SKIP_SYNTAX, ++index, 1, 0, errorCode);
481b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            } else {
482b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                // skip the quote-ending apostrophe
483b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                addPart(UMSGPAT_PART_TYPE_SKIP_SYNTAX, index++, 1, 0, errorCode);
484b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                break;
485b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            }
486b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        } else {
487b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            // The quoted text reaches to the end of the of the message.
488b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            index=msg.length();
489b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            // Add a Part for auto-quoting.
490b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            addPart(UMSGPAT_PART_TYPE_INSERT_CHAR, index, 0,
491b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                    u_apos, errorCode);  // value=char to be inserted
492b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            needsAutoQuoting=TRUE;
493b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            break;
494b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        }
495b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
496b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                } else {
497b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // Interpret the apostrophe as literal text.
498b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // Add a Part for auto-quoting.
499b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    addPart(UMSGPAT_PART_TYPE_INSERT_CHAR, index, 0,
500b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            u_apos, errorCode);  // value=char to be inserted
501b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    needsAutoQuoting=TRUE;
502b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
503b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
50454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        } else if(UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(parentType) && c==u_pound) {
505b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // The unquoted # in a plural message fragment will be replaced
506b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // with the (number-offset).
507b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            addPart(UMSGPAT_PART_TYPE_REPLACE_NUMBER, index-1, 1, 0, errorCode);
508b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if(c==u_leftCurlyBrace) {
509b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            index=parseArg(index-1, 1, nestingLevel, parseError, errorCode);
510b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if((nestingLevel>0 && c==u_rightCurlyBrace) ||
511b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  (parentType==UMSGPAT_ARG_TYPE_CHOICE && c==u_pipe)) {
512b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Finish the message before the terminator.
513b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // In a choice style, report the "}" substring only for the following ARG_LIMIT,
514b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // not for this MSG_LIMIT.
515b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t limitLength=(parentType==UMSGPAT_ARG_TYPE_CHOICE && c==u_rightCurlyBrace) ? 0 : 1;
516b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            addLimitPart(msgStart, UMSGPAT_PART_TYPE_MSG_LIMIT, index-1, limitLength,
517b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                         nestingLevel, errorCode);
518b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(parentType==UMSGPAT_ARG_TYPE_CHOICE) {
519b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // Let the choice style parser see the '}' or '|'.
520b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return index-1;
521b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
522b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // continue parsing after the '}'
523b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return index;
524b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
525b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }  // else: c is part of literal text
526b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
527b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(nestingLevel>0 && !inTopLevelChoiceMessage(nestingLevel, parentType)) {
528b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        setParseError(parseError, 0);  // Unmatched '{' braces in message.
529b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errorCode=U_UNMATCHED_BRACES;
530b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
531b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
532b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    addLimitPart(msgStart, UMSGPAT_PART_TYPE_MSG_LIMIT, index, 0, nestingLevel, errorCode);
533b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return index;
534b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
535b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
536b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
537b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::parseArg(int32_t index, int32_t argStartLength, int32_t nestingLevel,
538b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                         UParseError *parseError, UErrorCode &errorCode) {
539b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t argStart=partsLength;
540b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UMessagePatternArgType argType=UMSGPAT_ARG_TYPE_NONE;
541b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    addPart(UMSGPAT_PART_TYPE_ARG_START, index, argStartLength, argType, errorCode);
542b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(errorCode)) {
543b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
544b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
545b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t nameIndex=index=skipWhiteSpace(index+argStartLength);
546b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(index==msg.length()) {
547b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        setParseError(parseError, 0);  // Unmatched '{' braces in message.
548b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errorCode=U_UNMATCHED_BRACES;
549b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
550b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
551b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // parse argument name or number
552b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    index=skipIdentifier(index);
553b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t number=parseArgNumber(nameIndex, index);
554b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(number>=0) {
555b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t length=index-nameIndex;
556b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(length>Part::MAX_LENGTH || number>Part::MAX_VALUE) {
557b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            setParseError(parseError, nameIndex);  // Argument number too large.
558b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
559b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
560b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
561b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        hasArgNumbers=TRUE;
562b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        addPart(UMSGPAT_PART_TYPE_ARG_NUMBER, nameIndex, length, number, errorCode);
563b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if(number==UMSGPAT_ARG_NAME_NOT_NUMBER) {
564b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t length=index-nameIndex;
565b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(length>Part::MAX_LENGTH) {
566b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            setParseError(parseError, nameIndex);  // Argument name too long.
567b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
568b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
569b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
570b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        hasArgNames=TRUE;
571b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        addPart(UMSGPAT_PART_TYPE_ARG_NAME, nameIndex, length, 0, errorCode);
572b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {  // number<-1 (ARG_NAME_NOT_VALID)
573b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        setParseError(parseError, nameIndex);  // Bad argument syntax.
574b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errorCode=U_PATTERN_SYNTAX_ERROR;
575b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
576b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
577b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    index=skipWhiteSpace(index);
578b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(index==msg.length()) {
579b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        setParseError(parseError, 0);  // Unmatched '{' braces in message.
580b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errorCode=U_UNMATCHED_BRACES;
581b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
582b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
583b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar c=msg.charAt(index);
584b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(c==u_rightCurlyBrace) {
585b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // all done
586b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if(c!=u_comma) {
587b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        setParseError(parseError, nameIndex);  // Bad argument syntax.
588b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errorCode=U_PATTERN_SYNTAX_ERROR;
589b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
590b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else /* ',' */ {
591b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // parse argument type: case-sensitive a-zA-Z
592b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t typeIndex=index=skipWhiteSpace(index+1);
593b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        while(index<msg.length() && isArgTypeChar(msg.charAt(index))) {
594b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ++index;
595b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
596b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t length=index-typeIndex;
597b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        index=skipWhiteSpace(index);
598b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(index==msg.length()) {
599b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            setParseError(parseError, 0);  // Unmatched '{' braces in message.
600b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errorCode=U_UNMATCHED_BRACES;
601b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
602b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
603b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(length==0 || ((c=msg.charAt(index))!=u_comma && c!=u_rightCurlyBrace)) {
604b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            setParseError(parseError, nameIndex);  // Bad argument syntax.
605b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errorCode=U_PATTERN_SYNTAX_ERROR;
606b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
607b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
608b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(length>Part::MAX_LENGTH) {
609b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            setParseError(parseError, nameIndex);  // Argument type name too long.
610b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
611b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
612b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
613b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        argType=UMSGPAT_ARG_TYPE_SIMPLE;
614b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(length==6) {
615b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // case-insensitive comparisons for complex-type names
616b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(isChoice(typeIndex)) {
617b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                argType=UMSGPAT_ARG_TYPE_CHOICE;
618b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if(isPlural(typeIndex)) {
619b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                argType=UMSGPAT_ARG_TYPE_PLURAL;
620b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if(isSelect(typeIndex)) {
621b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                argType=UMSGPAT_ARG_TYPE_SELECT;
622b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
62354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        } else if(length==13) {
62454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            if(isSelect(typeIndex) && isOrdinal(typeIndex+6)) {
62554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                argType=UMSGPAT_ARG_TYPE_SELECTORDINAL;
62654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            }
627b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
628b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // change the ARG_START type from NONE to argType
629b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        partsList->a[argStart].value=(int16_t)argType;
630b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(argType==UMSGPAT_ARG_TYPE_SIMPLE) {
631b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            addPart(UMSGPAT_PART_TYPE_ARG_TYPE, typeIndex, length, 0, errorCode);
632b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
633b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // look for an argument style (pattern)
634b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(c==u_rightCurlyBrace) {
635b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(argType!=UMSGPAT_ARG_TYPE_SIMPLE) {
636b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                setParseError(parseError, nameIndex);  // No style field for complex argument.
637b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errorCode=U_PATTERN_SYNTAX_ERROR;
638b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return 0;
639b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
640b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else /* ',' */ {
641b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ++index;
642b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(argType==UMSGPAT_ARG_TYPE_SIMPLE) {
643b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                index=parseSimpleStyle(index, parseError, errorCode);
644b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if(argType==UMSGPAT_ARG_TYPE_CHOICE) {
645b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                index=parseChoiceStyle(index, nestingLevel, parseError, errorCode);
646b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
647b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                index=parsePluralOrSelectStyle(argType, index, nestingLevel, parseError, errorCode);
648b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
649b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
650b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
651b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Argument parsing stopped on the '}'.
652b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    addLimitPart(argStart, UMSGPAT_PART_TYPE_ARG_LIMIT, index, 1, argType, errorCode);
653b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return index+1;
654b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
655b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
656b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
657b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::parseSimpleStyle(int32_t index, UParseError *parseError, UErrorCode &errorCode) {
658b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(errorCode)) {
659b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
660b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
661b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t start=index;
662b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t nestedBraces=0;
663b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    while(index<msg.length()) {
664b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UChar c=msg.charAt(index++);
665b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(c==u_apos) {
666b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Treat apostrophe as quoting but include it in the style part.
667b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Find the end of the quoted literal text.
668b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            index=msg.indexOf(u_apos, index);
669b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(index<0) {
670b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // Quoted literal argument style text reaches to the end of the message.
671b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                setParseError(parseError, start);
672b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errorCode=U_PATTERN_SYNTAX_ERROR;
673b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return 0;
674b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
675b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // skip the quote-ending apostrophe
676b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ++index;
677b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if(c==u_leftCurlyBrace) {
678b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ++nestedBraces;
679b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if(c==u_rightCurlyBrace) {
680b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(nestedBraces>0) {
681b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                --nestedBraces;
682b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
683b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                int32_t length=--index-start;
684b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if(length>Part::MAX_LENGTH) {
685b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    setParseError(parseError, start);  // Argument style text too long.
686b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
687b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    return 0;
688b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
689b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                addPart(UMSGPAT_PART_TYPE_ARG_STYLE, start, length, 0, errorCode);
690b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return index;
691b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
692b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }  // c is part of literal text
693b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
694b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    setParseError(parseError, 0);  // Unmatched '{' braces in message.
695b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    errorCode=U_UNMATCHED_BRACES;
696b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return 0;
697b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
698b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
699b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
700b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::parseChoiceStyle(int32_t index, int32_t nestingLevel,
701b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                 UParseError *parseError, UErrorCode &errorCode) {
702b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(errorCode)) {
703b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
704b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
705b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t start=index;
706b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    index=skipWhiteSpace(index);
707b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(index==msg.length() || msg.charAt(index)==u_rightCurlyBrace) {
708b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        setParseError(parseError, 0);  // Missing choice argument pattern.
709b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errorCode=U_PATTERN_SYNTAX_ERROR;
710b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
711b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
712b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(;;) {
713b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // The choice argument style contains |-separated (number, separator, message) triples.
714b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Parse the number.
715b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t numberIndex=index;
716b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        index=skipDouble(index);
717b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t length=index-numberIndex;
718b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(length==0) {
719b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            setParseError(parseError, start);  // Bad choice pattern syntax.
720b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errorCode=U_PATTERN_SYNTAX_ERROR;
721b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
722b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
723b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(length>Part::MAX_LENGTH) {
724b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            setParseError(parseError, numberIndex);  // Choice number too long.
725b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
726b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
727b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
728b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        parseDouble(numberIndex, index, TRUE, parseError, errorCode);  // adds ARG_INT or ARG_DOUBLE
729b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(U_FAILURE(errorCode)) {
730b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
731b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
732b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Parse the separator.
733b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        index=skipWhiteSpace(index);
734b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(index==msg.length()) {
735b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            setParseError(parseError, start);  // Bad choice pattern syntax.
736b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errorCode=U_PATTERN_SYNTAX_ERROR;
737b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
738b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
739b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UChar c=msg.charAt(index);
740b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(!(c==u_pound || c==u_lessThan || c==u_lessOrEqual)) {  // U+2264 is <=
741b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            setParseError(parseError, start);  // Expected choice separator (#<\u2264) instead of c.
742b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errorCode=U_PATTERN_SYNTAX_ERROR;
743b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
744b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
745b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        addPart(UMSGPAT_PART_TYPE_ARG_SELECTOR, index, 1, 0, errorCode);
746b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Parse the message fragment.
747b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        index=parseMessage(++index, 0, nestingLevel+1, UMSGPAT_ARG_TYPE_CHOICE, parseError, errorCode);
748b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(U_FAILURE(errorCode)) {
749b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
750b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
751b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // parseMessage(..., CHOICE) returns the index of the terminator, or msg.length().
752b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(index==msg.length()) {
753b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return index;
754b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
755b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(msg.charAt(index)==u_rightCurlyBrace) {
756b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(!inMessageFormatPattern(nestingLevel)) {
757b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                setParseError(parseError, start);  // Bad choice pattern syntax.
758b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errorCode=U_PATTERN_SYNTAX_ERROR;
759b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return 0;
760b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
761b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return index;
762b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }  // else the terminator is '|'
763b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        index=skipWhiteSpace(index+1);
764b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
765b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
766b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
767b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
768b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::parsePluralOrSelectStyle(UMessagePatternArgType argType,
769b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                         int32_t index, int32_t nestingLevel,
770b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                         UParseError *parseError, UErrorCode &errorCode) {
771b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(errorCode)) {
772b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
773b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
774b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t start=index;
775b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool isEmpty=TRUE;
776b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool hasOther=FALSE;
777b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(;;) {
778b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // First, collect the selector looking for a small set of terminators.
779b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // It would be a little faster to consider the syntax of each possible
780b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // token right here, but that makes the code too complicated.
781b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        index=skipWhiteSpace(index);
782b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UBool eos=index==msg.length();
783b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(eos || msg.charAt(index)==u_rightCurlyBrace) {
784b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(eos==inMessageFormatPattern(nestingLevel)) {
785b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                setParseError(parseError, start);  // Bad plural/select pattern syntax.
786b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errorCode=U_PATTERN_SYNTAX_ERROR;
787b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return 0;
788b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
789b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(!hasOther) {
790b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                setParseError(parseError, 0);  // Missing 'other' keyword in plural/select pattern.
791b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errorCode=U_DEFAULT_KEYWORD_MISSING;
792b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return 0;
793b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
794b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return index;
795b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
796b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t selectorIndex=index;
79754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        if(UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType) && msg.charAt(selectorIndex)==u_equal) {
798b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // explicit-value plural selector: =double
799b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            index=skipDouble(index+1);
800b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t length=index-selectorIndex;
801b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(length==1) {
802b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                setParseError(parseError, start);  // Bad plural/select pattern syntax.
803b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errorCode=U_PATTERN_SYNTAX_ERROR;
804b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return 0;
805b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
806b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(length>Part::MAX_LENGTH) {
807b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                setParseError(parseError, selectorIndex);  // Argument selector too long.
808b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
809b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return 0;
810b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
811b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            addPart(UMSGPAT_PART_TYPE_ARG_SELECTOR, selectorIndex, length, 0, errorCode);
812b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            parseDouble(selectorIndex+1, index, FALSE,
813b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        parseError, errorCode);  // adds ARG_INT or ARG_DOUBLE
814b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
815b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            index=skipIdentifier(index);
816b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t length=index-selectorIndex;
817b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(length==0) {
818b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                setParseError(parseError, start);  // Bad plural/select pattern syntax.
819b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errorCode=U_PATTERN_SYNTAX_ERROR;
820b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return 0;
821b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
822b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Note: The ':' in "offset:" is just beyond the skipIdentifier() range.
82354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            if( UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType) && length==6 && index<msg.length() &&
824b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                0==msg.compare(selectorIndex, 7, kOffsetColon, 0, 7)
825b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ) {
826b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // plural offset, not a selector
827b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if(!isEmpty) {
828b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // Plural argument 'offset:' (if present) must precede key-message pairs.
829b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    setParseError(parseError, start);
830b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    errorCode=U_PATTERN_SYNTAX_ERROR;
831b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    return 0;
832b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
833b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // allow whitespace between offset: and its value
834b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                int32_t valueIndex=skipWhiteSpace(index+1);  // The ':' is at index.
835b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                index=skipDouble(valueIndex);
836b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if(index==valueIndex) {
837b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    setParseError(parseError, start);  // Missing value for plural 'offset:'.
838b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    errorCode=U_PATTERN_SYNTAX_ERROR;
839b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    return 0;
840b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
841b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if((index-valueIndex)>Part::MAX_LENGTH) {
842b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    setParseError(parseError, valueIndex);  // Plural offset value too long.
843b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
844b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    return 0;
845b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
846b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                parseDouble(valueIndex, index, FALSE,
847b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            parseError, errorCode);  // adds ARG_INT or ARG_DOUBLE
848b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if(U_FAILURE(errorCode)) {
849b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    return 0;
850b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
851b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                isEmpty=FALSE;
852b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                continue;  // no message fragment after the offset
853b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
854b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // normal selector word
855b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if(length>Part::MAX_LENGTH) {
856b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    setParseError(parseError, selectorIndex);  // Argument selector too long.
857b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
858b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    return 0;
859b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
860b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                addPart(UMSGPAT_PART_TYPE_ARG_SELECTOR, selectorIndex, length, 0, errorCode);
861b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if(0==msg.compare(selectorIndex, length, kOther, 0, 5)) {
862b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    hasOther=TRUE;
863b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
864b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
865b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
866b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(U_FAILURE(errorCode)) {
867b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
868b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
869b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
870b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // parse the message fragment following the selector
871b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        index=skipWhiteSpace(index);
872b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(index==msg.length() || msg.charAt(index)!=u_leftCurlyBrace) {
873b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            setParseError(parseError, selectorIndex);  // No message fragment after plural/select selector.
874b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errorCode=U_PATTERN_SYNTAX_ERROR;
875b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
876b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
877b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        index=parseMessage(index, 1, nestingLevel+1, argType, parseError, errorCode);
878b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(U_FAILURE(errorCode)) {
879b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
880b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
881b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        isEmpty=FALSE;
882b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
883b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
884b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
885b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
886b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::parseArgNumber(const UnicodeString &s, int32_t start, int32_t limit) {
887b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // If the identifier contains only ASCII digits, then it is an argument _number_
888b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // and must not have leading zeros (except "0" itself).
889b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Otherwise it is an argument _name_.
890b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(start>=limit) {
891b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return UMSGPAT_ARG_NAME_NOT_VALID;
892b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
893b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t number;
894b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Defer numeric errors until we know there are only digits.
895b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool badNumber;
896b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar c=s.charAt(start++);
897b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(c==0x30) {
898b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(start==limit) {
899b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return 0;
900b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
901b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            number=0;
902b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            badNumber=TRUE;  // leading zero
903b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
904b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if(0x31<=c && c<=0x39) {
905b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        number=c-0x30;
906b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        badNumber=FALSE;
907b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
908b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return UMSGPAT_ARG_NAME_NOT_NUMBER;
909b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
910b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    while(start<limit) {
911b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        c=s.charAt(start++);
912b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(0x30<=c && c<=0x39) {
913b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(number>=INT32_MAX/10) {
914b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                badNumber=TRUE;  // overflow
915b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
916b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            number=number*10+(c-0x30);
917b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
918b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return UMSGPAT_ARG_NAME_NOT_NUMBER;
919b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
920b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
921b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // There are only ASCII digits.
922b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(badNumber) {
923b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return UMSGPAT_ARG_NAME_NOT_VALID;
924b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
925b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return number;
926b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
927b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
928b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
929b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
930b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::parseDouble(int32_t start, int32_t limit, UBool allowInfinity,
931b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            UParseError *parseError, UErrorCode &errorCode) {
932b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(errorCode)) {
933b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
934b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
935b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    U_ASSERT(start<limit);
936b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // fake loop for easy exit and single throw statement
937103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    for(;;) { /*loop doesn't iterate*/
938b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // fast path for small integers and infinity
939b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t value=0;
940b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t isNegative=0;  // not boolean so that we can easily add it to value
941b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t index=start;
942b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UChar c=msg.charAt(index++);
943b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(c==u_minus) {
944b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            isNegative=1;
945b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(index==limit) {
946b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;  // no number
947b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
948b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            c=msg.charAt(index++);
949b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if(c==u_plus) {
950b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(index==limit) {
951b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;  // no number
952b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
953b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            c=msg.charAt(index++);
954b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
955b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(c==0x221e) {  // infinity
956b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(allowInfinity && index==limit) {
957b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                double infinity=uprv_getInfinity();
958b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                addArgDoublePart(
959b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    isNegative!=0 ? -infinity : infinity,
960b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    start, limit-start, errorCode);
961b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return;
962b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
963b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
964b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
965b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
966b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // try to parse the number as a small integer but fall back to a double
967b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        while('0'<=c && c<='9') {
968b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            value=value*10+(c-'0');
969b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(value>(Part::MAX_VALUE+isNegative)) {
970b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;  // not a small-enough integer
971b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
972b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if(index==limit) {
973b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                addPart(UMSGPAT_PART_TYPE_ARG_INT, start, limit-start,
974b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        isNegative!=0 ? -value : value, errorCode);
975b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return;
976b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
977b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            c=msg.charAt(index++);
978b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
979b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Let Double.parseDouble() throw a NumberFormatException.
980b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        char numberChars[128];
981b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t capacity=(int32_t)sizeof(numberChars);
982b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t length=limit-start;
983b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(length>=capacity) {
984b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;  // number too long
985b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
986b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        msg.extract(start, length, numberChars, capacity, US_INV);
987b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if((int32_t)uprv_strlen(numberChars)<length) {
988b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;  // contains non-invariant character that was turned into NUL
989b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
990b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        char *end;
991b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        double numericValue=uprv_strtod(numberChars, &end);
992b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(end!=(numberChars+length)) {
993b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;  // parsing error
994b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
995b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        addArgDoublePart(numericValue, start, length, errorCode);
996b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
997b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
998b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    setParseError(parseError, start /*, limit*/);  // Bad syntax for numeric value.
999b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    errorCode=U_PATTERN_SYNTAX_ERROR;
1000b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return;
1001b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1002b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1003b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
1004b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::skipWhiteSpace(int32_t index) {
1005b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *s=msg.getBuffer();
1006b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t msgLength=msg.length();
1007b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *t=PatternProps::skipWhiteSpace(s+index, msgLength-index);
1008b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return (int32_t)(t-s);
1009b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1010b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1011b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
1012b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::skipIdentifier(int32_t index) {
1013b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *s=msg.getBuffer();
1014b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t msgLength=msg.length();
1015b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *t=PatternProps::skipIdentifier(s+index, msgLength-index);
1016b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return (int32_t)(t-s);
1017b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1018b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1019b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
1020b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::skipDouble(int32_t index) {
1021b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t msgLength=msg.length();
1022b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    while(index<msgLength) {
1023b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UChar c=msg.charAt(index);
1024b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // U+221E: Allow the infinity symbol, for ChoiceFormat patterns.
1025b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if((c<0x30 && c!=u_plus && c!=u_minus && c!=u_dot) || (c>0x39 && c!=u_e && c!=u_E && c!=0x221e)) {
1026b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
1027b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1028b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ++index;
1029b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1030b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return index;
1031b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1032b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1033b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1034b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::isArgTypeChar(UChar32 c) {
1035b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return (u_a<=c && c<=u_z) || (u_A<=c && c<=u_Z);
1036b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1037b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1038b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1039b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::isChoice(int32_t index) {
1040b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar c;
1041b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return
1042b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_c || c==u_C) &&
1043b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_h || c==u_H) &&
1044b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_o || c==u_O) &&
1045b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_i || c==u_I) &&
1046b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_c || c==u_C) &&
1047b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index))==u_e || c==u_E);
1048b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1049b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1050b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1051b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::isPlural(int32_t index) {
1052b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar c;
1053b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return
1054b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_p || c==u_P) &&
1055b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_l || c==u_L) &&
1056b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_u || c==u_U) &&
1057b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_r || c==u_R) &&
1058b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_a || c==u_A) &&
1059b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index))==u_l || c==u_L);
1060b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1061b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1062b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1063b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::isSelect(int32_t index) {
1064b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar c;
1065b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return
1066b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_s || c==u_S) &&
1067b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_e || c==u_E) &&
1068b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_l || c==u_L) &&
1069b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_e || c==u_E) &&
1070b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index++))==u_c || c==u_C) &&
1071b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((c=msg.charAt(index))==u_t || c==u_T);
1072b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1073b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1074b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
107554dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusMessagePattern::isOrdinal(int32_t index) {
107654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    UChar c;
107754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    return
107854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        ((c=msg.charAt(index++))==u_o || c==u_O) &&
107954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        ((c=msg.charAt(index++))==u_r || c==u_R) &&
108054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        ((c=msg.charAt(index++))==u_d || c==u_D) &&
108154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        ((c=msg.charAt(index++))==u_i || c==u_I) &&
108254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        ((c=msg.charAt(index++))==u_n || c==u_N) &&
108354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        ((c=msg.charAt(index++))==u_a || c==u_A) &&
108454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        ((c=msg.charAt(index))==u_l || c==u_L);
108554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
108654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
108754dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusUBool
1088b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::inMessageFormatPattern(int32_t nestingLevel) {
1089b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return nestingLevel>0 || partsList->a[0].type==UMSGPAT_PART_TYPE_MSG_START;
1090b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1091b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1092b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1093b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::inTopLevelChoiceMessage(int32_t nestingLevel, UMessagePatternArgType parentType) {
1094b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return
1095b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        nestingLevel==1 &&
1096b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        parentType==UMSGPAT_ARG_TYPE_CHOICE &&
1097b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        partsList->a[0].type!=UMSGPAT_PART_TYPE_MSG_START;
1098b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1099b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1100b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
1101b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::addPart(UMessagePatternPartType type, int32_t index, int32_t length,
1102b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        int32_t value, UErrorCode &errorCode) {
1103b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(partsList->ensureCapacityForOneMore(partsLength, errorCode)) {
1104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        Part &part=partsList->a[partsLength++];
1105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        part.type=type;
1106b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        part.index=index;
1107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        part.length=(uint16_t)length;
1108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        part.value=(int16_t)value;
1109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        part.limitPartIndex=0;
1110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1112b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
1114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::addLimitPart(int32_t start,
1115b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                             UMessagePatternPartType type, int32_t index, int32_t length,
1116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                             int32_t value, UErrorCode &errorCode) {
1117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    partsList->a[start].limitPartIndex=partsLength;
1118b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    addPart(type, index, length, value, errorCode);
1119b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
1122b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::addArgDoublePart(double numericValue, int32_t start, int32_t length,
1123b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                 UErrorCode &errorCode) {
1124b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(errorCode)) {
1125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
1126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t numericIndex=numericValuesLength;
1128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(numericValuesList==NULL) {
1129b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        numericValuesList=new MessagePatternDoubleList();
1130b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(numericValuesList==NULL) {
1131b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errorCode=U_MEMORY_ALLOCATION_ERROR;
1132b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return;
1133b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if(!numericValuesList->ensureCapacityForOneMore(numericValuesLength, errorCode)) {
1135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
1136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
1137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(numericIndex>Part::MAX_VALUE) {
1138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
1139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return;
1140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    numericValuesList->a[numericValuesLength++]=numericValue;
1143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    addPart(UMSGPAT_PART_TYPE_ARG_DOUBLE, start, length, numericIndex, errorCode);
1144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
1147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessagePattern::setParseError(UParseError *parseError, int32_t index) {
1148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(parseError==NULL) {
1149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
1150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    parseError->offset=index;
1152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Set preContext to some of msg before index.
1154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Avoid splitting a surrogate pair.
1155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t length=index;
1156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(length>=U_PARSE_CONTEXT_LEN) {
1157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        length=U_PARSE_CONTEXT_LEN-1;
1158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(length>0 && U16_IS_TRAIL(msg[index-length])) {
1159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            --length;
1160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    msg.extract(index-length, length, parseError->preContext);
1163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    parseError->preContext[length]=0;
1164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1165b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Set postContext to some of msg starting at index.
1166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    length=msg.length()-index;
1167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(length>=U_PARSE_CONTEXT_LEN) {
1168b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        length=U_PARSE_CONTEXT_LEN-1;
1169b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(length>0 && U16_IS_LEAD(msg[index+length-1])) {
1170b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            --length;
1171b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1172b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1173b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    msg.extract(index, length, parseError->postContext);
1174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    parseError->postContext[length]=0;
1175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1176b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1177b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// MessageImpl ------------------------------------------------------------- ***
1178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1179b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
1180b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessageImpl::appendReducedApostrophes(const UnicodeString &s, int32_t start, int32_t limit,
1181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                      UnicodeString &sb) {
1182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t doubleApos=-1;
1183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(;;) {
1184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t i=s.indexOf(u_apos, start);
1185b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(i<0 || i>=limit) {
1186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            sb.append(s, start, limit-start);
1187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
1188b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(i==doubleApos) {
1190b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Double apostrophe at start-1 and start==i, append one.
1191b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            sb.append(u_apos);
1192b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ++start;
1193b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            doubleApos=-1;
1194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1195b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Append text between apostrophes and skip this one.
1196b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            sb.append(s, start, i-start);
1197b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            doubleApos=start=i+1;
1198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1199b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1200b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1202b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Ported from second half of ICU4J SelectFormat.format(String).
1203b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString &
1204b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessageImpl::appendSubMessageWithoutSkipSyntax(const MessagePattern &msgPattern,
1205b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                               int32_t msgStart,
1206b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                               UnicodeString &result) {
1207b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UnicodeString &msgString=msgPattern.getPatternString();
1208b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t prevIndex=msgPattern.getPart(msgStart).getLimit();
1209b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(int32_t i=msgStart;;) {
1210b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const MessagePattern::Part &part=msgPattern.getPart(++i);
1211b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UMessagePatternPartType type=part.getType();
1212b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t index=part.getIndex();
1213b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(type==UMSGPAT_PART_TYPE_MSG_LIMIT) {
1214b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return result.append(msgString, prevIndex, index-prevIndex);
1215b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if(type==UMSGPAT_PART_TYPE_SKIP_SYNTAX) {
1216b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            result.append(msgString, prevIndex, index-prevIndex);
1217b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            prevIndex=part.getLimit();
1218b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if(type==UMSGPAT_PART_TYPE_ARG_START) {
1219b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            result.append(msgString, prevIndex, index-prevIndex);
1220b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            prevIndex=index;
1221b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            i=msgPattern.getLimitPartIndex(i);
1222b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            index=msgPattern.getPart(i).getLimit();
1223b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            appendReducedApostrophes(msgString, prevIndex, index, result);
1224b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            prevIndex=index;
1225b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1226b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1227b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1228b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_NAMESPACE_END
1230b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1231b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#endif  // !UCONFIG_NO_FORMATTING
1232