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,267 @@
/*
* 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.
*/
import haxe.iterators.ArrayKeyValueIterator;
@:coreApi
class Array<T> {
public var length(default, null):Int;
public function new():Void {
untyped _hx_tab_array(this, 0);
}
public function concat(a:Array<T>):Array<T> {
var ret = this.copy();
for (i in a)
ret.push(i);
return ret;
}
public function join(sep:String):String {
var tbl:lua.Table<Int, String> = lua.Table.create();
for (i in iterator()) {
lua.Table.insert(tbl, Std.string(i));
}
return lua.Table.concat(tbl, sep);
}
public function pop():Null<T> {
if (length == 0)
return null;
var ret = this[length - 1];
this[length - 1] = null;
length--;
return ret;
}
public function push(x:T):Int {
this[this.length] = x;
return length;
}
public function reverse():Void {
var tmp:T;
var i = 0;
while (i < Std.int(this.length / 2)) {
tmp = this[i];
this[i] = this[this.length - i - 1];
this[this.length - i - 1] = tmp;
i++;
}
}
public function shift():Null<T> {
if (this.length == 0)
return null;
var ret = this[0];
if (this.length == 1) {
this[0] = null;
} else if (this.length > 1) {
this[0] = this[1];
lua.Table.remove(untyped this, 1);
}
this.length -= 1;
return ret;
}
public function slice(pos:Int, ?end:Int):Array<T> {
if (end == null || end > length)
end = length;
else if (end < 0)
end = (length - (-end % length)) % length; // negative pos needs to be wrapped from the end, and mod according to array length
if (pos < 0)
pos = (length - (-pos % length)) % length; // and here
if (pos > end || pos > length)
return [];
var ret = [];
for (i in pos...end) {
ret.push(this[i]);
}
return ret;
}
// TODO: copied from neko Array.sort, move to general util library?
public function sort(f:T->T->Int):Void {
var i = 0;
var l = this.length;
while (i < l) {
var swap = false;
var j = 0;
var max = l - i - 1;
while (j < max) {
if (f(this[j], this[j + 1]) > 0) {
var tmp = this[j + 1];
this[j + 1] = this[j];
this[j] = tmp;
swap = true;
}
j += 1;
}
if (!swap)
break;
i += 1;
}
}
public function splice(pos:Int, len:Int):Array<T> {
if (len < 0 || pos > length)
return [];
else if (pos < 0)
pos = length - (-pos % length);
len = cast Math.min(len, this.length - pos);
var ret = [];
for (i in pos...(pos + len)) {
ret.push(this[i]);
this[i] = this[i + len];
}
for (i in (pos + len)...length) {
this[i] = this[i + len];
}
this.length -= len;
return ret;
}
public function toString():String {
var tbl:lua.Table<Int, String> = lua.Table.create();
lua.Table.insert(tbl, '[');
lua.Table.insert(tbl, join(","));
lua.Table.insert(tbl, ']');
return lua.Table.concat(tbl, "");
}
public function unshift(x:T):Void {
var len = length;
for (i in 0...len)
this[len - i] = this[len - i - 1];
this[0] = x;
}
public inline function insert(pos:Int, x:T):Void {
if (pos > length)
pos = length;
if (pos < 0) {
pos = (length + pos);
if (pos < 0)
pos = 0;
}
var cur_len = length;
while (cur_len > pos) {
this[cur_len] = this[cur_len - 1];
cur_len -= 1;
}
this[pos] = x;
}
public function remove(x:T):Bool {
for (i in 0...length) {
if (this[i] == x) {
for (j in i...length - 1) {
this[j] = this[j + 1];
}
// We need to decrement the length variable, and set its
// value to null to avoid hanging on to a reference in the
// underlying lua table.
this[length - 1] = null;
// Do this in two steps to avoid re-updating the __index metamethod
length--;
return true;
}
}
return false;
}
public function contains(x:T):Bool {
for (i in 0...length) {
if (this[i] == x)
return true;
}
return false;
}
public function indexOf(x:T, ?fromIndex:Int):Int {
var end = length;
if (fromIndex == null)
fromIndex = 0;
else if (fromIndex < 0) {
fromIndex = length + fromIndex;
if (fromIndex < 0)
fromIndex = 0;
}
for (i in fromIndex...end) {
if (x == this[i])
return i;
}
return -1;
}
public function lastIndexOf(x:T, ?fromIndex:Int):Int {
if (fromIndex == null || fromIndex >= length)
fromIndex = length - 1;
else if (fromIndex < 0) {
fromIndex = length + fromIndex;
if (fromIndex < 0)
return -1;
}
var i = fromIndex;
while (i >= 0) {
if (this[i] == x)
return i;
else
i--;
}
return -1;
}
public inline function copy():Array<T> {
return [for (i in this) i];
}
public inline function map<S>(f:T->S):Array<S> {
return [for (i in this) f(i)];
}
public inline function filter(f:T->Bool):Array<T> {
return [for (i in this) if (f(i)) i];
}
public inline function iterator():haxe.iterators.ArrayIterator<T> {
return new haxe.iterators.ArrayIterator(this);
}
public inline function keyValueIterator():ArrayKeyValueIterator<T> {
return new ArrayKeyValueIterator(this);
}
public function resize(len:Int):Void {
if (length < len) {
this.length = len;
} else if (length > len) {
for (i in len...length) {
this[i] = null;
}
this.length = len;
}
}
}

View File

@ -0,0 +1,112 @@
/*
* 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.
*/
@:coreApi class Date {
var d:lua.Os.DateType;
var dUTC:lua.Os.DateType;
var t:lua.Time;
public function new(year:Int, month:Int, day:Int, hour:Int, min:Int, sec:Int) {
t = lua.Os.time({
year: year,
month: month + 1,
day: day,
hour: hour,
min: min,
sec: sec
});
d = lua.Os.date("*t", t);
dUTC = lua.Os.date("!*t", t);
};
public function getTime():Float
return cast t * 1000;
public function getHours():Int
return d.hour;
public function getMinutes():Int
return d.min;
public function getSeconds():Int
return d.sec;
public function getFullYear():Int
return d.year;
public function getMonth():Int
return d.month - 1;
public function getDate():Int
return d.day;
public function getDay():Int
return d.wday - 1;
public function getUTCHours():Int
return dUTC.hour;
public function getUTCMinutes():Int
return dUTC.min;
public function getUTCSeconds():Int
return dUTC.sec;
public function getUTCFullYear():Int
return dUTC.year;
public function getUTCMonth():Int
return dUTC.month - 1;
public function getUTCDate():Int
return dUTC.day;
public function getUTCDay():Int
return dUTC.wday - 1;
public function getTimezoneOffset():Int {
var tUTC = lua.Os.time(dUTC);
return Std.int((tUTC - t) / 60);
}
public inline function toString():String {
return lua.Boot.dateStr(this);
}
public static inline function now():Date {
return fromTime(lua.Os.time() * 1000);
}
public static inline function fromTime(t:Float):Date {
var d:Dynamic = {}
untyped {
lua.Lua.setmetatable(d, untyped {__index: Date.prototype});
d.t = t / 1000;
d.d = lua.Os.date("*t", Std.int(d.t));
d.dUTC = lua.Os.date("!*t", Std.int(d.t));
}
return d;
}
public static inline function fromString(s:String):Date {
return lua.Boot.strDate(s);
}
}

View File

