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.FilterWriter; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.IOException; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.Writer; 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Writer that wraps another writer and passes width-limited and 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * optionally-prefixed output to its subordinate. When lines are 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * wrapped they are automatically indented based on the start of the 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * line. 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class IndentingWriter extends FilterWriter { 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code null-ok;} optional prefix for every line */ 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final String prefix; 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code > 0;} the maximum output width */ 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final int width; 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code > 0;} the maximum indent */ 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final int maxIndent; 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= 0;} current output column (zero-based) */ 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int column; 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** whether indent spaces are currently being collected */ 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private boolean collectingIndent; 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= 0;} current indent amount */ 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int indent; 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} writer to send final output to 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param width {@code >= 0;} the maximum output width (not including 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code prefix}), or {@code 0} for no maximum 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param prefix {@code non-null;} the prefix for each line 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public IndentingWriter(Writer out, int width, String prefix) { 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super(out); 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (out == null) { 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("out == null"); 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (width < 0) { 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("width < 0"); 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (prefix == null) { 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("prefix == null"); 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.width = (width != 0) ? width : Integer.MAX_VALUE; 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.maxIndent = width >> 1; 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.prefix = (prefix.length() == 0) ? null : prefix; 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul bol(); 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs a no-prefix instance. 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} writer to send final output to 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param width {@code >= 0;} the maximum output width (not including 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code prefix}), or {@code 0} for no maximum 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public IndentingWriter(Writer out, int width) { 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this(out, width, ""); 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void write(int c) throws IOException { 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul synchronized (lock) { 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (collectingIndent) { 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (c == ' ') { 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul indent++; 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (indent >= maxIndent) { 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul indent = maxIndent; 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul collectingIndent = false; 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul collectingIndent = false; 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((column == width) && (c != '\n')) { 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.write('\n'); 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul column = 0; 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Note: No else, so this should fall through to the next 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * if statement. 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (column == 0) { 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (prefix != null) { 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.write(prefix); 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!collectingIndent) { 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < indent; i++) { 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.write(' '); 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul column = indent; 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.write(c); 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (c == '\n') { 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul bol(); 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul column++; 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void write(char[] cbuf, int off, int len) throws IOException { 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul synchronized (lock) { 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul while (len > 0) { 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul write(cbuf[off]); 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul off++; 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul len--; 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void write(String str, int off, int len) throws IOException { 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul synchronized (lock) { 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul while (len > 0) { 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul write(str.charAt(off)); 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul off++; 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul len--; 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Indicates that output is at the beginning of a line. 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void bol() { 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul column = 0; 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul collectingIndent = (maxIndent != 0); 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul indent = 0; 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 170