src/Pure/General/bytes.scala
author wenzelm
Fri, 15 Nov 2013 19:31:10 +0100
changeset 54442 c39972ddd672
parent 54440 2c4940d2edf7
child 54444 a2290f36d1d6
permissions -rw-r--r--
more specific Protocol_Output: empty message.body, main content via bytes/text;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/General/bytes.scala
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
     2
    Module:     PIDE
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
     3
    Author:     Makarius
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
     4
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
     5
Immutable byte vectors versus UTF8 strings.
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
     6
*/
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
     7
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
     8
package isabelle
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
     9
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    10
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    11
import java.io.{File => JFile, OutputStream, FileInputStream}
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    12
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    13
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    14
object Bytes
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    15
{
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    16
  val empty: Bytes = new Bytes(Array[Byte](), 0, 0)
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    17
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    18
  def apply(s: CharSequence): Bytes =
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    19
  {
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    20
    val str = s.toString
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    21
    if (str.isEmpty) empty
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    22
    else {
54442
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    23
      val b = str.getBytes(UTF8.charset)
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    24
      new Bytes(b, 0, b.length)
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    25
    }
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    26
  }
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    27
54442
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    28
  def apply(a: Array[Byte], offset: Int, length: Int): Bytes =
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    29
    if (length == 0) empty
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    30
    else {
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    31
      val b = new Array[Byte](length)
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    32
      java.lang.System.arraycopy(a, offset, b, 0, length)
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    33
      new Bytes(b, 0, b.length)
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    34
    }
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    35
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    36
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    37
  /* read */
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    38
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    39
  def read(file: JFile): Bytes =
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    40
  {
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    41
    var i = 0
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    42
    var m = 0
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    43
    val n = file.length.toInt
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    44
    val bytes = new Array[Byte](n)
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    45
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    46
    val stream = new FileInputStream(file)
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    47
    try {
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    48
      do {
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    49
        m = stream.read(bytes, i, n - i)
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    50
        if (m != -1) i += m
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    51
      } while (m != -1 && n > i)
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    52
    }
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    53
    finally { stream.close }
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    54
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    55
    new Bytes(bytes, 0, bytes.length)
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    56
  }
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    57
}
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    58
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    59
final class Bytes private(
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    60
  protected val bytes: Array[Byte],
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    61
  protected val offset: Int,
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    62
  val length: Int)
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    63
{
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    64
  /* equality */
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    65
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    66
  override def equals(that: Any): Boolean =
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    67
  {
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    68
    that match {
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    69
      case other: Bytes =>
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    70
        if (this eq other) true
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    71
        else if (length != other.length) false
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    72
        else (0 until length).forall(i => bytes(offset + i) == other.bytes(other.offset + i))
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    73
      case _ => false
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    74
    }
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    75
  }
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    76
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    77
  private lazy val hash: Int =
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    78
  {
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    79
    var h = 0
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    80
    for (i <- offset until offset + length) {
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    81
      val b = bytes(i).asInstanceOf[Int] & 0xFF
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    82
      h = 31 * h + b
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    83
    }
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    84
    h
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    85
  }
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    86
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    87
  override def hashCode(): Int = hash
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    88
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    89
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    90
  /* content */
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    91
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    92
  def sha1_digest: SHA1.Digest = SHA1.digest(bytes)
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    93
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    94
  override def toString: String = new String(bytes, offset, length, UTF8.charset)
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    95
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    96
  def isEmpty: Boolean = length == 0
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    97
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    98
  def +(other: Bytes): Bytes =
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    99
    if (other.isEmpty) this
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
   100
    else if (isEmpty) other
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   101
    else {
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   102
      val new_bytes = new Array[Byte](length + other.length)
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   103
      java.lang.System.arraycopy(bytes, offset, new_bytes, 0, length)
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   104
      java.lang.System.arraycopy(other.bytes, other.offset, new_bytes, length, other.length)
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   105
      new Bytes(new_bytes, 0, new_bytes.length)
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   106
    }
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
   107
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
   108
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
   109
  /* write */
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
   110
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
   111
  def write(stream: OutputStream): Unit = stream.write(bytes, offset, length)
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   112
}
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   113