PageRenderTime 121ms CodeModel.GetById 76ms RepoModel.GetById 0ms app.codeStats 3ms

/Dependencies/boo/src/Boo.Lang/List.cs

https://github.com/w4x/boolangstudio
C# | 707 lines | 579 code | 99 blank | 29 comment | 64 complexity | fc02ccb589a034ce4667b072ac4be9d2 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. /// <summary>
  37. /// List.
  38. /// </summary>
  39. [Serializable]
  40. public class List : IList
  41. {
  42. private const int DefaultCapacity = 16;
  43. protected object[] _items;
  44. protected int _count;
  45. public List() : this(DefaultCapacity)
  46. {
  47. }
  48. public List(IEnumerable enumerable) : this()
  49. {
  50. Extend(enumerable);
  51. }
  52. public List(int initialCapacity)
  53. {
  54. if (initialCapacity < 0)
  55. {
  56. throw new ArgumentOutOfRangeException("initialCapacity");
  57. }
  58. _items = new object[initialCapacity];
  59. _count = 0;
  60. }
  61. public List(object[] items, bool takeOwnership)
  62. {
  63. if (null == items)
  64. {
  65. throw new ArgumentNullException("items");
  66. }
  67. if (takeOwnership)
  68. {
  69. _items = items;
  70. }
  71. else
  72. {
  73. _items = (object[])items.Clone();
  74. }
  75. _count = items.Length;
  76. }
  77. public static List operator*(List lhs, int count)
  78. {
  79. return lhs.Multiply(count);
  80. }
  81. public static List operator*(int count, List rhs)
  82. {
  83. return rhs.Multiply(count);
  84. }
  85. public static List operator+(List lhs, IEnumerable rhs)
  86. {
  87. List result = new List(lhs.Count);
  88. result.Extend(lhs);
  89. result.Extend(rhs);
  90. return result;
  91. }
  92. public static string operator%(string format, List rhs)
  93. {
  94. return string.Format(format, rhs.ToArray());
  95. }
  96. public List Multiply(int count)
  97. {
  98. if (count < 0)
  99. {
  100. throw new ArgumentOutOfRangeException("count");
  101. }
  102. object[] items = new object[_count*count];
  103. for (int i=0; i<count; ++i)
  104. {
  105. Array.Copy(_items, 0, items, i*_count, _count);
  106. }
  107. return new List(items, true);
  108. }
  109. public int Count
  110. {
  111. get
  112. {
  113. return _count;
  114. }
  115. }
  116. public IEnumerator GetEnumerator()
  117. {
  118. return new ListEnumerator(this);
  119. }
  120. public void CopyTo(Array target, int index)
  121. {
  122. Array.Copy(_items, 0, target, index, _count);
  123. }
  124. public bool IsSynchronized
  125. {
  126. get
  127. {
  128. return false;
  129. }
  130. }
  131. public object SyncRoot
  132. {
  133. get
  134. {
  135. return _items;
  136. }
  137. }
  138. public object this[int index]
  139. {
  140. get
  141. {
  142. return _items[CheckIndex(NormalizeIndex(index))];
  143. }
  144. set
  145. {
  146. _items[CheckIndex(NormalizeIndex(index))] = value;
  147. }
  148. }
  149. public List Push(object item)
  150. {
  151. return Add(item);
  152. }
  153. public List Add(object item)
  154. {
  155. EnsureCapacity(_count+1);
  156. _items[_count] = item;
  157. ++_count;
  158. return this;
  159. }
  160. public List AddUnique(object item)
  161. {
  162. if (!Contains(item))
  163. {
  164. Add(item);
  165. }
  166. return this;
  167. }
  168. public List Extend(IEnumerable enumerable)
  169. {
  170. foreach (object item in enumerable)
  171. {
  172. Add(item);
  173. }
  174. return this;
  175. }
  176. public List ExtendUnique(IEnumerable enumerable)
  177. {
  178. foreach (object item in enumerable)
  179. {
  180. AddUnique(item);
  181. }
  182. return this;
  183. }
  184. public List Collect(Predicate condition)
  185. {
  186. if (null == condition)
  187. {
  188. throw new ArgumentNullException("condition");
  189. }
  190. List newList = new List();
  191. InnerCollect(newList, condition);
  192. return newList;
  193. }
  194. public List Collect(List target, Predicate condition)
  195. {
  196. if (null == target)
  197. {
  198. throw new ArgumentNullException("target");
  199. }
  200. if (null == condition)
  201. {
  202. throw new ArgumentNullException("condition");
  203. }
  204. InnerCollect(target, condition);
  205. return target;
  206. }
  207. public Array ToArray(Type targetType)
  208. {
  209. Array target = Array.CreateInstance(targetType, _count);
  210. CopyTo(target, 0);
  211. return target;
  212. }
  213. public object[] ToArray(object[] array)
  214. {
  215. CopyTo(array, 0);
  216. return array;
  217. }
  218. public object[] ToArray()
  219. {
  220. return (object[])ToArray(typeof(object));
  221. }
  222. public List Sort()
  223. {
  224. Array.Sort(_items, 0, _count, BooComparer.Default);
  225. return this;
  226. }
  227. public List Sort(IComparer comparer)
  228. {
  229. Array.Sort(_items, 0, _count, comparer);
  230. return this;
  231. }
  232. private class ComparerImpl : IComparer
  233. {
  234. Comparer _comparer;
  235. public ComparerImpl(Comparer comparer)
  236. {
  237. _comparer = comparer;
  238. }
  239. public int Compare(object lhs, object rhs)
  240. {
  241. return _comparer(lhs, rhs);
  242. }
  243. }
  244. public List Sort(Comparer comparer)
  245. {
  246. if (null == comparer)
  247. {
  248. throw new ArgumentNullException("comparer");
  249. }
  250. return Sort(new ComparerImpl(comparer));
  251. }
  252. override public string ToString()
  253. {
  254. return "[" + Join(", ") + "]";
  255. }
  256. public string Join(string separator)
  257. {
  258. return Builtins.join(this, separator);
  259. }
  260. override public int GetHashCode()
  261. {
  262. int hash = _count;
  263. for (int i=0; i<_count; ++i)
  264. {
  265. object item = _items[i];
  266. if (null != item)
  267. {
  268. hash ^= item.GetHashCode();
  269. }
  270. }
  271. return hash;
  272. }
  273. override public bool Equals(object other)
  274. {
  275. if (other == this) return true;
  276. List rhs = other as List;
  277. if (null == rhs) return false;
  278. if (_count != rhs.Count) return false;
  279. for (int i=0; i<_count; ++i)
  280. {
  281. if (!RuntimeServices.EqualityOperator(_items[i], rhs[i]))
  282. {
  283. return false;
  284. }
  285. }
  286. return true;
  287. }
  288. public void Clear()
  289. {
  290. for (int i=0; i<_count; ++i)
  291. {
  292. _items[i] = null;
  293. }
  294. _count = 0;
  295. }
  296. public List GetRange(int begin)
  297. {
  298. return InnerGetRange(AdjustIndex(NormalizeIndex(begin)), _count);
  299. }
  300. public List GetRange(int begin, int end)
  301. {
  302. return InnerGetRange(
  303. AdjustIndex(NormalizeIndex(begin)),
  304. AdjustIndex(NormalizeIndex(end)));
  305. }
  306. public bool Contains(object item)
  307. {
  308. return -1 != IndexOf(item);
  309. }
  310. public bool Contains(Predicate condition)
  311. {
  312. return -1 != IndexOf(condition);
  313. }
  314. public bool ContainsReference(object item)
  315. {
  316. return -1 != IndexOfReference(item);
  317. }
  318. public object Find(Predicate condition)
  319. {
  320. int index = IndexOf(condition);
  321. if (-1 != index)
  322. {
  323. return _items[index];
  324. }
  325. return null;
  326. }
  327. public int IndexOf(Predicate condition)
  328. {
  329. if (null == condition)
  330. {
  331. throw new ArgumentNullException("condition");
  332. }
  333. for (int i=0; i<_count; ++i)
  334. {
  335. if (condition(_items[i]))
  336. {
  337. return i;
  338. }
  339. }
  340. return -1;
  341. }
  342. public int IndexOfReference(object item)
  343. {
  344. for (int i=0; i<_count; ++i)
  345. {
  346. if (_items[i] == item)
  347. {
  348. return i;
  349. }
  350. }
  351. return -1;
  352. }
  353. public int IndexOf(object item)
  354. {
  355. for (int i=0; i<_count; ++i)
  356. {
  357. if (RuntimeServices.EqualityOperator(_items[i], item))
  358. {
  359. return i;
  360. }
  361. }
  362. return -1;
  363. }
  364. public List Insert(int index, object item)
  365. {
  366. int actual = NormalizeIndex(index);
  367. EnsureCapacity(Math.Max(_count, actual) + 1);
  368. if (actual < _count)
  369. {
  370. Array.Copy(_items, actual, _items, actual+1, _count-actual);
  371. }
  372. _items[actual] = item;
  373. ++_count;
  374. return this;
  375. }
  376. public object Pop()
  377. {
  378. return Pop(-1);
  379. }
  380. public object Pop(int index)
  381. {
  382. int actualIndex = CheckIndex(NormalizeIndex(index));
  383. object item = _items[actualIndex];
  384. InnerRemoveAt(actualIndex);
  385. return item;
  386. }
  387. public List PopRange(int begin)
  388. {
  389. int actualIndex = AdjustIndex(NormalizeIndex(begin));
  390. List range = InnerGetRange(actualIndex, AdjustIndex(NormalizeIndex(_count)));
  391. for (int i=actualIndex; i<_count; ++i)
  392. {
  393. _items[i] = null;
  394. }
  395. _count = actualIndex;
  396. return range;
  397. }
  398. public List RemoveAll(Predicate match)
  399. {
  400. if (null == match) throw new ArgumentNullException("match");
  401. for (int i=0; i<_count; ++i)
  402. {
  403. if (match(_items[i])) InnerRemoveAt(i--);
  404. }
  405. return this;
  406. }
  407. public List Remove(object item)
  408. {
  409. InnerRemove(item);
  410. return this;
  411. }
  412. public List RemoveAt(int index)
  413. {
  414. InnerRemoveAt(CheckIndex(NormalizeIndex(index)));
  415. return this;
  416. }
  417. public IEnumerable Reversed
  418. {
  419. get
  420. {
  421. return new ReversedListEnumerator(_items, _count);
  422. }
  423. }
  424. void IList.Insert(int index, object item)
  425. {
  426. Insert(index, item);
  427. }
  428. void IList.Remove(object item)
  429. {
  430. InnerRemove(item);
  431. }
  432. void IList.RemoveAt(int index)
  433. {
  434. InnerRemoveAt(CheckIndex(NormalizeIndex(index)));
  435. }
  436. int IList.Add(object item)
  437. {
  438. Add(item);
  439. return _count-1;
  440. }
  441. bool IList.IsReadOnly
  442. {
  443. get
  444. {
  445. return false;
  446. }
  447. }
  448. bool IList.IsFixedSize
  449. {
  450. get
  451. {
  452. return false;
  453. }
  454. }
  455. void EnsureCapacity(int minCapacity)
  456. {
  457. if (minCapacity > _items.Length)
  458. {
  459. object[] items = NewArray(minCapacity);
  460. Array.Copy(_items, 0, items, 0, _count);
  461. _items = items;
  462. }
  463. }
  464. object[] NewArray(int minCapacity)
  465. {
  466. int newLen = Math.Max(1, _items.Length)*2;
  467. return new object[Math.Max(newLen, minCapacity)];
  468. }
  469. void InnerRemoveAt(int index)
  470. {
  471. --_count;
  472. _items[index] = null;
  473. if (index != _count)
  474. {
  475. Array.Copy(_items, index+1, _items, index, _count-index);
  476. }
  477. }
  478. void InnerRemove(object item)
  479. {
  480. int index = IndexOf(item);
  481. if (index != -1)
  482. {
  483. InnerRemoveAt(index);
  484. }
  485. }
  486. void InnerCollect(List target, Predicate condition)
  487. {
  488. for (int i=0; i<_count; ++i)
  489. {
  490. object item = _items[i];
  491. if (condition(item))
  492. {
  493. target.Add(item);
  494. }
  495. }
  496. }
  497. List InnerGetRange(int begin, int end)
  498. {
  499. int targetLen = end-begin;
  500. if (targetLen > 0)
  501. {
  502. object[] target = new object[targetLen];
  503. Array.Copy(_items, begin, target, 0, targetLen);
  504. return new List(target, true);
  505. }
  506. return new List();
  507. }
  508. int AdjustIndex(int index)
  509. {
  510. if (index > _count)
  511. {
  512. return _count;
  513. }
  514. if (index < 0)
  515. {
  516. return 0;
  517. }
  518. return index;
  519. }
  520. int CheckIndex(int index)
  521. {
  522. if (index >= _count)
  523. {
  524. throw new IndexOutOfRangeException();
  525. }
  526. return index;
  527. }
  528. int NormalizeIndex(int index)
  529. {
  530. if (index < 0)
  531. {
  532. index += _count;
  533. }
  534. return index;
  535. }
  536. class ReversedListEnumerator : IEnumerator, IEnumerable
  537. {
  538. object[] _items;
  539. int _index;
  540. int _count;
  541. public ReversedListEnumerator(object[] items, int count)
  542. {
  543. _items = items;
  544. _index = count;
  545. _count = count;
  546. }
  547. public void Reset()
  548. {
  549. _index = _count;
  550. }
  551. public bool MoveNext()
  552. {
  553. return --_index >= 0;
  554. }
  555. public IEnumerator GetEnumerator()
  556. {
  557. return this;
  558. }
  559. public object Current
  560. {
  561. get
  562. {
  563. return _items[_index];
  564. }
  565. }
  566. }
  567. class ListEnumerator : IEnumerator
  568. {
  569. List _list;
  570. object[] _items;
  571. int _count;
  572. int _index;
  573. object _current;
  574. public ListEnumerator(List list)
  575. {
  576. _list = list;
  577. _items = list._items;
  578. _count = list._count;
  579. _index = 0;
  580. }
  581. public void Reset()
  582. {
  583. _index = 0;
  584. }
  585. public bool MoveNext()
  586. {
  587. if (_count != _list._count || _items != _list._items)
  588. {
  589. throw new InvalidOperationException(ResourceManager.GetString("ListWasModified"));
  590. }
  591. if (_index < _count)
  592. {
  593. _current = _items[_index];
  594. ++_index;
  595. return true;
  596. }
  597. return false;
  598. }
  599. public object Current
  600. {
  601. get
  602. {
  603. return _current;
  604. }
  605. }
  606. }
  607. }
  608. }