Update Files

This commit is contained in:
2025-01-22 16:18:30 +01:00
parent ed4603cf95
commit a36294b518
16718 changed files with 2960346 additions and 0 deletions

View File

@ -0,0 +1,83 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys;
/**
File information, as given by `sys.FileSystem.stat`.
**/
typedef FileStat = {
/**
The user group id for the file owner.
**/
var gid:Int;
/**
The user id for the file owner.
**/
var uid:Int;
/**
The last access time for the file (when enabled by the file system).
**/
var atime:Date;
/**
The last modification time for the file.
**/
var mtime:Date;
/**
The creation time for the file (not all file systems support this).
**/
var ctime:Date;
/**
The size of the file, in bytes.
**/
var size:Int;
/**
The device on which stat resides.
**/
var dev:Int;
/**
The inode number for stat.
**/
var ino:Int;
/**
The number of hard links to stat.
**/
var nlink:Int;
/**
The device type on which stat resides (special files only).
**/
var rdev:Int;
/**
The permission bits of stat. The meaning of the bits is platform dependent.
**/
var mode:Int;
}

View File

@ -0,0 +1,108 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys;
/**
This class provides information about files and directories.
If `null` is passed as a file path to any function in this class, the
result is unspecified, and may differ from target to target.
See `sys.io.File` for the complementary file API.
**/
extern class FileSystem {
/**
Returns `true` if the file or directory specified by `path` exists.
**/
static function exists(path:String):Bool;
/**
Renames/moves the file or directory specified by `path` to `newPath`.
If `path` is not a valid file system entry, or if it is not accessible,
or if `newPath` is not accessible, an exception is thrown.
**/
static function rename(path:String, newPath:String):Void;
/**
Returns `FileStat` information for the file or directory specified by
`path`.
**/
static function stat(path:String):FileStat;
/**
Returns the full path of the file or directory specified by `relPath`,
which is relative to the current working directory. Symlinks will be
followed and the path will be normalized.
**/
static function fullPath(relPath:String):String;
/**
Returns the full path of the file or directory specified by `relPath`,
which is relative to the current working directory. The path doesn't
have to exist.
**/
static function absolutePath(relPath:String):String;
/**
Returns `true` if the file or directory specified by `path` is a directory.
If `path` is not a valid file system entry or if its destination is not
accessible, an exception is thrown.
**/
static function isDirectory(path:String):Bool;
/**
Creates a directory specified by `path`.
This method is recursive: The parent directories don't have to exist.
If the directory cannot be created, an exception is thrown.
**/
static function createDirectory(path:String):Void;
/**
Deletes the file specified by `path`.
If `path` does not denote a valid file, or if that file cannot be
deleted, an exception is thrown.
**/
static function deleteFile(path:String):Void;
/**
Deletes the directory specified by `path`. Only empty directories can
be deleted.
If `path` does not denote a valid directory, or if that directory cannot
be deleted, an exception is thrown.
**/
static function deleteDirectory(path:String):Void;
/**
Returns the names of all files and directories in the directory specified
by `path`. `"."` and `".."` are not included in the output.
If `path` does not denote a valid directory, an exception is thrown.
**/
static function readDirectory(path:String):Array<String>;
}

View File

