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
29package org.jf.util;
30
31import java.io.IOException;
32import java.io.Writer;
33
34public class IndentingWriter extends Writer {
35    protected final Writer writer;
36    protected final char[] buffer = new char[16];
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 writeLineStart() throws IOException {
46    }
47
48    protected void writeIndent() throws IOException {
49        for (int i=0; i<indentLevel; i++) {
50            writer.write(' ');
51        }
52    }
53
54    @Override
55    public void write(int chr) throws IOException {
56        //synchronized(lock) {
57            if (beginningOfLine) {
58                writeLineStart();
59            }
60            if (chr == '\n') {
61                writer.write(newLine);
62                beginningOfLine = true;
63            } else {
64                if (beginningOfLine) {
65                    writeIndent();
66                }
67                beginningOfLine = false;
68                writer.write(chr);
69            }
70        //}
71    }
72
73    @Override
74    public void write(char[] chars) throws IOException {
75        //synchronized(lock) {
76            for (char chr: chars) {
77                write(chr);
78            }
79        //}
80    }
81
82    @Override
83    public void write(char[] chars, int start, int len) throws IOException {
84        //synchronized(lock) {
85            len = start+len;
86            while (start < len) {
87                write(chars[start++]);
88            }
89        //}
90    }
91
92    @Override
93    public void write(String s) throws IOException {
94        //synchronized (lock) {
95            for (int i=0; i<s.length(); i++) {
96                write(s.charAt(i));
97            }
98        //}
99    }
100
101    @Override
102    public void write(String str, int start, int len) throws IOException {
103        //synchronized(lock) {
104            len = start+len;
105            while (start < len) {
106                write(str.charAt(start++));
107            }
108        //}
109    }
110
111    @Override
112    public Writer append(CharSequence charSequence) throws IOException {
113        write(charSequence.toString());
114        return this;
115    }
116
117    @Override
118    public Writer append(CharSequence charSequence, int start, int len) throws IOException {
119        write(charSequence.subSequence(start, len).toString());
120        return this;
121    }
122
123    @Override
124    public Writer append(char c) throws IOException {
125        write(c);
126        return this;
127    }
128
129    @Override
130    public void flush() throws IOException {
131        //synchronized(lock) {
132            writer.flush();
133        //}
134    }
135
136    @Override
137    public void close() throws IOException {
138        //synchronized(lock) {
139            writer.close();
140        //}
141    }
142
143    public void indent(int indentAmount) {
144        //synchronized(lock) {
145            this.indentLevel += indentAmount;
146            if (indentLevel < 0) {
147                indentLevel = 0;
148            }
149        //}
150    }
151
152    public void deindent(int indentAmount) {
153        //synchronized(lock) {
154            this.indentLevel -= indentAmount;
155            if (indentLevel < 0) {
156                indentLevel = 0;
157            }
158        //}
159    }
160
161    public void printUnsignedLongAsHex(long value) throws IOException {
162        int bufferIndex = 0;
163        do {
164            int digit = (int)(value & 15);
165            if (digit < 10) {
166                buffer[bufferIndex++] = (char)(digit + '0');
167            } else {
168                buffer[bufferIndex++] = (char)((digit - 10) + 'a');
169            }
170
171            value >>>= 4;
172        } while (value != 0);
173
174        while (bufferIndex>0) {
175            write(buffer[--bufferIndex]);
176        }
177    }
178
179    public void printSignedIntAsDec(int value) throws IOException {
180        int bufferIndex = 0;
181
182        if (value < 0) {
183            value *= -1;
184            write('-');
185        }
186
187        do {
188            int digit = value % 10;
189            buffer[bufferIndex++] = (char)(digit + '0');
190
191            value = value / 10;
192        } while (value != 0);
193
194        while (bufferIndex>0) {
195            write(buffer[--bufferIndex]);
196        }
197    }
198}
199