code: private void appendDecodedPctUtf8(StringBuilder sb, ByteBuffer bbuf,
  			String inputStr, int seqStart, int seqEnd,
  			CharsetDecoder utf8decoder) {
  		// assert bbuf.position() * 3 == seqEnd - seqStart;
  		utf8decoder.reset();
  		CharBuffer cbuf = CharBuffer.allocate(bbuf.position());
  		bbuf.flip();
  		while (bbuf.position() < bbuf.limit()) {
  			CoderResult coderResult = utf8decoder.decode(bbuf, cbuf, true);
  			sb.append(cbuf.flip());
  			if (coderResult.isMalformed()) {
  				// put the malformed %xx%xx into the result un-decoded
  				CharSequence undecodablePctHex = inputStr.subSequence(seqStart
  						+ 3 * bbuf.position(), seqStart + 3 * bbuf.position()
  						+ 3 * coderResult.length());
  				sb.append(undecodablePctHex);
  
  				// there could be more good stuff after the bad
  				bbuf.position(bbuf.position() + coderResult.length());
  			}
  			cbuf.clear();
  		}
  	}
docs: Decodes bytes in bbuf as utf-8 and appends decoded characters to sb. If
  decoding of any portion fails, appends the un-decodable %xx%xx sequence
  extracted from inputStr instead of decoded characters. See "bad unicode"
  tests in GoogleCanonicalizerTest#testDecode(). Variables only make sense
  within context of {@link #decode(String)}.
  
  @param sb
  StringBuilder to append to
  @param bbuf
  raw bytes decoded from %-encoded input
  @param inputStr
  full input string
  @param seqStart
  start index inclusive within inputStr of %-encoded sequence
  @param seqEnd
  end index exclusive within inputStr of %-encoded sequence
  @param utf8decoder