public static FormatOptions parse ( String message , int pos , int end , boolean isUpperCase ) throws ParseException { // It is vital that we shortcut parsing and return the default instance here (rather than just // creating a new instance with default values) because we check for it using '==' later). // Also, it saves us thousands of otherwise unnecessary allocations. if ( pos == end && ! isUpperCase ) { return DEFAULT ; } // STEP 1: Parse flag bits. int flags = isUpperCase ? FLAG_UPPER_CASE : 0 ; char c ; while ( true ) { if ( pos == end ) { return new FormatOptions ( flags , UNSET , UNSET ) ; } c = message . charAt ( pos ++ ) ; if ( c < MIN_FLAG_VALUE || c > MAX_FLAG_VALUE ) { break ; } int flagIdx = indexOfFlagCharacter ( c ) ; if ( flagIdx < 0 ) { if ( c == ' ' ) { // Edge case of something like "%.2f" (precision but no width). return new FormatOptions ( flags , UNSET , parsePrecision ( message , pos , end ) ) ; } throw ParseException . atPosition ( "invalid flag" , message , pos - 1 ) ; } int flagBit = 1 << flagIdx ; if ( ( flags & flagBit ) != 0 ) { throw ParseException . atPosition ( "repeated flag" , message , pos - 1 ) ; } flags |= flagBit ; } // STEP 2: Parse width (which must start with [1-9]). // We know that c > MAX_FLAG_VALUE, which is really just '0', so (c >= 1) int widthStart = pos - 1 ; if ( c > ' ' ) { throw ParseException . atPosition ( "invalid flag" , message , widthStart ) ; } int width = c - ' ' ; while ( true ) { if ( pos == end ) { return new FormatOptions ( flags , width , UNSET ) ; } c = message . charAt ( pos ++ ) ; if ( c == ' ' ) { return new FormatOptions ( flags , width , parsePrecision ( message , pos , end ) ) ; } int n = ( char ) ( c - ' ' ) ; if ( n >= 10 ) { throw ParseException . atPosition ( "invalid width character" , message , pos - 1 ) ; } width = ( width * 10 ) + n ; if ( width > MAX_ALLOWED_WIDTH ) { throw ParseException . withBounds ( "width too large" , message , widthStart , end ) ; } } }
Parses a sub - sequence of a log message to extract and return its options . Note that callers cannot rely on this method producing new instances each time it is called as caching of common option values may occur .