@Test(expected = IllegalArgumentException.class) public void stringWithoutQuoteRaises() { ProtoString.parse("foo"); }
public static ProtoString parse(String encoded) { if (encoded.isEmpty()) { throw new IllegalArgumentException("String must not be empty."); } if (encoded.charAt(0) != '\'' && encoded.charAt(0) != '"') { throw new IllegalArgumentException("String must start with a single or double quote."); } int[] offsets = new int[encoded.length()]; ImmutableList.Builder<TextRange> invalidEscapeRanges = ImmutableList.builder(); StringBuilder result = new StringBuilder(encoded.length()); StringLexer lexer = new StringLexer(); lexer.start(encoded); boolean lastWasLiteral = false; while (lexer.hasMoreTokens()) { CharSequence value = lexer.currentTokenValue(); int start = lexer.getTokenStart(); for (int i = 0; i < value.length(); i++) { offsets[result.length() + i] = start + i; } result.append(value); if (lexer.isCurrentTokenInvalid()) { invalidEscapeRanges.add(TextRange.create(lexer.getTokenStart(), lexer.getTokenEnd())); } lastWasLiteral = lexer.isCurrentTokenLiteral(); lexer.advance(); } boolean unterminated = false; String parsed; if (!lastWasLiteral || result.charAt(result.length() - 1) != result.charAt(0) || result.length() == 1) { unterminated = true; parsed = result.substring(1); } else { parsed = result.substring(1, result.length() - 1); } offsets = Arrays.copyOfRange(offsets, 1, 1 + parsed.length()); return new ProtoString(encoded, parsed, unterminated, invalidEscapeRanges.build(), offsets); }
ProtoString { public static ProtoString parse(String encoded) { if (encoded.isEmpty()) { throw new IllegalArgumentException("String must not be empty."); } if (encoded.charAt(0) != '\'' && encoded.charAt(0) != '"') { throw new IllegalArgumentException("String must start with a single or double quote."); } int[] offsets = new int[encoded.length()]; ImmutableList.Builder<TextRange> invalidEscapeRanges = ImmutableList.builder(); StringBuilder result = new StringBuilder(encoded.length()); StringLexer lexer = new StringLexer(); lexer.start(encoded); boolean lastWasLiteral = false; while (lexer.hasMoreTokens()) { CharSequence value = lexer.currentTokenValue(); int start = lexer.getTokenStart(); for (int i = 0; i < value.length(); i++) { offsets[result.length() + i] = start + i; } result.append(value); if (lexer.isCurrentTokenInvalid()) { invalidEscapeRanges.add(TextRange.create(lexer.getTokenStart(), lexer.getTokenEnd())); } lastWasLiteral = lexer.isCurrentTokenLiteral(); lexer.advance(); } boolean unterminated = false; String parsed; if (!lastWasLiteral || result.charAt(result.length() - 1) != result.charAt(0) || result.length() == 1) { unterminated = true; parsed = result.substring(1); } else { parsed = result.substring(1, result.length() - 1); } offsets = Arrays.copyOfRange(offsets, 1, 1 + parsed.length()); return new ProtoString(encoded, parsed, unterminated, invalidEscapeRanges.build(), offsets); } }
ProtoString { public static ProtoString parse(String encoded) { if (encoded.isEmpty()) { throw new IllegalArgumentException("String must not be empty."); } if (encoded.charAt(0) != '\'' && encoded.charAt(0) != '"') { throw new IllegalArgumentException("String must start with a single or double quote."); } int[] offsets = new int[encoded.length()]; ImmutableList.Builder<TextRange> invalidEscapeRanges = ImmutableList.builder(); StringBuilder result = new StringBuilder(encoded.length()); StringLexer lexer = new StringLexer(); lexer.start(encoded); boolean lastWasLiteral = false; while (lexer.hasMoreTokens()) { CharSequence value = lexer.currentTokenValue(); int start = lexer.getTokenStart(); for (int i = 0; i < value.length(); i++) { offsets[result.length() + i] = start + i; } result.append(value); if (lexer.isCurrentTokenInvalid()) { invalidEscapeRanges.add(TextRange.create(lexer.getTokenStart(), lexer.getTokenEnd())); } lastWasLiteral = lexer.isCurrentTokenLiteral(); lexer.advance(); } boolean unterminated = false; String parsed; if (!lastWasLiteral || result.charAt(result.length() - 1) != result.charAt(0) || result.length() == 1) { unterminated = true; parsed = result.substring(1); } else { parsed = result.substring(1, result.length() - 1); } offsets = Arrays.copyOfRange(offsets, 1, 1 + parsed.length()); return new ProtoString(encoded, parsed, unterminated, invalidEscapeRanges.build(), offsets); } private  ProtoString(
      String original,
      String parsed,
      boolean unterminated,
      ImmutableList<TextRange> invalidEscapeRanges,
      int[] offsets); }
