2 *******************************************************************************
3 * Copyright (C) 2011-2012, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 *******************************************************************************
6 * file name: messagepattern.h
8 * tab size: 8 (not used)
11 * created on: 2011mar14
12 * created by: Markus W. Scherer
15 #ifndef __MESSAGEPATTERN_H__
16 #define __MESSAGEPATTERN_H__
20 * \brief C++ API: MessagePattern class: Parses and represents ICU MessageFormat patterns.
23 #include "unicode/utypes.h"
25 #if !UCONFIG_NO_FORMATTING
27 #include "unicode/parseerr.h"
28 #include "unicode/unistr.h"
31 * Mode for when an apostrophe starts quoted literal text for MessageFormat output.
32 * The default is DOUBLE_OPTIONAL unless overridden via uconfig.h
33 * (UCONFIG_MSGPAT_DEFAULT_APOSTROPHE_MODE).
35 * A pair of adjacent apostrophes always results in a single apostrophe in the output,
36 * even when the pair is between two single, text-quoting apostrophes.
38 * The following table shows examples of desired MessageFormat.format() output
39 * with the pattern strings that yield that output.
43 * <th>Desired output</th>
44 * <th>DOUBLE_OPTIONAL</th>
45 * <th>DOUBLE_REQUIRED</th>
48 * <td>I see {many}</td>
49 * <td>I see '{many}'</td>
53 * <td>I said {'Wow!'}</td>
54 * <td>I said '{''Wow!''}'</td>
58 * <td>I don't know</td>
59 * <td>I don't know OR<br> I don''t know</td>
60 * <td>I don''t know</td>
64 * @see UCONFIG_MSGPAT_DEFAULT_APOSTROPHE_MODE
66 enum UMessagePatternApostropheMode
{
68 * A literal apostrophe is represented by
69 * either a single or a double apostrophe pattern character.
70 * Within a MessageFormat pattern, a single apostrophe only starts quoted literal text
71 * if it immediately precedes a curly brace {},
72 * or a pipe symbol | if inside a choice format,
73 * or a pound symbol # if inside a plural format.
75 * This is the default behavior starting with ICU 4.8.
78 UMSGPAT_APOS_DOUBLE_OPTIONAL
,
80 * A literal apostrophe must be represented by
81 * a double apostrophe pattern character.
82 * A single apostrophe always starts quoted literal text.
84 * This is the behavior of ICU 4.6 and earlier, and of the JDK.
87 UMSGPAT_APOS_DOUBLE_REQUIRED
92 typedef enum UMessagePatternApostropheMode UMessagePatternApostropheMode
;
95 * MessagePattern::Part type constants.
98 enum UMessagePatternPartType
{
100 * Start of a message pattern (main or nested).
101 * The length is 0 for the top-level message
102 * and for a choice argument sub-message, otherwise 1 for the '{'.
103 * The value indicates the nesting level, starting with 0 for the main message.
105 * There is always a later MSG_LIMIT part.
108 UMSGPAT_PART_TYPE_MSG_START
,
110 * End of a message pattern (main or nested).
111 * The length is 0 for the top-level message and
112 * the last sub-message of a choice argument,
113 * otherwise 1 for the '}' or (in a choice argument style) the '|'.
114 * The value indicates the nesting level, starting with 0 for the main message.
117 UMSGPAT_PART_TYPE_MSG_LIMIT
,
119 * Indicates a substring of the pattern string which is to be skipped when formatting.
120 * For example, an apostrophe that begins or ends quoted text
121 * would be indicated with such a part.
122 * The value is undefined and currently always 0.
125 UMSGPAT_PART_TYPE_SKIP_SYNTAX
,
127 * Indicates that a syntax character needs to be inserted for auto-quoting.
129 * The value is the character code of the insertion character. (U+0027=APOSTROPHE)
132 UMSGPAT_PART_TYPE_INSERT_CHAR
,
134 * Indicates a syntactic (non-escaped) # symbol in a plural variant.
135 * When formatting, replace this part's substring with the
136 * (value-offset) for the plural argument value.
137 * The value is undefined and currently always 0.
140 UMSGPAT_PART_TYPE_REPLACE_NUMBER
,
142 * Start of an argument.
143 * The length is 1 for the '{'.
144 * The value is the ordinal value of the ArgType. Use getArgType().
146 * This part is followed by either an ARG_NUMBER or ARG_NAME,
147 * followed by optional argument sub-parts (see UMessagePatternArgType constants)
148 * and finally an ARG_LIMIT part.
151 UMSGPAT_PART_TYPE_ARG_START
,
153 * End of an argument.
154 * The length is 1 for the '}'.
155 * The value is the ordinal value of the ArgType. Use getArgType().
158 UMSGPAT_PART_TYPE_ARG_LIMIT
,
160 * The argument number, provided by the value.
163 UMSGPAT_PART_TYPE_ARG_NUMBER
,
166 * The value is undefined and currently always 0.
169 UMSGPAT_PART_TYPE_ARG_NAME
,
172 * The value is undefined and currently always 0.
175 UMSGPAT_PART_TYPE_ARG_TYPE
,
177 * The argument style text.
178 * The value is undefined and currently always 0.
181 UMSGPAT_PART_TYPE_ARG_STYLE
,
183 * A selector substring in a "complex" argument style.
184 * The value is undefined and currently always 0.
187 UMSGPAT_PART_TYPE_ARG_SELECTOR
,
189 * An integer value, for example the offset or an explicit selector value
190 * in a PluralFormat style.
191 * The part value is the integer value.
194 UMSGPAT_PART_TYPE_ARG_INT
,
196 * A numeric value, for example the offset or an explicit selector value
197 * in a PluralFormat style.
198 * The part value is an index into an internal array of numeric values;
199 * use getNumericValue().
202 UMSGPAT_PART_TYPE_ARG_DOUBLE
207 typedef enum UMessagePatternPartType UMessagePatternPartType
;
210 * Argument type constants.
211 * Returned by Part.getArgType() for ARG_START and ARG_LIMIT parts.
213 * Messages nested inside an argument are each delimited by MSG_START and MSG_LIMIT,
214 * with a nesting level one greater than the surrounding message.
217 enum UMessagePatternArgType
{
219 * The argument has no specified type.
222 UMSGPAT_ARG_TYPE_NONE
,
224 * The argument has a "simple" type which is provided by the ARG_TYPE part.
225 * An ARG_STYLE part might follow that.
228 UMSGPAT_ARG_TYPE_SIMPLE
,
230 * The argument is a ChoiceFormat with one or more
231 * ((ARG_INT | ARG_DOUBLE), ARG_SELECTOR, message) tuples.
234 UMSGPAT_ARG_TYPE_CHOICE
,
236 * The argument is a PluralFormat with an optional ARG_INT or ARG_DOUBLE offset
238 * and one or more (ARG_SELECTOR [explicit-value] message) tuples.
239 * If the selector has an explicit value (e.g., =2), then
240 * that value is provided by the ARG_INT or ARG_DOUBLE part preceding the message.
241 * Otherwise the message immediately follows the ARG_SELECTOR.
244 UMSGPAT_ARG_TYPE_PLURAL
,
246 * The argument is a SelectFormat with one or more (ARG_SELECTOR, message) pairs.
249 UMSGPAT_ARG_TYPE_SELECT
254 typedef enum UMessagePatternArgType UMessagePatternArgType
;
258 * Return value from MessagePattern.validateArgumentName() for when
259 * the string is a valid "pattern identifier" but not a number.
262 UMSGPAT_ARG_NAME_NOT_NUMBER
=-1,
265 * Return value from MessagePattern.validateArgumentName() for when
266 * the string is invalid.
267 * It might not be a valid "pattern identifier",
268 * or it have only ASCII digits but there is a leading zero or the number is too large.
271 UMSGPAT_ARG_NAME_NOT_VALID
=-2
275 * Special value that is returned by getNumericValue(Part) when no
276 * numeric value is defined for a part.
277 * @see MessagePattern.getNumericValue()
280 #define UMSGPAT_NO_NUMERIC_VALUE ((double)(-123456789))
284 class MessagePatternDoubleList
;
285 class MessagePatternPartsList
;
288 * Parses and represents ICU MessageFormat patterns.
289 * Also handles patterns for ChoiceFormat, PluralFormat and SelectFormat.
290 * Used in the implementations of those classes as well as in tools
291 * for message validation, translation and format conversion.
293 * The parser handles all syntax relevant for identifying message arguments.
294 * This includes "complex" arguments whose style strings contain
295 * nested MessageFormat pattern substrings.
296 * For "simple" arguments (with no nested MessageFormat pattern substrings),
297 * the argument style is not parsed any further.
299 * The parser handles named and numbered message arguments and allows both in one message.
301 * Once a pattern has been parsed successfully, iterate through the parsed data
302 * with countParts(), getPart() and related methods.
304 * The data logically represents a parse tree, but is stored and accessed
305 * as a list of "parts" for fast and simple parsing and to minimize object allocations.
306 * Arguments and nested messages are best handled via recursion.
307 * For every _START "part", MessagePattern.getLimitPartIndex() efficiently returns
308 * the index of the corresponding _LIMIT "part".
312 * message = MSG_START (SKIP_SYNTAX | INSERT_CHAR | REPLACE_NUMBER | argument)* MSG_LIMIT
313 * argument = noneArg | simpleArg | complexArg
314 * complexArg = choiceArg | pluralArg | selectArg
316 * noneArg = ARG_START.NONE (ARG_NAME | ARG_NUMBER) ARG_LIMIT.NONE
317 * simpleArg = ARG_START.SIMPLE (ARG_NAME | ARG_NUMBER) ARG_TYPE [ARG_STYLE] ARG_LIMIT.SIMPLE
318 * choiceArg = ARG_START.CHOICE (ARG_NAME | ARG_NUMBER) choiceStyle ARG_LIMIT.CHOICE
319 * pluralArg = ARG_START.PLURAL (ARG_NAME | ARG_NUMBER) pluralStyle ARG_LIMIT.PLURAL
320 * selectArg = ARG_START.SELECT (ARG_NAME | ARG_NUMBER) selectStyle ARG_LIMIT.SELECT
322 * choiceStyle = ((ARG_INT | ARG_DOUBLE) ARG_SELECTOR message)+
323 * pluralStyle = [ARG_INT | ARG_DOUBLE] (ARG_SELECTOR [ARG_INT | ARG_DOUBLE] message)+
324 * selectStyle = (ARG_SELECTOR message)+
327 * <li>Literal output text is not represented directly by "parts" but accessed
328 * between parts of a message, from one part's getLimit() to the next part's getIndex().
329 * <li><code>ARG_START.CHOICE</code> stands for an ARG_START Part with ArgType CHOICE.
330 * <li>In the choiceStyle, the ARG_SELECTOR has the '<', the '#' or
331 * the less-than-or-equal-to sign (U+2264).
332 * <li>In the pluralStyle, the first, optional numeric Part has the "offset:" value.
333 * The optional numeric Part between each (ARG_SELECTOR, message) pair
334 * is the value of an explicit-number selector like "=2",
335 * otherwise the selector is a non-numeric identifier.
336 * <li>The REPLACE_NUMBER Part can occur only in an immediate sub-message of the pluralStyle.
339 * This class is not intended for public subclassing.
343 class U_COMMON_API MessagePattern
: public UObject
{
346 * Constructs an empty MessagePattern with default UMessagePatternApostropheMode.
347 * @param errorCode Standard ICU error code. Its input value must
348 * pass the U_SUCCESS() test, or else the function returns
349 * immediately. Check for U_FAILURE() on output or use with
350 * function chaining. (See User Guide for details.)
353 MessagePattern(UErrorCode
&errorCode
);
356 * Constructs an empty MessagePattern.
357 * @param mode Explicit UMessagePatternApostropheMode.
358 * @param errorCode Standard ICU error code. Its input value must
359 * pass the U_SUCCESS() test, or else the function returns
360 * immediately. Check for U_FAILURE() on output or use with
361 * function chaining. (See User Guide for details.)
364 MessagePattern(UMessagePatternApostropheMode mode
, UErrorCode
&errorCode
);
367 * Constructs a MessagePattern with default UMessagePatternApostropheMode and
368 * parses the MessageFormat pattern string.
369 * @param pattern a MessageFormat pattern string
370 * @param parseError Struct to receive information on the position
371 * of an error within the pattern.
373 * @param errorCode Standard ICU error code. Its input value must
374 * pass the U_SUCCESS() test, or else the function returns
375 * immediately. Check for U_FAILURE() on output or use with
376 * function chaining. (See User Guide for details.)
377 * TODO: turn @throws into UErrorCode specifics?
378 * @throws IllegalArgumentException for syntax errors in the pattern string
379 * @throws IndexOutOfBoundsException if certain limits are exceeded
380 * (e.g., argument number too high, argument name too long, etc.)
381 * @throws NumberFormatException if a number could not be parsed
384 MessagePattern(const UnicodeString
&pattern
, UParseError
*parseError
, UErrorCode
&errorCode
);
388 * @param other Object to copy.
391 MessagePattern(const MessagePattern
&other
);
394 * Assignment operator.
395 * @param other Object to copy.
396 * @return *this=other
399 MessagePattern
&operator=(const MessagePattern
&other
);
405 virtual ~MessagePattern();
408 * Parses a MessageFormat pattern string.
409 * @param pattern a MessageFormat pattern string
410 * @param parseError Struct to receive information on the position
411 * of an error within the pattern.
413 * @param errorCode Standard ICU error code. Its input value must
414 * pass the U_SUCCESS() test, or else the function returns
415 * immediately. Check for U_FAILURE() on output or use with
416 * function chaining. (See User Guide for details.)
418 * @throws IllegalArgumentException for syntax errors in the pattern string
419 * @throws IndexOutOfBoundsException if certain limits are exceeded
420 * (e.g., argument number too high, argument name too long, etc.)
421 * @throws NumberFormatException if a number could not be parsed
424 MessagePattern
&parse(const UnicodeString
&pattern
,
425 UParseError
*parseError
, UErrorCode
&errorCode
);
428 * Parses a ChoiceFormat pattern string.
429 * @param pattern a ChoiceFormat pattern string
430 * @param parseError Struct to receive information on the position
431 * of an error within the pattern.
433 * @param errorCode Standard ICU error code. Its input value must
434 * pass the U_SUCCESS() test, or else the function returns
435 * immediately. Check for U_FAILURE() on output or use with
436 * function chaining. (See User Guide for details.)
438 * @throws IllegalArgumentException for syntax errors in the pattern string
439 * @throws IndexOutOfBoundsException if certain limits are exceeded
440 * (e.g., argument number too high, argument name too long, etc.)
441 * @throws NumberFormatException if a number could not be parsed
444 MessagePattern
&parseChoiceStyle(const UnicodeString
&pattern
,
445 UParseError
*parseError
, UErrorCode
&errorCode
);
448 * Parses a PluralFormat pattern string.
449 * @param pattern a PluralFormat pattern string
450 * @param parseError Struct to receive information on the position
451 * of an error within the pattern.
453 * @param errorCode Standard ICU error code. Its input value must
454 * pass the U_SUCCESS() test, or else the function returns
455 * immediately. Check for U_FAILURE() on output or use with
456 * function chaining. (See User Guide for details.)
458 * @throws IllegalArgumentException for syntax errors in the pattern string
459 * @throws IndexOutOfBoundsException if certain limits are exceeded
460 * (e.g., argument number too high, argument name too long, etc.)
461 * @throws NumberFormatException if a number could not be parsed
464 MessagePattern
&parsePluralStyle(const UnicodeString
&pattern
,
465 UParseError
*parseError
, UErrorCode
&errorCode
);
468 * Parses a SelectFormat pattern string.
469 * @param pattern a SelectFormat pattern string
470 * @param parseError Struct to receive information on the position
471 * of an error within the pattern.
473 * @param errorCode Standard ICU error code. Its input value must
474 * pass the U_SUCCESS() test, or else the function returns
475 * immediately. Check for U_FAILURE() on output or use with
476 * function chaining. (See User Guide for details.)
478 * @throws IllegalArgumentException for syntax errors in the pattern string
479 * @throws IndexOutOfBoundsException if certain limits are exceeded
480 * (e.g., argument number too high, argument name too long, etc.)
481 * @throws NumberFormatException if a number could not be parsed
484 MessagePattern
&parseSelectStyle(const UnicodeString
&pattern
,
485 UParseError
*parseError
, UErrorCode
&errorCode
);
488 * Clears this MessagePattern.
489 * countParts() will return 0.
495 * Clears this MessagePattern and sets the UMessagePatternApostropheMode.
496 * countParts() will return 0.
497 * @param mode The new UMessagePatternApostropheMode.
500 void clearPatternAndSetApostropheMode(UMessagePatternApostropheMode mode
) {
506 * @param other another object to compare with.
507 * @return TRUE if this object is equivalent to the other one.
510 UBool
operator==(const MessagePattern
&other
) const;
513 * @param other another object to compare with.
514 * @return FALSE if this object is equivalent to the other one.
517 inline UBool
operator!=(const MessagePattern
&other
) const {
518 return !operator==(other
);
522 * @return A hash code for this object.
525 int32_t hashCode() const;
528 * @return this instance's UMessagePatternApostropheMode.
531 UMessagePatternApostropheMode
getApostropheMode() const {
535 // Java has package-private jdkAposMode() here.
536 // In C++, this is declared in the MessageImpl class.
539 * @return the parsed pattern string (null if none was parsed).
542 const UnicodeString
&getPatternString() const {
547 * Does the parsed pattern have named arguments like {first_name}?
548 * @return TRUE if the parsed pattern has at least one named argument.
551 UBool
hasNamedArguments() const {
556 * Does the parsed pattern have numbered arguments like {2}?
557 * @return TRUE if the parsed pattern has at least one numbered argument.
560 UBool
hasNumberedArguments() const {
561 return hasArgNumbers
;
565 * Validates and parses an argument name or argument number string.
566 * An argument name must be a "pattern identifier", that is, it must contain
567 * no Unicode Pattern_Syntax or Pattern_White_Space characters.
568 * If it only contains ASCII digits, then it must be a small integer with no leading zero.
569 * @param name Input string.
570 * @return >=0 if the name is a valid number,
571 * ARG_NAME_NOT_NUMBER (-1) if it is a "pattern identifier" but not all ASCII digits,
572 * ARG_NAME_NOT_VALID (-2) if it is neither.
575 static int32_t validateArgumentName(const UnicodeString
&name
);
578 * Returns a version of the parsed pattern string where each ASCII apostrophe
579 * is doubled (escaped) if it is not already, and if it is not interpreted as quoting syntax.
581 * For example, this turns "I don't '{know}' {gender,select,female{h''er}other{h'im}}."
582 * into "I don''t '{know}' {gender,select,female{h''er}other{h''im}}."
583 * @return the deep-auto-quoted version of the parsed pattern string.
584 * @see MessageFormat.autoQuoteApostrophe()
587 UnicodeString
autoQuoteApostropheDeep() const;
592 * Returns the number of "parts" created by parsing the pattern string.
593 * Returns 0 if no pattern has been parsed or clear() was called.
594 * @return the number of pattern parts.
597 int32_t countParts() const {
602 * Gets the i-th pattern "part".
603 * @param i The index of the Part data. (0..countParts()-1)
604 * @return the i-th pattern "part".
607 const Part
&getPart(int32_t i
) const {
612 * Returns the UMessagePatternPartType of the i-th pattern "part".
613 * Convenience method for getPart(i).getType().
614 * @param i The index of the Part data. (0..countParts()-1)
615 * @return The UMessagePatternPartType of the i-th Part.
618 UMessagePatternPartType
getPartType(int32_t i
) const {
619 return getPart(i
).type
;
623 * Returns the pattern index of the specified pattern "part".
624 * Convenience method for getPart(partIndex).getIndex().
625 * @param partIndex The index of the Part data. (0..countParts()-1)
626 * @return The pattern index of this Part.
629 int32_t getPatternIndex(int32_t partIndex
) const {
630 return getPart(partIndex
).index
;
634 * Returns the substring of the pattern string indicated by the Part.
635 * Convenience method for getPatternString().substring(part.getIndex(), part.getLimit()).
636 * @param part a part of this MessagePattern.
637 * @return the substring associated with part.
640 UnicodeString
getSubstring(const Part
&part
) const {
641 return msg
.tempSubString(part
.index
, part
.length
);
645 * Compares the part's substring with the input string s.
646 * @param part a part of this MessagePattern.
648 * @return TRUE if getSubstring(part).equals(s).
651 UBool
partSubstringMatches(const Part
&part
, const UnicodeString
&s
) const {
652 return 0==msg
.compare(part
.index
, part
.length
, s
);
656 * Returns the numeric value associated with an ARG_INT or ARG_DOUBLE.
657 * @param part a part of this MessagePattern.
658 * @return the part's numeric value, or UMSGPAT_NO_NUMERIC_VALUE if this is not a numeric part.
661 double getNumericValue(const Part
&part
) const;
664 * Returns the "offset:" value of a PluralFormat argument, or 0 if none is specified.
665 * @param pluralStart the index of the first PluralFormat argument style part. (0..countParts()-1)
666 * @return the "offset:" value.
669 double getPluralOffset(int32_t pluralStart
) const;
672 * Returns the index of the ARG|MSG_LIMIT part corresponding to the ARG|MSG_START at start.
673 * @param start The index of some Part data (0..countParts()-1);
674 * this Part should be of Type ARG_START or MSG_START.
675 * @return The first i>start where getPart(i).getType()==ARG|MSG_LIMIT at the same nesting level,
676 * or start itself if getPartType(msgStart)!=ARG|MSG_START.
679 int32_t getLimitPartIndex(int32_t start
) const {
680 int32_t limit
=getPart(start
).limitPartIndex
;
688 * A message pattern "part", representing a pattern parsing event.
689 * There is a part for the start and end of a message or argument,
690 * for quoting and escaping of and with ASCII apostrophes,
691 * and for syntax elements of "complex" arguments.
694 class Part
: public UMemory
{
697 * Default constructor, do not use.
703 * Returns the type of this part.
704 * @return the part type.
707 UMessagePatternPartType
getType() const {
712 * Returns the pattern string index associated with this Part.
713 * @return this part's pattern string index.
716 int32_t getIndex() const {
721 * Returns the length of the pattern substring associated with this Part.
722 * This is 0 for some parts.
723 * @return this part's pattern substring length.
726 int32_t getLength() const {
731 * Returns the pattern string limit (exclusive-end) index associated with this Part.
732 * Convenience method for getIndex()+getLength().
733 * @return this part's pattern string limit index, same as getIndex()+getLength().
736 int32_t getLimit() const {
741 * Returns a value associated with this part.
742 * See the documentation of each part type for details.
743 * @return the part value.
746 int32_t getValue() const {
751 * Returns the argument type if this part is of type ARG_START or ARG_LIMIT,
752 * otherwise UMSGPAT_ARG_TYPE_NONE.
753 * @return the argument type for this part.
756 UMessagePatternArgType
getArgType() const {
757 UMessagePatternPartType type
=getType();
758 if(type
==UMSGPAT_PART_TYPE_ARG_START
|| type
==UMSGPAT_PART_TYPE_ARG_LIMIT
) {
759 return (UMessagePatternArgType
)value
;
761 return UMSGPAT_ARG_TYPE_NONE
;
766 * Indicates whether the Part type has a numeric value.
767 * If so, then that numeric value can be retrieved via MessagePattern.getNumericValue().
768 * @param type The Part type to be tested.
769 * @return TRUE if the Part type has a numeric value.
772 static UBool
hasNumericValue(UMessagePatternPartType type
) {
773 return type
==UMSGPAT_PART_TYPE_ARG_INT
|| type
==UMSGPAT_PART_TYPE_ARG_DOUBLE
;
777 * @param other another object to compare with.
778 * @return TRUE if this object is equivalent to the other one.
781 UBool
operator==(const Part
&other
) const;
784 * @param other another object to compare with.
785 * @return FALSE if this object is equivalent to the other one.
788 inline UBool
operator!=(const Part
&other
) const {
789 return !operator==(other
);
793 * @return A hash code for this object.
796 int32_t hashCode() const {
797 return ((type
*37+index
)*37+length
)*37+value
;
801 friend class MessagePattern
;
803 static const int32_t MAX_LENGTH
=0xffff;
804 static const int32_t MAX_VALUE
=0x7fff;
806 // Some fields are not final because they are modified during pattern parsing.
807 // After pattern parsing, the parts are effectively immutable.
808 UMessagePatternPartType type
;
812 int32_t limitPartIndex
;
816 void preParse(const UnicodeString
&pattern
, UParseError
*parseError
, UErrorCode
&errorCode
);
820 int32_t parseMessage(int32_t index
, int32_t msgStartLength
,
821 int32_t nestingLevel
, UMessagePatternArgType parentType
,
822 UParseError
*parseError
, UErrorCode
&errorCode
);
824 int32_t parseArg(int32_t index
, int32_t argStartLength
, int32_t nestingLevel
,
825 UParseError
*parseError
, UErrorCode
&errorCode
);
827 int32_t parseSimpleStyle(int32_t index
, UParseError
*parseError
, UErrorCode
&errorCode
);
829 int32_t parseChoiceStyle(int32_t index
, int32_t nestingLevel
,
830 UParseError
*parseError
, UErrorCode
&errorCode
);
832 int32_t parsePluralOrSelectStyle(UMessagePatternArgType argType
, int32_t index
, int32_t nestingLevel
,
833 UParseError
*parseError
, UErrorCode
&errorCode
);
836 * Validates and parses an argument name or argument number string.
837 * This internal method assumes that the input substring is a "pattern identifier".
838 * @return >=0 if the name is a valid number,
839 * ARG_NAME_NOT_NUMBER (-1) if it is a "pattern identifier" but not all ASCII digits,
840 * ARG_NAME_NOT_VALID (-2) if it is neither.
841 * @see #validateArgumentName(String)
843 static int32_t parseArgNumber(const UnicodeString
&s
, int32_t start
, int32_t limit
);
845 int32_t parseArgNumber(int32_t start
, int32_t limit
) {
846 return parseArgNumber(msg
, start
, limit
);
850 * Parses a number from the specified message substring.
851 * @param start start index into the message string
852 * @param limit limit index into the message string, must be start<limit
853 * @param allowInfinity TRUE if U+221E is allowed (for ChoiceFormat)
857 void parseDouble(int32_t start
, int32_t limit
, UBool allowInfinity
,
858 UParseError
*parseError
, UErrorCode
&errorCode
);
860 // Java has package-private appendReducedApostrophes() here.
861 // In C++, this is declared in the MessageImpl class.
863 int32_t skipWhiteSpace(int32_t index
);
865 int32_t skipIdentifier(int32_t index
);
868 * Skips a sequence of characters that could occur in a double value.
869 * Does not fully parse or validate the value.
871 int32_t skipDouble(int32_t index
);
873 static UBool
isArgTypeChar(UChar32 c
);
875 UBool
isChoice(int32_t index
);
877 UBool
isPlural(int32_t index
);
879 UBool
isSelect(int32_t index
);
882 * @return TRUE if we are inside a MessageFormat (sub-)pattern,
883 * as opposed to inside a top-level choice/plural/select pattern.
885 UBool
inMessageFormatPattern(int32_t nestingLevel
);
888 * @return TRUE if we are in a MessageFormat sub-pattern
889 * of a top-level ChoiceFormat pattern.
891 UBool
inTopLevelChoiceMessage(int32_t nestingLevel
, UMessagePatternArgType parentType
);
893 void addPart(UMessagePatternPartType type
, int32_t index
, int32_t length
,
894 int32_t value
, UErrorCode
&errorCode
);
896 void addLimitPart(int32_t start
,
897 UMessagePatternPartType type
, int32_t index
, int32_t length
,
898 int32_t value
, UErrorCode
&errorCode
);
900 void addArgDoublePart(double numericValue
, int32_t start
, int32_t length
, UErrorCode
&errorCode
);
902 void setParseError(UParseError
*parseError
, int32_t index
);
904 // No ICU "poor man's RTTI" for this class nor its subclasses.
905 virtual UClassID
getDynamicClassID() const;
907 UBool
init(UErrorCode
&errorCode
);
908 UBool
copyStorage(const MessagePattern
&other
, UErrorCode
&errorCode
);
910 UMessagePatternApostropheMode aposMode
;
912 // ArrayList<Part> parts=new ArrayList<Part>();
913 MessagePatternPartsList
*partsList
;
916 // ArrayList<Double> numericValues;
917 MessagePatternDoubleList
*numericValuesList
;
918 double *numericValues
;
919 int32_t numericValuesLength
;
922 UBool needsAutoQuoting
;
927 #endif // !UCONFIG_NO_FORMATTING
929 #endif // __MESSAGEPATTERN_H__