1 /* 2 * [The "BSD licence"] 3 * Copyright (c) 2010 Ben Gruver 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 package org.jf.util; 30 31 import java.io.IOException; 32 import java.io.Writer; 33 34 public class IndentingWriter extends Writer { 35 protected final Writer writer; 36 protected final char[] buffer = new char[24]; 37 protected int indentLevel = 0; 38 private boolean beginningOfLine = true; 39 private static final String newLine = System.getProperty("line.separator"); 40 IndentingWriter(Writer writer)41 public IndentingWriter(Writer writer) { 42 this.writer = writer; 43 } 44 writeIndent()45 protected void writeIndent() throws IOException { 46 for (int i=0; i<indentLevel; i++) { 47 writer.write(' '); 48 } 49 } 50 51 @Override write(int chr)52 public void write(int chr) throws IOException { 53 if (chr == '\n') { 54 writer.write(newLine); 55 beginningOfLine = true; 56 } else { 57 if (beginningOfLine) { 58 writeIndent(); 59 } 60 beginningOfLine = false; 61 writer.write(chr); 62 } 63 } 64 65 /** 66 * Writes out a block of text that contains no newlines 67 */ writeLine(char[] chars, int start, int len)68 private void writeLine(char[] chars, int start, int len) throws IOException { 69 if (beginningOfLine && len > 0) { 70 writeIndent(); 71 beginningOfLine = false; 72 } 73 writer.write(chars, start, len); 74 } 75 76 77 /** 78 * Writes out a block of text that contains no newlines 79 */ writeLine(String str, int start, int len)80 private void writeLine(String str, int start, int len) throws IOException { 81 if (beginningOfLine && len > 0) { 82 writeIndent(); 83 beginningOfLine = false; 84 } 85 writer.write(str, start, len); 86 } 87 88 @Override write(char[] chars)89 public void write(char[] chars) throws IOException { 90 write(chars, 0, chars.length); 91 } 92 93 @Override write(char[] chars, int start, int len)94 public void write(char[] chars, int start, int len) throws IOException { 95 final int end = start+len; 96 int pos = start; 97 while (pos < end) { 98 if (chars[pos] == '\n') { 99 writeLine(chars, start, pos-start); 100 101 writer.write(newLine); 102 beginningOfLine = true; 103 pos++; 104 start = pos; 105 } else { 106 pos++; 107 } 108 } 109 writeLine(chars, start, pos-start); 110 } 111 112 @Override write(String s)113 public void write(String s) throws IOException { 114 write(s, 0, s.length()); 115 } 116 117 @Override write(String str, int start, int len)118 public void write(String str, int start, int len) throws IOException { 119 final int end = start+len; 120 int pos = start; 121 while (pos < end) { 122 pos = str.indexOf('\n', start); 123 if (pos == -1 || pos >= end) { 124 writeLine(str, start, end-start); 125 return; 126 } else { 127 writeLine(str, start, pos-start); 128 writer.write(newLine); 129 beginningOfLine = true; 130 start = pos+1; 131 } 132 } 133 } 134 135 @Override append(CharSequence charSequence)136 public Writer append(CharSequence charSequence) throws IOException { 137 write(charSequence.toString()); 138 return this; 139 } 140 141 @Override append(CharSequence charSequence, int start, int len)142 public Writer append(CharSequence charSequence, int start, int len) throws IOException { 143 write(charSequence.subSequence(start, len).toString()); 144 return this; 145 } 146 147 @Override append(char c)148 public Writer append(char c) throws IOException { 149 write(c); 150 return this; 151 } 152 153 @Override flush()154 public void flush() throws IOException { 155 writer.flush(); 156 } 157 158 @Override close()159 public void close() throws IOException { 160 writer.close(); 161 } 162 indent(int indentAmount)163 public void indent(int indentAmount) { 164 this.indentLevel += indentAmount; 165 if (indentLevel < 0) { 166 indentLevel = 0; 167 } 168 } 169 deindent(int indentAmount)170 public void deindent(int indentAmount) { 171 this.indentLevel -= indentAmount; 172 if (indentLevel < 0) { 173 indentLevel = 0; 174 } 175 } 176 printUnsignedLongAsHex(long value)177 public void printUnsignedLongAsHex(long value) throws IOException { 178 int bufferIndex = 23; 179 do { 180 int digit = (int)(value & 15); 181 if (digit < 10) { 182 buffer[bufferIndex--] = (char)(digit + '0'); 183 } else { 184 buffer[bufferIndex--] = (char)((digit - 10) + 'a'); 185 } 186 187 value >>>= 4; 188 } while (value != 0); 189 190 bufferIndex++; 191 192 writeLine(buffer, bufferIndex, 24-bufferIndex); 193 } 194 printSignedLongAsDec(long value)195 public void printSignedLongAsDec(long value) throws IOException { 196 int bufferIndex = 23; 197 198 if (value < 0) { 199 value *= -1; 200 write('-'); 201 } 202 203 do { 204 long digit = value % 10; 205 buffer[bufferIndex--] = (char)(digit + '0'); 206 207 value = value / 10; 208 } while (value != 0); 209 210 bufferIndex++; 211 212 writeLine(buffer, bufferIndex, 24-bufferIndex); 213 } 214 printSignedIntAsDec(int value)215 public void printSignedIntAsDec(int value) throws IOException { 216 int bufferIndex = 15; 217 218 if (value < 0) { 219 value *= -1; 220 write('-'); 221 } 222 223 do { 224 int digit = value % 10; 225 buffer[bufferIndex--] = (char)(digit + '0'); 226 227 value = value / 10; 228 } while (value != 0); 229 230 bufferIndex++; 231 232 writeLine(buffer, bufferIndex, 16-bufferIndex); 233 } 234 printUnsignedIntAsDec(int value)235 public void printUnsignedIntAsDec(int value) throws IOException { 236 int bufferIndex = 15; 237 238 if (value < 0) { 239 printSignedLongAsDec(value & 0xFFFFFFFFL); 240 } else { 241 printSignedIntAsDec(value); 242 } 243 } 244 } 245