1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/*
2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project
3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License");
5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License.
6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at
7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *      http://www.apache.org/licenses/LICENSE-2.0
9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software
11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS,
12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and
14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License.
15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.util;
18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.IOException;
20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.OutputStream;
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.OutputStreamWriter;
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.StringWriter;
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.Writer;
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Class that takes a combined output destination and provides two
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * output writers, one of which ends up writing to the left column and
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * one which goes on the right.
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class TwoColumnOutput {
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} underlying writer for final output */
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final Writer out;
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code > 0;} the left column width */
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final int leftWidth;
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} pending left column output */
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final StringBuffer leftBuf;
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} pending right column output */
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final StringBuffer rightBuf;
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} left column writer */
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final IndentingWriter leftColumn;
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} right column writer */
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final IndentingWriter rightColumn;
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Turns the given two strings (with widths) and spacer into a formatted
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * two-column string.
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param s1 {@code non-null;} first string
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param width1 {@code > 0;} width of the first column
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param spacer {@code non-null;} spacer string
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param s2 {@code non-null;} second string
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param width2 {@code > 0;} width of the second column
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-formatted string
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String toString(String s1, int width1, String spacer,
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                                  String s2, int width2) {
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int len1 = s1.length();
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int len2 = s2.length();
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        StringWriter sw = new StringWriter((len1 + len2) * 3);
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        TwoColumnOutput twoOut =
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            new TwoColumnOutput(sw, width1, width2, spacer);
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        try {
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            twoOut.getLeft().write(s1);
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            twoOut.getRight().write(s2);
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } catch (IOException ex) {
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new RuntimeException("shouldn't happen", ex);
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        twoOut.flush();
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return sw.toString();
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs an instance.
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param out {@code non-null;} writer to send final output to
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param leftWidth {@code > 0;} width of the left column, in characters
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param rightWidth {@code > 0;} width of the right column, in characters
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param spacer {@code non-null;} spacer string to sit between the two columns
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public TwoColumnOutput(Writer out, int leftWidth, int rightWidth,
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                           String spacer) {
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (out == null) {
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("out == null");
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (leftWidth < 1) {
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new IllegalArgumentException("leftWidth < 1");
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (rightWidth < 1) {
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new IllegalArgumentException("rightWidth < 1");
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (spacer == null) {
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("spacer == null");
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        StringWriter leftWriter = new StringWriter(1000);
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        StringWriter rightWriter = new StringWriter(1000);
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.out = out;
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.leftWidth = leftWidth;
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.leftBuf = leftWriter.getBuffer();
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.rightBuf = rightWriter.getBuffer();
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.leftColumn = new IndentingWriter(leftWriter, leftWidth);
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.rightColumn =
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            new IndentingWriter(rightWriter, rightWidth, spacer);
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs an instance.
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param out {@code non-null;} stream to send final output to
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param leftWidth {@code >= 1;} width of the left column, in characters
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param rightWidth {@code >= 1;} width of the right column, in characters
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param spacer {@code non-null;} spacer string to sit between the two columns
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public TwoColumnOutput(OutputStream out, int leftWidth, int rightWidth,
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                           String spacer) {
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this(new OutputStreamWriter(out), leftWidth, rightWidth, spacer);
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the writer to use to write to the left column.
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the left column writer
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public Writer getLeft() {
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return leftColumn;
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the writer to use to write to the right column.
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the right column writer
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public Writer getRight() {
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return rightColumn;
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Flushes the output. If there are more lines of pending output in one
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * column, then the other column will get filled with blank lines.
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void flush() {
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        try {
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            appendNewlineIfNecessary(leftBuf, leftColumn);
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            appendNewlineIfNecessary(rightBuf, rightColumn);
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            outputFullLines();
158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            flushLeft();
159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            flushRight();
160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } catch (IOException ex) {
161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new RuntimeException(ex);
162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Outputs to the final destination as many full line pairs as
167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * there are in the pending output, removing those lines from
168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * their respective buffers. This method terminates when at
169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * least one of the two column buffers is empty.
170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private void outputFullLines() throws IOException {
172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (;;) {
173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            int leftLen = leftBuf.indexOf("\n");
174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (leftLen < 0) {
175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                return;
176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            int rightLen = rightBuf.indexOf("\n");
179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (rightLen < 0) {
180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                return;
181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (leftLen != 0) {
184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.write(leftBuf.substring(0, leftLen));
185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (rightLen != 0) {
188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                writeSpaces(out, leftWidth - leftLen);
189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.write(rightBuf.substring(0, rightLen));
190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.write('\n');
193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            leftBuf.delete(0, leftLen + 1);
195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            rightBuf.delete(0, rightLen + 1);
196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Flushes the left column buffer, printing it and clearing the buffer.
201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * If the buffer is already empty, this does nothing.
202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private void flushLeft() throws IOException {
204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        appendNewlineIfNecessary(leftBuf, leftColumn);
205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        while (leftBuf.length() != 0) {
207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            rightColumn.write('\n');
208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            outputFullLines();
209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Flushes the right column buffer, printing it and clearing the buffer.
214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * If the buffer is already empty, this does nothing.
215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private void flushRight() throws IOException {
217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        appendNewlineIfNecessary(rightBuf, rightColumn);
218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        while (rightBuf.length() != 0) {
220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            leftColumn.write('\n');
221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            outputFullLines();
222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Appends a newline to the given buffer via the given writer, but
227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * only if it isn't empty and doesn't already end with one.
228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param buf {@code non-null;} the buffer in question
230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param out {@code non-null;} the writer to use
231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static void appendNewlineIfNecessary(StringBuffer buf,
233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                                                 Writer out)
234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throws IOException {
235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int len = buf.length();
236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if ((len != 0) && (buf.charAt(len - 1) != '\n')) {
238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.write('\n');
239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Writes the given number of spaces to the given writer.
244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param out {@code non-null;} where to write
246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param amt {@code >= 0;} the number of spaces to write
247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static void writeSpaces(Writer out, int amt) throws IOException {
249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        while (amt > 0) {
250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.write(' ');
251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            amt--;
252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
255