src/Pure/General/bytes.scala
changeset 80508 8585399f26f6
parent 80503 d59cc10a6888
child 80509 2a9abd6a164e
equal deleted inserted replaced
80507:8e4731a2a041 80508:8585399f26f6
     6 
     6 
     7 package isabelle
     7 package isabelle
     8 
     8 
     9 
     9 
    10 import java.io.{ByteArrayInputStream, ByteArrayOutputStream, FileInputStream, FileOutputStream,
    10 import java.io.{ByteArrayInputStream, ByteArrayOutputStream, FileInputStream, FileOutputStream,
    11   InputStream, OutputStream, File => JFile}
    11   InputStreamReader, InputStream, OutputStream, File => JFile}
    12 import java.nio.ByteBuffer
    12 import java.nio.ByteBuffer
    13 import java.nio.charset.StandardCharsets.ISO_8859_1
    13 import java.nio.charset.StandardCharsets.ISO_8859_1
    14 import java.nio.channels.FileChannel
    14 import java.nio.channels.FileChannel
    15 import java.nio.file.StandardOpenOption
    15 import java.nio.file.StandardOpenOption
    16 import java.util.Arrays
    16 import java.util.Arrays
    23 
    23 
    24 object Bytes {
    24 object Bytes {
    25   /* internal sizes */
    25   /* internal sizes */
    26 
    26 
    27   private val array_size: Long = Int.MaxValue - 8  // see java.io.InputStream.MAX_BUFFER_SIZE
    27   private val array_size: Long = Int.MaxValue - 8  // see java.io.InputStream.MAX_BUFFER_SIZE
       
    28   private val string_size: Long = Int.MaxValue / 2
    28   private val block_size: Int = 16384  // see java.io.InputStream.DEFAULT_BUFFER_SIZE
    29   private val block_size: Int = 16384  // see java.io.InputStream.DEFAULT_BUFFER_SIZE
    29   private val chunk_size: Long = Space.MiB(100).bytes
    30   private val chunk_size: Long = Space.MiB(100).bytes
    30 
    31 
    31   private def make_size(chunks: Array[Array[Byte]], buffer: Array[Byte]): Long =
    32   private def make_size(chunks: Array[Array[Byte]], buffer: Array[Byte]): Long =
    32     chunks.foldLeft(buffer.length.toLong)((n, chunk) => n + chunk.length)
    33     chunks.foldLeft(buffer.length.toLong)((n, chunk) => n + chunk.length)
   481     val buf = new ByteArrayOutputStream(small_size)
   482     val buf = new ByteArrayOutputStream(small_size)
   482     for (a <- subarray_iterator) { buf.write(a.array, a.offset, a.length) }
   483     for (a <- subarray_iterator) { buf.write(a.array, a.offset, a.length) }
   483     buf.toByteArray
   484     buf.toByteArray
   484   }
   485   }
   485 
   486 
   486   override def text: String =
   487   def text: String =
   487     if (is_empty) ""
   488     if (is_empty) ""
   488     else {
   489     else {
   489       var i = 0L
   490       val reader = new InputStreamReader(stream(), UTF8.charset)
   490       var utf8 = false
   491       val buf = new Array[Char]((size min Bytes.string_size).toInt + 1)
   491       while (i < size && !utf8) {
   492       var m = 0
   492         if (byte_unchecked(i) < 0) { utf8 = true }
   493       var n = 0
   493         i += 1
   494       while (m >= 0 && n < buf.length) {
   494       }
   495         m = reader.read(buf, n, (buf.length - n) min Bytes.block_size)
   495       utf8
   496         if (m > 0) { n += m }
   496 
   497       }
   497       if (utf8) UTF8.decode_permissive(bytes)
   498       require(m == -1, "Malformed UTF-8 string: overlong result")
   498       else new String(make_array, UTF8.charset)
   499       new String(buf, 0, n)
   499     }
   500     }
   500 
   501 
   501   def wellformed_text: Option[String] =
   502   def wellformed_text: Option[String] =
   502     try {
   503     try {
   503       val s = text
   504       val s = text