From 9b178df043a2eeb447bb33d338cdaac8c7a0d33f Mon Sep 17 00:00:00 2001 From: buraq Date: Thu, 19 Aug 2004 17:17:55 +0000 Subject: files for io, used by xml parsing --- sources/scala/io/Position.scala | 84 ++++++++++++++++++++++++++++ sources/scala/io/Source.scala | 121 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 sources/scala/io/Position.scala create mode 100644 sources/scala/io/Source.scala (limited to 'sources/scala/io') diff --git a/sources/scala/io/Position.scala b/sources/scala/io/Position.scala new file mode 100644 index 0000000000..4fb57b9dc7 --- /dev/null +++ b/sources/scala/io/Position.scala @@ -0,0 +1,84 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +** $Id$ +\* */ + +package scala.io; + +/** convenience methods to encode line and column number in one + * single integer. The encode line (column) + * numbers range from 0 to LINE_MASK (COLUMN_MASK), where 0 indicates + * that the line (column) is the undefined and 1 represents the first + * line (column). Line (Column) numbers greater than LINE_MASK + * (COLUMN_MASK) are replaced by LINE_MASK (COLUMN_MASK). Furthermore, + * if the encoded line number is LINE_MASK, the column number is + * always set to 0. + + * The following properties hold: + * - the undefined position is 0: encode(0,0) == 0 + * - encodings are non-negative : encode(line,column) >= 0 + * - position order is preserved: + * (line1 < line2) || (line1 == line2 && column1 < column2) + * implies + * encode(line1,column1) <= encode(line2,column2) + * @author Burak Emir (translated from work by Matthias Zengers and others) + */ +object Position { + + /** Number of bits used to encode the line number */ + final val LINE_BITS = 20; + /** Number of bits used to encode the column number */ + final val COLUMN_BITS = 31 - LINE_BITS; // no negatives => 31 + + /** Mask to decode the line number */ + final val LINE_MASK = (1 << LINE_BITS) - 1; + /** Mask to decode the column number */ + final val COLUMN_MASK = (1 << COLUMN_BITS) - 1; + + /** The undefined position */ + final val NOPOS = 0; + + /** The first position in a source file */ + final val FIRSTPOS = encode(1, 1); + + //######################################################################## + // Public Functions + + /** Encodes a position into a single integer. */ + final def encode(line: Int, column: Int): Int = { + var line1, column1 = 0; + if( line < 0 ) + error(line+" < 0"); + if(( line == 0 )&&(column != 0)) + error(line+","+column+" not allowed"); + if( column < 0 ) + error(line+","+column+" not allowed"); + + if (line >= LINE_MASK) { line1 = LINE_MASK; column1 = 0; } + if (column > COLUMN_MASK) column1 = COLUMN_MASK; + (line1 << COLUMN_BITS) | column1; + } + + /** Returns the line number of the encoded position. */ + final def line(pos: Int): Int = { + (pos >> COLUMN_BITS) & LINE_MASK; + } + + /** Returns the column number of the encoded position. */ + final def column(pos: Int): Int = { + pos & COLUMN_MASK; + } + + /** Returns a string representation of the encoded position. */ + def toString(pos: Int): String = { + val sb = new StringBuffer(); + sb.append(line(pos)); + sb.append(':'); + sb.append(column(pos)); + sb.toString(); + } +} diff --git a/sources/scala/io/Source.scala b/sources/scala/io/Source.scala new file mode 100644 index 0000000000..8c22e2f3bf --- /dev/null +++ b/sources/scala/io/Source.scala @@ -0,0 +1,121 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +** $Id$ +\* */ + +package scala.io; + +/** convenience methods to create an iterable representation of a source file + * @author Burak Emir + */ +object Source { + + /** creates Source from array of bytes, with empty description + */ + def fromBytes(bytes: Array[Byte]): Source = + fromString(new String(bytes)); + + /** creates Source from array of bytes with given encoding, with empty description + */ + def fromBytes(bytes: Array[Byte], enc: String): Source = + fromString(new String(bytes, enc)); + + /** creates Source from array of characters, with empty description + */ + def fromChars(chars: Array[Char]): Source = { + val it = Iterator.fromArray(chars); + new Source { + val iter = it; + } + } + /** creates Source from string, with empty description + */ + def fromString(s: String): Source = { + val it = Iterator.fromString(s); + new Source { + val iter = it; + } + } + + /** creates Source from file with given name, setting its description to + * filename. + */ + def fromFile(name: String): Source = + fromFile( new java.io.File( name )); + + /** creates Source from file with given name, using given encoding, setting + * its description to filename. + */ + def fromFile(name: String, enc: String): Source = + fromFile( new java.io.File( name ), enc); + + /** creates Source from file, using default character encoding, setting its + * description to filename. + */ + def fromFile(file: java.io.File): Source = { + val arr: Array[Byte] = new Array[Byte]( file.length().asInstanceOf[Int] ); + val is = new java.io.FileInputStream( file ); + is.read( arr ); + val s = fromBytes(arr); + s.descr = file.getName(); + s + } + + /** creates Source from file, using given character encoding, setting its + * description to filename. + */ + def fromFile(file: java.io.File, enc: String): Source = { + val arr: Array[Byte] = new Array[Byte]( file.length().asInstanceOf[Int] ); + val is = new java.io.FileInputStream( file ); + is.read( arr ); + val s = fromBytes(arr, enc); + s.descr = file.getName(); + s + } +} + +/** an iterable representation of source files. + * @author Burak Emir + */ +abstract class Source extends Iterator[Char] { + /** default col increment for tabs '\t', set to 4 */ + val tabinc = 4; + + val iter: Iterator[Char]; + /** returns next characters, updates positions and assigns the character + * ch as side effect + */ + def next = { + ch = iter.next; + pos = Position.encode(cline,ccol); + ch match { + case '\n' => + ccol = 1; + cline = cline + 1; + case '\t' => + ccol = ccol + tabinc; + case _ => + ccol = ccol + 1; + } + ch + }; + /** returns true if this source has more characters + */ + def hasNext = iter.hasNext; + + var cline = 1; + var ccol = 1; + /** position of last character returned by next*/ + var pos = 0; + + /** the last character returned by next. + * the value before the first call to next is undefined + */ + var ch: Char = _; + /** description of this source */ + var descr:String = ""; +} -- cgit v1.2.3