/* * Copyright (C) 2012 Sony Mobile Communications AB * * This file is part of ApkAnalyser. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package andreflect.gui.linebuilder; import java.io.IOException; import java.io.Writer; import org.jf.dexlib.Code.Instruction; import org.jf.util.IndentingWriter; import analyser.gui.LineBuilder; import analyser.gui.LineBuilderFormatter; import andreflect.Util; import andreflect.gui.linebuilder.DalvikByteCodeLineBuilder.DalvikBytecodeOffset; public class DalvikIndentingWriterImpl extends IndentingWriter implements DalvikIndentingWriter { private final LineBuilder lb; private int indentLevel = 0; private boolean beginningOfLine; private final char[] buffer = new char[16]; private int linenumber = -1; private int codeaddress = -1; private int color = 0; private Instruction instruction = null; protected DalvikIndentingWriterImpl(LineBuilder lb) { super(null); this.lb = lb; } @Override public void setColor(int c) { color = c; } @Override public void resetColor() { color = COLOR_TEXT; } @Override public void setLine(int line) { linenumber = line; } @Override public void setInsAddress(int address) { codeaddress = address; } @Override public void setInstruction(Instruction instruction) { this.instruction = instruction; } @Override public String getProtoString(String typeDescriptor) { return Util.getProtoString(typeDescriptor); } @Override public void write(int chr) throws IOException { //synchronized(lock) { if (chr == '\n') { lb.newLine(); beginningOfLine = true; } else { if (beginningOfLine && color != COLOR_LABEL) { if (codeaddress != -1 && color != LineBuilderFormatter.COLOR_KEYWORD) { lb.append(String.format("%1$5X", codeaddress), COLOR_CODEADDRESS); lb.setReferenceToCurrent(new DalvikBytecodeOffset(instruction, linenumber, codeaddress)); } else { lb.append(" "); } if (codeaddress != -1 && linenumber != -1 && color != LineBuilderFormatter.COLOR_KEYWORD) { lb.append(String.format("%1$5d", linenumber), COLOR_SOURCELINE); } else { lb.append(" "); } codeaddress = -1; for (int i = 0; i < indentLevel; i++) { lb.append(' '); } } if (color == COLOR_LABEL) { lb.append(Character.toUpperCase((char) chr), color); } else { lb.append((char) chr, color); } beginningOfLine = false; } //} } @Override public void write(String s) throws IOException { //synchronized (lock) { boolean isKeyword = s.startsWith(".") && s.length() > 1; if (isKeyword) { setColor(LineBuilderFormatter.COLOR_KEYWORD); } for (int i = 0; i < s.length(); i++) { write(s.charAt(i)); } if (isKeyword) { resetColor(); } //} } @Override public void write(char[] chars) throws IOException { //synchronized(lock) { for (char chr : chars) { write(chr); } //} } @Override public void write(char[] chars, int start, int len) throws IOException { //synchronized(lock) { len = start + len; while (start < len) { write(chars[start++]); } //} } @Override public void write(String str, int start, int len) throws IOException { //synchronized(lock) { len = start + len; while (start < len) { write(str.charAt(start++)); } //} } @Override public Writer append(CharSequence charSequence) throws IOException { write(charSequence.toString()); return this; } @Override public Writer append(CharSequence charSequence, int start, int len) throws IOException { write(charSequence.subSequence(start, len).toString()); return this; } @Override public Writer append(char c) throws IOException { write(c); return this; } @Override public void flush() throws IOException { //synchronized(lock) { // writer.flush(); //} } @Override public void close() throws IOException { //synchronized(lock) { // writer.close(); //} } @Override public void indent(int indentAmount) { //synchronized(lock) { indentLevel += indentAmount; if (indentLevel < 0) { indentLevel = 0; } //} } @Override public void deindent(int indentAmount) { //synchronized(lock) { indentLevel -= indentAmount; if (indentLevel < 0) { indentLevel = 0; } //} } public void printLongAsHex(long value) throws IOException { int bufferIndex = 0; do { int digit = (int) (value & 15); if (digit < 10) { buffer[bufferIndex++] = (char) (digit + '0'); } else { buffer[bufferIndex++] = (char) ((digit - 10) + 'a'); } value >>>= 4; } while (value != 0); while (bufferIndex > 0) { write(buffer[--bufferIndex]); } } public void printIntAsDec(int value) throws IOException { int bufferIndex = 0; boolean negative = value < 0; do { int digit = value % 10; buffer[bufferIndex++] = (char) (digit + '0'); value = value / 10; } while (value != 0); if (negative) { write('-'); } while (bufferIndex > 0) { write(buffer[--bufferIndex]); } } }