/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.jstestdriver.token;
import com.google.common.collect.Maps;
import java.io.FilterWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Collections;
import java.util.Map;
/**
* Automatically escapes \, ', ", \n, \f, \r when writing to the underlying writer.
* (Why isn't the Gson Escaper public? Arg!)
* Not Thread Safe!
* @author corysmith@google.com (Cory Smith)
*
*/
public class EscapingWriter extends FilterWriter {
private static final Map<Character, char[]> REPLACE;
static {
Map<Character, char[]> replace = Maps.newHashMap();
replace.put('\\', new char[]{'\\','\\'});
replace.put('\n', new char[]{'\\','n'});
replace.put('\r', new char[]{'\\','r'});
replace.put('\f', new char[]{'\\','f'});
replace.put('\'', new char[]{'\\','\''});
replace.put('"', new char[]{'\\','"'});
REPLACE = Collections.unmodifiableMap(replace);
}
private final char[] escapedBuffer = new char[256];
public EscapingWriter(Writer out) {
super(out);
}
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
int pos = 0;
for (int i = off; i < len; i++ ) {
if (REPLACE.containsKey(Character.valueOf(cbuf[i]))) {
pos = writeToBuffer(pos, REPLACE.get(cbuf[i]));
} else {
pos = writeToBuffer(pos, cbuf[i]);
}
}
out.write(escapedBuffer, 0, pos);
}
private int writeToBuffer(int pos, char c) throws IOException {
if (pos + 1 > escapedBuffer.length) { // flush it
out.write(escapedBuffer, 0, pos);
pos = 0;
}
escapedBuffer[pos++] = c;
return pos;
}
private int writeToBuffer(int pos, char[] characters) throws IOException {
if (pos + characters.length > escapedBuffer.length) { // flush it
out.write(escapedBuffer, 0, pos);
pos = 0;
}
System.arraycopy(characters, 0, escapedBuffer, 0, pos);
pos += characters.length;
return pos;
}
@Override
public void write(int c) throws IOException {
Character chr = Character.valueOf((char)c);
if (REPLACE.containsKey(chr)) {
out.write(REPLACE.get(chr));
} else {
out.write(c);
}
}
@Override
public void write(char[] cbuf) throws IOException {
write(cbuf, 0, cbuf.length);
}
}