mirror of
https://github.com/JakeWharton/mosaic.git
synced 2025-10-28 20:53:42 +08:00
Standard stream reading and writing (#964)
This commit is contained in:
@ -2,9 +2,14 @@ public final class com/jakewharton/mosaic/tty/StandardStreams : java/lang/AutoCl
|
|||||||
public static final field Companion Lcom/jakewharton/mosaic/tty/StandardStreams$Companion;
|
public static final field Companion Lcom/jakewharton/mosaic/tty/StandardStreams$Companion;
|
||||||
public static final fun bind ()Lcom/jakewharton/mosaic/tty/StandardStreams;
|
public static final fun bind ()Lcom/jakewharton/mosaic/tty/StandardStreams;
|
||||||
public fun close ()V
|
public fun close ()V
|
||||||
|
public final fun interruptInputRead ()V
|
||||||
public final fun isErrorTty ()Z
|
public final fun isErrorTty ()Z
|
||||||
public final fun isInputTty ()Z
|
public final fun isInputTty ()Z
|
||||||
public final fun isOutputTty ()Z
|
public final fun isOutputTty ()Z
|
||||||
|
public final fun readInput ([BII)I
|
||||||
|
public final fun readInputWithTimeout ([BIII)I
|
||||||
|
public final fun writeError ([BII)I
|
||||||
|
public final fun writeOutput ([BII)I
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class com/jakewharton/mosaic/tty/StandardStreams$Companion {
|
public final class com/jakewharton/mosaic/tty/StandardStreams$Companion {
|
||||||
|
|||||||
@ -12,9 +12,14 @@ final class com.jakewharton.mosaic.tty/IOException : kotlin/Exception { // com.j
|
|||||||
|
|
||||||
final class com.jakewharton.mosaic.tty/StandardStreams : kotlin/AutoCloseable { // com.jakewharton.mosaic.tty/StandardStreams|null[0]
|
final class com.jakewharton.mosaic.tty/StandardStreams : kotlin/AutoCloseable { // com.jakewharton.mosaic.tty/StandardStreams|null[0]
|
||||||
final fun close() // com.jakewharton.mosaic.tty/StandardStreams.close|close(){}[0]
|
final fun close() // com.jakewharton.mosaic.tty/StandardStreams.close|close(){}[0]
|
||||||
|
final fun interruptInputRead() // com.jakewharton.mosaic.tty/StandardStreams.interruptInputRead|interruptInputRead(){}[0]
|
||||||
final fun isErrorTty(): kotlin/Boolean // com.jakewharton.mosaic.tty/StandardStreams.isErrorTty|isErrorTty(){}[0]
|
final fun isErrorTty(): kotlin/Boolean // com.jakewharton.mosaic.tty/StandardStreams.isErrorTty|isErrorTty(){}[0]
|
||||||
final fun isInputTty(): kotlin/Boolean // com.jakewharton.mosaic.tty/StandardStreams.isInputTty|isInputTty(){}[0]
|
final fun isInputTty(): kotlin/Boolean // com.jakewharton.mosaic.tty/StandardStreams.isInputTty|isInputTty(){}[0]
|
||||||
final fun isOutputTty(): kotlin/Boolean // com.jakewharton.mosaic.tty/StandardStreams.isOutputTty|isOutputTty(){}[0]
|
final fun isOutputTty(): kotlin/Boolean // com.jakewharton.mosaic.tty/StandardStreams.isOutputTty|isOutputTty(){}[0]
|
||||||
|
final fun readInput(kotlin/ByteArray, kotlin/Int, kotlin/Int): kotlin/Int // com.jakewharton.mosaic.tty/StandardStreams.readInput|readInput(kotlin.ByteArray;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final fun readInputWithTimeout(kotlin/ByteArray, kotlin/Int, kotlin/Int, kotlin/Int): kotlin/Int // com.jakewharton.mosaic.tty/StandardStreams.readInputWithTimeout|readInputWithTimeout(kotlin.ByteArray;kotlin.Int;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final fun writeError(kotlin/ByteArray, kotlin/Int, kotlin/Int): kotlin/Int // com.jakewharton.mosaic.tty/StandardStreams.writeError|writeError(kotlin.ByteArray;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
final fun writeOutput(kotlin/ByteArray, kotlin/Int, kotlin/Int): kotlin/Int // com.jakewharton.mosaic.tty/StandardStreams.writeOutput|writeOutput(kotlin.ByteArray;kotlin.Int;kotlin.Int){}[0]
|
||||||
|
|
||||||
final object Companion { // com.jakewharton.mosaic.tty/StandardStreams.Companion|null[0]
|
final object Companion { // com.jakewharton.mosaic.tty/StandardStreams.Companion|null[0]
|
||||||
final fun bind(): com.jakewharton.mosaic.tty/StandardStreams // com.jakewharton.mosaic.tty/StandardStreams.Companion.bind|bind(){}[0]
|
final fun bind(): com.jakewharton.mosaic.tty/StandardStreams // com.jakewharton.mosaic.tty/StandardStreams.Companion.bind|bind(){}[0]
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#if defined(__APPLE__) || defined(__linux__)
|
#if defined(__APPLE__) || defined(__linux__)
|
||||||
|
|
||||||
#include "mosaic-streams-posix.h"
|
#include "mosaic-streams-posix.h"
|
||||||
|
#include "mosaic-tty-posix.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -8,6 +9,8 @@
|
|||||||
|
|
||||||
typedef struct MosaicStreamsImpl {
|
typedef struct MosaicStreamsImpl {
|
||||||
int stdin;
|
int stdin;
|
||||||
|
int interrupt_stdin_reader;
|
||||||
|
int interrupt_stdin_writer;
|
||||||
int stdout;
|
int stdout;
|
||||||
int stderr;
|
int stderr;
|
||||||
} MosaicStreamsImpl;
|
} MosaicStreamsImpl;
|
||||||
@ -21,7 +24,15 @@ MosaicStreamsInitResult mosaic_streams_init_internal(int stdin, int stdout, int
|
|||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int interruptPipe[2];
|
||||||
|
if (unlikely(pipe(interruptPipe)) != 0) {
|
||||||
|
result.error = errno;
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
|
||||||
streams->stdin = stdin;
|
streams->stdin = stdin;
|
||||||
|
streams->interrupt_stdin_reader = interruptPipe[0];
|
||||||
|
streams->interrupt_stdin_writer = interruptPipe[1];
|
||||||
streams->stdout = stdout;
|
streams->stdout = stdout;
|
||||||
streams->stderr = stderr;
|
streams->stderr = stderr;
|
||||||
|
|
||||||
@ -29,6 +40,10 @@ MosaicStreamsInitResult mosaic_streams_init_internal(int stdin, int stdout, int
|
|||||||
|
|
||||||
ret:
|
ret:
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
err_free:
|
||||||
|
free(streams);
|
||||||
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
MosaicStreamsInitResult mosaic_streams_init() {
|
MosaicStreamsInitResult mosaic_streams_init() {
|
||||||
@ -60,6 +75,32 @@ MosaicStreamsTtyResult mosaic_streams_is_stderr_tty(MosaicStreams *streams) {
|
|||||||
return mosaic_streams_is_tty(streams->stderr);
|
return mosaic_streams_is_tty(streams->stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MosaicIoResult mosaic_streams_read_input(MosaicStreams *streams, uint8_t *buffer, int count) {
|
||||||
|
return tty_readInternal(streams->stdin, streams->interrupt_stdin_reader, buffer, count, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
MosaicIoResult mosaic_streams_read_input_with_timeout(MosaicStreams *streams, uint8_t *buffer, int count, int timeoutMillis) {
|
||||||
|
struct timeval timeout;
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = timeoutMillis * 1000;
|
||||||
|
|
||||||
|
return tty_readInternal(streams->stdin, streams->interrupt_stdin_reader, buffer, count, &timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t mosaic_streams_interrupt_input_read(MosaicStreams *streams) {
|
||||||
|
uint8_t space = ' ';
|
||||||
|
MosaicIoResult result = tty_writeInternal(streams->interrupt_stdin_writer, &space, 1);
|
||||||
|
return result.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
MosaicIoResult mosaic_streams_write_output(MosaicStreams *streams, uint8_t *buffer, int count) {
|
||||||
|
return tty_writeInternal(streams->stdout, buffer, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
MosaicIoResult mosaic_streams_write_error(MosaicStreams *streams, uint8_t *buffer, int count) {
|
||||||
|
return tty_writeInternal(streams->stderr, buffer, count);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t mosaic_streams_free(MosaicStreams *streams) {
|
uint32_t mosaic_streams_free(MosaicStreams *streams) {
|
||||||
free(streams);
|
free(streams);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
||||||
#include "mosaic-streams-windows.h"
|
#include "mosaic-streams-windows.h"
|
||||||
|
#include "mosaic-tty-windows.h"
|
||||||
|
|
||||||
typedef struct MosaicStreamsImpl {
|
typedef struct MosaicStreamsImpl {
|
||||||
HANDLE stdin;
|
HANDLE stdin;
|
||||||
|
HANDLE stdin_interrupt_event;
|
||||||
HANDLE stdout;
|
HANDLE stdout;
|
||||||
HANDLE stderr;
|
HANDLE stderr;
|
||||||
} MosaicStreamsImpl;
|
} MosaicStreamsImpl;
|
||||||
@ -17,7 +19,14 @@ MosaicStreamsInitResult mosaic_streams_init_internal(HANDLE stdin, HANDLE stdout
|
|||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HANDLE stdinInterruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
if (unlikely(stdinInterruptEvent == NULL)) {
|
||||||
|
result.error = GetLastError();
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
|
||||||
streams->stdin = stdin;
|
streams->stdin = stdin;
|
||||||
|
streams->stdin_interrupt_event = stdinInterruptEvent;
|
||||||
streams->stdout = stdout;
|
streams->stdout = stdout;
|
||||||
streams->stderr = stderr;
|
streams->stderr = stderr;
|
||||||
|
|
||||||
@ -25,6 +34,10 @@ MosaicStreamsInitResult mosaic_streams_init_internal(HANDLE stdin, HANDLE stdout
|
|||||||
|
|
||||||
ret:
|
ret:
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
err_free:
|
||||||
|
free(streams);
|
||||||
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOSAIC_EXPORT MosaicStreamsInitResult mosaic_streams_init() {
|
MOSAIC_EXPORT MosaicStreamsInitResult mosaic_streams_init() {
|
||||||
@ -76,9 +89,61 @@ MOSAIC_EXPORT MosaicStreamsTtyResult mosaic_streams_is_stderr_tty(MosaicStreams
|
|||||||
return mosaic_streams_is_tty(streams->stderr);
|
return mosaic_streams_is_tty(streams->stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOSAIC_EXPORT MosaicIoResult mosaic_streams_read_input(MosaicStreams *streams, uint8_t *buffer, int count) {
|
||||||
|
return mosaic_streams_read_input_with_timeout(streams, buffer, count, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
MOSAIC_EXPORT MosaicIoResult mosaic_streams_read_input_with_timeout(MosaicStreams *streams, uint8_t *buffer, int count, int timeoutMillis) {
|
||||||
|
MosaicIoResult result = {};
|
||||||
|
|
||||||
|
HANDLE waitHandles[2] = { streams->stdin, streams->stdin_interrupt_event };
|
||||||
|
|
||||||
|
DWORD waitResult = WaitForMultipleObjects(2, waitHandles, FALSE, timeoutMillis);
|
||||||
|
if (likely(waitResult == WAIT_OBJECT_0)) {
|
||||||
|
DWORD c;
|
||||||
|
if (!ReadFile(streams->stdin, buffer, count, &c, NULL)) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
result.count = c;
|
||||||
|
} else if (unlikely(waitResult == WAIT_FAILED)) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
// Else return a count of 0 because either:
|
||||||
|
// - The interrupt event was selected (which auto resets its state).
|
||||||
|
// - The user-supplied, non-infinite timeout ran out.
|
||||||
|
|
||||||
|
ret:
|
||||||
|
return result;
|
||||||
|
|
||||||
|
err:
|
||||||
|
result.error = GetLastError();
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOSAIC_EXPORT uint32_t mosaic_streams_interrupt_input_read(MosaicStreams *streams) {
|
||||||
|
return likely(SetEvent(streams->stdin_interrupt_event) != 0)
|
||||||
|
? 0
|
||||||
|
: GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
MOSAIC_EXPORT MosaicIoResult mosaic_streams_write_output(MosaicStreams *streams, uint8_t *buffer, int count) {
|
||||||
|
return tty_writeInternal(streams->stdout, buffer, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
MOSAIC_EXPORT MosaicIoResult mosaic_streams_write_error(MosaicStreams *streams, uint8_t *buffer, int count) {
|
||||||
|
return tty_writeInternal(streams->stderr, buffer, count);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t mosaic_streams_free(MosaicStreams *streams) {
|
uint32_t mosaic_streams_free(MosaicStreams *streams) {
|
||||||
|
DWORD result = 0;
|
||||||
|
|
||||||
|
if (unlikely(CloseHandle(streams->stdin_interrupt_event) == 0)) {
|
||||||
|
result = GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
free(streams);
|
free(streams);
|
||||||
return 0;
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -24,6 +24,13 @@ MOSAIC_EXPORT MosaicStreamsTtyResult mosaic_streams_is_stdin_tty(MosaicStreams *
|
|||||||
MOSAIC_EXPORT MosaicStreamsTtyResult mosaic_streams_is_stdout_tty(MosaicStreams *streams);
|
MOSAIC_EXPORT MosaicStreamsTtyResult mosaic_streams_is_stdout_tty(MosaicStreams *streams);
|
||||||
MOSAIC_EXPORT MosaicStreamsTtyResult mosaic_streams_is_stderr_tty(MosaicStreams *streams);
|
MOSAIC_EXPORT MosaicStreamsTtyResult mosaic_streams_is_stderr_tty(MosaicStreams *streams);
|
||||||
|
|
||||||
|
MOSAIC_EXPORT MosaicIoResult mosaic_streams_read_input(MosaicStreams *streams, uint8_t *buffer, int count);
|
||||||
|
MOSAIC_EXPORT MosaicIoResult mosaic_streams_read_input_with_timeout(MosaicStreams *streams, uint8_t *buffer, int count, int timeoutMillis);
|
||||||
|
MOSAIC_EXPORT uint32_t mosaic_streams_interrupt_input_read(MosaicStreams *streams);
|
||||||
|
|
||||||
|
MOSAIC_EXPORT MosaicIoResult mosaic_streams_write_output(MosaicStreams *streams, uint8_t *buffer, int count);
|
||||||
|
MOSAIC_EXPORT MosaicIoResult mosaic_streams_write_error(MosaicStreams *streams, uint8_t *buffer, int count);
|
||||||
|
|
||||||
MOSAIC_EXPORT uint32_t mosaic_streams_free(MosaicStreams *streams);
|
MOSAIC_EXPORT uint32_t mosaic_streams_free(MosaicStreams *streams);
|
||||||
|
|
||||||
#endif // MOSAIC_STREAMS_H
|
#endif // MOSAIC_STREAMS_H
|
||||||
|
|||||||
@ -176,11 +176,11 @@ MOSAIC_EXPORT uint32_t tty_interruptRead(MosaicTty *tty) {
|
|||||||
: GetLastError();
|
: GetLastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
MOSAIC_EXPORT MosaicIoResult tty_write(MosaicTty *tty, uint8_t *buffer, int count) {
|
MosaicIoResult tty_writeInternal(HANDLE h, uint8_t *buffer, int count) {
|
||||||
MosaicIoResult result = {};
|
MosaicIoResult result = {};
|
||||||
|
|
||||||
DWORD written;
|
DWORD written;
|
||||||
if (WriteFile(tty->conout_for_write, buffer, count, &written, NULL)) {
|
if (WriteFile(h, buffer, count, &written, NULL)) {
|
||||||
result.count = written;
|
result.count = written;
|
||||||
} else {
|
} else {
|
||||||
result.error = GetLastError();
|
result.error = GetLastError();
|
||||||
@ -189,6 +189,10 @@ MOSAIC_EXPORT MosaicIoResult tty_write(MosaicTty *tty, uint8_t *buffer, int coun
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOSAIC_EXPORT MosaicIoResult tty_write(MosaicTty *tty, uint8_t *buffer, int count) {
|
||||||
|
return tty_writeInternal(tty->conout_for_write, buffer, count);
|
||||||
|
}
|
||||||
|
|
||||||
MOSAIC_EXPORT uint32_t tty_enableRawMode(MosaicTty *tty) {
|
MOSAIC_EXPORT uint32_t tty_enableRawMode(MosaicTty *tty) {
|
||||||
uint32_t result = 0;
|
uint32_t result = 0;
|
||||||
|
|
||||||
|
|||||||
@ -28,4 +28,6 @@ MosaicTtyInitResult tty_initWithHandles(
|
|||||||
bool conoutForWriteFake
|
bool conoutForWriteFake
|
||||||
);
|
);
|
||||||
|
|
||||||
|
MosaicIoResult tty_writeInternal(HANDLE h, uint8_t *buffer, int count);
|
||||||
|
|
||||||
#endif // MOSAIC_TTY_WINDOWS_H
|
#endif // MOSAIC_TTY_WINDOWS_H
|
||||||
|
|||||||
@ -9,5 +9,12 @@ public expect class StandardStreams : AutoCloseable {
|
|||||||
public fun isOutputTty(): Boolean
|
public fun isOutputTty(): Boolean
|
||||||
public fun isErrorTty(): Boolean
|
public fun isErrorTty(): Boolean
|
||||||
|
|
||||||
|
public fun readInput(buffer: ByteArray, offset: Int, count: Int): Int
|
||||||
|
public fun readInputWithTimeout(buffer: ByteArray, offset: Int, count: Int, timeoutMillis: Int): Int
|
||||||
|
public fun interruptInputRead()
|
||||||
|
|
||||||
|
public fun writeOutput(buffer: ByteArray, offset: Int, count: Int): Int
|
||||||
|
public fun writeError(buffer: ByteArray, offset: Int, count: Int): Int
|
||||||
|
|
||||||
override fun close()
|
override fun close()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,17 @@ package com.jakewharton.mosaic.tty
|
|||||||
|
|
||||||
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_free
|
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_free
|
||||||
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_init
|
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_init
|
||||||
|
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_interrupt_input_read
|
||||||
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_is_stderr_tty
|
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_is_stderr_tty
|
||||||
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_is_stdin_tty
|
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_is_stdin_tty
|
||||||
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_is_stdout_tty
|
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_is_stdout_tty
|
||||||
|
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_read_input
|
||||||
|
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_read_input_with_timeout
|
||||||
|
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_write_error
|
||||||
|
import com.jakewharton.mosaic.tty.Libmosaic.mosaic_streams_write_output
|
||||||
import java.lang.foreign.Arena
|
import java.lang.foreign.Arena
|
||||||
import java.lang.foreign.MemorySegment
|
import java.lang.foreign.MemorySegment
|
||||||
|
import java.lang.foreign.ValueLayout
|
||||||
|
|
||||||
public class StandardStreams internal constructor(
|
public class StandardStreams internal constructor(
|
||||||
private var ptr: MemorySegment,
|
private var ptr: MemorySegment,
|
||||||
@ -57,6 +63,63 @@ public class StandardStreams internal constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
public fun readInput(buffer: ByteArray, offset: Int, count: Int): Int {
|
||||||
|
val segment = Libmosaic.LIBRARY_ARENA.allocate(count.toLong())
|
||||||
|
val result = mosaic_streams_read_input(Arena.global(), ptr, segment, count)
|
||||||
|
val error = MosaicIoResult.error(result)
|
||||||
|
if (error == 0) {
|
||||||
|
val read = MosaicIoResult.count(result)
|
||||||
|
MemorySegment.copy(segment, ValueLayout.JAVA_BYTE, 0L, buffer, offset, read)
|
||||||
|
return read
|
||||||
|
}
|
||||||
|
throwIoe(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
public fun readInputWithTimeout(buffer: ByteArray, offset: Int, count: Int, timeoutMillis: Int): Int {
|
||||||
|
val segment = Libmosaic.LIBRARY_ARENA.allocate(count.toLong())
|
||||||
|
val result = mosaic_streams_read_input_with_timeout(Arena.global(), ptr, segment, count, timeoutMillis)
|
||||||
|
val error = MosaicIoResult.error(result)
|
||||||
|
if (error == 0) {
|
||||||
|
val read = MosaicIoResult.count(result)
|
||||||
|
MemorySegment.copy(segment, ValueLayout.JAVA_BYTE, 0L, buffer, offset, read)
|
||||||
|
return read
|
||||||
|
}
|
||||||
|
throwIoe(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
public fun interruptInputRead() {
|
||||||
|
val error = mosaic_streams_interrupt_input_read(ptr)
|
||||||
|
if (error == 0) return
|
||||||
|
throwIoe(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
public fun writeOutput(buffer: ByteArray, offset: Int, count: Int): Int {
|
||||||
|
val segment = Libmosaic.LIBRARY_ARENA.allocate(count.toLong())
|
||||||
|
MemorySegment.copy(buffer, offset, segment, ValueLayout.JAVA_BYTE, 0, count)
|
||||||
|
val result = mosaic_streams_write_output(Arena.global(), ptr, segment, count)
|
||||||
|
val error = MosaicIoResult.error(result)
|
||||||
|
if (error == 0) {
|
||||||
|
return MosaicIoResult.count(result)
|
||||||
|
}
|
||||||
|
throwIoe(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
public fun writeError(buffer: ByteArray, offset: Int, count: Int): Int {
|
||||||
|
val segment = Libmosaic.LIBRARY_ARENA.allocate(count.toLong())
|
||||||
|
MemorySegment.copy(buffer, offset, segment, ValueLayout.JAVA_BYTE, 0, count)
|
||||||
|
val result = mosaic_streams_write_error(Arena.global(), ptr, segment, count)
|
||||||
|
val error = MosaicIoResult.error(result)
|
||||||
|
if (error == 0) {
|
||||||
|
return MosaicIoResult.count(result)
|
||||||
|
}
|
||||||
|
throwIoe(error)
|
||||||
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
val ptr = ptr
|
val ptr = ptr
|
||||||
if (ptr != MemorySegment.NULL) {
|
if (ptr != MemorySegment.NULL) {
|
||||||
|
|||||||
@ -13,6 +13,37 @@ final class Jni {
|
|||||||
|
|
||||||
static native boolean streamsErrorIsTty(long streamsPtr);
|
static native boolean streamsErrorIsTty(long streamsPtr);
|
||||||
|
|
||||||
|
static native int streamsReadInput(
|
||||||
|
long streamsPtr,
|
||||||
|
byte[] buffer,
|
||||||
|
int offset,
|
||||||
|
int count
|
||||||
|
);
|
||||||
|
|
||||||
|
static native int streamsReadInputWithTimeout(
|
||||||
|
long streamsPtr,
|
||||||
|
byte[] buffer,
|
||||||
|
int offset,
|
||||||
|
int count,
|
||||||
|
int timeout
|
||||||
|
);
|
||||||
|
|
||||||
|
static native void streamsInterruptInputRead(long streamsPtr);
|
||||||
|
|
||||||
|
static native int streamsWriteOutput(
|
||||||
|
long streamsPtr,
|
||||||
|
byte[] buffer,
|
||||||
|
int offset,
|
||||||
|
int count
|
||||||
|
);
|
||||||
|
|
||||||
|
static native int streamsWriteError(
|
||||||
|
long streamsPtr,
|
||||||
|
byte[] buffer,
|
||||||
|
int offset,
|
||||||
|
int count
|
||||||
|
);
|
||||||
|
|
||||||
static native void streamsFree(long streamsPtr);
|
static native void streamsFree(long streamsPtr);
|
||||||
|
|
||||||
static native long ttyCallbackInit(Tty.Callback callback);
|
static native long ttyCallbackInit(Tty.Callback callback);
|
||||||
|
|||||||
@ -25,6 +25,31 @@ public actual class StandardStreams internal constructor(
|
|||||||
return Jni.streamsErrorIsTty(ptr)
|
return Jni.streamsErrorIsTty(ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
public actual fun readInput(buffer: ByteArray, offset: Int, count: Int): Int {
|
||||||
|
return Jni.streamsReadInput(ptr, buffer, offset, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
public actual fun readInputWithTimeout(buffer: ByteArray, offset: Int, count: Int, timeoutMillis: Int): Int {
|
||||||
|
return Jni.streamsReadInputWithTimeout(ptr, buffer, offset, count, timeoutMillis)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
public actual fun interruptInputRead() {
|
||||||
|
return Jni.streamsInterruptInputRead(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
public actual fun writeOutput(buffer: ByteArray, offset: Int, count: Int): Int {
|
||||||
|
return Jni.streamsWriteOutput(ptr, buffer, offset, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
public actual fun writeError(buffer: ByteArray, offset: Int, count: Int): Int {
|
||||||
|
return Jni.streamsWriteError(ptr, buffer, offset, count)
|
||||||
|
}
|
||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
actual override fun close() {
|
actual override fun close() {
|
||||||
val ptr = ptr
|
val ptr = ptr
|
||||||
|
|||||||
@ -2,7 +2,9 @@ package com.jakewharton.mosaic.tty
|
|||||||
|
|
||||||
import kotlinx.cinterop.CValue
|
import kotlinx.cinterop.CValue
|
||||||
import kotlinx.cinterop.CValuesRef
|
import kotlinx.cinterop.CValuesRef
|
||||||
|
import kotlinx.cinterop.addressOf
|
||||||
import kotlinx.cinterop.useContents
|
import kotlinx.cinterop.useContents
|
||||||
|
import kotlinx.cinterop.usePinned
|
||||||
|
|
||||||
public actual class StandardStreams internal constructor(
|
public actual class StandardStreams internal constructor(
|
||||||
ptr: CValuesRef<MosaicStreams>,
|
ptr: CValuesRef<MosaicStreams>,
|
||||||
@ -32,6 +34,48 @@ public actual class StandardStreams internal constructor(
|
|||||||
public actual fun isOutputTty(): Boolean = mosaic_streams_is_stdout_tty(ptr).isTty
|
public actual fun isOutputTty(): Boolean = mosaic_streams_is_stdout_tty(ptr).isTty
|
||||||
public actual fun isErrorTty(): Boolean = mosaic_streams_is_stderr_tty(ptr).isTty
|
public actual fun isErrorTty(): Boolean = mosaic_streams_is_stderr_tty(ptr).isTty
|
||||||
|
|
||||||
|
public actual fun readInput(buffer: ByteArray, offset: Int, count: Int): Int {
|
||||||
|
buffer.asUByteArray().usePinned {
|
||||||
|
mosaic_streams_read_input(ptr, it.addressOf(offset), count).useContents {
|
||||||
|
if (error == 0U) return this.count
|
||||||
|
throwIoe(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public actual fun readInputWithTimeout(buffer: ByteArray, offset: Int, count: Int, timeoutMillis: Int): Int {
|
||||||
|
buffer.asUByteArray().usePinned {
|
||||||
|
mosaic_streams_read_input_with_timeout(ptr, it.addressOf(offset), count, timeoutMillis).useContents {
|
||||||
|
if (error == 0U) return this.count
|
||||||
|
throwIoe(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public actual fun interruptInputRead() {
|
||||||
|
val error = mosaic_streams_interrupt_input_read(ptr)
|
||||||
|
if (error == 0U) return
|
||||||
|
throwIoe(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
public actual fun writeOutput(buffer: ByteArray, offset: Int, count: Int): Int {
|
||||||
|
buffer.asUByteArray().usePinned {
|
||||||
|
mosaic_streams_write_output(ptr, it.addressOf(offset), count).useContents {
|
||||||
|
if (error == 0U) return this.count
|
||||||
|
throwIoe(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public actual fun writeError(buffer: ByteArray, offset: Int, count: Int): Int {
|
||||||
|
buffer.asUByteArray().usePinned {
|
||||||
|
mosaic_streams_write_error(ptr, it.addressOf(offset), count).useContents {
|
||||||
|
if (error == 0U) return this.count
|
||||||
|
throwIoe(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
actual override fun close() {
|
actual override fun close() {
|
||||||
ptr?.let {
|
ptr?.let {
|
||||||
mosaic_streams_free(it)
|
mosaic_streams_free(it)
|
||||||
|
|||||||
Reference in New Issue
Block a user