summaryrefslogblamecommitdiff
path: root/examples/scala-js/javalib/src/main/scala/java/io/PrintWriter.scala
blob: 4e693e043b241c6442dd38abe161037711e5961a (plain) (tree)





















































































































































                                                                                        
package java.io

import java.util.Formatter

class PrintWriter(protected[io] var out: Writer,
    autoFlush: Boolean) extends Writer {

  def this(out: Writer) = this(out, false)

  def this(out: OutputStream, autoFlush: Boolean) =
    this(new OutputStreamWriter(out), autoFlush)
  def this(out: OutputStream) =
    this(out, false)

  /* The following constructors, although implemented, will not link, since
   * File, FileOutputStream and BufferedOutputStream are not implemented.
   * They're here just in case a third-party library on the classpath
   * implements those.
   */
  def this(file: File) =
    this(new BufferedOutputStream(new FileOutputStream(file)))
  def this(file: File, csn: String) =
    this(new OutputStreamWriter(new BufferedOutputStream(
        new FileOutputStream(file)), csn))
  def this(fileName: String) = this(new File(fileName))
  def this(fileName: String, csn: String) = this(new File(fileName), csn)

  private var closed: Boolean = false
  private var errorFlag: Boolean = false

  def flush(): Unit =
    ensureOpenAndTrapIOExceptions(out.flush())

  def close(): Unit = trapIOExceptions {
    if (!closed) {
      flush()
      closed = true
      out.close()
    }
  }

  def checkError(): Boolean = {
    if (closed) {
      /* Just check the error flag.
       * Common sense would tell us to look at the underlying writer's
       * checkError() result too (like we do in the not closed case below).
       * But the JDK does not behave like that. So we don't either.
       */
      errorFlag
    } else {
      flush()
      /* If the underlying writer is also a PrintWriter, we also check its
       * checkError() result. This is not clearly specified by the JavaDoc,
       * but, experimentally, the JDK seems to behave that way.
       */
      errorFlag || (out match {
        case out: PrintWriter => out.checkError()
        case _                => false
      })
    }
  }

  protected[io] def setError(): Unit = errorFlag = true
  protected[io] def clearError(): Unit = errorFlag = false

  override def write(c: Int): Unit =
    ensureOpenAndTrapIOExceptions(out.write(c))

  override def write(buf: Array[Char], off: Int, len: Int): Unit =
    ensureOpenAndTrapIOExceptions(out.write(buf, off, len))

  override def write(buf: Array[Char]): Unit =
    ensureOpenAndTrapIOExceptions(out.write(buf))

  override def write(s: String, off: Int, len: Int): Unit =
    ensureOpenAndTrapIOExceptions(out.write(s, off, len))

  override def write(s: String): Unit =
    ensureOpenAndTrapIOExceptions(out.write(s))

  def print(b: Boolean): Unit     = write(String.valueOf(b))
  def print(c: Char): Unit        = write(c)
  def print(i: Int): Unit         = write(String.valueOf(i))
  def print(l: Long): Unit        = write(String.valueOf(l))
  def print(f: Float): Unit       = write(String.valueOf(f))
  def print(d: Double): Unit      = write(String.valueOf(d))
  def print(s: Array[Char]): Unit = write(s)
  def print(s: String): Unit      = write(if (s == null) "null" else s)
  def print(obj: AnyRef): Unit    = write(String.valueOf(obj))

  def println(): Unit = {
    write('\n') // In Scala.js the line separator is always LF
    if (autoFlush)
      flush()
  }

  def println(b: Boolean): Unit     = { print(b); println() }
  def println(c: Char): Unit        = { print(c); println() }
  def println(i: Int): Unit         = { print(i); println() }
  def println(l: Long): Unit        = { print(l); println() }
  def println(f: Float): Unit       = { print(f); println() }
  def println(d: Double): Unit      = { print(d); println() }
  def println(s: Array[Char]): Unit = { print(s); println() }
  def println(s: String): Unit      = { print(s); println() }
  def println(obj: AnyRef): Unit    = { print(obj); println() }

  def printf(fmt: String, args: Array[Object]): PrintWriter =
    format(fmt, args)

  // Not implemented:
  //def printf(l: java.util.Locale, fmt: String, args: Array[Object]): PrintWriter = ???

  def format(fmt: String, args: Array[Object]): PrintWriter = {
    new Formatter(this).format(fmt, args)
    if (autoFlush)
      flush()
    this
  }

  // Not implemented:
  //def format(l: java.util.Locale, fmt: String, args: Array[Object]): PrintWriter = ???

  override def append(csq: CharSequence): PrintWriter = {
    super.append(csq)
    this
  }

  override def append(csq: CharSequence, start: Int, end: Int): PrintWriter = {
    super.append(csq, start, end)
    this
  }

  override def append(c: Char): PrintWriter = {
    super.append(c)
    this
  }

  @inline private[this] def trapIOExceptions(body: => Unit): Unit = {
    try {
      body
    } catch {
      case _: IOException => setError()
    }
  }

  @inline private[this] def ensureOpenAndTrapIOExceptions(body: => Unit): Unit = {
    if (closed) setError()
    else trapIOExceptions(body)
  }
}