PageRenderTime 28ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/src/sys/java/fan/sys/List.java

https://bitbucket.org/bedlaczech/fan-1.0
Java | 1382 lines | 1166 code | 138 blank | 78 comment | 319 complexity | 4785202db036706dec8cfde44a2df6ec MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. //
  2. // Copyright (c) 2006, Brian Frank and Andy Frank
  3. // Licensed under the Academic Free License version 3.0
  4. //
  5. // History:
  6. // 4 Dec 05 Brian Frank Creation
  7. //
  8. package fan.sys;
  9. import java.lang.Thread;
  10. import java.lang.reflect.Array;
  11. import java.math.BigDecimal;
  12. import java.util.Arrays;
  13. import java.util.Collection;
  14. import java.util.Comparator;
  15. import java.util.HashMap;
  16. import fanx.serial.*;
  17. import fanx.util.*;
  18. /**
  19. * List
  20. */
  21. public final class List
  22. extends FanObj
  23. implements Literal
  24. {
  25. //////////////////////////////////////////////////////////////////////////
  26. // Constructors
  27. //////////////////////////////////////////////////////////////////////////
  28. public static List make(Type of, long capacity)
  29. {
  30. return new List(of, (int)capacity);
  31. }
  32. public static List makeObj(long capacity)
  33. {
  34. return new List(Sys.ObjType.toNullable(), (int)capacity);
  35. }
  36. public static List make(Type of, Object[] values)
  37. {
  38. if (values == null) return null;
  39. return new List(of, values);
  40. }
  41. public List(Type of, Object[] values)
  42. {
  43. if (of == null) { Thread.dumpStack(); throw NullErr.make(); }
  44. this.of = of;
  45. this.values = values;
  46. this.size = values.length;
  47. }
  48. public List(Type of, Object[] values, int size)
  49. {
  50. if (of == null) { Thread.dumpStack(); throw NullErr.make(); }
  51. this.of = of;
  52. this.values = values;
  53. this.size = size;
  54. }
  55. public List(Type of, int capacity)
  56. {
  57. if (of == null) { Thread.dumpStack(); throw NullErr.make(); }
  58. this.of = of;
  59. this.values = capacity == 0 ? empty : newArray(capacity);
  60. }
  61. public List(Type of)
  62. {
  63. if (of == null) { Thread.dumpStack(); throw NullErr.make(); }
  64. this.of = of;
  65. this.values = empty;
  66. }
  67. public List(Type of, Collection collection)
  68. {
  69. if (of == null) { Thread.dumpStack(); throw NullErr.make(); }
  70. this.of = of;
  71. this.size = collection.size();
  72. this.values = collection.toArray(newArray(size));
  73. }
  74. public List(String[] values)
  75. {
  76. this.of = Sys.StrType;
  77. this.size = values.length;
  78. this.values = values;
  79. }
  80. //////////////////////////////////////////////////////////////////////////
  81. // Identity
  82. //////////////////////////////////////////////////////////////////////////
  83. public final Type typeof()
  84. {
  85. return of.toListOf();
  86. }
  87. public final Type of()
  88. {
  89. return of;
  90. }
  91. //////////////////////////////////////////////////////////////////////////
  92. // Access
  93. //////////////////////////////////////////////////////////////////////////
  94. public final boolean isEmpty()
  95. {
  96. return size == 0;
  97. }
  98. public final long size()
  99. {
  100. return size;
  101. }
  102. public final void size(long s)
  103. {
  104. modify();
  105. int newSize = (int)s;
  106. if (newSize > size)
  107. {
  108. if (!of.isNullable()) throw ArgErr.make("Cannot grow non-nullable list of " + of);
  109. if (newSize > values.length)
  110. {
  111. Object[] temp = newArray(newSize);
  112. System.arraycopy(values, 0, temp, 0, size);
  113. values = temp;
  114. }
  115. else
  116. {
  117. for (int i=size; i<newSize; ++i) values[i] = null;
  118. }
  119. size = newSize;
  120. }
  121. else
  122. {
  123. // null out removed items for GC
  124. for (int i=newSize; i<size; ++i) values[i] = null;
  125. size = newSize;
  126. }
  127. }
  128. public final long capacity()
  129. {
  130. return values.length;
  131. }
  132. public final void capacity(long c)
  133. {
  134. modify();
  135. int newCapacity = (int)c;
  136. if (newCapacity < size) throw ArgErr.make("capacity < size");
  137. Object[] temp = newArray(newCapacity);
  138. System.arraycopy(values, 0, temp, 0, size);
  139. values = temp;
  140. }
  141. public final Object get(long index)
  142. {
  143. try
  144. {
  145. int i = (int)index;
  146. if (i < 0) i = size + i;
  147. if (i >= size) throw IndexErr.make(index);
  148. return values[i];
  149. }
  150. catch (ArrayIndexOutOfBoundsException e)
  151. {
  152. throw IndexErr.make(index);
  153. }
  154. }
  155. public final Object getSafe(long index) { return getSafe(index, null); }
  156. public final Object getSafe(long index, Object def)
  157. {
  158. if (index < 0) index = size + index;
  159. if (index >= size || index < 0) return def;
  160. return values[(int)index];
  161. }
  162. public final List getRange(Range r)
  163. {
  164. try
  165. {
  166. int s = r.startIndex(size);
  167. int e = r.endIndex(size);
  168. int n = e - s + 1;
  169. if (n < 0) throw IndexErr.make(r);
  170. List acc = new List(of, n);
  171. acc.size = n;
  172. System.arraycopy(values, s, acc.values, 0, n);
  173. return acc;
  174. }
  175. catch (ArrayIndexOutOfBoundsException e)
  176. {
  177. throw IndexErr.make(r);
  178. }
  179. }
  180. public final boolean contains(Object value)
  181. {
  182. return index(value) != null;
  183. }
  184. public final boolean containsAll(List list)
  185. {
  186. for (int i=0; i<list.sz(); ++i)
  187. if (index(list.get(i)) == null)
  188. return false;
  189. return true;
  190. }
  191. public final boolean containsAny(List list)
  192. {
  193. for (int i=0; i<list.sz(); ++i)
  194. if (index(list.get(i)) != null)
  195. return true;
  196. return false;
  197. }
  198. public final Long index(Object value) { return index(value, 0L); }
  199. public final Long index(Object value, long off)
  200. {
  201. if (size == 0) return null;
  202. int start = (int)off;
  203. if (start < 0) start = size + start;
  204. if (start >= size) throw IndexErr.make(off);
  205. try
  206. {
  207. if (value == null)
  208. {
  209. for (int i=start; i<size; ++i)
  210. if (values[i] == null)
  211. return Long.valueOf(i);
  212. }
  213. else
  214. {
  215. for (int i=start; i<size; ++i)
  216. {
  217. Object obj = values[i];
  218. if (obj != null && obj.equals(value))
  219. return Long.valueOf(i);
  220. }
  221. }
  222. return null;
  223. }
  224. catch (ArrayIndexOutOfBoundsException e)
  225. {
  226. throw IndexErr.make(off);
  227. }
  228. }
  229. public final Long indexr(Object value) { return indexr(value, -1L); }
  230. public final Long indexr(Object value, long off)
  231. {
  232. if (size == 0) return null;
  233. int start = (int)off;
  234. if (start < 0) start = size + start;
  235. if (start >= size) throw IndexErr.make(off);
  236. try
  237. {
  238. if (value == null)
  239. {
  240. for (int i=start; i>=0; --i)
  241. if (values[i] == null)
  242. return Long.valueOf(i);
  243. }
  244. else
  245. {
  246. for (int i=start; i>=0; --i)
  247. {
  248. Object obj = values[i];
  249. if (obj != null && obj.equals(value))
  250. return Long.valueOf(i);
  251. }
  252. }
  253. return null;
  254. }
  255. catch (ArrayIndexOutOfBoundsException e)
  256. {
  257. throw IndexErr.make(off);
  258. }
  259. }
  260. public final Long indexSame(Object value) { return indexSame(value, 0L); }
  261. public final Long indexSame(Object value, long off)
  262. {
  263. if (size == 0) return null;
  264. int start = (int)off;
  265. if (start < 0) start = size + start;
  266. if (start >= size) throw IndexErr.make(off);
  267. try
  268. {
  269. for (int i=start; i<size; ++i)
  270. if (value == values[i])
  271. return Long.valueOf(i);
  272. return null;
  273. }
  274. catch (ArrayIndexOutOfBoundsException e)
  275. {
  276. throw IndexErr.make(off);
  277. }
  278. }
  279. public final Object first()
  280. {
  281. if (size == 0) return null;
  282. return values[0];
  283. }
  284. public final Object last()
  285. {
  286. if (size == 0) return null;
  287. return values[size-1];
  288. }
  289. public final List dup()
  290. {
  291. Object[] dup = newArray(size);
  292. System.arraycopy(values, 0, dup, 0, size);
  293. return new List(of, dup);
  294. }
  295. public final long hash()
  296. {
  297. long hash = 33;
  298. for (int i=0; i<size; ++i)
  299. {
  300. Object obj = values[i];
  301. hash = (31*hash) + (obj == null ? 0 : hash(obj));
  302. }
  303. return hash;
  304. }
  305. public final boolean equals(Object that)
  306. {
  307. if (that instanceof List)
  308. {
  309. List x = (List)that;
  310. if (!of.equals(x.of)) return false;
  311. if (size != x.size) return false;
  312. for (int i=0; i<size; ++i)
  313. if (!OpUtil.compareEQ(values[i], x.values[i])) return false;
  314. return true;
  315. }
  316. return false;
  317. }
  318. //////////////////////////////////////////////////////////////////////////
  319. // Modification
  320. //////////////////////////////////////////////////////////////////////////
  321. public final List set(long index, Object value)
  322. {
  323. modify();
  324. try
  325. {
  326. int i = (int)index;
  327. if (i < 0) i = size + i;
  328. if (i >= size) throw IndexErr.make(index);
  329. values[i] = value;
  330. return this;
  331. }
  332. catch (ArrayIndexOutOfBoundsException e)
  333. {
  334. throw IndexErr.make(index);
  335. }
  336. catch (ArrayStoreException e)
  337. {
  338. throw CastErr.make("Setting '" + FanObj.typeof(value) + "' into '" + of + "[]'");
  339. }
  340. }
  341. public final List add(Object value)
  342. {
  343. // modify in insert(int, Obj)
  344. return insert(size, value);
  345. }
  346. public final List addAll(List list)
  347. {
  348. // modify in insertAll(int, List)
  349. return insertAll(size, list);
  350. }
  351. public final List insert(long index, Object value)
  352. {
  353. // modify in insert(int, Obj)
  354. int i = (int)index;
  355. if (i < 0) i = size + i;
  356. if (i > size) throw IndexErr.make(index);
  357. return insert(i, value);
  358. }
  359. private List insert(int i, Object value)
  360. {
  361. try
  362. {
  363. modify();
  364. if (values.length <= size)
  365. grow(size+1);
  366. if (i < size)
  367. System.arraycopy(values, i, values, i+1, size-i);
  368. values[i] = value;
  369. size++;
  370. return this;
  371. }
  372. catch (ArrayStoreException e)
  373. {
  374. throw CastErr.make("Adding '" + FanObj.typeof(value) + "' into '" + of + "[]'");
  375. }
  376. }
  377. public final List insertAll(long index, List list)
  378. {
  379. // modify in insertAll(int, List)
  380. int i = (int)index;
  381. if (i < 0) i = size + i;
  382. if (i > size || i < 0) throw IndexErr.make(index);
  383. return insertAll(i, list);
  384. }
  385. private List insertAll(int i, List list)
  386. {
  387. modify();
  388. if (list.size == 0) return this;
  389. if (values.length < size+list.size)
  390. grow(size+list.size);
  391. if (i < size)
  392. System.arraycopy(values, i, values, i+list.size, size-i);
  393. System.arraycopy(list.values, 0, values, i, list.size);
  394. size+=list.size;
  395. return this;
  396. }
  397. public final Object remove(Object val)
  398. {
  399. // modify in removeAt(Int)
  400. Long index = index(val);
  401. if (index == null) return null;
  402. return removeAt(index);
  403. }
  404. public final Object removeSame(Object val)
  405. {
  406. // modify in removeAt(Int)
  407. Long index = indexSame(val);
  408. if (index == null) return null;
  409. return removeAt(index);
  410. }
  411. public final Object removeAt(long index)
  412. {
  413. modify();
  414. int i = (int)index;
  415. if (i < 0) i = size + i;
  416. if (i >= size) throw IndexErr.make(index);
  417. Object old = values[i];
  418. if (i < size-1)
  419. System.arraycopy(values, i+1, values, i, size-i-1);
  420. size--;
  421. return old;
  422. }
  423. public final List removeRange(Range r)
  424. {
  425. modify();
  426. int s = r.startIndex(size);
  427. int e = r.endIndex(size);
  428. int n = e - s + 1;
  429. if (n < 0) throw IndexErr.make(r);
  430. int shift = size-s-n;
  431. if (shift > 0) System.arraycopy(values, s+n, values, s, shift);
  432. size -= n;
  433. for (int i=size; i<size+n; ++i) values[i] = null;
  434. return this;
  435. }
  436. public final List removeAll(List toRemove)
  437. {
  438. // optimize special cases
  439. modify();
  440. if (toRemove.sz() == 0) { return this; }
  441. if (toRemove.sz() == 1) { remove(toRemove.get(0)); return this; }
  442. // rebuild the backing store array, implementation
  443. // assumes that this list is bigger than toRemove list
  444. Object[] newValues = newArray(values.length);
  445. int newSize = 0;
  446. for (int i=0; i<size; ++i)
  447. {
  448. Object val = values[i];
  449. if (!toRemove.contains(val)) newValues[newSize++] = val;
  450. }
  451. this.values = newValues;
  452. this.size = newSize;
  453. return this;
  454. }
  455. private void grow(int desiredSize)
  456. {
  457. int desired = (int)desiredSize;
  458. if (desired < 1) throw Err.make("desired " + desired + " < 1");
  459. int newSize = Math.max(desired, size*2);
  460. if (newSize < 10) newSize = 10;
  461. Object[] temp = newArray(newSize);
  462. System.arraycopy(values, 0, temp, 0, size);
  463. values = temp;
  464. }
  465. public final List trim()
  466. {
  467. modify();
  468. if (size == 0)
  469. {
  470. values = empty;
  471. }
  472. else if (values.length != size)
  473. {
  474. Object[] temp = newArray(size);
  475. System.arraycopy(values, 0, temp, 0, size);
  476. values = temp;
  477. }
  478. return this;
  479. }
  480. public final List clear()
  481. {
  482. modify();
  483. for (int i=0; i<size; ++i)
  484. values[i] = null;
  485. size = 0;
  486. return this;
  487. }
  488. public final List fill(Object val, long times)
  489. {
  490. modify();
  491. int t = (int)times;
  492. if (values.length < size+t) grow(size+t);
  493. for (int i=0; i<t; ++i) values[size+i] = val;
  494. size += t;
  495. return this;
  496. }
  497. //////////////////////////////////////////////////////////////////////////
  498. // Stack
  499. //////////////////////////////////////////////////////////////////////////
  500. public final Object peek()
  501. {
  502. if (size == 0) return null;
  503. return values[size-1];
  504. }
  505. public final Object pop()
  506. {
  507. // modify in removeAt()
  508. if (size == 0) return null;
  509. return removeAt(-1);
  510. }
  511. public final List push(Object obj)
  512. {
  513. // modify in add()
  514. return add(obj);
  515. }
  516. //////////////////////////////////////////////////////////////////////////
  517. // Iterators
  518. //////////////////////////////////////////////////////////////////////////
  519. public final void each(Func f)
  520. {
  521. if (f.arity() == 1)
  522. {
  523. for (int i=0; i<size; ++i)
  524. f.call(values[i]);
  525. }
  526. else
  527. {
  528. for (int i=0; i<size; ++i)
  529. f.call(values[i], Long.valueOf(i));
  530. }
  531. }
  532. public final void eachr(Func f)
  533. {
  534. if (f.arity() == 1)
  535. {
  536. for (int i=size-1; i>=0; --i)
  537. f.call(values[i]);
  538. }
  539. else
  540. {
  541. for (int i=size-1; i>=0; --i)
  542. f.call(values[i], Long.valueOf(i));
  543. }
  544. }
  545. public final void eachRange(Range r, Func f)
  546. {
  547. int s = r.startIndex(size);
  548. int e = r.endIndex(size);
  549. int n = e - s + 1;
  550. if (n < 0) throw IndexErr.make(r);
  551. if (f.arity() == 1)
  552. {
  553. for (int i=s; i<=e; ++i)
  554. f.call(values[i]);
  555. }
  556. else
  557. {
  558. for (int i=s; i<=e; ++i)
  559. f.call(values[i], Long.valueOf(i));
  560. }
  561. }
  562. public final Object eachWhile(Func f)
  563. {
  564. if (f.arity() == 1)
  565. {
  566. for (int i=0; i<size; ++i)
  567. {
  568. Object r = f.call(values[i]);
  569. if (r != null) return r;
  570. }
  571. }
  572. else
  573. {
  574. for (int i=0; i<size; ++i)
  575. {
  576. Object r = f.call(values[i], Long.valueOf(i));
  577. if (r != null) return r;
  578. }
  579. }
  580. return null;
  581. }
  582. public final Object eachrWhile(Func f)
  583. {
  584. if (f.arity() == 1)
  585. {
  586. for (int i=size-1; i>=0; --i)
  587. {
  588. Object r = f.call(values[i]);
  589. if (r != null) return r;
  590. }
  591. }
  592. else
  593. {
  594. for (int i=size-1; i>=0; --i)
  595. {
  596. Object r = f.call(values[i], Long.valueOf(i));
  597. if (r != null) return r;
  598. }
  599. }
  600. return null;
  601. }
  602. public final Object find(Func f)
  603. {
  604. if (f.arity() == 1)
  605. {
  606. for (int i=0; i<size; ++i)
  607. if (f.callBool(values[i]))
  608. return values[i];
  609. }
  610. else
  611. {
  612. for (int i=0; i<size; ++i)
  613. if (f.callBool(values[i], Long.valueOf(i)))
  614. return values[i];
  615. }
  616. return null;
  617. }
  618. public final Long findIndex(Func f)
  619. {
  620. if (f.arity() == 1)
  621. {
  622. for (int i=0; i<size; ++i)
  623. {
  624. if (f.callBool(values[i]))
  625. return Long.valueOf(i);
  626. }
  627. }
  628. else
  629. {
  630. for (int i=0; i<size; ++i)
  631. {
  632. Long pos = Long.valueOf(i);
  633. if (f.callBool(values[i], pos))
  634. return pos;
  635. }
  636. }
  637. return null;
  638. }
  639. public final List findAll(Func f)
  640. {
  641. List acc = new List(of, size);
  642. if (f.arity() == 1)
  643. {
  644. for (int i=0; i<size; ++i)
  645. if (f.callBool(values[i]))
  646. acc.add(values[i]);
  647. }
  648. else
  649. {
  650. for (int i=0; i<size; ++i)
  651. if (f.callBool(values[i], Long.valueOf(i)))
  652. acc.add(values[i]);
  653. }
  654. return acc;
  655. }
  656. public final List findType(Type t)
  657. {
  658. List acc = new List(t, size);
  659. for (int i=0; i<size; ++i)
  660. {
  661. Object item = values[i];
  662. if (item != null && typeof(item).is(t))
  663. acc.add(item);
  664. }
  665. return acc;
  666. }
  667. public final List exclude(Func f)
  668. {
  669. List acc = new List(of, size);
  670. if (f.arity() == 1)
  671. {
  672. for (int i=0; i<size; ++i)
  673. if (!f.callBool(values[i]))
  674. acc.add(values[i]);
  675. }
  676. else
  677. {
  678. for (int i=0; i<size; ++i)
  679. if (!f.callBool(values[i], Long.valueOf(i)))
  680. acc.add(values[i]);
  681. }
  682. return acc;
  683. }
  684. public final boolean any(Func f)
  685. {
  686. if (f.arity() == 1)
  687. {
  688. for (int i=0; i<size; ++i)
  689. if (f.callBool(values[i]))
  690. return true;
  691. }
  692. else
  693. {
  694. for (int i=0; i<size; ++i)
  695. if (f.callBool(values[i], Long.valueOf(i)))
  696. return true;
  697. }
  698. return false;
  699. }
  700. public final boolean all(Func f)
  701. {
  702. if (f.arity() == 1)
  703. {
  704. for (int i=0; i<size; ++i)
  705. if (!f.callBool(values[i]))
  706. return false;
  707. }
  708. else
  709. {
  710. for (int i=0; i<size; ++i)
  711. if (!f.callBool(values[i], Long.valueOf(i)))
  712. return false;
  713. }
  714. return true;
  715. }
  716. public final Object reduce(Object reduction, Func f)
  717. {
  718. if (f.arity() == 1)
  719. {
  720. for (int i=0; i<size; ++i)
  721. reduction = f.call(reduction, values[i]);
  722. }
  723. else
  724. {
  725. for (int i=0; i<size; ++i)
  726. reduction = f.call(reduction, values[i], Long.valueOf(i));
  727. }
  728. return reduction;
  729. }
  730. public final List map(Func f)
  731. {
  732. Type r = f.returns();
  733. if (r == Sys.VoidType) r = Sys.ObjType.toNullable();
  734. List acc = new List(r, (int)size());
  735. if (f.arity() == 1)
  736. {
  737. for (int i=0; i<size; ++i)
  738. acc.add(f.call(values[i]));
  739. }
  740. else
  741. {
  742. for (int i=0; i<size; ++i)
  743. acc.add(f.call(values[i], Long.valueOf(i)));
  744. }
  745. return acc;
  746. }
  747. public final Object max() { return max(null); }
  748. public final Object max(Func f)
  749. {
  750. if (size == 0) return null;
  751. Comparator c = toComparator(f);
  752. Object max = values[0];
  753. for (int i=1; i<size; ++i)
  754. if (c.compare(values[i], max) > 0)
  755. max = values[i];
  756. return max;
  757. }
  758. public final Object min() { return min(null); }
  759. public final Object min(Func f)
  760. {
  761. if (size == 0) return null;
  762. Comparator c = toComparator(f);
  763. Object min = values[0];
  764. for (int i=1; i<size; ++i)
  765. if (c.compare(values[i], min) < 0)
  766. min = values[i];
  767. return min;
  768. }
  769. public final List unique()
  770. {
  771. if (size <= 1) return dup();
  772. HashMap dups = new HashMap(size*3);
  773. List acc = new List(of, size);
  774. for (int i=0; i<size; ++i)
  775. {
  776. Object v = values[i];
  777. if (dups.get(v) == null)
  778. {
  779. dups.put(v, this);
  780. acc.add(v);
  781. }
  782. }
  783. return acc;
  784. }
  785. public final List union(List that)
  786. {
  787. int capacity = size + that.size;
  788. HashMap dups = new HashMap(capacity*3);
  789. List acc = new List(of, capacity);
  790. // first me
  791. for (int i=0; i<size; ++i)
  792. {
  793. Object v = values[i];
  794. if (dups.get(v) == null)
  795. {
  796. dups.put(v, this);
  797. acc.add(v);
  798. }
  799. }
  800. // then him
  801. for (int i=0; i<that.size; ++i)
  802. {
  803. Object v = that.values[i];
  804. if (dups.get(v) == null)
  805. {
  806. dups.put(v, this);
  807. acc.add(v);
  808. }
  809. }
  810. return acc;
  811. }
  812. public final List intersection(List that)
  813. {
  814. // put other list into map
  815. HashMap dups = new HashMap(that.size*3);
  816. for (int i=0; i<that.size; ++i)
  817. dups.put(that.values[i], this);
  818. // now walk this list and accumulate
  819. // everything found in the dups map
  820. List acc = new List(of, size);
  821. for (int i=0; i<size; ++i)
  822. {
  823. Object v = values[i];
  824. if (dups.get(v) != null)
  825. {
  826. acc.add(v);
  827. dups.remove(v);
  828. }
  829. }
  830. return acc;
  831. }
  832. //////////////////////////////////////////////////////////////////////////
  833. // Utils
  834. //////////////////////////////////////////////////////////////////////////
  835. public final List sort() { return sort(null); }
  836. public final List sort(final Func f)
  837. {
  838. modify();
  839. Arrays.sort(values, 0, size, toComparator(f));
  840. return this;
  841. }
  842. public final List sortr() { return sortr(null); }
  843. public final List sortr(final Func f)
  844. {
  845. modify();
  846. Arrays.sort(values, 0, size, toReverseComparator(f));
  847. return this;
  848. }
  849. public final long binarySearch(Object key) { return binarySearch(key, null); }
  850. public final long binarySearch(Object key, Func f)
  851. {
  852. Comparator c = toComparator(f);
  853. Object[] values = this.values;
  854. int low = 0, high = size-1;
  855. while (low <= high)
  856. {
  857. int probe = (low + high) >> 1;
  858. int cmp = c.compare(values[probe], key);
  859. if (cmp < 0)
  860. low = probe + 1;
  861. else if (cmp > 0)
  862. high = probe - 1;
  863. else
  864. return probe;
  865. }
  866. return -(low + 1);
  867. }
  868. public final long binaryFind(Func f)
  869. {
  870. Object[] values = this.values;
  871. int low = 0, high = size-1;
  872. boolean oneArg = f.arity() == 1;
  873. while (low <= high)
  874. {
  875. int probe = (low + high) >> 1;
  876. Object val = values[probe];
  877. Object res = oneArg ? f.call(val) : f.call(val, Long.valueOf(probe));
  878. long cmp = ((Long)res).longValue();
  879. if (cmp > 0)
  880. low = probe + 1;
  881. else if (cmp < 0)
  882. high = probe - 1;
  883. else
  884. return probe;
  885. }
  886. return -(low + 1);
  887. }
  888. public final List reverse()
  889. {
  890. modify();
  891. Object[] values = this.values;
  892. int size = this.size;
  893. int mid = size/2;
  894. for (int i=0; i<mid; ++i)
  895. {
  896. Object a = values[i];
  897. Object b = values[size-i-1];
  898. values[i] = b;
  899. values[size-i-1] = a;
  900. }
  901. return this;
  902. }
  903. public final List swap(long a, long b)
  904. {
  905. // modify in set()
  906. Object temp = get(a);
  907. set(a, get(b));
  908. set(b, temp);
  909. return this;
  910. }
  911. public final List moveTo(Object item, long toIndex)
  912. {
  913. modify();
  914. Long curIndex = index(item);
  915. if (curIndex == null) return this;
  916. if (curIndex == toIndex) return this;
  917. removeAt(curIndex);
  918. if (toIndex == -1) return add(item);
  919. if (toIndex < 0) ++toIndex;
  920. return insert(toIndex, item);
  921. }
  922. public final List flatten()
  923. {
  924. List acc = new List(Sys.ObjType.toNullable(), size*2);
  925. doFlatten(acc);
  926. return acc;
  927. }
  928. private void doFlatten(List acc)
  929. {
  930. for (int i=0; i<size; ++i)
  931. {
  932. Object item = values[i];
  933. if (item instanceof List)
  934. ((List)item).doFlatten(acc);
  935. else
  936. acc.add(item);
  937. }
  938. }
  939. public final Object random()
  940. {
  941. if (size == 0) return null;
  942. int i = FanInt.random.nextInt();
  943. if (i < 0) i = -i;
  944. return values[i % size];
  945. }
  946. public final List shuffle()
  947. {
  948. modify();
  949. for (int i=0; i<size; ++i)
  950. {
  951. int randi = FanInt.random.nextInt(i+1);
  952. Object temp = values[i];
  953. values[i] = values[randi];
  954. values[randi] = temp;
  955. }
  956. return this;
  957. }
  958. //////////////////////////////////////////////////////////////////////////
  959. // Conversion
  960. //////////////////////////////////////////////////////////////////////////
  961. public final String join() { return join("", null); }
  962. public final String join(String sep) { return join(sep, null); }
  963. public final String join(String sep, Func f)
  964. {
  965. if (size == 0) return "";
  966. if (size == 1)
  967. {
  968. Object v = values[0];
  969. if (f != null) return (String)f.call(v, 0L);
  970. if (v == null) return "null";
  971. return toStr(v);
  972. }
  973. StringBuilder s = new StringBuilder(32+size*32);
  974. for (int i=0; i<size; ++i)
  975. {
  976. if (i > 0) s.append(sep);
  977. if (f == null)
  978. s.append(values[i]);
  979. else
  980. s.append(f.call(values[i], Long.valueOf(i)));
  981. }
  982. return s.toString();
  983. }
  984. public final String toStr()
  985. {
  986. if (size == 0) return "[,]";
  987. StringBuilder s = new StringBuilder(32+size*32);
  988. s.append("[");
  989. for (int i=0; i<size; ++i)
  990. {
  991. if (i > 0) s.append(", ");
  992. s.append(values[i]);
  993. }
  994. s.append("]");
  995. return s.toString();
  996. }
  997. public final String toCode()
  998. {
  999. StringBuilder s = new StringBuilder(32+size*32);
  1000. s.append(of.signature());
  1001. s.append('[');
  1002. if (size == 0) s.append(',');
  1003. for (int i=0; i<size; ++i)
  1004. {
  1005. if (i > 0) s.append(',').append(' ');
  1006. s.append(FanObj.trap(values[i], "toCode", null));
  1007. }
  1008. s.append(']');
  1009. return s.toString();
  1010. }
  1011. public final void encode(ObjEncoder out)
  1012. {
  1013. // route back to obj encoder
  1014. out.writeList(this);
  1015. }
  1016. //////////////////////////////////////////////////////////////////////////
  1017. // Runtime Utils
  1018. //////////////////////////////////////////////////////////////////////////
  1019. public final int sz()
  1020. {
  1021. return size;
  1022. }
  1023. public final Object get(int i)
  1024. {
  1025. try
  1026. {
  1027. if (i >= size) throw IndexErr.make(""+i);
  1028. return values[i];
  1029. }
  1030. catch (ArrayIndexOutOfBoundsException e)
  1031. {
  1032. throw IndexErr.make(""+i);
  1033. }
  1034. }
  1035. private Object[] newArray(int capacity)
  1036. {
  1037. // use backing store of correct array type;
  1038. // handle Java types and bootstrap types directly
  1039. Type t = of.toNonNullable();
  1040. if (t == Sys.ObjType) return new Object[capacity];
  1041. if (t == Sys.StrType) return new String[capacity];
  1042. if (t == Sys.IntType) return new Long[capacity];
  1043. if (t == Sys.BoolType) return new Boolean[capacity];
  1044. if (t == Sys.FloatType) return new Double[capacity];
  1045. if (t == Sys.DecimalType) return new BigDecimal[capacity];
  1046. if (t == Sys.NumType) return new Number[capacity];
  1047. if (t == Sys.SlotType) return new Slot[capacity];
  1048. if (t == Sys.FieldType) return new Field[capacity];
  1049. if (t == Sys.MethodType) return new Method[capacity];
  1050. if (t == Sys.ParamType) return new Param[capacity];
  1051. return (Object[])Array.newInstance(of.toClass(), capacity);
  1052. }
  1053. /**
  1054. * Get this list as an array of the specified class. The resulting
  1055. * array could potentially be a direct reference to the backing array.
  1056. */
  1057. public final Object[] asArray(Class of)
  1058. {
  1059. // short circuit if values is already correct array type
  1060. if (size == values.length && of == values.getClass().getComponentType())
  1061. return values;
  1062. // make a safe copy of correct length and type
  1063. Object[] r = (Object[]) Array.newInstance(of, size);
  1064. System.arraycopy(values, 0, r, 0, size);
  1065. return r;
  1066. }
  1067. public final Object[] toArray()
  1068. {
  1069. if (values.length == size) return values;
  1070. Object[] r = newArray(size);
  1071. System.arraycopy(values, 0, r, 0, size);
  1072. return r;
  1073. }
  1074. public final Object[] toArray(Object[] a)
  1075. {
  1076. try
  1077. {
  1078. System.arraycopy(values, 0, a, 0, size);
  1079. return a;
  1080. }
  1081. catch (ArrayIndexOutOfBoundsException e)
  1082. {
  1083. throw IndexErr.make();
  1084. }
  1085. }
  1086. public final Object[] toArray(Object[] a, int start, int len)
  1087. {
  1088. try
  1089. {
  1090. System.arraycopy(values, start, a, 0, len);
  1091. return a;
  1092. }
  1093. catch (ArrayIndexOutOfBoundsException e)
  1094. {
  1095. throw IndexErr.make();
  1096. }
  1097. }
  1098. public final Object[] copyInto(Object[] a, int off, int len)
  1099. {
  1100. try
  1101. {
  1102. System.arraycopy(values, 0, a, off, len);
  1103. return a;
  1104. }
  1105. catch (ArrayIndexOutOfBoundsException e)
  1106. {
  1107. throw IndexErr.make();
  1108. }
  1109. }
  1110. public final String[] toStrings()
  1111. {
  1112. String[] a = new String[size];
  1113. for (int i=0; i<size; ++i)
  1114. {
  1115. Object obj = get(i);
  1116. if (obj == null) a[i] = "null";
  1117. else a[i] = toStr(obj);
  1118. }
  1119. return a;
  1120. }
  1121. public final int[] toInts()
  1122. {
  1123. int[] a = new int[size];
  1124. for (int i=0; i<size; ++i) a[i] = ((Long)get(i)).intValue();
  1125. return a;
  1126. }
  1127. //////////////////////////////////////////////////////////////////////////
  1128. // Comparators
  1129. //////////////////////////////////////////////////////////////////////////
  1130. static Comparator toComparator(final Func f)
  1131. {
  1132. if (f == null) return defaultComparator;
  1133. return new Comparator()
  1134. {
  1135. public int compare(Object a, Object b) { return ((Long)f.call(a, b)).intValue(); }
  1136. };
  1137. }
  1138. static final Comparator defaultComparator = new Comparator()
  1139. {
  1140. public int compare(Object a, Object b) { return (int)OpUtil.compare(a, b); }
  1141. };
  1142. static Comparator toReverseComparator(final Func f)
  1143. {
  1144. if (f == null) return defaultReverseComparator;
  1145. return new Comparator()
  1146. {
  1147. public int compare(Object a, Object b) { return ((Long)f.call(b, a)).intValue(); }
  1148. };
  1149. }
  1150. static final Comparator defaultReverseComparator = new Comparator()
  1151. {
  1152. public int compare(Object a, Object b) { return (int)OpUtil.compare(b, a); }
  1153. };
  1154. //////////////////////////////////////////////////////////////////////////
  1155. // Readonly
  1156. //////////////////////////////////////////////////////////////////////////
  1157. public final boolean isRW()
  1158. {
  1159. return !readonly;
  1160. }
  1161. public final boolean isRO()
  1162. {
  1163. return readonly;
  1164. }
  1165. public final List rw()
  1166. {
  1167. if (!readonly) return this;
  1168. Object[] temp = newArray(size);
  1169. System.arraycopy(values, 0, temp, 0, size);
  1170. List rw = new List(of);
  1171. rw.values = temp;
  1172. rw.size = size;
  1173. rw.readonly = false;
  1174. rw.readonlyList = this;
  1175. return rw;
  1176. }
  1177. public final List ro()
  1178. {
  1179. if (readonly) return this;
  1180. if (readonlyList == null)
  1181. {
  1182. List ro = new List(of);
  1183. ro.values = values;
  1184. ro.size = size;
  1185. ro.readonly = true;
  1186. readonlyList = ro;
  1187. }
  1188. return readonlyList;
  1189. }
  1190. public final boolean isImmutable()
  1191. {
  1192. return immutable;
  1193. }
  1194. public final Object toImmutable()
  1195. {
  1196. if (immutable) return this;
  1197. // make safe copy
  1198. Object[] temp = newArray(size);
  1199. for (int i=0; i<size; ++i)
  1200. {
  1201. Object item = values[i];
  1202. if (item != null)
  1203. {
  1204. if (item instanceof List)
  1205. item = ((List)item).toImmutable();
  1206. else if (item instanceof Map)
  1207. item = ((Map)item).toImmutable();
  1208. else if (!isImmutable(item))
  1209. throw NotImmutableErr.make("Item [" + i + "] not immutable " + typeof(item));
  1210. }
  1211. temp[i] = item;
  1212. }
  1213. // return new immutable list
  1214. List ro = new List(of, temp);
  1215. ro.readonly = true;
  1216. ro.immutable = true;
  1217. return ro;
  1218. }
  1219. private void modify()
  1220. {
  1221. // if readonly then throw readonly exception
  1222. if (readonly)
  1223. throw ReadonlyErr.make("List is readonly");
  1224. // if we have a cached readonlyList, then detach
  1225. // it so it remains immutable
  1226. if (readonlyList != null)
  1227. {
  1228. Object[] temp = newArray(size);
  1229. System.arraycopy(values, 0, temp, 0, size);
  1230. readonlyList.values = temp;
  1231. readonlyList = null;
  1232. }
  1233. }
  1234. //////////////////////////////////////////////////////////////////////////
  1235. // Fields
  1236. //////////////////////////////////////////////////////////////////////////
  1237. private static final Object[] empty = new Object[0];
  1238. private Type of;
  1239. private Object[] values;
  1240. private int size;
  1241. private boolean readonly;
  1242. private boolean immutable;
  1243. private List readonlyList;
  1244. }