PageRenderTime 56ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/sys/dotnet/fan/sys/List.cs

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