opend chnging some defaults - char, float, monitor, preparing arsd

This commit is contained in:
Adam D. Ruppe 2025-09-07 10:30:49 -04:00
parent 0d6411cc58
commit 4a913bb7fb
6 changed files with 79 additions and 37 deletions

24
cgi.d
View File

@ -606,6 +606,8 @@ unittest {
static import std.file;
static import arsd.core;
import arsd.core : EnableSynchronization; // polyfill for opend with removed monitor
version(Posix)
import arsd.core : makeNonBlocking;
@ -1883,7 +1885,7 @@ class Cgi {
// not using maxContentLength because that might be cranked up to allow
// large file uploads. We can handle them, but a huge post[] isn't any good.
if(pps.buffer.length + chunk.length > 8 * 1024 * 1024) // surely this is plenty big enough
if(pps.buffer.length + chunk.length > 24 * 1024 * 1024) // surely this is plenty big enough
throw new Exception("wtf is up with such a gigantic form submission????");
pps.buffer ~= chunk;
@ -2289,6 +2291,9 @@ class Cgi {
```
To ensure the necessary data is available to cgi.d.
History:
The overload with the `checker` callback was added July 29, 2025.
+/
void requireBasicAuth(string user, string pass, string message = null, string file = __FILE__, size_t line = __LINE__) {
if(authorization != "Basic " ~ Base64.encode(cast(immutable(ubyte)[]) (user ~ ":" ~ pass))) {
@ -2296,6 +2301,17 @@ class Cgi {
}
}
/// ditto
void requireBasicAuth(scope bool delegate(string user, string pass) checker, string message = null, string file = __FILE__, size_t line = __LINE__) {
// FIXME
/+
if(authorization != "Basic " ~ Base64.encode(cast(immutable(ubyte)[]) (user ~ ":" ~ pass))) {
throw new AuthorizationRequiredException("Basic", message, file, line);
}
+/
}
/// Very simple caching controls - setCache(false) means it will never be cached. Good for rapidly updated or sensitive sites.
/// setCache(true) means it will always be cached for as long as possible. Best for static content.
/// Use setResponseExpires and updateResponseExpires for more control
@ -5959,6 +5975,8 @@ import core.atomic;
FIXME: should I offer an event based async thing like netman did too? Yeah, probably.
*/
class ListeningConnectionManager {
version(D_OpenD) mixin EnableSynchronization;
Semaphore semaphore;
Socket[256] queue;
shared(ubyte) nextIndexFront;
@ -12130,8 +12148,10 @@ auto handleWith(alias handler)(string urlPrefix) {
// cuz I'm too lazy to do it better right now
static class Hack : WebObject {
static import std.traits;
static if(is(typeof(handler) Params == __parameters))
@(__traits(getAttributes, handler))
@UrlName("")
auto handle(std.traits.Parameters!handler args) {
auto handle(Params args) {
return handler(args);
}
}

20
core.d
View File

@ -56,6 +56,18 @@ static if(__traits(compiles, () { import core.interpolation; })) {
struct InterpolatedExpression(string code) {}
}
static if(!__traits(hasMember, object, "SynchronizableObject")) {
alias SynchronizableObject = Object;
mixin template EnableSynchronization() {}
} else {
alias EnableSynchronization = Object.EnableSynchronization;
}
// the old char.inits if you need them
enum char char_invalid = '\xFF';
enum wchar wchar_invalid = '\uFFFF';
enum dchar dchar_invalid = '\U0000FFFF';
// arsd core is now default but you can opt out for a lil while
version(no_arsd_core) {
@ -7152,7 +7164,7 @@ private class CoreEventLoopImplementation : ICoreEventLoop {
}
private static final class CallbackQueue {
private static final class CallbackQueue : SynchronizableObject {
int fd = -1;
string name;
CallbackHelper callback;
@ -7489,14 +7501,14 @@ struct SynchronizedCircularBuffer(T, size_t maxSize = 128) {
private int front;
private int back;
private Object synchronizedOn;
private SynchronizableObject synchronizedOn;
@disable this();
/++
The Object's monitor is used to synchronize the methods in here.
+/
this(Object synchronizedOn) {
this(SynchronizableObject synchronizedOn) {
this.synchronizedOn = synchronizedOn;
}
@ -8481,6 +8493,8 @@ unittest {
Not actually implemented until February 6, 2025, when it changed from mixin template to class.
+/
class LoggerOf(T, size_t bufferSize = 16) {
version(D_OpenD) mixin EnableSynchronization;
private LoggedMessage!T[bufferSize] ring;
private ulong writeBufferPosition;

View File

@ -16385,7 +16385,7 @@ class Event : ReflectableProperties {
dchar character() {
if(auto ce = cast(CharEvent) this)
return ce.character;
return dchar.init;
return dchar_invalid;
}
}

View File

@ -367,13 +367,13 @@ class DummySample : SampleController {
void pause() {}
void resume() {}
void stop() {}
float position() { return float.init; }
float position() { return float.nan; }
bool finished() { return true; }
bool paused() { return true; }
float duration() { return float.init; }
float duration() { return float.nan; }
float volume() { return 1.0; }
float volume(float v) { return float.init; }
float volume(float v) { return float.nan; }
float playbackSpeed() { return 1.0; }
void playbackSpeed(float v) { }
@ -397,18 +397,18 @@ private final class SampleControlFlags : SampleController {
void seek(float where) { synchronized(this) {if(where < 0) where = 0; requestedSeek = where;} }
float currentPosition = 0.0;
float requestedSeek = float.init;
float requestedSeek = float.nan;
float detectedDuration;
float detectedDuration = float.nan;
float duration() { return detectedDuration; }
// FIXME: these aren't implemented
float volume() { return 1.0; }
float volume(float v) { return float.init; }
float volume(float v) { return float.nan; }
float playbackSpeed_ = 1.0;
float requestedPlaybackSpeed;
float requestedPlaybackSpeed = float.nan;
float playbackSpeed() { return playbackSpeed_; }
void playbackSpeed(float v) { requestedPlaybackSpeed = v; }
@ -420,18 +420,18 @@ private final class SampleControlFlags : SampleController {
) {
// should I synchronize it after all?
synchronized(this) {
if(this.requestedSeek !is float.init) {
if(this.requestedSeek !is float.nan) {
if(executeSeek !is null && executeSeek(this.requestedSeek)) {
this.currentPosition = this.requestedSeek;
}
this.requestedSeek = float.init;
this.requestedSeek = float.nan;
}
if(this.requestedPlaybackSpeed !is float.init) {
if(this.requestedPlaybackSpeed !is float.nan) {
if(executePlaybackSpeed !is null && executePlaybackSpeed(this.playbackSpeed_)) {
this.playbackSpeed_ = this.requestedPlaybackSpeed;
}
this.requestedPlaybackSpeed = float.init;
this.requestedPlaybackSpeed = float.nan;
}
}

View File

@ -1784,7 +1784,7 @@ float[2] getDpi() {
}
auto xft = getXftDpi();
if(xft is float.init)
if(xft is float.nan)
fallback();
else {
dpi[0] = xft;
@ -1814,7 +1814,7 @@ float getXftDpi() {
}
}
return float.init;
return float.nan;
}
/++
@ -2012,6 +2012,7 @@ enum CornerStyle {
will need to destroy it yourself.
+/
class SimpleWindow : CapableOfHandlingNativeEvent, CapableOfBeingDrawnUpon {
version(D_OpenD) mixin EnableSynchronization;
/++
Copies the window's current state into a [TrueColorImage].
@ -4315,7 +4316,7 @@ struct EventLoop {
EventLoop.get().exit();
}
private __gshared static Object monitor = new Object(); // deliberate CTFE usage here fyi
private __gshared static SynchronizableObject monitor = new SynchronizableObject(); // deliberate CTFE usage here fyi
/// Construct an application-global event loop for yourself
/// See_Also: [SimpleWindow.setEventHandlers]
@ -10980,7 +10981,7 @@ private struct RunQueueMember {
}
private __gshared RunQueueMember*[] runInGuiThreadQueue;
private __gshared Object runInGuiThreadLock = new Object; // intentional CTFE
private __gshared SynchronizableObject runInGuiThreadLock = new SynchronizableObject; // intentional CTFE
private bool thisIsGuiThread = false;
private shared bool guiThreadExists_ = false;
private shared bool guiThreadTerminating = false;

View File

@ -269,6 +269,8 @@ __gshared void delegate() nothrow @nogc sigIntExtension;
static import arsd.core;
public import arsd.core : dchar_invalid;
import core.stdc.stdio;
version(TerminalDirectToEmulator) {
@ -2543,7 +2545,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
Params:
prompt = the prompt to give the user. For example, `"Your name: "`.
echoChar = the character to show back to the user as they type. The default value of `dchar.init` shows the user their own input back normally. Passing `0` here will disable echo entirely, like a Unix password prompt. Or you might also try `'*'` to do a password prompt that shows the number of characters input to the user.
echoChar = the character to show back to the user as they type. The default value of `dchar_invalid` shows the user their own input back normally. Passing `0` here will disable echo entirely, like a Unix password prompt. Or you might also try `'*'` to do a password prompt that shows the number of characters input to the user.
prefilledData = the initial data to populate the edit buffer
History:
@ -2557,7 +2559,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
On November 7, 2023 (dub v11.3), this function started returning stdin.readln in the event that the instance is not connected to a terminal.
+/
string getline(string prompt = null, dchar echoChar = dchar.init, string prefilledData = null) {
string getline(string prompt = null, dchar echoChar = dchar_invalid, string prefilledData = null) {
if(!usingDirectEmulator && type != ConsoleOutputType.minimalProcessing)
if(!stdoutIsTerminal || !stdinIsTerminal) {
import std.stdio;
@ -2601,7 +2603,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
}
/// ditto
string getline(string prompt, string prefilledData, dchar echoChar = dchar.init) {
string getline(string prompt, string prefilledData, dchar echoChar = dchar_invalid) {
return getline(prompt, echoChar, prefilledData);
}
@ -2697,14 +2699,17 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
throw new Exception("terminal reply timed out");
auto len = read(terminal.fdIn, buffer.ptr, buffer.length);
if(len == -1) {
if(errno == EINTR)
if(errno == EINTR) {
tries++;
goto try_again;
}
if(errno == EAGAIN || errno == EWOULDBLOCK) {
import core.thread;
Thread.sleep(10.msecs);
tries++;
goto try_again;
}
throw new Exception("Other error in read cursor position");
} else if(len == 0) {
throw new Exception("Couldn't get cursor position to initialize get line " ~ to!string(len) ~ " " ~ to!string(errno));
}
@ -3304,7 +3309,7 @@ struct RealTimeConsoleInput {
bool kbhit() {
auto got = getch(true);
if(got == dchar.init)
if(got == dchar_invalid)
return false;
getchBuffer = got;
@ -3385,21 +3390,21 @@ struct RealTimeConsoleInput {
}
}
private dchar getchBuffer;
private dchar getchBuffer = dchar_invalid;
/// Get one key press from the terminal, discarding other
/// events in the process. Returns dchar.init upon receiving end-of-file.
/// events in the process. Returns dchar_invalid upon receiving end-of-file.
///
/// Be aware that this may return non-character key events, like F1, F2, arrow keys, etc., as private use Unicode characters. Check them against KeyboardEvent.Key if you like.
dchar getch(bool nonblocking = false) {
if(getchBuffer != dchar.init) {
if(getchBuffer != dchar_invalid) {
auto a = getchBuffer;
getchBuffer = dchar.init;
getchBuffer = dchar_invalid;
return a;
}
if(nonblocking && !anyInput_internal())
return dchar.init;
return dchar_invalid;
auto event = nextEvent();
while(event.type != InputEvent.Type.KeyboardEvent || event.keyboardEvent.pressed == false) {
@ -3408,10 +3413,10 @@ struct RealTimeConsoleInput {
if(event.type == InputEvent.Type.HangupEvent)
throw new HangupException();
if(event.type == InputEvent.Type.EndOfFileEvent)
return dchar.init;
return dchar_invalid;
if(nonblocking && !anyInput_internal())
return dchar.init;
return dchar_invalid;
event = nextEvent();
}
@ -6190,7 +6195,7 @@ class LineGetter {
Possible values are:
`dchar.init` = normal; user can see their input.
`dchar_invalid` = normal; user can see their input.
`'\0'` = nothing; the cursor does not visually move as they edit. Similar to Unix style password prompts.
@ -6198,8 +6203,10 @@ class LineGetter {
History:
Added October 11, 2021 (dub v10.4)
OpenD changed `dchar.init` from an invalid char to `0` in September 2025. If you explicitly assigned `dchar.init`, I strongly recommend changing that to `dchar_invalid` for maximum compatibility.
+/
dchar echoChar = dchar.init;
dchar echoChar = dchar_invalid;
protected static struct Drawer {
LineGetter lg;
@ -6248,7 +6255,7 @@ class LineGetter {
if(lg.echoChar == '\0')
return;
else if(lg.echoChar !is dchar.init)
else if(lg.echoChar !is dchar_invalid)
ch = lg.echoChar;
auto l = encode(buffer, ch);
@ -9439,7 +9446,7 @@ version(TerminalDirectToEmulator) {
fontSize = widget.scaleWithDpi(fontSize);
} else {
auto xft = getXftDpi();
if(xft is float.init)
if(xft is float.nan)
xft = 96;
// the xft passed as assumed means it will figure that's what the size
// is based on (which it is, inside xft) preventing the double scale problem