@ -0,0 +1,500 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys;
import haxe.io.BytesOutput;
import haxe.io.Bytes;
import haxe.io.Input;
import sys.net.Host;
import sys.net.Socket;
class Http extends haxe.http.HttpBase {
public var noShutdown:Bool;
public var cnxTimeout:Float;
public var responseHeaders:Map<String, String>;
var chunk_size:Null<Int>;
var chunk_buf:haxe.io.Bytes;
var file:{
param:String,
filename:String,
io:haxe.io.Input,
size:Int,
mimeType:String
};
public static var PROXY:{host:String, port:Int, auth:{user:String, pass:String}} = null;
public function new(url:String) {
cnxTimeout = 10;
#if php
noShutdown = !php.Global.function_exists('stream_socket_shutdown');
#end
super(url);
}
public override function request(?post:Bool) {
var output = new haxe.io.BytesOutput();
var old = onError;
var err = false;
onError = function(e) {
responseBytes = output.getBytes();
err = true;
// Resetting back onError before calling it allows for a second "retry" request to be sent without onError being wrapped twice
onError = old;
onError(e);
}
post = post || postBytes != null || postData != null;
customRequest(post, output);
if (!err) {
success(output.getBytes());
}
}
@:noCompletion
@:deprecated("Use fileTransfer instead")
inline public function fileTransfert(argname:String, filename:String, file:haxe.io.Input, size:Int, mimeType = "application/octet-stream") {
fileTransfer(argname, filename, file, size, mimeType);
}
public function fileTransfer(argname:String, filename:String, file:haxe.io.Input, size:Int, mimeType = "application/octet-stream") {
this.file = {
param: argname,
filename: filename,
io: file,
size: size,
mimeType: mimeType
};
}
public function customRequest(post:Bool, api:haxe.io.Output, ?sock:sys.net.Socket, ?method:String) {
this.responseAsString = null;
this.responseBytes = null;
var url_regexp = ~/^(https?:\/\/)?([a-zA-Z\.0-9_-]+)(:[0-9]+)?(.*)$/;
if (!url_regexp.match(url)) {
onError("Invalid URL");
return;
}
var secure = (url_regexp.matched(1) == "https://");
if (sock == null) {
if (secure) {
#if php
sock = new php.net.SslSocket();
#elseif java
sock = new java.net.SslSocket();
#elseif python
sock = new python.net.SslSocket();
#elseif (!no_ssl && (hxssl || hl || cpp || (neko && !(macro || interp) || eval)))
sock = new sys.ssl.Socket();
#elseif (neko || cpp)
throw "Https is only supported with -lib hxssl";
#else
throw new haxe.exceptions.NotImplementedException("Https support in haxe.Http is not implemented for this target");
#end
} else {
sock = new Socket();
}
sock.setTimeout(cnxTimeout);
}
var host = url_regexp.matched(2);
var portString = url_regexp.matched(3);
var request = url_regexp.matched(4);
// ensure path begins with a forward slash
// this is required by original URL specifications and many servers have issues if it's not supplied
// see https://stackoverflow.com/questions/1617058/ok-to-skip-slash-before-query-string
if (request.charAt(0) != "/") {
request = "/" + request;
}
var port = if (portString == null || portString == "") secure ? 443 : 80 else Std.parseInt(portString.substr(1, portString.length - 1));
var multipart = (file != null);
var boundary = null;
var uri = null;
if (multipart) {
post = true;
boundary = Std.string(Std.random(1000))
+ Std.string(Std.random(1000))
+ Std.string(Std.random(1000))
+ Std.string(Std.random(1000));
while (boundary.length < 38)
boundary = "-" + boundary;
var b = new StringBuf();
for (p in params) {
b.add("--");
b.add(boundary);
b.add("\r\n");
b.add('Content-Disposition: form-data; name="');
b.add(p.name);
b.add('"');
b.add("\r\n");
b.add("\r\n");
b.add(p.value);
b.add("\r\n");
}
b.add("--");
b.add(boundary);
b.add("\r\n");
b.add('Content-Disposition: form-data; name="');
b.add(file.param);
b.add('"; filename="');
b.add(file.filename);
b.add('"');
b.add("\r\n");
b.add("Content-Type: " + file.mimeType + "\r\n" + "\r\n");
uri = b.toString();
} else {
for (p in params) {
if (uri == null)
uri = "";
else
uri += "&";
uri += StringTools.urlEncode(p.name) + "=" + StringTools.urlEncode('${p.value}');
}
}
var b = new BytesOutput();
if (method != null) {
b.writeString(method);
b.writeString(" ");
} else if (post)
b.writeString("POST ");
else
b.writeString("GET ");
if (Http.PROXY != null) {
b.writeString("http://");
b.writeString(host);
if (port != 80) {
b.writeString(":");
b.writeString('$port');
}
}
b.writeString(request);
if (!post && uri != null) {
if (request.indexOf("?", 0) >= 0)
b.writeString("&");
else
b.writeString("?");
b.writeString(uri);
}
b.writeString(" HTTP/1.1\r\nHost: " + host + "\r\n");
if (postData != null) {
postBytes = Bytes.ofString(postData);
postData = null;
}
if (postBytes != null)
b.writeString("Content-Length: " + postBytes.length + "\r\n");
else if (post && uri != null) {
if (multipart || !Lambda.exists(headers, function(h) return h.name == "Content-Type")) {
b.writeString("Content-Type: ");
if (multipart) {
b.writeString("multipart/form-data");
b.writeString("; boundary=");
b.writeString(boundary);
} else
b.writeString("application/x-www-form-urlencoded");
b.writeString("\r\n");
}
if (multipart)
b.writeString("Content-Length: " + (uri.length + file.size + boundary.length + 6) + "\r\n");
else
b.writeString("Content-Length: " + uri.length + "\r\n");
}
b.writeString("Connection: close\r\n");
for (h in headers) {
b.writeString(h.name);
b.writeString(": ");
b.writeString(h.value);
b.writeString("\r\n");
}
b.writeString("\r\n");
if (postBytes != null)
b.writeFullBytes(postBytes, 0, postBytes.length);
else if (post && uri != null)
b.writeString(uri);
try {
if (Http.PROXY != null)
sock.connect(new Host(Http.PROXY.host), Http.PROXY.port);
else
sock.connect(new Host(host), port);
if (multipart)
writeBody(b, file.io, file.size, boundary, sock)
else
writeBody(b, null, 0, null, sock);
readHttpResponse(api, sock);
sock.close();
} catch (e:Dynamic) {
try
sock.close()
catch (e:Dynamic) {};
onError(Std.string(e));
}
}
function writeBody(body:Null<BytesOutput>, fileInput:Null<Input>, fileSize:Int, boundary:Null<String>, sock:Socket) {
if (body != null) {
var bytes = body.getBytes();
sock.output.writeFullBytes(bytes, 0, bytes.length);
}
if (boundary != null) {
var bufsize = 4096;
var buf = haxe.io.Bytes.alloc(bufsize);
while (fileSize > 0) {
var size = if (fileSize > bufsize) bufsize else fileSize;
var len = 0;
try {
len = fileInput.readBytes(buf, 0, size);
} catch (e:haxe.io.Eof)
break;
sock.output.writeFullBytes(buf, 0, len);
fileSize -= len;
}
sock.output.writeString("\r\n");
sock.output.writeString("--");
sock.output.writeString(boundary);
sock.output.writeString("--");
}
}
function readHttpResponse(api:haxe.io.Output, sock:sys.net.Socket) {
// READ the HTTP header (until \r\n\r\n)
var b = new haxe.io.BytesBuffer();
var k = 4;
var s = haxe.io.Bytes.alloc(4);
sock.setTimeout(cnxTimeout);
while (true) {
var p = sock.input.readBytes(s, 0, k);
while (p != k)
p += sock.input.readBytes(s, p, k - p);
b.addBytes(s, 0, k);
switch (k) {
case 1:
var c = s.get(0);
if (c == 10)
break;
if (c == 13)
k = 3;
else
k = 4;
case 2:
var c = s.get(1);
if (c == 10) {
if (s.get(0) == 13)
break;
k = 4;
} else if (c == 13)
k = 3;
else
k = 4;
case 3:
var c = s.get(2);
if (c == 10) {
if (s.get(1) != 13)
k = 4;
else if (s.get(0) != 10)
k = 2;
else
break;
} else if (c == 13) {
if (s.get(1) != 10 || s.get(0) != 13)
k = 1;
else
k = 3;
} else
k = 4;
case 4:
var c = s.get(3);
if (c == 10) {
if (s.get(2) != 13)
continue;
else if (s.get(1) != 10 || s.get(0) != 13)
k = 2;
else
break;
} else if (c == 13) {
if (s.get(2) != 10 || s.get(1) != 13)
k = 3;
else
k = 1;
}
}
}
#if neko
var headers = neko.Lib.stringReference(b.getBytes()).split("\r\n");
#else
var headers = b.getBytes().toString().split("\r\n");
#end
var response = headers.shift();
var rp = response.split(" ");
var status = Std.parseInt(rp[1]);
if (status == 0 || status == null)
throw "Response status error";
// remove the two lasts \r\n\r\n
headers.pop();
headers.pop();
responseHeaders = new haxe.ds.StringMap();
var size = null;
var chunked = false;
for (hline in headers) {
var a = hline.split(": ");
var hname = a.shift();
var hval = if (a.length == 1) a[0] else a.join(": ");
hval = StringTools.ltrim(StringTools.rtrim(hval));
responseHeaders.set(hname, hval);
switch (hname.toLowerCase()) {
case "content-length":
size = Std.parseInt(hval);
case "transfer-encoding":
chunked = (hval.toLowerCase() == "chunked");
}
}
onStatus(status);
var chunk_re = ~/^([0-9A-Fa-f]+)[ ]*\r\n/m;
chunk_size = null;
chunk_buf = null;
var bufsize = 1024;
var buf = haxe.io.Bytes.alloc(bufsize);
if (chunked) {
try {
while (true) {
var len = sock.input.readBytes(buf, 0, bufsize);
if (!readChunk(chunk_re, api, buf, len))
break;
}
} catch (e:haxe.io.Eof) {
throw "Transfer aborted";
}
} else if (size == null) {
if (!noShutdown)
sock.shutdown(false, true);
try {
while (true) {
var len = sock.input.readBytes(buf, 0, bufsize);
if (len == 0)
break;
api.writeBytes(buf, 0, len);
}
} catch (e:haxe.io.Eof) {}
} else {
api.prepare(size);
try {
while (size > 0) {
var len = sock.input.readBytes(buf, 0, if (size > bufsize) bufsize else size);
api.writeBytes(buf, 0, len);
size -= len;
}
} catch (e:haxe.io.Eof) {
throw "Transfer aborted";
}
}
if (chunked && (chunk_size != null || chunk_buf != null))
throw "Invalid chunk";
if (status < 200 || status >= 400)
throw "Http Error #" + status;
api.close();
}
function readChunk(chunk_re:EReg, api:haxe.io.Output, buf:haxe.io.Bytes, len) {
if (chunk_size == null) {
if (chunk_buf != null) {
var b = new haxe.io.BytesBuffer();
b.add(chunk_buf);
b.addBytes(buf, 0, len);
buf = b.getBytes();
len += chunk_buf.length;
chunk_buf = null;
}
#if neko
if (chunk_re.match(neko.Lib.stringReference(buf))) {
#else
if (chunk_re.match(buf.toString())) {
#end
var p = chunk_re.matchedPos();
if (p.len <= len) {
var cstr = chunk_re.matched(1);
chunk_size = Std.parseInt("0x" + cstr);
if (chunk_size == 0) {
chunk_size = null;
chunk_buf = null;
return false;
}
len -= p.len;
return readChunk(chunk_re, api, buf.sub(p.len, len), len);
}
}
// prevent buffer accumulation
if (len > 10) {
onError("Invalid chunk");
return false;
}
chunk_buf = buf.sub(0, len);
return true;
}
if (chunk_size > len) {
chunk_size -= len;
api.writeBytes(buf, 0, len);
return true;
}
var end = chunk_size + 2;
if (len >= end) {
if (chunk_size > 0)
api.writeBytes(buf, 0, chunk_size);
len -= end;
chunk_size = null;
if (len == 0)
return true;
return readChunk(chunk_re, api, buf.sub(end, len), len);
}
if (chunk_size > 0)
api.writeBytes(buf, 0, chunk_size);
chunk_size -= len;
return true;
}
/**
Makes a synchronous request to `url`.
This creates a new Http instance and makes a GET request by calling its
`request(false)` method.
If `url` is null, the result is unspecified.
**/
public static function requestUrl(url:String):String {
var h = new Http(url);
var r = null;
h.onData = function(d) {
r = d;
}
h.onError = function(e) {
throw e;
}
h.request(false);
return r;
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.db;
interface Connection {
function request(s:String):ResultSet;
function close():Void;
function escape(s:String):String;
function quote(s:String):String;
function addValue(s:StringBuf, v:Dynamic):Void;
function lastInsertId():Int;
function dbName():String;
function startTransaction():Void;
function commit():Void;
function rollback():Void;
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.db;
class Mysql {
public static function connect(params:{
host:String,
?port:Int,
user:String,
pass:String,
?socket:String,
?database:String
}):sys.db.Connection {
throw new haxe.exceptions.NotImplementedException("Not implemented for this platform");
return null;
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.db;
interface ResultSet {
/**
Get amount of rows left in this set.
Depending on a database management system accessing this field may cause
all rows to be fetched internally. However, it does not affect `next` calls.
**/
var length(get, null):Int;
/**
Amount of columns in a row.
Depending on a database management system may return `0` if the query
did not match any rows.
**/
var nfields(get, null):Int;
/**
Tells whether there is a row to be fetched.
**/
function hasNext():Bool;
/**
Fetch next row.
**/
function next():Dynamic;
/**
Fetch all the rows not fetched yet.
**/
function results():List<Dynamic>;
/**
Get the value of `n`-th column of the current row.
Throws an exception if the re
**/
function getResult(n:Int):String;
/**
Get the value of `n`-th column of the current row as an integer value.
**/
function getIntResult(n:Int):Int;
/**
Get the value of `n`-th column of the current row as a float value.
**/
function getFloatResult(n:Int):Float;
/**
Get the list of column names.
Depending on a database management system may return `null` if there's no
more rows to fetch.
**/
function getFieldsNames():Null<Array<String>>;
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.db;
class Sqlite {
/**
Opens a new SQLite connection on the specified path.
(cs) You will need a SQLite ADO.NET Provider
(see http://www.mono-project.com/docs/database-access/providers/sqlite/).
Also note that this will try to open an assembly named `Mono.Data.Sqlite`
if it wasn't loaded yet.
(java) You will need a SQLite JDBC driver (e.g.
https://github.com/xerial/sqlite-jdbc/releases).
**/
public static function open(file:String):Connection {
throw "Not implemented for this platform";
return null;
}
}

View File

@ -0,0 +1,132 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.io;
/**
API for reading and writing files.
See `sys.FileSystem` for the complementary file system API.
**/
extern class File {
/**
Retrieves the content of the file specified by `path` as a String.
If the file does not exist or can not be read, an exception is thrown.
`sys.FileSystem.exists` can be used to check for existence.
If `path` is null, the result is unspecified.
**/
static function getContent(path:String):String;
/**
Stores `content` in the file specified by `path`.
If the file cannot be written to, an exception is thrown.
If `path` or `content` are null, the result is unspecified.
**/
static function saveContent(path:String, content:String):Void;
/**
Retrieves the binary content of the file specified by `path`.
If the file does not exist or can not be read, an exception is thrown.
`sys.FileSystem.exists` can be used to check for existence.
If `path` is null, the result is unspecified.
**/
static function getBytes(path:String):haxe.io.Bytes;
/**
Stores `bytes` in the file specified by `path` in binary mode.
If the file cannot be written to, an exception is thrown.
If `path` or `bytes` are null, the result is unspecified.
**/
static function saveBytes(path:String, bytes:haxe.io.Bytes):Void;
/**
Returns an `FileInput` handle to the file specified by `path`.
If `binary` is true, the file is opened in binary mode. Otherwise it is
opened in non-binary mode.
If the file does not exist or can not be read, an exception is thrown.
Operations on the returned `FileInput` handle read on the opened file.
File handles should be closed via `FileInput.close` once the operation
is complete.
If `path` is null, the result is unspecified.
**/
static function read(path:String, binary:Bool = true):FileInput;
/**
Returns an `FileOutput` handle to the file specified by `path`.
If `binary` is true, the file is opened in binary mode. Otherwise it is
opened in non-binary mode.
If the file cannot be written to, an exception is thrown.
Operations on the returned `FileOutput` handle write to the opened file.
If the file existed, its previous content is overwritten.
File handles should be closed via `FileOutput.close` once the operation
is complete.
If `path` is null, the result is unspecified.
**/
static function write(path:String, binary:Bool = true):FileOutput;
/**
Similar to `sys.io.File.write`, but appends to the file if it exists
instead of overwriting its contents.
**/
static function append(path:String, binary:Bool = true):FileOutput;
/**
Similar to `sys.io.File.append`. While `append` can only seek or write
starting from the end of the file's previous contents, `update` can
seek to any position, so the file's previous contents can be
selectively overwritten.
**/
static function update(path:String, binary:Bool = true):FileOutput;
/**
Copies the contents of the file specified by `srcPath` to the file
specified by `dstPath`.
If the `srcPath` does not exist or cannot be read, or if the `dstPath`
file cannot be written to, an exception is thrown.
If the file at `dstPath` exists, its contents are overwritten.
If `srcPath` or `dstPath` are null, the result is unspecified.
**/
static function copy(srcPath:String, dstPath:String):Void;
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.io;
/**
Use `sys.io.File.read` to create a `FileInput`.
**/
extern class FileInput extends haxe.io.Input {
function seek(p:Int, pos:FileSeek):Void;
function tell():Int;
function eof():Bool;
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.io;
/**
Use `sys.io.File.write` to create a `FileOutput`.
**/
extern class FileOutput extends haxe.io.Output {
function seek(p:Int, pos:FileSeek):Void;
function tell():Int;
}

View File

@ -0,0 +1,29 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.io;
enum FileSeek {
SeekBegin;
SeekCur;
SeekEnd;
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.io;
extern class Process {
/**
Standard output. The output stream where a process writes its output data.
**/
var stdout(default, null):haxe.io.Input;
/**
Standard error. The output stream to output error messages or diagnostics.
**/
var stderr(default, null):haxe.io.Input;
/**
Standard input. The stream data going into a process.
**/
var stdin(default, null):haxe.io.Output;
/**
Construct a `Process` object, which run the given command immediately.
Command arguments can be passed in two ways: 1. using `args`, 2. appending to `cmd` and leaving `args` as `null`.
1. When using `args` to pass command arguments, each argument will be automatically quoted, and shell meta-characters will be escaped if needed.
`cmd` should be an executable name that can be located in the `PATH` environment variable, or a path to an executable.
2. When `args` is not given or is `null`, command arguments can be appended to `cmd`. No automatic quoting/escaping will be performed. `cmd` should be formatted exactly as it would be when typed at the command line.
It can run executables, as well as shell commands that are not executables (e.g. on Windows: `dir`, `cd`, `echo` etc).
`detached` allows the created process to be standalone. You cannot communicate with it but you can look at its exit code. Not supported on php.
`close()` should be called when the `Process` is no longer used.
**/
function new(cmd:String, ?args:Array<String>, ?detached:Bool):Void;
/**
Return the process ID.
**/
function getPid():Int;
/**
Query the exit code of the process.
If `block` is true or not specified, it will block until the process terminates.
If `block` is false, it will return either the process exit code if it's already terminated or null if it's still running.
If the process has already exited, return the exit code immediately.
**/
function exitCode(block:Bool = true):Null<Int>;
/**
Close the process handle and release the associated resources.
All `Process` fields should not be used after `close()` is called.
**/
function close():Void;
/**
Kill the process.
**/
function kill():Void;
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.net;
/**
An address is used to represent a port on a given host ip.
It is used by `sys.net.UdpSocket`.
**/
class Address {
public var host:Int;
public var port:Int;
public function new() {
host = 0;
port = 0;
}
public function getHost() {
var h = new Host("127.0.0.1");
untyped h.ip = host;
return h;
}
public function compare(a:Address) {
var dh = a.host - host;
if (dh != 0)
return dh;
var dp = a.port - port;
if (dp != 0)
return dp;
return 0;
}
public function clone() {
var c = new Address();
c.host = host;
c.port = port;
return c;
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.net;
/**
A given IP host name.
**/
extern class Host {
/**
The provided host string.
**/
var host(default, null):String;
/**
The actual IP corresponding to the host.
**/
var ip(default, null):Int;
/**
Creates a new Host : the name can be an IP in the form "127.0.0.1" or an host name such as "google.com", in which case
the corresponding IP address is resolved using DNS. An exception occur if the host name could not be found.
**/
function new(name:String):Void;
/**
Returns the IP representation of the host
**/
function toString():String;
/**
Perform a reverse-DNS query to resolve a host name from an IP.
**/
function reverse():String;
/**
Returns the local computer host name
**/
static function localhost():String;
}

View File

@ -0,0 +1,139 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.net;
/**
A TCP socket class : allow you to both connect to a given server and exchange messages or start your own server and wait for connections.
**/
extern class Socket {
/**
The stream on which you can read available data. By default the stream is blocking until the requested data is available,
use `setBlocking(false)` or `setTimeout` to prevent infinite waiting.
**/
var input(default, null):haxe.io.Input;
/**
The stream on which you can send data. Please note that in case the output buffer you will block while writing the data, use `setBlocking(false)` or `setTimeout` to prevent that.
**/
var output(default, null):haxe.io.Output;
/**
A custom value that can be associated with the socket. Can be used to retrieve your custom infos after a `select`.
***/
var custom:Dynamic;
/**
Creates a new unconnected socket.
**/
function new():Void;
/**
Closes the socket : make sure to properly close all your sockets or you will crash when you run out of file descriptors.
**/
function close():Void;
/**
Read the whole data available on the socket.
*Note*: this is **not** meant to be used together with `setBlocking(false)`,
as it will always throw `haxe.io.Error.Blocked`. `input` methods should be used directly instead.
**/
function read():String;
/**
Write the whole data to the socket output.
*Note*: this is **not** meant to be used together with `setBlocking(false)`, as
`haxe.io.Error.Blocked` may be thrown mid-write with no indication of how many bytes have been written.
`output.writeBytes()` should be used instead as it returns this information.
**/
function write(content:String):Void;
/**
Connect to the given server host/port. Throw an exception in case we couldn't successfully connect.
**/
function connect(host:Host, port:Int):Void;
/**
Allow the socket to listen for incoming questions. The parameter tells how many pending connections we can have until they get refused. Use `accept()` to accept incoming connections.
**/
function listen(connections:Int):Void;
/**
Shutdown the socket, either for reading or writing.
**/
function shutdown(read:Bool, write:Bool):Void;
/**
Bind the socket to the given host/port so it can afterwards listen for connections there.
**/
function bind(host:Host, port:Int):Void;
/**
Accept a new connected client. This will return a connected socket on which you can read/write some data.
**/
function accept():Socket;
/**
Return the information about the other side of a connected socket.
**/
function peer():{host:Host, port:Int};
/**
Return the information about our side of a connected socket.
**/
function host():{host:Host, port:Int};
/**
Gives a timeout (in seconds) after which blocking socket operations (such as reading and writing) will abort and throw an exception.
**/
function setTimeout(timeout:Float):Void;
/**
Block until some data is available for read on the socket.
**/
function waitForRead():Void;
/**
Change the blocking mode of the socket. A blocking socket is the default behavior. A non-blocking socket will abort blocking operations immediately by throwing a haxe.io.Error.Blocked value.
**/
function setBlocking(b:Bool):Void;
/**
Allows the socket to immediately send the data when written to its output : this will cause less ping but might increase the number of packets / data size, especially when doing a lot of small writes.
**/
function setFastSend(b:Bool):Void;
/**
Wait until one of the sockets group is ready for the given operation:
- `read` contains sockets on which we want to wait for available data to be read,
- `write` contains sockets on which we want to wait until we are allowed to write some data to their output buffers,
- `others` contains sockets on which we want to wait for exceptional conditions.
- `select` will block until one of the condition is met, in which case it will return the sockets for which the condition was true.
In case a `timeout` (in seconds) is specified, select might wait at worst until the timeout expires.
**/
static function select(read:Array<Socket>, write:Array<Socket>, others:Array<Socket>,
?timeout:Float):{read:Array<Socket>, write:Array<Socket>, others:Array<Socket>};
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.net;
/**
A UDP socket class
**/
class UdpSocket extends Socket {
public function new() {
throw "Not available on this platform";
super();
}
/**
Allows the socket to send to broadcast addresses.
**/
public function setBroadcast(b:Bool):Void {
throw "Not available on this platform";
}
/**
Sends data to the specified target host/port address.
**/
public function sendTo(buf:haxe.io.Bytes, pos:Int, len:Int, addr:Address):Int {
return 0;
}
/**
Reads data from any incoming address and store the receiver address into the address parameter.
**/
public function readFrom(buf:haxe.io.Bytes, pos:Int, len:Int, addr:Address):Int {
return 0;
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.ssl;
extern class Certificate {
static function loadFile(file:String):Certificate;
static function loadPath(path:String):Certificate;
static function fromString(str:String):Certificate;
static function loadDefaults():Certificate;
var commonName(get, null):Null<String>;
var altNames(get, null):Array<String>;
var notBefore(get, null):Date;
var notAfter(get, null):Date;
function subject(field:String):Null<String>;
function issuer(field:String):Null<String>;
function next():Null<Certificate>;
function add(pem:String):Void;
function addDER(der:haxe.io.Bytes):Void;
private function get_commonName():Null<String>;
private function get_altNames():Array<String>;
private function get_notBefore():Date;
private function get_notAfter():Date;
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.ssl;
extern class Digest {
static function make(data:haxe.io.Bytes, alg:DigestAlgorithm):haxe.io.Bytes;
static function sign(data:haxe.io.Bytes, privKey:Key, alg:DigestAlgorithm):haxe.io.Bytes;
static function verify(data:haxe.io.Bytes, signature:haxe.io.Bytes, pubKey:Key, alg:DigestAlgorithm):Bool;
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.ssl;
enum abstract DigestAlgorithm(String) to String {
var MD5 = "MD5";
var SHA1 = "SHA1";
var SHA224 = "SHA224";
var SHA256 = "SHA256";
var SHA384 = "SHA384";
var SHA512 = "SHA512";
var RIPEMD160 = "RIPEMD160";
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.ssl;
extern class Key {
static function loadFile(file:String, ?isPublic:Bool, ?pass:String):Key;
static function readPEM(data:String, isPublic:Bool, ?pass:String):Key;
static function readDER(data:haxe.io.Bytes, isPublic:Bool):Key;
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.ssl;
/**
A TLS socket class : allow you to both connect to a given server and exchange messages or start your own server and wait for connections.
**/
extern class Socket extends sys.net.Socket {
static var DEFAULT_VERIFY_CERT:Null<Bool>;
static var DEFAULT_CA:Null<sys.ssl.Certificate>;
/**
Define if peer certificate is verified during SSL handshake.
**/
var verifyCert:Null<Bool>;
function new():Void;
/**
Perform the SSL handshake.
**/
function handshake():Void;
/**
Configure the certificate chain for peer certificate verification.
**/
function setCA(cert:sys.ssl.Certificate):Void;
/**
Configure the hostname for Server Name Indication TLS extension.
**/
function setHostname(name:String):Void;
/**
Configure own certificate and private key.
**/
function setCertificate(cert:Certificate, key:Key):Void;
/**
Configure additionals certificates and private keys for Server Name Indication extension.
The callback may be called during handshake to determine the certificate to use.
**/
function addSNICertificate(cbServernameMatch:String->Bool, cert:Certificate, key:Key):Void;
/**
Return the certificate received from the other side of a connection.
**/
function peerCertificate():sys.ssl.Certificate;
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.thread;
#if (!target.threaded)
#error "This class is not available on this target"
#end
/**
A Deque is a double-ended queue with a `pop` method that can block until
an element is available. It is commonly used to synchronize threads.
*/
@:coreApi extern class Deque<T> {
/**
Create a new Deque instance which is initially empty.
**/
function new():Void;
/**
Adds an element at the end of `this` Deque.
(Java,Jvm): throws `java.lang.NullPointerException` if `i` is `null`.
**/
function add(i:T):Void;
/**
Adds an element at the front of `this` Deque.
(Java,Jvm): throws `java.lang.NullPointerException` if `i` is `null`.
**/
function push(i:T):Void;
/**
Tries to retrieve an element from the front of `this` Deque.
If an element is available, it is removed from the queue and returned.
If no element is available and `block` is `false`, `null` is returned.
Otherwise, execution blocks until an element is available and returns it.
**/
function pop(block:Bool):Null<T>;
}

View File

@ -0,0 +1,198 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.thread;
#if (!target.threaded)
#error "This class is not available on this target"
#end
import haxe.Exception;
/**
Thread pool with a varying amount of threads.
A new thread is spawned every time a task is submitted while all existing
threads are busy.
**/
@:coreApi
class ElasticThreadPool implements IThreadPool {
/* Amount of alive threads in this pool. */
public var threadsCount(get,null):Int;
/* Maximum amount of threads in this pool. */
public var maxThreadsCount:Int;
/** Indicates if `shutdown` method of this pool has been called. */
public var isShutdown(get,never):Bool;
var _isShutdown = false;
function get_isShutdown():Bool return _isShutdown;
final pool:Array<Worker> = [];
final queue = new Deque<()->Void>();
final mutex = new Mutex();
final threadTimeout:Float;
/**
Create a new thread pool with `threadsCount` threads.
If a worker thread does not receive a task for `threadTimeout` seconds it
is terminated.
**/
public function new(maxThreadsCount:Int, threadTimeout:Float = 60):Void {
if(maxThreadsCount < 1)
throw new ThreadPoolException('ElasticThreadPool needs maxThreadsCount to be at least 1.');
this.maxThreadsCount = maxThreadsCount;
this.threadTimeout = threadTimeout;
}
/**
Submit a task to run in a thread.
Throws an exception if the pool is shut down.
**/
public function run(task:()->Void):Void {
if(_isShutdown)
throw new ThreadPoolException('Task is rejected. Thread pool is shut down.');
if(task == null)
throw new ThreadPoolException('Task to run must not be null.');
mutex.acquire();
var submitted = false;
var deadWorker = null;
for(worker in pool) {
if(deadWorker == null && worker.dead) {
deadWorker = worker;
}
if(worker.task == null) {
submitted = true;
worker.wakeup(task);
break;
}
}
if(!submitted) {
if(deadWorker != null) {
deadWorker.wakeup(task);
} else if(pool.length < maxThreadsCount) {
var worker = new Worker(queue, threadTimeout);
pool.push(worker);
worker.wakeup(task);
} else {
queue.add(task);
}
}
mutex.release();
}
/**
Initiates a shutdown.
All previousely submitted tasks will be executed, but no new tasks will
be accepted.
Multiple calls to this method have no effect.
**/
public function shutdown():Void {
if(_isShutdown) return;
mutex.acquire();
_isShutdown = true;
for(worker in pool) {
worker.shutdown();
}
mutex.release();
}
function get_threadsCount():Int {
var result = 0;
for(worker in pool)
if(!worker.dead)
++result;
return result;
}
}
private class Worker {
public var task(default,null):Null<()->Void>;
public var dead(default,null) = false;
final deathMutex = new Mutex();
final waiter = new Lock();
final queue:Deque<()->Void>;
final timeout:Float;
var thread:Thread;
var isShutdown = false;
public function new(queue:Deque<()->Void>, timeout:Float) {
this.queue = queue;
this.timeout = timeout;
start();
}
public function wakeup(task:()->Void) {
deathMutex.acquire();
if(dead)
start();
this.task = task;
waiter.release();
deathMutex.release();
}
public function shutdown() {
isShutdown = true;
waiter.release();
}
function start() {
dead = false;
thread = Thread.create(loop);
}
function loop() {
try {
while(waiter.wait(timeout)) {
switch task {
case null:
if(isShutdown)
break;
case fn:
fn();
//if more tasks were added while all threads were busy
while(true) {
switch queue.pop(false) {
case null: break;
case fn: fn();
}
}
task = null;
}
}
deathMutex.acquire();
//in case a task was submitted right after the lock timed out
if(task != null)
start()
else
dead = true;
deathMutex.release();
} catch(e) {
task = null;
start();
throw e;
}
}
}

View File

@ -0,0 +1,275 @@
package sys.thread;
/**
When an event loop has an available event to execute.
**/
enum NextEventTime {
/** There's already an event waiting to be executed */
Now;
/** No new events are expected. */
Never;
/**
An event is expected to arrive at any time.
If `time` is specified, then the event will be ready at that time for sure.
*/
AnyTime(time:Null<Float>);
/** An event is expected to be ready for execution at `time`. */
At(time:Float);
}
/**
An event loop implementation used for `sys.thread.Thread`
**/
@:coreApi
class EventLoop {
final mutex = new Mutex();
final oneTimeEvents = new Array<Null<()->Void>>();
var oneTimeEventsIdx = 0;
final waitLock = new Lock();
var promisedEventsCount = 0;
var regularEvents:Null<RegularEvent>;
public function new():Void {}
/**
Schedule event for execution every `intervalMs` milliseconds in current loop.
**/
public function repeat(event:()->Void, intervalMs:Int):EventHandler {
mutex.acquire();
var interval = 0.001 * intervalMs;
var event = new RegularEvent(event, Sys.time() + interval, interval);
inline insertEventByTime(event);
waitLock.release();
mutex.release();
return event;
}
function insertEventByTime(event:RegularEvent):Void {
switch regularEvents {
case null:
regularEvents = event;
case current:
var previous = null;
while(true) {
if(current == null) {
previous.next = event;
event.previous = previous;
break;
} else if(event.nextRunTime < current.nextRunTime) {
event.next = current;
current.previous = event;
switch previous {
case null:
regularEvents = event;
case _:
event.previous = previous;
previous.next = event;
current.previous = event;
}
break;
} else {
previous = current;
current = current.next;
}
}
}
}
/**
Prevent execution of a previously scheduled event in current loop.
**/
public function cancel(eventHandler:EventHandler):Void {
mutex.acquire();
var event:RegularEvent = eventHandler;
event.cancelled = true;
if(regularEvents == event) {
regularEvents = event.next;
}
switch event.next {
case null:
case e: e.previous = event.previous;
}
switch event.previous {
case null:
case e: e.next = event.next;
}
mutex.release();
}
/**
Notify this loop about an upcoming event.
This makes the thread to stay alive and wait for as many events as many times
`.promise()` was called. These events should be added via `.runPromised()`
**/
public function promise():Void {
mutex.acquire();
++promisedEventsCount;
mutex.release();
}
/**
Execute `event` as soon as possible.
**/
public function run(event:()->Void):Void {
mutex.acquire();
oneTimeEvents[oneTimeEventsIdx++] = event;
waitLock.release();
mutex.release();
}
/**
Add previously promised `event` for execution.
**/
public function runPromised(event:()->Void):Void {
mutex.acquire();
oneTimeEvents[oneTimeEventsIdx++] = event;
--promisedEventsCount;
waitLock.release();
mutex.release();
}
/**
Executes all pending events.
The returned time stamps can be used with `Sys.time()` for calculations.
Depending on a target platform this method may be non-reentrant. It must
not be called from event callbacks.
**/
public function progress():NextEventTime {
return switch __progress(Sys.time(), [], []) {
case {nextEventAt:-2}: Now;
case {nextEventAt:-1, anyTime:false}: Never;
case {nextEventAt:-1, anyTime:true}: AnyTime(null);
case {nextEventAt:time, anyTime:true}: AnyTime(time);
case {nextEventAt:time, anyTime:false}: At(time);
}
}
/**
Blocks until a new event is added or `timeout` (in seconds) to expires.
Depending on a target platform this method may also automatically execute arriving
events while waiting. However if any event is executed it will stop waiting.
Returns `true` if more events are expected.
Returns `false` if no more events expected.
Depending on a target platform this method may be non-reentrant. It must
not be called from event callbacks.
**/
public function wait(?timeout:Float):Bool {
return waitLock.wait(timeout);
}
/**
Execute all pending events.
Wait and execute as many events as many times `promiseEvent()` was called.
Runs until all repeating events are cancelled and no more events is expected.
Depending on a target platform this method may be non-reentrant. It must
not be called from event callbacks.
**/
public function loop():Void {
var recycleRegular = [];
var recycleOneTimers = [];
while(true) {
var r = __progress(Sys.time(), recycleRegular, recycleOneTimers);
switch r {
case {nextEventAt:-2}:
case {nextEventAt:-1, anyTime:false}:
break;
case {nextEventAt:-1, anyTime:true}:
waitLock.wait();
case {nextEventAt:time}:
var timeout = time - Sys.time();
waitLock.wait(Math.max(0, timeout));
}
}
}
/**
`.progress` implementation with a reusable array for internal usage.
The `nextEventAt` field of the return value denotes when the next event
is expected to run:
* -1 - never
* -2 - now
* other values - at specified time
**/
inline function __progress(now:Float, recycleRegular:Array<RegularEvent>, recycleOneTimers:Array<()->Void>):{nextEventAt:Float, anyTime:Bool} {
var regularsToRun = recycleRegular;
var eventsToRunIdx = 0;
// When the next event is expected to run
var nextEventAt:Float = -1;
mutex.acquire();
//reset waitLock
while(waitLock.wait(0.0)) {}
// Collect regular events to run
var current = regularEvents;
while(current != null) {
if(current.nextRunTime <= now) {
regularsToRun[eventsToRunIdx++] = current;
current.nextRunTime += current.interval;
nextEventAt = -2;
} else if(nextEventAt == -1 || current.nextRunTime < nextEventAt) {
nextEventAt = current.nextRunTime;
}
current = current.next;
}
mutex.release();
// Run regular events
for(i in 0...eventsToRunIdx) {
if(!regularsToRun[i].cancelled)
regularsToRun[i].run();
regularsToRun[i] = null;
}
eventsToRunIdx = 0;
var oneTimersToRun = recycleOneTimers;
// Collect pending one-time events
mutex.acquire();
for(i => event in oneTimeEvents) {
switch event {
case null:
break;
case _:
oneTimersToRun[eventsToRunIdx++] = event;
oneTimeEvents[i] = null;
}
}
oneTimeEventsIdx = 0;
var hasPromisedEvents = promisedEventsCount > 0;
mutex.release();
//run events
for(i in 0...eventsToRunIdx) {
oneTimersToRun[i]();
oneTimersToRun[i] = null;
}
// Some events were executed. They could add new events to run.
if(eventsToRunIdx > 0) {
nextEventAt = -2;
}
return {nextEventAt:nextEventAt, anyTime:hasPromisedEvents}
}
}
abstract EventHandler(RegularEvent) from RegularEvent to RegularEvent {}
private class RegularEvent {
public var nextRunTime:Float;
public final interval:Float;
public final run:()->Void;
public var next:Null<RegularEvent>;
public var previous:Null<RegularEvent>;
public var cancelled:Bool = false;
public function new(run:()->Void, nextRunTime:Float, interval:Float) {
this.run = run;
this.nextRunTime = nextRunTime;
this.interval = interval;
}
}

View File

@ -0,0 +1,116 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.thread;
#if (!target.threaded)
#error "This class is not available on this target"
#end
import haxe.Exception;
/**
Thread pool with a constant amount of threads.
Threads in the pool will exist until the pool is explicitly shut down.
**/
@:coreApi
class FixedThreadPool implements IThreadPool {
/* Amount of threads in this pool. */
public var threadsCount(get,null):Int;
function get_threadsCount():Int return threadsCount;
/** Indicates if `shutdown` method of this pool has been called. */
public var isShutdown(get,never):Bool;
var _isShutdown = false;
function get_isShutdown():Bool return _isShutdown;
final pool:Array<Worker>;
final poolMutex = new Mutex();
final queue = new Deque<()->Void>();
/**
Create a new thread pool with `threadsCount` threads.
**/
public function new(threadsCount:Int):Void {
if(threadsCount < 1)
throw new ThreadPoolException('FixedThreadPool needs threadsCount to be at least 1.');
this.threadsCount = threadsCount;
pool = [for(i in 0...threadsCount) new Worker(queue)];
}
/**
Submit a task to run in a thread.
Throws an exception if the pool is shut down.
**/
public function run(task:()->Void):Void {
if(_isShutdown)
throw new ThreadPoolException('Task is rejected. Thread pool is shut down.');
if(task == null)
throw new ThreadPoolException('Task to run must not be null.');
queue.add(task);
}
/**
Initiates a shutdown.
All previousely submitted tasks will be executed, but no new tasks will
be accepted.
Multiple calls to this method have no effect.
**/
public function shutdown():Void {
if(_isShutdown) return;
_isShutdown = true;
for(_ in pool) {
queue.add(shutdownTask);
}
}
static function shutdownTask():Void {
throw new ShutdownException('');
}
}
private class ShutdownException extends Exception {}
private class Worker {
var thread:Thread;
final queue:Deque<Null<()->Void>>;
public function new(queue:Deque<Null<()->Void>>) {
this.queue = queue;
thread = Thread.create(loop);
}
function loop() {
try {
while(true) {
var task = queue.pop(true);
task();
}
} catch(_:ShutdownException) {
} catch(e) {
thread = Thread.create(loop);
throw e;
}
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.thread;
/**
A thread pool interface.
**/
interface IThreadPool {
/** Amount of alive threads in this pool. */
var threadsCount(get,never):Int;
/** Indicates if `shutdown` method of this pool has been called. */
var isShutdown(get,never):Bool;
/**
Submit a task to run in a thread.
Throws an exception if the pool is shut down.
**/
function run(task:()->Void):Void;
/**
Initiates a shutdown.
All previousely submitted tasks will be executed, but no new tasks will
be accepted.
Multiple calls to this method have no effect.
**/
function shutdown():Void;
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.thread;
#if (!target.threaded)
#error "This class is not available on this target"
#end
/**
A Lock allows blocking execution until it has been unlocked. It keeps track
of how often `release` has been called, and blocks exactly as many `wait`
calls.
The order of the `release` and `wait` calls is irrelevant. That is, a Lock
can be released before anyone waits for it. In that case, the `wait` call
will execute immediately.
Usage example:
```haxe
var lock = new Lock();
var elements = [1, 2, 3];
for (element in elements) {
// Create one thread per element
new Thread(function() {
trace(element);
Sys.sleep(1);
// Release once per thread = 3 times
lock.release();
});
}
for (_ in elements) {
// Wait 3 times
lock.wait();
}
trace("All threads finished");
```
**/
extern class Lock {
/**
Creates a new Lock which is initially locked.
**/
function new():Void;
/**
Waits for the lock to be released, or `timeout` (in seconds)
to expire. Returns `true` if the lock is released and `false`
if a time-out occurs.
**/
function wait(?timeout:Float):Bool;
/**
Releases the lock once.
The thread does not need to own the lock in order to release
it. Each call to `release` allows exactly one call to `wait`
to execute.
**/
function release():Void;
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.thread;
#if (!target.threaded)
#error "This class is not available on this target"
#end
/**
Creates a mutex, which can be used to acquire a temporary lock
to access some ressource. The main difference with a lock is
that a mutex must always be released by the owner thread.
**/
extern class Mutex {
/**
Creates a mutex.
**/
function new():Void;
/**
The current thread acquire the mutex or wait if not available.
The same thread can acquire several times the same mutex but
must release it as many times it has been acquired.
**/
function acquire():Void;
/**
Try to acquire the mutex, returns true if acquire or false
if it's already locked by another thread.
**/
function tryAcquire():Bool;
/**
Release a mutex that has been acquired by the current thread.
The behavior is undefined if the current thread does not own
the mutex.
**/
function release():Void;
}

View File

@ -0,0 +1,9 @@
package sys.thread;
import haxe.Exception;
class NoEventLoopException extends Exception {
public function new(msg:String = 'Event loop is not available. Refer to sys.thread.Thread.runWithEventLoop.', ?previous:Exception) {
super(msg, previous);
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.thread;
#if (!target.threaded)
#error "This class is not available on this target"
#end
private typedef ThreadImpl = {};
extern abstract Thread(ThreadImpl) from ThreadImpl {
/**
Event loop of this thread (if available).
Note that by default event loop is only available in the main thread.
To setup an event loop in other threads use `sys.thread.Thread.runWithEventLoop`
or create new threads with built-in event loops using `sys.thread.Thread.createWithEventLoop`
**/
public var events(get,never):EventLoop;
/**
Send a message to the thread queue. This message can be read by using `readMessage`.
**/
public function sendMessage(msg:Dynamic):Void;
/**
Returns the current thread.
**/
public static function current():Thread;
/**
Creates a new thread that will execute the `job` function, then exit.
This function does not setup an event loop for a new thread.
**/
public static function create(job:()->Void):Thread;
/**
Simply execute `job` if current thread already has an event loop.
But if current thread does not have an event loop: setup event loop,
run `job` and then destroy event loop. And in this case this function
does not return until no more events left to run.
**/
public static function runWithEventLoop(job:()->Void):Void;
/**
This is logically equal to `Thread.create(() -> Thread.runWithEventLoop(job));`
**/
public static function createWithEventLoop(job:()->Void):Thread;
/**
Reads a message from the thread queue. If `block` is true, the function
blocks until a message is available. If `block` is false, the function
returns `null` if no message is available.
**/
public static function readMessage(block:Bool):Dynamic;
/**
Run event loop of the current thread
**/
private static function processEvents():Void;
}

View File

@ -0,0 +1,6 @@
package sys.thread;
import haxe.Exception;
class ThreadPoolException extends Exception {
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (C)2005-2019 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package sys.thread;
#if (!target.threaded)
#error "This class is not available on this target"
#end
/**
Creates thread local storage.
(hl) Warning: At the moment `Tls` does not protect the value from being
garbage collected. Keep the value reachable to avoid crashes.
**/
extern class Tls<T> {
var value(get, set):T;
/**
Creates thread local storage. This is placeholder that can store
a value that will be different depending on the local thread.
Set the tls value to `null` before exiting the thread
or the memory will never be collected.
**/
function new():Void;
}