/System.Xronos/Language/PersistentVector.cs
C# | 216 lines | 161 code | 32 blank | 23 comment | 19 complexity | 24d3fc0b285ec3c508411436c2db888f MD5 | raw file
- /* ****************************************************************************
- *
- * Copyright (c) 2008 Stefan Rusek and Benjamin Pollack
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * ***************************************************************************/
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Collections;
-
- namespace System.Xronos.Language
- {
- public class PersistentVector : PersistentVectorBase
- {
- const int ChunkingFactor = 32;
-
- readonly int cnt;
- readonly object[][] chunks;
- readonly object[] tail;
-
- public static readonly PersistentVector Empty = new PersistentVector(0, null, RT.EmptyArray);
-
- public static PersistentVector Create(ISequence seq)
- {
- IPersistentVector ret = Empty;
- for (; seq != null; seq = seq.rest())
- ret = ret.cons(seq.first());
- return (PersistentVector)ret;
- }
-
- public static PersistentVector Create(object[] list)
- {
- if (list.Length == 0)
- return Empty;
-
- List<object[]> newChunks = new List<object[]>();
-
- for (int i = 0; i < list.Length; i += ChunkingFactor)
- {
- var arr = new object[Math.Min(ChunkingFactor, list.Length - i)];
- Array.Copy(list, i, arr, 0, arr.Length);
- newChunks.Add(arr);
- }
-
- var tail = newChunks[newChunks.Count - 1];
- newChunks.RemoveAt(newChunks.Count - 1);
-
- return new PersistentVector(list.Length,
- newChunks.Count != 0 ? newChunks.ToArray() : null,
- tail);
- }
-
- public static PersistentVector Create(IList list)
- {
- if (list.Count == 0)
- return Empty;
-
- List<object[]> newChunks = new List<object[]>();
-
- for (int i = 0; i < list.Count; i += ChunkingFactor)
- {
- var arr = new object[Math.Min(ChunkingFactor, list.Count - i)];
- for (int j = 0; j < arr.Length; j++)
- arr[j] = list[i + j];
- newChunks.Add(arr);
- }
-
- var tail = newChunks[newChunks.Count - 1];
- newChunks.RemoveAt(newChunks.Count - 1);
-
- return new PersistentVector(list.Count,
- newChunks.Count != 0 ? newChunks.ToArray() : null,
- tail);
- }
-
- public static PersistentVector Create(IEnumerable list)
- {
- var ilist = list as IList;
- if (ilist != null)
- return Create(ilist);
-
- IPersistentVector ret = Empty;
- foreach (var item in list)
- ret = ret.cons(item);
- return (PersistentVector)ret;
- }
-
- private PersistentVector(int cnt, object[][] chunks, object[] tail)
- : base(null)
- {
- this.cnt = cnt;
- this.chunks = chunks;
- this.tail = tail;
- }
-
- private PersistentVector(IPersistentMap meta, int cnt, object[][] chunks, object[] tail)
- : base(meta)
- {
- this.cnt = cnt;
- this.chunks = chunks;
- this.tail = tail;
- }
-
- private int TailOffset { get { return cnt - tail.Length; } }
-
- public override int Count
- {
- get { return cnt; }
- }
-
- public override object this[int index]
- {
- get
- {
- if (index >= 0 && index < cnt)
- {
- if (index >= TailOffset)
- return tail[index - TailOffset];
- return chunks[index / ChunkingFactor][index % ChunkingFactor];
- }
- throw new IndexOutOfRangeException();
- }
- set
- {
- throw new NotSupportedException();
- }
- }
-
- private T[] Append<T>(T[] arr, T t)
- {
- T[] newArr = new T[arr.Length + 1];
- Array.Copy(arr, newArr, arr.Length);
- newArr[arr.Length] = t;
- return newArr;
- }
-
- private T[] Replace<T>(T[] arr, int i, T val)
- {
- T[] newArr = new T[arr.Length];
- Array.Copy(arr, newArr, arr.Length);
- newArr[i] = val;
- return newArr;
- }
-
- private T[] RemoveOne<T>(T[] arr, out T last)
- {
- T[] newArr = new T[arr.Length - 1];
- Array.Copy(arr, 1, newArr, 0, newArr.Length);
- last = arr[newArr.Length];
- return newArr;
- }
-
- public override IPersistentVector assocN(int i, object val)
- {
- var newChunks = chunks;
- var newTail = tail;
-
- if (i >= TailOffset)
- {
- newTail = Replace(newTail, i - TailOffset, val);
- }
- else
- {
- var ixChunk = i / ChunkingFactor;
- newChunks = Replace(newChunks, ixChunk, Replace(newChunks[ixChunk], i % ChunkingFactor, val));
- }
-
- return new PersistentVector(cnt, newChunks, newTail);
- }
-
- public override IPersistentVector cons(object o)
- {
- var newChunks = chunks;
- var newTail = tail;
-
- if (newTail.Length == ChunkingFactor)
- {
- newChunks = Append(newChunks, newTail);
- newTail = new[] { o };
- }
- else
- newTail = Append(newTail, o);
-
- return new PersistentVector(cnt + 1, newChunks, newTail);
- }
-
- public override XronosObject withMeta(IPersistentMap meta)
- {
- return new PersistentVector(meta, cnt, chunks, tail);
- }
-
- public override IPersistentCollection empty()
- {
- return (IPersistentCollection)Empty.withMeta(meta());
- }
- }
- }