Home | History | Annotate | Download | only in util
      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 
     41     public IndentingWriter(Writer writer) {
     42         this.writer = writer;
     43     }
     44 
     45     protected void writeIndent() throws IOException {
     46         for (int i=0; i<indentLevel; i++) {
     47             writer.write(' ');
     48         }
     49     }
     50 
     51     @Override
     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      */
     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      */
     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
     89     public void write(char[] chars) throws IOException {
     90         write(chars, 0, chars.length);
     91     }
     92 
     93     @Override
     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
    113     public void write(String s) throws IOException {
    114         write(s, 0, s.length());
    115     }
    116 
    117     @Override
    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
    136     public Writer append(CharSequence charSequence) throws IOException {
    137         write(charSequence.toString());
    138         return this;
    139     }
    140 
    141     @Override
    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
    148     public Writer append(char c) throws IOException {
    149         write(c);
    150         return this;
    151     }
    152 
    153     @Override
    154     public void flush() throws IOException {
    155         writer.flush();
    156     }
    157 
    158     @Override
    159     public void close() throws IOException {
    160         writer.close();
    161     }
    162 
    163     public void indent(int indentAmount) {
    164         this.indentLevel += indentAmount;
    165         if (indentLevel < 0) {
    166             indentLevel = 0;
    167         }
    168     }
    169 
    170     public void deindent(int indentAmount) {
    171         this.indentLevel -= indentAmount;
    172         if (indentLevel < 0) {
    173             indentLevel = 0;
    174         }
    175     }
    176 
    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 
    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 
    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 
    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