summaryrefslogtreecommitdiffstats
path: root/src/org/jetbrains/java/decompiler/main/TextBuffer.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/jetbrains/java/decompiler/main/TextBuffer.java')
-rw-r--r--src/org/jetbrains/java/decompiler/main/TextBuffer.java163
1 files changed, 163 insertions, 0 deletions
diff --git a/src/org/jetbrains/java/decompiler/main/TextBuffer.java b/src/org/jetbrains/java/decompiler/main/TextBuffer.java
new file mode 100644
index 0000000..6d279bf
--- /dev/null
+++ b/src/org/jetbrains/java/decompiler/main/TextBuffer.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * 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 org.jetbrains.java.decompiler.main;
+
+import java.util.*;
+
+/**
+ * Allows to connect text with resulting lines
+ *
+ * @author egor
+ */
+public class TextBuffer {
+ private final String myLineSeparator = DecompilerContext.getNewLineSeparator();
+ private final StringBuilder myStringBuilder;
+ private Map<Integer, Integer> myLineToOffsetMapping = null;
+
+ public TextBuffer() {
+ myStringBuilder = new StringBuilder();
+ }
+
+ public TextBuffer(int size) {
+ myStringBuilder = new StringBuilder(size);
+ }
+
+ public void setCurrentLine(int line) {
+ if (line >= 0) {
+ checkMapCreated();
+ myLineToOffsetMapping.put(line, myStringBuilder.length()+1);
+ }
+ }
+
+ public TextBuffer append(String str) {
+ myStringBuilder.append(str);
+ return this;
+ }
+
+ public TextBuffer append(char ch) {
+ myStringBuilder.append(ch);
+ return this;
+ }
+
+ public TextBuffer appendLineSeparator() {
+ myStringBuilder.append(myLineSeparator);
+ return this;
+ }
+
+ public void addBanner(String banner) {
+ myStringBuilder.insert(0, banner);
+ if (myLineToOffsetMapping != null) {
+ for (Integer line : myLineToOffsetMapping.keySet()) {
+ myLineToOffsetMapping.put(line, myLineToOffsetMapping.get(line) + banner.length());
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ String original = myStringBuilder.toString();
+ if (myLineToOffsetMapping == null || myLineToOffsetMapping.isEmpty()) {
+ return original;
+ }
+ else {
+ StringBuilder res = new StringBuilder();
+ String[] srcLines = original.split(myLineSeparator);
+ int currentLineStartOffset = 0;
+ int currentLine = 0;
+ int previousMarkLine = 0;
+ int dumpedLines = 0;
+ ArrayList<Integer> linesWithMarks = new ArrayList<Integer>(myLineToOffsetMapping.keySet());
+ Collections.sort(linesWithMarks);
+ for (Integer markLine : linesWithMarks) {
+ Integer markOffset = myLineToOffsetMapping.get(markLine);
+ while (currentLine < srcLines.length) {
+ String line = srcLines[currentLine];
+ int lineEnd = currentLineStartOffset + line.length() + myLineSeparator.length();
+ if (markOffset >= currentLineStartOffset && markOffset <= lineEnd) {
+ int requiredLinesNumber = markLine - dumpedLines;
+ dumpedLines = markLine;
+ appendLines(res, srcLines, previousMarkLine, currentLine, requiredLinesNumber);
+ previousMarkLine = currentLine;
+ break;
+ }
+ currentLineStartOffset = lineEnd;
+ currentLine++;
+ }
+ }
+ if (previousMarkLine < srcLines.length) {
+ appendLines(res, srcLines, previousMarkLine, srcLines.length, srcLines.length - previousMarkLine);
+ }
+
+ return res.toString();
+ }
+ }
+
+ private void appendLines(StringBuilder res, String[] srcLines, int from, int to, int requiredLineNumber) {
+ if (to - from > requiredLineNumber) {
+ int separatorsRequired = to - from - requiredLineNumber - 1;
+ for (int i = from; i < to; i++) {
+ res.append(srcLines[i]);
+ if (separatorsRequired-- > 0) {
+ res.append(myLineSeparator);
+ }
+ }
+ res.append(myLineSeparator);
+ }
+ else if (to - from <= requiredLineNumber) {
+ for (int i = from; i < to; i++) {
+ res.append(srcLines[i]).append(myLineSeparator);
+ }
+ for (int i = 0; i < requiredLineNumber - to + from; i++) {
+ res.append(myLineSeparator);
+ }
+ }
+ }
+
+ public int length() {
+ return myStringBuilder.length();
+ }
+
+ public String substring(int start) {
+ return myStringBuilder.substring(start);
+ }
+
+ public void setLength(int position) {
+ myStringBuilder.setLength(position);
+ }
+
+ public void append(TextBuffer buffer) {
+ if (buffer.myLineToOffsetMapping != null && !buffer.myLineToOffsetMapping.isEmpty()) {
+ checkMapCreated();
+ for (Map.Entry<Integer, Integer> entry : buffer.myLineToOffsetMapping.entrySet()) {
+ myLineToOffsetMapping.put(entry.getKey(), entry.getValue() + myStringBuilder.length());
+ }
+ }
+ myStringBuilder.append(buffer.myStringBuilder);
+ }
+
+ private void checkMapCreated() {
+ if (myLineToOffsetMapping == null) {
+ myLineToOffsetMapping = new HashMap<Integer, Integer>();
+ }
+ }
+
+ public void insert(int offset, String s) {
+ if (myLineToOffsetMapping != null) {
+ throw new IllegalStateException("insert not yet supported with Line mapping");
+ }
+ myStringBuilder.insert(offset, s);
+ }
+}