Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Restored Source factories to a form source comp...

Restored Source factories to a form source compatible with 2.7.7. No
default implicit arguments, now low priority saves the day with a low
priority codec which io.Codec offers as last resort. Dropped the line
separator argument to getLines and made it act in a separator agnostic
way (any of \r\n, \r, or \n is a separator.) Review by community.
  • Loading branch information...
commit e9d3987da750e2d6ce154dd3b2ceca309b665674 1 parent 43e5eff
@paulp paulp authored
View
4 src/library/scala/LowPriorityImplicits.scala
@@ -6,8 +6,6 @@
** |/ **
\* */
-
-
package scala
import collection.mutable._
@@ -59,6 +57,4 @@ class LowPriorityImplicits {
def wrapArray(xs: Array[Short]): WrappedArray[Short] = new WrappedArray.ofShort(xs)
def wrapArray(xs: Array[Boolean]): WrappedArray[Boolean] = new WrappedArray.ofBoolean(xs)
def wrapArray(xs: Array[Unit]): WrappedArray[Unit] = new WrappedArray.ofUnit(xs)
-
-
}
View
6 src/library/scala/io/BufferedSource.scala
@@ -18,10 +18,10 @@ import Source.DefaultBufSize
*
* @author Burak Emir, Paul Phillips
*/
-class BufferedSource(inputStream: InputStream)(implicit codec: Codec = Codec.default) extends Source
-{
+class BufferedSource(inputStream: InputStream, bufferSize: Int)(implicit val codec: Codec) extends Source {
+ def this(inputStream: InputStream)(implicit codec: Codec) = this(inputStream, DefaultBufSize)(codec)
def reader() = new InputStreamReader(inputStream, codec.decoder)
- def bufferedReader() = new BufferedReader(reader(), DefaultBufSize)
+ def bufferedReader() = new BufferedReader(reader(), bufferSize)
override val iter = {
val reader = bufferedReader()
View
22 src/library/scala/io/Codec.scala
@@ -25,8 +25,7 @@ import java.nio.charset.{ Charset, CharsetDecoder, CharsetEncoder, CharacterCodi
/** A class for character encoding/decoding preferences.
*
*/
-class Codec(val charSet: Charset)
-{
+class Codec(val charSet: Charset) {
type Configure[T] = (T => T, Boolean)
type Handler = CharacterCodingException => Int
@@ -70,11 +69,26 @@ class Codec(val charSet: Charset)
})
}
-object Codec {
+trait LowPriorityCodecImplicits {
+ self: Codec.type =>
+
+ /** The Codec of Last Resort. */
+ implicit def fallbackSystemCodec: Codec = defaultCharsetCodec
+}
+
+object Codec extends LowPriorityCodecImplicits {
final val ISO8859 = Charset forName "ISO-8859-1"
final val UTF8 = Charset forName "UTF-8"
- def default = apply(Charset.defaultCharset)
+ /** Optimistically these two possible defaults will be the same thing.
+ * In practice this is not necessarily true, and in fact Sun classifies
+ * the fact that you can influence anything at all via -Dfile.encoding
+ * as an accident, with any anomalies considered "not a bug".
+ */
+ def defaultCharsetCodec = apply(Charset.defaultCharset)
+ def fileEncodingCodec = apply(util.Properties.encodingString)
+ def default = defaultCharsetCodec
+
def apply(encoding: String): Codec = new Codec(Charset forName encoding)
def apply(charSet: Charset): Codec = new Codec(charSet)
def apply(decoder: CharsetDecoder): Codec = {
View
194 src/library/scala/io/Source.scala
@@ -26,36 +26,78 @@ object Source {
*/
def stdin = fromInputStream(System.in)
- /** Creates a <code>Source</code> from an Iterable.
+ /** Creates a Source from an Iterable.
*
* @param iterable the Iterable
- * @return the <code>Source</code> instance.
+ * @return the Source
*/
def fromIterable(iterable: Iterable[Char]): Source = new Source {
val iter = iterable.iterator
} withReset(() => fromIterable(iterable))
- /** Creates a <code>Source</code> instance from a single character.
- *
- * @param c ...
- * @return the create <code>Source</code> instance.
+ /** Creates a Source instance from a single character.
*/
def fromChar(c: Char): Source = fromIterable(Array(c))
/** creates Source from array of characters, with empty description.
- *
- * @param chars ...
- * @return ...
*/
def fromChars(chars: Array[Char]): Source = fromIterable(chars)
- /** creates Source from string, with empty description.
- *
- * @param s ...
- * @return ...
+ /** creates Source from a String, with no description.
*/
def fromString(s: String): Source = fromIterable(s)
+ /** creates Source from file with given name, setting its description to
+ * filename.
+ */
+ def fromFile(name: String)(implicit codec: Codec): BufferedSource =
+ fromFile(new JFile(name))(codec)
+
+ /** creates Source from file with given name, using given encoding, setting
+ * its description to filename.
+ */
+ def fromFile(name: String, enc: String): BufferedSource =
+ fromFile(name)(Codec(enc))
+
+ /** creates <code>Source</code> from file with given file: URI
+ */
+ def fromFile(uri: URI)(implicit codec: Codec): BufferedSource =
+ fromFile(new JFile(uri))(codec)
+
+ /** creates Source from file with given file: URI
+ */
+ def fromFile(uri: URI, enc: String): BufferedSource =
+ fromFile(uri)(Codec(enc))
+
+ /** creates Source from file, using default character encoding, setting its
+ * description to filename.
+ */
+ def fromFile(file: JFile)(implicit codec: Codec): BufferedSource =
+ fromFile(file, Source.DefaultBufSize)(codec)
+
+ /** same as fromFile(file, enc, Source.DefaultBufSize)
+ */
+ def fromFile(file: JFile, enc: String): BufferedSource =
+ fromFile(file)(Codec(enc))
+
+ def fromFile(file: JFile, enc: String, bufferSize: Int): BufferedSource =
+ fromFile(file, bufferSize)(Codec(enc))
+
+ /** Creates Source from <code>file</code>, using given character encoding,
+ * setting its description to filename. Input is buffered in a buffer of
+ * size <code>bufferSize</code>.
+ */
+ def fromFile(file: JFile, bufferSize: Int)(implicit codec: Codec): BufferedSource = {
+ val inputStream = new FileInputStream(file)
+
+ createBufferedSource(
+ inputStream,
+ bufferSize,
+ () => fromFile(file, bufferSize)(codec),
+ () => inputStream.close()
+ )(codec) withDescription ("file:" + file.getAbsolutePath)
+ }
+
/** Create a <code>Source</code> from array of bytes, decoding
* the bytes according to codec.
*
@@ -63,74 +105,69 @@ object Source {
* @param enc ...
* @return the created <code>Source</code> instance.
*/
- def fromBytes(bytes: Array[Byte])(implicit codec: Codec = Codec.default): Source =
+ def fromBytes(bytes: Array[Byte])(implicit codec: Codec): Source =
fromString(new String(bytes, codec.name))
+ def fromBytes(bytes: Array[Byte], enc: String): Source =
+ fromBytes(bytes)(Codec(enc))
+
/** Create a <code>Source</code> from array of bytes, assuming
* one byte per character (ISO-8859-1 encoding.)
*/
def fromRawBytes(bytes: Array[Byte]): Source = fromString(new String(bytes, Codec.ISO8859.name))
- /** creates Source from file with given name, setting
- * its description to filename.
+ /** creates <code>Source</code> from file with given file: URI
*/
- def fromPath(name: String)(implicit codec: Codec = Codec.default): Source = fromFile(new JFile(name))
+ def fromURI(uri: URI)(implicit codec: Codec): BufferedSource = fromFile(new JFile(uri))(codec)
- /** creates <code>Source</code> from file with given file: URI
+ /** same as fromURL(new URL(s))(Codec(enc))
*/
- def fromURI(uri: URI)(implicit codec: Codec = Codec.default): Source = fromFile(new JFile(uri))
+ def fromURL(s: String, enc: String): BufferedSource =
+ fromURL(s)(Codec(enc))
- /** same as fromInputStream(url.openStream())(codec)
+ /** same as fromURL(new URL(s))
*/
- def fromURL(url: URL)(implicit codec: Codec = Codec.default): Source =
- fromInputStream(url.openStream())(codec)
+ def fromURL(s: String)(implicit codec: Codec): BufferedSource =
+ fromURL(new URL(s))(codec)
- /** Creates Source from <code>file</code>, using given character encoding,
- * setting its description to filename. Input is buffered in a buffer of
- * size <code>bufferSize</code>.
+ /** same as fromInputStream(url.openStream())(Codec(enc))
*/
- def fromFile(file: JFile, bufferSize: Int = DefaultBufSize)(implicit codec: Codec = Codec.default): Source = {
- val inputStream = new FileInputStream(file)
+ def fromURL(url: URL, enc: String): BufferedSource =
+ fromURL(url)(Codec(enc))
- fromInputStream(
- inputStream,
- bufferSize,
- () => fromFile(file, bufferSize)(codec),
- () => inputStream.close()
- ) withDescription ("file:" + file.getAbsolutePath)
- }
+ /** same as fromInputStream(url.openStream())(codec)
+ */
+ def fromURL(url: URL)(implicit codec: Codec): BufferedSource =
+ fromInputStream(url.openStream())(codec)
- /** Reads data from <code>inputStream</code> with a buffered reader,
- * using encoding in implicit parameter <code>codec</code>.
+ /** Reads data from inputStream with a buffered reader, using the encoding
+ * in implicit parameter codec.
*
* @param inputStream the input stream from which to read
* @param bufferSize buffer size (defaults to Source.DefaultBufSize)
* @param reset a () => Source which resets the stream (if unset, reset() will throw an Exception)
+ * @param close a () => Unit method which closes the stream (if unset, close() will do nothing)
* @param codec (implicit) a scala.io.Codec specifying behavior (defaults to Codec.default)
* @return the buffered source
*/
- def fromInputStream(
+ def createBufferedSource(
inputStream: InputStream,
bufferSize: Int = DefaultBufSize,
reset: () => Source = null,
close: () => Unit = null
- )(implicit codec: Codec = Codec.default): Source =
- {
+ )(implicit codec: Codec): BufferedSource = {
// workaround for default arguments being unable to refer to other parameters
- val resetFn = if (reset == null) () => fromInputStream(inputStream, bufferSize, reset, close) else reset
- new BufferedSource(inputStream)(codec) .
- withReset (resetFn) .
- withClose (close)
+ val resetFn = if (reset == null) () => createBufferedSource(inputStream, bufferSize, reset, close)(codec) else reset
+
+ new BufferedSource(inputStream, bufferSize)(codec) withReset resetFn withClose close
}
-}
-// Coming Soon?
-//
-// abstract class Source2[T] extends Iterable[T] { }
-//
-// abstract class ByteSource() extends Source2[Byte] { }
-//
-// abstract class CharSource(implicit codec: Codec = Codec.default) extends Source2[Char] { }
+ def fromInputStream(is: InputStream, enc: String): BufferedSource =
+ fromInputStream(is)(Codec(enc))
+
+ def fromInputStream(is: InputStream)(implicit codec: Codec): BufferedSource =
+ createBufferedSource(is, reset = () => fromInputStream(is)(codec), close = () => is.close())(codec)
+}
/** The class <code>Source</code> implements an iterable representation
* of source data. Calling method <code>reset</code> returns an identical,
@@ -139,8 +176,7 @@ object Source {
* @author Burak Emir
* @version 1.0
*/
-abstract class Source extends Iterator[Char]
-{
+abstract class Source extends Iterator[Char] {
/** the actual iterator */
protected val iter: Iterator[Char]
@@ -152,42 +188,35 @@ abstract class Source extends Iterator[Char]
var nerrors = 0
var nwarnings = 0
- /** convenience method, returns given line (not including newline)
+ /** Convenience method, returns given line (not including newline)
* from Source.
*
* @param line the line index, first line is 1
- * @return the character string of the specified line.
+ * @return the specified line.
*
*/
+ @deprecated("Use a collections method such as getLines().toIndexedSeq for random access.")
def getLine(line: Int): String = getLines() drop (line - 1) next
- class LineIterator(separator: String) extends Iterator[String] {
- require(separator.length == 1 || separator.length == 2, "Line separator may be 1 or 2 characters only.")
- lazy val iter: BufferedIterator[Char] = Source.this.iter.buffered
- // For two character newline sequences like \r\n, we peek at
- // the iterator head after seeing \r, and drop the \n if present.
- val isNewline: Char => Boolean = {
- val firstCh = separator(0)
- if (separator.length == 1) (_ == firstCh)
- else (ch: Char) => (ch == firstCh) && iter.hasNext && {
- val res = iter.head == separator(1)
- if (res) { iter.next } // drop the second character
- res
- }
- }
+ class LineIterator() extends Iterator[String] {
private[this] val sb = new StringBuilder
- private def getc() =
- if (!iter.hasNext) false
+ lazy val iter: BufferedIterator[Char] = Source.this.iter.buffered
+ def isNewline(ch: Char) = ch == '\r' || ch == '\n'
+ def getc() = iter.hasNext && {
+ val ch = iter.next
+ if (ch == '\n') false
+ else if (ch == '\r') {
+ if (iter.hasNext && iter.head == '\n')
+ iter.next
+
+ false
+ }
else {
- val ch = iter.next
- if (isNewline(ch)) false
- else {
- sb append ch
- true
- }
+ sb append ch
+ true
}
-
+ }
def hasNext = iter.hasNext
def next = {
sb.clear
@@ -196,12 +225,11 @@ abstract class Source extends Iterator[Char]
}
}
- /** returns an iterator who returns lines (NOT including newline character(s)).
- * If no separator is given, the platform-specific value "line.separator" is used.
- * a line ends in \r, \n, or \r\n.
+ /** Returns an iterator who returns lines (NOT including newline character(s)).
+ * It will treat any of \r\n, \r, or \n as a line separator (longest match) - if
+ * you need more refined behavior you can subclass Source#LineIterator directly.
*/
- def getLines(separator: String = compat.Platform.EOL): Iterator[String] =
- new LineIterator(separator)
+ def getLines(): Iterator[String] = new LineIterator()
/** Returns <code>true</code> if this source has more characters.
*/
View
2  src/library/scala/xml/parsing/ConstructingParser.scala
@@ -17,7 +17,7 @@ import scala.io.{ Source, Codec }
object ConstructingParser {
def fromFile(inp: File, preserveWS: Boolean) =
- new ConstructingParser(Source.fromFile(inp)(), preserveWS) initialize
+ new ConstructingParser(Source.fromFile(inp), preserveWS) initialize
def fromSource(inp: Source, preserveWS: Boolean) =
new ConstructingParser(inp, preserveWS) initialize
View
5 src/library/scala/xml/parsing/ExternalSources.scala
@@ -20,8 +20,7 @@ import scala.io.Source
* @author Burak Emir
* @version 1.0
*/
-trait ExternalSources
-{
+trait ExternalSources {
self: ExternalSources with MarkupParser with MarkupHandler =>
/** ...
@@ -38,6 +37,6 @@ trait ExternalSources
case x => x take ((x lastIndexOf separator) + 1)
}
- Source.fromPath(fileStr + systemId)()
+ Source.fromFile(fileStr + systemId)
}
}
View
2  src/library/scala/xml/persistent/CachedFileStorage.scala
@@ -73,7 +73,7 @@ extends java.lang.Thread with scala.util.logging.Logged {
import scala.io.Source
import scala.xml.parsing.ConstructingParser
log("[load]\nloading "+theFile)
- val src = Source.fromFile(theFile)()
+ val src = Source.fromFile(theFile)
log("parsing "+theFile)
val res = ConstructingParser.fromSource(src,false).document.docElem(0)
switch
View
2  test/files/jvm/unittest_io.scala
@@ -15,7 +15,7 @@ it is split on several lines.
isn't it?
""")
- def runTest() = assertEquals("wrong number of lines",src.getLines("\n").toList.length,5) // five new lines in there
+ def runTest() = assertEquals("wrong number of lines",src.getLines.toList.length,5) // five new lines in there
//for (line <- src.getLines) {
// Console.print(line)
//}
Please sign in to comment.
Something went wrong with that request. Please try again.