val array_size: Long = Int.MaxValue - 8 // see java.io.InputStream.MAX_BUFFER_SIZE val string_size: Long = Int.MaxValue / 2 val block_size: Int = 16384 // see java.io.InputStream.DEFAULT_BUFFER_SIZE val chunk_size: Long = Space.MiB(100).bytes
class Too_Large(size: Long, limit: Long) extends IndexOutOfBoundsException { overridedef getMessage: String = "Bytes too large for particular operation: " +
Space.bytes(size).print + " > " + Space.bytes(limit).print
}
/* main constructors */
val empty: Bytes = new Bytes(None, new Array(0), 0L, 0L)
def read_stream(stream: InputStream, limit: Long = -1L, hint: Long = 0L): Bytes = { if (limit == 0) empty else {
Builder.use(hint = if (limit > 0) limit else hint) { builder => val buf_size = block_size val buf = new Array[Byte](block_size) var m = 0 var n = 0L while ({ val l = if (limit > 0) (limit - n).min(buf_size).toInt else buf_size
m = stream.read(buf, 0, l) if (m > 0) {
builder += (buf, 0, m)
n += m
}
m != -1 && (limit < 0 || limit > n)
}) ()
}
}
}
def read_file(path: Path, offset: Long = 0L, limit: Long = -1L): Bytes = { val length = File.size(path) val start = offset.max(0L) val len = (length - start).max(0L).min(if (limit < 0) Long.MaxValue else limit) if (len == 0L) empty else {
Builder.use(hint = len) { builder =>
using(FileChannel.open(path.java_path, StandardOpenOption.READ)) { channel =>
channel.position(start) val buf_size = block_size val buf = ByteBuffer.allocate(buf_size) var m = 0 var n = 0L while ({ val l = (len - n).min(buf_size).toInt
buf.limit(l)
m = channel.read(buf) if (m > 0) {
builder += (buf.array(), 0, m)
buf.clear()
n += m
}
m != -1 && len > n
}) ()
}
}
}
}
privatevar buffer_list: mutable.ListBuffer[Array[Byte]] = null privatevar buffer = new Array[Byte](if (hint <= 0) 1024 else (hint min chunk_size min array_size).toInt) privatevar buffer_index = 0 privatevar buffer_total = 0
privatedef buffer_content(): Array[Byte] = if (buffer_list != null) { val array = new Array[Byte](buffer_total) var i = 0 for (b <- buffer_list) { val n = b.length
System.arraycopy(b, 0, array, i, n)
i += n
}
System.arraycopy(buffer, 0, array, i, buffer_index)
array
} elseif (buffer_index == buffer.length) buffer else Arrays.copyOf(buffer, buffer_index)
privatedef buffer_check(request: Int = 0): Unit = if (buffer_index == buffer.length) { if (buffer_total == chunk_size) {
chunks += buffer_content()
buffer_list = null
buffer = new Array[Byte](chunk_size.toInt)
buffer_total = 0
buffer_index = 0
} else { if (buffer_list == null) { buffer_list = new mutable.ListBuffer }
buffer_list += buffer
buffer_index = 0 val limit = (chunk_size - buffer_total).toInt
buffer = new Array[Byte]((buffer_total max request) min limit)
}
}
def += (b: Byte): Unit = {
buffer(buffer_index) = b
buffer_total += 1
buffer_index += 1
buffer_check()
}
def += (array: Array[Byte], offset: Int, length: Int): Unit = { if (offset < 0 || length < 0 || offset.toLong + length.toLong > array.length) { thrownew IndexOutOfBoundsException
} else { var i = offset var n = length while (n > 0) { val l = n min (buffer.length - buffer_index)
System.arraycopy(array, i, buffer, buffer_index, l)
buffer_total += l
buffer_index += l
i += l
n -= l
buffer_check(request = n)
}
}
}
def += (s: String): Unit = if (s.length > 0) { builder += UTF8.bytes(s) }
protecteddef byte_unchecked(i: Long): Byte = { val a = offset + i
chunks match { case None => chunk0(a.toInt) case Some(cs) => val b = a % Bytes.chunk_size val c = a / Bytes.chunk_size if (c < cs.length) cs(c.toInt)(b.toInt) else chunk0(b.toInt)
}
}
// signed byte def byte(i: Long): Byte = if (0 <= i && i < size) byte_unchecked(i) elsethrownew IndexOutOfBoundsException
lazyval sha1_digest: SHA1.Digest = if (is_empty) SHA1.digest_empty else {
SHA1.make_digest { sha => for (a <- subarray_iterator if a.length > 0) {
sha.update(a.array, a.offset, a.length)
}
}
}
overridedef hashCode(): Int = sha1_digest.hashCode()
overridedef equals(that: Any): Boolean = {
that match { case other: Bytes => if (bytes.eq(other)) true elseif (size != other.size) false else { if (chunks.isEmpty && other.chunks.isEmpty) {
Arrays.equals(chunk0, offset.toInt, (offset + size).toInt,
other.chunk0, other.offset.toInt, (other.offset + other.size).toInt)
} elseif (!is_sliced && !other.is_sliced) {
(subarray_iterator zip other.subarray_iterator)
.forall((a, b) => Arrays.equals(a.array, b.array))
} else sha1_digest == other.sha1_digest
} case _ => false
}
}
/* content */
def + (other: Bytes): Bytes = if (other.is_empty) bytes elseif (is_empty) other else {
Bytes.Builder.use(hint = size + other.size) { builder => for (a <- subarray_iterator ++ other.subarray_iterator) {
builder += a
}
}
}
def make_array: Array[Byte] = { val n = if (size <= Bytes.array_size) size.toInt elsethrownew Bytes.Too_Large(size, Bytes.array_size) val buf = new ByteArrayOutputStream(n) for (a <- subarray_iterator) { buf.write(a.array, a.offset, a.length) }
buf.toByteArray
}
def text: String = if (is_empty) "" else { val reader = new InputStreamReader(stream(), UTF8.charset) val buf = new Array[Char]((size min Bytes.string_size).toInt + 1) var m = 0 var n = 0 while (m >= 0 && n < buf.length) {
m = reader.read(buf, n, (buf.length - n) min Bytes.block_size) if (m > 0) { n += m }
}
require(m == -1, "Malformed UTF-8 string: overlong result") new String(buf, 0, n)
}
def wellformed_text: Option[String] = try { val s = text if (bytes == Bytes(s)) Some(s) else None
} catch { case ERROR(_) => None }
def decode_base64: Bytes =
using(Base64.decode_stream(stream()))(Bytes.read_stream(_, hint = (size / 1.2).round))
def maybe_encode_base64: (Boolean, String) =
wellformed_text match { case Some(s) => (false, s) case None => (true, encode_base64.text)
}
/* streams */
def stream(): InputStream = if (chunks.isEmpty) new ByteArrayInputStream(chunk0, offset.toInt, size.toInt) else { new InputStream { privatevar index = 0L
def read(): Int = { if (index < size) { val res = byte_unchecked(index).toInt & 0xff
index += 1
res
} else -1
}
overridedef read(buffer: Array[Byte], start: Int, length: Int): Int = { if (length < 16) super.read(buffer, start, length) else { val index0 = index
index = (index + length) min size val n = (index - index0).toInt if (n == 0) -1 else { var i = start for (a <- slice(index0, index).subarray_iterator) { val l = a.length if (l > 0) {
System.arraycopy(a.array, a.offset, buffer, i, l)
i += l
}
}
n
}
}
}
}
}
def write_stream(stream: OutputStream): Unit = for (a <- subarray_iterator if a.length > 0) {
stream.write(a.array, a.offset, a.length)
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.