if base <= 10 do fallthrough;
value *= ~~base;
- value += ~~(c - #char "A");
+ value += ~~((c - #char "A") + 10);
}
case #char "a" .. #char "z" {
if base <= 10 do fallthrough;
value *= ~~base;
- value += ~~(c - #char "a");
+ value += ~~((c - #char "a") + 10);
}
case #default do break break;
// Not possible to unread.
InvalidUnread :: 0x09;
+
+ // When reading from a stream, no data was read.
+ ReadPending :: 0x0a;
}
\ No newline at end of file
return .None;
}
+
read_bytes :: (use reader: ^Reader, bytes: [] u8) -> (i32, Error) {
n := bytes.count;
if n == 0 {
if reader_empty(reader) do return 0, reader_consume_error(reader);
if n >= buffer.count {
- error, n = stream_read(stream, bytes);
+ while true {
+ error, n = stream_read(stream, bytes);
+ if error != .ReadPending do break;
+ }
if n > 0 do last_byte = cast(i32) bytes[n - 1];
-
return n, reader_consume_error(reader);
}
+ }
- start, end = 0, 0;
- error, n = stream_read(stream, buffer);
- if n == 0 do return 0, reader_consume_error(reader);
- end += n;
+ write_index := 0;
+ while n > 0 {
+ if reader_read_next_chunk(reader) == .ReadPending {
+ return write_index, .ReadPending;
+ }
+
+ to_write := math.min(n, end);
+ memory.copy(bytes.data + write_index, buffer.data, to_write);
+ n -= to_write;
+ write_index += to_write;
+ start += to_write;
}
- memory.copy(bytes.data, buffer.data + start, n);
- start += n;
- last_byte = cast(i32) buffer[start - 1];
- return n, .None;
+ last_byte = cast(i32) bytes[bytes.count - 1];
+ return bytes.count, .None;
}
read_string :: (use reader: ^Reader, bytes := 1, allocator := context.allocator) -> str {
return n;
}
-read_line :: (use reader: ^Reader, consume_newline := true, allocator := context.allocator, inplace := false) -> str {
- reader_read_next_chunk(reader);
+read_line :: (use reader: ^Reader, consume_newline := true, allocator := context.allocator, inplace := false, shift_buffer := true) -> str {
+ if shift_buffer {
+ while reader_read_next_chunk(reader) == .ReadPending ---
+ }
count := start;
defer start = count;
return out;
}
-read_word :: (use reader: ^Reader, numeric_allowed := false, allocator := context.allocator, inplace := false) -> str {
+read_word :: (use reader: ^Reader, numeric_allowed := false, allocator := context.allocator, inplace := false, shift_buffer := true) -> str {
skip_whitespace(reader);
- reader_read_next_chunk(reader);
+ if shift_buffer {
+ while reader_read_next_chunk(reader) == .ReadPending ---
+ }
count := start;
defer start = count;
return out;
}
-read_until :: (use reader: ^Reader, until: u8, skip: u32 = 0, allocator := context.allocator, consume_end := false, inplace := false) -> str {
- reader_read_next_chunk(reader);
+read_until :: (use reader: ^Reader, until: u8, skip: u32 = 0, allocator := context.allocator, consume_end := false, inplace := false, shift_buffer := true) -> str {
+ if shift_buffer {
+ while reader_read_next_chunk(reader) == .ReadPending ---
+ }
count := start;
defer start = count;
// Try to re-read multiple times
for 16 {
err, n := stream_read(stream, buffer[end .. buffer.count]);
+ if err == .ReadPending {
+ error = err;
+ return err if end == 0 else .None;
+ }
+
end += n;
if err != .None {
if err == .EOF do done = true;
socket_recv :: (s: ^Socket, maxlen := 1024, allocator := context.allocator) -> [] u8 {
buffer := alloc.from_stack(maxlen);
- received := __net_recv(s.handle, .{ buffer, maxlen });
- if received < 0 { s.vtable = null; return .[]; }
+ would_block: bool;
+ received := __net_recv(s.handle, .{ buffer, maxlen }, ^would_block);
+ if received < 0 {
+ if !would_block do s.vtable = null;
+ return .[];
+ }
result := memory.make_slice(u8, received, allocator=allocator);
memory.copy(result.data, buffer, received);
}
socket_recv_into :: (s: ^Socket, buffer: [] u8) -> i32 {
- received := __net_recv(s.handle, buffer);
- if received < 0 { s.vtable = null; }
+ would_block: bool;
+ received := __net_recv(s.handle, buffer, ^would_block);
+ if received < 0 && !would_block do s.vtable = null;
+ if would_block do return 0;
+
return received;
}
read = (use s: ^Socket, buffer: [] u8) -> (io.Error, u32) {
if handle == 0 do return .BadFile, 0;
- bytes_read := __net_recv(handle, buffer);
- if bytes_read < 0 { s.vtable = null; }
+ would_block := false;
+ bytes_read := __net_recv(handle, buffer, ^would_block);
+ if bytes_read < 0 && !would_block do s.vtable = null;
+
+ if would_block do return .ReadPending, bytes_read;
+
return .None, bytes_read;
},
#package __net_accept :: (handle: Socket.Handle, out_address: ^Socket_Address.Handle) -> Socket.Handle ---
#package __net_connect :: (handle: Socket.Handle, host: str, port: u16) -> SocketError ---
#package __net_send :: (handle: Socket.Handle, data: [] u8) -> i32 ---
- #package __net_recv :: (handle: Socket.Handle, data: [] u8) -> i32 ---
+ #package __net_recv :: (handle: Socket.Handle, data: [] u8, async_would_block: ^bool) -> i32 ---
#package __net_poll_recv :: (handle: [] Socket.Handle, timeout: i32, out_recv_indicies: ^i32) -> i32 ---
#package __net_address_get_address :: (address: Socket_Address.Handle, out_buffer: [] u8) -> i32 ---
Revamping File System:
- [ ] runtime.fs should contain runtime specific file system API calls
- [ ] 'os.File' should effectily be 'os.FileStream' and FileStream should go away
+ [x] runtime.fs should contain runtime specific file system API calls
+ [x] 'os.File' should effectily be 'os.FileStream' and FileStream should go away
os.File :: struct {
use stream: io.Stream;
use data: runtime.fs.FileData;
}
- [ ] Most file functionality will be provided using the stream API.
+ [x] Most file functionality will be provided using the stream API.
// HACK HACK HACK
// There should need to be this much stuff in here, but because Wasmer doesn't ship a "wasmerdll.lib"
// file for windows, it is impossible for it to link successfully against the function provided in onyx.exe.
- // Therefore, we must serve as the linker and do this manually. Hopefully they that library file
+ // Therefore, we must serve as the linker and do this manually. Hopefully that library file will be
// shipped soon so this can go away...
char* (*wasm_memory_data)(wasm_memory_t *wasm_memory);
wasm_extern_t* (*wasm_extern_lookup_by_name)(wasm_module_t* module, wasm_instance_t* instance, const char* name);
return NULL;
}
-ONYX_DEF(__net_recv, (WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
+ONYX_DEF(__net_recv, (WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
+ *(i32 *) ONYX_PTR(params->data[3].of.i32) = 0;
+
#ifdef _BH_LINUX
// TODO: The flags at the end should be controllable.
int received = recv(params->data[0].of.i32, ONYX_PTR(params->data[1].of.i32), params->data[2].of.i32, 0);
results->data[0] = WASM_I32_VAL(received);
+
+ if (received < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ *(i32 *) ONYX_PTR(params->data[3].of.i32) = 1;
+ }
+ }
#endif
return NULL;
package openal
+use package core { cptr }
+
#library "onyx_openal"
ALCdevice :: #distinct u64
alcCaptureSamples :: (device: ALCdevice, buf: rawptr, samples: i32) -> void ---
// This returns a C-allocated string, which is not supported at the moment.
- // alGetString :: (device: ALCdevice, param:i32) -> cstr ---
- // alcGetString :: (device: ALCdevice, param:i32) -> cstr ---
+ alGetString :: (device: ALCdevice, param: i32) -> cptr(u8) ---
+ alcGetString :: (device: ALCdevice, param: i32) -> cptr(u8) ---
}
AL_FALSE :: 0
ONYX_DEF(alSpeedOfSound, (FLOAT), ()) { alDistanceModel(P(0, f32)); return NULL; }
ONYX_DEF(alGetError, (), (INT)) { results->data[0] = WASM_I32_VAL(alGetError()); return NULL; }
+ONYX_DEF(alGetString, (INT), (LONG)) {
+ wasm_val_init_ptr(&results->data[0], (void *) alGetString(P(0, i32)));
+ return NULL;
+}
ONYX_DEF(alcCreateContext, (LONG, PTR), (LONG)) { wasm_val_init_ptr(&results->data[0], alcCreateContext((ALCdevice *) P(0, i64), ONYX_PTR(P(1, i32)))); return NULL; }
ONYX_DEF(alcMakeContextCurrent, (LONG), (BOOL)) { results->data[0] = WASM_I32_VAL(alcMakeContextCurrent((ALCcontext *) P(0, i64))); return NULL; }
ONYX_DEF(alcCaptureStart, (LONG), ()) { alcCaptureStart((ALCdevice *) P(0, i64)); return NULL; }
ONYX_DEF(alcCaptureStop, (LONG), ()) { alcCaptureStop((ALCdevice *) P(0, i64)); return NULL; }
ONYX_DEF(alcCaptureSamples, (LONG, PTR, INT), ()) { alcCaptureSamples((ALCdevice *) P(0, i64), ONYX_PTR(P(1, i32)), P(2, i32)); return NULL; }
-
+ONYX_DEF(alcGetString, (LONG, INT), (LONG)) {
+ wasm_val_init_ptr(&results->data[0], (void *) alcGetString((ALCdevice *) P(0, i64), P(1, i32)));
+ return NULL;
+}
ONYX_LIBRARY {
ONYX_FUNC(alGenBuffers)