forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			314 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			314 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * 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;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
									A linked-list of elements. The list is composed of element container objects
							 | 
						||
| 
								 | 
							
									that are chained together. It is optimized so that adding or removing an
							 | 
						||
| 
								 | 
							
									element does not imply copying the whole list content every time.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									@see https://haxe.org/manual/std-List.html
							 | 
						||
| 
								 | 
							
								**/
							 | 
						||
| 
								 | 
							
								class List<T> {
							 | 
						||
| 
								 | 
							
									private var h:ListNode<T>;
							 | 
						||
| 
								 | 
							
									private var q:ListNode<T>;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										The length of `this` List.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public var length(default, null):Int;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Creates a new empty list.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function new() {
							 | 
						||
| 
								 | 
							
										length = 0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Adds element `item` at the end of `this` List.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										`this.length` increases by 1.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function add(item:T) {
							 | 
						||
| 
								 | 
							
										var x = ListNode.create(item, null);
							 | 
						||
| 
								 | 
							
										if (h == null)
							 | 
						||
| 
								 | 
							
											h = x;
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
											q.next = x;
							 | 
						||
| 
								 | 
							
										q = x;
							 | 
						||
| 
								 | 
							
										length++;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Adds element `item` at the beginning of `this` List.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										`this.length` increases by 1.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function push(item:T) {
							 | 
						||
| 
								 | 
							
										var x = ListNode.create(item, h);
							 | 
						||
| 
								 | 
							
										h = x;
							 | 
						||
| 
								 | 
							
										if (q == null)
							 | 
						||
| 
								 | 
							
											q = x;
							 | 
						||
| 
								 | 
							
										length++;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Returns the first element of `this` List, or null if no elements exist.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										This function does not modify `this` List.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function first():Null<T> {
							 | 
						||
| 
								 | 
							
										return if (h == null) null else h.item;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Returns the last element of `this` List, or null if no elements exist.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										This function does not modify `this` List.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function last():Null<T> {
							 | 
						||
| 
								 | 
							
										return if (q == null) null else q.item;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Returns the first element of `this` List, or null if no elements exist.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										The element is removed from `this` List.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function pop():Null<T> {
							 | 
						||
| 
								 | 
							
										if (h == null)
							 | 
						||
| 
								 | 
							
											return null;
							 | 
						||
| 
								 | 
							
										var x = h.item;
							 | 
						||
| 
								 | 
							
										h = h.next;
							 | 
						||
| 
								 | 
							
										if (h == null)
							 | 
						||
| 
								 | 
							
											q = null;
							 | 
						||
| 
								 | 
							
										length--;
							 | 
						||
| 
								 | 
							
										return x;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Tells if `this` List is empty.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function isEmpty():Bool {
							 | 
						||
| 
								 | 
							
										return (h == null);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Empties `this` List.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										This function does not traverse the elements, but simply sets the
							 | 
						||
| 
								 | 
							
										internal references to null and `this.length` to 0.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function clear():Void {
							 | 
						||
| 
								 | 
							
										h = null;
							 | 
						||
| 
								 | 
							
										q = null;
							 | 
						||
| 
								 | 
							
										length = 0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Removes the first occurrence of `v` in `this` List.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										If `v` is found by checking standard equality, it is removed from `this`
							 | 
						||
| 
								 | 
							
										List and the function returns true.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										Otherwise, false is returned.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function remove(v:T):Bool {
							 | 
						||
| 
								 | 
							
										var prev:ListNode<T> = null;
							 | 
						||
| 
								 | 
							
										var l = h;
							 | 
						||
| 
								 | 
							
										while (l != null) {
							 | 
						||
| 
								 | 
							
											if (l.item == v) {
							 | 
						||
| 
								 | 
							
												if (prev == null)
							 | 
						||
| 
								 | 
							
													h = l.next;
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
													prev.next = l.next;
							 | 
						||
| 
								 | 
							
												if (q == l)
							 | 
						||
| 
								 | 
							
													q = prev;
							 | 
						||
| 
								 | 
							
												length--;
							 | 
						||
| 
								 | 
							
												return true;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											prev = l;
							 | 
						||
| 
								 | 
							
											l = l.next;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Returns an iterator on the elements of the list.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public inline function iterator():ListIterator<T> {
							 | 
						||
| 
								 | 
							
										return new ListIterator<T>(h);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Returns an iterator of the List indices and values.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									@:pure @:runtime public inline function keyValueIterator():ListKeyValueIterator<T> {
							 | 
						||
| 
								 | 
							
										return new ListKeyValueIterator(h);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Returns a string representation of `this` List.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										The result is enclosed in { } with the individual elements being
							 | 
						||
| 
								 | 
							
										separated by a comma.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function toString() {
							 | 
						||
| 
								 | 
							
										var s = new StringBuf();
							 | 
						||
| 
								 | 
							
										var first = true;
							 | 
						||
| 
								 | 
							
										var l = h;
							 | 
						||
| 
								 | 
							
										s.add("{");
							 | 
						||
| 
								 | 
							
										while (l != null) {
							 | 
						||
| 
								 | 
							
											if (first)
							 | 
						||
| 
								 | 
							
												first = false;
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												s.add(", ");
							 | 
						||
| 
								 | 
							
											s.add(Std.string(l.item));
							 | 
						||
| 
								 | 
							
											l = l.next;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										s.add("}");
							 | 
						||
| 
								 | 
							
										return s.toString();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Returns a string representation of `this` List, with `sep` separating
							 | 
						||
| 
								 | 
							
										each element.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function join(sep:String) {
							 | 
						||
| 
								 | 
							
										var s = new StringBuf();
							 | 
						||
| 
								 | 
							
										var first = true;
							 | 
						||
| 
								 | 
							
										var l = h;
							 | 
						||
| 
								 | 
							
										while (l != null) {
							 | 
						||
| 
								 | 
							
											if (first)
							 | 
						||
| 
								 | 
							
												first = false;
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												s.add(sep);
							 | 
						||
| 
								 | 
							
											s.add(l.item);
							 | 
						||
| 
								 | 
							
											l = l.next;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return s.toString();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Returns a list filtered with `f`. The returned list will contain all
							 | 
						||
| 
								 | 
							
										elements for which `f(x) == true`.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function filter(f:T->Bool) {
							 | 
						||
| 
								 | 
							
										var l2 = new List();
							 | 
						||
| 
								 | 
							
										var l = h;
							 | 
						||
| 
								 | 
							
										while (l != null) {
							 | 
						||
| 
								 | 
							
											var v = l.item;
							 | 
						||
| 
								 | 
							
											l = l.next;
							 | 
						||
| 
								 | 
							
											if (f(v))
							 | 
						||
| 
								 | 
							
												l2.add(v);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return l2;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
										Returns a new list where all elements have been converted by the
							 | 
						||
| 
								 | 
							
										function `f`.
							 | 
						||
| 
								 | 
							
									**/
							 | 
						||
| 
								 | 
							
									public function map<X>(f:T->X):List<X> {
							 | 
						||
| 
								 | 
							
										var b = new List();
							 | 
						||
| 
								 | 
							
										var l = h;
							 | 
						||
| 
								 | 
							
										while (l != null) {
							 | 
						||
| 
								 | 
							
											var v = l.item;
							 | 
						||
| 
								 | 
							
											l = l.next;
							 | 
						||
| 
								 | 
							
											b.add(f(v));
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return b;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if neko
							 | 
						||
| 
								 | 
							
								private extern class ListNode<T> extends neko.NativeArray<Dynamic> {
							 | 
						||
| 
								 | 
							
									var item(get, set):T;
							 | 
						||
| 
								 | 
							
									var next(get, set):ListNode<T>;
							 | 
						||
| 
								 | 
							
									private inline function get_item():T
							 | 
						||
| 
								 | 
							
										return this[0];
							 | 
						||
| 
								 | 
							
									private inline function set_item(v:T):T
							 | 
						||
| 
								 | 
							
										return this[0] = v;
							 | 
						||
| 
								 | 
							
									private inline function get_next():ListNode<T>
							 | 
						||
| 
								 | 
							
										return this[1];
							 | 
						||
| 
								 | 
							
									private inline function set_next(v:ListNode<T>):ListNode<T>
							 | 
						||
| 
								 | 
							
										return this[1] = v;
							 | 
						||
| 
								 | 
							
									inline static function create<T>(item:T, next:ListNode<T>):ListNode<T> {
							 | 
						||
| 
								 | 
							
										return untyped __dollar__array(item, next);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								private class ListNode<T> {
							 | 
						||
| 
								 | 
							
									public var item:T;
							 | 
						||
| 
								 | 
							
									public var next:ListNode<T>;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public function new(item:T, next:ListNode<T>) {
							 | 
						||
| 
								 | 
							
										this.item = item;
							 | 
						||
| 
								 | 
							
										this.next = next;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									extern public inline static function create<T>(item:T, next:ListNode<T>):ListNode<T> {
							 | 
						||
| 
								 | 
							
										return new ListNode(item, next);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private class ListIterator<T> {
							 | 
						||
| 
								 | 
							
									var head:ListNode<T>;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public inline function new(head:ListNode<T>) {
							 | 
						||
| 
								 | 
							
										this.head = head;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public inline function hasNext():Bool {
							 | 
						||
| 
								 | 
							
										return head != null;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public inline function next():T {
							 | 
						||
| 
								 | 
							
										var val = head.item;
							 | 
						||
| 
								 | 
							
										head = head.next;
							 | 
						||
| 
								 | 
							
										return val;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private class ListKeyValueIterator<T> {
							 | 
						||
| 
								 | 
							
									var idx:Int;
							 | 
						||
| 
								 | 
							
									var head:ListNode<T>;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public inline function new(head:ListNode<T>) {
							 | 
						||
| 
								 | 
							
										this.head = head;
							 | 
						||
| 
								 | 
							
										this.idx = 0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public inline function hasNext():Bool {
							 | 
						||
| 
								 | 
							
										return head != null;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public inline function next():{key:Int, value:T} {
							 | 
						||
| 
								 | 
							
										var val = head.item;
							 | 
						||
| 
								 | 
							
										head = head.next;
							 | 
						||
| 
								 | 
							
										return {value: val, key: idx++};
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |