001 /*
002 * Copyright (C) 2010 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019
020 package org.crsh.util;
021
022 import org.crsh.shell.io.ShellWriter;
023 import org.crsh.shell.io.ShellWriterContext;
024
025 import java.io.IOException;
026
027 /**
028 * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
029 * @version $Revision$
030 */
031 public class LineFeedWriter implements ShellWriter {
032
033 /** . */
034 private static final int NOT_PADDED = 0;
035
036 /** . */
037 private static final int PADDING = 1;
038
039 /** . */
040 private static final int PADDED = 2;
041
042 /** . */
043 private final Appendable out;
044
045 /** . */
046 private final String lineFeed;
047
048 /** . */
049 private int status;
050
051 public LineFeedWriter(Appendable out) {
052 this(out, "\r\n");
053 }
054
055 public LineFeedWriter(Appendable out, String lineFeed) {
056 this.out = out;
057 this.lineFeed = lineFeed;
058 this.status = NOT_PADDED;
059 }
060
061 public Appendable append(char c) throws IOException {
062 return append(null, c);
063 }
064
065 public ShellWriter append(ShellWriterContext ctx, final char c) throws IOException {
066 return append(ctx, Character.toString(c));
067 }
068
069 public Appendable append(CharSequence csq, int start, int end) throws IOException {
070 return append(null, csq, start, end);
071 }
072
073 public Appendable append(CharSequence csq) throws IOException {
074 return append(null, csq);
075 }
076
077 public ShellWriter append(ShellWriterContext ctx, CharSequence csq) throws IOException {
078 return append(ctx, csq, 0, csq.length());
079 }
080
081 public ShellWriter append(ShellWriterContext ctx, CharSequence csq, int start, int end) throws IOException {
082 int previous = start;
083 int to = start + end;
084 for (int i = start;i < to;i++) {
085 char c = csq.charAt(i);
086 if (c == '\r') {
087 if (i > previous) {
088 realAppend(ctx, csq, previous, i);
089 }
090 previous = i + 1;
091 } else if (c == '\n') {
092 if (i > previous) {
093 realAppend(ctx, csq, previous, i);
094 }
095 writeLF(ctx);
096 previous = i + 1;
097 i++;
098 }
099 }
100 if (to != previous) {
101 realAppend(ctx, csq, previous, to);
102 }
103 return this;
104 }
105
106 private void realAppend(ShellWriterContext ctx, CharSequence csq, int off, int end) throws IOException {
107 if (end > off) {
108
109 //
110 switch (status) {
111 case NOT_PADDED:
112 if (ctx != null) {
113 status = PADDING;
114 ctx.pad(this);
115 }
116 status = PADDED;
117 break;
118 case PADDING:
119 case PADDED:
120 // Do nothing
121 break;
122 default:
123 throw new AssertionError();
124 }
125
126 //
127 out.append(csq, off, end);
128
129 //
130 switch (status) {
131 case PADDING:
132 // Do nothing
133 break;
134 case PADDED:
135 if (ctx != null) {
136 ctx.text(csq, off, end);
137 }
138 break;
139 default:
140 throw new AssertionError();
141 }
142 }
143 }
144
145 private void writeLF(ShellWriterContext ctx) throws IOException {
146 switch (status) {
147 case PADDING:
148 throw new IllegalStateException();
149 case PADDED:
150 status = NOT_PADDED;
151 case NOT_PADDED:
152 out.append(lineFeed);
153 if (ctx != null) {
154 ctx.lineFeed();
155 }
156 break;
157 default:
158 throw new AssertionError();
159 }
160 }
161 }