@ -0,0 +1,214 @@
/*
* 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.
*/
import lua.Table;
import lua.Lib;
import lua.lib.lrexlib.Rex;
// Note - lrexlib gives ascii-based offsets. Use native string tools.
import lua.NativeStringTools.*;
@:coreApi
class EReg {
var r:Rex; // the Rex extern instance.
var global:Bool; // whether the regex is in global mode.
var s:String; // the last matched string
var m:Table<Int, Int>; // the [start:Int, end:Int, and submatches:String (matched groups)] as a single table.
static var FLAGS:Table<String, Int> = Rex.flags();
public function new(r:String, opt:String):Void {
var ropt = 0;
for (i in 0...opt.length) {
switch (opt.charAt(i)) {
case "i":
ropt |= FLAGS.CASELESS;
case "m":
ropt |= FLAGS.MULTILINE;
case "s":
ropt |= FLAGS.DOTALL;
case "g":
global = true;
default:
null;
}
}
ropt |= FLAGS.UTF8; // always check validity of utf8 string
ropt |= FLAGS.UCP; // always enable utf8 character properties
if (global == null)
global = false;
this.r = Rex.create(r, ropt);
}
public function match(s:String):Bool {
return matchFromByte(s, 1);
}
inline function matchFromByte(s:String, offset:Int):Bool {
if (s == null)
return false;
this.m = lua.TableTools.pack(r.exec(s, offset));
this.s = s;
return m[1] != null;
}
public function matched(n:Int):String {
if (m[1] == null || n < 0)
throw "EReg::matched";
else if (n == 0) {
var k = sub(s, m[1], m[2]).match;
return k;
} else if (Std.isOfType(m[3], lua.Table)) {
var mn = 2 * (n - 1);
if (Std.isOfType(untyped m[3][mn + 1], Bool))
return null;
return sub(s, untyped m[3][mn + 1], untyped m[3][mn + 2]).match;
} else {
throw "EReg:matched";
}
}
public function matchedLeft():String {
if (m[1] == null)
throw "No string matched";
return sub(s, 1, m[1] - 1).match;
}
public function matchedRight():String {
if (m[1] == null)
throw "No string matched";
return sub(s, m[2] + 1).match;
}
public function matchedPos():{pos:Int, len:Int} {
var left = matchedLeft();
var matched = matched(0);
if (m[1] == null)
throw "No string matched";
return {
pos: left.length,
len: matched.length
}
}
public function matchSub(s:String, pos:Int, len:Int = -1):Bool {
var ss = s.substr(0, len < 0 ? s.length : pos + len);
if (global) {
m = lua.TableTools.pack(r.exec(ss, pos + 1));
var b = m[1] != null;
if (b) {
this.s = s;
}
return b;
} else {
m = lua.TableTools.pack(r.exec(ss, pos + 1));
var b = m[1] != null;
if (b) {
this.s = s;
}
return b;
}
}
public function split(s:String):Array<String> {
if (global) {
return Lib.fillArray(Rex.split(s, r));
} else {
// we can't use directly Rex.split because it's ignoring the 'g' flag
var d = "#__delim__#";
return Lib.fillArray(Rex.split(replace(s, d), d));
}
}
public function replace(s:String, by:String):String {
var chunks = by.split("$$");
chunks = [for (chunk in chunks) Rex.gsub(chunk, "\\$(\\d)", "%%%1", 1)];
by = chunks.join("$");
return Rex.gsub(s, r, by, global ? null : 1);
}
public function map(s:String, f:EReg->String):String {
var bytesOffset = 1;
var buf = new StringBuf();
do {
if (bytesOffset > len(s)) {
break;
} else if (!matchFromByte(s, bytesOffset)) {
buf.add(sub(s, bytesOffset).match);
break;
}
var pos = m[1];
var length = m[2] - m[1];
buf.add(sub(s, bytesOffset, pos - 1).match);
buf.add(f(this));
if (length < 0) {
var charBytes = len(sub(s, pos).match.charAt(0));
buf.add(sub(s, pos, pos + charBytes - 1).match);
bytesOffset = pos + charBytes;
} else {
bytesOffset = m[2] + 1;
}
} while (global);
if (!global && bytesOffset > 1 && bytesOffset - 1 < len(s))
buf.add(sub(s, bytesOffset).match);
return buf.toString();
}
function map_old(s:String, f:EReg->String):String {
var offset = 0;
var buf = new StringBuf();
do {
if (offset >= s.length) {
break;
} else if (!matchSub(s, offset)) {
buf.add(s.substr(offset));
break;
}
var p = matchedPos();
buf.add(s.substr(offset, p.pos - offset));
buf.add(f(this));
if (p.len == 0) {
buf.add(s.substr(p.pos, 1));
offset = p.pos + 1;
} else
offset = p.pos + p.len;
} while (global);
if (!global && offset > 0 && offset < s.length)
buf.add(s.substr(offset));
return buf.toString();
}
public static function escape(s:String):String {
return escapeRegExpRe.map(s, function(r) return "\\" + r.matched(0));
}
static var escapeRegExpRe = ~/[\[\]{}()*+?.\\\^$|]/g;
static function __init__():Void {
if (Rex == null) {
throw "Rex is missing. Please install lrexlib-pcre.";
}
}
}

View File

