16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Copyright (C) 2011-2012, International Business Machines
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Corporation and others.  All Rights Reserved.
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   file name:  messagepattern.cpp
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   encoding:   US-ASCII
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   tab size:   8 (not used)
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   indentation:4
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created on: 2011mar14
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created by: Markus W. Scherer
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h"
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if !UCONFIG_NO_FORMATTING
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/messagepattern.h"
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/unistr.h"
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utf16.h"
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h"
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cstring.h"
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "messageimpl.h"
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "patternprops.h"
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "putilimp.h"
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uassert.h"
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_BEGIN
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Unicode character/code point constants ---------------------------------- ***
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_pound=0x23;
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_apos=0x27;
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_plus=0x2B;
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_comma=0x2C;
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_minus=0x2D;
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_dot=0x2E;
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_colon=0x3A;
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_lessThan=0x3C;
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_equal=0x3D;
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_A=0x41;
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_C=0x43;
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_D=0x44;
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_E=0x45;
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_H=0x48;
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_I=0x49;
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_L=0x4C;
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_N=0x4E;
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_O=0x4F;
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_P=0x50;
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_R=0x52;
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_S=0x53;
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_T=0x54;
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_U=0x55;
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_Z=0x5A;
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_a=0x61;
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_c=0x63;
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_d=0x64;
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_e=0x65;
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_f=0x66;
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_h=0x68;
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_i=0x69;
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_l=0x6C;
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_n=0x6E;
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_o=0x6F;
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_p=0x70;
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_r=0x72;
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_s=0x73;
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_t=0x74;
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_u=0x75;
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_z=0x7A;
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_leftCurlyBrace=0x7B;
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_pipe=0x7C;
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_rightCurlyBrace=0x7D;
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar u_lessOrEqual=0x2264;  // U+2264 is <=
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar kOffsetColon[]={  // "offset:"
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    u_o, u_f, u_f, u_s, u_e, u_t, u_colon
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar kOther[]={  // "other"
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    u_o, u_t, u_h, u_e, u_r
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// MessagePatternList ------------------------------------------------------ ***
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgtemplate<typename T, int32_t stackCapacity>
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgclass MessagePatternList : public UMemory {
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgpublic:
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    MessagePatternList() {}
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    void copyFrom(const MessagePatternList<T, stackCapacity> &other,
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  int32_t length,
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  UErrorCode &errorCode);
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool ensureCapacityForOneMore(int32_t oldLength, UErrorCode &errorCode);
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool equals(const MessagePatternList<T, stackCapacity> &other, int32_t length) const {
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for(int32_t i=0; i<length; ++i) {
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(a[i]!=other.a[i]) { return FALSE; }
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    MaybeStackArray<T, stackCapacity> a;
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgtemplate<typename T, int32_t stackCapacity>
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePatternList<T, stackCapacity>::copyFrom(
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const MessagePatternList<T, stackCapacity> &other,
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t length,
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UErrorCode &errorCode) {
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_SUCCESS(errorCode) && length>0) {
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length>a.getCapacity() && NULL==a.resize(length)) {
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_MEMORY_ALLOCATION_ERROR;
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_memcpy(a.getAlias(), other.a.getAlias(), length*sizeof(T));
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgtemplate<typename T, int32_t stackCapacity>
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePatternList<T, stackCapacity>::ensureCapacityForOneMore(int32_t oldLength, UErrorCode &errorCode) {
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) {
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(a.getCapacity()>oldLength || a.resize(2*oldLength, oldLength)!=NULL) {
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    errorCode=U_MEMORY_ALLOCATION_ERROR;
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return FALSE;
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// MessagePatternList specializations -------------------------------------- ***
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgclass MessagePatternDoubleList : public MessagePatternList<double, 8> {
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgclass MessagePatternPartsList : public MessagePatternList<MessagePattern::Part, 32> {
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// MessagePattern constructors etc. ---------------------------------------- ***
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::MessagePattern(UErrorCode &errorCode)
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        : aposMode(UCONFIG_MSGPAT_DEFAULT_APOSTROPHE_MODE),
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          partsList(NULL), parts(NULL), partsLength(0),
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          numericValuesList(NULL), numericValues(NULL), numericValuesLength(0),
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          hasArgNames(FALSE), hasArgNumbers(FALSE), needsAutoQuoting(FALSE) {
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    init(errorCode);
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::MessagePattern(UMessagePatternApostropheMode mode, UErrorCode &errorCode)
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        : aposMode(mode),
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          partsList(NULL), parts(NULL), partsLength(0),
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          numericValuesList(NULL), numericValues(NULL), numericValuesLength(0),
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          hasArgNames(FALSE), hasArgNumbers(FALSE), needsAutoQuoting(FALSE) {
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    init(errorCode);
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::MessagePattern(const UnicodeString &pattern, UParseError *parseError, UErrorCode &errorCode)
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        : aposMode(UCONFIG_MSGPAT_DEFAULT_APOSTROPHE_MODE),
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          partsList(NULL), parts(NULL), partsLength(0),
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          numericValuesList(NULL), numericValues(NULL), numericValuesLength(0),
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          hasArgNames(FALSE), hasArgNumbers(FALSE), needsAutoQuoting(FALSE) {
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(init(errorCode)) {
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        parse(pattern, parseError, errorCode);
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::init(UErrorCode &errorCode) {
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) {
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    partsList=new MessagePatternPartsList();
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(partsList==NULL) {
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_MEMORY_ALLOCATION_ERROR;
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    parts=partsList->a.getAlias();
1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return TRUE;
1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::MessagePattern(const MessagePattern &other)
1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        : UObject(other), aposMode(other.aposMode), msg(other.msg),
1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          partsList(NULL), parts(NULL), partsLength(0),
1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          numericValuesList(NULL), numericValues(NULL), numericValuesLength(0),
1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          hasArgNames(other.hasArgNames), hasArgNumbers(other.hasArgNumbers),
1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          needsAutoQuoting(other.needsAutoQuoting) {
1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode errorCode=U_ZERO_ERROR;
1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!copyStorage(other, errorCode)) {
1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        clear();
1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern &
1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::operator=(const MessagePattern &other) {
1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(this==&other) {
1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return *this;
2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    aposMode=other.aposMode;
2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    msg=other.msg;
2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    hasArgNames=other.hasArgNames;
2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    hasArgNumbers=other.hasArgNumbers;
2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    needsAutoQuoting=other.needsAutoQuoting;
2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode errorCode=U_ZERO_ERROR;
2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!copyStorage(other, errorCode)) {
2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        clear();
2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return *this;
2116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
2146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::copyStorage(const MessagePattern &other, UErrorCode &errorCode) {
2156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) {
2166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return FALSE;
2176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    parts=NULL;
2196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    partsLength=0;
2206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    numericValues=NULL;
2216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    numericValuesLength=0;
2226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(partsList==NULL) {
2236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        partsList=new MessagePatternPartsList();
2246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(partsList==NULL) {
2256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_MEMORY_ALLOCATION_ERROR;
2266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
2276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        parts=partsList->a.getAlias();
2296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(other.partsLength>0) {
2316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        partsList->copyFrom(*other.partsList, other.partsLength, errorCode);
2326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_FAILURE(errorCode)) {
2336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
2346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        parts=partsList->a.getAlias();
2366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        partsLength=other.partsLength;
2376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(other.numericValuesLength>0) {
2396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(numericValuesList==NULL) {
2406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            numericValuesList=new MessagePatternDoubleList();
2416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(numericValuesList==NULL) {
2426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                errorCode=U_MEMORY_ALLOCATION_ERROR;
2436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return FALSE;
2446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
2456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            numericValues=numericValuesList->a.getAlias();
2466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        numericValuesList->copyFrom(
2486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *other.numericValuesList, other.numericValuesLength, errorCode);
2496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_FAILURE(errorCode)) {
2506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return FALSE;
2516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        numericValues=numericValuesList->a.getAlias();
2536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        numericValuesLength=other.numericValuesLength;
2546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return TRUE;
2566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::~MessagePattern() {
2596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    delete partsList;
2606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    delete numericValuesList;
2616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// MessagePattern API ------------------------------------------------------ ***
2646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern &
2666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::parse(const UnicodeString &pattern, UParseError *parseError, UErrorCode &errorCode) {
2676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    preParse(pattern, parseError, errorCode);
2686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    parseMessage(0, 0, 0, UMSGPAT_ARG_TYPE_NONE, parseError, errorCode);
2696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    postParse();
2706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return *this;
2716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern &
2746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::parseChoiceStyle(const UnicodeString &pattern,
2756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                 UParseError *parseError, UErrorCode &errorCode) {
2766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    preParse(pattern, parseError, errorCode);
2776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    parseChoiceStyle(0, 0, parseError, errorCode);
2786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    postParse();
2796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return *this;
2806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern &
2836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::parsePluralStyle(const UnicodeString &pattern,
2846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                 UParseError *parseError, UErrorCode &errorCode) {
2856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    preParse(pattern, parseError, errorCode);
2866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    parsePluralOrSelectStyle(UMSGPAT_ARG_TYPE_PLURAL, 0, 0, parseError, errorCode);
2876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    postParse();
2886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return *this;
2896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern &
2926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::parseSelectStyle(const UnicodeString &pattern,
2936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                 UParseError *parseError, UErrorCode &errorCode) {
2946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    preParse(pattern, parseError, errorCode);
2956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    parsePluralOrSelectStyle(UMSGPAT_ARG_TYPE_SELECT, 0, 0, parseError, errorCode);
2966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    postParse();
2976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return *this;
2986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
3016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::clear() {
3026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Mostly the same as preParse().
3036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    msg.remove();
3046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    hasArgNames=hasArgNumbers=FALSE;
3056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    needsAutoQuoting=FALSE;
3066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    partsLength=0;
3076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    numericValuesLength=0;
3086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
3116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::operator==(const MessagePattern &other) const {
3126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(this==&other) {
3136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
3146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return
3166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        aposMode==other.aposMode &&
3176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        msg==other.msg &&
3186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // parts.equals(o.parts)
3196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        partsLength==other.partsLength &&
3206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        (partsLength==0 || partsList->equals(*other.partsList, partsLength));
3216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // No need to compare numericValues if msg and parts are the same.
3226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
3256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::hashCode() const {
3266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t hash=(aposMode*37+msg.hashCode())*37+partsLength;
3276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(int32_t i=0; i<partsLength; ++i) {
3286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        hash=hash*37+parts[i].hashCode();
3296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return hash;
3316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
3346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::validateArgumentName(const UnicodeString &name) {
3356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!PatternProps::isIdentifier(name.getBuffer(), name.length())) {
3366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return UMSGPAT_ARG_NAME_NOT_VALID;
3376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return parseArgNumber(name, 0, name.length());
3396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString
3426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::autoQuoteApostropheDeep() const {
3436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!needsAutoQuoting) {
3446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return msg;
3456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UnicodeString modified(msg);
3476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Iterate backward so that the insertion indexes do not change.
3486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t count=countParts();
3496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(int32_t i=count; i>0;) {
3506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const Part &part=getPart(--i);
3516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(part.getType()==UMSGPAT_PART_TYPE_INSERT_CHAR) {
3526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org           modified.insert(part.index, (UChar)part.value);
3536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return modified;
3566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgdouble
3596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::getNumericValue(const Part &part) const {
3606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UMessagePatternPartType type=part.type;
3616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(type==UMSGPAT_PART_TYPE_ARG_INT) {
3626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return part.value;
3636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(type==UMSGPAT_PART_TYPE_ARG_DOUBLE) {
3646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return numericValues[part.value];
3656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
3666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return UMSGPAT_NO_NUMERIC_VALUE;
3676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
3716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  * Returns the "offset:" value of a PluralFormat argument, or 0 if none is specified.
3726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  * @param pluralStart the index of the first PluralFormat argument style part. (0..countParts()-1)
3736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  * @return the "offset:" value.
3746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  * @draft ICU 4.8
3756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  */
3766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgdouble
3776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::getPluralOffset(int32_t pluralStart) const {
3786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const Part &part=getPart(pluralStart);
3796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(Part::hasNumericValue(part.type)) {
3806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return getNumericValue(part);
3816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
3826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
3836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// MessagePattern::Part ---------------------------------------------------- ***
3876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
3896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::Part::operator==(const Part &other) const {
3906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(this==&other) {
3916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
3926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return
3946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        type==other.type &&
3956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        index==other.index &&
3966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length==other.length &&
3976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        value==other.value &&
3986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        limitPartIndex==other.limitPartIndex;
3996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// MessagePattern parser --------------------------------------------------- ***
4026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
4046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::preParse(const UnicodeString &pattern, UParseError *parseError, UErrorCode &errorCode) {
4056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) {
4066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
4076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(parseError!=NULL) {
4096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        parseError->line=0;
4106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        parseError->offset=0;
4116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        parseError->preContext[0]=0;
4126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        parseError->postContext[0]=0;
4136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    msg=pattern;
4156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    hasArgNames=hasArgNumbers=FALSE;
4166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    needsAutoQuoting=FALSE;
4176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    partsLength=0;
4186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    numericValuesLength=0;
4196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
4226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::postParse() {
4236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(partsList!=NULL) {
4246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        parts=partsList->a.getAlias();
4256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(numericValuesList!=NULL) {
4276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        numericValues=numericValuesList->a.getAlias();
4286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
4326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::parseMessage(int32_t index, int32_t msgStartLength,
4336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             int32_t nestingLevel, UMessagePatternArgType parentType,
4346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             UParseError *parseError, UErrorCode &errorCode) {
4356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) {
4366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
4376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(nestingLevel>Part::MAX_VALUE) {
4396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
4406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
4416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t msgStart=partsLength;
4436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    addPart(UMSGPAT_PART_TYPE_MSG_START, index, msgStartLength, nestingLevel, errorCode);
4446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    index+=msgStartLength;
4456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) {  // while(index<msg.length()) with U_FAILURE(errorCode) check
4466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_FAILURE(errorCode)) {
4476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
4486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(index>=msg.length()) {
4506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
4516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UChar c=msg.charAt(index++);
4536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(c==u_apos) {
4546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(index==msg.length()) {
4556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // The apostrophe is the last character in the pattern.
4566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // Add a Part for auto-quoting.
4576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                addPart(UMSGPAT_PART_TYPE_INSERT_CHAR, index, 0,
4586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        u_apos, errorCode);  // value=char to be inserted
4596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                needsAutoQuoting=TRUE;
4606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
4616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                c=msg.charAt(index);
4626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(c==u_apos) {
4636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    // double apostrophe, skip the second one
4646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    addPart(UMSGPAT_PART_TYPE_SKIP_SYNTAX, index++, 1, 0, errorCode);
4656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else if(
4666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    aposMode==UMSGPAT_APOS_DOUBLE_REQUIRED ||
4676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    c==u_leftCurlyBrace || c==u_rightCurlyBrace ||
4686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    (parentType==UMSGPAT_ARG_TYPE_CHOICE && c==u_pipe) ||
4696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    (UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(parentType) && c==u_pound)
4706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ) {
4716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    // skip the quote-starting apostrophe
4726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    addPart(UMSGPAT_PART_TYPE_SKIP_SYNTAX, index-1, 1, 0, errorCode);
4736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    // find the end of the quoted literal text
4746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    for(;;) {
4756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        index=msg.indexOf(u_apos, index+1);
4766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if(index>=0) {
4776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            if(/*(index+1)<msg.length() &&*/ msg.charAt(index+1)==u_apos) {
4786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                // double apostrophe inside quoted literal text
4796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                // still encodes a single apostrophe, skip the second one
4806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                addPart(UMSGPAT_PART_TYPE_SKIP_SYNTAX, ++index, 1, 0, errorCode);
4816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            } else {
4826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                // skip the quote-ending apostrophe
4836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                addPart(UMSGPAT_PART_TYPE_SKIP_SYNTAX, index++, 1, 0, errorCode);
4846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                break;
4856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            }
4866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        } else {
4876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            // The quoted text reaches to the end of the of the message.
4886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            index=msg.length();
4896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            // Add a Part for auto-quoting.
4906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            addPart(UMSGPAT_PART_TYPE_INSERT_CHAR, index, 0,
4916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                    u_apos, errorCode);  // value=char to be inserted
4926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            needsAutoQuoting=TRUE;
4936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            break;
4946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
4956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
4966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
4976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    // Interpret the apostrophe as literal text.
4986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    // Add a Part for auto-quoting.
4996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    addPart(UMSGPAT_PART_TYPE_INSERT_CHAR, index, 0,
5006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            u_apos, errorCode);  // value=char to be inserted
5016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    needsAutoQuoting=TRUE;
5026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
5036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(parentType) && c==u_pound) {
5056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // The unquoted # in a plural message fragment will be replaced
5066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // with the (number-offset).
5076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            addPart(UMSGPAT_PART_TYPE_REPLACE_NUMBER, index-1, 1, 0, errorCode);
5086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(c==u_leftCurlyBrace) {
5096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            index=parseArg(index-1, 1, nestingLevel, parseError, errorCode);
5106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if((nestingLevel>0 && c==u_rightCurlyBrace) ||
5116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  (parentType==UMSGPAT_ARG_TYPE_CHOICE && c==u_pipe)) {
5126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Finish the message before the terminator.
5136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // In a choice style, report the "}" substring only for the following ARG_LIMIT,
5146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // not for this MSG_LIMIT.
5156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t limitLength=(parentType==UMSGPAT_ARG_TYPE_CHOICE && c==u_rightCurlyBrace) ? 0 : 1;
5166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            addLimitPart(msgStart, UMSGPAT_PART_TYPE_MSG_LIMIT, index-1, limitLength,
5176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         nestingLevel, errorCode);
5186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(parentType==UMSGPAT_ARG_TYPE_CHOICE) {
5196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // Let the choice style parser see the '}' or '|'.
5206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return index-1;
5216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
5226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // continue parsing after the '}'
5236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return index;
5246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }  // else: c is part of literal text
5266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(nestingLevel>0 && !inTopLevelChoiceMessage(nestingLevel, parentType)) {
5286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        setParseError(parseError, 0);  // Unmatched '{' braces in message.
5296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_UNMATCHED_BRACES;
5306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
5316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    addLimitPart(msgStart, UMSGPAT_PART_TYPE_MSG_LIMIT, index, 0, nestingLevel, errorCode);
5336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return index;
5346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
5376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::parseArg(int32_t index, int32_t argStartLength, int32_t nestingLevel,
5386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UParseError *parseError, UErrorCode &errorCode) {
5396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t argStart=partsLength;
5406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UMessagePatternArgType argType=UMSGPAT_ARG_TYPE_NONE;
5416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    addPart(UMSGPAT_PART_TYPE_ARG_START, index, argStartLength, argType, errorCode);
5426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) {
5436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
5446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t nameIndex=index=skipWhiteSpace(index+argStartLength);
5466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(index==msg.length()) {
5476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        setParseError(parseError, 0);  // Unmatched '{' braces in message.
5486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_UNMATCHED_BRACES;
5496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
5506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // parse argument name or number
5526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    index=skipIdentifier(index);
5536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t number=parseArgNumber(nameIndex, index);
5546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(number>=0) {
5556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t length=index-nameIndex;
5566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length>Part::MAX_LENGTH || number>Part::MAX_VALUE) {
5576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            setParseError(parseError, nameIndex);  // Argument number too large.
5586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
5596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
5606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        hasArgNumbers=TRUE;
5626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        addPart(UMSGPAT_PART_TYPE_ARG_NUMBER, nameIndex, length, number, errorCode);
5636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(number==UMSGPAT_ARG_NAME_NOT_NUMBER) {
5646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t length=index-nameIndex;
5656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length>Part::MAX_LENGTH) {
5666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            setParseError(parseError, nameIndex);  // Argument name too long.
5676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
5686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
5696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        hasArgNames=TRUE;
5716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        addPart(UMSGPAT_PART_TYPE_ARG_NAME, nameIndex, length, 0, errorCode);
5726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {  // number<-1 (ARG_NAME_NOT_VALID)
5736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        setParseError(parseError, nameIndex);  // Bad argument syntax.
5746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_PATTERN_SYNTAX_ERROR;
5756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
5766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    index=skipWhiteSpace(index);
5786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(index==msg.length()) {
5796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        setParseError(parseError, 0);  // Unmatched '{' braces in message.
5806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_UNMATCHED_BRACES;
5816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
5826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar c=msg.charAt(index);
5846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(c==u_rightCurlyBrace) {
5856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // all done
5866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(c!=u_comma) {
5876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        setParseError(parseError, nameIndex);  // Bad argument syntax.
5886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_PATTERN_SYNTAX_ERROR;
5896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
5906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else /* ',' */ {
5916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // parse argument type: case-sensitive a-zA-Z
5926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t typeIndex=index=skipWhiteSpace(index+1);
5936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while(index<msg.length() && isArgTypeChar(msg.charAt(index))) {
5946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++index;
5956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t length=index-typeIndex;
5976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        index=skipWhiteSpace(index);
5986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(index==msg.length()) {
5996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            setParseError(parseError, 0);  // Unmatched '{' braces in message.
6006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_UNMATCHED_BRACES;
6016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
6026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length==0 || ((c=msg.charAt(index))!=u_comma && c!=u_rightCurlyBrace)) {
6046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            setParseError(parseError, nameIndex);  // Bad argument syntax.
6056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PATTERN_SYNTAX_ERROR;
6066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
6076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length>Part::MAX_LENGTH) {
6096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            setParseError(parseError, nameIndex);  // Argument type name too long.
6106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
6116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
6126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        argType=UMSGPAT_ARG_TYPE_SIMPLE;
6146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length==6) {
6156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // case-insensitive comparisons for complex-type names
6166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(isChoice(typeIndex)) {
6176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                argType=UMSGPAT_ARG_TYPE_CHOICE;
6186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if(isPlural(typeIndex)) {
6196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                argType=UMSGPAT_ARG_TYPE_PLURAL;
6206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if(isSelect(typeIndex)) {
6216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                argType=UMSGPAT_ARG_TYPE_SELECT;
6226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(length==13) {
6246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(isSelect(typeIndex) && isOrdinal(typeIndex+6)) {
6256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                argType=UMSGPAT_ARG_TYPE_SELECTORDINAL;
6266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // change the ARG_START type from NONE to argType
6296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        partsList->a[argStart].value=(int16_t)argType;
6306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(argType==UMSGPAT_ARG_TYPE_SIMPLE) {
6316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            addPart(UMSGPAT_PART_TYPE_ARG_TYPE, typeIndex, length, 0, errorCode);
6326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // look for an argument style (pattern)
6346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(c==u_rightCurlyBrace) {
6356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(argType!=UMSGPAT_ARG_TYPE_SIMPLE) {
6366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                setParseError(parseError, nameIndex);  // No style field for complex argument.
6376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                errorCode=U_PATTERN_SYNTAX_ERROR;
6386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
6396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else /* ',' */ {
6416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++index;
6426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(argType==UMSGPAT_ARG_TYPE_SIMPLE) {
6436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                index=parseSimpleStyle(index, parseError, errorCode);
6446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if(argType==UMSGPAT_ARG_TYPE_CHOICE) {
6456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                index=parseChoiceStyle(index, nestingLevel, parseError, errorCode);
6466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
6476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                index=parsePluralOrSelectStyle(argType, index, nestingLevel, parseError, errorCode);
6486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Argument parsing stopped on the '}'.
6526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    addLimitPart(argStart, UMSGPAT_PART_TYPE_ARG_LIMIT, index, 1, argType, errorCode);
6536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return index+1;
6546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
6576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::parseSimpleStyle(int32_t index, UParseError *parseError, UErrorCode &errorCode) {
6586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) {
6596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
6606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t start=index;
6626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t nestedBraces=0;
6636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(index<msg.length()) {
6646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UChar c=msg.charAt(index++);
6656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(c==u_apos) {
6666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Treat apostrophe as quoting but include it in the style part.
6676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Find the end of the quoted literal text.
6686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            index=msg.indexOf(u_apos, index);
6696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(index<0) {
6706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // Quoted literal argument style text reaches to the end of the message.
6716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                setParseError(parseError, start);
6726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                errorCode=U_PATTERN_SYNTAX_ERROR;
6736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
6746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // skip the quote-ending apostrophe
6766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++index;
6776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(c==u_leftCurlyBrace) {
6786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++nestedBraces;
6796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(c==u_rightCurlyBrace) {
6806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(nestedBraces>0) {
6816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                --nestedBraces;
6826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
6836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                int32_t length=--index-start;
6846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(length>Part::MAX_LENGTH) {
6856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    setParseError(parseError, start);  // Argument style text too long.
6866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
6876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return 0;
6886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
6896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                addPart(UMSGPAT_PART_TYPE_ARG_STYLE, start, length, 0, errorCode);
6906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return index;
6916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }  // c is part of literal text
6936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    setParseError(parseError, 0);  // Unmatched '{' braces in message.
6956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    errorCode=U_UNMATCHED_BRACES;
6966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return 0;
6976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
7006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::parseChoiceStyle(int32_t index, int32_t nestingLevel,
7016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                 UParseError *parseError, UErrorCode &errorCode) {
7026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) {
7036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
7046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t start=index;
7066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    index=skipWhiteSpace(index);
7076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(index==msg.length() || msg.charAt(index)==u_rightCurlyBrace) {
7086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        setParseError(parseError, 0);  // Missing choice argument pattern.
7096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        errorCode=U_PATTERN_SYNTAX_ERROR;
7106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
7116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) {
7136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // The choice argument style contains |-separated (number, separator, message) triples.
7146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Parse the number.
7156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t numberIndex=index;
7166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        index=skipDouble(index);
7176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t length=index-numberIndex;
7186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length==0) {
7196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            setParseError(parseError, start);  // Bad choice pattern syntax.
7206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PATTERN_SYNTAX_ERROR;
7216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
7226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length>Part::MAX_LENGTH) {
7246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            setParseError(parseError, numberIndex);  // Choice number too long.
7256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
7266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
7276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        parseDouble(numberIndex, index, TRUE, parseError, errorCode);  // adds ARG_INT or ARG_DOUBLE
7296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_FAILURE(errorCode)) {
7306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
7316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Parse the separator.
7336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        index=skipWhiteSpace(index);
7346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(index==msg.length()) {
7356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            setParseError(parseError, start);  // Bad choice pattern syntax.
7366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PATTERN_SYNTAX_ERROR;
7376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
7386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UChar c=msg.charAt(index);
7406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(!(c==u_pound || c==u_lessThan || c==u_lessOrEqual)) {  // U+2264 is <=
7416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            setParseError(parseError, start);  // Expected choice separator (#<\u2264) instead of c.
7426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PATTERN_SYNTAX_ERROR;
7436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
7446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        addPart(UMSGPAT_PART_TYPE_ARG_SELECTOR, index, 1, 0, errorCode);
7466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Parse the message fragment.
7476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        index=parseMessage(++index, 0, nestingLevel+1, UMSGPAT_ARG_TYPE_CHOICE, parseError, errorCode);
7486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_FAILURE(errorCode)) {
7496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
7506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // parseMessage(..., CHOICE) returns the index of the terminator, or msg.length().
7526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(index==msg.length()) {
7536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return index;
7546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(msg.charAt(index)==u_rightCurlyBrace) {
7566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(!inMessageFormatPattern(nestingLevel)) {
7576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                setParseError(parseError, start);  // Bad choice pattern syntax.
7586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                errorCode=U_PATTERN_SYNTAX_ERROR;
7596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
7606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
7616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return index;
7626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }  // else the terminator is '|'
7636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        index=skipWhiteSpace(index+1);
7646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
7686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::parsePluralOrSelectStyle(UMessagePatternArgType argType,
7696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                         int32_t index, int32_t nestingLevel,
7706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                         UParseError *parseError, UErrorCode &errorCode) {
7716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) {
7726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
7736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t start=index;
7756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool isEmpty=TRUE;
7766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool hasOther=FALSE;
7776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) {
7786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // First, collect the selector looking for a small set of terminators.
7796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // It would be a little faster to consider the syntax of each possible
7806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // token right here, but that makes the code too complicated.
7816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        index=skipWhiteSpace(index);
7826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UBool eos=index==msg.length();
7836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(eos || msg.charAt(index)==u_rightCurlyBrace) {
7846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(eos==inMessageFormatPattern(nestingLevel)) {
7856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                setParseError(parseError, start);  // Bad plural/select pattern syntax.
7866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                errorCode=U_PATTERN_SYNTAX_ERROR;
7876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
7886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
7896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(!hasOther) {
7906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                setParseError(parseError, 0);  // Missing 'other' keyword in plural/select pattern.
7916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                errorCode=U_DEFAULT_KEYWORD_MISSING;
7926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
7936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
7946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return index;
7956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t selectorIndex=index;
7976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType) && msg.charAt(selectorIndex)==u_equal) {
7986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // explicit-value plural selector: =double
7996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            index=skipDouble(index+1);
8006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t length=index-selectorIndex;
8016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(length==1) {
8026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                setParseError(parseError, start);  // Bad plural/select pattern syntax.
8036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                errorCode=U_PATTERN_SYNTAX_ERROR;
8046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
8056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(length>Part::MAX_LENGTH) {
8076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                setParseError(parseError, selectorIndex);  // Argument selector too long.
8086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
8096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
8106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            addPart(UMSGPAT_PART_TYPE_ARG_SELECTOR, selectorIndex, length, 0, errorCode);
8126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            parseDouble(selectorIndex+1, index, FALSE,
8136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        parseError, errorCode);  // adds ARG_INT or ARG_DOUBLE
8146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
8156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            index=skipIdentifier(index);
8166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t length=index-selectorIndex;
8176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(length==0) {
8186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                setParseError(parseError, start);  // Bad plural/select pattern syntax.
8196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                errorCode=U_PATTERN_SYNTAX_ERROR;
8206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
8216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Note: The ':' in "offset:" is just beyond the skipIdentifier() range.
8236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if( UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType) && length==6 && index<msg.length() &&
8246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                0==msg.compare(selectorIndex, 7, kOffsetColon, 0, 7)
8256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ) {
8266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // plural offset, not a selector
8276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(!isEmpty) {
8286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    // Plural argument 'offset:' (if present) must precede key-message pairs.
8296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    setParseError(parseError, start);
8306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    errorCode=U_PATTERN_SYNTAX_ERROR;
8316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return 0;
8326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // allow whitespace between offset: and its value
8346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                int32_t valueIndex=skipWhiteSpace(index+1);  // The ':' is at index.
8356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                index=skipDouble(valueIndex);
8366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(index==valueIndex) {
8376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    setParseError(parseError, start);  // Missing value for plural 'offset:'.
8386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    errorCode=U_PATTERN_SYNTAX_ERROR;
8396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return 0;
8406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if((index-valueIndex)>Part::MAX_LENGTH) {
8426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    setParseError(parseError, valueIndex);  // Plural offset value too long.
8436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
8446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return 0;
8456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                parseDouble(valueIndex, index, FALSE,
8476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            parseError, errorCode);  // adds ARG_INT or ARG_DOUBLE
8486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(U_FAILURE(errorCode)) {
8496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return 0;
8506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                isEmpty=FALSE;
8526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                continue;  // no message fragment after the offset
8536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
8546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // normal selector word
8556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(length>Part::MAX_LENGTH) {
8566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    setParseError(parseError, selectorIndex);  // Argument selector too long.
8576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
8586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return 0;
8596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                addPart(UMSGPAT_PART_TYPE_ARG_SELECTOR, selectorIndex, length, 0, errorCode);
8616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(0==msg.compare(selectorIndex, length, kOther, 0, 5)) {
8626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    hasOther=TRUE;
8636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_FAILURE(errorCode)) {
8676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
8686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // parse the message fragment following the selector
8716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        index=skipWhiteSpace(index);
8726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(index==msg.length() || msg.charAt(index)!=u_leftCurlyBrace) {
8736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            setParseError(parseError, selectorIndex);  // No message fragment after plural/select selector.
8746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_PATTERN_SYNTAX_ERROR;
8756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
8766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        index=parseMessage(index, 1, nestingLevel+1, argType, parseError, errorCode);
8786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_FAILURE(errorCode)) {
8796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
8806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        isEmpty=FALSE;
8826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
8846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
8866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::parseArgNumber(const UnicodeString &s, int32_t start, int32_t limit) {
8876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // If the identifier contains only ASCII digits, then it is an argument _number_
8886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // and must not have leading zeros (except "0" itself).
8896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Otherwise it is an argument _name_.
8906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(start>=limit) {
8916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return UMSGPAT_ARG_NAME_NOT_VALID;
8926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t number;
8946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Defer numeric errors until we know there are only digits.
8956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool badNumber;
8966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar c=s.charAt(start++);
8976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(c==0x30) {
8986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(start==limit) {
8996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
9006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
9016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            number=0;
9026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            badNumber=TRUE;  // leading zero
9036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(0x31<=c && c<=0x39) {
9056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        number=c-0x30;
9066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        badNumber=FALSE;
9076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
9086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return UMSGPAT_ARG_NAME_NOT_NUMBER;
9096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(start<limit) {
9116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        c=s.charAt(start++);
9126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(0x30<=c && c<=0x39) {
9136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(number>=INT32_MAX/10) {
9146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                badNumber=TRUE;  // overflow
9156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            number=number*10+(c-0x30);
9176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
9186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return UMSGPAT_ARG_NAME_NOT_NUMBER;
9196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // There are only ASCII digits.
9226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(badNumber) {
9236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return UMSGPAT_ARG_NAME_NOT_VALID;
9246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
9256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return number;
9266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
9286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
9306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::parseDouble(int32_t start, int32_t limit, UBool allowInfinity,
9316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            UParseError *parseError, UErrorCode &errorCode) {
9326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) {
9336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
9346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    U_ASSERT(start<limit);
9366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // fake loop for easy exit and single throw statement
9376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) { /*loop doesn't iterate*/
9386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // fast path for small integers and infinity
9396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t value=0;
9406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t isNegative=0;  // not boolean so that we can easily add it to value
9416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t index=start;
9426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UChar c=msg.charAt(index++);
9436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(c==u_minus) {
9446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            isNegative=1;
9456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(index==limit) {
9466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;  // no number
9476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            c=msg.charAt(index++);
9496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(c==u_plus) {
9506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(index==limit) {
9516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;  // no number
9526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            c=msg.charAt(index++);
9546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(c==0x221e) {  // infinity
9566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(allowInfinity && index==limit) {
9576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                double infinity=uprv_getInfinity();
9586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                addArgDoublePart(
9596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    isNegative!=0 ? -infinity : infinity,
9606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    start, limit-start, errorCode);
9616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
9626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
9636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
9646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // try to parse the number as a small integer but fall back to a double
9676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while('0'<=c && c<='9') {
9686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            value=value*10+(c-'0');
9696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(value>(Part::MAX_VALUE+isNegative)) {
9706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;  // not a small-enough integer
9716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(index==limit) {
9736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                addPart(UMSGPAT_PART_TYPE_ARG_INT, start, limit-start,
9746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        isNegative!=0 ? -value : value, errorCode);
9756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
9766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            c=msg.charAt(index++);
9786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Let Double.parseDouble() throw a NumberFormatException.
9806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char numberChars[128];
9816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t capacity=(int32_t)sizeof(numberChars);
9826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t length=limit-start;
9836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length>=capacity) {
9846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;  // number too long
9856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        msg.extract(start, length, numberChars, capacity, US_INV);
9876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((int32_t)uprv_strlen(numberChars)<length) {
9886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;  // contains non-invariant character that was turned into NUL
9896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char *end;
9916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        double numericValue=uprv_strtod(numberChars, &end);
9926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(end!=(numberChars+length)) {
9936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;  // parsing error
9946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        addArgDoublePart(numericValue, start, length, errorCode);
9966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
9976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    setParseError(parseError, start /*, limit*/);  // Bad syntax for numeric value.
9996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    errorCode=U_PATTERN_SYNTAX_ERROR;
10006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return;
10016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
10046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::skipWhiteSpace(int32_t index) {
10056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *s=msg.getBuffer();
10066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t msgLength=msg.length();
10076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *t=PatternProps::skipWhiteSpace(s+index, msgLength-index);
10086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (int32_t)(t-s);
10096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
10126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::skipIdentifier(int32_t index) {
10136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *s=msg.getBuffer();
10146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t msgLength=msg.length();
10156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *t=PatternProps::skipIdentifier(s+index, msgLength-index);
10166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (int32_t)(t-s);
10176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
10206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::skipDouble(int32_t index) {
10216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t msgLength=msg.length();
10226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(index<msgLength) {
10236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UChar c=msg.charAt(index);
10246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // U+221E: Allow the infinity symbol, for ChoiceFormat patterns.
10256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((c<0x30 && c!=u_plus && c!=u_minus && c!=u_dot) || (c>0x39 && c!=u_e && c!=u_E && c!=0x221e)) {
10266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
10276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ++index;
10296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return index;
10316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
10346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::isArgTypeChar(UChar32 c) {
10356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (u_a<=c && c<=u_z) || (u_A<=c && c<=u_Z);
10366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
10396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::isChoice(int32_t index) {
10406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar c;
10416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return
10426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_c || c==u_C) &&
10436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_h || c==u_H) &&
10446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_o || c==u_O) &&
10456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_i || c==u_I) &&
10466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_c || c==u_C) &&
10476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index))==u_e || c==u_E);
10486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
10516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::isPlural(int32_t index) {
10526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar c;
10536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return
10546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_p || c==u_P) &&
10556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_l || c==u_L) &&
10566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_u || c==u_U) &&
10576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_r || c==u_R) &&
10586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_a || c==u_A) &&
10596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index))==u_l || c==u_L);
10606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
10636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::isSelect(int32_t index) {
10646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar c;
10656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return
10666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_s || c==u_S) &&
10676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_e || c==u_E) &&
10686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_l || c==u_L) &&
10696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_e || c==u_E) &&
10706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_c || c==u_C) &&
10716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index))==u_t || c==u_T);
10726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
10756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::isOrdinal(int32_t index) {
10766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar c;
10776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return
10786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_o || c==u_O) &&
10796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_r || c==u_R) &&
10806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_d || c==u_D) &&
10816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_i || c==u_I) &&
10826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_n || c==u_N) &&
10836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index++))==u_a || c==u_A) &&
10846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((c=msg.charAt(index))==u_l || c==u_L);
10856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
10886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::inMessageFormatPattern(int32_t nestingLevel) {
10896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return nestingLevel>0 || partsList->a[0].type==UMSGPAT_PART_TYPE_MSG_START;
10906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
10936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::inTopLevelChoiceMessage(int32_t nestingLevel, UMessagePatternArgType parentType) {
10946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return
10956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        nestingLevel==1 &&
10966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        parentType==UMSGPAT_ARG_TYPE_CHOICE &&
10976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        partsList->a[0].type!=UMSGPAT_PART_TYPE_MSG_START;
10986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
11016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::addPart(UMessagePatternPartType type, int32_t index, int32_t length,
11026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        int32_t value, UErrorCode &errorCode) {
11036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(partsList->ensureCapacityForOneMore(partsLength, errorCode)) {
11046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        Part &part=partsList->a[partsLength++];
11056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        part.type=type;
11066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        part.index=index;
11076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        part.length=(uint16_t)length;
11086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        part.value=(int16_t)value;
11096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        part.limitPartIndex=0;
11106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
11126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
11146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::addLimitPart(int32_t start,
11156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             UMessagePatternPartType type, int32_t index, int32_t length,
11166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             int32_t value, UErrorCode &errorCode) {
11176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    partsList->a[start].limitPartIndex=partsLength;
11186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    addPart(type, index, length, value, errorCode);
11196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
11206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
11226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::addArgDoublePart(double numericValue, int32_t start, int32_t length,
11236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                 UErrorCode &errorCode) {
11246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(errorCode)) {
11256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
11266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t numericIndex=numericValuesLength;
11286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(numericValuesList==NULL) {
11296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        numericValuesList=new MessagePatternDoubleList();
11306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(numericValuesList==NULL) {
11316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_MEMORY_ALLOCATION_ERROR;
11326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
11336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(!numericValuesList->ensureCapacityForOneMore(numericValuesLength, errorCode)) {
11356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
11366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
11376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(numericIndex>Part::MAX_VALUE) {
11386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
11396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
11406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    numericValuesList->a[numericValuesLength++]=numericValue;
11436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    addPart(UMSGPAT_PART_TYPE_ARG_DOUBLE, start, length, numericIndex, errorCode);
11446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
11456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
11476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessagePattern::setParseError(UParseError *parseError, int32_t index) {
11486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(parseError==NULL) {
11496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
11506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    parseError->offset=index;
11526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Set preContext to some of msg before index.
11546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Avoid splitting a surrogate pair.
11556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length=index;
11566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(length>=U_PARSE_CONTEXT_LEN) {
11576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=U_PARSE_CONTEXT_LEN-1;
11586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length>0 && U16_IS_TRAIL(msg[index-length])) {
11596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            --length;
11606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    msg.extract(index-length, length, parseError->preContext);
11636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    parseError->preContext[length]=0;
11646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Set postContext to some of msg starting at index.
11666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    length=msg.length()-index;
11676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(length>=U_PARSE_CONTEXT_LEN) {
11686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=U_PARSE_CONTEXT_LEN-1;
11696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length>0 && U16_IS_LEAD(msg[index+length-1])) {
11706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            --length;
11716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    msg.extract(index, length, parseError->postContext);
11746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    parseError->postContext[length]=0;
11756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
11766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// MessageImpl ------------------------------------------------------------- ***
11786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
11806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessageImpl::appendReducedApostrophes(const UnicodeString &s, int32_t start, int32_t limit,
11816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                      UnicodeString &sb) {
11826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t doubleApos=-1;
11836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) {
11846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t i=s.indexOf(u_apos, start);
11856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(i<0 || i>=limit) {
11866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sb.append(s, start, limit-start);
11876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
11886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(i==doubleApos) {
11906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Double apostrophe at start-1 and start==i, append one.
11916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sb.append(u_apos);
11926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++start;
11936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            doubleApos=-1;
11946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
11956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // Append text between apostrophes and skip this one.
11966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            sb.append(s, start, i-start);
11976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            doubleApos=start=i+1;
11986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Ported from second half of ICU4J SelectFormat.format(String).
12036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString &
12046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgMessageImpl::appendSubMessageWithoutSkipSyntax(const MessagePattern &msgPattern,
12056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                               int32_t msgStart,
12066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                               UnicodeString &result) {
12076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UnicodeString &msgString=msgPattern.getPatternString();
12086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t prevIndex=msgPattern.getPart(msgStart).getLimit();
12096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(int32_t i=msgStart;;) {
12106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const MessagePattern::Part &part=msgPattern.getPart(++i);
12116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UMessagePatternPartType type=part.getType();
12126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t index=part.getIndex();
12136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(type==UMSGPAT_PART_TYPE_MSG_LIMIT) {
12146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return result.append(msgString, prevIndex, index-prevIndex);
12156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(type==UMSGPAT_PART_TYPE_SKIP_SYNTAX) {
12166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            result.append(msgString, prevIndex, index-prevIndex);
12176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            prevIndex=part.getLimit();
12186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(type==UMSGPAT_PART_TYPE_ARG_START) {
12196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            result.append(msgString, prevIndex, index-prevIndex);
12206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            prevIndex=index;
12216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            i=msgPattern.getLimitPartIndex(i);
12226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            index=msgPattern.getPart(i).getLimit();
12236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            appendReducedApostrophes(msgString, prevIndex, index, result);
12246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            prevIndex=index;
12256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
12266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_END
12306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif  // !UCONFIG_NO_FORMATTING
1232