clarified signature: more general operation Bytes.read_slice;
authorwenzelm
Sun, 26 Mar 2023 14:24:38 +0200
changeset 77711 25fd62cba347
parent 77710 b8b01343e3df
child 77712 dd4bb80dbc3a
clarified signature: more general operation Bytes.read_slice;
src/Pure/General/bytes.scala
src/Pure/ML/ml_heap.scala
--- a/src/Pure/General/bytes.scala	Sun Mar 26 12:53:53 2023 +0200
+++ b/src/Pure/General/bytes.scala	Sun Mar 26 14:24:38 2023 +0200
@@ -9,6 +9,9 @@
 
 import java.io.{ByteArrayInputStream, ByteArrayOutputStream, FileInputStream, FileOutputStream, InputStream, OutputStream, File as JFile}
 import java.net.URL
+import java.nio.ByteBuffer
+import java.nio.channels.FileChannel
+import java.nio.file.StandardOpenOption
 import org.tukaani.xz
 import com.github.luben.zstd
 
@@ -75,6 +78,28 @@
 
   def read(url: URL): Bytes = using(url.openStream)(read_stream(_))
 
+  def read_slice(path: Path, offset: Long = 0L, limit: Long = Long.MaxValue): Bytes = {
+    val start = offset.max(0L)
+    val len = (path.file.length - start).max(0L).min(limit)
+    if (len > Integer.MAX_VALUE) error("Cannot read large file slice: " + Space.bytes(len).print)
+    else if (len == 0L) empty
+    else {
+      using(FileChannel.open(path.java_path, StandardOpenOption.READ)) { file =>
+        file.position(start)
+        val n = len.toInt
+        val buf = ByteBuffer.allocate(n)
+        var i = 0
+        var m = 0
+        while ({
+          m = file.read(buf)
+          if (m != -1) i += m
+          m != -1 && n > i
+        }) ()
+        new Bytes(buf.array, 0, i)
+      }
+    }
+  }
+
 
   /* write */
 
--- a/src/Pure/ML/ml_heap.scala	Sun Mar 26 12:53:53 2023 +0200
+++ b/src/Pure/ML/ml_heap.scala	Sun Mar 26 14:24:38 2023 +0200
@@ -19,30 +19,16 @@
 
   def read_digest(heap: Path): Option[SHA1.Digest] = {
     if (heap.is_file) {
-      using(FileChannel.open(heap.java_path, StandardOpenOption.READ)) { file =>
-        val len = file.size
-        val n = sha1_prefix.length + SHA1.digest_length
-        if (len >= n) {
-          file.position(len - n)
-
-          val buf = ByteBuffer.allocate(n)
-          var i = 0
-          var m = 0
-          while ({
-            m = file.read(buf)
-            if (m != -1) i += m
-            m != -1 && n > i
-          }) ()
-
-          if (i == n) {
-            val prefix = new String(buf.array(), 0, sha1_prefix.length, UTF8.charset)
-            val s = new String(buf.array(), sha1_prefix.length, SHA1.digest_length, UTF8.charset)
-            if (prefix == sha1_prefix) Some(SHA1.fake_digest(s)) else None
-          }
-          else None
-        }
+      val l = sha1_prefix.length
+      val m = l + SHA1.digest_length
+      val n = heap.file.length
+      val bs = Bytes.read_slice(heap, offset = n - m)
+      if (bs.length == m) {
+        val s = bs.text
+        if (s.startsWith(sha1_prefix)) Some(SHA1.fake_digest(s.substring(l)))
         else None
       }
+      else None
     }
     else None
   }