ProtoString { public static ProtoString parse(String encoded) { if (encoded.isEmpty()) { throw new IllegalArgumentException("String must not be empty."); } if (encoded.charAt(0) != '\'' && encoded.charAt(0) != '"') { throw new IllegalArgumentException("String must start with a single or double quote."); } int[] offsets = new int[encoded.length()]; ImmutableList.Builder<TextRange> invalidEscapeRanges = ImmutableList.builder(); StringBuilder result = new StringBuilder(encoded.length()); StringLexer lexer = new StringLexer(); lexer.start(encoded); boolean lastWasLiteral = false; while (lexer.hasMoreTokens()) { CharSequence value = lexer.currentTokenValue(); int start = lexer.getTokenStart(); for (int i = 0; i < value.length(); i++) { offsets[result.length() + i] = start + i; } result.append(value); if (lexer.isCurrentTokenInvalid()) { invalidEscapeRanges.add(TextRange.create(lexer.getTokenStart(), lexer.getTokenEnd())); } lastWasLiteral = lexer.isCurrentTokenLiteral(); lexer.advance(); } boolean unterminated = false; String parsed; if (!lastWasLiteral || result.charAt(result.length() - 1) != result.charAt(0) || result.length() == 1) { unterminated = true; parsed = result.substring(1); } else { parsed = result.substring(1, result.length() - 1); } offsets = Arrays.copyOfRange(offsets, 1, 1 + parsed.length()); return new ProtoString(encoded, parsed, unterminated, invalidEscapeRanges.build(), offsets); } private  ProtoString(
      String original,
      String parsed,
      boolean unterminated,
      ImmutableList<TextRange> invalidEscapeRanges,
      int[] offsets); String getOriginal(); @Override String toString(); ImmutableList<TextRange> getInvalidEscapeRanges(); boolean isUnterminated(); int getOriginalOffset(int offset); static ProtoString parse(String encoded); }
ProtoString { public static ProtoString parse(String encoded) { if (encoded.isEmpty()) { throw new IllegalArgumentException("String must not be empty."); } if (encoded.charAt(0) != '\'' && encoded.charAt(0) != '"') { throw new IllegalArgumentException("String must start with a single or double quote."); } int[] offsets = new int[encoded.length()]; ImmutableList.Builder<TextRange> invalidEscapeRanges = ImmutableList.builder(); StringBuilder result = new StringBuilder(encoded.length()); StringLexer lexer = new StringLexer(); lexer.start(encoded); boolean lastWasLiteral = false; while (lexer.hasMoreTokens()) { CharSequence value = lexer.currentTokenValue(); int start = lexer.getTokenStart(); for (int i = 0; i < value.length(); i++) { offsets[result.length() + i] = start + i; } result.append(value); if (lexer.isCurrentTokenInvalid()) { invalidEscapeRanges.add(TextRange.create(lexer.getTokenStart(), lexer.getTokenEnd())); } lastWasLiteral = lexer.isCurrentTokenLiteral(); lexer.advance(); } boolean unterminated = false; String parsed; if (!lastWasLiteral || result.charAt(result.length() - 1) != result.charAt(0) || result.length() == 1) { unterminated = true; parsed = result.substring(1); } else { parsed = result.substring(1, result.length() - 1); } offsets = Arrays.copyOfRange(offsets, 1, 1 + parsed.length()); return new ProtoString(encoded, parsed, unterminated, invalidEscapeRanges.build(), offsets); } private  ProtoString(
      String original,
      String parsed,
      boolean unterminated,
      ImmutableList<TextRange> invalidEscapeRanges,
      int[] offsets); String getOriginal(); @Override String toString(); ImmutableList<TextRange> getInvalidEscapeRanges(); boolean isUnterminated(); int getOriginalOffset(int offset); static ProtoString parse(String encoded);  }