From 8b6c8a3c0709bc13c74f11ffb660c1c764564915 Mon Sep 17 00:00:00 2001 From: mihaylov Date: Tue, 11 Apr 2006 15:36:05 +0000 Subject: Rewrote the files in scala/tools/util/ in Scala --- .../scala/tools/nsc/backend/jvm/GenJVM.scala | 4 +- .../scala/tools/nsc/models/SemanticTokens.scala | 3 +- .../tools/nsc/reporters/ConsoleReporter.scala | 2 +- .../scala/tools/nsc/reporters/ReporterTimer.scala | 9 +- .../scala/tools/nsc/symtab/SymbolLoaders.scala | 34 ++- .../nsc/symtab/classfile/ClassfileParser.scala | 80 +++---- src/compiler/scala/tools/nsc/util/ClassPath.scala | 32 +-- src/compiler/scala/tools/nsc/util/Position.scala | 2 +- src/compiler/scala/tools/nsc/util/SourceFile.scala | 9 +- src/compiler/scala/tools/util/AbstractFile.java | 128 ------------ src/compiler/scala/tools/util/AbstractFile.scala | 123 +++++++++++ .../scala/tools/util/AbstractFileReader.java | 111 ---------- .../scala/tools/util/AbstractFileReader.scala | 83 ++++++++ src/compiler/scala/tools/util/AbstractTimer.java | 49 ----- src/compiler/scala/tools/util/AbstractTimer.scala | 48 +++++ src/compiler/scala/tools/util/CharArrayFile.java | 53 ----- src/compiler/scala/tools/util/CharArrayFile.scala | 29 +++ src/compiler/scala/tools/util/EmptyIterator.java | 48 ----- src/compiler/scala/tools/util/PlainFile.java | 165 --------------- src/compiler/scala/tools/util/PlainFile.scala | 105 ++++++++++ src/compiler/scala/tools/util/SourceReader.java | 155 -------------- src/compiler/scala/tools/util/SourceReader.scala | 137 ++++++++++++ src/compiler/scala/tools/util/Timer.java | 27 --- src/compiler/scala/tools/util/UTF8Codec.java | 66 ------ src/compiler/scala/tools/util/UTF8Codec.scala | 78 +++++++ src/compiler/scala/tools/util/VirtualFile.java | 97 --------- src/compiler/scala/tools/util/VirtualFile.scala | 67 ++++++ src/compiler/scala/tools/util/ZipArchive.java | 229 --------------------- src/compiler/scala/tools/util/ZipArchive.scala | 190 +++++++++++++++++ 29 files changed, 945 insertions(+), 1218 deletions(-) delete mode 100644 src/compiler/scala/tools/util/AbstractFile.java create mode 100644 src/compiler/scala/tools/util/AbstractFile.scala delete mode 100644 src/compiler/scala/tools/util/AbstractFileReader.java create mode 100644 src/compiler/scala/tools/util/AbstractFileReader.scala delete mode 100644 src/compiler/scala/tools/util/AbstractTimer.java create mode 100644 src/compiler/scala/tools/util/AbstractTimer.scala delete mode 100644 src/compiler/scala/tools/util/CharArrayFile.java create mode 100644 src/compiler/scala/tools/util/CharArrayFile.scala delete mode 100644 src/compiler/scala/tools/util/EmptyIterator.java delete mode 100644 src/compiler/scala/tools/util/PlainFile.java create mode 100644 src/compiler/scala/tools/util/PlainFile.scala delete mode 100644 src/compiler/scala/tools/util/SourceReader.java create mode 100644 src/compiler/scala/tools/util/SourceReader.scala delete mode 100644 src/compiler/scala/tools/util/Timer.java delete mode 100644 src/compiler/scala/tools/util/UTF8Codec.java create mode 100644 src/compiler/scala/tools/util/UTF8Codec.scala delete mode 100644 src/compiler/scala/tools/util/VirtualFile.java create mode 100644 src/compiler/scala/tools/util/VirtualFile.scala delete mode 100644 src/compiler/scala/tools/util/ZipArchive.java create mode 100644 src/compiler/scala/tools/util/ZipArchive.scala diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 9409c73e68..1a4611d1fd 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -99,7 +99,9 @@ abstract class GenJVM extends SubComponent { val outfile = getFile(jclass, ".class"); jclass.writeTo(outfile); val file = scala.tools.util.AbstractFile.getFile(outfile); - informProgress("wrote " + outfile + " " + (if (file != null) "" + file.getFile() + " " + file.getFile().exists() else "no file")); + informProgress("wrote " + outfile + " " + + (if (file != null) "" + file.file + " " + file.file.exists() + else "no file")); } var serialVUID: Option[Long] = None; diff --git a/src/compiler/scala/tools/nsc/models/SemanticTokens.scala b/src/compiler/scala/tools/nsc/models/SemanticTokens.scala index 511bd1e9bb..a4424ab2af 100644 --- a/src/compiler/scala/tools/nsc/models/SemanticTokens.scala +++ b/src/compiler/scala/tools/nsc/models/SemanticTokens.scala @@ -508,7 +508,8 @@ class SemanticTokens(val compiler: Global) { val buf = unit.source.content; if (tree.pos >= buf.length) { if (false) { - System.err.println("" + tree + "@" + tree.pos + " not in " + unit.source.file.getName() + "[" + buf.length + "]"); + System.err.println("" + tree + "@" + tree.pos + " not in " + + unit.source.file.name + "[" + buf.length + "]"); Thread.dumpStack(); throw new Error(); } diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala index f759b66bec..a99a321854 100644 --- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala @@ -75,7 +75,7 @@ class ConsoleReporter(reader : BufferedReader, writer : PrintWriter) extends Abs if (pos.line != Position.NOLINE) buf.insert(0, ":" + pos.line); val file = pos.source.file; - buf.insert(0, if (shortname) file.getName() else file.getPath()); + buf.insert(0, if (shortname) file.name else file.path); printMessage(buf.toString()); printSourceLine(pos); } else printMessage(msg); diff --git a/src/compiler/scala/tools/nsc/reporters/ReporterTimer.scala b/src/compiler/scala/tools/nsc/reporters/ReporterTimer.scala index 5c0cfd4092..505ede5953 100644 --- a/src/compiler/scala/tools/nsc/reporters/ReporterTimer.scala +++ b/src/compiler/scala/tools/nsc/reporters/ReporterTimer.scala @@ -7,21 +7,16 @@ // $Id$ package scala.tools.nsc.reporters; + import scala.tools.util.AbstractTimer; /** * This class implements a timer that uses a Reporter to issue * timings. */ -class ReporterTimer(_reporter : Reporter) extends AbstractTimer { - //######################################################################## - // Private Fields - private val reporter = _reporter; - //######################################################################## - // Public Methods +class ReporterTimer(reporter : Reporter) extends AbstractTimer { def issue(msg : String, duration : Long) = reporter.info(null, "[" + msg + " in " + duration + "ms]", false); - //######################################################################## } diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index f8d9d37cfb..bce1e2e202 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -130,28 +130,24 @@ abstract class SymbolLoaders { val classes = new HashMap[String, global.classPath0.Context]; val packages = new HashMap[String, global.classPath0.Context]; for (val dir <- directory.entries) if (dir.location != null) { - val it = dir.location.list(); - while (it.hasNext()) { - val file = it.next().asInstanceOf[AbstractFile]; - if (file.isDirectory() && directory.validPackage(file.getName()) && !packages.isDefinedAt(file.getName())) - packages(file.getName()) = directory.find(file.getName(), true); - else if (!file.isDirectory() && file.getName().endsWith(".class")) { - val name = file.getName().substring(0, file.getName().length() - (".class").length()); - if (isValid(name) && !classes.isDefinedAt(name)) { - val clazz = directory.find(name, false); - if (clazz != null) classes(name) = clazz; - } - } + for (val file <- dir.location) { + if (file.isDirectory && directory.validPackage(file.name) && !packages.isDefinedAt(file.name)) + packages(file.name) = directory.find(file.name, true); + else if (!file.isDirectory && file.name.endsWith(".class")) { + val name = file.name.substring(0, file.name.length() - (".class").length()); + if (isValid(name) && !classes.isDefinedAt(name)) { + val clazz = directory.find(name, false); + if (clazz != null) classes(name) = clazz; + } + } } } for (val dir <- directory.entries) if (dir.source != null) { - val jt = dir.source.location.list(); - while (jt.hasNext()) { - val file = jt.next().asInstanceOf[AbstractFile]; - if (file.isDirectory() && directory.validPackage(file.getName()) && !packages.isDefinedAt(file.getName())) - packages(file.getName()) = directory.find(file.getName(), true); - else if (dir.source.compile && !file.isDirectory() && file.getName().endsWith(".scala")) { - val name = file.getName().substring(0, file.getName().length() - (".scala").length()); + for (val file <- dir.source.location) { + if (file.isDirectory && directory.validPackage(file.name) && !packages.isDefinedAt(file.name)) + packages(file.name) = directory.find(file.name, true); + else if (dir.source.compile && !file.isDirectory && file.name.endsWith(".scala")) { + val name = file.name.substring(0, file.name.length() - (".scala").length()); if (isValid(name) && !classes.isDefinedAt(name)) { val source = directory.find(name, false); if (source != null) classes(name) = source; diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index d306d9a8ea..0d72ae43b9 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -84,13 +84,13 @@ abstract class ClassfileParser { private def statics: Symbol = staticModule.moduleClass; private def parseHeader: unit = { - val magic = in.nextInt(); + val magic = in.nextInt; if (magic != JAVA_MAGIC) throw new IOException("class file '" + in.file + "' " + "has wrong magic number 0x" + Integer.toHexString(magic) + ", should be 0x" + Integer.toHexString(JAVA_MAGIC)); - val minorVersion = in.nextChar(); - val majorVersion = in.nextChar(); + val minorVersion = in.nextChar; + val majorVersion = in.nextChar; if ((majorVersion < JAVA_MAJOR_VERSION) || ((majorVersion == JAVA_MAJOR_VERSION) && (minorVersion < JAVA_MINOR_VERSION))) @@ -103,7 +103,7 @@ abstract class ClassfileParser { } class ConstantPool { - private val len = in.nextChar(); + private val len = in.nextChar; private val starts = new Array[int](len); private val values = new Array[Object](len); private val internalized = new Array[Name](len); @@ -111,9 +111,9 @@ abstract class ClassfileParser { while (i < starts.length) { starts(i) = in.bp; i = i + 1; - in.nextByte() match { + in.nextByte match { case CONSTANT_UTF8 | CONSTANT_UNICODE => - in.skip(in.nextChar()); + in.skip(in.nextChar); case CONSTANT_CLASS | CONSTANT_STRING => in.skip(2); case CONSTANT_FIELDREF | CONSTANT_METHODREF | CONSTANT_INTFMETHODREF | CONSTANT_NAMEANDTYPE | CONSTANT_INTEGER | CONSTANT_FLOAT => @@ -240,17 +240,17 @@ abstract class ClassfileParser { } def parseClass(): unit = { - val jflags = in.nextChar(); + val jflags = in.nextChar; var sflags = transFlags(jflags); if ((sflags & DEFERRED) != 0) sflags = sflags & ~DEFERRED | ABSTRACT; - val c = pool.getClassSymbol(in.nextChar()); + val c = pool.getClassSymbol(in.nextChar); if (c != clazz) throw new IOException("class file '" + in.file + "' contains wrong " + clazz); - val superType = pool.getSuperClass(in.nextChar()).tpe; - val ifaceCount = in.nextChar(); + val superType = pool.getSuperClass(in.nextChar).tpe; + val ifaceCount = in.nextChar; val parents = (superType :: (for (val i <- List.range(0, ifaceCount)) - yield pool.getSuperClass(in.nextChar()).tpe)); + yield pool.getSuperClass(in.nextChar).tpe)); instanceDefs = new Scope(); staticDefs = new Scope(); val classInfo = ClassInfoType(parents, instanceDefs, clazz); @@ -271,9 +271,9 @@ abstract class ClassfileParser { staticModule.setFlag(JAVA); staticModule.moduleClass.setFlag(JAVA); in.bp = curbp; - val fieldCount = in.nextChar(); + val fieldCount = in.nextChar; for (val i <- Iterator.range(0, fieldCount)) parseField(); - val methodCount = in.nextChar(); + val methodCount = in.nextChar; for (val i <- Iterator.range(0, methodCount)) parseMethod(); if (instanceDefs.lookup(nme.CONSTRUCTOR) == NoSymbol && (sflags & INTERFACE) == 0) { //System.out.println("adding constructor to " + clazz);//DEBUG @@ -285,14 +285,14 @@ abstract class ClassfileParser { } def parseField(): unit = { - val jflags = in.nextChar(); + val jflags = in.nextChar; var sflags = transFlags(jflags); if ((sflags & FINAL) == 0) sflags = sflags | MUTABLE; if ((sflags & PRIVATE) != 0) { in.skip(4); skipAttributes(); } else { - val name = pool.getName(in.nextChar()); - val info = pool.getType(in.nextChar()); + val name = pool.getName(in.nextChar); + val info = pool.getType(in.nextChar); val sym = getOwner(jflags) .newValue(Position.NOPOS, name).setFlag(sflags).setInfo(info); setPrivateWithin(sym, jflags); @@ -302,14 +302,14 @@ abstract class ClassfileParser { } def parseMethod(): unit = { - val jflags = in.nextChar(); + val jflags = in.nextChar; var sflags = transFlags(jflags); if ((jflags & JAVA_ACC_BRIDGE) != 0) sflags = sflags | PRIVATE; if ((sflags & PRIVATE) != 0) { in.skip(4); skipAttributes(); } else { - val name = pool.getName(in.nextChar()); - var info = pool.getType(in.nextChar()); + val name = pool.getName(in.nextChar); + var info = pool.getType(in.nextChar); if (name == nme.CONSTRUCTOR) info match { case MethodType(formals, restpe) => @@ -457,12 +457,12 @@ abstract class ClassfileParser { c convertTo pt } def parseAttribute(): unit = { - val attrName = pool.getName(in.nextChar()); - val attrLen = in.nextInt(); + val attrName = pool.getName(in.nextChar); + val attrLen = in.nextInt; attrName match { case nme.SignatureATTR => if (global.settings.Xgenerics.value) { - val sig = pool.getExternalName(in.nextChar()); + val sig = pool.getExternalName(in.nextChar); val newType = polySigToType(sym, sig); sym.setInfo(newType) if (settings.debug.value) @@ -480,7 +480,7 @@ abstract class ClassfileParser { sym.setFlag(DEPRECATED); in.skip(attrLen) case nme.ConstantValueATTR => - val c = pool.getConstant(in.nextChar()); + val c = pool.getConstant(in.nextChar); val c1 = convertTo(c, symtype); if (c1 != null) sym.setInfo(ConstantType(c1)); else System.out.println("failure to convert "+c+" to "+symtype);//debug @@ -490,12 +490,12 @@ abstract class ClassfileParser { unpickler.unpickle(in.buf, in.bp, clazz, staticModule); this.isScala = true; case nme.JacoMetaATTR => - val meta = pool.getName(in.nextChar()).toString().trim(); + val meta = pool.getName(in.nextChar).toString().trim(); metaParser.parse(meta, sym, symtype); this.hasMeta = true; case nme.SourceFileATTR => assert(attrLen == 2); - val source = pool.getName(in.nextChar()); + val source = pool.getName(in.nextChar); if (sourcePath != null) { val sourceFile0 = sourcePath.lookupPath(source.toString(), false); if (sourceFile0 != null && clazz.sourceFile == null) { @@ -511,8 +511,8 @@ abstract class ClassfileParser { } } def parseTaggedConstant(): Any = { - val tag = in.nextByte(); - val index = in.nextChar(); + val tag = in.nextByte; + val index = in.nextChar; tag match { case STRING_TAG => pool.getName(index).toString(); case BOOL_TAG => pool.getConstant(index).intValue != 0; @@ -536,15 +536,15 @@ abstract class ClassfileParser { } def parseAnnotations(len: Int): Unit = { val buf = new StringBuffer(); - val nAttr = in.nextChar(); + val nAttr = in.nextChar; for (val n <- Iterator.range(0,nAttr)) { - val attrNameIndex = in.nextChar(); + val attrNameIndex = in.nextChar; val attrType = pool.getType(attrNameIndex); buf.append("@").append(attrType.toString()).append("("); - val nargs = in.nextChar() + val nargs = in.nextChar for (val i <- Iterator.range(0, nargs)) { if (i > 0) buf.append(", "); - val name = pool.getName(in.nextChar()); + val name = pool.getName(in.nextChar); buf.append(name).append(" = "); val value = parseTaggedConstant(); buf.append(value); @@ -554,11 +554,11 @@ abstract class ClassfileParser { global.informProgress("parsed attribute " + buf); } def parseInnerClasses(): unit = { - for (val i <- Iterator.range(0, in.nextChar())) { - val innerIndex = in.nextChar(); - val outerIndex = in.nextChar(); - val nameIndex = in.nextChar(); - val jflags = in.nextChar(); + for (val i <- Iterator.range(0, in.nextChar)) { + val innerIndex = in.nextChar; + val outerIndex = in.nextChar; + val nameIndex = in.nextChar; + val jflags = in.nextChar; if (innerIndex != 0 && outerIndex != 0 && nameIndex != 0 && (jflags & (JAVA_ACC_PUBLIC | JAVA_ACC_PROTECTED)) != 0 && pool.getClassSymbol(outerIndex) == sym) { @@ -569,19 +569,19 @@ abstract class ClassfileParser { } } } - val attrCount = in.nextChar(); + val attrCount = in.nextChar; for (val i <- Iterator.range(0, attrCount)) parseAttribute() } def skipAttributes(): unit = { - val attrCount = in.nextChar(); + val attrCount = in.nextChar; for (val i <- Iterator.range(0, attrCount)) { - in.skip(2); in.skip(in.nextInt()) + in.skip(2); in.skip(in.nextInt) } } def skipMembers(): unit = { - val memberCount = in.nextChar(); + val memberCount = in.nextChar; for (val i <- Iterator.range(0, memberCount)) { in.skip(6); skipAttributes() } diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala index 91ce023b49..88e5050cbb 100644 --- a/src/compiler/scala/tools/nsc/util/ClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala @@ -88,15 +88,15 @@ class ClassPath(onlyPresentation: Boolean) { def isPackage: Boolean = if (entries.isEmpty) false - else if (entries.head.location != null) entries.head.location.isDirectory() - else entries.head.source.location.isDirectory() + else if (entries.head.location != null) entries.head.location.isDirectory + else entries.head.source.location.isDirectory def name = if (entries.isEmpty) "" else { val head = entries.head - val name = if (head.location != null) head.location.getName() - else head.source.location.getName() + val name = if (head.location != null) head.location.name + else head.source.location.name if (isPackage) name else name.substring(0, name.length() - (".class").length()) } @@ -116,20 +116,20 @@ class ClassPath(onlyPresentation: Boolean) { def head = entries.head def clazz = head.location def source = if (head.source == null) null else head.source.location - def isPredef = source.getName().equals("Predef.scala") || - source.getPath().startsWith("scala/runtime"); + def isPredef = source.name.equals("Predef.scala") || + source.path.startsWith("scala/runtime"); if (entries.isEmpty || entries.isEmpty || source == null) false else if (!onlyPresentation && !head.source.compile) false - else if (source.isDirectory()) false + else if (source.isDirectory) false else if (clazz == null) true else if (onlyPresentation && !isPredef) true - else if (source.lastModified() > clazz.lastModified()) true + else if (source.lastModified > clazz.lastModified) true else false } - def sourceFile = if (entries.head.source != null && !entries.head.source.location.isDirectory()) + def sourceFile = if (entries.head.source != null && !entries.head.source.location.isDirectory) entries.head.source.location else null def classFile = if (!isSourceFile) entries.head.location else null @@ -205,13 +205,13 @@ class ClassPath(onlyPresentation: Boolean) { val strtok = new StringTokenizer(path, File.pathSeparator) while (strtok.hasMoreTokens()) { val file = AbstractFile.getDirectory(strtok.nextToken()) - val files = (if (file != null) file.list() else null) - if (files != null) while(files.hasNext()) { - val file0 = files.next().asInstanceOf[AbstractFile] - val name = file0.getName() - if (name.endsWith(".jar") || name.endsWith(".zip")) { - val archive = AbstractFile.getDirectory(new File(file.getFile(), name)) - if (archive != null) entries += (new Library(archive)) + if (file != null) { + for (val file0 <- file) { + val name = file0.name + if (name.endsWith(".jar") || name.endsWith(".zip")) { + val archive = AbstractFile.getDirectory(new File(file.file, name)) + if (archive != null) entries += (new Library(archive)) + } } } } diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala index e900aa2553..fc3e358607 100644 --- a/src/compiler/scala/tools/nsc/util/Position.scala +++ b/src/compiler/scala/tools/nsc/util/Position.scala @@ -86,7 +86,7 @@ class Position( val source : SourceFile, val offset: Int) { override def toString(): String = { val sb = new StringBuffer(); if (source != null) { - sb.append(source.file.getPath()); + sb.append(source.file.path); if (hasOffset) { sb.append(line); sb.append(':'); diff --git a/src/compiler/scala/tools/nsc/util/SourceFile.scala b/src/compiler/scala/tools/nsc/util/SourceFile.scala index 916f625241..0c1bd9758c 100644 --- a/src/compiler/scala/tools/nsc/util/SourceFile.scala +++ b/src/compiler/scala/tools/nsc/util/SourceFile.scala @@ -29,7 +29,7 @@ class SourceFile(_file : AbstractFile, _content : Array[Char]) { import SourceFile._; def this(_file: AbstractFile) = { - this(_file, (new String(_file.read())).toCharArray) + this(_file, (new String(_file.read)).toCharArray) } val file = _file; @@ -53,7 +53,7 @@ class SourceFile(_file : AbstractFile, _content : Array[Char]) { // constants // NOTE: all indexes are based on zero!!!! - override def toString(): String = file.getName() /* + ":" + content.length */ ; + override def toString(): String = file.name /* + ":" + content.length */ ; def dbg(offset : Int) = (new Position(this, offset)).dbgString; @@ -69,7 +69,8 @@ class SourceFile(_file : AbstractFile, _content : Array[Char]) { if (!isIndex) assert(toFind != Position.NOPOS); if ( isIndex) assert(toFind > Position.NOLINE - Position.FIRSTLINE); - if (!isIndex && (toFind >= content.length)) throw new Error(toFind + " not valid offset in " + file.getName() + ":" + content.length); + if (!isIndex && (toFind >= content.length)) + throw new Error(toFind + " not valid offset in " + file.name + ":" + content.length); def get(isIndex : Boolean) = if (isIndex) index else offset; @@ -108,7 +109,7 @@ class SourceFile(_file : AbstractFile, _content : Array[Char]) { } return true; } - def path = getFile().getPath(); + def path = getFile().path; def skipWhitespace(offset : Int): Int = if (Character.isWhitespace(content(offset))) skipWhitespace(offset + 1) else offset; diff --git a/src/compiler/scala/tools/util/AbstractFile.java b/src/compiler/scala/tools/util/AbstractFile.java deleted file mode 100644 index 24df046799..0000000000 --- a/src/compiler/scala/tools/util/AbstractFile.java +++ /dev/null @@ -1,128 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - -package scala.tools.util; - -import java.io.File; -import java.io.IOException; -import java.util.Iterator; -import java.util.jar.JarFile; -import java.util.zip.ZipFile; - -/** - * This class implements an abstract representation of files and - * directories. These files and directories may have some real counter - * part within the file system but that is not necessarily true. For - * example, there exist abstract files that represent files within a - * zip archive or files that exist only in memory. - * - * Every abstract file has a path (i.e. a full name) and a name - * (i.e. a short name) and may be backed by some real File. There are - * two different kinds of abstract files: regular files and - * directories. Regular files may be read and have a last modification - * time. Directories may list their content and look for subfiles with - * a specified name or path and of a specified kind. - */ -public abstract class AbstractFile { - - //######################################################################## - // Public Factories - - /** Returns "getFile(new File(path))". */ - public static AbstractFile getFile(String path) { - return getFile(new File(path)); - } - - /** - * If the specified File exists and is a regular file, returns an - * abstract regular file backed by it. Otherwise, returns null. - */ - public static AbstractFile getFile(File file) { - return file.isFile() && file.exists() ? new PlainFile(file) : null; - } - - - /** Returns "getDirectory(new File(path))". */ - public static AbstractFile getDirectory(String path) { - return getDirectory(new File(path)); - } - - /** - * if the specified File exists and is either a directory or a - * readable zip or jar archive, returns an abstract directory - * backed by it. Otherwise, returns null. - */ - public static AbstractFile getDirectory(File file) { - if (file.isDirectory() && file.exists()) return new PlainFile(file); - if (file.isFile() && file.exists()) { - String path = file.getPath(); - if (path.endsWith(".jar") || path.endsWith(".zip")) - return ZipArchive.fromFile(file); - } - return null; - } - - //######################################################################## - // Public Methods - - /** Returns the name of this abstract file. */ - public abstract String getName(); - - /** Returns the path of this abstract file. */ - public abstract String getPath(); - - /** Returns the underlying File if any and null otherwise. */ - public abstract File getFile(); - - /** Is this abstract file a directory? */ - public abstract boolean isDirectory(); - - /** Returns the time that this abstract file was last modified. */ - public abstract long lastModified(); - - /** Reads the content of this abstract file into a byte array. */ - public abstract byte[] read() throws IOException; - - /** Returns all abstract subfiles of this abstract directory. */ - public abstract Iterator/**/ list(); - - /** - * Returns the abstract file in this abstract directory with the - * specified name. If there is no such file, returns null. The - * argument "directory" tells whether to look for a directory or - * or a regular file. - */ - public abstract AbstractFile lookupName(String name, boolean directory); - - /** - * Returns the abstract file in this abstract directory with the - * specified path relative to it, If there is no such file, - * returns null. The argument "directory" tells whether to look - * for a directory or or a regular file. - */ - public final AbstractFile lookupPath(String path, boolean directory) { - final int length = path.length(); - final char separator = File.separatorChar; - assert 0 < length && path.lastIndexOf(separator) < length - 1: path; - AbstractFile file = this; - for (int start = 0, index; true; start = index + 1) { - index = path.indexOf(separator, start); - assert index < 0 || start < index: path+" - "+start+" - "+index; - String name = path.substring(start, index < 0 ? length : index); - file = file.lookupName(name, index < 0 ? directory : true); - if (file == null || index < 0) return file; - } - } - - /** Returns the path of this abstract file. */ - public final String toString() { - return getPath(); - } - - //######################################################################## -} diff --git a/src/compiler/scala/tools/util/AbstractFile.scala b/src/compiler/scala/tools/util/AbstractFile.scala new file mode 100644 index 0000000000..b6b2abe935 --- /dev/null +++ b/src/compiler/scala/tools/util/AbstractFile.scala @@ -0,0 +1,123 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002-2006, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +\* */ + +// $Id$ + + +package scala.tools.util; + + +import java.io.File; + +object AbstractFile { + + /** Returns "getFile(new File(path))". */ + def getFile(path: String): AbstractFile = getFile(new File(path)); + + /** + * If the specified File exists and is a regular file, returns an + * abstract regular file backed by it. Otherwise, returns null. + */ + def getFile(file: File): AbstractFile = + if (file.isFile() && file.exists()) new PlainFile(file) else null; + + + /** Returns "getDirectory(new File(path))". */ + def getDirectory(path: String): AbstractFile = getDirectory(new File(path)); + + /** + * if the specified File exists and is either a directory or a + * readable zip or jar archive, returns an abstract directory + * backed by it. Otherwise, returns null. + */ + def getDirectory(file: File): AbstractFile = { + if (file.isDirectory() && file.exists()) return new PlainFile(file); + if (file.isFile() && file.exists()) { + val path = file.getPath(); + if (path.endsWith(".jar") || path.endsWith(".zip")) + return ZipArchive.fromFile(file); + } + null + } + +} + +/** + * This class implements an abstract representation of files and + * directories. These files and directories may have some real counter + * part within the file system but that is not necessarily true. For + * example, there exist abstract files that represent files within a + * zip archive or files that exist only in memory. + * + * Every abstract file has a path (i.e. a full name) and a name + * (i.e. a short name) and may be backed by some real File. There are + * two different kinds of abstract files: regular files and + * directories. Regular files may be read and have a last modification + * time. Directories may list their content and look for subfiles with + * a specified name or path and of a specified kind. + */ +abstract class AbstractFile extends Object with Iterable[AbstractFile] { + + //######################################################################## + // Public Methods + + /** Returns the name of this abstract file. */ + def name: String; + + /** Returns the path of this abstract file. */ + def path: String; + + /** Returns the underlying File if any and null otherwise. */ + def file: File; + + /** Is this abstract file a directory? */ + def isDirectory: Boolean; + + /** Returns the time that this abstract file was last modified. */ + def lastModified: Long; + + /** Reads the content of this abstract file into a byte array. */ + def read: Array[Byte]; + + /** Returns all abstract subfiles of this abstract directory. */ + def elements: Iterator[AbstractFile]; + + /** + * Returns the abstract file in this abstract directory with the + * specified name. If there is no such file, returns null. The + * argument "directory" tells whether to look for a directory or + * or a regular file. + */ + def lookupName(name: String, directory: Boolean): AbstractFile; + + /** + * Returns the abstract file in this abstract directory with the + * specified path relative to it, If there is no such file, + * returns null. The argument "directory" tells whether to look + * for a directory or a regular file. + */ + def lookupPath(path: String, directory: Boolean): AbstractFile = { + val length = path.length(); + val separator = File.separatorChar; + assert(0 < length && path.lastIndexOf(separator) < length - 1, path); + var file = this; + var start = 0; + while (true) { + val index = path.indexOf(separator, start); + assert(index < 0 || start < index, path+" - "+start+" - "+index); + val name = path.substring(start, if (index < 0) length else index); + file = file.lookupName(name, if (index < 0) directory else true); + if (file == null || index < 0) return file; + start = index + 1; + } + file + } + + /** Returns the path of this abstract file. */ + override def toString() = path; + + //######################################################################## +} diff --git a/src/compiler/scala/tools/util/AbstractFileReader.java b/src/compiler/scala/tools/util/AbstractFileReader.java deleted file mode 100644 index bafb170217..0000000000 --- a/src/compiler/scala/tools/util/AbstractFileReader.java +++ /dev/null @@ -1,111 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -** ** -** $Id$ -\* */ - -package scala.tools.util; - -import java.io.IOException; - -public class AbstractFileReader { - - /** the buffer containing the file - */ - public byte[] buf; - - /** the current input pointer - */ - public int bp; - - /** the abstract file - */ - public final AbstractFile file; - - /** constructor - */ - public AbstractFileReader(AbstractFile f) throws IOException { - buf = f.read(); - bp = 0; - file = f; - } - - /** return byte at offset 'pos' - */ - public byte byteAt(int pos) { - return buf[pos]; - } - - /** read a byte - */ - public byte nextByte() { - return buf[bp++]; - } - - /** read some bytes - */ - public byte[] nextBytes(int len) { - byte[] res = new byte[len]; - System.arraycopy(buf, bp, res, 0, len); - bp += len; - return res; - } - - /** read a character - */ - public char nextChar() { - return - (char)(((buf[bp++] & 0xff) << 8) + - (buf[bp++] & 0xff)); - } - - /** read an integer - */ - public int nextInt() { - return ((buf[bp++] & 0xff) << 24) + - ((buf[bp++] & 0xff) << 16) + - ((buf[bp++] & 0xff) << 8) + - (buf[bp++] & 0xff); - } - - /** extract a character at position bp from buf - */ - public char getChar(int mybp) { - return (char)(((buf[mybp] & 0xff) << 8) + (buf[mybp+1] & 0xff)); - } - - /** extract an integer at position bp from buf - */ - public int getInt(int mybp) { - return ((buf[mybp ] & 0xff) << 24) + - ((buf[mybp+1] & 0xff) << 16) + - ((buf[mybp+2] & 0xff) << 8) + - (buf[mybp+3] & 0xff); - } - - /** extract a long integer at position bp from buf - */ - public long getLong(int mybp) { - return ((long)(getInt(mybp)) << 32) + (getInt(mybp + 4) & 0xffffffffL); - } - - /** extract a float at position bp from buf - */ - public strictfp float getFloat(int mybp) { - return Float.intBitsToFloat(getInt(mybp)); - } - - /** extract a double at position bp from buf - */ - public strictfp double getDouble(int mybp) { - return Double.longBitsToDouble(getLong(mybp)); - } - - /** skip next 'n' bytes - */ - public void skip(int n) { - bp += n; - } -} diff --git a/src/compiler/scala/tools/util/AbstractFileReader.scala b/src/compiler/scala/tools/util/AbstractFileReader.scala new file mode 100644 index 0000000000..099d4d9f47 --- /dev/null +++ b/src/compiler/scala/tools/util/AbstractFileReader.scala @@ -0,0 +1,83 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002-2006, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +\* */ + +// $Id$ + + +package scala.tools.util; + + +class AbstractFileReader(val file: AbstractFile) { + + /** the buffer containing the file + */ + val buf: Array[Byte] = file.read; + + /** the current input pointer + */ + var bp: Int = 0; + + /** return byte at offset 'pos' + */ + def byteAt(pos: Int): Byte = return buf(pos); + + /** read a byte + */ + def nextByte: Byte = { + val b = buf(bp); + bp = bp + 1; + b + } + + /** read some bytes + */ + def nextBytes(len: Int): Array[Byte] = { + bp = bp + len; + buf.subArray(bp - len, bp); + } + + /** read a character + */ + def nextChar: Char = { + (((nextByte & 0xff) << 8) + (nextByte & 0xff)).toChar; + } + + /** read an integer + */ + def nextInt: Int = + ((nextByte & 0xff) << 24) + ((nextByte & 0xff) << 16) + + ((nextByte & 0xff) << 8) + (nextByte & 0xff); + + + /** extract a character at position bp from buf + */ + def getChar(mybp: Int): Char = + (((buf(mybp) & 0xff) << 8) + (buf(mybp+1) & 0xff)).toChar; + + /** extract an integer at position bp from buf + */ + def getInt(mybp: Int): Int = + ((buf(mybp ) & 0xff) << 24) + ((buf(mybp+1) & 0xff) << 16) + + ((buf(mybp+2) & 0xff) << 8) + (buf(mybp+3) & 0xff); + + /** extract a long integer at position bp from buf + */ + def getLong(mybp: Int): Long = + (getInt(mybp).toLong << 32) + (getInt(mybp + 4) & 0xffffffffL); + + /** extract a float at position bp from buf + */ + def getFloat(mybp: Int): Float = Float.intBitsToFloat(getInt(mybp)); + + /** extract a double at position bp from buf + */ + def getDouble(mybp: Int): Double = Double.longBitsToDouble(getLong(mybp)); + + /** skip next 'n' bytes + */ + def skip(n: Int): Unit = bp = bp + n; + +} diff --git a/src/compiler/scala/tools/util/AbstractTimer.java b/src/compiler/scala/tools/util/AbstractTimer.java deleted file mode 100644 index 6314023fe3..0000000000 --- a/src/compiler/scala/tools/util/AbstractTimer.java +++ /dev/null @@ -1,49 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - -package scala.tools.util; - -import java.util.ArrayList; - -/** - * This abstract class implements the collection of timings. How the - * collected timings are issued has to be implemented in subclasses. - */ -public abstract class AbstractTimer implements Timer { - - //######################################################################## - // Private Fields - - /** A stack for maintaining start times */ - private final ArrayList starts = new ArrayList(); - - //######################################################################## - // Public Methods - - /** Issues a timing information (duration in milliseconds). */ - public abstract void issue(String message, long duration); - - /** Starts a new timer. */ - public void start() { - starts.add(new Long(System.currentTimeMillis())); - } - - /** Ends the current timer. */ - public void stop(String message) { - long stop = System.currentTimeMillis(); - long start = ((Long)starts.remove(starts.size() - 1)).longValue(); - issue(message, stop - start); - } - - /** Drops the current timer. */ - public void drop() { - starts.remove(starts.size() - 1); - } - - //######################################################################## -} diff --git a/src/compiler/scala/tools/util/AbstractTimer.scala b/src/compiler/scala/tools/util/AbstractTimer.scala new file mode 100644 index 0000000000..f306fb1113 --- /dev/null +++ b/src/compiler/scala/tools/util/AbstractTimer.scala @@ -0,0 +1,48 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002-2006, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +\* */ + +// $Id$ + +package scala.tools.util; + +import scala.collection.mutable.Stack; + +/** + * This abstract class implements the collection of timings. How the + * collected timings are issued has to be implemented in subclasses. + */ +abstract class AbstractTimer { + + //######################################################################## + // Private Fields + + /** A stack for maintaining start times */ + private val starts = new Stack[Long](); + + //######################################################################## + // Public Methods + + /** Issues a timing information (duration in milliseconds). */ + def issue(message: String, duration: Long): Unit; + + /** Starts a new timer. */ + def start() = { + starts += System.currentTimeMillis(); + } + + /** Ends the current timer. */ + def stop(message: String): Unit = { + val stop = System.currentTimeMillis(); + issue(message, stop - starts.pop); + } + + /** Drops the current timer. */ + def drop(): Unit = { + starts.pop; + } + + //######################################################################## +} diff --git a/src/compiler/scala/tools/util/CharArrayFile.java b/src/compiler/scala/tools/util/CharArrayFile.java deleted file mode 100644 index 55c8f4a19d..0000000000 --- a/src/compiler/scala/tools/util/CharArrayFile.java +++ /dev/null @@ -1,53 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - -package scala.tools.util; - -/** - * This class implements an abstract regular file backed by a - * character array. - */ -public class CharArrayFile extends VirtualFile { - - //######################################################################## - // Private Fields - - /** The character array */ - private final char[] chars; - - //######################################################################## - // Public Constructors - - /** - * Initializes this instance with the specified name, an identical - * path and the specified character array. - */ - public CharArrayFile(String name, char[] chars) { - this(name, name, chars); - } - - /** - * Initializes this instance with the specified name, path and - * character array. - */ - public CharArrayFile(String name, String path, char[] chars) { - super(name, path); - this.chars = chars; - } - - //######################################################################## - // Public Methods - - /** Reads the content of this abstract file into a byte array. */ - public byte[] read() { - assert false: "!!! not yet implemented"; - return new String(chars).getBytes(); // !!! - } - - //######################################################################## -} diff --git a/src/compiler/scala/tools/util/CharArrayFile.scala b/src/compiler/scala/tools/util/CharArrayFile.scala new file mode 100644 index 0000000000..c8a58c2129 --- /dev/null +++ b/src/compiler/scala/tools/util/CharArrayFile.scala @@ -0,0 +1,29 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002-2006, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +\* */ + +// $Id$ + + +package scala.tools.util; + + +/** + * This class implements an abstract regular file backed by a + * character array. + */ +class CharArrayFile(name: String, path: String, chars: Array[Char]) + extends VirtualFile(name, path) +{ + + def this(name: String, chars: Array[Char]) = this(name, name, chars); + + /** Reads the content of this abstract file into a byte array. */ + override def read: Array[Byte] = { + Predef.error("!!! not yet implemented"); + new String(chars).getBytes(); // !!! + } + +} diff --git a/src/compiler/scala/tools/util/EmptyIterator.java b/src/compiler/scala/tools/util/EmptyIterator.java deleted file mode 100644 index f677d97e3d..0000000000 --- a/src/compiler/scala/tools/util/EmptyIterator.java +++ /dev/null @@ -1,48 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - -package scala.tools.util; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** This class implements an empty iterator. */ -public class EmptyIterator implements Iterator { - - //######################################################################## - // Public Constants - - /** The unique instance of this class. */ - public static final EmptyIterator object = new EmptyIterator(); - - //######################################################################## - // Private Constructors - - /** Initializes this instance. */ - private EmptyIterator() {} - - //######################################################################## - // Public Methods - - /** Returns false. */ - public boolean hasNext() { - return false; - } - - /** Throws NoSuchElementException. */ - public Object next() { - throw new NoSuchElementException(); - } - - /** Throws IllegalStateException. */ - public void remove() { - throw new IllegalStateException(); - } - - //######################################################################## -} diff --git a/src/compiler/scala/tools/util/PlainFile.java b/src/compiler/scala/tools/util/PlainFile.java deleted file mode 100644 index 56feb847fb..0000000000 --- a/src/compiler/scala/tools/util/PlainFile.java +++ /dev/null @@ -1,165 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - -package scala.tools.util; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** This class implements an abstract file backed by a File. */ -public class PlainFile extends AbstractFile { - - //######################################################################## - // Public Factories - - /** Returns "fromFile(new File(path))". */ - public static AbstractFile fromPath(String path) { - return fromFile(new File(path)); - } - - /** - * If the specified File exists, returns an abstract file backed - * by it. Otherwise, returns null. - */ - public static AbstractFile fromFile(File file) { - return file.exists() ? new PlainFile(file) : null; - } - - //######################################################################## - // Private Fields - - /** The underlying File */ - private final File file; - - //######################################################################## - // Protected Constructors - - /** Initializes this instance with the specified File. */ - protected PlainFile(File file) { - this.file = file; - assert file != null; - if (!file.exists()) throw new Error("non-existent file: " + file); - } - - //######################################################################## - // Public Methods - - /** Returns the name of this abstract file. */ - public String getName() { - return file.getName(); - } - - /** Returns the path of this abstract file. */ - public String getPath() { - return file.getPath(); - } - - /** Returns the underlying File if any and null otherwise. */ - public File getFile() { - return file; - } - - - public int hashCode() { - try { - return file.getCanonicalPath().hashCode(); - } catch (IOException ex) { - return 0; - } - } - - public boolean equals(Object that) { - try { - return that instanceof PlainFile && - file.getCanonicalPath().equals(((PlainFile) that).file.getCanonicalPath()); - } catch (IOException ex) { - return that instanceof PlainFile && - file.getAbsolutePath().equals(((PlainFile) that).file.getAbsolutePath()); - } - } - - /** Is this abstract file a directory? */ - public boolean isDirectory() { - return file.isDirectory(); - } - - /** Returns the time that this abstract file was last modified. */ - public long lastModified() { - return file.lastModified(); - } - - /** Reads the content of this abstract file into a byte array. */ - public byte[] read() throws IOException { - assert !isDirectory(): "cannot read directory '" + this + "'"; - FileInputStream in = new FileInputStream(file); - int rest = (int)file.length(); - byte[] buf = new byte[rest]; - do { - int res = in.read(buf, buf.length - rest, rest); - if (res == -1) - throw new IOException("read error"); - rest -= res; - } while (rest > 0); - in.close(); - return buf; - } - - /** Returns all abstract subfiles of this abstract directory. */ - public Iterator/**/ list() { - assert isDirectory(): "not a directory '" + this + "'"; - final String[] names = file.list(); - if (names == null || names.length == 0) return EmptyIterator.object; - class ListIterator implements Iterator { - private int i; - File lookAhead = null; - public boolean hasNext() { - if (lookAhead != null) return true; - else if (i == names.length) return false; - else { - lookAhead = new File(file, names[i++]); - if (lookAhead.exists()) return true; - else { - lookAhead = null; - return hasNext(); - } - } - } - public Object next() { - if (hasNext()) { - File f = lookAhead; - lookAhead = null; - return new PlainFile(f); - } else throw new NoSuchElementException(); - } - public void remove() { - throw new UnsupportedOperationException(); - } - } - return new ListIterator(); - } - - /** - * Returns the abstract file in this abstract directory with the - * specified name. If there is no such file, returns null. The - * argument "directory" tells whether to look for a directory or - * or a regular file. - */ - public AbstractFile lookupName(String name, boolean directory) { - assert isDirectory(): "not a directory '" + this + "'"; - File child = new File(file, name); - if (!child.exists()) return null; - if (directory != child.isDirectory()) return null; - if (directory == child.isFile() ) return null; - return new PlainFile(child); - } - - //######################################################################## -} diff --git a/src/compiler/scala/tools/util/PlainFile.scala b/src/compiler/scala/tools/util/PlainFile.scala new file mode 100644 index 0000000000..ee597b8868 --- /dev/null +++ b/src/compiler/scala/tools/util/PlainFile.scala @@ -0,0 +1,105 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002-2006, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +\* */ + +// $Id$ + + +package scala.tools.util; + + +import java.io.{File, FileInputStream, IOException}; + +object PlainFile { + + /** Returns "fromFile(new File(path))". */ + def fromPath(path: String): AbstractFile = fromFile(new File(path)); + + /** + * If the specified File exists, returns an abstract file backed + * by it. Otherwise, returns null. + */ + def fromFile(file: File): AbstractFile = + if (file.exists()) new PlainFile(file) else null; + +} + +/** This class implements an abstract file backed by a File. */ +class PlainFile(val file: File) extends AbstractFile { + + assert(file != null); + assert(file.exists(), "non-existent file: " + file); + + //######################################################################## + // Public Methods + + /** Returns the name of this abstract file. */ + def name = file.getName(); + + /** Returns the path of this abstract file. */ + def path = file.getPath(); + + + override def hashCode(): Int = + try { file.getCanonicalPath().hashCode() } + catch { case _: IOException => 0 } + + override def equals(that: Any): Boolean = + try { + that.isInstanceOf[PlainFile] && + file.getCanonicalPath().equals(that.asInstanceOf[PlainFile].file.getCanonicalPath()); + } catch { + case _: IOException => + that.isInstanceOf[PlainFile] && + file.getAbsolutePath().equals(that.asInstanceOf[PlainFile].file.getAbsolutePath()); + } + + /** Is this abstract file a directory? */ + def isDirectory: Boolean = file.isDirectory(); + + /** Returns the time that this abstract file was last modified. */ + def lastModified: Long = file.lastModified(); + + /** Reads the content of this abstract file into a byte array. */ + def read: Array[Byte] = { + assert(!isDirectory, "cannot read directory '" + this + "'"); + val in = new FileInputStream(file); + var rest: Int = file.length().toInt; + val buf: Array[Byte] = new Array[Byte](rest); + while (rest > 0) { + val res = in.read(buf, buf.length - rest, rest); + if (res == -1) + throw new IOException("read error"); + rest = rest - res; + } + in.close(); + return buf; + } + + /** Returns all abstract subfiles of this abstract directory. */ + def elements: Iterator[AbstractFile] = { + assert(isDirectory, "not a directory '" + this + "'"); + val names: Array[String] = file.list(); + if (names == null || names.length == 0) Iterator.empty; + else Iterator.fromArray(names).map(name: String => new File(file, name)) + .filter(.exists()).map(file => new PlainFile(file)) + } + + /** + * Returns the abstract file in this abstract directory with the + * specified name. If there is no such file, returns null. The + * argument "directory" tells whether to look for a directory or + * or a regular file. + */ + def lookupName(name: String, directory: Boolean): AbstractFile = { + //assert(isDirectory, "not a directory '" + this + "'"); + val child = new File(file, name); + if (!child.exists() || (directory != child.isDirectory) || + directory == child.isFile()) null; + else new PlainFile(child); + } + + //######################################################################## +} diff --git a/src/compiler/scala/tools/util/SourceReader.java b/src/compiler/scala/tools/util/SourceReader.java deleted file mode 100644 index ae5ae2a162..0000000000 --- a/src/compiler/scala/tools/util/SourceReader.java +++ /dev/null @@ -1,155 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - -package scala.tools.util; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.channels.FileChannel; -import java.nio.channels.ReadableByteChannel; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CoderResult; - -/** This class implements methods to read and decode source files. */ -public class SourceReader { - - //######################################################################## - // Private Fields - - /** The decoder used to transform bytes into characters */ - private final CharsetDecoder decoder; - - /** The input byte buffer (small enough to fit in cache) */ - private final ByteBuffer bytes; - - /** The output character buffer */ - private CharBuffer chars; - - //######################################################################## - // Public Constructors - - /** Initializes this instance with the specified decoder. */ - public SourceReader(CharsetDecoder decoder) { - this.decoder = decoder; - this.bytes = ByteBuffer.allocate(0x4000); - this.chars = CharBuffer.allocate(0x4000); - } - - //######################################################################## - // Public Methods - - /** Reads the file with the specified name. */ - public char[] read(String filename) throws IOException { - return read(new File(filename)); - } - - /** Reads the specified file. */ - public char[] read(File file) throws IOException { - FileChannel channel = new FileInputStream(file).getChannel(); - try { - return read(channel); - } finally { - channel.close(); - } - } - - /** Reads the specified file. */ - public char[] read(AbstractFile file) throws IOException { - CharsetDecoder decoder = this.decoder.reset(); - ByteBuffer bytes = ByteBuffer.wrap(file.read()); - CharBuffer chars = this.chars; chars.clear(); - return terminate(flush(decoder, decode(decoder, bytes, chars, true))); - } - - /** Reads the specified byte channel. */ - public char[] read(ReadableByteChannel input) throws IOException { - CharsetDecoder decoder = this.decoder.reset(); - ByteBuffer bytes = this.bytes; bytes.clear(); - CharBuffer chars = this.chars; chars.clear(); - for (boolean endOfInput = false; !endOfInput; ) { - endOfInput = input.read(bytes) < 0; - bytes.flip(); - chars = decode(decoder, bytes, chars, endOfInput); - } - return terminate(flush(decoder, chars)); - } - - //######################################################################## - // Private Methods - - /** - * Sets the specified char buffer as the new output buffer and - * reads and returns its content. - */ - private char[] terminate(CharBuffer chars) { - char[] result = new char[chars.length()]; - chars.get(result); - this.chars = chars; - return result; - } - - //######################################################################## - // Private Functions - - /** - * Decodes the content of the specified byte buffer with the - * specified decoder into the specified char buffer, allocating - * bigger ones if necessary, then compacts the byte buffer and - * returns the last allocated char buffer. The "endOfInput" - * argument indicates whether the byte buffer contains the last - * chunk of the input file. - */ - private static CharBuffer decode(CharsetDecoder decoder, ByteBuffer bytes, - CharBuffer chars, boolean endOfInput) throws IOException - { - while (true) { - CoderResult result = decoder.decode(bytes, chars, endOfInput); - if (result.isUnderflow()) break; - if (result.isError()) throw new IOException(result.toString()); - assert result.isOverflow(); - chars = increaseCapacity(chars); - } - bytes.compact(); - return chars; - } - - /** - * Flushes the specified decoder into the specified char buffer, - * allocating bigger ones if necessary and then flips and returns - * the last allocated char buffer. - */ - private static CharBuffer flush(CharsetDecoder decoder, CharBuffer chars) - throws IOException - { - while (true) { - CoderResult result = decoder.flush(chars); - if (result.isUnderflow()) break; - if (result.isError()) throw new IOException(result.toString()); - assert result.isOverflow(); - chars = increaseCapacity(chars); - } - chars.flip(); - return chars; - } - - /** - * Flips the specified buffer and returns a new one with the same - * content but with an increased capacity. - */ - private static CharBuffer increaseCapacity(CharBuffer buffer) { - buffer.flip(); - int capacity = 2 * buffer.capacity(); - return CharBuffer.allocate(capacity).put(buffer); - } - - //######################################################################## - -} diff --git a/src/compiler/scala/tools/util/SourceReader.scala b/src/compiler/scala/tools/util/SourceReader.scala new file mode 100644 index 0000000000..fd22aea471 --- /dev/null +++ b/src/compiler/scala/tools/util/SourceReader.scala @@ -0,0 +1,137 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002-2006, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +\* */ + +// $Id$ + + +package scala.tools.util; + + +import java.io.{File, FileInputStream, IOException}; +import java.nio.{ByteBuffer, CharBuffer}; +import java.nio.channels.{FileChannel, ReadableByteChannel}; +import java.nio.charset.{CharsetDecoder, CoderResult}; + +/** This class implements methods to read and decode source files. */ +class SourceReader(decoder: CharsetDecoder) { + + import SourceReader.{decode, flush} + + //######################################################################## + // Private Fields + + /** The input byte buffer (small enough to fit in cache) */ + private val bytes: ByteBuffer = ByteBuffer.allocate(0x4000); + + /** The output character buffer */ + private var chars: CharBuffer = CharBuffer.allocate(0x4000); + + //######################################################################## + // Public Methods + + /** Reads the file with the specified name. */ + def read(filename: String): Array[Char]= read(new File(filename)); + + /** Reads the specified file. */ + def read(file: File): Array[Char] = { + val channel: FileChannel = new FileInputStream(file).getChannel(); + try { + read(channel); + } finally { + channel.close(); + } + } + + /** Reads the specified file. */ + def read(file: AbstractFile): Array[Char] = { + val decoder: CharsetDecoder = this.decoder.reset(); + val bytes: ByteBuffer = ByteBuffer.wrap(file.read); + val chars: CharBuffer = this.chars; chars.clear(); + terminate(flush(decoder, decode(decoder, bytes, chars, true))); + } + + /** Reads the specified byte channel. */ + def read(input: ReadableByteChannel): Array[Char] = { + val decoder: CharsetDecoder = this.decoder.reset(); + val bytes: ByteBuffer = this.bytes; bytes.clear(); + var chars: CharBuffer = this.chars; chars.clear(); + var endOfInput: Boolean = false + while (!endOfInput ) { + endOfInput = input.read(bytes) < 0; + bytes.flip(); + chars = decode(decoder, bytes, chars, endOfInput); + } + terminate(flush(decoder, chars)); + } + + //######################################################################## + // Private Methods + + /** + * Sets the specified char buffer as the new output buffer and + * reads and returns its content. + */ + private def terminate(chars: CharBuffer): Array[Char] = { + val result = new Array[Char](chars.length()); + chars.get(result); + this.chars = chars; + result; + } + +} + +object SourceReader { + + /** + * Decodes the content of the specified byte buffer with the + * specified decoder into the specified char buffer, allocating + * bigger ones if necessary, then compacts the byte buffer and + * returns the last allocated char buffer. The "endOfInput" + * argument indicates whether the byte buffer contains the last + * chunk of the input file. + */ + def decode(decoder: CharsetDecoder, bytes: ByteBuffer, chars: CharBuffer, + endOfInput: boolean): CharBuffer = + { + val result: CoderResult = decoder.decode(bytes, chars, endOfInput); + if (result.isUnderflow()) { + bytes.compact(); + chars; + } else { + if (result.isError()) throw new IOException(result.toString()); + assert(result.isOverflow()); + decode(decoder, bytes, increaseCapacity(chars), endOfInput); + } + } + + /** + * Flushes the specified decoder into the specified char buffer, + * allocating bigger ones if necessary and then flips and returns + * the last allocated char buffer. + */ + def flush(decoder: CharsetDecoder, chars: CharBuffer): CharBuffer = { + val result: CoderResult = decoder.flush(chars); + if (result.isUnderflow()) { + chars.flip(); + chars; + } else { + if (result.isError()) throw new IOException(result.toString()); + assert(result.isOverflow()); + flush(decoder, increaseCapacity(chars)); + } + } + + /** + * Flips the specified buffer and returns a new one with the same + * content but with an increased capacity. + */ + private def increaseCapacity(buffer: CharBuffer): CharBuffer = { + buffer.flip(); + val capacity = 2 * buffer.capacity(); + CharBuffer.allocate(capacity).put(buffer); + } + +} diff --git a/src/compiler/scala/tools/util/Timer.java b/src/compiler/scala/tools/util/Timer.java deleted file mode 100644 index df60d580ae..0000000000 --- a/src/compiler/scala/tools/util/Timer.java +++ /dev/null @@ -1,27 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - -package scala.tools.util; - -/** This interface provides methods to collect timings. */ -public interface Timer { - - //######################################################################## - // Public Methods - - /** Starts a new timer. */ - public void start(); - - /** Stops the current timer. */ - public void stop(String message); - - /** Drops the current timer. */ - public void drop(); - - //######################################################################## -} diff --git a/src/compiler/scala/tools/util/UTF8Codec.java b/src/compiler/scala/tools/util/UTF8Codec.java deleted file mode 100644 index 29fe516537..0000000000 --- a/src/compiler/scala/tools/util/UTF8Codec.java +++ /dev/null @@ -1,66 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - -package scala.tools.util; - -public final class UTF8Codec { - - public static int encode(char[] src, int from, byte[] dst, int to, int len) { - int i = from; - int j = to; - int end = from + len; - while (i < end) { - int ch = src[i++]; - if (ch < 128) - dst[j++] = (byte)ch; - else if (ch <= 0x3FF) { - dst[j++] = (byte)(0xC0 | (ch >> 6)); - dst[j++] = (byte)(0x80 | (ch & 0x3F)); - } else { - dst[j++] = (byte)(0xE0 | (ch >> 12)); - dst[j++] = (byte)(0x80 | ((ch >> 6) & 0x3F)); - dst[j++] = (byte)(0x80 | (ch & 0x3F)); - } - } - return j; - } - - public static int encode(String s, byte[] dst, int to) { - return encode(s.toCharArray(), 0, dst, to, s.length()); - } - - public static byte[] encode(String s) { - byte[] dst = new byte[s.length() * 3]; - int len = encode(s, dst, 0); - byte[] result = new byte[len]; - System.arraycopy(dst, 0, result, 0, len); - return result; - } - - public static int decode(byte[] src, int from, char[] dst, int to, int len) { - int i = from; - int j = to; - int end = from + len; - while (i < end) { - int b = src[i++] & 0xFF; - if (b >= 0xE0) { - b = ((b & 0x0F) << 12) | (src[i++] & 0x3F) << 6; - b = b | (src[i++] & 0x3F); - } else if (b >= 0xC0) { - b = ((b & 0x1F) << 6) | (src[i++] & 0x3F); - } - dst[j++] = (char)b; - } - return j; - } - - public static String decode(byte[] src, int from, int len) { - char[] cs = new char[len]; - return String.copyValueOf(cs, 0, decode(src, 0, cs, 0, len)); - } -} diff --git a/src/compiler/scala/tools/util/UTF8Codec.scala b/src/compiler/scala/tools/util/UTF8Codec.scala new file mode 100644 index 0000000000..3cc7200e18 --- /dev/null +++ b/src/compiler/scala/tools/util/UTF8Codec.scala @@ -0,0 +1,78 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002-2006, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +\* */ + +// $Id$ + + +package scala.tools.util; + + +object UTF8Codec { + + def encode(src: Array[Char], from: Int, dst: Array[Byte], to: Int, len: Int): Int = { + var i = from; + var j = to; + val end = from + len; + while (i < end) { + val ch = src(i); + i = i + 1; + if (ch < 128) { + dst(j) = ch.toByte; + j = j + 1; + } + else if (ch <= 0x3FF) { + dst(j) = (0xC0 | (ch >> 6)).toByte; + dst(j+1) = (0x80 | (ch & 0x3F)).toByte; + j = j + 2; + } else { + dst(j) = (0xE0 | (ch >> 12)).toByte; + dst(j+1) = (0x80 | ((ch >> 6) & 0x3F)).toByte; + dst(j+2) = (0x80 | (ch & 0x3F)).toByte; + j = j + 3; + } + } + j + } + + def encode(s: String, dst: Array[Byte], to: Int): Int = + encode(s.toCharArray(), 0, dst, to, s.length()); + + + def encode(s: String): Array[Byte] = { + val dst = new Array[Byte](s.length() * 3); + val len = encode(s, dst, 0); + dst.subArray(0, len) + } + + def decode(src: Array[Byte], from: Int, + dst: Array[Char], to: Int, len: Int): Int = + { + var i = from; + var j = to; + val end = from + len; + while (i < end) { + var b = src(i) & 0xFF; + i = i + 1; + if (b >= 0xE0) { + b = ((b & 0x0F) << 12) | (src(i) & 0x3F) << 6; + b = b | (src(i+1) & 0x3F); + i = i + 2; + } else if (b >= 0xC0) { + b = ((b & 0x1F) << 6) | (src(i) & 0x3F); + i = i + 1; + } + dst(j) = b.toChar; + j = j + 1; + } + j + } + + def decode(src: Array[Byte], from: Int, len: Int): String = { + val cs = new Array[Char](len); + String.copyValueOf(cs, 0, decode(src, 0, cs, 0, len)); + } + +} diff --git a/src/compiler/scala/tools/util/VirtualFile.java b/src/compiler/scala/tools/util/VirtualFile.java deleted file mode 100644 index b0e6e2a897..0000000000 --- a/src/compiler/scala/tools/util/VirtualFile.java +++ /dev/null @@ -1,97 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - -package scala.tools.util; - -import java.io.File; -import java.io.IOException; -import java.util.Iterator; - -/** This class implements an empty abstract regular file. */ -public class VirtualFile extends AbstractFile { - - //######################################################################## - // Private Fields - - /** The file name */ - private final String name; - - /** The file path */ - private final String path; - - //######################################################################## - // Public Constructors - - /** - * Initializes this instance with the specified name and an - * identical path. - */ - public VirtualFile(String name) { - this(name, name); - } - - /** Initializes this instance with the specified name and path. */ - public VirtualFile(String name, String path) { - this.name = name; - this.path = path; - assert name != null && path != null: name + " - " + path; - } - - //######################################################################## - // Public Methods - - /** Returns the name of this abstract file. */ - public String getName() { - return name; - } - - /** Returns the path of this abstract file. */ - public String getPath() { - return path; - } - - /** Returns null. */ - public final File getFile() { - return null; - } - - /** Is this abstract file a directory? */ - public boolean isDirectory() { - return false; - } - - /** Returns the time that this abstract file was last modified. */ - public long lastModified() { - return Long.MIN_VALUE; - } - - /** Reads the content of this abstract file into a byte array. */ - public byte[] read() throws IOException { - assert !isDirectory(): "cannot read directory '" + this + "'"; - return new byte[0]; - } - - /** Returns all abstract subfiles of this abstract directory. */ - public Iterator/**/ list() { - assert isDirectory(): "not a directory '" + this + "'"; - return EmptyIterator.object; - } - - /** - * Returns the abstract file in this abstract directory with the - * specified name. If there is no such file, returns null. The - * argument "directory" tells whether to look for a directory or - * or a regular file. - */ - public AbstractFile lookupName(String name, boolean directory) { - assert isDirectory(): "not a directory '" + this + "'"; - return null; - } - - //######################################################################## -} diff --git a/src/compiler/scala/tools/util/VirtualFile.scala b/src/compiler/scala/tools/util/VirtualFile.scala new file mode 100644 index 0000000000..58360b2a34 --- /dev/null +++ b/src/compiler/scala/tools/util/VirtualFile.scala @@ -0,0 +1,67 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002-2006, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +\* */ + +// $Id$ + + +package scala.tools.util; + + +import java.io.{File,IOException}; + +/** This class implements an empty abstract regular file. */ +class VirtualFile(val name: String, _path: String) extends AbstractFile { + + assert(name != null && path != null, name + " - " + path); + + //######################################################################## + // Public Constructors + + /** + * Initializes this instance with the specified name and an + * identical path. + */ + def this(name: String) = this(name, name); + + //######################################################################## + // Public Methods + + def path = _path; + + /** Returns null. */ + final def file: File = null; + + /** Is this abstract file a directory? */ + def isDirectory: Boolean = false; + + /** Returns the time that this abstract file was last modified. */ + def lastModified: Long = Long.MIN_VALUE; + + /** Reads the content of this abstract file into a byte array. */ + def read: Array[Byte] = { + assert(!isDirectory, "cannot read directory '" + this + "'"); + new Array[Byte](0); + } + + /** Returns all abstract subfiles of this abstract directory. */ + def elements: Iterator[AbstractFile] = { + assert(isDirectory, "not a directory '" + this + "'"); + Iterator.empty; + } + + /** + * Returns the abstract file in this abstract directory with the + * specified name. If there is no such file, returns null. The + * argument "directory" tells whether to look for a directory or + * or a regular file. + */ + def lookupName(name: String, directory: Boolean): AbstractFile = { + assert(isDirectory, "not a directory '" + this + "'"); + null; + } + + //######################################################################## +} diff --git a/src/compiler/scala/tools/util/ZipArchive.java b/src/compiler/scala/tools/util/ZipArchive.java deleted file mode 100644 index b3cd9e6538..0000000000 --- a/src/compiler/scala/tools/util/ZipArchive.java +++ /dev/null @@ -1,229 +0,0 @@ -/* ____ ____ ____ ____ ______ *\ -** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** -** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** -** /_____/\____/\___/\____/____/ ** -\* */ - -// $Id$ - -package scala.tools.util; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -/** - * This class implements an abstract directory backed by a zip - * archive. - */ -public final class ZipArchive extends PlainFile { - - //######################################################################## - // Public Factories - - /** Returns "fromFile(new File(path))". */ - public static AbstractFile fromPath(String path) { - return fromFile(new File(path)); - } - - /** - * If the specified File exists and is a readable zip archive, - * returns an abstract file backed by it. Otherwise, returns null. - */ - public static AbstractFile fromFile(File file) { - try { - return new ZipArchive(file, new ZipFile(file)); - } catch (IOException exception) { - return null; - } - } - - /** - * Returns an abstract directory backed by the specified archive. - */ - public static AbstractFile fromArchive(ZipFile archive) { - return new ZipArchive(new File(archive.getName()), archive); - } - - //######################################################################## - // Private Fields - - /** The zip archive */ - private final ZipFile archive; - - /** The root directory or null if not yet initialized */ - private DirEntry root; - - //######################################################################## - // Protected Constructors - - /** - * Initializes this instance with the specified File and ZipFile. - */ - protected ZipArchive(File file, ZipFile archive) { - super(file); - this.archive = archive; - assert archive != null; - } - - //######################################################################## - // Public Methods - - /** Returns true. */ - public boolean isDirectory() { - return true; - } - - /** Returns all abstract subfiles of this abstract directory. */ - public Iterator/**/ list() { - if (root == null) load(); - return root.list(); - } - - /** - * Returns the abstract file in this abstract directory with the - * specified name. If there is no such file, returns null. The - * argument "directory" tells whether to look for a directory or - * or a regular file. - */ - public AbstractFile lookupName(String name, boolean directory) { - if (root == null) load(); - return root.lookupName(name, directory); - } - - //######################################################################## - // Private Methods - - /** Loads the archive and creates the root directory. */ - private void load() { - this.root = new DirEntry("", "/"); - // A path to DirEntry map - HashMap/**/ dirs = new HashMap(); - dirs.put("/", root); - for (Enumeration e = archive.entries(); e.hasMoreElements(); ) { - ZipEntry entry = (ZipEntry)e.nextElement(); - String path = entry.getName(); - assert entry.isDirectory() == path.endsWith("/"): this +"-"+ path; - if (entry.isDirectory()) { - DirEntry dir = getDir(dirs, path); - assert dir.entry == null: this + " - " + path; - dir.entry = entry; - } else { - int index = path.lastIndexOf('/'); - String name = index < 0 ? path : path.substring(index + 1); - String home = index < 0 ? "/" : path.substring(0, index + 1); - DirEntry parent = getDir(dirs, home); - assert !parent.entries.containsKey(path): this + " - " + path; - parent.entries.put(name, new FileEntry(name, path, entry)); - } - } - } - - /** - * Lookups the specified table for a DirEntry with the specified - * path. If successful, returns the found DirEntry. Otherwise - * creates a new DirEntry, enters it into the table and in the - * table of its parent ZipDir and returns it. - */ - private DirEntry getDir(HashMap/**/ dirs, String path) { - DirEntry dir = (DirEntry)dirs.get(path); - if (dir == null) { - int index = path.lastIndexOf('/', path.length() - 2); - String name = index < 0 ? path : path.substring(index + 1); - String home = index < 0 ? "/" : path.substring(0, index + 1); - DirEntry parent = getDir(dirs, home); - dir = new DirEntry(name.substring(0, name.length() - 1), path); - parent.entries.put(name, dir); - dirs.put(path, dir); - } - return dir; - } - - //######################################################################## - // Private Class - Entry - - /** Superclass of archive entries */ - private abstract class Entry extends VirtualFile { - - public Entry(String name, String path) { - super(name, path); - } - - public final String getPath() { - return ZipArchive.this + "(" + super.getPath() + ")"; - } - - } - - //######################################################################## - // Private Class - DirEntry - - /** A directory archive entry */ - private final class DirEntry extends Entry { - - public final HashMap/**/ entries; - public ZipEntry entry; - - public DirEntry(String name, String path) { - super(name, path); - this.entries = new HashMap(); - } - - public boolean isDirectory() { - return true; - } - - public long lastModified() { - return entry != null ? entry.getTime() : super.lastModified(); - } - - public Iterator/**/ list() { - return entries.values().iterator(); - } - - public AbstractFile lookupName(String name, boolean directory) { - return (AbstractFile)entries.get(directory ? name + "/" : name); - } - - } - - //######################################################################## - // Private Class - FileEntry - - /** A regular file archive entry */ - public final class FileEntry extends Entry { - - public final ZipEntry entry; - - public FileEntry(String name, String path, ZipEntry entry) { - super(name, path); - this.entry = entry; - } - - public long lastModified() { - return entry.getTime(); - } - - public byte[] read() throws IOException { - InputStream in = archive.getInputStream(entry); - int rest = (int)entry.getSize(); - byte[] buf = new byte[rest]; - do { - int res = in.read(buf, buf.length - rest, rest); - if (res == -1) - throw new IOException("read error"); - rest -= res; - } while (rest > 0); - in.close(); - return buf; - } - - } - - //######################################################################## -} diff --git a/src/compiler/scala/tools/util/ZipArchive.scala b/src/compiler/scala/tools/util/ZipArchive.scala new file mode 100644 index 0000000000..c15b432e4b --- /dev/null +++ b/src/compiler/scala/tools/util/ZipArchive.scala @@ -0,0 +1,190 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +\* */ + +// $Id$ + + +package scala.tools.util; + + +import java.io.{File, IOException, InputStream}; +import java.util.Enumeration; +import java.util.zip.{ZipEntry, ZipFile}; +import scala.collection.mutable.{Map, HashMap} + +object ZipArchive { + + //######################################################################## + + /** Returns "fromFile(new File(path))". */ + def fromPath(path: String): AbstractFile = fromFile(new File(path)); + + /** + * If the specified File exists and is a readable zip archive, + * returns an abstract file backed by it. Otherwise, returns null. + */ + def fromFile(file: File): AbstractFile = + try { new ZipArchive(file, new ZipFile(file)) } + catch { case _: IOException => null } + + /** + * Returns an abstract directory backed by the specified archive. + */ + def fromArchive(archive: ZipFile): AbstractFile = + new ZipArchive(new File(archive.getName()), archive); +} + +/** + * This class implements an abstract directory backed by a zip + * archive. + */ +final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file) { + + assert(archive != null) + //######################################################################## + // Private Fields + + /** The root directory or null if not yet initialized */ + private var root: DirEntry = _; + + //######################################################################## + // Public Methods + + /** Returns true. */ + override def isDirectory = true; + + /** Returns all abstract subfiles of this abstract directory. */ + override def elements: Iterator[AbstractFile] = { + if (root == null) load(); + root.elements; + } + + /** + * Returns the abstract file in this abstract directory with the + * specified name. If there is no such file, returns null. The + * argument "directory" tells whether to look for a directory or + * or a regular file. + */ + override def lookupName(name: String, directory: Boolean): AbstractFile = { + if (root == null) load(); + root.lookupName(name, directory); + } + + //######################################################################## + // Private Methods + + /** Loads the archive and creates the root directory. */ + private def load(): Unit = { + this.root = new DirEntry("", "/"); + // A path to DirEntry map + val dirs: Map[String,DirEntry] = new HashMap(); + dirs.update("/", root); + val entries = archive.entries(); + while (entries.hasMoreElements()) { + val entry = entries.nextElement().asInstanceOf[ZipEntry]; + val path = entry.getName(); + assert(entry.isDirectory() == path.endsWith("/"), + this.toString() + " - " + path); + if (entry.isDirectory()) { + val dir: DirEntry = getDir(dirs, path); + assert(dir.entry == null, this.toString() + " - " + path); + dir.entry = entry; + } else { + val index = path.lastIndexOf('/'); + val name = if (index < 0) path else path.substring(index + 1); + val home = if (index < 0) "/" else path.substring(0, index + 1); + val parent: DirEntry = getDir(dirs, home); + assert(!parent.entries.contains(path), this.toString() + " - " + path); + parent.entries.update(name, new FileEntry(name, path, entry)); + } + } + } + + /** + * Lookups the specified table for a DirEntry with the specified + * path. If successful, returns the found DirEntry. Otherwise + * creates a new DirEntry, enters it into the table and in the + * table of its parent ZipDir and returns it. + */ + private def getDir(dirs: Map[String,DirEntry], path: String): DirEntry = + dirs.get(path) match { + case Some(dir) => dir + case None => { + val index = path.lastIndexOf('/', path.length() - 2); + val name = if (index < 0) path else path.substring(index + 1); + val home = if (index < 0) "/" else path.substring(0, index + 1); + val parent: DirEntry = getDir(dirs, home); + val dir = new DirEntry(name.substring(0, name.length() - 1), path); + parent.entries.update(name, dir); + dirs.update(path, dir); + dir + } + } + + //######################################################################## + // Private Class - Entry + + /** Superclass of archive entries */ + abstract class Entry(name: String, path: String) + extends VirtualFile(name, path) + { + + final override def path = ZipArchive.this.toString() + "(" + super.path + ")"; + + } + + //######################################################################## + // Private Class - DirEntry + + /** A directory archive entry */ + private final class DirEntry(name: String, path: String) + extends Entry(name, path) + { + + val entries: Map[String,Entry] = new HashMap(); + + var entry: ZipEntry = _; + + override def isDirectory = true; + + override def lastModified: Long = + if (entry != null) entry.getTime() else super.lastModified; + + override def elements: Iterator[AbstractFile] = entries.values; + + override def lookupName(name: String, directory: Boolean): AbstractFile = + entries.get(if (directory) name + "/" else name) match { + case Some(dir) => dir + case None => null + } + } + + //######################################################################## + // Private Class - FileEntry + + /** A regular file archive entry */ + final class FileEntry(name: String, path: String, val entry: ZipEntry) + extends Entry(name, path) + { + + override def lastModified: Long = entry.getTime(); + + override def read: Array[Byte] = { + val in: InputStream = archive.getInputStream(entry); + var rest: Int = entry.getSize().toInt; + val buf = new Array[Byte](rest); + while (rest > 0) { + val res = in.read(buf, buf.length - rest, rest); + if (res == -1) + throw new IOException("read error"); + rest = rest - res; + } + in.close(); + buf + } + } + +} -- cgit v1.2.3