PageRenderTime 63ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://code.google.com/p/fan/
Java | 1349 lines | 1135 code | 136 blank | 78 comment | 306 complexity | ddbdeb7575861c4c95c07fb0b2fd8e36 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 indexSame(Object value) { return indexSame(value, 0L); }
  230. public final Long indexSame(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. for (int i=start; i<size; ++i)
  239. if (value == values[i])
  240. return Long.valueOf(i);
  241. return null;
  242. }
  243. catch (ArrayIndexOutOfBoundsException e)
  244. {
  245. throw IndexErr.make(off);
  246. }
  247. }
  248. public final Object first()
  249. {
  250. if (size == 0) return null;
  251. return values[0];
  252. }
  253. public final Object last()
  254. {
  255. if (size == 0) return null;
  256. return values[size-1];
  257. }
  258. public final List dup()
  259. {
  260. Object[] dup = newArray(size);
  261. System.arraycopy(values, 0, dup, 0, size);
  262. return new List(of, dup);
  263. }
  264. public final long hash()
  265. {
  266. long hash = 33;
  267. for (int i=0; i<size; ++i)
  268. {
  269. Object obj = values[i];
  270. hash = (31*hash) + (obj == null ? 0 : hash(obj));
  271. }
  272. return hash;
  273. }
  274. public final boolean equals(Object that)
  275. {
  276. if (that instanceof List)
  277. {
  278. List x = (List)that;
  279. if (!of.equals(x.of)) return false;
  280. if (size != x.size) return false;
  281. for (int i=0; i<size; ++i)
  282. if (!OpUtil.compareEQ(values[i], x.values[i])) return false;
  283. return true;
  284. }
  285. return false;
  286. }
  287. //////////////////////////////////////////////////////////////////////////
  288. // Modification
  289. //////////////////////////////////////////////////////////////////////////
  290. public final List set(long index, Object value)
  291. {
  292. modify();
  293. try
  294. {
  295. int i = (int)index;
  296. if (i < 0) i = size + i;
  297. if (i >= size) throw IndexErr.make(index);
  298. values[i] = value;
  299. return this;
  300. }
  301. catch (ArrayIndexOutOfBoundsException e)
  302. {
  303. throw IndexErr.make(index);
  304. }
  305. catch (ArrayStoreException e)
  306. {
  307. throw CastErr.make("Setting '" + FanObj.typeof(value) + "' into '" + of + "[]'");
  308. }
  309. }
  310. public final List add(Object value)
  311. {
  312. // modify in insert(int, Obj)
  313. return insert(size, value);
  314. }
  315. public final List addAll(List list)
  316. {
  317. // modify in insertAll(int, List)
  318. return insertAll(size, list);
  319. }
  320. public final List insert(long index, Object value)
  321. {
  322. // modify in insert(int, Obj)
  323. int i = (int)index;
  324. if (i < 0) i = size + i;
  325. if (i > size) throw IndexErr.make(index);
  326. return insert(i, value);
  327. }
  328. private List insert(int i, Object value)
  329. {
  330. try
  331. {
  332. modify();
  333. if (values.length <= size)
  334. grow(size+1);
  335. if (i < size)
  336. System.arraycopy(values, i, values, i+1, size-i);
  337. values[i] = value;
  338. size++;
  339. return this;
  340. }
  341. catch (ArrayStoreException e)
  342. {
  343. throw CastErr.make("Adding '" + FanObj.typeof(value) + "' into '" + of + "[]'");
  344. }
  345. }
  346. public final List insertAll(long index, List list)
  347. {
  348. // modify in insertAll(int, List)
  349. int i = (int)index;
  350. if (i < 0) i = size + i;
  351. if (i > size || i < 0) throw IndexErr.make(index);
  352. return insertAll(i, list);
  353. }
  354. private List insertAll(int i, List list)
  355. {
  356. modify();
  357. if (list.size == 0) return this;
  358. if (values.length < size+list.size)
  359. grow(size+list.size);
  360. if (i < size)
  361. System.arraycopy(values, i, values, i+list.size, size-i);
  362. System.arraycopy(list.values, 0, values, i, list.size);
  363. size+=list.size;
  364. return this;
  365. }
  366. public final Object remove(Object val)
  367. {
  368. // modify in removeAt(Int)
  369. Long index = index(val);
  370. if (index == null) return null;
  371. return removeAt(index);
  372. }
  373. public final Object removeSame(Object val)
  374. {
  375. // modify in removeAt(Int)
  376. Long index = indexSame(val);
  377. if (index == null) return null;
  378. return removeAt(index);
  379. }
  380. public final Object removeAt(long index)
  381. {
  382. modify();
  383. int i = (int)index;
  384. if (i < 0) i = size + i;
  385. if (i >= size) throw IndexErr.make(index);
  386. Object old = values[i];
  387. if (i < size-1)
  388. System.arraycopy(values, i+1, values, i, size-i-1);
  389. size--;
  390. return old;
  391. }
  392. public final List removeRange(Range r)
  393. {
  394. modify();
  395. int s = r.startIndex(size);
  396. int e = r.endIndex(size);
  397. int n = e - s + 1;
  398. if (n < 0) throw IndexErr.make(r);
  399. int shift = size-s-n;
  400. if (shift > 0) System.arraycopy(values, s+n, values, s, shift);
  401. size -= n;
  402. for (int i=size; i<size+n; ++i) values[i] = null;
  403. return this;
  404. }
  405. public final List removeAll(List toRemove)
  406. {
  407. // optimize special cases
  408. modify();
  409. if (toRemove.sz() == 0) { return this; }
  410. if (toRemove.sz() == 1) { remove(toRemove.get(0)); return this; }
  411. // rebuild the backing store array, implementation
  412. // assumes that this list is bigger than toRemove list
  413. Object[] newValues = newArray(values.length);
  414. int newSize = 0;
  415. for (int i=0; i<size; ++i)
  416. {
  417. Object val = values[i];
  418. if (!toRemove.contains(val)) newValues[newSize++] = val;
  419. }
  420. this.values = newValues;
  421. this.size = newSize;
  422. return this;
  423. }
  424. private void grow(int desiredSize)
  425. {
  426. int desired = (int)desiredSize;
  427. if (desired < 1) throw Err.make("desired " + desired + " < 1");
  428. int newSize = Math.max(desired, size*2);
  429. if (newSize < 10) newSize = 10;
  430. Object[] temp = newArray(newSize);
  431. System.arraycopy(values, 0, temp, 0, size);
  432. values = temp;
  433. }
  434. public final List trim()
  435. {
  436. modify();
  437. if (size == 0)
  438. {
  439. values = empty;
  440. }
  441. else if (values.length != size)
  442. {
  443. Object[] temp = newArray(size);
  444. System.arraycopy(values, 0, temp, 0, size);
  445. values = temp;
  446. }
  447. return this;
  448. }
  449. public final List clear()
  450. {
  451. modify();
  452. for (int i=0; i<size; ++i)
  453. values[i] = null;
  454. size = 0;
  455. return this;
  456. }
  457. public final List fill(Object val, long times)
  458. {
  459. modify();
  460. int t = (int)times;
  461. if (values.length < size+t) grow(size+t);
  462. for (int i=0; i<t; ++i) values[size+i] = val;
  463. size += t;
  464. return this;
  465. }
  466. //////////////////////////////////////////////////////////////////////////
  467. // Stack
  468. //////////////////////////////////////////////////////////////////////////
  469. public final Object peek()
  470. {
  471. if (size == 0) return null;
  472. return values[size-1];
  473. }
  474. public final Object pop()
  475. {
  476. // modify in removeAt()
  477. if (size == 0) return null;
  478. return removeAt(-1);
  479. }
  480. public final List push(Object obj)
  481. {
  482. // modify in add()
  483. return add(obj);
  484. }
  485. //////////////////////////////////////////////////////////////////////////
  486. // Iterators
  487. //////////////////////////////////////////////////////////////////////////
  488. public final void each(Func f)
  489. {
  490. if (f.arity() == 1)
  491. {
  492. for (int i=0; i<size; ++i)
  493. f.call(values[i]);
  494. }
  495. else
  496. {
  497. for (int i=0; i<size; ++i)
  498. f.call(values[i], Long.valueOf(i));
  499. }
  500. }
  501. public final void eachr(Func f)
  502. {
  503. if (f.arity() == 1)
  504. {
  505. for (int i=size-1; i>=0; --i)
  506. f.call(values[i]);
  507. }
  508. else
  509. {
  510. for (int i=size-1; i>=0; --i)
  511. f.call(values[i], Long.valueOf(i));
  512. }
  513. }
  514. public final void eachRange(Range r, Func f)
  515. {
  516. int s = r.startIndex(size);
  517. int e = r.endIndex(size);
  518. int n = e - s + 1;
  519. if (n < 0) throw IndexErr.make(r);
  520. if (f.arity() == 1)
  521. {
  522. for (int i=s; i<=e; ++i)
  523. f.call(values[i]);
  524. }
  525. else
  526. {
  527. for (int i=s; i<=e; ++i)
  528. f.call(values[i], Long.valueOf(i));
  529. }
  530. }
  531. public final Object eachWhile(Func f)
  532. {
  533. if (f.arity() == 1)
  534. {
  535. for (int i=0; i<size; ++i)
  536. {
  537. Object r = f.call(values[i]);
  538. if (r != null) return r;
  539. }
  540. }
  541. else
  542. {
  543. for (int i=0; i<size; ++i)
  544. {
  545. Object r = f.call(values[i], Long.valueOf(i));
  546. if (r != null) return r;
  547. }
  548. }
  549. return null;
  550. }
  551. public final Object eachrWhile(Func f)
  552. {
  553. if (f.arity() == 1)
  554. {
  555. for (int i=size-1; i>=0; --i)
  556. {
  557. Object r = f.call(values[i]);
  558. if (r != null) return r;
  559. }
  560. }
  561. else
  562. {
  563. for (int i=size-1; i>=0; --i)
  564. {
  565. Object r = f.call(values[i], Long.valueOf(i));
  566. if (r != null) return r;
  567. }
  568. }
  569. return null;
  570. }
  571. public final Object find(Func f)
  572. {
  573. if (f.arity() == 1)
  574. {
  575. for (int i=0; i<size; ++i)
  576. if (f.callBool(values[i]))
  577. return values[i];
  578. }
  579. else
  580. {
  581. for (int i=0; i<size; ++i)
  582. if (f.callBool(values[i], Long.valueOf(i)))
  583. return values[i];
  584. }
  585. return null;
  586. }
  587. public final Long findIndex(Func f)
  588. {
  589. if (f.arity() == 1)
  590. {
  591. for (int i=0; i<size; ++i)
  592. {
  593. if (f.callBool(values[i]))
  594. return Long.valueOf(i);
  595. }
  596. }
  597. else
  598. {
  599. for (int i=0; i<size; ++i)
  600. {
  601. Long pos = Long.valueOf(i);
  602. if (f.callBool(values[i], pos))
  603. return pos;
  604. }
  605. }
  606. return null;
  607. }
  608. public final List findAll(Func f)
  609. {
  610. List acc = new List(of, size);
  611. if (f.arity() == 1)
  612. {
  613. for (int i=0; i<size; ++i)
  614. if (f.callBool(values[i]))
  615. acc.add(values[i]);
  616. }
  617. else
  618. {
  619. for (int i=0; i<size; ++i)
  620. if (f.callBool(values[i], Long.valueOf(i)))
  621. acc.add(values[i]);
  622. }
  623. return acc;
  624. }
  625. public final List findType(Type t)
  626. {
  627. List acc = new List(t, size);
  628. for (int i=0; i<size; ++i)
  629. {
  630. Object item = values[i];
  631. if (item != null && typeof(item).is(t))
  632. acc.add(item);
  633. }
  634. return acc;
  635. }
  636. public final List exclude(Func f)
  637. {
  638. List acc = new List(of, size);
  639. if (f.arity() == 1)
  640. {
  641. for (int i=0; i<size; ++i)
  642. if (!f.callBool(values[i]))
  643. acc.add(values[i]);
  644. }
  645. else
  646. {
  647. for (int i=0; i<size; ++i)
  648. if (!f.callBool(values[i], Long.valueOf(i)))
  649. acc.add(values[i]);
  650. }
  651. return acc;
  652. }
  653. public final boolean any(Func f)
  654. {
  655. if (f.arity() == 1)
  656. {
  657. for (int i=0; i<size; ++i)
  658. if (f.callBool(values[i]))
  659. return true;
  660. }
  661. else
  662. {
  663. for (int i=0; i<size; ++i)
  664. if (f.callBool(values[i], Long.valueOf(i)))
  665. return true;
  666. }
  667. return false;
  668. }
  669. public final boolean all(Func f)
  670. {
  671. if (f.arity() == 1)
  672. {
  673. for (int i=0; i<size; ++i)
  674. if (!f.callBool(values[i]))
  675. return false;
  676. }
  677. else
  678. {
  679. for (int i=0; i<size; ++i)
  680. if (!f.callBool(values[i], Long.valueOf(i)))
  681. return false;
  682. }
  683. return true;
  684. }
  685. public final Object reduce(Object reduction, Func f)
  686. {
  687. if (f.arity() == 1)
  688. {
  689. for (int i=0; i<size; ++i)
  690. reduction = f.call(reduction, values[i]);
  691. }
  692. else
  693. {
  694. for (int i=0; i<size; ++i)
  695. reduction = f.call(reduction, values[i], Long.valueOf(i));
  696. }
  697. return reduction;
  698. }
  699. public final List map(Func f)
  700. {
  701. Type r = f.returns();
  702. if (r == Sys.VoidType) r = Sys.ObjType.toNullable();
  703. List acc = new List(r, (int)size());
  704. if (f.arity() == 1)
  705. {
  706. for (int i=0; i<size; ++i)
  707. acc.add(f.call(values[i]));
  708. }
  709. else
  710. {
  711. for (int i=0; i<size; ++i)
  712. acc.add(f.call(values[i], Long.valueOf(i)));
  713. }
  714. return acc;
  715. }
  716. public final Object max() { return max(null); }
  717. public final Object max(Func f)
  718. {
  719. if (size == 0) return null;
  720. Comparator c = toComparator(f);
  721. Object max = values[0];
  722. for (int i=1; i<size; ++i)
  723. if (c.compare(values[i], max) > 0)
  724. max = values[i];
  725. return max;
  726. }
  727. public final Object min() { return min(null); }
  728. public final Object min(Func f)
  729. {
  730. if (size == 0) return null;
  731. Comparator c = toComparator(f);
  732. Object min = values[0];
  733. for (int i=1; i<size; ++i)
  734. if (c.compare(values[i], min) < 0)
  735. min = values[i];
  736. return min;
  737. }
  738. public final List unique()
  739. {
  740. if (size <= 1) return dup();
  741. HashMap dups = new HashMap(size*3);
  742. List acc = new List(of, size);
  743. for (int i=0; i<size; ++i)
  744. {
  745. Object v = values[i];
  746. if (dups.get(v) == null)
  747. {
  748. dups.put(v, this);
  749. acc.add(v);
  750. }
  751. }
  752. return acc;
  753. }
  754. public final List union(List that)
  755. {
  756. int capacity = size + that.size;
  757. HashMap dups = new HashMap(capacity*3);
  758. List acc = new List(of, capacity);
  759. // first me
  760. for (int i=0; i<size; ++i)
  761. {
  762. Object v = values[i];
  763. if (dups.get(v) == null)
  764. {
  765. dups.put(v, this);
  766. acc.add(v);
  767. }
  768. }
  769. // then him
  770. for (int i=0; i<that.size; ++i)
  771. {
  772. Object v = that.values[i];
  773. if (dups.get(v) == null)
  774. {
  775. dups.put(v, this);
  776. acc.add(v);
  777. }
  778. }
  779. return acc;
  780. }
  781. public final List intersection(List that)
  782. {
  783. // put other list into map
  784. HashMap dups = new HashMap(that.size*3);
  785. for (int i=0; i<that.size; ++i)
  786. dups.put(that.values[i], this);
  787. // now walk this list and accumulate
  788. // everything found in the dups map
  789. List acc = new List(of, size);
  790. for (int i=0; i<size; ++i)
  791. {
  792. Object v = values[i];
  793. if (dups.get(v) != null)
  794. {
  795. acc.add(v);
  796. dups.remove(v);
  797. }
  798. }
  799. return acc;
  800. }
  801. //////////////////////////////////////////////////////////////////////////
  802. // Utils
  803. //////////////////////////////////////////////////////////////////////////
  804. public final List sort() { return sort(null); }
  805. public final List sort(final Func f)
  806. {
  807. modify();
  808. Arrays.sort(values, 0, size, toComparator(f));
  809. return this;
  810. }
  811. public final List sortr() { return sortr(null); }
  812. public final List sortr(final Func f)
  813. {
  814. modify();
  815. Arrays.sort(values, 0, size, toReverseComparator(f));
  816. return this;
  817. }
  818. public final long binarySearch(Object key) { return binarySearch(key, null); }
  819. public final long binarySearch(Object key, Func f)
  820. {
  821. Comparator c = toComparator(f);
  822. Object[] values = this.values;
  823. int low = 0, high = size-1;
  824. while (low <= high)
  825. {
  826. int probe = (low + high) >> 1;
  827. int cmp = c.compare(values[probe], key);
  828. if (cmp < 0)
  829. low = probe + 1;
  830. else if (cmp > 0)
  831. high = probe - 1;
  832. else
  833. return probe;
  834. }
  835. return -(low + 1);
  836. }
  837. public final long binaryFind(Func f)
  838. {
  839. Object[] values = this.values;
  840. int low = 0, high = size-1;
  841. boolean oneArg = f.arity() == 1;
  842. while (low <= high)
  843. {
  844. int probe = (low + high) >> 1;
  845. Object val = values[probe];
  846. Object res = oneArg ? f.call(val) : f.call(val, Long.valueOf(probe));
  847. long cmp = ((Long)res).longValue();
  848. if (cmp > 0)
  849. low = probe + 1;
  850. else if (cmp < 0)
  851. high = probe - 1;
  852. else
  853. return probe;
  854. }
  855. return -(low + 1);
  856. }
  857. public final List reverse()
  858. {
  859. modify();
  860. Object[] values = this.values;
  861. int size = this.size;
  862. int mid = size/2;
  863. for (int i=0; i<mid; ++i)
  864. {
  865. Object a = values[i];
  866. Object b = values[size-i-1];
  867. values[i] = b;
  868. values[size-i-1] = a;
  869. }
  870. return this;
  871. }
  872. public final List swap(long a, long b)
  873. {
  874. // modify in set()
  875. Object temp = get(a);
  876. set(a, get(b));
  877. set(b, temp);
  878. return this;
  879. }
  880. public final List moveTo(Object item, long toIndex)
  881. {
  882. modify();
  883. Long curIndex = index(item);
  884. if (curIndex == null) return this;
  885. if (curIndex == toIndex) return this;
  886. removeAt(curIndex);
  887. if (toIndex == -1) return add(item);
  888. if (toIndex < 0) ++toIndex;
  889. return insert(toIndex, item);
  890. }
  891. public final List flatten()
  892. {
  893. List acc = new List(Sys.ObjType.toNullable(), size*2);
  894. doFlatten(acc);
  895. return acc;
  896. }
  897. private void doFlatten(List acc)
  898. {
  899. for (int i=0; i<size; ++i)
  900. {
  901. Object item = values[i];
  902. if (item instanceof List)
  903. ((List)item).doFlatten(acc);
  904. else
  905. acc.add(item);
  906. }
  907. }
  908. public final Object random()
  909. {
  910. if (size == 0) return null;
  911. int i = FanInt.random.nextInt();
  912. if (i < 0) i = -i;
  913. return values[i % size];
  914. }
  915. public final List shuffle()
  916. {
  917. modify();
  918. for (int i=0; i<size; ++i)
  919. {
  920. int randi = FanInt.random.nextInt(i+1);
  921. Object temp = values[i];
  922. values[i] = values[randi];
  923. values[randi] = temp;
  924. }
  925. return this;
  926. }
  927. //////////////////////////////////////////////////////////////////////////
  928. // Conversion
  929. //////////////////////////////////////////////////////////////////////////
  930. public final String join() { return join("", null); }
  931. public final String join(String sep) { return join(sep, null); }
  932. public final String join(String sep, Func f)
  933. {
  934. if (size == 0) return "";
  935. if (size == 1)
  936. {
  937. Object v = values[0];
  938. if (f != null) return (String)f.call(v, 0L);
  939. if (v == null) return "null";
  940. return toStr(v);
  941. }
  942. StringBuilder s = new StringBuilder(32+size*32);
  943. for (int i=0; i<size; ++i)
  944. {
  945. if (i > 0) s.append(sep);
  946. if (f == null)
  947. s.append(values[i]);
  948. else
  949. s.append(f.call(values[i], Long.valueOf(i)));
  950. }
  951. return s.toString();
  952. }
  953. public final String toStr()
  954. {
  955. if (size == 0) return "[,]";
  956. StringBuilder s = new StringBuilder(32+size*32);
  957. s.append("[");
  958. for (int i=0; i<size; ++i)
  959. {
  960. if (i > 0) s.append(", ");
  961. s.append(values[i]);
  962. }
  963. s.append("]");
  964. return s.toString();
  965. }
  966. public final String toCode()
  967. {
  968. StringBuilder s = new StringBuilder(32+size*32);
  969. s.append(of.signature());
  970. s.append('[');
  971. if (size == 0) s.append(',');
  972. for (int i=0; i<size; ++i)
  973. {
  974. if (i > 0) s.append(',').append(' ');
  975. s.append(FanObj.trap(values[i], "toCode", null));
  976. }
  977. s.append(']');
  978. return s.toString();
  979. }
  980. public final void encode(ObjEncoder out)
  981. {
  982. // route back to obj encoder
  983. out.writeList(this);
  984. }
  985. //////////////////////////////////////////////////////////////////////////
  986. // Runtime Utils
  987. //////////////////////////////////////////////////////////////////////////
  988. public final int sz()
  989. {
  990. return size;
  991. }
  992. public final Object get(int i)
  993. {
  994. try
  995. {
  996. if (i >= size) throw IndexErr.make(""+i);
  997. return values[i];
  998. }
  999. catch (ArrayIndexOutOfBoundsException e)
  1000. {
  1001. throw IndexErr.make(""+i);
  1002. }
  1003. }
  1004. private Object[] newArray(int capacity)
  1005. {
  1006. // use backing store of correct array type;
  1007. // handle Java types and bootstrap types directly
  1008. Type t = of.toNonNullable();
  1009. if (t == Sys.ObjType) return new Object[capacity];
  1010. if (t == Sys.StrType) return new String[capacity];
  1011. if (t == Sys.IntType) return new Long[capacity];
  1012. if (t == Sys.BoolType) return new Boolean[capacity];
  1013. if (t == Sys.FloatType) return new Double[capacity];
  1014. if (t == Sys.DecimalType) return new BigDecimal[capacity];
  1015. if (t == Sys.NumType) return new Number[capacity];
  1016. if (t == Sys.SlotType) return new Slot[capacity];
  1017. if (t == Sys.FieldType) return new Field[capacity];
  1018. if (t == Sys.MethodType) return new Method[capacity];
  1019. if (t == Sys.ParamType) return new Param[capacity];
  1020. return (Object[])Array.newInstance(of.toClass(), capacity);
  1021. }
  1022. /**
  1023. * Get this list as an array of the specified class. The resulting
  1024. * array could potentially be a direct reference to the backing array.
  1025. */
  1026. public final Object[] asArray(Class of)
  1027. {
  1028. // short circuit if values is already correct array type
  1029. if (size == values.length && of == values.getClass().getComponentType())
  1030. return values;
  1031. // make a safe copy of correct length and type
  1032. Object[] r = (Object[]) Array.newInstance(of, size);
  1033. System.arraycopy(values, 0, r, 0, size);
  1034. return r;
  1035. }
  1036. public final Object[] toArray()
  1037. {
  1038. if (values.length == size) return values;
  1039. Object[] r = newArray(size);
  1040. System.arraycopy(values, 0, r, 0, size);
  1041. return r;
  1042. }
  1043. public final Object[] toArray(Object[] a)
  1044. {
  1045. try
  1046. {
  1047. System.arraycopy(values, 0, a, 0, size);
  1048. return a;
  1049. }
  1050. catch (ArrayIndexOutOfBoundsException e)
  1051. {
  1052. throw IndexErr.make();
  1053. }
  1054. }
  1055. public final Object[] toArray(Object[] a, int start, int len)
  1056. {
  1057. try
  1058. {
  1059. System.arraycopy(values, start, a, 0, len);
  1060. return a;
  1061. }
  1062. catch (ArrayIndexOutOfBoundsException e)
  1063. {
  1064. throw IndexErr.make();
  1065. }
  1066. }
  1067. public final Object[] copyInto(Object[] a, int off, int len)
  1068. {
  1069. try
  1070. {
  1071. System.arraycopy(values, 0, a, off, len);
  1072. return a;
  1073. }
  1074. catch (ArrayIndexOutOfBoundsException e)
  1075. {
  1076. throw IndexErr.make();
  1077. }
  1078. }
  1079. public final String[] toStrings()
  1080. {
  1081. String[] a = new String[size];
  1082. for (int i=0; i<size; ++i)
  1083. {
  1084. Object obj = get(i);
  1085. if (obj == null) a[i] = "null";
  1086. else a[i] = toStr(obj);
  1087. }
  1088. return a;
  1089. }
  1090. public final int[] toInts()
  1091. {
  1092. int[] a = new int[size];
  1093. for (int i=0; i<size; ++i) a[i] = ((Long)get(i)).intValue();
  1094. return a;
  1095. }
  1096. //////////////////////////////////////////////////////////////////////////
  1097. // Comparators
  1098. //////////////////////////////////////////////////////////////////////////
  1099. static Comparator toComparator(final Func f)
  1100. {
  1101. if (f == null) return defaultComparator;
  1102. return new Comparator()
  1103. {
  1104. public int compare(Object a, Object b) { return ((Long)f.call(a, b)).intValue(); }
  1105. };
  1106. }
  1107. static final Comparator defaultComparator = new Comparator()
  1108. {
  1109. public int compare(Object a, Object b) { return (int)OpUtil.compare(a, b); }
  1110. };
  1111. static Comparator toReverseComparator(final Func f)
  1112. {
  1113. if (f == null) return defaultReverseComparator;
  1114. return new Comparator()
  1115. {
  1116. public int compare(Object a, Object b) { return ((Long)f.call(b, a)).intValue(); }
  1117. };
  1118. }
  1119. static final Comparator defaultReverseComparator = new Comparator()
  1120. {
  1121. public int compare(Object a, Object b) { return (int)OpUtil.compare(b, a); }
  1122. };
  1123. //////////////////////////////////////////////////////////////////////////
  1124. // Readonly
  1125. //////////////////////////////////////////////////////////////////////////
  1126. public final boolean isRW()
  1127. {
  1128. return !readonly;
  1129. }
  1130. public final boolean isRO()
  1131. {
  1132. return readonly;
  1133. }
  1134. public final List rw()
  1135. {
  1136. if (!readonly) return this;
  1137. Object[] temp = newArray(size);
  1138. System.arraycopy(values, 0, temp, 0, size);
  1139. List rw = new List(of);
  1140. rw.values = temp;
  1141. rw.size = size;
  1142. rw.readonly = false;
  1143. rw.readonlyList = this;
  1144. return rw;
  1145. }
  1146. public final List ro()
  1147. {
  1148. if (readonly) return this;
  1149. if (readonlyList == null)
  1150. {
  1151. List ro = new List(of);
  1152. ro.values = values;
  1153. ro.size = size;
  1154. ro.readonly = true;
  1155. readonlyList = ro;
  1156. }
  1157. return readonlyList;
  1158. }
  1159. public final boolean isImmutable()
  1160. {
  1161. return immutable;
  1162. }
  1163. public final Object toImmutable()
  1164. {
  1165. if (immutable) return this;
  1166. // make safe copy
  1167. Object[] temp = newArray(size);
  1168. for (int i=0; i<size; ++i)
  1169. {
  1170. Object item = values[i];
  1171. if (item != null)
  1172. {
  1173. if (item instanceof List)
  1174. item = ((List)item).toImmutable();
  1175. else if (item instanceof Map)
  1176. item = ((Map)item).toImmutable();
  1177. else if (!isImmutable(item))
  1178. throw NotImmutableErr.make("Item [" + i + "] not immutable " + typeof(item));
  1179. }
  1180. temp[i] = item;
  1181. }
  1182. // return new immutable list
  1183. List ro = new List(of, temp);
  1184. ro.readonly = true;
  1185. ro.immutable = true;
  1186. return ro;
  1187. }
  1188. private void modify()
  1189. {
  1190. // if readonly then throw readonly exception
  1191. if (readonly)
  1192. throw ReadonlyErr.make("List is readonly");
  1193. // if we have a cached readonlyList, then detach
  1194. // it so it remains immutable
  1195. if (readonlyList != null)
  1196. {
  1197. Object[] temp = newArray(size);
  1198. System.arraycopy(values, 0, temp, 0, size);
  1199. readonlyList.values = temp;
  1200. readonlyList = null;
  1201. }
  1202. }
  1203. //////////////////////////////////////////////////////////////////////////
  1204. // Fields
  1205. //////////////////////////////////////////////////////////////////////////
  1206. private static final Object[] empty = new Object[0];
  1207. private Type of;
  1208. private Object[] values;
  1209. private int size;
  1210. private boolean readonly;
  1211. private boolean immutable;
  1212. private List readonlyList;
  1213. }