Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/common/unicode/messagepattern.h
38827 views
/*1*******************************************************************************2* Copyright (C) 2011-2013, International Business Machines3* Corporation and others. All Rights Reserved.4*******************************************************************************5* file name: messagepattern.h6* encoding: US-ASCII7* tab size: 8 (not used)8* indentation:49*10* created on: 2011mar1411* created by: Markus W. Scherer12*/1314#ifndef __MESSAGEPATTERN_H__15#define __MESSAGEPATTERN_H__1617/**18* \file19* \brief C++ API: MessagePattern class: Parses and represents ICU MessageFormat patterns.20*/2122#include "unicode/utypes.h"2324#if !UCONFIG_NO_FORMATTING2526#include "unicode/parseerr.h"27#include "unicode/unistr.h"2829/**30* Mode for when an apostrophe starts quoted literal text for MessageFormat output.31* The default is DOUBLE_OPTIONAL unless overridden via uconfig.h32* (UCONFIG_MSGPAT_DEFAULT_APOSTROPHE_MODE).33* <p>34* A pair of adjacent apostrophes always results in a single apostrophe in the output,35* even when the pair is between two single, text-quoting apostrophes.36* <p>37* The following table shows examples of desired MessageFormat.format() output38* with the pattern strings that yield that output.39* <p>40* <table>41* <tr>42* <th>Desired output</th>43* <th>DOUBLE_OPTIONAL</th>44* <th>DOUBLE_REQUIRED</th>45* </tr>46* <tr>47* <td>I see {many}</td>48* <td>I see '{many}'</td>49* <td>(same)</td>50* </tr>51* <tr>52* <td>I said {'Wow!'}</td>53* <td>I said '{''Wow!''}'</td>54* <td>(same)</td>55* </tr>56* <tr>57* <td>I don't know</td>58* <td>I don't know OR<br> I don''t know</td>59* <td>I don''t know</td>60* </tr>61* </table>62* @stable ICU 4.863* @see UCONFIG_MSGPAT_DEFAULT_APOSTROPHE_MODE64*/65enum UMessagePatternApostropheMode {66/**67* A literal apostrophe is represented by68* either a single or a double apostrophe pattern character.69* Within a MessageFormat pattern, a single apostrophe only starts quoted literal text70* if it immediately precedes a curly brace {},71* or a pipe symbol | if inside a choice format,72* or a pound symbol # if inside a plural format.73* <p>74* This is the default behavior starting with ICU 4.8.75* @stable ICU 4.876*/77UMSGPAT_APOS_DOUBLE_OPTIONAL,78/**79* A literal apostrophe must be represented by80* a double apostrophe pattern character.81* A single apostrophe always starts quoted literal text.82* <p>83* This is the behavior of ICU 4.6 and earlier, and of the JDK.84* @stable ICU 4.885*/86UMSGPAT_APOS_DOUBLE_REQUIRED87};88/**89* @stable ICU 4.890*/91typedef enum UMessagePatternApostropheMode UMessagePatternApostropheMode;9293/**94* MessagePattern::Part type constants.95* @stable ICU 4.896*/97enum UMessagePatternPartType {98/**99* Start of a message pattern (main or nested).100* The length is 0 for the top-level message101* and for a choice argument sub-message, otherwise 1 for the '{'.102* The value indicates the nesting level, starting with 0 for the main message.103* <p>104* There is always a later MSG_LIMIT part.105* @stable ICU 4.8106*/107UMSGPAT_PART_TYPE_MSG_START,108/**109* End of a message pattern (main or nested).110* The length is 0 for the top-level message and111* the last sub-message of a choice argument,112* otherwise 1 for the '}' or (in a choice argument style) the '|'.113* The value indicates the nesting level, starting with 0 for the main message.114* @stable ICU 4.8115*/116UMSGPAT_PART_TYPE_MSG_LIMIT,117/**118* Indicates a substring of the pattern string which is to be skipped when formatting.119* For example, an apostrophe that begins or ends quoted text120* would be indicated with such a part.121* The value is undefined and currently always 0.122* @stable ICU 4.8123*/124UMSGPAT_PART_TYPE_SKIP_SYNTAX,125/**126* Indicates that a syntax character needs to be inserted for auto-quoting.127* The length is 0.128* The value is the character code of the insertion character. (U+0027=APOSTROPHE)129* @stable ICU 4.8130*/131UMSGPAT_PART_TYPE_INSERT_CHAR,132/**133* Indicates a syntactic (non-escaped) # symbol in a plural variant.134* When formatting, replace this part's substring with the135* (value-offset) for the plural argument value.136* The value is undefined and currently always 0.137* @stable ICU 4.8138*/139UMSGPAT_PART_TYPE_REPLACE_NUMBER,140/**141* Start of an argument.142* The length is 1 for the '{'.143* The value is the ordinal value of the ArgType. Use getArgType().144* <p>145* This part is followed by either an ARG_NUMBER or ARG_NAME,146* followed by optional argument sub-parts (see UMessagePatternArgType constants)147* and finally an ARG_LIMIT part.148* @stable ICU 4.8149*/150UMSGPAT_PART_TYPE_ARG_START,151/**152* End of an argument.153* The length is 1 for the '}'.154* The value is the ordinal value of the ArgType. Use getArgType().155* @stable ICU 4.8156*/157UMSGPAT_PART_TYPE_ARG_LIMIT,158/**159* The argument number, provided by the value.160* @stable ICU 4.8161*/162UMSGPAT_PART_TYPE_ARG_NUMBER,163/**164* The argument name.165* The value is undefined and currently always 0.166* @stable ICU 4.8167*/168UMSGPAT_PART_TYPE_ARG_NAME,169/**170* The argument type.171* The value is undefined and currently always 0.172* @stable ICU 4.8173*/174UMSGPAT_PART_TYPE_ARG_TYPE,175/**176* The argument style text.177* The value is undefined and currently always 0.178* @stable ICU 4.8179*/180UMSGPAT_PART_TYPE_ARG_STYLE,181/**182* A selector substring in a "complex" argument style.183* The value is undefined and currently always 0.184* @stable ICU 4.8185*/186UMSGPAT_PART_TYPE_ARG_SELECTOR,187/**188* An integer value, for example the offset or an explicit selector value189* in a PluralFormat style.190* The part value is the integer value.191* @stable ICU 4.8192*/193UMSGPAT_PART_TYPE_ARG_INT,194/**195* A numeric value, for example the offset or an explicit selector value196* in a PluralFormat style.197* The part value is an index into an internal array of numeric values;198* use getNumericValue().199* @stable ICU 4.8200*/201UMSGPAT_PART_TYPE_ARG_DOUBLE202};203/**204* @stable ICU 4.8205*/206typedef enum UMessagePatternPartType UMessagePatternPartType;207208/**209* Argument type constants.210* Returned by Part.getArgType() for ARG_START and ARG_LIMIT parts.211*212* Messages nested inside an argument are each delimited by MSG_START and MSG_LIMIT,213* with a nesting level one greater than the surrounding message.214* @stable ICU 4.8215*/216enum UMessagePatternArgType {217/**218* The argument has no specified type.219* @stable ICU 4.8220*/221UMSGPAT_ARG_TYPE_NONE,222/**223* The argument has a "simple" type which is provided by the ARG_TYPE part.224* An ARG_STYLE part might follow that.225* @stable ICU 4.8226*/227UMSGPAT_ARG_TYPE_SIMPLE,228/**229* The argument is a ChoiceFormat with one or more230* ((ARG_INT | ARG_DOUBLE), ARG_SELECTOR, message) tuples.231* @stable ICU 4.8232*/233UMSGPAT_ARG_TYPE_CHOICE,234/**235* The argument is a cardinal-number PluralFormat with an optional ARG_INT or ARG_DOUBLE offset236* (e.g., offset:1)237* and one or more (ARG_SELECTOR [explicit-value] message) tuples.238* If the selector has an explicit value (e.g., =2), then239* that value is provided by the ARG_INT or ARG_DOUBLE part preceding the message.240* Otherwise the message immediately follows the ARG_SELECTOR.241* @stable ICU 4.8242*/243UMSGPAT_ARG_TYPE_PLURAL,244/**245* The argument is a SelectFormat with one or more (ARG_SELECTOR, message) pairs.246* @stable ICU 4.8247*/248UMSGPAT_ARG_TYPE_SELECT,249/**250* The argument is an ordinal-number PluralFormat251* with the same style parts sequence and semantics as UMSGPAT_ARG_TYPE_PLURAL.252* @stable ICU 50253*/254UMSGPAT_ARG_TYPE_SELECTORDINAL255};256/**257* @stable ICU 4.8258*/259typedef enum UMessagePatternArgType UMessagePatternArgType;260261/**262* \def UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE263* Returns TRUE if the argument type has a plural style part sequence and semantics,264* for example UMSGPAT_ARG_TYPE_PLURAL and UMSGPAT_ARG_TYPE_SELECTORDINAL.265* @stable ICU 50266*/267#define UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType) \268((argType)==UMSGPAT_ARG_TYPE_PLURAL || (argType)==UMSGPAT_ARG_TYPE_SELECTORDINAL)269270enum {271/**272* Return value from MessagePattern.validateArgumentName() for when273* the string is a valid "pattern identifier" but not a number.274* @stable ICU 4.8275*/276UMSGPAT_ARG_NAME_NOT_NUMBER=-1,277278/**279* Return value from MessagePattern.validateArgumentName() for when280* the string is invalid.281* It might not be a valid "pattern identifier",282* or it have only ASCII digits but there is a leading zero or the number is too large.283* @stable ICU 4.8284*/285UMSGPAT_ARG_NAME_NOT_VALID=-2286};287288/**289* Special value that is returned by getNumericValue(Part) when no290* numeric value is defined for a part.291* @see MessagePattern.getNumericValue()292* @stable ICU 4.8293*/294#define UMSGPAT_NO_NUMERIC_VALUE ((double)(-123456789))295296U_NAMESPACE_BEGIN297298class MessagePatternDoubleList;299class MessagePatternPartsList;300301/**302* Parses and represents ICU MessageFormat patterns.303* Also handles patterns for ChoiceFormat, PluralFormat and SelectFormat.304* Used in the implementations of those classes as well as in tools305* for message validation, translation and format conversion.306* <p>307* The parser handles all syntax relevant for identifying message arguments.308* This includes "complex" arguments whose style strings contain309* nested MessageFormat pattern substrings.310* For "simple" arguments (with no nested MessageFormat pattern substrings),311* the argument style is not parsed any further.312* <p>313* The parser handles named and numbered message arguments and allows both in one message.314* <p>315* Once a pattern has been parsed successfully, iterate through the parsed data316* with countParts(), getPart() and related methods.317* <p>318* The data logically represents a parse tree, but is stored and accessed319* as a list of "parts" for fast and simple parsing and to minimize object allocations.320* Arguments and nested messages are best handled via recursion.321* For every _START "part", MessagePattern.getLimitPartIndex() efficiently returns322* the index of the corresponding _LIMIT "part".323* <p>324* List of "parts":325* <pre>326* message = MSG_START (SKIP_SYNTAX | INSERT_CHAR | REPLACE_NUMBER | argument)* MSG_LIMIT327* argument = noneArg | simpleArg | complexArg328* complexArg = choiceArg | pluralArg | selectArg329*330* noneArg = ARG_START.NONE (ARG_NAME | ARG_NUMBER) ARG_LIMIT.NONE331* simpleArg = ARG_START.SIMPLE (ARG_NAME | ARG_NUMBER) ARG_TYPE [ARG_STYLE] ARG_LIMIT.SIMPLE332* choiceArg = ARG_START.CHOICE (ARG_NAME | ARG_NUMBER) choiceStyle ARG_LIMIT.CHOICE333* pluralArg = ARG_START.PLURAL (ARG_NAME | ARG_NUMBER) pluralStyle ARG_LIMIT.PLURAL334* selectArg = ARG_START.SELECT (ARG_NAME | ARG_NUMBER) selectStyle ARG_LIMIT.SELECT335*336* choiceStyle = ((ARG_INT | ARG_DOUBLE) ARG_SELECTOR message)+337* pluralStyle = [ARG_INT | ARG_DOUBLE] (ARG_SELECTOR [ARG_INT | ARG_DOUBLE] message)+338* selectStyle = (ARG_SELECTOR message)+339* </pre>340* <ul>341* <li>Literal output text is not represented directly by "parts" but accessed342* between parts of a message, from one part's getLimit() to the next part's getIndex().343* <li><code>ARG_START.CHOICE</code> stands for an ARG_START Part with ArgType CHOICE.344* <li>In the choiceStyle, the ARG_SELECTOR has the '<', the '#' or345* the less-than-or-equal-to sign (U+2264).346* <li>In the pluralStyle, the first, optional numeric Part has the "offset:" value.347* The optional numeric Part between each (ARG_SELECTOR, message) pair348* is the value of an explicit-number selector like "=2",349* otherwise the selector is a non-numeric identifier.350* <li>The REPLACE_NUMBER Part can occur only in an immediate sub-message of the pluralStyle.351* </ul>352* <p>353* This class is not intended for public subclassing.354*355* @stable ICU 4.8356*/357class U_COMMON_API MessagePattern : public UObject {358public:359/**360* Constructs an empty MessagePattern with default UMessagePatternApostropheMode.361* @param errorCode Standard ICU error code. Its input value must362* pass the U_SUCCESS() test, or else the function returns363* immediately. Check for U_FAILURE() on output or use with364* function chaining. (See User Guide for details.)365* @stable ICU 4.8366*/367MessagePattern(UErrorCode &errorCode);368369/**370* Constructs an empty MessagePattern.371* @param mode Explicit UMessagePatternApostropheMode.372* @param errorCode Standard ICU error code. Its input value must373* pass the U_SUCCESS() test, or else the function returns374* immediately. Check for U_FAILURE() on output or use with375* function chaining. (See User Guide for details.)376* @stable ICU 4.8377*/378MessagePattern(UMessagePatternApostropheMode mode, UErrorCode &errorCode);379380/**381* Constructs a MessagePattern with default UMessagePatternApostropheMode and382* parses the MessageFormat pattern string.383* @param pattern a MessageFormat pattern string384* @param parseError Struct to receive information on the position385* of an error within the pattern.386* Can be NULL.387* @param errorCode Standard ICU error code. Its input value must388* pass the U_SUCCESS() test, or else the function returns389* immediately. Check for U_FAILURE() on output or use with390* function chaining. (See User Guide for details.)391* TODO: turn @throws into UErrorCode specifics?392* @throws IllegalArgumentException for syntax errors in the pattern string393* @throws IndexOutOfBoundsException if certain limits are exceeded394* (e.g., argument number too high, argument name too long, etc.)395* @throws NumberFormatException if a number could not be parsed396* @stable ICU 4.8397*/398MessagePattern(const UnicodeString &pattern, UParseError *parseError, UErrorCode &errorCode);399400/**401* Copy constructor.402* @param other Object to copy.403* @stable ICU 4.8404*/405MessagePattern(const MessagePattern &other);406407/**408* Assignment operator.409* @param other Object to copy.410* @return *this=other411* @stable ICU 4.8412*/413MessagePattern &operator=(const MessagePattern &other);414415/**416* Destructor.417* @stable ICU 4.8418*/419virtual ~MessagePattern();420421/**422* Parses a MessageFormat pattern string.423* @param pattern a MessageFormat pattern string424* @param parseError Struct to receive information on the position425* of an error within the pattern.426* Can be NULL.427* @param errorCode Standard ICU error code. Its input value must428* pass the U_SUCCESS() test, or else the function returns429* immediately. Check for U_FAILURE() on output or use with430* function chaining. (See User Guide for details.)431* @return *this432* @throws IllegalArgumentException for syntax errors in the pattern string433* @throws IndexOutOfBoundsException if certain limits are exceeded434* (e.g., argument number too high, argument name too long, etc.)435* @throws NumberFormatException if a number could not be parsed436* @stable ICU 4.8437*/438MessagePattern &parse(const UnicodeString &pattern,439UParseError *parseError, UErrorCode &errorCode);440441/**442* Parses a ChoiceFormat pattern string.443* @param pattern a ChoiceFormat pattern string444* @param parseError Struct to receive information on the position445* of an error within the pattern.446* Can be NULL.447* @param errorCode Standard ICU error code. Its input value must448* pass the U_SUCCESS() test, or else the function returns449* immediately. Check for U_FAILURE() on output or use with450* function chaining. (See User Guide for details.)451* @return *this452* @throws IllegalArgumentException for syntax errors in the pattern string453* @throws IndexOutOfBoundsException if certain limits are exceeded454* (e.g., argument number too high, argument name too long, etc.)455* @throws NumberFormatException if a number could not be parsed456* @stable ICU 4.8457*/458MessagePattern &parseChoiceStyle(const UnicodeString &pattern,459UParseError *parseError, UErrorCode &errorCode);460461/**462* Parses a PluralFormat pattern string.463* @param pattern a PluralFormat pattern string464* @param parseError Struct to receive information on the position465* of an error within the pattern.466* Can be NULL.467* @param errorCode Standard ICU error code. Its input value must468* pass the U_SUCCESS() test, or else the function returns469* immediately. Check for U_FAILURE() on output or use with470* function chaining. (See User Guide for details.)471* @return *this472* @throws IllegalArgumentException for syntax errors in the pattern string473* @throws IndexOutOfBoundsException if certain limits are exceeded474* (e.g., argument number too high, argument name too long, etc.)475* @throws NumberFormatException if a number could not be parsed476* @stable ICU 4.8477*/478MessagePattern &parsePluralStyle(const UnicodeString &pattern,479UParseError *parseError, UErrorCode &errorCode);480481/**482* Parses a SelectFormat pattern string.483* @param pattern a SelectFormat pattern string484* @param parseError Struct to receive information on the position485* of an error within the pattern.486* Can be NULL.487* @param errorCode Standard ICU error code. Its input value must488* pass the U_SUCCESS() test, or else the function returns489* immediately. Check for U_FAILURE() on output or use with490* function chaining. (See User Guide for details.)491* @return *this492* @throws IllegalArgumentException for syntax errors in the pattern string493* @throws IndexOutOfBoundsException if certain limits are exceeded494* (e.g., argument number too high, argument name too long, etc.)495* @throws NumberFormatException if a number could not be parsed496* @stable ICU 4.8497*/498MessagePattern &parseSelectStyle(const UnicodeString &pattern,499UParseError *parseError, UErrorCode &errorCode);500501/**502* Clears this MessagePattern.503* countParts() will return 0.504* @stable ICU 4.8505*/506void clear();507508/**509* Clears this MessagePattern and sets the UMessagePatternApostropheMode.510* countParts() will return 0.511* @param mode The new UMessagePatternApostropheMode.512* @stable ICU 4.8513*/514void clearPatternAndSetApostropheMode(UMessagePatternApostropheMode mode) {515clear();516aposMode=mode;517}518519/**520* @param other another object to compare with.521* @return TRUE if this object is equivalent to the other one.522* @stable ICU 4.8523*/524UBool operator==(const MessagePattern &other) const;525526/**527* @param other another object to compare with.528* @return FALSE if this object is equivalent to the other one.529* @stable ICU 4.8530*/531inline UBool operator!=(const MessagePattern &other) const {532return !operator==(other);533}534535/**536* @return A hash code for this object.537* @stable ICU 4.8538*/539int32_t hashCode() const;540541/**542* @return this instance's UMessagePatternApostropheMode.543* @stable ICU 4.8544*/545UMessagePatternApostropheMode getApostropheMode() const {546return aposMode;547}548549// Java has package-private jdkAposMode() here.550// In C++, this is declared in the MessageImpl class.551552/**553* @return the parsed pattern string (null if none was parsed).554* @stable ICU 4.8555*/556const UnicodeString &getPatternString() const {557return msg;558}559560/**561* Does the parsed pattern have named arguments like {first_name}?562* @return TRUE if the parsed pattern has at least one named argument.563* @stable ICU 4.8564*/565UBool hasNamedArguments() const {566return hasArgNames;567}568569/**570* Does the parsed pattern have numbered arguments like {2}?571* @return TRUE if the parsed pattern has at least one numbered argument.572* @stable ICU 4.8573*/574UBool hasNumberedArguments() const {575return hasArgNumbers;576}577578/**579* Validates and parses an argument name or argument number string.580* An argument name must be a "pattern identifier", that is, it must contain581* no Unicode Pattern_Syntax or Pattern_White_Space characters.582* If it only contains ASCII digits, then it must be a small integer with no leading zero.583* @param name Input string.584* @return >=0 if the name is a valid number,585* ARG_NAME_NOT_NUMBER (-1) if it is a "pattern identifier" but not all ASCII digits,586* ARG_NAME_NOT_VALID (-2) if it is neither.587* @stable ICU 4.8588*/589static int32_t validateArgumentName(const UnicodeString &name);590591/**592* Returns a version of the parsed pattern string where each ASCII apostrophe593* is doubled (escaped) if it is not already, and if it is not interpreted as quoting syntax.594* <p>595* For example, this turns "I don't '{know}' {gender,select,female{h''er}other{h'im}}."596* into "I don''t '{know}' {gender,select,female{h''er}other{h''im}}."597* @return the deep-auto-quoted version of the parsed pattern string.598* @see MessageFormat.autoQuoteApostrophe()599* @stable ICU 4.8600*/601UnicodeString autoQuoteApostropheDeep() const;602603class Part;604605/**606* Returns the number of "parts" created by parsing the pattern string.607* Returns 0 if no pattern has been parsed or clear() was called.608* @return the number of pattern parts.609* @stable ICU 4.8610*/611int32_t countParts() const {612return partsLength;613}614615/**616* Gets the i-th pattern "part".617* @param i The index of the Part data. (0..countParts()-1)618* @return the i-th pattern "part".619* @stable ICU 4.8620*/621const Part &getPart(int32_t i) const {622return parts[i];623}624625/**626* Returns the UMessagePatternPartType of the i-th pattern "part".627* Convenience method for getPart(i).getType().628* @param i The index of the Part data. (0..countParts()-1)629* @return The UMessagePatternPartType of the i-th Part.630* @stable ICU 4.8631*/632UMessagePatternPartType getPartType(int32_t i) const {633return getPart(i).type;634}635636/**637* Returns the pattern index of the specified pattern "part".638* Convenience method for getPart(partIndex).getIndex().639* @param partIndex The index of the Part data. (0..countParts()-1)640* @return The pattern index of this Part.641* @stable ICU 4.8642*/643int32_t getPatternIndex(int32_t partIndex) const {644return getPart(partIndex).index;645}646647/**648* Returns the substring of the pattern string indicated by the Part.649* Convenience method for getPatternString().substring(part.getIndex(), part.getLimit()).650* @param part a part of this MessagePattern.651* @return the substring associated with part.652* @stable ICU 4.8653*/654UnicodeString getSubstring(const Part &part) const {655return msg.tempSubString(part.index, part.length);656}657658/**659* Compares the part's substring with the input string s.660* @param part a part of this MessagePattern.661* @param s a string.662* @return TRUE if getSubstring(part).equals(s).663* @stable ICU 4.8664*/665UBool partSubstringMatches(const Part &part, const UnicodeString &s) const {666return 0==msg.compare(part.index, part.length, s);667}668669/**670* Returns the numeric value associated with an ARG_INT or ARG_DOUBLE.671* @param part a part of this MessagePattern.672* @return the part's numeric value, or UMSGPAT_NO_NUMERIC_VALUE if this is not a numeric part.673* @stable ICU 4.8674*/675double getNumericValue(const Part &part) const;676677/**678* Returns the "offset:" value of a PluralFormat argument, or 0 if none is specified.679* @param pluralStart the index of the first PluralFormat argument style part. (0..countParts()-1)680* @return the "offset:" value.681* @stable ICU 4.8682*/683double getPluralOffset(int32_t pluralStart) const;684685/**686* Returns the index of the ARG|MSG_LIMIT part corresponding to the ARG|MSG_START at start.687* @param start The index of some Part data (0..countParts()-1);688* this Part should be of Type ARG_START or MSG_START.689* @return The first i>start where getPart(i).getType()==ARG|MSG_LIMIT at the same nesting level,690* or start itself if getPartType(msgStart)!=ARG|MSG_START.691* @stable ICU 4.8692*/693int32_t getLimitPartIndex(int32_t start) const {694int32_t limit=getPart(start).limitPartIndex;695if(limit<start) {696return start;697}698return limit;699}700701/**702* A message pattern "part", representing a pattern parsing event.703* There is a part for the start and end of a message or argument,704* for quoting and escaping of and with ASCII apostrophes,705* and for syntax elements of "complex" arguments.706* @stable ICU 4.8707*/708class Part : public UMemory {709public:710/**711* Default constructor, do not use.712* @internal713*/714Part() {}715716/**717* Returns the type of this part.718* @return the part type.719* @stable ICU 4.8720*/721UMessagePatternPartType getType() const {722return type;723}724725/**726* Returns the pattern string index associated with this Part.727* @return this part's pattern string index.728* @stable ICU 4.8729*/730int32_t getIndex() const {731return index;732}733734/**735* Returns the length of the pattern substring associated with this Part.736* This is 0 for some parts.737* @return this part's pattern substring length.738* @stable ICU 4.8739*/740int32_t getLength() const {741return length;742}743744/**745* Returns the pattern string limit (exclusive-end) index associated with this Part.746* Convenience method for getIndex()+getLength().747* @return this part's pattern string limit index, same as getIndex()+getLength().748* @stable ICU 4.8749*/750int32_t getLimit() const {751return index+length;752}753754/**755* Returns a value associated with this part.756* See the documentation of each part type for details.757* @return the part value.758* @stable ICU 4.8759*/760int32_t getValue() const {761return value;762}763764/**765* Returns the argument type if this part is of type ARG_START or ARG_LIMIT,766* otherwise UMSGPAT_ARG_TYPE_NONE.767* @return the argument type for this part.768* @stable ICU 4.8769*/770UMessagePatternArgType getArgType() const {771UMessagePatternPartType type=getType();772if(type==UMSGPAT_PART_TYPE_ARG_START || type==UMSGPAT_PART_TYPE_ARG_LIMIT) {773return (UMessagePatternArgType)value;774} else {775return UMSGPAT_ARG_TYPE_NONE;776}777}778779/**780* Indicates whether the Part type has a numeric value.781* If so, then that numeric value can be retrieved via MessagePattern.getNumericValue().782* @param type The Part type to be tested.783* @return TRUE if the Part type has a numeric value.784* @stable ICU 4.8785*/786static UBool hasNumericValue(UMessagePatternPartType type) {787return type==UMSGPAT_PART_TYPE_ARG_INT || type==UMSGPAT_PART_TYPE_ARG_DOUBLE;788}789790/**791* @param other another object to compare with.792* @return TRUE if this object is equivalent to the other one.793* @stable ICU 4.8794*/795UBool operator==(const Part &other) const;796797/**798* @param other another object to compare with.799* @return FALSE if this object is equivalent to the other one.800* @stable ICU 4.8801*/802inline UBool operator!=(const Part &other) const {803return !operator==(other);804}805806/**807* @return A hash code for this object.808* @stable ICU 4.8809*/810int32_t hashCode() const {811return ((type*37+index)*37+length)*37+value;812}813814private:815friend class MessagePattern;816817static const int32_t MAX_LENGTH=0xffff;818static const int32_t MAX_VALUE=0x7fff;819820// Some fields are not final because they are modified during pattern parsing.821// After pattern parsing, the parts are effectively immutable.822UMessagePatternPartType type;823int32_t index;824uint16_t length;825int16_t value;826int32_t limitPartIndex;827};828829private:830void preParse(const UnicodeString &pattern, UParseError *parseError, UErrorCode &errorCode);831832void postParse();833834int32_t parseMessage(int32_t index, int32_t msgStartLength,835int32_t nestingLevel, UMessagePatternArgType parentType,836UParseError *parseError, UErrorCode &errorCode);837838int32_t parseArg(int32_t index, int32_t argStartLength, int32_t nestingLevel,839UParseError *parseError, UErrorCode &errorCode);840841int32_t parseSimpleStyle(int32_t index, UParseError *parseError, UErrorCode &errorCode);842843int32_t parseChoiceStyle(int32_t index, int32_t nestingLevel,844UParseError *parseError, UErrorCode &errorCode);845846int32_t parsePluralOrSelectStyle(UMessagePatternArgType argType, int32_t index, int32_t nestingLevel,847UParseError *parseError, UErrorCode &errorCode);848849/**850* Validates and parses an argument name or argument number string.851* This internal method assumes that the input substring is a "pattern identifier".852* @return >=0 if the name is a valid number,853* ARG_NAME_NOT_NUMBER (-1) if it is a "pattern identifier" but not all ASCII digits,854* ARG_NAME_NOT_VALID (-2) if it is neither.855* @see #validateArgumentName(String)856*/857static int32_t parseArgNumber(const UnicodeString &s, int32_t start, int32_t limit);858859int32_t parseArgNumber(int32_t start, int32_t limit) {860return parseArgNumber(msg, start, limit);861}862863/**864* Parses a number from the specified message substring.865* @param start start index into the message string866* @param limit limit index into the message string, must be start<limit867* @param allowInfinity TRUE if U+221E is allowed (for ChoiceFormat)868* @param parseError869* @param errorCode870*/871void parseDouble(int32_t start, int32_t limit, UBool allowInfinity,872UParseError *parseError, UErrorCode &errorCode);873874// Java has package-private appendReducedApostrophes() here.875// In C++, this is declared in the MessageImpl class.876877int32_t skipWhiteSpace(int32_t index);878879int32_t skipIdentifier(int32_t index);880881/**882* Skips a sequence of characters that could occur in a double value.883* Does not fully parse or validate the value.884*/885int32_t skipDouble(int32_t index);886887static UBool isArgTypeChar(UChar32 c);888889UBool isChoice(int32_t index);890891UBool isPlural(int32_t index);892893UBool isSelect(int32_t index);894895UBool isOrdinal(int32_t index);896897/**898* @return TRUE if we are inside a MessageFormat (sub-)pattern,899* as opposed to inside a top-level choice/plural/select pattern.900*/901UBool inMessageFormatPattern(int32_t nestingLevel);902903/**904* @return TRUE if we are in a MessageFormat sub-pattern905* of a top-level ChoiceFormat pattern.906*/907UBool inTopLevelChoiceMessage(int32_t nestingLevel, UMessagePatternArgType parentType);908909void addPart(UMessagePatternPartType type, int32_t index, int32_t length,910int32_t value, UErrorCode &errorCode);911912void addLimitPart(int32_t start,913UMessagePatternPartType type, int32_t index, int32_t length,914int32_t value, UErrorCode &errorCode);915916void addArgDoublePart(double numericValue, int32_t start, int32_t length, UErrorCode &errorCode);917918void setParseError(UParseError *parseError, int32_t index);919920UBool init(UErrorCode &errorCode);921UBool copyStorage(const MessagePattern &other, UErrorCode &errorCode);922923UMessagePatternApostropheMode aposMode;924UnicodeString msg;925// ArrayList<Part> parts=new ArrayList<Part>();926MessagePatternPartsList *partsList;927Part *parts;928int32_t partsLength;929// ArrayList<Double> numericValues;930MessagePatternDoubleList *numericValuesList;931double *numericValues;932int32_t numericValuesLength;933UBool hasArgNames;934UBool hasArgNumbers;935UBool needsAutoQuoting;936};937938U_NAMESPACE_END939940#endif // !UCONFIG_NO_FORMATTING941942#endif // __MESSAGEPATTERN_H__943944945