mirror of https://github.com/adamdruppe/arsd.git
opend chnging some defaults - char, float, monitor, preparing arsd
This commit is contained in:
parent
0d6411cc58
commit
4a913bb7fb
24
cgi.d
24
cgi.d
|
|
@ -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
20
core.d
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -16385,7 +16385,7 @@ class Event : ReflectableProperties {
|
|||
dchar character() {
|
||||
if(auto ce = cast(CharEvent) this)
|
||||
return ce.character;
|
||||
return dchar.init;
|
||||
return dchar_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
39
terminal.d
39
terminal.d
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue