summaryrefslogtreecommitdiff
path: root/examples/scala-js/tools/shared/src/main/scala/scala/scalajs/tools/io/IO.scala
blob: b69b07c389090794aca57ed9b359975a86447953 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package scala.scalajs.tools.io

import scala.annotation.tailrec

import scala.reflect.ClassTag

import java.io._

object IO {
  /** Returns the lines in an input stream.
   *  Lines do not contain the new line characters.
   */
  def readLines(stream: InputStream): List[String] =
    readLines(new InputStreamReader(stream))

  /** Returns the lines in a string.
   *  Lines do not contain the new line characters.
   */
  def readLines(content: String): List[String] =
    readLines(new StringReader(content))

  /** Returns the lines in a reader.
   *  Lines do not contain the new line characters.
   */
  def readLines(reader: Reader): List[String] = {
    val br = new BufferedReader(reader)
    try {
      val builder = List.newBuilder[String]
      @tailrec
      def loop(): Unit = {
        val line = br.readLine()
        if (line ne null) {
          builder += line
          loop()
        }
      }
      loop()
      builder.result()
    } finally {
      br.close()
    }
  }

  /** Reads the entire content of a reader as a string. */
  def readReaderToString(reader: Reader): String = {
    val buffer = newBuffer[Char]
    val builder = new StringBuilder
    @tailrec
    def loop(): Unit = {
      val len = reader.read(buffer)
      if (len > 0) {
        builder.appendAll(buffer, 0, len)
        loop()
      }
    }
    loop()
    builder.toString()
  }

  /** Reads the entire content of an input stream as a UTF-8 string. */
  def readInputStreamToString(stream: InputStream): String = {
    val reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"))
    readReaderToString(reader)
  }

  /** Reads the entire content of an input stream as a byte array. */
  def readInputStreamToByteArray(stream: InputStream): Array[Byte] = {
    val builder = new ByteArrayOutputStream()
    val buffer = newBuffer[Byte]
    @tailrec
    def loop(): Unit = {
      val size = stream.read(buffer)
      if (size > 0) {
        builder.write(buffer, 0, size)
        loop()
      }
    }
    loop()
    builder.toByteArray()
  }

  /** Concatenates a bunch of VirtualTextFiles to a WritableVirtualTextFile.
   *  Adds a '\n' after each file.
   */
  def concatFiles(output: WritableVirtualTextFile,
      files: Seq[VirtualTextFile]): Unit = {
    val buffer = newBuffer[Char]
    val out = output.contentWriter

    try {
      for (file <- files) {
        val reader = file.reader

        @tailrec
        def loop(): Unit = {
          val size = reader.read(buffer)
          if (size > 0) {
            out.write(buffer, 0, size)
            loop()
          }
        }

        try loop()
        finally reader.close()

        // New line after each file
        out.write('\n')
      }
    } finally {
      out.close()
    }
  }

  @inline
  private def newBuffer[T : ClassTag] = new Array[T](4096)
}