001    // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
002    // for details. All rights reserved. Use of this source code is governed by a
003    // BSD-style license that can be found in the LICENSE file.
004    
005    package com.google.dart.compiler.util;
006    
007    import java.util.Arrays;
008    
009    public class TextOutputImpl implements TextOutput {
010        private final boolean compact;
011        private int identLevel = 0;
012        private final static int indentGranularity = 2;
013        private char[][] indents = new char[][] {new char[0]};
014        private boolean justNewlined;
015        private final StringBuilder out;
016        private int position = 0;
017        private int line = 0;
018        private int column = 0;
019    
020        private OutListener outListener;
021    
022        public TextOutputImpl() {
023            this(false);
024        }
025    
026        public boolean isCompact() {
027            return compact;
028        }
029    
030        public TextOutputImpl(boolean compact) {
031            this.compact = compact;
032            out = new StringBuilder();
033        }
034    
035        @Override
036        public String toString() {
037            return out.toString();
038        }
039    
040        @Override
041        public int getPosition() {
042            return position;
043        }
044    
045        @Override
046        public int getLine() {
047            return line;
048        }
049    
050        @Override
051        public int getColumn() {
052            return column;
053        }
054    
055        @Override
056        public void indentIn() {
057            ++identLevel;
058            if (identLevel >= indents.length) {
059                // Cache a new level of indentation string.
060                char[] newIndentLevel = new char[identLevel * indentGranularity];
061                Arrays.fill(newIndentLevel, ' ');
062                char[][] newIndents = new char[indents.length + 1][];
063                System.arraycopy(indents, 0, newIndents, 0, indents.length);
064                newIndents[identLevel] = newIndentLevel;
065                indents = newIndents;
066            }
067        }
068    
069        @Override
070        public void indentOut() {
071            --identLevel;
072        }
073    
074        @Override
075        public void newline() {
076            out.append('\n');
077            position++;
078            line++;
079            column = 0;
080            justNewlined = true;
081            if (outListener != null) {
082                outListener.newLined();
083            }
084        }
085    
086        @Override
087        public void print(double value) {
088            maybeIndent();
089            int oldLength = out.length();
090            out.append(value);
091            movePosition(out.length() - oldLength);
092        }
093    
094        @Override
095        public void print(int value) {
096            maybeIndent();
097            int oldLength = out.length();
098            out.append(value);
099            movePosition(out.length() - oldLength);
100        }
101    
102        @Override
103        public void print(char c) {
104            maybeIndent();
105            out.append(c);
106            movePosition(1);
107        }
108    
109        private void movePosition(int l) {
110            position += l;
111            column += l;
112        }
113    
114        @Override
115        public void print(char[] s) {
116            maybeIndent();
117            printAndCount(s);
118        }
119    
120        @Override
121        public void print(CharSequence s) {
122            maybeIndent();
123            printAndCount(s);
124        }
125    
126        @Override
127        public void printOpt(char c) {
128            if (!compact) {
129                print(c);
130            }
131        }
132    
133        @Override
134        public void printOpt(char[] s) {
135            if (!compact) {
136                maybeIndent();
137                printAndCount(s);
138            }
139        }
140    
141        @Override
142        public void printOpt(String s) {
143            if (!compact) {
144                maybeIndent();
145                printAndCount(s);
146            }
147        }
148    
149        @Override
150        public void maybeIndent() {
151            if (justNewlined && !compact) {
152                printAndCount(indents[identLevel]);
153                justNewlined = false;
154                if (outListener != null) {
155                    outListener.indentedAfterNewLine();
156                }
157            }
158        }
159    
160        private void printAndCount(CharSequence charSequence) {
161            position += charSequence.length();
162            column += charSequence.length();
163            out.append(charSequence);
164        }
165    
166        private void printAndCount(char[] chars) {
167            position += chars.length;
168            column += chars.length;
169            out.append(chars);
170        }
171    
172        @Override
173        public boolean isJustNewlined() {
174            return justNewlined && !compact;
175        }
176    
177        @Override
178        public void setOutListener(OutListener outListener) {
179            this.outListener = outListener;
180        }
181    }