summaryrefslogtreecommitdiff
path: root/sources/ch/epfl/lamp/util/SourceFile.java
diff options
context:
space:
mode:
Diffstat (limited to 'sources/ch/epfl/lamp/util/SourceFile.java')
-rw-r--r--sources/ch/epfl/lamp/util/SourceFile.java217
1 files changed, 217 insertions, 0 deletions
diff --git a/sources/ch/epfl/lamp/util/SourceFile.java b/sources/ch/epfl/lamp/util/SourceFile.java
new file mode 100644
index 0000000000..44dbf82506
--- /dev/null
+++ b/sources/ch/epfl/lamp/util/SourceFile.java
@@ -0,0 +1,217 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package ch.epfl.lamp.util;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+
+/**
+ * This class represents a single source file.
+ */
+public class SourceFile {
+
+ //########################################################################
+ // Public Constants
+
+ /** Constants used for source parsing */
+ public static final byte LF = 0x0A;
+ public static final byte FF = 0x0C;
+ public static final byte CR = 0x0D;
+ public static final byte SU = 0x1A;
+
+ //########################################################################
+ // Public Functions
+
+ /** Returns the source file with the given id. */
+ public static SourceFile fromId(int id) {
+ if (id <= 0 || files.size() < id) return UNKNOWN;
+ return (SourceFile)files.get(id - 1);
+ }
+
+ /** Releases all source file. */
+ public static void releaseAll() {
+ files.clear();
+ }
+
+ //########################################################################
+ // Private Variables
+
+ /** The unknown source file */
+ private static final SourceFile UNKNOWN = new SourceFile();
+
+ /** The list containing all source files */
+ private static final ArrayList files = new ArrayList();
+
+ //########################################################################
+ // Private Fields
+
+ /** The name of this source file */
+ private final String name;
+
+ /** The content of source this file */
+ private final byte[] bytes;
+
+ /** The id of this source file */
+ private final int id;
+
+ /** The encoding of this source file or null if unspecified */
+ private String encoding;
+
+ /** The position of the last line returned by getLine */
+ private int lineNumber = 0;
+ private int lineStart = 0;
+ private int lineLength = 0;
+ private int nextIndex = 0;
+
+ //########################################################################
+ // Private Constructors
+
+ /** Initializes a new instance. */
+ private SourceFile() {
+ this.name = "<<unknown source file>>";
+ this.bytes = normalize(new byte[0]);
+ this.id = 0;
+ }
+
+ //########################################################################
+ // Public Constructors
+
+ /** Initializes a new instance. */
+ public SourceFile(String name) throws IOException {
+ this(new File(name));
+ }
+
+ /** Initializes a new instance. */
+ public SourceFile(File name) throws IOException {
+ this(name.toString(), read(name));
+ }
+
+ /** Initializes a new instance. */
+ public SourceFile(String name, InputStream input) throws IOException {
+ this(name, read(name, input));
+ }
+
+ /** Initializes a new instance. */
+ public SourceFile(String name, byte[] bytes) {
+ this.name = name;
+ this.bytes = normalize(bytes);
+ this.id = files.size() + 1;
+ files.add(this);
+ }
+
+ //########################################################################
+ // Public Methods
+
+ /** Returns the name of this source file. */
+ public String name() {
+ return name;
+ }
+
+ /** Returns the content of this source file. */
+ public byte[] bytes() {
+ return bytes;
+ }
+
+ /** Returns the id of this source file. */
+ public int id() {
+ return id;
+ }
+
+ /** Sets the encoding of the file. */
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
+ /** Returns the content of the given line. */
+ public String getLine(int line) {
+ int index = lineNumber <= line ? nextIndex : (lineNumber = 0);
+ for (; index < bytes.length && lineNumber < line; lineNumber++) {
+ lineStart = index;
+ for (; index < bytes.length; index++) {
+ if (bytes[index] == CR) break;
+ if (bytes[index] == LF) break;
+ if (bytes[index] == FF) break;
+ }
+ lineLength = index - lineStart;
+ if (index < bytes.length) index++;
+ if (index < bytes.length)
+ if (bytes[index - 1] == CR && bytes[index] == LF) index++;
+ }
+ nextIndex = index;
+ try {
+ return encoding != null ?
+ new String(bytes, lineStart, lineLength, encoding) :
+ new String(bytes, lineStart, lineLength);
+ } catch (UnsupportedEncodingException exception) {
+ throw new Error(exception); // !!! use ApplicationError
+ }
+ }
+
+ /**
+ * Returns an instance of Position representing the given line and
+ * column of this source file.
+ */
+ public Position getPosition(int line, int column) {
+ return new Position(this, line, column);
+ }
+
+ /**
+ * Returns the integer encoding the position of the given line and
+ * column of this source file.
+ */
+ public int getEncodedPosition(int line, int column) {
+ return Position.encode(this, line, column);
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ //########################################################################
+ // Private Methods
+
+ /** Reads the file and returns its content as a byte array. */
+ private static byte[] read(File file) throws IOException {
+ InputStream input = new FileInputStream(file);
+ try {
+ return read(file.toString(), input);
+ } finally {
+ input.close();
+ }
+ }
+
+ /** Reads the InputStream and returns its content as a byte array. */
+ private static byte[] read(String name, InputStream input)
+ throws IOException
+ {
+ try {
+ byte[] bytes = new byte[input.available() + 1];
+ if (input.read(bytes) != bytes.length - 1) throw new IOException();
+ bytes[bytes.length - 1] = SU;
+ return bytes;
+ } catch (IOException exception) {
+ throw new IOException("cannot read '" + name + "'");
+ }
+ }
+
+ /** Ensures that the last byte of the array is SU. */
+ private static byte[] normalize(byte[] input) {
+ if (input.length > 0 && input[input.length - 1] == SU) return input;
+ byte[] bytes = new byte[input.length + 1];
+ System.arraycopy(input, 0, bytes, 0, input.length);
+ bytes[input.length] = SU;
+ return bytes;
+ }
+
+ //########################################################################
+}