List.hx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. * Copyright (C)2005-2012 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. /**
  23. A linked-list of elements. The list is composed of two-elements arrays
  24. that are chained together. It is optimized so that adding or removing an
  25. element does not imply copying the whole array content every time.
  26. **/
  27. class List<T> {
  28. private var h : Array<Dynamic>;
  29. private var q : Array<Dynamic>;
  30. /**
  31. The length of `this` List.
  32. **/
  33. public var length(default,null) : Int;
  34. /**
  35. Creates a new empty list.
  36. **/
  37. public function new() {
  38. length = 0;
  39. }
  40. /**
  41. Adds element `item` at the end of `this` List.
  42. `this.length` increases by 1.
  43. **/
  44. public function add( item : T ) {
  45. var x:Array<Dynamic> = #if neko untyped __dollar__array(item,null) #else [item] #end;
  46. if( h == null )
  47. h = x;
  48. else
  49. q[1] = x;
  50. q = x;
  51. length++;
  52. }
  53. /**
  54. Adds element `item` at the beginning of `this` List.
  55. `this.length` increases by 1.
  56. **/
  57. public function push( item : T ) {
  58. var x : Array<Dynamic> = #if neko
  59. untyped __dollar__array(item,h)
  60. #else
  61. [item,h]
  62. #end;
  63. h = x;
  64. if( q == null )
  65. q = x;
  66. length++;
  67. }
  68. /**
  69. Returns the first element of `this` List, or null if no elements exist.
  70. This function does not modify `this` List.
  71. **/
  72. public function first() : Null<T> {
  73. return if( h == null ) null else h[0];
  74. }
  75. /**
  76. Returns the last element of `this` List, or null if no elements exist.
  77. This function does not modify `this` List.
  78. **/
  79. public function last() : Null<T> {
  80. return if( q == null ) null else q[0];
  81. }
  82. /**
  83. Returns the first element of `this` List, or null if no elements exist.
  84. The element is removed from `this` List.
  85. **/
  86. public function pop() : Null<T> {
  87. if( h == null )
  88. return null;
  89. var x = h[0];
  90. h = h[1];
  91. if( h == null )
  92. q = null;
  93. length--;
  94. return x;
  95. }
  96. /**
  97. Tells if `this` List is empty.
  98. **/
  99. public function isEmpty() : Bool {
  100. return (h == null);
  101. }
  102. /**
  103. Empties `this` List.
  104. This function does not traverse the elements, but simply sets the
  105. internal references to null and `this.length` to 0.
  106. **/
  107. public function clear() : Void {
  108. h = null;
  109. q = null;
  110. length = 0;
  111. }
  112. /**
  113. Removes the first occurence of `v` in `this` List.
  114. If `v` is found by checking standard equality, it is removed from `this`
  115. List and the function returns true.
  116. Otherwise, false is returned.
  117. **/
  118. public function remove( v : T ) : Bool {
  119. var prev = null;
  120. var l = h;
  121. while( l != null ) {
  122. if( l[0] == v ) {
  123. if( prev == null )
  124. h = l[1];
  125. else
  126. prev[1] = l[1];
  127. if( q == l )
  128. q = prev;
  129. length--;
  130. return true;
  131. }
  132. prev = l;
  133. l = l[1];
  134. }
  135. return false;
  136. }
  137. /**
  138. Returns an iterator on the elements of the list.
  139. **/
  140. public inline function iterator() : ListIterator<T> {
  141. return new ListIterator<T>(h);
  142. }
  143. /**
  144. Returns a string representation of `this` List.
  145. The result is enclosed in { } with the individual elements being
  146. separated by a comma.
  147. **/
  148. public function toString() {
  149. var s = new StringBuf();
  150. var first = true;
  151. var l = h;
  152. s.add("{");
  153. while( l != null ) {
  154. if( first )
  155. first = false;
  156. else
  157. s.add(", ");
  158. s.add(Std.string(l[0]));
  159. l = l[1];
  160. }
  161. s.add("}");
  162. return s.toString();
  163. }
  164. /**
  165. Returns a string representation of `this` List, with `sep` separating
  166. each element.
  167. **/
  168. public function join(sep : String) {
  169. var s = new StringBuf();
  170. var first = true;
  171. var l = h;
  172. while( l != null ) {
  173. if( first )
  174. first = false;
  175. else
  176. s.add(sep);
  177. s.add(l[0]);
  178. l = l[1];
  179. }
  180. return s.toString();
  181. }
  182. /**
  183. Returns a list filtered with `f`. The returned list will contain all
  184. elements for which `f(x) == true`.
  185. **/
  186. public function filter( f : T -> Bool ) {
  187. var l2 = new List();
  188. var l = h;
  189. while( l != null ) {
  190. var v = l[0];
  191. l = l[1];
  192. if( f(v) )
  193. l2.add(v);
  194. }
  195. return l2;
  196. }
  197. /**
  198. Returns a new list where all elements have been converted by the
  199. function `f`.
  200. **/
  201. public function map<X>(f : T -> X) : List<X> {
  202. var b = new List();
  203. var l = h;
  204. while( l != null ) {
  205. var v = l[0];
  206. l = l[1];
  207. b.add(f(v));
  208. }
  209. return b;
  210. }
  211. }
  212. private class ListIterator<T> {
  213. var head:Array<Dynamic>;
  214. var val:Dynamic;
  215. public inline function new(head:Array<Dynamic>) {
  216. this.head = head;
  217. this.val = null;
  218. }
  219. public inline function hasNext():Bool {
  220. return head != null;
  221. }
  222. public inline function next():T {
  223. val = head[0];
  224. head = head[1];
  225. return val;
  226. }
  227. }