@Override
 public void encodeToWriter(
     CharSequence str, int off, int len, Writer writer, EncodingState encodingState)
     throws IOException {
   if (str == null || len <= 0) {
     return;
   }
   int n = Math.min(str.length(), off + len);
   int i;
   int startPos = -1;
   char prevChar = (char) 0;
   for (i = off; i < n; i++) {
     char ch = str.charAt(i);
     if (startPos == -1) {
       startPos = i;
     }
     String escaped = escapeCharacter(ch, prevChar);
     if (escaped != null) {
       if (i - startPos > 0) {
         CharSequences.writeCharSequence(writer, str, startPos, i);
       }
       if (escaped.length() > 0) {
         writer.write(escaped);
       }
       startPos = -1;
     }
     prevChar = ch;
   }
   if (startPos > -1 && i - startPos > 0) {
     CharSequences.writeCharSequence(writer, str, startPos, i);
   }
 }
 /*
  * (non-Javadoc)
  * @see
  * EncodedAppender#append(org
  * .codehaus.groovy.grails.support.encoding.Encoder,
  * EncodingState, char[], int,
  * int)
  */
 public void append(Encoder encoder, EncodingState encodingState, char[] b, int off, int len)
     throws IOException {
   if (b == null || len <= 0) {
     return;
   }
   if (shouldEncode(encoder, encodingState)) {
     EncodingState newEncoders = createNewEncodingState(encoder, encodingState);
     if (encoder instanceof StreamingEncoder) {
       ((StreamingEncoder) encoder)
           .encodeToStream(
               encoder, CharSequences.createCharSequence(b, off, len), 0, len, this, newEncoders);
     } else {
       encodeAndWrite(encoder, newEncoders, String.valueOf(b, off, len));
     }
   } else {
     write(encodingState, b, off, len);
   }
 }
 /*
  * (non-Javadoc)
  * @see
  * EncodedAppender#append(org
  * .codehaus.groovy.grails.support.encoding.Encoder,
  * EncodingState,
  * java.lang.CharSequence, int, int)
  */
 public void append(
     Encoder encoder, EncodingState encodingState, CharSequence str, int off, int len)
     throws IOException {
   if (str == null || len <= 0) {
     return;
   }
   if (shouldEncode(encoder, encodingState)) {
     EncodingState newEncoders = createNewEncodingState(encoder, encodingState);
     if (encoder instanceof StreamingEncoder) {
       ((StreamingEncoder) encoder).encodeToStream(encoder, str, off, len, this, newEncoders);
     } else {
       CharSequence source;
       if (CharSequences.canUseOriginalForSubSequence(str, off, len)) {
         source = str;
       } else {
         source = str.subSequence(off, off + len);
       }
       encodeAndWrite(encoder, newEncoders, source);
     }
   } else {
     appendCharSequence(encodingState, str, off, off + len);
   }
 }