@ -0,0 +1,119 @@
/*
* 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;
class Math {
public static var PI(get, null):Float;
static inline function get_PI():Float
return lua.Math.pi;
public static var NEGATIVE_INFINITY(get, null):Float;
static inline function get_NEGATIVE_INFINITY():Float
return -lua.Math.huge;
public static var POSITIVE_INFINITY(get, null):Float;
static inline function get_POSITIVE_INFINITY():Float
return lua.Math.huge;
public static var NaN(get, null):Float;
// Note: this has to be an untyped literal, otherwise the compiler tries
// to unify it to an Int, which defeats useful numeric reflection behavior.
static inline function get_NaN():Float
return untyped __lua__("(0/0)");
public static function isNaN(f:Float):Bool
return (f != f);
public static function isFinite(f:Float):Bool {
return (f > Math.NEGATIVE_INFINITY && f < Math.POSITIVE_INFINITY);
}
public static inline function abs(v:Float):Float
return lua.Math.abs(v);
public static inline function acos(v:Float):Float
return lua.Math.acos(v);
public static inline function asin(v:Float):Float
return lua.Math.asin(v);
public static inline function atan(v:Float):Float
return lua.Math.atan(v);
public static inline function ceil(v:Float):Int
return lua.Math.ceil(v);
public static inline function cos(v:Float):Float
return lua.Math.cos(v);
public static inline function exp(v:Float):Float
return lua.Math.exp(v);
public static inline function sin(v:Float):Float
return lua.Math.sin(v);
public static inline function sqrt(v:Float):Float
return lua.Math.sqrt(v);
public static inline function tan(v:Float):Float
return lua.Math.tan(v);
public static inline function floor(v:Float):Int
return lua.Math.floor(v);
public static inline function log(v:Float):Float
return lua.Math.log(v);
public static inline function random():Float
return untyped __define_feature__("Math.random", lua.Math.random());
public static inline function atan2(y:Float, x:Float):Float
return lua.Math.atan2(y, x);
public static function max(a:Float, b:Float):Float {
return Math.isNaN(a) || Math.isNaN(b) ? Math.NaN : lua.Math.max(a, b);
}
public static function min(a:Float, b:Float):Float {
return Math.isNaN(a) || Math.isNaN(b) ? Math.NaN : lua.Math.min(a, b);
}
public static inline function pow(v:Float, exp:Float):Float
return lua.Math.pow(v, exp);
public static inline function round(v:Float):Int
return Math.floor(v + 0.5);
public static inline function ffloor(v:Float):Float
return floor(v);
public static inline function fceil(v:Float):Float
return ceil(v);
public static inline function fround(v:Float):Float
return round(v);
}

View File

@ -0,0 +1,166 @@
/*
* 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.
*/
import lua.Lua;
import lua.TableTools;
import lua.Boot;
@:coreApi class Reflect {
public inline static function hasField(o:Dynamic, field:String):Bool {
if (Lua.type(o) == "string" && (untyped String.prototype[field] != null || field == "length")) {
return true;
} else
return untyped o.__fields__ != null ? o.__fields__[field] != null : o[field] != null;
}
public static function field(o:Dynamic, field:String):Dynamic
untyped {
if (Lua.type(o) == "string") {
if (field == "length") {
return cast(o : String).length;
} else
return untyped String.prototype[field];
} else {
return try o[field] catch (e:Dynamic) null;
}
}
public inline static function setField(o:Dynamic, field:String, value:Dynamic):Void
untyped {
o[field] = value;
}
public static function getProperty(o:Dynamic, field:String):Dynamic {
return if (o == null) {
untyped __define_feature__("Reflect.getProperty", null);
} else if (o.__properties__ != null && Reflect.field(o, "get_" + field) != null) {
callMethod(o, Reflect.field(o, "get_" + field), []);
} else {
Reflect.field(o, field);
}
}
public static function setProperty(o:Dynamic, field:String, value:Dynamic):Void
untyped {
if (o.__properties__ != null && o.__properties__["set_" + field]) {
var tmp:String = o.__properties__["set_" + field];
callMethod(o, Reflect.field(o, tmp), [value]);
} else {
o[field] = __define_feature__("Reflect.setProperty", value);
}
}
public static function callMethod(o:Dynamic, func:haxe.Constraints.Function, args:Array<Dynamic>):Dynamic {
if (args == null || args.length == 0) {
return func(o);
} else {
var self_arg = false;
if (o != null && o.__name__ == null) {
self_arg = true;
}
return if (self_arg) {
func(o, lua.TableTools.unpack(cast args, 0, args.length - 1));
} else {
func(lua.TableTools.unpack(cast args, 0, args.length - 1));
}
}
}
public static function fields(o:Dynamic):Array<String> {
if (lua.Lua.type(o) == "string") {
return Reflect.fields(untyped String.prototype);
} else {
return untyped _hx_field_arr(o);
}
}
public static function isFunction(f:Dynamic):Bool {
return Lua.type(f) == "function" && !(Boot.isClass(f) || Boot.isEnum(f));
}
public static function compare<T>(a:T, b:T):Int {
if (a == b)
return 0
else if (a == null)
return -1
else if (b == null)
return 1
else
return (cast a) > (cast b) ? 1 : -1;
}
public static function compareMethods(f1:Dynamic, f2:Dynamic):Bool {
return f1 == f2;
}
public static function isObject(v:Dynamic):Bool
untyped {
if (v == null)
return false;
var t = __lua__("type(v)");
return (t == "string" || (t == "table" && v.__enum__ == null))
|| (t == "function" && (lua.Boot.isClass(v) || lua.Boot.isEnum(v)) != null);
}
public static function isEnumValue(v:Dynamic):Bool {
return v != null && Std.isOfType(v, lua.Table) && v.__enum__ != null;
}
public static function deleteField(o:Dynamic, field:String):Bool
untyped {
if (!hasField(o, field))
return false;
o[field] = null;
o.__fields__[field] = null;
return true;
}
public static function copy<T>(o:Null<T>):Null<T> {
if (o == null)
return null;
var o2:Dynamic = {};
for (f in Reflect.fields(o))
Reflect.setField(o2, f, Reflect.field(o, f));
return o2;
}
@:overload(function(f:Array<Dynamic>->Void):Dynamic {})
public static function makeVarArgs(f:Array<Dynamic>->Dynamic):Dynamic {
/*
- Convert var arg to table
- Set indexing from zero
- Extract real table length
- Recreate as dynamic array
- Return function called with this array
*/
return untyped __lua__("function(...)
local a = {...}
local b = {}
local l = 0
for k, v in pairs(a) do
b[k-1] = v
l = math.max(k,l)
end
return f(_hx_tab_array(b, l))
end");
}
}

View File

@ -0,0 +1,110 @@
/*
* 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.
*/
import lua.Boot;
import lua.NativeStringTools;
@:keepInit
@:coreApi class Std {
@:deprecated('Std.is is deprecated. Use Std.isOfType instead.')
public static inline function is(v:Dynamic, t:Dynamic):Bool {
return isOfType(v, t);
}
public static inline function isOfType(v:Dynamic, t:Dynamic):Bool {
return untyped lua.Boot.__instanceof(v, t);
}
public static inline function downcast<T:{}, S:T>(value:T, c:Class<S>):S {
return untyped lua.Boot.__instanceof(value, c) ? cast value : null;
}
@:deprecated('Std.instance() is deprecated. Use Std.downcast() instead.')
public static inline function instance<T:{}, S:T>(value:T, c:Class<S>):S {
return downcast(value, c);
}
@:keep
public static function string(s:Dynamic) : String {
return untyped _hx_tostring(s, 0);
}
public static function int(x:Float):Int {
if (!Math.isFinite(x) || Math.isNaN(x))
return 0;
else
return lua.Boot.clampInt32(x);
}
public static function parseInt(x:String):Null<Int> {
if (x == null)
return null;
var hexMatch = NativeStringTools.match(x, "^[ \t\r\n]*([%-+]*0[xX][%da-fA-F]*)");
if (hexMatch != null) {
var sign = switch StringTools.fastCodeAt(hexMatch, 0) {
case '-'.code: -1;
case '+'.code: 1;
case _: 0;
}
return (sign == -1 ? -1 : 1) * lua.Lua.tonumber(hexMatch.substr(sign == 0 ? 2 : 3), 16);
} else {
var intMatch = NativeStringTools.match(x, "^ *[%-+]?%d*");
if (intMatch != null) {
return lua.Lua.tonumber(intMatch);
} else {
return null;
}
}
}
public static function parseFloat(x:String):Float {
if (x == null || x == "")
return Math.NaN;
var digitMatch = NativeStringTools.match(x, "^ *[%.%-+]?[0-9]%d*");
if (digitMatch == null) {
return Math.NaN;
}
x = x.substr(digitMatch.length);
var decimalMatch = NativeStringTools.match(x, "^%.%d*");
if (decimalMatch == null)
decimalMatch = "";
x = x.substr(decimalMatch.length);
var eMatch = NativeStringTools.match(x, "^[eE][+%-]?%d+");
if (eMatch == null)
eMatch = "";
var result = lua.Lua.tonumber(digitMatch + decimalMatch + eMatch);
return result != null ? result : Math.NaN;
}
public static function random(x:Int):Int {
return untyped x <= 0 ? 0 : Math.floor(Math.random() * x);
}
static function __init__():Void
untyped {
__feature__("lua.Boot.isClass", String.__name__ = __feature__("Type.getClassName", "String", true));
__feature__("Type.resolveClass", _hxClasses["Array"] = Array);
__feature__("lua.Boot.isClass", Array.__name__ = __feature__("Type.getClassName", "Array", true));
}
}

View File

@ -0,0 +1,169 @@
/*
* 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.
*/
import lua.Lua;
import lua.Table;
import lua.Boot;
#if lua_vanilla
private typedef BaseString = lua.NativeStringTools;
#else
private typedef BaseString = lua.lib.luautf8.Utf8;
#end
@:coreApi
class String {
static var __oldindex:String->String->Dynamic;
public var length(default, null):Int;
public inline function new(string:String)
untyped {}
@:keep
static function __index(s:Dynamic, k:Dynamic):Dynamic {
if (k == "length")
return BaseString.len(s);
else if (Reflect.hasField(untyped String.prototype, k))
return untyped String.prototype[k];
else if (__oldindex != null) {
if (Lua.type(__oldindex) == "function") {
return __oldindex(s, k);
} else if (Lua.type(__oldindex) == "table") {
return untyped __oldindex[k];
}
return null;
} else
return null;
}
public inline function toUpperCase():String
return BaseString.upper(this);
public inline function toLowerCase():String
return BaseString.lower(this);
public inline function indexOf(str:String, ?startIndex:Int):Int {
if (startIndex == null)
startIndex = 1;
else
startIndex += 1;
if (str == "") {
return indexOfEmpty(this, startIndex - 1);
}
var r = BaseString.find(this, str, startIndex, true).begin;
if (r != null && r > 0)
return r - 1;
else
return -1;
}
static function indexOfEmpty(s:String, startIndex:Int):Int {
var length = BaseString.len(s);
if(startIndex < 0) {
startIndex = length + startIndex;
if(startIndex < 0) startIndex = 0;
}
return startIndex > length ? length : startIndex;
}
public inline function lastIndexOf(str:String, ?startIndex:Int):Int {
var ret = -1;
if (startIndex == null)
startIndex = length;
while (true) {
var p = indexOf(str, ret + 1);
if (p == -1 || p > startIndex || p == ret)
break;
ret = p;
}
return ret;
}
public inline function split(delimiter:String):Array<String> {
var idx = 1;
var ret = [];
while (idx != null) {
var newidx = 0;
if (delimiter.length > 0) {
newidx = BaseString.find(this, delimiter, idx, true).begin;
} else if (idx >= this.length) {
newidx = null;
} else {
newidx = idx + 1;
}
if (newidx != null) {
var match = BaseString.sub(this, idx, newidx - 1).match;
ret.push(match);
idx = newidx + delimiter.length;
} else {
ret.push(BaseString.sub(this, idx, this.length).match);
idx = null;
}
}
return ret;
}
public inline function toString():String {
return this;
}
public inline function substring(startIndex:Int, ?endIndex:Int):String {
if (endIndex == null)
endIndex = this.length;
if (endIndex < 0)
endIndex = 0;
if (startIndex < 0)
startIndex = 0;
if (endIndex < startIndex) {
// swap the index positions
return BaseString.sub(this, endIndex + 1, startIndex).match;
} else {
return BaseString.sub(this, startIndex + 1, endIndex).match;
}
}
public inline function charAt(index:Int):String {
return BaseString.sub(this, index + 1, index + 1).match;
}
public inline function charCodeAt(index:Int):Null<Int> {
return BaseString.byte(this, index + 1);
}
public inline function substr(pos:Int, ?len:Int):String {
if (len == null || len > pos + this.length)
len = this.length;
else if (len < 0)
len = length + len;
if (pos < 0)
pos = length + pos;
if (pos < 0)
pos = 0;
return BaseString.sub(this, pos + 1, pos + len).match;
}
public inline static function fromCharCode(code:Int):String {
return BaseString.char(code);
}
}

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.
*/
import lua.Table;
class StringBuf {
var b:Table<Int, String>;
public var length(get, null):Int;
public inline function new() {
b = Table.create();
this.length = 0;
}
inline function get_length():Int {
return length;
}
public inline function add<T>(x:T):Void {
var str = Std.string(x);
Table.insert(b, str);
length += str.length;
}
public inline function addChar(c:Int):Void {
Table.insert(b, String.fromCharCode(c));
length += 1;
}
public inline function addSub(s:String, pos:Int, ?len:Int):Void {
var part = len == null ? s.substr(pos) : s.substr(pos, len);
Table.insert(b, part);
length += part.length;
}
public inline function toString():String {
return Table.concat(b);
}
}

View File

@ -0,0 +1,126 @@
/*
* 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.
*/
import lua.Boot;
import lua.Io;
import lua.Lua;
import lua.lib.luv.Os;
import lua.lib.luv.Misc;
import sys.io.FileInput;
import sys.io.FileOutput;
@:coreApi
class Sys {
static var _system_name:String;
public static inline function print(v:Dynamic):Void {
return lua.Lib.print(v);
}
public static inline function println(v:Dynamic):Void {
return lua.Lib.println(v);
}
public inline static function args():Array<String> {
var targs = lua.PairTools.copy(Lua.arg);
var args = lua.Table.toArray(targs);
return args;
}
public static function command(cmd:String, ?args:Array<String>):Int {
var p = new sys.io.Process(cmd, args);
var code = p.exitCode();
p.close();
return code;
}
public inline static function cpuTime():Float {
return lua.Os.clock();
}
public inline static function exit(code:Int):Void {
lua.Os.exit(code);
}
public inline static function getChar(echo:Bool):Int {
return lua.Io.read().charCodeAt(0);
}
static function getSystemName():String {
return lua.Boot.systemName();
}
public static function systemName():String {
if (_system_name == null)
_system_name = getSystemName();
return _system_name;
}
public static function environment():Map<String, String> {
var env = lua.lib.luv.Os.environ();
return lua.Table.toMap(env);
}
@:deprecated("Use programPath instead") public static function executablePath():String {
return Misc.exepath();
}
public inline static function programPath():String {
return haxe.io.Path.join([getCwd(), Lua.arg[0]]);
}
public inline static function getCwd():String
return Misc.cwd();
public inline static function setCwd(s:String):Void
Misc.chdir(s);
public inline static function getEnv(s:String):String {
return Os.getenv(s);
}
public inline static function putEnv(s:String, v:String):Void {
Os.setenv(s, v);
}
public inline static function setTimeLocale(loc:String):Bool {
// TODO Verify
return lua.Os.setlocale(loc) != null;
}
public static function sleep(seconds:Float):Void
lua.lib.luv.Thread.sleep(Math.floor(seconds * 1000));
public inline static function stderr():haxe.io.Output
return @:privateAccess new FileOutput(Io.stderr);
public inline static function stdin():haxe.io.Input
return @:privateAccess new FileInput(Io.stdin);
public inline static function stdout():haxe.io.Output
return @:privateAccess new FileOutput(Io.stdout);
public static function time():Float {
var stamp = lua.lib.luv.Misc.gettimeofday();
return stamp.seconds + (stamp.microseconds / 1000000);
}
}

View File

@ -0,0 +1,220 @@
/*
* 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.
*/
import lua.Lua;
import lua.Table;
enum ValueType {
TNull;
TInt;
TFloat;
TBool;
TObject;
TFunction;
TClass(c:Class<Dynamic>);
TEnum(e:Enum<Dynamic>);
TUnknown;
}
@:coreApi class Type {
public static function getClass<T>(o:T):Class<T>
untyped {
if (o == null)
return null;
return lua.Boot.getClass(o);
}
public static function getEnum(o:EnumValue):Enum<Dynamic>
untyped {
if (o == null)
return null;
return o.__enum__;
}
public static function getSuperClass(c:Class<Dynamic>):Class<Dynamic>
untyped {
return c.__super__;
}
public static inline function getClassName(c:Class<Dynamic>):String {
return untyped __define_feature__("Type.getClassName", c.__name__);
}
public static function getEnumName(e:Enum<Dynamic>):String {
if (untyped e.__ename__ == null)
return null;
return untyped e.__ename__;
}
public static function resolveClass(name:String):Class<Dynamic>
untyped {
// TODO: better tmp name for _hxClasses
var cl:Class<Dynamic> = _hxClasses[name];
// ensure that this is a class
if (cl == null || !lua.Boot.isClass(cl))
return null;
return cl;
}
public static function resolveEnum(name:String):Enum<Dynamic>
untyped {
// TODO: better tmp name for _hxClasses
var e:Dynamic = _hxClasses[name];
// ensure that this is an enum
if (e == null || !lua.Boot.isEnum(e))
return null;
return e;
}
public static function createInstance<T>(cl:Class<T>, args:Array<Dynamic>):T
untyped {
return __new__(cl, lua.TableTools.unpack(cast args, 0));
}
public static function createEmptyInstance<T>(cl:Class<T>):T
untyped {
var ret = __lua_table__();
Lua.setmetatable(ret, untyped {__index: cl.prototype});
return ret;
}
public static function createEnum<T>(e:Enum<T>, constr:String, ?params:Array<Dynamic>):T {
var f:Dynamic = Reflect.field(e, constr);
if (f == null)
throw "No such constructor " + constr;
if (Reflect.isFunction(f)) {
if (params == null)
throw "Constructor " + constr + " need parameters";
return Reflect.callMethod(null, f, params);
}
if (params != null && params.length != 0)
throw "Constructor " + constr + " does not need parameters";
return f;
}
public static function createEnumIndex<T>(e:Enum<T>, index:Int, ?params:Array<Dynamic>):T {
var c:String = (untyped e.__constructs__)[index];
if (c == null)
throw index + " is not a valid enum constructor index";
return createEnum(e, c, params);
}
public static function getInstanceFields(c:Class<Dynamic>):Array<String> {
var p:Dynamic = untyped c.prototype;
var a:Array<String> = [];
while (p != null) {
for (f in Reflect.fields(p)) {
if (!Lambda.has(a, f))
a.push(f);
}
var mt = lua.Lua.getmetatable(p);
if (mt != null && mt.__index != null)
p = mt.__index;
else
p = null;
}
return a;
}
public static function getClassFields(c:Class<Dynamic>):Array<String> {
var a = Reflect.fields(c);
a.remove("__name__");
a.remove("__interfaces__");
a.remove("__properties__");
a.remove("__super__");
a.remove("__meta__");
a.remove("prototype");
a.remove("new");
return a;
}
public static function getEnumConstructs(e:Enum<Dynamic>):Array<String> {
var a:Array<String> = untyped e.__constructs__;
return a.copy();
}
public static function typeof(v:Dynamic):ValueType {
switch (Lua.type(v)) {
case "boolean":
return TBool;
case "string":
return TClass(String);
case "number":
// this should handle all cases : NaN, +/-Inf and Floats outside range
if (Math.ceil(v) == v % 2147483648.0)
return TInt;
return TFloat;
case "table":
var e = v.__enum__;
if (e != null)
return TEnum(e);
var c = lua.Boot.getClass(v);
if (c != null)
return TClass(c);
return TObject;
case "function":
if (lua.Boot.isClass(v) || lua.Boot.isEnum(v))
return TObject;
return TFunction;
case "nil":
return TNull;
default:
return TUnknown;
}
}
public static function enumEq<T>(a:T, b:T):Bool
untyped {
if (a == b)
return true;
try {
if (a[0] != b[0])
return false;
for (i in 2...a.length)
if (!enumEq(a[i], b[i]))
return false;
var e = a.__enum__;
if (e != b.__enum__ || e == null)
return false;
} catch (e:Dynamic) {
return false;
}
return true;
}
public inline static function enumConstructor(e:EnumValue):String {
return untyped e[0];
}
public inline static function enumParameters(e:EnumValue):Array<Dynamic> {
return (cast e : Array<Dynamic>).slice(2);
}
public inline static function enumIndex(e:EnumValue):Int {
return untyped e[1];
}
public static function allEnums<T>(e:Enum<T>):Array<T> {
return ((cast e).__empty_constructs__ : Array<T>).copy();
}
}

View File

@ -0,0 +1,85 @@
package haxe;
@:coreApi
class Exception {
public var message(get,never):String;
public var stack(get,never):CallStack;
public var previous(get,never):Null<Exception>;
public var native(get,never):Any;
@:noCompletion var __exceptionMessage:String;
@:noCompletion var __exceptionStack:Null<CallStack>;
@:noCompletion var __nativeStack:Array<String>;
@:noCompletion @:ifFeature("haxe.Exception.get_stack") var __skipStack:Int = 0;
@:noCompletion var __nativeException:Any;
@:noCompletion var __previousException:Null<Exception>;
static function caught(value:Any):Exception {
if(Std.isOfType(value, Exception)) {
return value;
} else {
return new ValueException(value, null, value);
}
}
static function thrown(value:Any):Any {
if(Std.isOfType(value, Exception)) {
return (value:Exception).native;
} else {
var e = new ValueException(value);
e.__shiftStack();
return e;
}
}
public function new(message:String, ?previous:Exception, ?native:Any) {
__exceptionMessage = message;
__previousException = previous;
if(native != null) {
__nativeException = native;
__nativeStack = NativeStackTrace.exceptionStack();
} else {
__nativeException = this;
__nativeStack = NativeStackTrace.callStack();
__skipStack = 1;
}
}
function unwrap():Any {
return __nativeException;
}
public function toString():String {
return message;
}
public function details():String {
return inline CallStack.exceptionToString(this);
}
@:noCompletion
@:ifFeature("haxe.Exception.get_stack")
inline function __shiftStack():Void {
__skipStack++;
}
function get_message():String {
return __exceptionMessage;
}
function get_previous():Null<Exception> {
return __previousException;
}
final function get_native():Any {
return __nativeException;
}
function get_stack():CallStack {
return switch __exceptionStack {
case null:
__exceptionStack = NativeStackTrace.toHaxe(__nativeStack, __skipStack);
case s: s;
}
}
}

View File

@ -0,0 +1,34 @@
/*
* 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 haxe;
@:coreApi
class Json {
public static function parse(text:String):Dynamic {
return haxe.format.JsonParser.parse(text);
}
public static function stringify(value:Dynamic, ?replacer:(key:Dynamic, value:Dynamic) -> Dynamic, ?space:String):String {
return haxe.format.JsonPrinter.print(value, replacer, space);
}
}

View File

@ -0,0 +1,54 @@
package haxe;
import haxe.CallStack.StackItem;
/**
Do not use manually.
**/
@:dox(hide)
@:noCompletion
class NativeStackTrace {
@:ifFeature('haxe.NativeStackTrace.exceptionStack')
static public inline function saveStack(exception:Any):Void {
}
static public function callStack():Array<String> {
return switch lua.Debug.traceback() {
case null: [];
case s: s.split('\n').slice(3);
}
}
static public function exceptionStack():Array<String> {
return []; //Not implemented. Maybe try xpcal instead of pcal in genlua.
}
static public function toHaxe(native:Array<String>, skip:Int = 0):Array<StackItem> {
var stack = [];
var cnt = -1;
for (item in native) {
var parts = item.substr(1).split(":"); //`substr` to skip a tab at the beginning of a line
var file = parts[0];
if(file == '[C]') {
continue;
}
++cnt;
if(skip > cnt) {
continue;
}
var line = parts[1];
var method = if(parts.length <= 2) {
null;
} else {
var methodPos = parts[2].indexOf("'");
if(methodPos < 0) {
null;
} else {
Method(null, parts[2].substring(methodPos + 1, parts[2].length - 1));
}
}
stack.push(FilePos(method, file, Std.parseInt(line)));
}
return stack;
}
}

View File

@ -0,0 +1,55 @@
package haxe;
import lua.Lua.select;
import lua.Table;
import lua.PairTools.copy;
import lua.TableTools.maxn;
import lua.TableTools.pack;
import lua.TableTools.unpack;
import haxe.iterators.RestIterator;
import haxe.iterators.RestKeyValueIterator;
private typedef NativeRest<T> = Table<Int,T>;
@:coreApi
abstract Rest<T>(NativeRest<T>) {
public var length(get, never):Int;
inline function get_length():Int
return maxn(this);
@:from static public function of<T>(array:Array<T>):Rest<T> {
return new Rest(Table.fromArray(array));
}
inline function new(table:Table<Int,T>):Void
this = table;
@:arrayAccess inline function get(index:Int):T
return this[index + 1];
@:to public function toArray():Array<T> {
return Table.toArray(this);
}
public inline function iterator():RestIterator<T>
return new RestIterator<T>(this);
public inline function keyValueIterator():RestKeyValueIterator<T>
return new RestKeyValueIterator<T>(this);
public inline function append(item:T):Rest<T> {
var result = copy(this);
Table.insert(result, item);
return new Rest(result);
}
public inline function prepend(item:T):Rest<T> {
var result = copy(this);
Table.insert(result, 1, item);
return new Rest(result);
}
public function toString():String {
return toArray().toString();
}
}

View File

@ -0,0 +1,115 @@
/*
* 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 haxe.ds;
import lua.Lua;
class IntMap<T> implements haxe.Constraints.IMap<Int, T> {
private var h:lua.Table<Int, T>;
static var tnull:Dynamic = lua.Table.create();
public inline function new():Void {
h = lua.Table.create();
}
public inline function set(key:Int, value:T):Void {
if (value == null) {
h[key] = tnull;
} else {
h[key] = value;
}
}
public inline function get(key:Int):Null<T> {
var ret = h[key];
if (ret == tnull) {
ret = null;
}
return ret;
}
public inline function exists(key:Int):Bool {
return h[key] != null;
}
public function remove(key:Int):Bool {
if (h[key] == null) {
return false;
} else {
h[key] = null;
return true;
}
}
public function keys():Iterator<Int> {
var next = Lua.next;
var cur = next(h, null).index;
return {
next: function() {
var ret = cur;
cur = next(h, cur).index;
return cast ret;
},
hasNext: function() return cur != null
}
}
public function iterator():Iterator<T> {
var it = keys();
return untyped {
hasNext: function() return it.hasNext(),
next: function() return h[it.next()]
};
}
@:runtime public inline function keyValueIterator():KeyValueIterator<Int, T> {
return new haxe.iterators.MapKeyValueIterator(this);
}
public function copy():IntMap<T> {
var copied = new IntMap();
for (key in keys())
copied.set(key, get(key));
return copied;
}
public function toString():String {
var s = new StringBuf();
s.add("{");
var it = keys();
for (i in it) {
s.add(i);
s.add(" => ");
s.add(Std.string(get(i)));
if (it.hasNext())
s.add(", ");
}
s.add("}");
return s.toString();
}
public inline function clear():Void {
h = lua.Table.create();
}
}

View File

@ -0,0 +1,120 @@
/*
* 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 haxe.ds;
class ObjectMap<A, B> implements haxe.Constraints.IMap<A, B> {
static var count = 0;
static inline function assignId(obj:{}):Int {
return untyped obj.__id__ = ++count;
}
static inline function getId(obj:{}):Int {
return untyped obj.__id__;
}
var h:Dynamic;
var k:Dynamic;
public inline function new():Void {
h = lua.Table.create();
k = lua.Table.create();
}
public inline function set(key:A, value:B):Void
untyped {
h[key] = value;
k[key] = true;
}
public inline function get(key:A):Null<B>
untyped {
return h[key];
}
public inline function exists(key:A):Bool
untyped {
return k[key] != null;
}
public function remove(key:A):Bool
untyped {
if (k[key] == null)
return false;
k[key] = null;
h[key] = null;
return true;
}
public function keys():Iterator<A>
untyped {
var cur = next(h, null);
return {
next: function() {
var ret = cur;
cur = untyped next(k, cur);
return ret;
},
hasNext: function() return cur != null
}
}
public function iterator():Iterator<B> {
var itr = keys();
return untyped {
hasNext: itr.hasNext,
next: function() return h[itr.next()]
};
}
@:runtime public inline function keyValueIterator():KeyValueIterator<A, B> {
return new haxe.iterators.MapKeyValueIterator(this);
}
public function copy():ObjectMap<A, B> {
var copied = new ObjectMap();
for (key in keys())
copied.set(key, get(key));
return copied;
}
public function toString():String {
var s = new StringBuf();
s.add("{");
var it = keys();
for (i in it) {
s.add(i);
s.add(" => ");
s.add(Std.string(get(i)));
if (it.hasNext())
s.add(", ");
}
s.add("}");
return s.toString();
}
public inline function clear():Void {
h = lua.Table.create();
k = lua.Table.create();
}
}

View File

@ -0,0 +1,119 @@
/*
* 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 haxe.ds;
import lua.Lua;
class StringMap<T> implements haxe.Constraints.IMap<String, T> {
private var h:lua.Table<String, T>;
static var tnull:Dynamic = lua.Table.create();
public inline function new():Void {
h = lua.Table.create();
}
public inline function set(key:String, value:T):Void
untyped {
if (value == null) {
h[key] = tnull;
} else {
h[key] = value;
}
}
public inline function get(key:String):Null<T>
untyped {
var ret = h[key];
if (ret == tnull) {
ret = null;
}
return ret;
}
public inline function exists(key:String):Bool
untyped {
return h[key] != null;
}
public function remove(key:String):Bool
untyped {
if (h[key] == null) {
return false;
} else {
h[key] = null;
return true;
}
}
public function keys():Iterator<String> {
var next = Lua.next;
var cur = next(h, null).index;
return {
next: function() {
var ret = cur;
cur = next(h, cur).index;
return cast ret;
},
hasNext: function() return cur != null
}
}
public function iterator():Iterator<T> {
var it = keys();
return untyped {
hasNext: function() return it.hasNext(),
next: function() return h[it.next()]
};
}
@:runtime public inline function keyValueIterator():KeyValueIterator<String, T> {
return new haxe.iterators.MapKeyValueIterator(this);
}
public function copy():StringMap<T> {
var copied = new StringMap();
for (key in keys())
copied.set(key, get(key));
return copied;
}
public function toString():String {
var s = new StringBuf();
s.add("{");
var it = keys();
for (i in it) {
s.add(i);
s.add(" => ");
s.add(Std.string(get(i)));
if (it.hasNext())
s.add(", ");
}
s.add("}");
return s.toString();
}
public inline function clear():Void {
h = lua.Table.create();
}
}

View File

@ -0,0 +1,292 @@
/*
* 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 haxe.format;
/**
An implementation of JSON parser in Haxe.
This class is used by `haxe.Json` when native JSON implementation
is not available.
@see https://haxe.org/manual/std-Json-parsing.html
**/
class JsonParser {
/**
Parses given JSON-encoded `str` and returns the resulting object.
JSON objects are parsed into anonymous structures and JSON arrays
are parsed into `Array<Dynamic>`.
If given `str` is not valid JSON, an exception will be thrown.
If `str` is null, the result is unspecified.
**/
static public inline function parse(str:String):Dynamic {
return lua.lib.hxluasimdjson.Json.parse(str);
}
var str:String;
var pos:Int;
function new(str:String) {
this.str = str;
this.pos = 0;
}
function doParse():Dynamic {
var result = parseRec();
var c;
while (!StringTools.isEof(c = nextChar())) {
switch (c) {
case ' '.code, '\r'.code, '\n'.code, '\t'.code:
// allow trailing whitespace
default:
invalidChar();
}
}
return result;
}
function parseRec():Dynamic {
while (true) {
var c = nextChar();
switch (c) {
case ' '.code, '\r'.code, '\n'.code, '\t'.code:
// loop
case '{'.code:
var obj = {}, field = null, comma:Null<Bool> = null;
while (true) {
var c = nextChar();
switch (c) {
case ' '.code, '\r'.code, '\n'.code, '\t'.code:
// loop
case '}'.code:
if (field != null || comma == false)
invalidChar();
return obj;
case ':'.code:
if (field == null)
invalidChar();
Reflect.setField(obj, field, parseRec());
field = null;
comma = true;
case ','.code:
if (comma) comma = false else invalidChar();
case '"'.code:
if (field != null || comma) invalidChar();
field = parseString();
default:
invalidChar();
}
}
case '['.code:
var arr = [], comma:Null<Bool> = null;
while (true) {
var c = nextChar();
switch (c) {
case ' '.code, '\r'.code, '\n'.code, '\t'.code:
// loop
case ']'.code:
if (comma == false) invalidChar();
return arr;
case ','.code:
if (comma) comma = false else invalidChar();
default:
if (comma) invalidChar();
pos--;
arr.push(parseRec());
comma = true;
}
}
case 't'.code:
var save = pos;
if (nextChar() != 'r'.code || nextChar() != 'u'.code || nextChar() != 'e'.code) {
pos = save;
invalidChar();
}
return true;
case 'f'.code:
var save = pos;
if (nextChar() != 'a'.code || nextChar() != 'l'.code || nextChar() != 's'.code || nextChar() != 'e'.code) {
pos = save;
invalidChar();
}
return false;
case 'n'.code:
var save = pos;
if (nextChar() != 'u'.code || nextChar() != 'l'.code || nextChar() != 'l'.code) {
pos = save;
invalidChar();
}
return null;
case '"'.code:
return parseString();
case '0'.code, '1'.code, '2'.code, '3'.code, '4'.code, '5'.code, '6'.code, '7'.code, '8'.code, '9'.code, '-'.code:
return parseNumber(c);
default:
invalidChar();
}
}
}
function parseString() {
// eq( haxe.format.JsonParser.parse('"\\u00E9"'), "é" );
var start = pos;
var buf:StringBuf = null;
var prev = -1;
inline function cancelSurrogate() {
// invalid high surrogate (not followed by low surrogate)
buf.addChar(0xFFFD);
prev = -1;
}
while (true) {
var c = nextChar();
if (c == '"'.code)
break;
if (c == '\\'.code) {
if (buf == null) {
buf = new StringBuf();
}
buf.addSub(str, start, pos - start - 1);
c = nextChar();
switch (c) {
case "r".code:
buf.addChar("\r".code);
case "n".code:
buf.addChar("\n".code);
case "t".code:
buf.addChar("\t".code);
case "b".code:
buf.addChar(8);
case "f".code:
buf.addChar(12);
case "/".code, '\\'.code, '"'.code:
buf.addChar(c);
case 'u'.code:
var uc:Int = Std.parseInt("0x" + str.substr(pos, 4));
pos += 4;
if (prev != -1) {
if (uc < 0xDC00 || uc > 0xDFFF)
cancelSurrogate();
else {
buf.addChar(((prev - 0xD800) << 10) + (uc - 0xDC00) + 0x10000);
prev = -1;
}
} else if (uc >= 0xD800 && uc <= 0xDBFF)
prev = uc;
else
buf.addChar(uc);
default:
throw "Invalid escape sequence \\" + String.fromCharCode(c) + " at position " + (pos - 1);
}
start = pos;
}
// ensure utf8 chars are not cut
else if (c >= 0x80) {
pos++;
if (c >= 0xFC)
pos += 4;
else if (c >= 0xF8)
pos += 3;
else if (c >= 0xF0)
pos += 2;
else if (c >= 0xE0)
pos++;
}
else if (StringTools.isEof(c))
throw "Unclosed string";
}
if (buf == null) {
return str.substr(start, pos - start - 1);
} else {
buf.addSub(str, start, pos - start - 1);
return buf.toString();
}
}
inline function parseNumber(c:Int):Dynamic {
var start = pos - 1;
var minus = c == '-'.code, digit = !minus, zero = c == '0'.code;
var point = false, e = false, pm = false, end = false;
while (true) {
c = nextChar();
switch (c) {
case '0'.code:
if (zero && !point)
invalidNumber(start);
if (minus) {
minus = false;
zero = true;
}
digit = true;
case '1'.code, '2'.code, '3'.code, '4'.code, '5'.code, '6'.code, '7'.code, '8'.code, '9'.code:
if (zero && !point)
invalidNumber(start);
if (minus)
minus = false;
digit = true;
zero = false;
case '.'.code:
if (minus || point || e)
invalidNumber(start);
digit = false;
point = true;
case 'e'.code, 'E'.code:
if (minus || zero || e)
invalidNumber(start);
digit = false;
e = true;
case '+'.code, '-'.code:
if (!e || pm)
invalidNumber(start);
digit = false;
pm = true;
default:
if (!digit)
invalidNumber(start);
pos--;
end = true;
}
if (end)
break;
}
var f = Std.parseFloat(str.substr(start, pos - start));
var i = Std.int(f);
return if (i == f) i else f;
}
function nextChar() {
pos++;
return lua.NativeStringTools.byte(str, pos);
}
function invalidChar() {
pos--; // rewind
throw "Invalid char " + lua.NativeStringTools.byte(str, pos) + " at position " + pos;
}
function invalidNumber(start:Int) {
throw "Invalid number at position " + start + ": " + str.substr(start, pos - start);
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (C)2005-2018 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 haxe.iterators;
import lua.lib.luautf8.Utf8;
class StringIterator {
var codes : (String, Int)->StringCodePoint;
var codepoint : Int;
var str : String;
var position : Int;
public inline function new(s:String) {
this.codes = Utf8.codes(s);
this.str = s;
var cp = codes(str, 0);
this.codepoint = cp.codepoint;
this.position = cp.position;
}
public inline function hasNext() {
return codepoint != null;
}
public inline function next() {
var ret = codepoint;
var cp = codes(str, position);
codepoint = cp.codepoint;
position = cp.position;
return ret;
}
}

View File

@ -0,0 +1,125 @@
/*
* 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 lua.Io;
import haxe.io.Path;
import lua.lib.luv.fs.FileSystem as LFileSystem;
class FileSystem {
public static function exists(path:String):Bool {
if (path == null)
return false;
else {
var res = LFileSystem.stat(path);
return res.result != null;
}
}
public inline static function rename(path:String, newPath:String):Void {
var ret = lua.Os.rename(path, newPath);
if (!ret.success) {
throw ret.message;
}
}
public inline static function stat(path:String):FileStat {
var ls = LFileSystem.stat(path);
if (ls.result == null)
throw ls.message;
var l = ls.result;
return {
gid: l.gid,
uid: l.uid,
rdev: l.rdev,
size: l.size,
nlink: l.nlink,
mtime: Date.fromTime(l.mtime.sec + l.mtime.nsec / 1000000),
mode: l.mode,
ino: l.ino,
dev: l.dev,
ctime: Date.fromTime(l.ctime.sec + l.ctime.nsec / 1000000),
atime: Date.fromTime(l.atime.sec + l.atime.nsec / 1000000)
};
}
public inline static function fullPath(relPath:String):String {
return LFileSystem.realpath(Path.normalize(absolutePath(relPath)));
}
public inline static function absolutePath(relPath:String):String {
if (haxe.io.Path.isAbsolute(relPath)) {
return relPath;
}
var pwd = lua.lib.luv.Misc.cwd();
if (pwd == null)
return relPath;
return Path.join([pwd, relPath]);
}
public inline static function deleteFile(path:String):Void {
var ret = lua.Os.remove(path);
if (!ret.success) {
throw ret.message;
}
}
public inline static function readDirectory(path:String):Array<String> {
var scandir = LFileSystem.scandir(path);
var itr = function() {
var next = LFileSystem.scandir_next(scandir).name;
return next;
}
return lua.Lib.fillArray(itr);
}
public inline static function isDirectory(path:String):Bool {
var result = LFileSystem.stat(path).result;
if (result == null)
return false;
else
return result.type == "directory";
}
public inline static function deleteDirectory(path:String):Void {
var ret = LFileSystem.rmdir(path);
if (ret.result == null) {
throw ret.message;
}
}
public static function createDirectory(path:String):Void {
var path = haxe.io.Path.addTrailingSlash(path);
var _p = null;
var parts = [];
while (path != (_p = haxe.io.Path.directory(path))) {
parts.unshift(path);
path = _p;
}
for (part in parts) {
if (part.charCodeAt(part.length - 1) != ":".code && !exists(part) && !LFileSystem.mkdir(part, 511).result)
throw "Could not create directory:" + part;
}
}
}

View File

@ -0,0 +1,97 @@
/*
* 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;
import haxe.SysTools;
import lua.Lua;
import lua.Io;
import lua.Os;
import lua.FileHandle;
import lua.Boot;
@:coreApi
class File {
public static function getContent(path:String):String {
var f = Io.open(path, "r");
if (f == null)
throw 'Invalid path : $path';
var s = f.read("*all");
f.close();
return s;
}
public static function append(path:String, binary:Bool = true):FileOutput {
return @:privateAccess new FileOutput(Io.open(path, "a"));
}
public static function update(path:String, binary:Bool = true):FileOutput {
if (!FileSystem.exists(path)) {
write(path).close();
}
return @:privateAccess new FileOutput(Io.open(path, binary ? "r+b" : "r+"));
}
public static function copy(srcPath:String, dstPath:String):Void {
var result = switch (Sys.systemName()) {
case "Windows": Os.execute('copy ${SysTools.quoteWinArg(srcPath, true)} ${SysTools.quoteWinArg(dstPath, true)}');
default: Os.execute('cp ${SysTools.quoteUnixArg(srcPath)} ${SysTools.quoteUnixArg(dstPath)}');
};
if (#if (lua_ver >= 5.2) !result.success #elseif (lua_ver < 5.2) result != 0 #else ((result : Dynamic) != true && (result : Dynamic) != 0) #end
) {
throw 'Failed to copy $srcPath to $dstPath';
}
}
public static function getBytes(path:String):haxe.io.Bytes {
var finput = read(path, true);
var res = finput.readAll();
finput.close();
return res;
}
public static function read(path:String, binary:Bool = true):FileInput {
var fh = Io.open(path, binary ? 'rb' : 'r');
if (fh == null)
throw 'Invalid path : $path';
return @:privateAccess new FileInput(fh);
}
public static function write(path:String, binary:Bool = true):FileOutput {
var fh = Io.open(path, binary ? 'wb' : 'w');
if (fh == null)
throw 'Invalid path : $path';
return @:privateAccess new FileOutput(fh);
}
public static function saveBytes(path:String, bytes:haxe.io.Bytes):Void {
var f = write(path, true);
f.writeBytes(bytes, 0, bytes.length);
f.close();
}
public static function saveContent(path:String, content:String):Void {
var f = write(path, true);
f.writeString(content);
f.close();
}
}

View File

@ -0,0 +1,100 @@
/*
* 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;
import lua.FileHandle;
import lua.Io;
import lua.NativeStringTools;
import lua.Boot;
import lua.Os;
import haxe.io.Bytes;
import haxe.io.Error;
import haxe.io.Eof;
class FileInput extends haxe.io.Input {
var f:FileHandle;
var _eof:Bool;
function new(f:FileHandle) {
if (f == null)
throw 'Invalid filehandle : $f';
this.bigEndian = Boot.platformBigEndian;
this.f = f;
this._eof = false;
}
inline public function seek(p:Int, pos:FileSeek):Void {
var arg = switch (pos) {
case SeekBegin: "set";
case SeekCur: "cur";
case SeekEnd: "end";
}
_eof = false;
return f.seek(arg, p);
}
inline public function tell():Int {
return f.seek();
}
inline public function eof():Bool {
return _eof;
}
override inline public function readByte():Int {
var byte = f.read(1);
if (byte == null) {
_eof = true;
throw new haxe.io.Eof();
}
return NativeStringTools.byte(byte);
}
override function readBytes(s:Bytes, pos:Int, len:Int):Int {
if (eof())
throw new haxe.io.Eof();
return super.readBytes(s, pos, len);
}
override inline public function close():Void {
f.close();
}
override public function readAll(?bufsize:Int):Bytes {
if (bufsize == null)
bufsize = (1 << 14); // 16 Ko
var buf = Bytes.alloc(bufsize);
var total = new haxe.io.BytesBuffer();
try {
while (true) {
var len = readBytes(buf, 0, bufsize);
if (len == 0)
break;
total.addBytes(buf, 0, len);
}
} catch (e:Eof) {
_eof = true;
}
return total.getBytes();
}
}

View File

@ -0,0 +1,62 @@
/*
* 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;
import lua.FileHandle;
import haxe.io.Bytes;
class FileOutput extends haxe.io.Output {
var f:FileHandle;
function new(f:FileHandle) {
if (f == null)
throw 'Invalid filehandle : $f';
this.f = f;
}
public inline function seek(p:Int, pos:FileSeek):Void {
var arg = switch (pos) {
case SeekBegin: "set";
case SeekCur: "cur";
case SeekEnd: "end";
}
return f.seek(arg, p);
}
public inline function tell():Int {
return f.seek();
}
override inline public function writeByte(c:Int):Void {
f.write(String.fromCharCode(c));
}
override inline public function writeBytes(s:Bytes, pos:Int, len:Int):Int {
f.write(s.getString(pos, len));
return s.length;
}
override public function close() {
f.close();
}
}

View File

@ -0,0 +1,228 @@
/*
* 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;
import lua.Io;
import lua.lib.luv.Pipe;
import lua.lib.luv.Signal;
import lua.lib.luv.Loop;
import lua.Boot;
import lua.Table;
import lua.NativeStringTools;
import haxe.SysTools;
import haxe.io.Bytes;
import haxe.io.Error;
import haxe.io.Eof;
@:coreApi
class Process {
var _pid:Int;
var _handle:lua.lib.luv.Process;
var _code:Int;
var closef:Int->Signal->Void;
public var stdout(default, null):haxe.io.Input;
public var stderr(default, null):haxe.io.Input;
public var stdin(default, null):haxe.io.Output;
static var argQuote = Sys.systemName() == "Windows" ? function(x) return SysTools.quoteWinArg(x, true) : SysTools.quoteUnixArg;
static var _shell = Sys.systemName() == "Windows" ? 'cmd.exe' : '/bin/sh';
/**
Sets the args for the shell, which will include the cmd to be executed
by the shell.
**/
static function setArgs(cmd:String, ?args:Array<String>):Table<Int, String> {
var pargs = lua.Table.create();
var idx = 1;
if (sys.FileSystem.exists(cmd))
cmd = '"$cmd"'; // escape simple paths
var all = [cmd];
if (args != null) {
for (a in args) {
all.push(argQuote(a));
}
}
if (Sys.systemName() == "Windows") {
pargs[idx++] = '/s';
pargs[idx++] = '/c';
pargs[idx++] = all.join(" ");
} else {
pargs[idx++] = "-c";
pargs[idx++] = all.join(" ");
}
return pargs;
}
public function new(cmd:String, ?args:Array<String>, ?detached:Bool) {
if (detached)
throw "Detached process is not supported on this platform";
var _stdout = new Pipe(false);
var _stderr = new Pipe(false);
var _stdin = new Pipe(false);
stdout = new ProcessInput(_stdout);
stderr = new ProcessInput(_stderr);
stdin = new ProcessOutput(_stdin);
var stdio = untyped __lua_table__([_stdin, _stdout, _stderr]);
var opt = {args: setArgs(cmd, args), stdio: stdio};
var p = lua.lib.luv.Process.spawn(_shell, opt, function(code:Int, signal:Signal) {
_code = code;
if (!_handle.is_closing()){
_handle.close();
}
_stdin.shutdown(()->_stdin.close());
_stderr.shutdown(()->_stderr.close());
_stdout.shutdown(()->_stdout.close());
});
_handle = p.handle;
if (p.handle == null)
throw p.pid;
_pid = p.pid;
}
public function getPid():Int {
return _pid;
}
public function close():Void {
if (!_handle.is_closing()){
_handle.close();
}
}
public function exitCode(block:Bool = true):Null<Int> {
if (!block)
return _code;
while (_handle.is_active()) {
Loop.run(); // process io until the handle closes (emulate blocking)
}
return _code;
}
public function kill():Void {
_handle.kill("sigterm");
}
}
private class ProcessInput extends haxe.io.Input {
var b:Pipe;
var buf:String;
var idx:Int;
var _eof:Bool;
public function new(pipe:Pipe) {
b = pipe;
_eof = false;
}
inline public function eof():Bool {
return _eof;
}
override function readBytes(s:Bytes, pos:Int, len:Int):Int {
if (eof())
throw new haxe.io.Eof();
return super.readBytes(s, pos, len);
}
override public function readByte() {
var err_str = null;
if (buf == null || idx >= NativeStringTools.len(buf)) {
buf = null;
idx = 0;
var pending = true;
b.read_start(function(err, chunk) {
if (chunk != null) {
if (buf != null) {
buf = buf + chunk;
} else {
buf = chunk;
}
}
if (err != null)
err_str = err;
pending = false;
});
// process io until we read our input (emulate blocking)
while (pending)
Loop.run();
}
if (buf == null) {
_eof = true;
throw new haxe.io.Eof();
}
if (err_str != null)
throw err_str;
var code = NativeStringTools.byte(buf, ++idx);
return code;
}
override public function readAll(?bufsize:Int):Bytes {
if (bufsize == null)
bufsize = (1 << 14); // 16 Ko
var buf = Bytes.alloc(bufsize);
var total = new haxe.io.BytesBuffer();
try {
while (true) {
var len = readBytes(buf, 0, bufsize);
// don't throw blocked error here
if (len != 0)
total.addBytes(buf, 0, len);
if (len < bufsize)
break;
}
} catch (e:Eof) {
_eof = true;
}
return total.getBytes();
}
override public function close() {
b.close();
}
}
private class ProcessOutput extends haxe.io.Output {
var b:Pipe;
public function new(pipe:Pipe) {
b = pipe;
set_bigEndian(Boot.platformBigEndian);
}
override public function writeByte(c:Int):Void {
b.write(NativeStringTools.char(c));
}
override public function close() {
b.close();
}
}

View File

@ -0,0 +1,71 @@
/*
* 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;
import haxe.io.Bytes;
import haxe.io.BytesInput;
import lua.NativeStringTools.find;
import lua.lib.luv.net.Dns;
import lua.lib.luv.Os;
@:coreapi
class Host {
public var host(default, null):String;
public var ip(default, null):Int;
var _ip:String;
public function new(name:String):Void {
host = name;
if (find(name, "(%d+)%.(%d+)%.(%d+)%.(%d+)").begin != null) {
_ip = name;
} else {
var res = lua.lib.luv.net.Dns.getaddrinfo(name);
if (res.result == null)
throw "Unrecognized node name";
_ip = res.result[1].addr;
if (_ip == "::1")
_ip = "127.0.0.0";
}
var num = 0;
for (a in _ip.split(".")) {
num = num * 256 + lua.Lua.tonumber(a);
}
ip = num;
}
public function toString():String {
return _ip;
}
public function reverse():String {
return Dns.getnameinfo({ip: _ip}).result;
}
static public function localhost():String {
return Os.gethostname();
}
}

View File

@ -0,0 +1,234 @@
/*
* 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;
import lua.lib.luasocket.Socket as LuaSocket;
import lua.lib.luasocket.socket.*;
import lua.*;
import haxe.io.Bytes;
import haxe.io.Error;
class Socket {
public var input(default, null):haxe.io.Input;
public var output(default, null):haxe.io.Output;
var custom:Dynamic;
var _socket:LuaSocket;
var blocking = false;
var timeout = null;
public function new():Void {}
public function close():Void {
_socket.close();
}
public function read():String {
return input.readAll().toString();
}
public function write(content:String):Void {
output.writeString(content);
}
public function connect(host:Host, port:Int):Void {
var res = LuaSocket.connect(host.host, port);
if (res.message != null)
throw 'Socket Error : ${res.message}';
input = new SocketInput(res.result);
output = new SocketOutput(res.result);
_socket = res.result;
_socket.settimeout(timeout);
}
public function listen(connections:Int):Void {
var res = LuaSocket.tcp();
if (res.message != null)
throw 'Socket Listen Error : ${res.message}';
res.result.listen(connections);
_socket = res.result;
_socket.settimeout(timeout);
}
public function shutdown(read:Bool, write:Bool):Void {
var client:TcpClient = cast _socket;
switch [read, write] {
case [true, true]:
client.shutdown(Both);
case [true, false]:
client.shutdown(Receive);
case [false, true]:
client.shutdown(Send);
default:
null;
}
}
public function bind(host:Host, port:Int):Void {
var res = LuaSocket.bind(host.host, port);
if (res.message != null)
throw 'Socket Bind Error : ${res.message}';
_socket = res.result;
}
public function accept():Socket {
var server:TcpServer = cast _socket;
var res = server.accept();
if (res.message != null)
throw 'Error : ${res.message}';
var sock = new Socket();
sock._socket = res.result;
sock.input = new SocketInput(res.result);
sock.output = new SocketOutput(res.result);
return sock;
}
public function peer():{host:Host, port:Int} {
var client:TcpClient = cast _socket;
var res = client.getpeername();
var host = new Host(res.address);
return {host: host, port: Std.parseInt(res.port)};
}
public function host():{host:Host, port:Int} {
var server:TcpServer = cast _socket;
var res = server.getsockname();
var host = new Host(res.address);
return {host: host, port: Std.parseInt(res.port)};
}
public inline function setTimeout(timeout:Float):Void {
this.timeout = timeout;
if (_socket != null) {
var client:TcpClient = cast _socket;
client.settimeout(timeout);
}
}
public function waitForRead():Void {
select([this], null, null);
}
public function setBlocking(b:Bool):Void {
blocking = b;
}
public function setFastSend(b:Bool):Void {
var client:TcpClient = cast _socket;
client.setoption(TcpNoDelay, true);
}
static public function select(read:Array<Socket>, write:Array<Socket>, others:Array<Socket>,
?timeout:Float):{read:Array<Socket>, write:Array<Socket>, others:Array<Socket>} {
var read_tbl = read == null ? Table.create() : Table.fromArray([for (r in read) cast r._socket]);
var write_tbl = write == null ? Table.create() : Table.fromArray(([for (r in write) cast r._socket]));
var res = LuaSocket.select(read_tbl, write_tbl, timeout);
var convert_socket = function(x:LuaSocket) {
var sock = new Socket();
sock.input = new SocketInput(cast x);
sock.output = new SocketOutput(cast x);
return sock;
}
var read_arr = res.read == null ? [] : Table.toArray(res.read).map(convert_socket);
var write_arr = res.write == null ? [] : Table.toArray(res.write).map(convert_socket);
return {read: read_arr, write: write_arr, others: []};
}
}
private class SocketInput extends haxe.io.Input {
var tcp:TcpClient;
public function new(tcp:TcpClient) {
this.tcp = tcp;
}
override public function readByte():Int {
var res = tcp.receive(1);
if (res.message == "closed"){
throw new haxe.io.Eof();
}
else if (res.message != null)
throw 'Error : ${res.message}';
return res.result.charCodeAt(0);
}
override public function readBytes(s:Bytes, pos:Int, len:Int):Int {
var leftToRead = len;
var b = s.getData();
if (pos < 0 || len < 0 || pos + len > s.length)
throw haxe.io.Error.OutsideBounds;
var readCount = 0;
try {
while (leftToRead > 0) {
b[pos] = cast readByte();
pos++;
readCount++;
leftToRead--;
}
} catch (e:haxe.io.Eof) {
if (readCount == 0) {
throw e;
}
}
return readCount;
}
}
private class SocketOutput extends haxe.io.Output {
var tcp:TcpClient;
public function new(tcp:TcpClient) {
this.tcp = tcp;
}
override public function writeByte(c:Int):Void {
var char = NativeStringTools.char(c);
var res = tcp.send(char);
if (res.message != null){
throw 'Error : Socket writeByte : ${res.message}';
}
}
override public function writeBytes(s:Bytes, pos:Int, len:Int):Int {
if (pos < 0 || len < 0 || pos + len > s.length)
throw Error.OutsideBounds;
var b = s.getData().slice(pos, pos +len).map(function(byte){
return lua.NativeStringTools.char(byte);
});
var encoded = Table.concat(cast b, 0);
var res = tcp.send(encoded);
if (res.message != null){
throw 'Error : Socket writeByte : ${res.message}';
}
return len;
}
}