xref: /aosp_15_r20/external/leakcanary2/shark-hprof/src/main/java/shark/FileSourceProvider.kt (revision d9e8da70d8c9df9a41d7848ae506fb3115cae6e6)
1 package shark
2 
3 import java.io.File
4 import java.io.RandomAccessFile
5 import kotlin.math.min
6 import okio.Buffer
7 import okio.BufferedSource
8 import okio.Okio
9 
10 class FileSourceProvider(private val file: File) : DualSourceProvider {
openStreamingSourcenull11   override fun openStreamingSource(): BufferedSource = Okio.buffer(Okio.source(file.inputStream()))
12 
13   override fun openRandomAccessSource(): RandomAccessSource {
14 
15     val randomAccessFile = RandomAccessFile(file, "r")
16 
17     val arrayBuffer = ByteArray(500_000)
18 
19     return object : RandomAccessSource {
20       override fun read(
21         sink: Buffer,
22         position: Long,
23         byteCount: Long
24       ): Long {
25         val byteCountInt = byteCount.toInt()
26         randomAccessFile.seek(position)
27         var totalBytesRead = 0
28         val maxRead = arrayBuffer.size
29         while (totalBytesRead < byteCount) {
30           val toRead = min(byteCountInt - totalBytesRead, maxRead)
31           val bytesRead = randomAccessFile.read(arrayBuffer, 0, toRead)
32           if (bytesRead == -1) {
33             check(totalBytesRead != 0) {
34               "Did not expect to reach end of file after reading 0 bytes"
35             }
36             break
37           }
38           sink.write(arrayBuffer, 0, bytesRead)
39           totalBytesRead += bytesRead
40         }
41         return totalBytesRead.toLong()
42       }
43 
44       override fun close() {
45         try {
46           randomAccessFile.close()
47         } catch (ignored: Throwable) {
48           SharkLog.d(ignored) { "Failed to close file, ignoring" }
49         }
50       }
51     }
52   }
53 }
54 
55