private void evalPlural ( MessageArg arg , boolean cardinal ) { tag . skip ( COMMA_WS ) ; if ( ! arg . resolve ( ) ) { return ; } String value = arg . asString ( ) ; String offsetValue = value ; // Look for optional "offset:<number>" argument. This modifies the argument value, // changing the plural operands calculation. long offset = 0 ; if ( tag . seek ( PLURAL_OFFSET , choice ) ) { tag . jump ( choice ) ; tag . skip ( COMMA_WS ) ; // Parse the offset digits and the argument value. offset = toLong ( format , choice . pos + 7 , choice . end ) ; long newValue = toLong ( value , 0 , value . length ( ) ) - offset ; // Operands are evaluated based on the offset-adjusted value. offsetValue = Long . toString ( newValue ) ; operands . set ( offsetValue ) ; } else { operands . set ( value ) ; } // Evaluate the plural operands for the current argument. String language = locale . language ( ) ; PluralCategory category = cardinal ? PLURAL_RULES . evalCardinal ( language , operands ) : PLURAL_RULES . evalOrdinal ( language , operands ) ; Recognizer matcher = PLURAL_MATCHERS [ category . ordinal ( ) ] ; // Scan over the potential choices inside this tag. We will evaluate // the first choice that matches our plural category. char ch ; while ( ( ch = tag . peek ( ) ) != Chars . EOF ) { // First look for explicit match, falling back to a plural category. if ( ch == ' ' && tag . seek ( PLURAL_EXPLICIT , choice ) ) { tag . jump ( choice ) ; // Skip the '=' character. choice . pos ++ ; // If our argument matches the exact value, recurse and then return. String repr = choice . token ( ) . toString ( ) ; if ( repr . equals ( value ) && tag . seekBounds ( choice , ' ' , ' ' ) ) { recurse ( choice , offsetValue ) ; return ; } } else if ( tag . seek ( matcher , choice ) ) { // Jump over the plural category. tag . jump ( choice ) ; tag . skipWs ( ) ; // If the choice format is valid, recurse and then return. if ( tag . peek ( ) == ' ' && tag . seekBounds ( choice , ' ' , ' ' ) ) { recurse ( choice , offsetValue ) ; } return ; } // Skip over this choice and any trailing whitespace, or bail out if no match. if ( ! tag . seekBounds ( choice , ' ' , ' ' ) ) { return ; } tag . jump ( choice ) ; tag . skip ( COMMA_WS ) ; } }
PLURAL - Evaluate the argument as a plural either cardinal or ordinal .