ArrayObj.hx 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /*
  2. * Copyright (C)2005-2019 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. package hl.types;
  23. @:keep
  24. class ArrayObj<T> extends ArrayBase {
  25. var array:hl.NativeArray<Dynamic>;
  26. public function new() {
  27. length = 0;
  28. array = new NativeArray<Dynamic>(0);
  29. }
  30. public function concat(a:ArrayObj<T>):ArrayObj<T> {
  31. var arr = new hl.NativeArray(length + a.length);
  32. arr.blit(0, array, 0, length);
  33. arr.blit(length, a.array, 0, a.length);
  34. return alloc(cast arr);
  35. }
  36. override function join(sep:String):String {
  37. var b = new StringBuf();
  38. for (i in 0...length) {
  39. if (i > 0)
  40. b.add(sep);
  41. b.add(array[i]);
  42. }
  43. return b.toString();
  44. }
  45. override function isArrayObj() {
  46. return true;
  47. }
  48. public function pop():Null<T> {
  49. if (length == 0)
  50. return null;
  51. length--;
  52. var v = array[length];
  53. array[length] = null;
  54. return v;
  55. }
  56. public function push(x:T):Int {
  57. var len = length;
  58. if (array.length == len)
  59. __expand(len);
  60. else
  61. length++;
  62. array[len] = x;
  63. return length;
  64. }
  65. override function reverse():Void {
  66. for (i in 0...length >> 1) {
  67. var k = length - 1 - i;
  68. var tmp = array[i];
  69. array[i] = array[k];
  70. array[k] = tmp;
  71. }
  72. }
  73. public function shift():Null<T> {
  74. if (length == 0)
  75. return null;
  76. length--;
  77. var v = array[0];
  78. array.blit(0, array, 1, length);
  79. array[length] = null;
  80. return v;
  81. }
  82. override function slice(pos:Int, ?end:Int):ArrayObj<T> {
  83. if (pos < 0) {
  84. pos = this.length + pos;
  85. if (pos < 0)
  86. pos = 0;
  87. }
  88. var pend:Int;
  89. if (end == null)
  90. pend = this.length;
  91. else {
  92. pend = end;
  93. if (pend < 0)
  94. pend += this.length;
  95. if (pend > this.length)
  96. pend = this.length;
  97. }
  98. var len = pend - pos;
  99. if (len < 0)
  100. return new ArrayObj();
  101. return alloc(array.sub(pos, len));
  102. }
  103. public function sort(f:T->T->Int):Void {
  104. // TODO : use native call ?
  105. haxe.ds.ArraySort.sort(cast this, f);
  106. }
  107. override function splice(pos:Int, len:Int):ArrayObj<T> {
  108. if (len < 0)
  109. return new ArrayObj();
  110. if (pos < 0) {
  111. pos = this.length + pos;
  112. if (pos < 0)
  113. pos = 0;
  114. }
  115. if (pos > this.length) {
  116. pos = 0;
  117. len = 0;
  118. } else if (pos + len > this.length) {
  119. len = this.length - pos;
  120. if (len < 0)
  121. len = 0;
  122. }
  123. var a = this.array;
  124. var ret:ArrayObj<T> = alloc(cast a.sub(pos, len));
  125. var end = pos + len;
  126. a.blit(pos, a, end, this.length - end);
  127. this.length -= len;
  128. while (--len >= 0)
  129. a[this.length + len] = null;
  130. return ret;
  131. }
  132. @:access(Std.toStringDepth)
  133. override function toString():String {
  134. if (Std.toStringDepth >= 5)
  135. return "...";
  136. Std.toStringDepth++;
  137. var b = new StringBuf();
  138. b.addChar("[".code);
  139. try {
  140. for (i in 0...length) {
  141. if (i > 0)
  142. b.addChar(",".code);
  143. b.add(array[i]);
  144. }
  145. } catch (e:Dynamic) {
  146. Std.toStringDepth--;
  147. hl.Api.rethrow(e);
  148. }
  149. b.addChar("]".code);
  150. Std.toStringDepth--;
  151. return b.toString();
  152. }
  153. public function unshift(x:T):Void {
  154. if (length == array.length)
  155. __expand(length)
  156. else
  157. length++;
  158. array.blit(1, array, 0, length - 1);
  159. array[0] = x;
  160. }
  161. public function insert(pos:Int, x:T):Void {
  162. if (pos < 0) {
  163. pos = length + pos;
  164. if (pos < 0)
  165. pos = 0;
  166. } else if (pos > length)
  167. pos = length;
  168. if (length == array.length)
  169. __expand(length)
  170. else
  171. length++;
  172. array.blit(pos + 1, array, pos, length - pos - 1);
  173. array[pos] = x;
  174. }
  175. public function remove(x:T):Bool {
  176. var i = indexOf(x);
  177. if (i < 0)
  178. return false;
  179. length--;
  180. array.blit(i, array, i + 1, length - i);
  181. array[length] = null;
  182. return true;
  183. }
  184. public function indexOf(x:T, ?fromIndex:Int):Int {
  185. var i:Int = fromIndex;
  186. if (i < 0) {
  187. i += length;
  188. if (i < 0)
  189. i = 0;
  190. }
  191. var length = length;
  192. var array = array;
  193. while (i < length) {
  194. if (array[i] == x)
  195. return i;
  196. i++;
  197. }
  198. return -1;
  199. }
  200. override function blit(pos:Int, src:ArrayBase.ArrayAccess, srcpos:Int, len:Int):Void {
  201. var src = (cast src : ArrayObj<T>);
  202. if (pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length)
  203. throw haxe.io.Error.OutsideBounds;
  204. array.blit(pos, src.array, srcpos, len);
  205. }
  206. public function lastIndexOf(x:T, ?fromIndex:Int):Int {
  207. var len = length;
  208. var i:Int = fromIndex != null ? fromIndex : len - 1;
  209. if (i >= len)
  210. i = len - 1;
  211. else if (i < 0)
  212. i += len;
  213. while (i >= 0) {
  214. if (array[i] == x)
  215. return i;
  216. i--;
  217. }
  218. return -1;
  219. }
  220. public function copy():ArrayObj<T> {
  221. var n = new NativeArray<Dynamic>(length);
  222. n.blit(0, array, 0, length);
  223. return alloc(n);
  224. }
  225. public function iterator():Iterator<T> {
  226. var n = new NativeArray.NativeArrayIterator<T>(cast array);
  227. @:privateAccess n.length = length;
  228. return n;
  229. }
  230. public function map<S>(f:T->S):ArrayDyn {
  231. var a = new ArrayObj();
  232. if (length > 0)
  233. a.__expand(length - 1);
  234. for (i in 0...length)
  235. a.array[i] = f(array[i]);
  236. return ArrayDyn.alloc(a, true);
  237. }
  238. public function filter(f:T->Bool):ArrayObj<T> {
  239. var a = new ArrayObj();
  240. for (i in 0...length) {
  241. var v = array[i];
  242. if (f(v))
  243. a.push(v);
  244. }
  245. return a;
  246. }
  247. override public function resize(len:Int):Void {
  248. if (length < len) {
  249. __expand(len - 1);
  250. } else if (length > len) {
  251. for (i in length...len) {
  252. array[i] = null;
  253. }
  254. this.length = len;
  255. }
  256. }
  257. // called by compiler when accessing the array outside of its bounds, might trigger resize
  258. function __expand(index:Int) {
  259. if (index < 0)
  260. throw "Invalid array index " + index;
  261. var newlen = index + 1;
  262. var size:Int = array.length;
  263. if (newlen > size) {
  264. var next = (size * 3) >> 1;
  265. if (next < newlen)
  266. next = newlen;
  267. var arr2 = new hl.NativeArray<Dynamic>(next);
  268. arr2.blit(0, array, 0, length);
  269. array = arr2;
  270. }
  271. length = newlen;
  272. }
  273. override function getDyn(pos:Int):Dynamic {
  274. var pos:UInt = pos;
  275. if (pos >= length)
  276. return null;
  277. return array[pos];
  278. }
  279. override function setDyn(pos:Int, v:Dynamic) {
  280. var pos:UInt = pos;
  281. if (pos >= length)
  282. __expand(pos);
  283. array[pos] = Api.safeCast(v, array.getType());
  284. }
  285. override function pushDyn(v:Dynamic)
  286. return push(v);
  287. override function popDyn():Null<Dynamic>
  288. return pop();
  289. override function shiftDyn():Null<Dynamic>
  290. return shift();
  291. override function unshiftDyn(v:Dynamic)
  292. unshift(v);
  293. override function insertDyn(pos:Int, v:Dynamic)
  294. insert(pos, v);
  295. override function removeDyn(v:Dynamic)
  296. return remove(v);
  297. override function sortDyn(f:Dynamic->Dynamic->Int)
  298. sort(f);
  299. public static function alloc<T>(a:hl.NativeArray<T>):ArrayObj<T> {
  300. var arr:ArrayObj<T> = untyped $new(ArrayObj);
  301. arr.array = a;
  302. arr.length = a.length;
  303. return arr;
  304. }
  305. }