PageRenderTime 36ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Boo.Lang/List.cs

https://github.com/boo/boo-lang
C# | 752 lines | 615 code | 107 blank | 30 comment | 64 complexity | 0a27e141ef4a66a82464112fc9d949b2 MD5 | raw file
Possible License(s): GPL-2.0
  1. #region license
  2. // Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without modification,
  6. // are permitted provided that the following conditions are met:
  7. //
  8. // * Redistributions of source code must retain the above copyright notice,
  9. // this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above copyright notice,
  11. // this list of conditions and the following disclaimer in the documentation
  12. // and/or other materials provided with the distribution.
  13. // * Neither the name of Rodrigo B. de Oliveira nor the names of its
  14. // contributors may be used to endorse or promote products derived from this
  15. // software without specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  18. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  21. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  25. // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. #endregion
  28. namespace Boo.Lang
  29. {
  30. using System;
  31. using System.Collections;
  32. using Boo.Lang.Runtime;
  33. // callable Predicate(item) as bool
  34. //public delegate bool Predicate(object item);
  35. public delegate int Comparer(object lhs, object rhs);
  36. [Serializable]
  37. public class List : List<object>, IList
  38. {
  39. public static string operator%(string format, List rhs)
  40. {
  41. return string.Format(format, rhs.ToArray());
  42. }
  43. public List()
  44. {
  45. }
  46. public List(IEnumerable enumerable) : base(enumerable)
  47. {
  48. }
  49. public List(int initialCapacity) : base(initialCapacity)
  50. {
  51. }
  52. public List(object[] items, bool takeOwnership) : base(items, takeOwnership)
  53. {
  54. }
  55. public object Find(System.Predicate<object> predicate)
  56. {
  57. object found;
  58. return Find(predicate, out found) ? found : null;
  59. }
  60. protected override List<object> NewConcreteList(object[] items, bool takeOwnership)
  61. {
  62. return new List(items, takeOwnership);
  63. }
  64. public Array ToArray(Type targetType)
  65. {
  66. Array target = Array.CreateInstance(targetType, _count);
  67. Array.Copy(_items, 0, target, 0, _count);
  68. return target;
  69. }
  70. }
  71. #if OldList
  72. /// <summary>
  73. /// List.
  74. /// </summary>
  75. [Serializable]
  76. public class List : IList
  77. {
  78. private const int DefaultCapacity = 16;
  79. protected object[] _items;
  80. protected int _count;
  81. public List() : this(DefaultCapacity)
  82. {
  83. }
  84. public List(IEnumerable enumerable) : this()
  85. {
  86. Extend(enumerable);
  87. }
  88. public List(int initialCapacity)
  89. {
  90. if (initialCapacity < 0)
  91. {
  92. throw new ArgumentOutOfRangeException("initialCapacity");
  93. }
  94. _items = new object[initialCapacity];
  95. _count = 0;
  96. }
  97. public List(object[] items, bool takeOwnership)
  98. {
  99. if (null == items)
  100. {
  101. throw new ArgumentNullException("items");
  102. }
  103. if (takeOwnership)
  104. {
  105. _items = items;
  106. }
  107. else
  108. {
  109. _items = (object[])items.Clone();
  110. }
  111. _count = items.Length;
  112. }
  113. public static List operator*(List lhs, int count)
  114. {
  115. return lhs.Multiply(count);
  116. }
  117. public static List operator*(int count, List rhs)
  118. {
  119. return rhs.Multiply(count);
  120. }
  121. public static List operator+(List lhs, IEnumerable rhs)
  122. {
  123. List result = new List(lhs.Count);
  124. result.Extend(lhs);
  125. result.Extend(rhs);
  126. return result;
  127. }
  128. public static string operator%(string format, List rhs)
  129. {
  130. return string.Format(format, rhs.ToArray(typeof(object)));
  131. }
  132. public List Multiply(int count)
  133. {
  134. if (count < 0)
  135. {
  136. throw new ArgumentOutOfRangeException("count");
  137. }
  138. object[] items = new object[_count*count];
  139. for (int i=0; i<count; ++i)
  140. {
  141. Array.Copy(_items, 0, items, i*_count, _count);
  142. }
  143. return new List(items, true);
  144. }
  145. public int Count
  146. {
  147. get
  148. {
  149. return _count;
  150. }
  151. }
  152. public IEnumerator GetEnumerator()
  153. {
  154. return new ListEnumerator(this);
  155. }
  156. public void CopyTo(Array target, int index)
  157. {
  158. Array.Copy(_items, 0, target, index, _count);
  159. }
  160. public bool IsSynchronized
  161. {
  162. get
  163. {
  164. return false;
  165. }
  166. }
  167. public object SyncRoot
  168. {
  169. get
  170. {
  171. return _items;
  172. }
  173. }
  174. public object this[int index]
  175. {
  176. get
  177. {
  178. return _items[CheckIndex(NormalizeIndex(index))];
  179. }
  180. set
  181. {
  182. _items[CheckIndex(NormalizeIndex(index))] = value;
  183. }
  184. }
  185. public List Push(object item)
  186. {
  187. return Add(item);
  188. }
  189. public List Add(object item)
  190. {
  191. EnsureCapacity(_count+1);
  192. _items[_count] = item;
  193. ++_count;
  194. return this;
  195. }
  196. public List AddUnique(object item)
  197. {
  198. if (!Contains(item))
  199. {
  200. Add(item);
  201. }
  202. return this;
  203. }
  204. public List Extend(IEnumerable enumerable)
  205. {
  206. foreach (object item in enumerable)
  207. {
  208. Add(item);
  209. }
  210. return this;
  211. }
  212. public List ExtendUnique(IEnumerable enumerable)
  213. {
  214. foreach (object item in enumerable)
  215. {
  216. AddUnique(item);
  217. }
  218. return this;
  219. }
  220. public List Collect(Predicate condition)
  221. {
  222. if (null == condition)
  223. {
  224. throw new ArgumentNullException("condition");
  225. }
  226. List newList = new List();
  227. InnerCollect(newList, condition);
  228. return newList;
  229. }
  230. public List Collect(List target, Predicate condition)
  231. {
  232. if (null == target)
  233. {
  234. throw new ArgumentNullException("target");
  235. }
  236. if (null == condition)
  237. {
  238. throw new ArgumentNullException("condition");
  239. }
  240. InnerCollect(target, condition);
  241. return target;
  242. }
  243. public Array ToArray(Type targetType)
  244. {
  245. Array target = Array.CreateInstance(targetType, _count);
  246. CopyTo(target, 0);
  247. return target;
  248. }
  249. public object[] ToArray(object[] array)
  250. {
  251. CopyTo(array, 0);
  252. return array;
  253. }
  254. public object[] ToArray()
  255. {
  256. return (object[])ToArray(typeof(object));
  257. }
  258. public List Sort()
  259. {
  260. Array.Sort(_items, 0, _count, BooComparer.Default);
  261. return this;
  262. }
  263. public List Sort(IComparer comparer)
  264. {
  265. Array.Sort(_items, 0, _count, comparer);
  266. return this;
  267. }
  268. private class ComparerImpl : IComparer
  269. {
  270. Comparer _comparer;
  271. public ComparerImpl(Comparer comparer)
  272. {
  273. _comparer = comparer;
  274. }
  275. public int Compare(object lhs, object rhs)
  276. {
  277. return _comparer(lhs, rhs);
  278. }
  279. }
  280. public List Sort(Comparer comparer)
  281. {
  282. if (null == comparer)
  283. {
  284. throw new ArgumentNullException("comparer");
  285. }
  286. return Sort(new ComparerImpl(comparer));
  287. }
  288. override public string ToString()
  289. {
  290. return "[" + Join(", ") + "]";
  291. }
  292. public string Join(string separator)
  293. {
  294. return Builtins.join(this, separator);
  295. }
  296. override public int GetHashCode()
  297. {
  298. int hash = _count;
  299. for (int i=0; i<_count; ++i)
  300. {
  301. object item = _items[i];
  302. if (null != item)
  303. {
  304. hash ^= item.GetHashCode();
  305. }
  306. }
  307. return hash;
  308. }
  309. override public bool Equals(object other)
  310. {
  311. if (other == this) return true;
  312. List rhs = other as List;
  313. if (null == rhs) return false;
  314. if (_count != rhs.Count) return false;
  315. for (int i=0; i<_count; ++i)
  316. {
  317. if (!RuntimeServices.EqualityOperator(_items[i], rhs[i]))
  318. {
  319. return false;
  320. }
  321. }
  322. return true;
  323. }
  324. public void Clear()
  325. {
  326. for (int i=0; i<_count; ++i)
  327. {
  328. _items[i] = null;
  329. }
  330. _count = 0;
  331. }
  332. public List GetRange(int begin)
  333. {
  334. return InnerGetRange(AdjustIndex(NormalizeIndex(begin)), _count);
  335. }
  336. public List GetRange(int begin, int end)
  337. {
  338. return InnerGetRange(
  339. AdjustIndex(NormalizeIndex(begin)),
  340. AdjustIndex(NormalizeIndex(end)));
  341. }
  342. public bool Contains(object item)
  343. {
  344. return -1 != IndexOf(item);
  345. }
  346. public bool Contains(Predicate condition)
  347. {
  348. return -1 != IndexOf(condition);
  349. }
  350. public bool ContainsReference(object item)
  351. {
  352. return -1 != IndexOfReference(item);
  353. }
  354. public object Find(Predicate condition)
  355. {
  356. int index = IndexOf(condition);
  357. if (-1 != index)
  358. {
  359. return _items[index];
  360. }
  361. return null;
  362. }
  363. public int IndexOf(Predicate condition)
  364. {
  365. if (null == condition)
  366. {
  367. throw new ArgumentNullException("condition");
  368. }
  369. for (int i=0; i<_count; ++i)
  370. {
  371. if (condition(_items[i]))
  372. {
  373. return i;
  374. }
  375. }
  376. return -1;
  377. }
  378. public int IndexOfReference(object item)
  379. {
  380. for (int i=0; i<_count; ++i)
  381. {
  382. if (_items[i] == item)
  383. {
  384. return i;
  385. }
  386. }
  387. return -1;
  388. }
  389. public int IndexOf(object item)
  390. {
  391. for (int i=0; i<_count; ++i)
  392. {
  393. if (RuntimeServices.EqualityOperator(_items[i], item))
  394. {
  395. return i;
  396. }
  397. }
  398. return -1;
  399. }
  400. public List Insert(int index, object item)
  401. {
  402. int actual = NormalizeIndex(index);
  403. EnsureCapacity(Math.Max(_count, actual) + 1);
  404. if (actual < _count)
  405. {
  406. Array.Copy(_items, actual, _items, actual+1, _count-actual);
  407. }
  408. _items[actual] = item;
  409. ++_count;
  410. return this;
  411. }
  412. public object Pop()
  413. {
  414. return Pop(-1);
  415. }
  416. public object Pop(int index)
  417. {
  418. int actualIndex = CheckIndex(NormalizeIndex(index));
  419. object item = _items[actualIndex];
  420. InnerRemoveAt(actualIndex);
  421. return item;
  422. }
  423. public List PopRange(int begin)
  424. {
  425. int actualIndex = AdjustIndex(NormalizeIndex(begin));
  426. List range = InnerGetRange(actualIndex, AdjustIndex(NormalizeIndex(_count)));
  427. for (int i=actualIndex; i<_count; ++i)
  428. {
  429. _items[i] = null;
  430. }
  431. _count = actualIndex;
  432. return range;
  433. }
  434. public List RemoveAll(Predicate match)
  435. {
  436. if (null == match) throw new ArgumentNullException("match");
  437. for (int i=0; i<_count; ++i)
  438. {
  439. if (match(_items[i])) InnerRemoveAt(i--);
  440. }
  441. return this;
  442. }
  443. public List Remove(object item)
  444. {
  445. InnerRemove(item);
  446. return this;
  447. }
  448. public List RemoveAt(int index)
  449. {
  450. InnerRemoveAt(CheckIndex(NormalizeIndex(index)));
  451. return this;
  452. }
  453. public IEnumerable Reversed
  454. {
  455. get
  456. {
  457. return new ReversedListEnumerator(_items, _count);
  458. }
  459. }
  460. void IList.Insert(int index, object item)
  461. {
  462. Insert(index, item);
  463. }
  464. void IList.Remove(object item)
  465. {
  466. InnerRemove(item);
  467. }
  468. void IList.RemoveAt(int index)
  469. {
  470. InnerRemoveAt(CheckIndex(NormalizeIndex(index)));
  471. }
  472. int IList.Add(object item)
  473. {
  474. Add(item);
  475. return _count-1;
  476. }
  477. bool IList.IsReadOnly
  478. {
  479. get
  480. {
  481. return false;
  482. }
  483. }
  484. bool IList.IsFixedSize
  485. {
  486. get
  487. {
  488. return false;
  489. }
  490. }
  491. void EnsureCapacity(int minCapacity)
  492. {
  493. if (minCapacity > _items.Length)
  494. {
  495. object[] items = NewArray(minCapacity);
  496. Array.Copy(_items, 0, items, 0, _count);
  497. _items = items;
  498. }
  499. }
  500. object[] NewArray(int minCapacity)
  501. {
  502. int newLen = Math.Max(1, _items.Length)*2;
  503. return new object[Math.Max(newLen, minCapacity)];
  504. }
  505. void InnerRemoveAt(int index)
  506. {
  507. --_count;
  508. _items[index] = null;
  509. if (index != _count)
  510. {
  511. Array.Copy(_items, index+1, _items, index, _count-index);
  512. }
  513. }
  514. void InnerRemove(object item)
  515. {
  516. int index = IndexOf(item);
  517. if (index != -1)
  518. {
  519. InnerRemoveAt(index);
  520. }
  521. }
  522. void InnerCollect(List target, Predicate condition)
  523. {
  524. for (int i=0; i<_count; ++i)
  525. {
  526. object item = _items[i];
  527. if (condition(item))
  528. {
  529. target.Add(item);
  530. }
  531. }
  532. }
  533. List InnerGetRange(int begin, int end)
  534. {
  535. int targetLen = end-begin;
  536. if (targetLen > 0)
  537. {
  538. object[] target = new object[targetLen];
  539. Array.Copy(_items, begin, target, 0, targetLen);
  540. return new List(target, true);
  541. }
  542. return new List();
  543. }
  544. int AdjustIndex(int index)
  545. {
  546. if (index > _count)
  547. {
  548. return _count;
  549. }
  550. if (index < 0)
  551. {
  552. return 0;
  553. }
  554. return index;
  555. }
  556. int CheckIndex(int index)
  557. {
  558. if (index >= _count)
  559. {
  560. throw new IndexOutOfRangeException();
  561. }
  562. return index;
  563. }
  564. int NormalizeIndex(int index)
  565. {
  566. if (index < 0)
  567. {
  568. index += _count;
  569. }
  570. return index;
  571. }
  572. class ReversedListEnumerator : IEnumerator, IEnumerable
  573. {
  574. object[] _items;
  575. int _index;
  576. int _count;
  577. public ReversedListEnumerator(object[] items, int count)
  578. {
  579. _items = items;
  580. _index = count;
  581. _count = count;
  582. }
  583. public void Reset()
  584. {
  585. _index = _count;
  586. }
  587. public bool MoveNext()
  588. {
  589. return --_index >= 0;
  590. }
  591. public IEnumerator GetEnumerator()
  592. {
  593. return this;
  594. }
  595. public object Current
  596. {
  597. get
  598. {
  599. return _items[_index];
  600. }
  601. }
  602. }
  603. class ListEnumerator : IEnumerator
  604. {
  605. List _list;
  606. object[] _items;
  607. int _count;
  608. int _index;
  609. object _current;
  610. public ListEnumerator(List list)
  611. {
  612. _list = list;
  613. _items = list._items;
  614. _count = list._count;
  615. _index = 0;
  616. }
  617. public void Reset()
  618. {
  619. _index = 0;
  620. }
  621. public bool MoveNext()
  622. {
  623. if (_count != _list._count || _items != _list._items)
  624. {
  625. throw new InvalidOperationException(ResourceManager.GetString("ListWasModified"));
  626. }
  627. if (_index < _count)
  628. {
  629. _current = _items[_index];
  630. ++_index;
  631. return true;
  632. }
  633. return false;
  634. }
  635. public object Current
  636. {
  637. get
  638. {
  639. return _current;
  640. }
  641. }
  642. }
  643. }
  644. #endif
  645. }