FormatOptions { public static FormatOptions parse(String message, int pos, int end, boolean isUpperCase) throws ParseException { if (pos == end && !isUpperCase) { return DEFAULT; } 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 == '.') { 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; } int widthStart = pos - 1; if (c > '9') { throw ParseException.atPosition("invalid flag", message, widthStart); } int width = c - '0'; 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 - '0'); 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); } } } private  FormatOptions(int flags, int width, int precision); static FormatOptions getDefault(); static FormatOptions of(int flags, int width, int precision); static FormatOptions parse(String message, int pos, int end, boolean isUpperCase); FormatOptions filter(int allowedFlags, boolean allowWidth, boolean allowPrecision); @SuppressWarnings("ReferenceEquality") boolean isDefault(); int getWidth(); int getPrecision(); boolean validate(int allowedFlags, boolean allowPrecision); boolean areValidFor(FormatChar formatChar); int getFlags(); boolean shouldLeftAlign(); boolean shouldShowAltForm(); boolean shouldShowLeadingZeros(); boolean shouldPrefixPlusForPositiveValues(); boolean shouldPrefixSpaceForPositiveValues(); boolean shouldShowGrouping(); boolean shouldUpperCase(); StringBuilder appendPrintfOptions(StringBuilder out); @Override boolean equals(@NullableDecl Object o); @Override int hashCode(); static final int FLAG_PREFIX_SPACE_FOR_POSITIVE_VALUES; static final int FLAG_SHOW_ALT_FORM; static final int FLAG_USE_PARENS_FOR_NEGATIVE_VALUES; static final int FLAG_PREFIX_PLUS_FOR_POSITIVE_VALUES; static final int FLAG_SHOW_GROUPING; static final int FLAG_LEFT_ALIGN; static final int FLAG_SHOW_LEADING_ZEROS; static final int FLAG_UPPER_CASE; static final int ALL_FLAGS; static final int UNSET; }
@Test public void testBadFlags() { try { FormatOptions.parse("%", 0, 1, false); fail("expected ParseException"); } catch (ParseException expected) { } try { FormatOptions.parse("-#-", 0, 3, false); fail("expected ParseException"); } catch (ParseException expected) { } }
@Test public void testWidth() throws ParseException { FormatOptions options = FormatOptions.parse("%1234x", 1, 5, false); assertThat(options).hasWidth(1234); assertThat(options).hasPrecision(-1); assertThat(options).hasNoFlags(); }
@Test public void testWidthTooLarge() throws ParseException { FormatOptions options = FormatOptions.parse("%999999x", 1, 7, false); assertThat(options).hasWidth(999999); assertThat(options).hasPrecision(-1); assertThat(options).hasNoFlags(); try { FormatOptions.parse("%1000000x", 1, 8, false); fail("expected ParseException"); } catch (ParseException expected) { } }
@Test public void testPrecision() throws ParseException { FormatOptions options = FormatOptions.parse("%.1234x", 1, 6, false); assertThat(options).hasWidth(-1); assertThat(options).hasPrecision(1234); assertThat(options).hasNoFlags(); }
@Test public void testPrecisionTooLarge() throws ParseException { FormatOptions options = FormatOptions.parse("%.999999x", 1, 8, false); assertThat(options).hasWidth(-1); assertThat(options).hasPrecision(999999); assertThat(options).hasNoFlags(); try { FormatOptions.parse("%.1000000x", 2, 9, false); fail("expected ParseException"); } catch (ParseException expected) { } }
@Test public void testValidateLikeInconsistentFlags() { FormatOptions options; options = parse("+ ", false); for (FormatChar fc : FormatChar.values()) { assertThat(options).areNotValidFor(fc); } options = parse("-0", false); for (FormatChar fc : FormatChar.values()) { assertThat(options).areNotValidFor(fc); } }