http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/utility/StandardCompress.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/StandardCompress.java
b/src/main/java/freemarker/template/utility/StandardCompress.java
deleted file mode 100644
index 4a40acf..0000000
--- a/src/main/java/freemarker/template/utility/StandardCompress.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 freemarker.template.utility;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Map;
-
-import freemarker.template.TemplateBooleanModel;
-import freemarker.template.TemplateModelException;
-import freemarker.template.TemplateNumberModel;
-import freemarker.template.TemplateTransformModel;
-
-/**
- * <p>A filter that compresses each sequence of consecutive whitespace
- * to a single line break (if the sequence contains a line break) or a
- * single space. In addition, leading and trailing whitespace is
- * completely removed.</p>
- *
- * <p>Specify the transform parameter <code>single_line = true</code>
- * to always compress to a single space instead of a line break.</p>
- *
- * <p>The default buffer size can be overridden by specifying a
- * <code>buffer_size</code> transform parameter (in bytes).</p>
- *
- * <p><b>Note:</b> The compress tag is implemented using this filter</p>
- *
- * <p>Usage:<br>
- * From java:</p>
- * <pre>
- * SimpleHash root = new SimpleHash();
- *
- * root.put( "standardCompress", new
freemarker.template.utility.StandardCompress() );
- *
- * ...
- * </pre>
- *
- * <p>From your FreeMarker template:</p>
- * <pre>
- * <transform standardCompress>
- * <p>This paragraph will have
- * extraneous
- *
- * whitespace removed.</p>
- * </transform>
- * </pre>
- *
- * <p>Output:</p>
- * <pre>
- * <p>This paragraph will have
- * extraneous
- * whitespace removed.</p>
- * </pre>
- */
-public class StandardCompress implements TemplateTransformModel {
- private static final String BUFFER_SIZE_KEY = "buffer_size";
- private static final String SINGLE_LINE_KEY = "single_line";
- private int defaultBufferSize;
-
- public static final StandardCompress INSTANCE = new StandardCompress();
-
- public StandardCompress() {
- this(2048);
- }
-
- /**
- * @param defaultBufferSize the default amount of characters to buffer
- */
- public StandardCompress(int defaultBufferSize) {
- this.defaultBufferSize = defaultBufferSize;
- }
-
- public Writer getWriter(final Writer out, Map args)
- throws TemplateModelException {
- int bufferSize = defaultBufferSize;
- boolean singleLine = false;
- if (args != null) {
- try {
- TemplateNumberModel num = (TemplateNumberModel)
args.get(BUFFER_SIZE_KEY);
- if (num != null)
- bufferSize = num.getAsNumber().intValue();
- } catch (ClassCastException e) {
- throw new TemplateModelException("Expecting numerical argument
to " + BUFFER_SIZE_KEY);
- }
- try {
- TemplateBooleanModel flag = (TemplateBooleanModel)
args.get(SINGLE_LINE_KEY);
- if (flag != null)
- singleLine = flag.getAsBoolean();
- } catch (ClassCastException e) {
- throw new TemplateModelException("Expecting boolean argument
to " + SINGLE_LINE_KEY);
- }
- }
- return new StandardCompressWriter(out, bufferSize, singleLine);
- }
-
- private static class StandardCompressWriter extends Writer {
- private static final int MAX_EOL_LENGTH = 2; // CRLF is two bytes
-
- private static final int AT_BEGINNING = 0;
- private static final int SINGLE_LINE = 1;
- private static final int INIT = 2;
- private static final int SAW_CR = 3;
- private static final int LINEBREAK_CR = 4;
- private static final int LINEBREAK_CRLF = 5;
- private static final int LINEBREAK_LF = 6;
-
- private final Writer out;
- private final char[] buf;
- private final boolean singleLine;
-
- private int pos = 0;
- private boolean inWhitespace = true;
- private int lineBreakState = AT_BEGINNING;
-
- public StandardCompressWriter(Writer out, int bufSize, boolean
singleLine) {
- this.out = out;
- this.singleLine = singleLine;
- buf = new char[bufSize];
- }
-
- @Override
- public void write(char[] cbuf, int off, int len) throws IOException {
- for (; ; ) {
- // Need to reserve space for the EOL potentially left in the
state machine
- int room = buf.length - pos - MAX_EOL_LENGTH;
- if (room >= len) {
- writeHelper(cbuf, off, len);
- break;
- } else if (room <= 0) {
- flushInternal();
- } else {
- writeHelper(cbuf, off, room);
- flushInternal();
- off += room;
- len -= room;
- }
- }
- }
-
- private void writeHelper(char[] cbuf, int off, int len) {
- for (int i = off, end = off + len; i < end; i++) {
- char c = cbuf[i];
- if (Character.isWhitespace(c)) {
- inWhitespace = true;
- updateLineBreakState(c);
- } else if (inWhitespace) {
- inWhitespace = false;
- writeLineBreakOrSpace();
- buf[pos++] = c;
- } else {
- buf[pos++] = c;
- }
- }
- }
-
- /*
- \r\n => CRLF
- \r[^\n] => CR
- \r$ => CR
- [^\r]\n => LF
- ^\n => LF
- */
- private void updateLineBreakState(char c) {
- switch (lineBreakState) {
- case INIT:
- if (c == '\r') {
- lineBreakState = SAW_CR;
- } else if (c == '\n') {
- lineBreakState = LINEBREAK_LF;
- }
- break;
- case SAW_CR:
- if (c == '\n') {
- lineBreakState = LINEBREAK_CRLF;
- } else {
- lineBreakState = LINEBREAK_CR;
- }
- }
- }
-
- private void writeLineBreakOrSpace() {
- switch (lineBreakState) {
- case SAW_CR:
- // whitespace ended with CR, fall through
- case LINEBREAK_CR:
- buf[pos++] = '\r';
- break;
- case LINEBREAK_CRLF:
- buf[pos++] = '\r';
- // fall through
- case LINEBREAK_LF:
- buf[pos++] = '\n';
- break;
- case AT_BEGINNING:
- // ignore leading whitespace
- break;
- case INIT:
- case SINGLE_LINE:
- buf[pos++] = ' ';
- }
- lineBreakState = (singleLine) ? SINGLE_LINE : INIT;
- }
-
- private void flushInternal() throws IOException {
- out.write(buf, 0, pos);
- pos = 0;
- }
-
- @Override
- public void flush() throws IOException {
- flushInternal();
- out.flush();
- }
-
- @Override
- public void close() throws IOException {
- flushInternal();
- }
- }
-}