PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/System.Xronos/Language/PersistentVector.cs

https://bitbucket.org/stefanrusek/xronos
C# | 216 lines | 161 code | 32 blank | 23 comment | 19 complexity | 24d3fc0b285ec3c508411436c2db888f MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) 2008 Stefan Rusek and Benjamin Pollack
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. * THE SOFTWARE.
  22. *
  23. * ***************************************************************************/
  24. using System;
  25. using System.Collections.Generic;
  26. using System.Linq;
  27. using System.Text;
  28. using System.Collections;
  29. namespace System.Xronos.Language
  30. {
  31. public class PersistentVector : PersistentVectorBase
  32. {
  33. const int ChunkingFactor = 32;
  34. readonly int cnt;
  35. readonly object[][] chunks;
  36. readonly object[] tail;
  37. public static readonly PersistentVector Empty = new PersistentVector(0, null, RT.EmptyArray);
  38. public static PersistentVector Create(ISequence seq)
  39. {
  40. IPersistentVector ret = Empty;
  41. for (; seq != null; seq = seq.rest())
  42. ret = ret.cons(seq.first());
  43. return (PersistentVector)ret;
  44. }
  45. public static PersistentVector Create(object[] list)
  46. {
  47. if (list.Length == 0)
  48. return Empty;
  49. List<object[]> newChunks = new List<object[]>();
  50. for (int i = 0; i < list.Length; i += ChunkingFactor)
  51. {
  52. var arr = new object[Math.Min(ChunkingFactor, list.Length - i)];
  53. Array.Copy(list, i, arr, 0, arr.Length);
  54. newChunks.Add(arr);
  55. }
  56. var tail = newChunks[newChunks.Count - 1];
  57. newChunks.RemoveAt(newChunks.Count - 1);
  58. return new PersistentVector(list.Length,
  59. newChunks.Count != 0 ? newChunks.ToArray() : null,
  60. tail);
  61. }
  62. public static PersistentVector Create(IList list)
  63. {
  64. if (list.Count == 0)
  65. return Empty;
  66. List<object[]> newChunks = new List<object[]>();
  67. for (int i = 0; i < list.Count; i += ChunkingFactor)
  68. {
  69. var arr = new object[Math.Min(ChunkingFactor, list.Count - i)];
  70. for (int j = 0; j < arr.Length; j++)
  71. arr[j] = list[i + j];
  72. newChunks.Add(arr);
  73. }
  74. var tail = newChunks[newChunks.Count - 1];
  75. newChunks.RemoveAt(newChunks.Count - 1);
  76. return new PersistentVector(list.Count,
  77. newChunks.Count != 0 ? newChunks.ToArray() : null,
  78. tail);
  79. }
  80. public static PersistentVector Create(IEnumerable list)
  81. {
  82. var ilist = list as IList;
  83. if (ilist != null)
  84. return Create(ilist);
  85. IPersistentVector ret = Empty;
  86. foreach (var item in list)
  87. ret = ret.cons(item);
  88. return (PersistentVector)ret;
  89. }
  90. private PersistentVector(int cnt, object[][] chunks, object[] tail)
  91. : base(null)
  92. {
  93. this.cnt = cnt;
  94. this.chunks = chunks;
  95. this.tail = tail;
  96. }
  97. private PersistentVector(IPersistentMap meta, int cnt, object[][] chunks, object[] tail)
  98. : base(meta)
  99. {
  100. this.cnt = cnt;
  101. this.chunks = chunks;
  102. this.tail = tail;
  103. }
  104. private int TailOffset { get { return cnt - tail.Length; } }
  105. public override int Count
  106. {
  107. get { return cnt; }
  108. }
  109. public override object this[int index]
  110. {
  111. get
  112. {
  113. if (index >= 0 && index < cnt)
  114. {
  115. if (index >= TailOffset)
  116. return tail[index - TailOffset];
  117. return chunks[index / ChunkingFactor][index % ChunkingFactor];
  118. }
  119. throw new IndexOutOfRangeException();
  120. }
  121. set
  122. {
  123. throw new NotSupportedException();
  124. }
  125. }
  126. private T[] Append<T>(T[] arr, T t)
  127. {
  128. T[] newArr = new T[arr.Length + 1];
  129. Array.Copy(arr, newArr, arr.Length);
  130. newArr[arr.Length] = t;
  131. return newArr;
  132. }
  133. private T[] Replace<T>(T[] arr, int i, T val)
  134. {
  135. T[] newArr = new T[arr.Length];
  136. Array.Copy(arr, newArr, arr.Length);
  137. newArr[i] = val;
  138. return newArr;
  139. }
  140. private T[] RemoveOne<T>(T[] arr, out T last)
  141. {
  142. T[] newArr = new T[arr.Length - 1];
  143. Array.Copy(arr, 1, newArr, 0, newArr.Length);
  144. last = arr[newArr.Length];
  145. return newArr;
  146. }
  147. public override IPersistentVector assocN(int i, object val)
  148. {
  149. var newChunks = chunks;
  150. var newTail = tail;
  151. if (i >= TailOffset)
  152. {
  153. newTail = Replace(newTail, i - TailOffset, val);
  154. }
  155. else
  156. {
  157. var ixChunk = i / ChunkingFactor;
  158. newChunks = Replace(newChunks, ixChunk, Replace(newChunks[ixChunk], i % ChunkingFactor, val));
  159. }
  160. return new PersistentVector(cnt, newChunks, newTail);
  161. }
  162. public override IPersistentVector cons(object o)
  163. {
  164. var newChunks = chunks;
  165. var newTail = tail;
  166. if (newTail.Length == ChunkingFactor)
  167. {
  168. newChunks = Append(newChunks, newTail);
  169. newTail = new[] { o };
  170. }
  171. else
  172. newTail = Append(newTail, o);
  173. return new PersistentVector(cnt + 1, newChunks, newTail);
  174. }
  175. public override XronosObject withMeta(IPersistentMap meta)
  176. {
  177. return new PersistentVector(meta, cnt, chunks, tail);
  178. }
  179. public override IPersistentCollection empty()
  180. {
  181. return (IPersistentCollection)Empty.withMeta(meta());
  182. }
  183. }
  184. }