PageRenderTime 53ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

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

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