src/Pure/General/bytes.scala
changeset 80492 43323d886ea3
parent 80491 b439582efc8a
child 80493 d334f158442b
equal deleted inserted replaced
80491:b439582efc8a 80492:43323d886ea3
     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   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.channels.FileChannel
    14 import java.nio.channels.FileChannel
    14 import java.nio.file.StandardOpenOption
    15 import java.nio.file.StandardOpenOption
    15 import java.util.Arrays
    16 import java.util.Arrays
    16 import org.tukaani.xz
    17 import org.tukaani.xz
    17 import com.github.luben.zstd
    18 import com.github.luben.zstd
    42   private def reuse_array(bytes: Array[Byte]): Bytes =
    43   private def reuse_array(bytes: Array[Byte]): Bytes =
    43     if (bytes.length <= chunk_size) new Bytes(None, bytes, 0L, bytes.length.toLong)
    44     if (bytes.length <= chunk_size) new Bytes(None, bytes, 0L, bytes.length.toLong)
    44     else apply(bytes)
    45     else apply(bytes)
    45 
    46 
    46   val empty: Bytes = reuse_array(new Array(0))
    47   val empty: Bytes = reuse_array(new Array(0))
       
    48 
       
    49   def raw(s: String): Bytes =
       
    50     if (s.isEmpty) empty
       
    51     else Builder.use(hint = s.length) { builder => builder += s.getBytes(ISO_8859_1) }
    47 
    52 
    48   def apply(s: String): Bytes =
    53   def apply(s: String): Bytes =
    49     if (s.isEmpty) empty
    54     if (s.isEmpty) empty
    50     else Builder.use(hint = s.length) { builder => builder += s }
    55     else Builder.use(hint = s.length) { builder => builder += s }
    51 
    56 
   129     using(new FileOutputStream(file, true))(bytes.write_stream(_))
   134     using(new FileOutputStream(file, true))(bytes.write_stream(_))
   130 
   135 
   131   def append(path: Path, bytes: Bytes): Unit = append(path.file, bytes)
   136   def append(path: Path, bytes: Bytes): Unit = append(path.file, bytes)
   132 
   137 
   133 
   138 
   134   /* vector of short unsigned integers */
       
   135 
       
   136   trait Vec {
       
   137     def size: Long
       
   138     def apply(i: Long): Char
       
   139   }
       
   140 
       
   141   class Vec_String(string: String) extends Vec {
       
   142     override def size: Long = string.length.toLong
       
   143     override def apply(i: Long): Char =
       
   144       if (0 <= i && i < size) string(i.toInt)
       
   145       else throw new IndexOutOfBoundsException
       
   146   }
       
   147 
       
   148 
       
   149   /* incremental builder: unsynchronized! */
   139   /* incremental builder: unsynchronized! */
   150 
   140 
   151   object Builder {
   141   object Builder {
   152     def use(hint: Long = 0L)(body: Builder => Unit): Bytes = {
   142     def use(hint: Long = 0L)(body: Builder => Unit): Bytes = {
   153       val builder = new Builder(hint)
   143       val builder = new Builder(hint)
   292 final class Bytes private(
   282 final class Bytes private(
   293   protected val chunks: Option[Array[Array[Byte]]],
   283   protected val chunks: Option[Array[Array[Byte]]],
   294   protected val chunk0: Array[Byte],
   284   protected val chunk0: Array[Byte],
   295   protected val offset: Long,
   285   protected val offset: Long,
   296   val size: Long
   286   val size: Long
   297 ) extends Bytes.Vec with YXML.Source {
   287 ) extends YXML.Source {
   298   bytes =>
   288   bytes =>
   299 
   289 
   300   assert(
   290   assert(
   301     (chunks.isEmpty ||
   291     (chunks.isEmpty ||
   302       chunks.get.nonEmpty &&
   292       chunks.get.nonEmpty &&
   497         if (byte_unchecked(i) < 0) { utf8 = true }
   487         if (byte_unchecked(i) < 0) { utf8 = true }
   498         i += 1
   488         i += 1
   499       }
   489       }
   500       utf8
   490       utf8
   501 
   491 
   502       if (utf8) UTF8.decode_permissive_bytes(bytes)
   492       if (utf8) UTF8.decode_permissive(bytes)
   503       else new String(make_array, UTF8.charset)
   493       else new String(make_array, UTF8.charset)
   504     }
   494     }
   505 
   495 
   506   def wellformed_text: Option[String] =
   496   def wellformed_text: Option[String] =
   507     try {
   497     try {