diff --git a/cgi.d b/cgi.d index 521b36a..451679a 100644 --- a/cgi.d +++ b/cgi.d @@ -1708,7 +1708,8 @@ class Cgi { remoteAddress = value; } else if (name == "x-forwarded-host" || name == "host") { - host = value; + if(name != "host" || host is null) + host = value; } else if (name == "accept-encoding") { if(value.indexOf("gzip") != -1) @@ -5662,7 +5663,13 @@ final class BasicDataServerImplementation : BasicDataServer, EventIoServer { } /++ + See [schedule] to make one of these. You then call one of the methods here to set it up: + --- + schedule!fn(args).at(DateTime(2019, 8, 7, 12, 00, 00)); // run the function at August 7, 2019, 12 noon UTC + schedule!fn(args).delay(6.seconds); // run it after waiting 6 seconds + schedule!fn(args).asap(); // run it in the background as soon as the event loop gets around to it + --- +/ struct ScheduledJobHelper { private string func; @@ -5684,6 +5691,10 @@ struct ScheduledJobHelper { void at(DateTime when, immutable TimeZone timezone = UTC()) { consumed = true; + auto conn = ScheduledJobServerConnection.connection; + import std.file; + auto st = SysTime(when, timezone); + auto jobId = conn.scheduleJob(1, cast(int) st.toUnixTime(), thisExePath, func, args); } /++ @@ -5692,6 +5703,9 @@ struct ScheduledJobHelper { void delay(Duration delay) { consumed = true; + auto conn = ScheduledJobServerConnection.connection; + import std.file; + auto jobId = conn.scheduleJob(0, cast(int) delay.total!"seconds", thisExePath, func, args); } /++ @@ -5701,19 +5715,20 @@ struct ScheduledJobHelper { +/ void asap() { consumed = true; - //delay(0); + auto conn = ScheduledJobServerConnection.connection; import std.file; auto jobId = conn.scheduleJob(0, 1, thisExePath, func, args); } + /+ /++ Schedules the job to recur on the given pattern. +/ - version(none) void recur(string spec) { } + +/ } private immutable void delegate(string[])[string] scheduledJobHandlers; diff --git a/color.d b/color.d index 897db9a..c0e4930 100644 --- a/color.d +++ b/color.d @@ -923,7 +923,7 @@ class IndexedImage : MemoryImage { override Color getPixel(int x, int y) const pure nothrow @trusted @nogc { if (x >= 0 && y >= 0 && x < _width && y < _height) { - uint pos = y*_width+x; + size_t pos = cast(size_t)y*_width+x; if (pos >= data.length) return Color(0, 0, 0, 0); ubyte b = data.ptr[pos]; if (b >= palette.length) return Color(0, 0, 0, 0); @@ -935,7 +935,7 @@ class IndexedImage : MemoryImage { override void setPixel(int x, int y, in Color clr) nothrow @trusted { if (x >= 0 && y >= 0 && x < _width && y < _height) { - uint pos = y*_width+x; + size_t pos = cast(size_t)y*_width+x; if (pos >= data.length) return; ubyte pidx = findNearestColor(palette, clr); if (palette.length < 255 && @@ -954,7 +954,11 @@ class IndexedImage : MemoryImage { this(int w, int h) pure nothrow @safe { _width = w; _height = h; - data = new ubyte[w*h]; + + // ensure that the computed size does not exceed basic address space limits + assert(cast(ulong)w * h <= size_t.max); + // upcast to avoid overflow for images larger than 536 Mpix + data = new ubyte[cast(size_t)w*h]; } /* @@ -1061,7 +1065,7 @@ class TrueColorImage : MemoryImage { override Color getPixel(int x, int y) const pure nothrow @trusted @nogc { if (x >= 0 && y >= 0 && x < _width && y < _height) { - uint pos = y*_width+x; + size_t pos = cast(size_t)y*_width+x; return imageData.colors.ptr[pos]; } else { return Color(0, 0, 0, 0); @@ -1070,7 +1074,7 @@ class TrueColorImage : MemoryImage { override void setPixel(int x, int y, in Color clr) nothrow @trusted { if (x >= 0 && y >= 0 && x < _width && y < _height) { - uint pos = y*_width+x; + size_t pos = cast(size_t)y*_width+x; if (pos < imageData.bytes.length/4) imageData.colors.ptr[pos] = clr; } } @@ -1079,14 +1083,19 @@ class TrueColorImage : MemoryImage { this(int w, int h) pure nothrow @safe { _width = w; _height = h; - imageData.bytes = new ubyte[w*h*4]; + + // ensure that the computed size does not exceed basic address space limits + assert(cast(ulong)w * h * 4 <= size_t.max); + // upcast to avoid overflow for images larger than 536 Mpix + imageData.bytes = new ubyte[cast(size_t)w * h * 4]; } /// Creates with existing data. The data pointer is stored here. this(int w, int h, ubyte[] data) pure nothrow @safe { _width = w; _height = h; - assert(data.length == w * h * 4); + assert(cast(ulong)w * h * 4 <= size_t.max); + assert(data.length == cast(size_t)w * h * 4); imageData.bytes = data; } diff --git a/dub.json b/dub.json index 0546a2e..857d244 100644 --- a/dub.json +++ b/dub.json @@ -14,13 +14,15 @@ { "name": "simpledisplay", "description": "Window creation and basic drawing", - "targetType": "sourceLibrary", - "libs-posix": ["X11", "Xext", "GL", "GLU"], - "libs-windows": ["gdi32", "opengl32", "glu32"], + "targetType": "library", + "importPaths": ["."], + "dflags": ["-mv=arsd.simpledisplay=simpledisplay.d"], "dependencies": {"arsd-official:color_base":"*"}, "configurations": [ { - "name": "normal" + "name": "normal", + "libs-posix": ["X11", "Xext", "GL", "GLU"], + "libs-windows": ["gdi32", "opengl32", "glu32"], }, { "name": "without-opengl", @@ -34,19 +36,10 @@ { "name": "minigui", "description": "Small GUI widget library for Windows and Linux", - "targetType": "sourceLibrary", + "targetType": "library", + "importPaths": ["."], + "dflags": ["-mv=arsd.minigui=minigui.d"], "dependencies": {"arsd-official:simpledisplay":"*"}, - "configurations": [ - { - "name": "normal" - }, - { - "name": "without-opengl", - "versions": ["without_opengl"], - "libs-windows": ["gdi32"], - "libs-posix": ["X11", "Xext"] - } - ], "sourceFiles": ["minigui.d"] }, { @@ -202,7 +195,9 @@ { "name": "color_base", "description": "Base color, point, image interface definitions", - "targetType": "sourceLibrary", + "targetType": "library", + "importPaths": ["."], + "dflags": ["-mv=arsd.color=color.d"], "sourceFiles": ["color.d"] }, { diff --git a/nanovega.d b/nanovega.d index 4cdd5da..4620860 100644 --- a/nanovega.d +++ b/nanovega.d @@ -12198,6 +12198,7 @@ version(bindbc){ alias GLchar = char; alias GLsizei = int; alias GLfloat = float; + alias GLintptr = size_t; alias GLsizeiptr = ptrdiff_t; enum uint GL_STENCIL_BUFFER_BIT = 0x00000400; @@ -12312,6 +12313,8 @@ version(bindbc){ __gshared glbfn_glDeleteVertexArrays glDeleteVertexArrays_NVGLZ; alias glDeleteVertexArrays = glDeleteVertexArrays_NVGLZ; alias glbfn_glGenerateMipmap = void function(GLenum); __gshared glbfn_glGenerateMipmap glGenerateMipmap_NVGLZ; alias glGenerateMipmap = glGenerateMipmap_NVGLZ; + alias glbfn_glBufferSubData = void function(GLenum, GLintptr, GLsizeiptr, const(GLvoid)*); + __gshared glbfn_glBufferSubData glBufferSubData_NVGLZ; alias glBufferSubData = glBufferSubData_NVGLZ; alias glbfn_glStencilMask = void function(GLuint); __gshared glbfn_glStencilMask glStencilMask_NVGLZ; alias glStencilMask = glStencilMask_NVGLZ; @@ -12413,6 +12416,8 @@ version(bindbc){ if (glDeleteVertexArrays_NVGLZ is null) assert(0, `OpenGL function 'glDeleteVertexArrays' not found!`); glGenerateMipmap_NVGLZ = cast(glbfn_glGenerateMipmap)glbindGetProcAddress(`glGenerateMipmap`); if (glGenerateMipmap_NVGLZ is null) assert(0, `OpenGL function 'glGenerateMipmap' not found!`); + glBufferSubData_NVGLZ = cast(glbfn_glBufferSubData)glbindGetProcAddress(`glBufferSubData`); + if (glBufferSubData_NVGLZ is null) assert(0, `OpenGL function 'glBufferSubData' not found!`); glStencilMask_NVGLZ = cast(glbfn_glStencilMask)glbindGetProcAddress(`glStencilMask`); if (glStencilMask_NVGLZ is null) assert(0, `OpenGL function 'glStencilMask' not found!`); diff --git a/png.d b/png.d index a0d880b..669c8b8 100644 --- a/png.d +++ b/png.d @@ -130,7 +130,7 @@ MemoryImage imageFromPng(PNG* png) { assert(0, "invalid png"); } - auto idataIdx = 0; + size_t idataIdx = 0; auto file = LazyPngFile!(Chunk[])(png.chunks); immutable(ubyte)[] previousLine; @@ -150,7 +150,7 @@ MemoryImage imageFromPng(PNG* png) { } // idata needs to be already sized for the image! width * height if indexed, width*height*4 if not. -void convertPngData(ubyte type, ubyte depth, const(ubyte)[] data, int width, ubyte[] idata, ref int idataIdx) { +void convertPngData(ubyte type, ubyte depth, const(ubyte)[] data, int width, ubyte[] idata, ref size_t idataIdx) { ubyte consumeOne() { ubyte ret = data[0]; data = data[1 .. $]; @@ -300,7 +300,7 @@ PNG* pngFromImage(IndexedImage i) { Chunk alpha; if(i.hasAlpha) { alpha.type = ['t', 'R', 'N', 'S']; - alpha.size = cast(int) i.palette.length; + alpha.size = cast(uint) i.palette.length; alpha.payload.length = alpha.size; } @@ -324,7 +324,7 @@ PNG* pngFromImage(IndexedImage i) { addImageDatastreamToPng(i.data, png); } else { // gotta convert it - ubyte[] datastream = new ubyte[i.width * i.height * h.depth / 8]; // FIXME? + ubyte[] datastream = new ubyte[cast(size_t)i.width * i.height * h.depth / 8]; // FIXME? int shift = 0; switch(h.depth) { @@ -334,8 +334,8 @@ PNG* pngFromImage(IndexedImage i) { case 4: shift = 4; break; case 8: shift = 0; break; } - int dsp = 0; - int dpos = 0; + size_t dsp = 0; + size_t dpos = 0; bool justAdvanced; for(int y = 0; y < i.height; y++) { for(int x = 0; x < i.width; x++) { @@ -467,12 +467,12 @@ void writeImageToPngFile(in char[] filename, TrueColorImage image) { h.height = image.height; png = blankPNG(h); - auto bytesPerLine = h.width * 4; + size_t bytesPerLine = cast(size_t)h.width * 4; if(h.type == 3) - bytesPerLine = h.width * 8 / h.depth; + bytesPerLine = cast(size_t)h.width * 8 / h.depth; Chunk dat; dat.type = ['I', 'D', 'A', 'T']; - int pos = 0; + size_t pos = 0; auto compressor = new Compress(); @@ -489,7 +489,8 @@ void writeImageToPngFile(in char[] filename, TrueColorImage image) { com ~= cast(ubyte[]) compressor.flush(); - dat.size = cast(int) com.length; + assert(com.length <= uint.max); + dat.size = cast(uint) com.length; dat.payload = com; dat.checksum = crc("IDAT", dat.payload); @@ -541,7 +542,7 @@ ubyte[] writePng(PNG* p) { foreach(c; p.chunks) a.length += c.size + 12; } - uint pos; + size_t pos; a[0..8] = p.header[0..8]; pos = 8; @@ -576,8 +577,8 @@ PngHeader getHeaderFromFile(string filename) { if(data[0..8] != [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]) throw new Exception("file " ~ filename ~ " is not a png"); - auto pos = 8; - uint size; + size_t pos = 8; + size_t size; size |= data[pos++] << 24; size |= data[pos++] << 16; size |= data[pos++] << 8; @@ -609,7 +610,7 @@ PNG* readPng(in ubyte[] data) { if(p.header != [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]) throw new Exception("not a png, header wrong"); - uint pos = 8; + size_t pos = 8; while(pos < data.length) { Chunk n; @@ -648,7 +649,7 @@ PNG* blankPNG(PngHeader h) { c.type = ['I', 'H', 'D', 'R']; c.payload.length = 13; - int pos = 0; + size_t pos = 0; c.payload[pos++] = h.width >> 24; c.payload[pos++] = (h.width >> 16) & 0xff; @@ -684,31 +685,31 @@ void addImageDatastreamToPng(const(ubyte)[] data, PNG* png) { PngHeader h = getHeader(png); - int bytesPerLine; + size_t bytesPerLine; switch(h.type) { case 0: // FIXME: < 8 depth not supported here but should be - bytesPerLine = h.width * 1 * h.depth / 8; + bytesPerLine = cast(size_t)h.width * 1 * h.depth / 8; break; case 2: - bytesPerLine = h.width * 3 * h.depth / 8; + bytesPerLine = cast(size_t)h.width * 3 * h.depth / 8; break; case 3: - bytesPerLine = h.width * 1 * h.depth / 8; + bytesPerLine = cast(size_t)h.width * 1 * h.depth / 8; break; case 4: // FIXME: < 8 depth not supported here but should be - bytesPerLine = h.width * 2 * h.depth / 8; + bytesPerLine = cast(size_t)h.width * 2 * h.depth / 8; break; case 6: - bytesPerLine = h.width * 4 * h.depth / 8; + bytesPerLine = cast(size_t)h.width * 4 * h.depth / 8; break; default: assert(0); } Chunk dat; dat.type = ['I', 'D', 'A', 'T']; - int pos = 0; + size_t pos = 0; const(ubyte)[] output; while(pos+bytesPerLine <= data.length) { diff --git a/terminal.d b/terminal.d index 7ab3dc5..0ec037c 100644 --- a/terminal.d +++ b/terminal.d @@ -1708,6 +1708,19 @@ struct RealTimeConsoleInput { /// Check for input, waiting no longer than the number of milliseconds bool timedCheckForInput(int milliseconds) { + if(inputQueue.length || timedCheckForInput_bypassingBuffer(timeout)) + return true; + version(Posix) + if(interrupted || windowSizeChanged || hangedUp) + return true; + return false; + } + + /* private */ bool anyInput_internal(int timeout = 0) { + return timedCheckForInput(timeout); + } + + bool timedCheckForInput_bypassingBuffer(int milliseconds) { version(Windows) { auto response = WaitForSingleObject(terminal.hConsole, milliseconds); if(response == 0) @@ -1733,15 +1746,6 @@ struct RealTimeConsoleInput { } } - /* private */ bool anyInput_internal() { - if(inputQueue.length || timedCheckForInput(0)) - return true; - version(Posix) - if(interrupted || windowSizeChanged || hangedUp) - return true; - return false; - } - private dchar getchBuffer; /// Get one key press from the terminal, discarding other