/* * 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 final class Array { private var __a:neko.NativeArray; public var length(default, null):Int; public function new():Void { this.__a = neko.NativeArray.alloc(0); this.length = 0; } private static function new1(a:neko.NativeArray, l:Int):Array { var inst = new Array(); inst.__a = a; inst.length = l; return inst; } public function concat(a:Array):Array { var a1 = this.__a; var a2 = a.__a; var s1 = this.length; var s2 = a.length; var a = neko.NativeArray.alloc(s1 + s2); neko.NativeArray.blit(a, 0, a1, 0, s1); neko.NativeArray.blit(a, s1, a2, 0, s2); return new1(a, s1 + s2); } public function copy():Array { return new1(neko.NativeArray.sub(this.__a, 0, this.length), this.length); } public inline function iterator():haxe.iterators.ArrayIterator { return new haxe.iterators.ArrayIterator(this); } public inline function keyValueIterator():ArrayKeyValueIterator { return new ArrayKeyValueIterator(this); } public function insert(pos:Int, x:T):Void { var l = this.length; if (pos < 0) { pos = l + pos; if (pos < 0) pos = 0; } if (pos > l) pos = l; this.__grow(l + 1); var a = this.__a; neko.NativeArray.blit(a, pos + 1, a, pos, l - pos); a[pos] = x; } public function join(sep:String):String { var s = new StringBuf(); var a = this.__a; var max = this.length - 1; for (p in 0...this.length) { s.add(a[p]); if (p != max) s.add(sep); } return s.toString(); } static var __hx_toString_depth = 0; public function toString():String { if (__hx_toString_depth >= 5) { return "..."; } var s = new StringBuf(); s.add("["); var it = iterator(); __hx_toString_depth++; try { for (i in it) { s.add(i); if (it.hasNext()) s.addChar(",".code); } __hx_toString_depth--; } catch (e:Dynamic) { __hx_toString_depth--; neko.Lib.rethrow(e); } s.add("]"); return s.toString(); } public function pop():Null { if (this.length == 0) return null; this.length -= 1; var x = this.__a[this.length]; this.__a[this.length] = null; return x; } public function push(x:T):Int { var l = this.length; this.__grow(l + 1); this.__a[l] = x; return l + 1; } public function unshift(x:T):Void { var l = this.length; this.__grow(l + 1); var a = this.__a; neko.NativeArray.blit(a, 1, a, 0, l); a[0] = x; } public function remove(x:T):Bool { var i = 0; var l = this.length; var a = this.__a; while (i < l) { if (a[i] == x) { neko.NativeArray.blit(a, i, a, i + 1, l - i - 1); l -= 1; this.length = l; a[l] = null; return true; } i += 1; } return false; } public function contains(x:T):Bool { var i = 0; var l = this.length; var a = this.__a; while (i < l) { if (a[i] == x) { return true; } i += 1; } return false; } public function indexOf(x:T, ?fromIndex:Int):Int { var len = length; var i:Int = (fromIndex != null) ? fromIndex : 0; var a = __a; if (i < 0) { i += len; if (i < 0) i = 0; } while (i < len) { if (a[i] == x) return i; i++; } return -1; } public function lastIndexOf(x:T, ?fromIndex:Int):Int { var len = length; var i:Int = (fromIndex != null) ? fromIndex : len - 1; var a = __a; if (i >= len) i = len - 1; else if (i < 0) i += len; while (i >= 0) { if (a[i] == x) return i; i--; } return -1; } public function reverse():Void { var i = 0; var l = this.length; var a = this.__a; var half = l >> 1; l -= 1; while (i < half) { var tmp = a[i]; a[i] = a[l - i]; a[l - i] = tmp; i += 1; } } public function shift():Null { var l = this.length; if (l == 0) return null; var a = this.__a; var x = a[0]; l -= 1; neko.NativeArray.blit(a, 0, a, 1, l); a[l] = null; this.length = l; return x; } public function slice(pos:Int, ?end:Int):Array { if (pos < 0) { pos = this.length + pos; if (pos < 0) pos = 0; } if (end == null) end = this.length; else if (end < 0) end = this.length + end; if (end > this.length) end = this.length; var len = end - pos; if (len < 0) return new Array(); return new1(neko.NativeArray.sub(this.__a, pos, len), len); } public function sort(f:T->T->Int):Void { var a = this.__a; 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(a[j], a[j + 1]) > 0) { var tmp = a[j + 1]; a[j + 1] = a[j]; a[j] = tmp; swap = true; } j += 1; } if (!swap) break; i += 1; } } public function splice(pos:Int, len:Int):Array { if (len < 0) return new Array(); if (pos < 0) { pos = this.length + pos; if (pos < 0) pos = 0; } if (pos > this.length) { pos = 0; len = 0; } else if (pos + len > this.length) { len = this.length - pos; if (len < 0) len = 0; } var a = this.__a; var ret = new1(neko.NativeArray.sub(a, pos, len), len); var end = pos + len; neko.NativeArray.blit(a, pos, a, end, this.length - end); this.length -= len; while (--len >= 0) a[this.length + len] = null; return ret; } public inline function map(f:T->S):Array { var l = length; var ret = new1(neko.NativeArray.alloc(l), l); for (i in 0...l) { ret[i] = f(this[i]); } return ret; } public inline function filter(f:T->Bool):Array { var ret = []; for (elt in this) if (f(elt)) ret.push(elt); return ret; } public function resize(len:Int):Void { if (length < len) { __set(len - 1, null); } else if (length > len) { for (i in len...length) { __a[i] = null; } this.length = len; } } /* NEKO INTERNAL */ private function __get(pos:Int):T { return this.__a[pos]; } private function __set(pos:Int, v:T):T { var a = this.__a; if (this.length <= pos) { var l = pos + 1; var dlen = l - neko.NativeArray.length(a); if (dlen > 0) { if (dlen == 1) { this.__grow(l); a = this.__a; } else { a = neko.NativeArray.alloc(l); neko.NativeArray.blit(a, 0, this.__a, 0, this.length); this.__a = a; } } this.length = l; } a[pos] = v; return v; } private function __grow(l:Int):Void { var a = this.__a; var sz = neko.NativeArray.length(a); if (sz >= l) { this.length = l; return; } var big = (sz * 3) >> 1; if (big < l) big = l; var a2 = neko.NativeArray.alloc(big); neko.NativeArray.blit(a2, 0, a, 0, this.length); this.__a = a2; this.length = l; } private function __neko():neko.NativeArray { var a = this.__a; var sz = neko.NativeArray.length(a); if (sz != this.length) { a = neko.NativeArray.sub(a, 0, this.length); this.__a = a; } return a; } #if !(macro || interp) static function __init__():Void { try { var msort:Dynamic = neko.Lib.load("std", "merge_sort", 3); untyped Array.prototype.sort = function(cmp) msort(__this__.__a, __this__.length, cmp); } catch (e:Dynamic) {} } #end }