1 19 20 package edu.umd.cs.findbugs.ba; 21 22 import java.io.ByteArrayInputStream ; 23 import java.io.ByteArrayOutputStream ; 24 import java.io.IOException ; 25 import java.io.InputStream ; 26 27 35 public class SourceFile { 36 private static int intValueOf(byte b) { 37 return b & 0xff; 38 } 39 40 44 private static class LineNumberMapBuilder { 45 private SourceFile sourceFile; 46 private int offset; 47 private int lastSeen; 48 49 public LineNumberMapBuilder(SourceFile sourceFile) { 50 this.sourceFile = sourceFile; 51 this.offset = 0; 52 this.lastSeen = -1; 53 } 54 55 public void addData(byte[] data, int len) { 56 for (int i = 0; i < len; ++i) { 57 int ch = intValueOf(data[i]); 58 add(ch); 60 } 61 } 62 63 public void eof() { 64 add(-1); 65 } 66 67 private void add(int ch) { 68 switch (ch) { 69 case '\n': 70 sourceFile.addLineOffset(offset + 1); 71 break; 72 case '\r': 73 break; 76 default: 77 if (lastSeen == '\r') { 78 sourceFile.addLineOffset(offset); 83 } 84 } 85 86 lastSeen = ch; 87 ++offset; 88 } 89 } 90 91 private static final int DEFAULT_SIZE = 100; 92 93 private SourceFileDataSource dataSource; 94 private byte[] data; 95 private int[] lineNumberMap; 96 private int numLines; 97 98 104 public SourceFile(SourceFileDataSource dataSource) { 105 this.dataSource = dataSource; 106 this.lineNumberMap = new int[DEFAULT_SIZE]; 107 this.numLines = 0; 108 } 109 110 113 public String getFullFileName() { 114 return dataSource.getFullFileName(); 115 } 116 117 123 public InputStream getInputStream() throws IOException { 124 loadFileData(); 125 return new ByteArrayInputStream (data); 126 } 127 128 135 public InputStream getInputStreamFromOffset(int offset) throws IOException { 136 loadFileData(); 137 return new ByteArrayInputStream (data, offset, data.length - offset); 138 } 139 140 147 public void addLineOffset(int offset) { 148 if (numLines >= lineNumberMap.length) { 149 int capacity = lineNumberMap.length * 2; 151 int[] newLineNumberMap = new int[capacity]; 152 System.arraycopy(lineNumberMap, 0, newLineNumberMap, 0, lineNumberMap.length); 153 lineNumberMap = newLineNumberMap; 154 } 155 156 lineNumberMap[numLines++] = offset; 157 } 158 159 168 public int getLineOffset(int line) { 169 if (line < 0 || line >= numLines) 170 return -1; 171 return lineNumberMap[line]; 172 } 173 174 private synchronized void loadFileData() throws IOException { 175 if (data != null) 176 return; 177 178 InputStream in = null; 179 180 try { 181 in = dataSource.open(); 182 ByteArrayOutputStream out = new ByteArrayOutputStream (); 183 184 addLineOffset(0); LineNumberMapBuilder mapBuilder = new LineNumberMapBuilder(this); 186 187 byte[] buf = new byte[1024]; 189 int n; 190 while ((n = in.read(buf)) >= 0) { 191 mapBuilder.addData(buf, n); 192 out.write(buf, 0, n); 193 } 194 mapBuilder.eof(); 195 196 setData(out.toByteArray()); 197 } finally { 198 if (in != null) 199 in.close(); 200 } 201 202 } 203 204 209 private void setData(byte[] data) { 210 this.data = data; 211 } 212 } 213 214 | Popular Tags |