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 }