summaryrefslogtreecommitdiff
path: root/runtime/nativeMain/src/kotlinx/io/Streams.kt
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/nativeMain/src/kotlinx/io/Streams.kt')
-rw-r--r--runtime/nativeMain/src/kotlinx/io/Streams.kt261
1 files changed, 261 insertions, 0 deletions
diff --git a/runtime/nativeMain/src/kotlinx/io/Streams.kt b/runtime/nativeMain/src/kotlinx/io/Streams.kt
new file mode 100644
index 00000000..23447439
--- /dev/null
+++ b/runtime/nativeMain/src/kotlinx/io/Streams.kt
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2018 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package kotlinx.io
+
+actual open class IOException actual constructor(message: String) : Exception(message) {
+ actual constructor() : this("IO Exception")
+}
+
+actual abstract class InputStream {
+
+ actual open fun available(): Int {
+ return 0
+ }
+
+ actual open fun close() {
+ /* empty */
+ }
+
+ actual abstract fun read(): Int
+
+ actual open fun read(b: ByteArray) = read(b, 0, b.size)
+
+ actual open fun read(b: ByteArray, offset: Int, len: Int): Int {
+ // Force null check for b first!
+ if (offset > b.size || offset < 0) {
+ throw IndexOutOfBoundsException()
+ }
+ if (len < 0 || len > b.size - offset) {
+ throw IndexOutOfBoundsException()
+ }
+ for (i in 0..len - 1) {
+ var c: Int
+ try {
+ c = read()
+ if (c == -1) {
+ return if (i == 0) -1 else i
+ }
+ } catch (e: IOException) {
+ if (i != 0) {
+ return i
+ }
+ throw e
+ }
+
+ b[offset + i] = c.toByte()
+ }
+ return len
+ }
+
+
+ actual open fun skip(n: Long): Long {
+ if (n <= 0) {
+ return 0
+ }
+ var skipped: Long = 0
+ var toRead = if (n < 4096) n.toInt() else 4096
+ // We are unsynchronized, so take a local copy of the skipBuf at some
+ // point in time.
+ var localBuf = skipBuf
+ if (localBuf == null || localBuf.size < toRead) {
+ // May be lazily written back to the static. No matter if it
+ // overwrites somebody else's store.
+ localBuf = ByteArray(toRead)
+ skipBuf = localBuf
+ }
+ while (skipped < n) {
+ val read = read(localBuf, 0, toRead)
+ if (read == -1) {
+ return skipped
+ }
+ skipped += read.toLong()
+ if (read < toRead) {
+ return skipped
+ }
+ if (n - skipped < toRead) {
+ toRead = (n - skipped).toInt()
+ }
+ }
+ return skipped
+ }
+
+ companion object {
+
+ private var skipBuf: ByteArray? = null
+ }
+}
+
+actual class ByteArrayInputStream : InputStream {
+
+ protected var buf: ByteArray
+ protected var pos: Int = 0
+ protected var mark: Int = 0
+ protected var count: Int = 0
+
+
+ actual constructor(buf: ByteArray) {
+ this.mark = 0
+ this.buf = buf
+ this.count = buf.size
+ }
+
+ constructor(buf: ByteArray, offset: Int, length: Int) {
+ this.buf = buf
+ pos = offset
+ mark = offset
+ count = if (offset + length > buf.size) buf.size else offset + length
+ }
+
+ override fun available(): Int {
+ return count - pos
+ }
+
+
+ actual override fun read(): Int {
+ return if (pos < count) buf[pos++].toInt() and 0xFF else -1
+ }
+
+ fun read(b: ByteArray?, offset: Int, len: Int): Int {
+ if (b == null) {
+ throw NullPointerException()
+ }
+ // avoid int overflow
+ if (offset < 0 || offset > b.size || len < 0
+ || len > b.size - offset) {
+ throw IndexOutOfBoundsException()
+ }
+ // Are there any bytes available?
+ if (this.pos >= this.count) {
+ return -1
+ }
+ if (len == 0) {
+ return 0
+ }
+
+ val copylen = if (this.count - pos < len) this.count - pos else len
+ arraycopy(buf, pos, b, offset, copylen)
+ pos += copylen
+ return copylen
+ }
+
+ override fun skip(n: Long): Long {
+ if (n <= 0) {
+ return 0
+ }
+ val temp = pos
+ pos = if (this.count - pos < n) this.count else (pos + n).toInt()
+ return (pos - temp).toLong()
+ }
+}
+
+
+actual abstract class OutputStream {
+ actual open fun close() {
+ /* empty */
+ }
+
+ actual open fun flush() {
+ /* empty */
+ }
+
+ actual open fun write(buffer: ByteArray) = write(buffer, 0, buffer.size)
+
+ actual open fun write(buffer: ByteArray, offset: Int, count: Int) {
+ // avoid int overflow, check null buffer
+ if (offset > buffer.size || offset < 0 || count < 0
+ || count > buffer.size - offset) {
+ throw IndexOutOfBoundsException()
+ }
+ for (i in offset..offset + count - 1) {
+ write(buffer[i].toInt())
+ }
+ }
+
+ actual abstract fun write(oneByte: Int)
+
+}
+
+actual class ByteArrayOutputStream : OutputStream {
+ protected var buf: ByteArray
+ protected var count: Int = 0
+
+ actual constructor() : super() {
+ buf = ByteArray(32)
+ }
+
+ constructor(size: Int) : super() {
+ if (size >= 0) {
+ buf = ByteArray(size)
+ } else {
+ throw IllegalArgumentException() //$NON-NLS-1$
+ }
+ }
+
+ private fun expand(i: Int) {
+ /* Can the buffer handle @i more bytes, if not expand it */
+ if (count + i <= buf.size) {
+ return
+ }
+
+ val newbuf = ByteArray((count + i) * 2)
+ arraycopy(buf, 0, newbuf, 0, count)
+ buf = newbuf
+ }
+
+ actual fun size(): Int {
+ return count
+ }
+
+ actual fun toByteArray(): ByteArray {
+ val newArray = ByteArray(count)
+ arraycopy(buf, 0, newArray, 0, count)
+ return newArray
+ }
+
+ override fun write(buffer: ByteArray, offset: Int, count: Int) {
+ // avoid int overflow
+ if (offset < 0 || offset > buffer.size || count < 0
+ || count > buffer.size - offset) {
+ throw IndexOutOfBoundsException() //$NON-NLS-1$
+ }
+ if (count == 0) {
+ return
+ }
+
+ /* Expand if necessary */
+ expand(count)
+ arraycopy(buffer, offset, buf, this.count, count)
+ this.count += count
+ }
+
+ actual override fun write(oneByte: Int) {
+ if (count == buf.size) {
+ expand(1)
+ }
+ buf[count++] = oneByte.toByte()
+ }
+
+ fun writeTo(out: OutputStream) {
+ out.write(buf, 0, count)
+ }
+}
+
+internal fun arraycopy(src: ByteArray, srcPos: Int, dst: ByteArray, dstPos: Int, len: Int) {
+ for (i in 0..len - 1) {
+ dst[dstPos + i] = src[srcPos + i]
+ }
+}