// Quick thing for allocating json values on the stack.
macro (v: Value, key: str, value: str,
- dont_copy_key := false, dont_copy_value := false) {
+ dont_copy_key := false, dont_copy_value := false) -> i32 {
_Value_String :: _Value_String;
_Value_Object :: _Value_Object;
+ _Value :: _Value
+ Value :: Value
use core {string}
v_ := cast(^_Value) v;
- if v_.type == .Object {
- k := key if dont_copy_key else string.alloc_copy(key);
- v := value if dont_copy_value else string.alloc_copy(value);
+ if v_.type != .Object do return 0;
+ k := key if dont_copy_key else string.alloc_copy(key);
+ val := value if dont_copy_value else string.alloc_copy(value);
- json_value := init(_Value_String);
- json_value.str_ = v;
- json_value.dont_free = dont_copy_value;
+ json_value := _Value_String.{
+ str_ = val,
+ dont_free = dont_copy_value
+ };
- (cast(^_Value_Object) v_).object_ << .{ k, dont_copy_key, ^json_value };
- }
+ (cast(^_Value_Object) v_).object_ << .{ k, dont_copy_key, ~~ cast(&_Value) ^json_value };
}
}
output := array.make(u8, 128, allocator=allocator);
while !reader_empty(reader) {
+ buffered := reader_get_buffered(reader);
+ if buffered > 0 {
+ array.ensure_capacity(&output, output.count + buffered);
+ memory.copy(output.data + output.count, buffer.data, buffered);
+ output.count += buffered;
+ start = end;
+ }
+
if err := reader_read_next_chunk(reader); err != .None && err != .ReadPending {
break;
}
reader_consume_error(reader);
break;
}
-
- buffered := reader_get_buffered(reader);
- if buffered > 0 {
- array.ensure_capacity(&output, output.count + buffered);
- memory.copy(output.data + output.count, buffer.data, buffered);
- output.count += buffered;
- start = end;
- }
}
return output;
write_index := 0;
while n > 0 && !reader_empty(reader) {
- reader_read_next_chunk(reader);
-
- to_write := math.min(n, end);
- memory.copy(bytes.data + write_index, buffer.data, to_write);
+ to_write := math.min(n, end - start);
+ memory.copy(bytes.data + write_index, buffer.data + start, to_write);
n -= to_write;
write_index += to_write;
start += to_write;
+
+ reader_read_next_chunk(reader);
}
last_byte = cast(i32) bytes[write_index - 1];
return buffer[start .. count];
}
- out: [..] u8;
- array.init(&out, allocator=allocator);
+ out := make(dyn_str, allocator);
while done := false; !done {
if start == end {
return buffer[start .. count];
}
- out: [..] u8;
- array.init(&out, allocator=allocator);
+ out := make(dyn_str, allocator);
while done := false; !done {
count := start;
return buffer[start .. count];
}
- out: [..] u8;
- array.init(&out, allocator=allocator);
+ out := make(dyn_str, allocator);
while done := false; !done {
count := start;
}
}
+ //
+ // If there are no "active" clients, but we are hitting this function,
+ // there are clients, but they are still being processed with .ready,
+ // events. If we continue, we will end up waiting for `pulse_time_ms`
+ // seconds, since there is nothing to wake up the polling action. In
+ // a rare chance when this is multi-threaded, waiting could stall other
+ // threads because we haven't pushed new ready events out. So, we have
+ // to immediately return, and enter a sort of complicated "spin loop"
+ // in order to not stall worker threads.
+ if active_clients.count == 0 {
+ return .{ null, 0 };
+ }
+
status_buffer := alloc.array_from_stack(Socket_Poll_Status, client_count);
socket_poll_all(cast([] &Socket) active_clients, pulse_time_ms, status_buffer);