Path: blob/jdk8u272-b10-aarch32-20201026/jdk/src/share/native/common/unicode/messagepattern.h
48773 views
// © 2016 and later: Unicode, Inc. and others.1// License & terms of use: http://www.unicode.org/copyright.html2/*3*******************************************************************************4* Copyright (C) 2011-2013, International Business Machines5* Corporation and others. All Rights Reserved.6*******************************************************************************7* file name: messagepattern.h8* encoding: UTF-89* tab size: 8 (not used)10* indentation:411*12* created on: 2011mar1413* created by: Markus W. Scherer14*/1516#ifndef __MESSAGEPATTERN_H__17#define __MESSAGEPATTERN_H__1819/**20* \file21* \brief C++ API: MessagePattern class: Parses and represents ICU MessageFormat patterns.22*/2324#include "unicode/utypes.h"2526#if !UCONFIG_NO_FORMATTING2728#include "unicode/parseerr.h"29#include "unicode/unistr.h"3031/**32* Mode for when an apostrophe starts quoted literal text for MessageFormat output.33* The default is DOUBLE_OPTIONAL unless overridden via uconfig.h34* (UCONFIG_MSGPAT_DEFAULT_APOSTROPHE_MODE).35* <p>36* A pair of adjacent apostrophes always results in a single apostrophe in the output,37* even when the pair is between two single, text-quoting apostrophes.38* <p>39* The following table shows examples of desired MessageFormat.format() output40* with the pattern strings that yield that output.41* <p>42* <table>43* <tr>44* <th>Desired output</th>45* <th>DOUBLE_OPTIONAL</th>46* <th>DOUBLE_REQUIRED</th>47* </tr>48* <tr>49* <td>I see {many}</td>50* <td>I see '{many}'</td>51* <td>(same)</td>52* </tr>53* <tr>54* <td>I said {'Wow!'}</td>55* <td>I said '{''Wow!''}'</td>56* <td>(same)</td>57* </tr>58* <tr>59* <td>I don't know</td>60* <td>I don't know OR<br> I don''t know</td>61* <td>I don''t know</td>62* </tr>63* </table>64* @stable ICU 4.865* @see UCONFIG_MSGPAT_DEFAULT_APOSTROPHE_MODE66*/67enum UMessagePatternApostropheMode {68/**69* A literal apostrophe is represented by70* either a single or a double apostrophe pattern character.71* Within a MessageFormat pattern, a single apostrophe only starts quoted literal text72* if it immediately precedes a curly brace {},73* or a pipe symbol | if inside a choice format,74* or a pound symbol # if inside a plural format.75* <p>76* This is the default behavior starting with ICU 4.8.77* @stable ICU 4.878*/79UMSGPAT_APOS_DOUBLE_OPTIONAL,80/**81* A literal apostrophe must be represented by82* a double apostrophe pattern character.83* A single apostrophe always starts quoted literal text.84* <p>85* This is the behavior of ICU 4.6 and earlier, and of the JDK.86* @stable ICU 4.887*/88UMSGPAT_APOS_DOUBLE_REQUIRED89};90/**91* @stable ICU 4.892*/93typedef enum UMessagePatternApostropheMode UMessagePatternApostropheMode;9495/**96* MessagePattern::Part type constants.97* @stable ICU 4.898*/99enum UMessagePatternPartType {100/**101* Start of a message pattern (main or nested).102* The length is 0 for the top-level message103* and for a choice argument sub-message, otherwise 1 for the '{'.104* The value indicates the nesting level, starting with 0 for the main message.105* <p>106* There is always a later MSG_LIMIT part.107* @stable ICU 4.8108*/109UMSGPAT_PART_TYPE_MSG_START,110/**111* End of a message pattern (main or nested).112* The length is 0 for the top-level message and113* the last sub-message of a choice argument,114* otherwise 1 for the '}' or (in a choice argument style) the '|'.115* The value indicates the nesting level, starting with 0 for the main message.116* @stable ICU 4.8117*/118UMSGPAT_PART_TYPE_MSG_LIMIT,119/**120* Indicates a substring of the pattern string which is to be skipped when formatting.121* For example, an apostrophe that begins or ends quoted text122* would be indicated with such a part.123* The value is undefined and currently always 0.124* @stable ICU 4.8125*/126UMSGPAT_PART_TYPE_SKIP_SYNTAX,127/**128* Indicates that a syntax character needs to be inserted for auto-quoting.129* The length is 0.130* The value is the character code of the insertion character. (U+0027=APOSTROPHE)131* @stable ICU 4.8132*/133UMSGPAT_PART_TYPE_INSERT_CHAR,134/**135* Indicates a syntactic (non-escaped) # symbol in a plural variant.136* When formatting, replace this part's substring with the137* (value-offset) for the plural argument value.138* The value is undefined and currently always 0.139* @stable ICU 4.8140*/141UMSGPAT_PART_TYPE_REPLACE_NUMBER,142/**143* Start of an argument.144* The length is 1 for the '{'.145* The value is the ordinal value of the ArgType. Use getArgType().146* <p>147* This part is followed by either an ARG_NUMBER or ARG_NAME,148* followed by optional argument sub-parts (see UMessagePatternArgType constants)149* and finally an ARG_LIMIT part.150* @stable ICU 4.8151*/152UMSGPAT_PART_TYPE_ARG_START,153/**154* End of an argument.155* The length is 1 for the '}'.156* The value is the ordinal value of the ArgType. Use getArgType().157* @stable ICU 4.8158*/159UMSGPAT_PART_TYPE_ARG_LIMIT,160/**161* The argument number, provided by the value.162* @stable ICU 4.8163*/164UMSGPAT_PART_TYPE_ARG_NUMBER,165/**166* The argument name.167* The value is undefined and currently always 0.168* @stable ICU 4.8169*/170UMSGPAT_PART_TYPE_ARG_NAME,171/**172* The argument type.173* The value is undefined and currently always 0.174* @stable ICU 4.8175*/176UMSGPAT_PART_TYPE_ARG_TYPE,177/**178* The argument style text.179* The value is undefined and currently always 0.180* @stable ICU 4.8181*/182UMSGPAT_PART_TYPE_ARG_STYLE,183/**184* A selector substring in a "complex" argument style.185* The value is undefined and currently always 0.186* @stable ICU 4.8187*/188UMSGPAT_PART_TYPE_ARG_SELECTOR,189/**190* An integer value, for example the offset or an explicit selector value191* in a PluralFormat style.192* The part value is the integer value.193* @stable ICU 4.8194*/195UMSGPAT_PART_TYPE_ARG_INT,196/**197* A numeric value, for example the offset or an explicit selector value198* in a PluralFormat style.199* The part value is an index into an internal array of numeric values;200* use getNumericValue().201* @stable ICU 4.8202*/203UMSGPAT_PART_TYPE_ARG_DOUBLE204};205/**206* @stable ICU 4.8207*/208typedef enum UMessagePatternPartType UMessagePatternPartType;209210/**211* Argument type constants.212* Returned by Part.getArgType() for ARG_START and ARG_LIMIT parts.213*214* Messages nested inside an argument are each delimited by MSG_START and MSG_LIMIT,215* with a nesting level one greater than the surrounding message.216* @stable ICU 4.8217*/218enum UMessagePatternArgType {219/**220* The argument has no specified type.221* @stable ICU 4.8222*/223UMSGPAT_ARG_TYPE_NONE,224/**225* The argument has a "simple" type which is provided by the ARG_TYPE part.226* An ARG_STYLE part might follow that.227* @stable ICU 4.8228*/229UMSGPAT_ARG_TYPE_SIMPLE,230/**231* The argument is a ChoiceFormat with one or more232* ((ARG_INT | ARG_DOUBLE), ARG_SELECTOR, message) tuples.233* @stable ICU 4.8234*/235UMSGPAT_ARG_TYPE_CHOICE,236/**237* The argument is a cardinal-number PluralFormat with an optional ARG_INT or ARG_DOUBLE offset238* (e.g., offset:1)239* and one or more (ARG_SELECTOR [explicit-value] message) tuples.240* If the selector has an explicit value (e.g., =2), then241* that value is provided by the ARG_INT or ARG_DOUBLE part preceding the message.242* Otherwise the message immediately follows the ARG_SELECTOR.243* @stable ICU 4.8244*/245UMSGPAT_ARG_TYPE_PLURAL,246/**247* The argument is a SelectFormat with one or more (ARG_SELECTOR, message) pairs.248* @stable ICU 4.8249*/250UMSGPAT_ARG_TYPE_SELECT,251/**252* The argument is an ordinal-number PluralFormat253* with the same style parts sequence and semantics as UMSGPAT_ARG_TYPE_PLURAL.254* @stable ICU 50255*/256UMSGPAT_ARG_TYPE_SELECTORDINAL257};258/**259* @stable ICU 4.8260*/261typedef enum UMessagePatternArgType UMessagePatternArgType;262263/**264* \def UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE265* Returns TRUE if the argument type has a plural style part sequence and semantics,266* for example UMSGPAT_ARG_TYPE_PLURAL and UMSGPAT_ARG_TYPE_SELECTORDINAL.267* @stable ICU 50268*/269#define UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType) \270((argType)==UMSGPAT_ARG_TYPE_PLURAL || (argType)==UMSGPAT_ARG_TYPE_SELECTORDINAL)271272enum {273/**274* Return value from MessagePattern.validateArgumentName() for when275* the string is a valid "pattern identifier" but not a number.276* @stable ICU 4.8277*/278UMSGPAT_ARG_NAME_NOT_NUMBER=-1,279280/**281* Return value from MessagePattern.validateArgumentName() for when282* the string is invalid.283* It might not be a valid "pattern identifier",284* or it have only ASCII digits but there is a leading zero or the number is too large.285* @stable ICU 4.8286*/287UMSGPAT_ARG_NAME_NOT_VALID=-2288};289290/**291* Special value that is returned by getNumericValue(Part) when no292* numeric value is defined for a part.293* @see MessagePattern.getNumericValue()294* @stable ICU 4.8295*/296#define UMSGPAT_NO_NUMERIC_VALUE ((double)(-123456789))297298U_NAMESPACE_BEGIN299300class MessagePatternDoubleList;301class MessagePatternPartsList;302303/**304* Parses and represents ICU MessageFormat patterns.305* Also handles patterns for ChoiceFormat, PluralFormat and SelectFormat.306* Used in the implementations of those classes as well as in tools307* for message validation, translation and format conversion.308* <p>309* The parser handles all syntax relevant for identifying message arguments.310* This includes "complex" arguments whose style strings contain311* nested MessageFormat pattern substrings.312* For "simple" arguments (with no nested MessageFormat pattern substrings),313* the argument style is not parsed any further.314* <p>315* The parser handles named and numbered message arguments and allows both in one message.316* <p>317* Once a pattern has been parsed successfully, iterate through the parsed data318* with countParts(), getPart() and related methods.319* <p>320* The data logically represents a parse tree, but is stored and accessed321* as a list of "parts" for fast and simple parsing and to minimize object allocations.322* Arguments and nested messages are best handled via recursion.323* For every _START "part", MessagePattern.getLimitPartIndex() efficiently returns324* the index of the corresponding _LIMIT "part".325* <p>326* List of "parts":327* <pre>328* message = MSG_START (SKIP_SYNTAX | INSERT_CHAR | REPLACE_NUMBER | argument)* MSG_LIMIT329* argument = noneArg | simpleArg | complexArg330* complexArg = choiceArg | pluralArg | selectArg331*332* noneArg = ARG_START.NONE (ARG_NAME | ARG_NUMBER) ARG_LIMIT.NONE333* simpleArg = ARG_START.SIMPLE (ARG_NAME | ARG_NUMBER) ARG_TYPE [ARG_STYLE] ARG_LIMIT.SIMPLE334* choiceArg = ARG_START.CHOICE (ARG_NAME | ARG_NUMBER) choiceStyle ARG_LIMIT.CHOICE335* pluralArg = ARG_START.PLURAL (ARG_NAME | ARG_NUMBER) pluralStyle ARG_LIMIT.PLURAL336* selectArg = ARG_START.SELECT (ARG_NAME | ARG_NUMBER) selectStyle ARG_LIMIT.SELECT337*338* choiceStyle = ((ARG_INT | ARG_DOUBLE) ARG_SELECTOR message)+339* pluralStyle = [ARG_INT | ARG_DOUBLE] (ARG_SELECTOR [ARG_INT | ARG_DOUBLE] message)+340* selectStyle = (ARG_SELECTOR message)+341* </pre>342* <ul>343* <li>Literal output text is not represented directly by "parts" but accessed344* between parts of a message, from one part's getLimit() to the next part's getIndex().345* <li><code>ARG_START.CHOICE</code> stands for an ARG_START Part with ArgType CHOICE.346* <li>In the choiceStyle, the ARG_SELECTOR has the '<', the '#' or347* the less-than-or-equal-to sign (U+2264).348* <li>In the pluralStyle, the first, optional numeric Part has the "offset:" value.349* The optional numeric Part between each (ARG_SELECTOR, message) pair350* is the value of an explicit-number selector like "=2",351* otherwise the selector is a non-numeric identifier.352* <li>The REPLACE_NUMBER Part can occur only in an immediate sub-message of the pluralStyle.353* </ul>354* <p>355* This class is not intended for public subclassing.356*357* @stable ICU 4.8358*/359class U_COMMON_API MessagePattern : public UObject {360public:361/**362* Constructs an empty MessagePattern with default UMessagePatternApostropheMode.363* @param errorCode Standard ICU error code. Its input value must364* pass the U_SUCCESS() test, or else the function returns365* immediately. Check for U_FAILURE() on output or use with366* function chaining. (See User Guide for details.)367* @stable ICU 4.8368*/369MessagePattern(UErrorCode &errorCode);370371/**372* Constructs an empty MessagePattern.373* @param mode Explicit UMessagePatternApostropheMode.374* @param errorCode Standard ICU error code. Its input value must375* pass the U_SUCCESS() test, or else the function returns376* immediately. Check for U_FAILURE() on output or use with377* function chaining. (See User Guide for details.)378* @stable ICU 4.8379*/380MessagePattern(UMessagePatternApostropheMode mode, UErrorCode &errorCode);381382/**383* Constructs a MessagePattern with default UMessagePatternApostropheMode and384* parses the MessageFormat pattern string.385* @param pattern a MessageFormat pattern string386* @param parseError Struct to receive information on the position387* of an error within the pattern.388* Can be NULL.389* @param errorCode Standard ICU error code. Its input value must390* pass the U_SUCCESS() test, or else the function returns391* immediately. Check for U_FAILURE() on output or use with392* function chaining. (See User Guide for details.)393* TODO: turn @throws into UErrorCode specifics?394* @throws IllegalArgumentException for syntax errors in the pattern string395* @throws IndexOutOfBoundsException if certain limits are exceeded396* (e.g., argument number too high, argument name too long, etc.)397* @throws NumberFormatException if a number could not be parsed398* @stable ICU 4.8399*/400MessagePattern(const UnicodeString &pattern, UParseError *parseError, UErrorCode &errorCode);401402/**403* Copy constructor.404* @param other Object to copy.405* @stable ICU 4.8406*/407MessagePattern(const MessagePattern &other);408409/**410* Assignment operator.411* @param other Object to copy.412* @return *this=other413* @stable ICU 4.8414*/415MessagePattern &operator=(const MessagePattern &other);416417/**418* Destructor.419* @stable ICU 4.8420*/421virtual ~MessagePattern();422423/**424* Parses a MessageFormat pattern string.425* @param pattern a MessageFormat pattern string426* @param parseError Struct to receive information on the position427* of an error within the pattern.428* Can be NULL.429* @param errorCode Standard ICU error code. Its input value must430* pass the U_SUCCESS() test, or else the function returns431* immediately. Check for U_FAILURE() on output or use with432* function chaining. (See User Guide for details.)433* @return *this434* @throws IllegalArgumentException for syntax errors in the pattern string435* @throws IndexOutOfBoundsException if certain limits are exceeded436* (e.g., argument number too high, argument name too long, etc.)437* @throws NumberFormatException if a number could not be parsed438* @stable ICU 4.8439*/440MessagePattern &parse(const UnicodeString &pattern,441UParseError *parseError, UErrorCode &errorCode);442443/**444* Parses a ChoiceFormat pattern string.445* @param pattern a ChoiceFormat pattern string446* @param parseError Struct to receive information on the position447* of an error within the pattern.448* Can be NULL.449* @param errorCode Standard ICU error code. Its input value must450* pass the U_SUCCESS() test, or else the function returns451* immediately. Check for U_FAILURE() on output or use with452* function chaining. (See User Guide for details.)453* @return *this454* @throws IllegalArgumentException for syntax errors in the pattern string455* @throws IndexOutOfBoundsException if certain limits are exceeded456* (e.g., argument number too high, argument name too long, etc.)457* @throws NumberFormatException if a number could not be parsed458* @stable ICU 4.8459*/460MessagePattern &parseChoiceStyle(const UnicodeString &pattern,461UParseError *parseError, UErrorCode &errorCode);462463/**464* Parses a PluralFormat pattern string.465* @param pattern a PluralFormat pattern string466* @param parseError Struct to receive information on the position467* of an error within the pattern.468* Can be NULL.469* @param errorCode Standard ICU error code. Its input value must470* pass the U_SUCCESS() test, or else the function returns471* immediately. Check for U_FAILURE() on output or use with472* function chaining. (See User Guide for details.)473* @return *this474* @throws IllegalArgumentException for syntax errors in the pattern string475* @throws IndexOutOfBoundsException if certain limits are exceeded476* (e.g., argument number too high, argument name too long, etc.)477* @throws NumberFormatException if a number could not be parsed478* @stable ICU 4.8479*/480MessagePattern &parsePluralStyle(const UnicodeString &pattern,481UParseError *parseError, UErrorCode &errorCode);482483/**484* Parses a SelectFormat pattern string.485* @param pattern a SelectFormat pattern string486* @param parseError Struct to receive information on the position487* of an error within the pattern.488* Can be NULL.489* @param errorCode Standard ICU error code. Its input value must490* pass the U_SUCCESS() test, or else the function returns491* immediately. Check for U_FAILURE() on output or use with492* function chaining. (See User Guide for details.)493* @return *this494* @throws IllegalArgumentException for syntax errors in the pattern string495* @throws IndexOutOfBoundsException if certain limits are exceeded496* (e.g., argument number too high, argument name too long, etc.)497* @throws NumberFormatException if a number could not be parsed498* @stable ICU 4.8499*/500MessagePattern &parseSelectStyle(const UnicodeString &pattern,501UParseError *parseError, UErrorCode &errorCode);502503/**504* Clears this MessagePattern.505* countParts() will return 0.506* @stable ICU 4.8507*/508void clear();509510/**511* Clears this MessagePattern and sets the UMessagePatternApostropheMode.512* countParts() will return 0.513* @param mode The new UMessagePatternApostropheMode.514* @stable ICU 4.8515*/516void clearPatternAndSetApostropheMode(UMessagePatternApostropheMode mode) {517clear();518aposMode=mode;519}520521/**522* @param other another object to compare with.523* @return TRUE if this object is equivalent to the other one.524* @stable ICU 4.8525*/526UBool operator==(const MessagePattern &other) const;527528/**529* @param other another object to compare with.530* @return FALSE if this object is equivalent to the other one.531* @stable ICU 4.8532*/533inline UBool operator!=(const MessagePattern &other) const {534return !operator==(other);535}536537/**538* @return A hash code for this object.539* @stable ICU 4.8540*/541int32_t hashCode() const;542543/**544* @return this instance's UMessagePatternApostropheMode.545* @stable ICU 4.8546*/547UMessagePatternApostropheMode getApostropheMode() const {548return aposMode;549}550551// Java has package-private jdkAposMode() here.552// In C++, this is declared in the MessageImpl class.553554/**555* @return the parsed pattern string (null if none was parsed).556* @stable ICU 4.8557*/558const UnicodeString &getPatternString() const {559return msg;560}561562/**563* Does the parsed pattern have named arguments like {first_name}?564* @return TRUE if the parsed pattern has at least one named argument.565* @stable ICU 4.8566*/567UBool hasNamedArguments() const {568return hasArgNames;569}570571/**572* Does the parsed pattern have numbered arguments like {2}?573* @return TRUE if the parsed pattern has at least one numbered argument.574* @stable ICU 4.8575*/576UBool hasNumberedArguments() const {577return hasArgNumbers;578}579580/**581* Validates and parses an argument name or argument number string.582* An argument name must be a "pattern identifier", that is, it must contain583* no Unicode Pattern_Syntax or Pattern_White_Space characters.584* If it only contains ASCII digits, then it must be a small integer with no leading zero.585* @param name Input string.586* @return >=0 if the name is a valid number,587* ARG_NAME_NOT_NUMBER (-1) if it is a "pattern identifier" but not all ASCII digits,588* ARG_NAME_NOT_VALID (-2) if it is neither.589* @stable ICU 4.8590*/591static int32_t validateArgumentName(const UnicodeString &name);592593/**594* Returns a version of the parsed pattern string where each ASCII apostrophe595* is doubled (escaped) if it is not already, and if it is not interpreted as quoting syntax.596* <p>597* For example, this turns "I don't '{know}' {gender,select,female{h''er}other{h'im}}."598* into "I don''t '{know}' {gender,select,female{h''er}other{h''im}}."599* @return the deep-auto-quoted version of the parsed pattern string.600* @see MessageFormat.autoQuoteApostrophe()601* @stable ICU 4.8602*/603UnicodeString autoQuoteApostropheDeep() const;604605class Part;606607/**608* Returns the number of "parts" created by parsing the pattern string.609* Returns 0 if no pattern has been parsed or clear() was called.610* @return the number of pattern parts.611* @stable ICU 4.8612*/613int32_t countParts() const {614return partsLength;615}616617/**618* Gets the i-th pattern "part".619* @param i The index of the Part data. (0..countParts()-1)620* @return the i-th pattern "part".621* @stable ICU 4.8622*/623const Part &getPart(int32_t i) const {624return parts[i];625}626627/**628* Returns the UMessagePatternPartType of the i-th pattern "part".629* Convenience method for getPart(i).getType().630* @param i The index of the Part data. (0..countParts()-1)631* @return The UMessagePatternPartType of the i-th Part.632* @stable ICU 4.8633*/634UMessagePatternPartType getPartType(int32_t i) const {635return getPart(i).type;636}637638/**639* Returns the pattern index of the specified pattern "part".640* Convenience method for getPart(partIndex).getIndex().641* @param partIndex The index of the Part data. (0..countParts()-1)642* @return The pattern index of this Part.643* @stable ICU 4.8644*/645int32_t getPatternIndex(int32_t partIndex) const {646return getPart(partIndex).index;647}648649/**650* Returns the substring of the pattern string indicated by the Part.651* Convenience method for getPatternString().substring(part.getIndex(), part.getLimit()).652* @param part a part of this MessagePattern.653* @return the substring associated with part.654* @stable ICU 4.8655*/656UnicodeString getSubstring(const Part &part) const {657return msg.tempSubString(part.index, part.length);658}659660/**661* Compares the part's substring with the input string s.662* @param part a part of this MessagePattern.663* @param s a string.664* @return TRUE if getSubstring(part).equals(s).665* @stable ICU 4.8666*/667UBool partSubstringMatches(const Part &part, const UnicodeString &s) const {668return 0==msg.compare(part.index, part.length, s);669}670671/**672* Returns the numeric value associated with an ARG_INT or ARG_DOUBLE.673* @param part a part of this MessagePattern.674* @return the part's numeric value, or UMSGPAT_NO_NUMERIC_VALUE if this is not a numeric part.675* @stable ICU 4.8676*/677double getNumericValue(const Part &part) const;678679/**680* Returns the "offset:" value of a PluralFormat argument, or 0 if none is specified.681* @param pluralStart the index of the first PluralFormat argument style part. (0..countParts()-1)682* @return the "offset:" value.683* @stable ICU 4.8684*/685double getPluralOffset(int32_t pluralStart) const;686687/**688* Returns the index of the ARG|MSG_LIMIT part corresponding to the ARG|MSG_START at start.689* @param start The index of some Part data (0..countParts()-1);690* this Part should be of Type ARG_START or MSG_START.691* @return The first i>start where getPart(i).getType()==ARG|MSG_LIMIT at the same nesting level,692* or start itself if getPartType(msgStart)!=ARG|MSG_START.693* @stable ICU 4.8694*/695int32_t getLimitPartIndex(int32_t start) const {696int32_t limit=getPart(start).limitPartIndex;697if(limit<start) {698return start;699}700return limit;701}702703/**704* A message pattern "part", representing a pattern parsing event.705* There is a part for the start and end of a message or argument,706* for quoting and escaping of and with ASCII apostrophes,707* and for syntax elements of "complex" arguments.708* @stable ICU 4.8709*/710class Part : public UMemory {711public:712/**713* Default constructor, do not use.714* @internal715*/716Part() {}717718/**719* Returns the type of this part.720* @return the part type.721* @stable ICU 4.8722*/723UMessagePatternPartType getType() const {724return type;725}726727/**728* Returns the pattern string index associated with this Part.729* @return this part's pattern string index.730* @stable ICU 4.8731*/732int32_t getIndex() const {733return index;734}735736/**737* Returns the length of the pattern substring associated with this Part.738* This is 0 for some parts.739* @return this part's pattern substring length.740* @stable ICU 4.8741*/742int32_t getLength() const {743return length;744}745746/**747* Returns the pattern string limit (exclusive-end) index associated with this Part.748* Convenience method for getIndex()+getLength().749* @return this part's pattern string limit index, same as getIndex()+getLength().750* @stable ICU 4.8751*/752int32_t getLimit() const {753return index+length;754}755756/**757* Returns a value associated with this part.758* See the documentation of each part type for details.759* @return the part value.760* @stable ICU 4.8761*/762int32_t getValue() const {763return value;764}765766/**767* Returns the argument type if this part is of type ARG_START or ARG_LIMIT,768* otherwise UMSGPAT_ARG_TYPE_NONE.769* @return the argument type for this part.770* @stable ICU 4.8771*/772UMessagePatternArgType getArgType() const {773UMessagePatternPartType msgType=getType();774if(msgType ==UMSGPAT_PART_TYPE_ARG_START || msgType ==UMSGPAT_PART_TYPE_ARG_LIMIT) {775return (UMessagePatternArgType)value;776} else {777return UMSGPAT_ARG_TYPE_NONE;778}779}780781/**782* Indicates whether the Part type has a numeric value.783* If so, then that numeric value can be retrieved via MessagePattern.getNumericValue().784* @param type The Part type to be tested.785* @return TRUE if the Part type has a numeric value.786* @stable ICU 4.8787*/788static UBool hasNumericValue(UMessagePatternPartType type) {789return type==UMSGPAT_PART_TYPE_ARG_INT || type==UMSGPAT_PART_TYPE_ARG_DOUBLE;790}791792/**793* @param other another object to compare with.794* @return TRUE if this object is equivalent to the other one.795* @stable ICU 4.8796*/797UBool operator==(const Part &other) const;798799/**800* @param other another object to compare with.801* @return FALSE if this object is equivalent to the other one.802* @stable ICU 4.8803*/804inline UBool operator!=(const Part &other) const {805return !operator==(other);806}807808/**809* @return A hash code for this object.810* @stable ICU 4.8811*/812int32_t hashCode() const {813return ((type*37+index)*37+length)*37+value;814}815816private:817friend class MessagePattern;818819static const int32_t MAX_LENGTH=0xffff;820static const int32_t MAX_VALUE=0x7fff;821822// Some fields are not final because they are modified during pattern parsing.823// After pattern parsing, the parts are effectively immutable.824UMessagePatternPartType type;825int32_t index;826uint16_t length;827int16_t value;828int32_t limitPartIndex;829};830831private:832void preParse(const UnicodeString &pattern, UParseError *parseError, UErrorCode &errorCode);833834void postParse();835836int32_t parseMessage(int32_t index, int32_t msgStartLength,837int32_t nestingLevel, UMessagePatternArgType parentType,838UParseError *parseError, UErrorCode &errorCode);839840int32_t parseArg(int32_t index, int32_t argStartLength, int32_t nestingLevel,841UParseError *parseError, UErrorCode &errorCode);842843int32_t parseSimpleStyle(int32_t index, UParseError *parseError, UErrorCode &errorCode);844845int32_t parseChoiceStyle(int32_t index, int32_t nestingLevel,846UParseError *parseError, UErrorCode &errorCode);847848int32_t parsePluralOrSelectStyle(UMessagePatternArgType argType, int32_t index, int32_t nestingLevel,849UParseError *parseError, UErrorCode &errorCode);850851/**852* Validates and parses an argument name or argument number string.853* This internal method assumes that the input substring is a "pattern identifier".854* @return >=0 if the name is a valid number,855* ARG_NAME_NOT_NUMBER (-1) if it is a "pattern identifier" but not all ASCII digits,856* ARG_NAME_NOT_VALID (-2) if it is neither.857* @see #validateArgumentName(String)858*/859static int32_t parseArgNumber(const UnicodeString &s, int32_t start, int32_t limit);860861int32_t parseArgNumber(int32_t start, int32_t limit) {862return parseArgNumber(msg, start, limit);863}864865/**866* Parses a number from the specified message substring.867* @param start start index into the message string868* @param limit limit index into the message string, must be start<limit869* @param allowInfinity TRUE if U+221E is allowed (for ChoiceFormat)870* @param parseError871* @param errorCode872*/873void parseDouble(int32_t start, int32_t limit, UBool allowInfinity,874UParseError *parseError, UErrorCode &errorCode);875876// Java has package-private appendReducedApostrophes() here.877// In C++, this is declared in the MessageImpl class.878879int32_t skipWhiteSpace(int32_t index);880881int32_t skipIdentifier(int32_t index);882883/**884* Skips a sequence of characters that could occur in a double value.885* Does not fully parse or validate the value.886*/887int32_t skipDouble(int32_t index);888889static UBool isArgTypeChar(UChar32 c);890891UBool isChoice(int32_t index);892893UBool isPlural(int32_t index);894895UBool isSelect(int32_t index);896897UBool isOrdinal(int32_t index);898899/**900* @return TRUE if we are inside a MessageFormat (sub-)pattern,901* as opposed to inside a top-level choice/plural/select pattern.902*/903UBool inMessageFormatPattern(int32_t nestingLevel);904905/**906* @return TRUE if we are in a MessageFormat sub-pattern907* of a top-level ChoiceFormat pattern.908*/909UBool inTopLevelChoiceMessage(int32_t nestingLevel, UMessagePatternArgType parentType);910911void addPart(UMessagePatternPartType type, int32_t index, int32_t length,912int32_t value, UErrorCode &errorCode);913914void addLimitPart(int32_t start,915UMessagePatternPartType type, int32_t index, int32_t length,916int32_t value, UErrorCode &errorCode);917918void addArgDoublePart(double numericValue, int32_t start, int32_t length, UErrorCode &errorCode);919920void setParseError(UParseError *parseError, int32_t index);921922UBool init(UErrorCode &errorCode);923UBool copyStorage(const MessagePattern &other, UErrorCode &errorCode);924925UMessagePatternApostropheMode aposMode;926UnicodeString msg;927// ArrayList<Part> parts=new ArrayList<Part>();928MessagePatternPartsList *partsList;929Part *parts;930int32_t partsLength;931// ArrayList<Double> numericValues;932MessagePatternDoubleList *numericValuesList;933double *numericValues;934int32_t numericValuesLength;935UBool hasArgNames;936UBool hasArgNumbers;937UBool needsAutoQuoting;938};939940U_NAMESPACE_END941942#endif // !UCONFIG_NO_FORMATTING943944#endif // __MESSAGEPATTERN_H__945946947