equal
deleted
inserted
replaced
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 { |