src/Pure/General/bytes.scala
author wenzelm
Sun, 04 Sep 2016 17:38:22 +0200
changeset 63779 9da65bc75610
parent 62527 aae9a2a855e0
child 64001 7ecb22be8f03
permissions -rw-r--r--
more operations;
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 {
62527
aae9a2a855e0 tuned signature;
wenzelm
parents: 60833
diff changeset
    23
      val b = UTF8.bytes(str)
54442
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
63779
9da65bc75610 more operations;
wenzelm
parents: 62527
diff changeset
    28
  def apply(a: Array[Byte]): Bytes = apply(a, 0, a.length)
9da65bc75610 more operations;
wenzelm
parents: 62527
diff changeset
    29
54442
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    30
  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
    31
    if (length == 0) empty
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    32
    else {
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    33
      val b = new Array[Byte](length)
55618
995162143ef4 tuned imports;
wenzelm
parents: 54512
diff changeset
    34
      System.arraycopy(a, offset, b, 0, length)
54442
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    35
      new Bytes(b, 0, b.length)
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    36
    }
c39972ddd672 more specific Protocol_Output: empty message.body, main content via bytes/text;
wenzelm
parents: 54440
diff changeset
    37
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    38
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    39
  /* read */
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    40
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    41
  def read(file: JFile): Bytes =
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    42
  {
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    43
    var i = 0
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    44
    var m = 0
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    45
    val n = file.length.toInt
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    46
    val bytes = new Array[Byte](n)
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    47
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    48
    val stream = new FileInputStream(file)
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    49
    try {
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    50
      do {
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    51
        m = stream.read(bytes, i, n - i)
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    52
        if (m != -1) i += m
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    53
      } while (m != -1 && n > i)
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    54
    }
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    55
    finally { stream.close }
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    56
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    57
    new Bytes(bytes, 0, bytes.length)
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    58
  }
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    59
}
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    60
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    61
final class Bytes private(
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    62
  protected val bytes: Array[Byte],
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    63
  protected val offset: Int,
60833
d201996f72a8 provide CharSequence operations as well;
wenzelm
parents: 55618
diff changeset
    64
  val length: Int) extends CharSequence
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    65
{
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    66
  /* equality */
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    67
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    68
  override def equals(that: Any): Boolean =
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    69
  {
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    70
    that match {
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    71
      case other: Bytes =>
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    72
        if (this eq other) true
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    73
        else if (length != other.length) false
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    74
        else (0 until length).forall(i => bytes(offset + i) == other.bytes(other.offset + i))
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    75
      case _ => false
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    76
    }
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    77
  }
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    78
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    79
  private lazy val hash: Int =
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    80
  {
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    81
    var h = 0
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    82
    for (i <- offset until offset + length) {
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    83
      val b = bytes(i).asInstanceOf[Int] & 0xFF
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    84
      h = 31 * h + b
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    85
    }
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    86
    h
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    87
  }
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    88
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    89
  override def hashCode(): Int = hash
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    90
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    91
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    92
  /* content */
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    93
54512
7a92ed889da4 persistent value;
wenzelm
parents: 54444
diff changeset
    94
  lazy val sha1_digest: SHA1.Digest = SHA1.digest(bytes)
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    95
54444
a2290f36d1d6 prefer UTF8.decode_permissive;
wenzelm
parents: 54442
diff changeset
    96
  override def toString: String =
a2290f36d1d6 prefer UTF8.decode_permissive;
wenzelm
parents: 54442
diff changeset
    97
    UTF8.decode_chars(s => s, bytes, offset, offset + length).toString
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
    98
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
    99
  def isEmpty: Boolean = length == 0
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   100
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   101
  def +(other: Bytes): Bytes =
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
   102
    if (other.isEmpty) this
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
   103
    else if (isEmpty) other
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   104
    else {
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   105
      val new_bytes = new Array[Byte](length + other.length)
55618
995162143ef4 tuned imports;
wenzelm
parents: 54512
diff changeset
   106
      System.arraycopy(bytes, offset, new_bytes, 0, length)
995162143ef4 tuned imports;
wenzelm
parents: 54512
diff changeset
   107
      System.arraycopy(other.bytes, other.offset, new_bytes, length, other.length)
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   108
      new Bytes(new_bytes, 0, new_bytes.length)
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   109
    }
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
   110
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
   111
60833
d201996f72a8 provide CharSequence operations as well;
wenzelm
parents: 55618
diff changeset
   112
  /* CharSequence operations */
d201996f72a8 provide CharSequence operations as well;
wenzelm
parents: 55618
diff changeset
   113
d201996f72a8 provide CharSequence operations as well;
wenzelm
parents: 55618
diff changeset
   114
  def charAt(i: Int): Char =
d201996f72a8 provide CharSequence operations as well;
wenzelm
parents: 55618
diff changeset
   115
    if (0 <= i && i < length) (bytes(offset + i).asInstanceOf[Int] & 0xFF).asInstanceOf[Char]
d201996f72a8 provide CharSequence operations as well;
wenzelm
parents: 55618
diff changeset
   116
    else throw new IndexOutOfBoundsException
d201996f72a8 provide CharSequence operations as well;
wenzelm
parents: 55618
diff changeset
   117
d201996f72a8 provide CharSequence operations as well;
wenzelm
parents: 55618
diff changeset
   118
  def subSequence(i: Int, j: Int): Bytes =
d201996f72a8 provide CharSequence operations as well;
wenzelm
parents: 55618
diff changeset
   119
  {
d201996f72a8 provide CharSequence operations as well;
wenzelm
parents: 55618
diff changeset
   120
    if (0 <= i && i <= j && j <= length) new Bytes(bytes, offset + i, j - i)
d201996f72a8 provide CharSequence operations as well;
wenzelm
parents: 55618
diff changeset
   121
    else throw new IndexOutOfBoundsException
d201996f72a8 provide CharSequence operations as well;
wenzelm
parents: 55618
diff changeset
   122
  }
d201996f72a8 provide CharSequence operations as well;
wenzelm
parents: 55618
diff changeset
   123
d201996f72a8 provide CharSequence operations as well;
wenzelm
parents: 55618
diff changeset
   124
54440
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
   125
  /* write */
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
   126
2c4940d2edf7 tuned signature;
wenzelm
parents: 54439
diff changeset
   127
  def write(stream: OutputStream): Unit = stream.write(bytes, offset, length)
54439
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   128
}
621a155c7715 immutable byte vectors versus UTF8 strings;
wenzelm
parents:
diff changeset
   129