/src/sys/dotnet/fan/sys/List.cs
C# | 1280 lines | 1065 code | 135 blank | 80 comment | 289 complexity | e26e6e559423e8d99d713894ed72425e MD5 | raw file
Possible License(s): CC-BY-SA-3.0
- //
- // Copyright (c) 2006, Brian Frank and Andy Frank
- // Licensed under the Academic Free License version 3.0
- //
- // History:
- // 27 Sep 06 Andy Frank Creation
- //
- using System;
- using System.Collections;
- using System.Diagnostics;
- using System.Text;
- using Fanx.Util;
- using Fanx.Serial;
- namespace Fan.Sys
- {
- /// <summary>
- /// List.
- /// </summary>
- public class List : FanObj, Literal
- {
- //////////////////////////////////////////////////////////////////////////
- // Constructors
- //////////////////////////////////////////////////////////////////////////
- public static List make(Type of, long capacity)
- {
- return new List(of, (int)capacity);
- }
- public static List makeObj(long capacity)
- {
- return new List(Sys.ObjType.toNullable(), (int)capacity);
- }
- public List(Type of, object[] values)
- {
- if (of == null) { Console.WriteLine(new StackTrace(true)); throw new NullErr().val; }
- this.m_of = of;
- this.m_values = values;
- this.m_size = values.Length;
- }
- public List(Type of, object[] values, int size)
- {
- if (of == null) { Console.WriteLine(new StackTrace(true)); throw new NullErr().val; }
- this.m_of = of;
- this.m_values = values;
- this.m_size = size;
- }
- public List(Type of, int capacity)
- {
- if (of == null) { Console.WriteLine(new StackTrace(true)); throw new NullErr().val; }
- this.m_of = of;
- this.m_values = capacity == 0 ? m_empty : new object[capacity];
- }
- public List(Type of)
- {
- if (of == null) { Console.WriteLine(new StackTrace(true)); throw new NullErr().val; }
- this.m_of = of;
- this.m_values = m_empty;
- }
- public List(Type of, ICollection collection)
- {
- if (of == null) { Console.WriteLine(new StackTrace(true)); throw new NullErr().val; }
- this.m_of = of;
- this.m_size = collection.Count;
- this.m_values = new object[m_size];
- collection.CopyTo(this.m_values, 0);
- }
- public List(string[] values)
- {
- this.m_of = Sys.StrType;
- this.m_size = values.Length;
- this.m_values = values;
- }
- //////////////////////////////////////////////////////////////////////////
- // Identity
- //////////////////////////////////////////////////////////////////////////
- public override Type @typeof()
- {
- return m_of.toListOf();
- }
- public Type of()
- {
- return m_of;
- }
- //////////////////////////////////////////////////////////////////////////
- // Access
- //////////////////////////////////////////////////////////////////////////
- public bool isEmpty()
- {
- return m_size == 0;
- }
- public long size()
- {
- return m_size;
- }
- public void size(long s)
- {
- modify();
- int newSize = (int)s;
- if (newSize > m_size)
- {
- if (!m_of.isNullable()) throw ArgErr.make("Cannot grow non-nullable list of " + m_of).val;
- if (newSize > m_values.Length)
- {
- object[] temp = new object[newSize];
- Array.Copy(m_values, 0, temp, 0, m_size);
- m_values = temp;
- }
- else
- {
- for (int i=m_size; i<newSize; ++i) m_values[i] = null;
- }
- m_size = newSize;
- }
- else
- {
- // null out removed items for GC
- for (int i=newSize; i<m_size; ++i) m_values[i] = null;
- m_size = newSize;
- }
- }
- public long capacity()
- {
- return m_values.Length;
- }
- public void capacity(long c)
- {
- modify();
- int newCapacity = (int)c;
- if (newCapacity < m_size) throw ArgErr.make("capacity < m_size").val;
- object[] temp = new object[newCapacity];
- Array.Copy(m_values, 0, temp, 0, m_size);
- m_values = temp;
- }
- public object get(long index)
- {
- try
- {
- int i = (int)index;
- if (i < 0) i = m_size + i;
- if (i >= m_size) throw IndexErr.make(index).val;
- return m_values[i];
- }
- catch (IndexOutOfRangeException)
- {
- throw IndexErr.make(index).val;
- }
- }
- public object getSafe(long index) { return getSafe(index, null); }
- public object getSafe(long index, object def)
- {
- if (index < 0) index = m_size + index;
- if (index >= m_size || index < 0) return def;
- return m_values[(int)index];
- }
- public List getRange(Range r)
- {
- try
- {
- int s = r.start(m_size);
- int e = r.end(m_size);
- int n = e - s + 1;
- if (n < 0) throw IndexErr.make(r).val;
- List acc = new List(m_of, n);
- acc.m_size = n;
- Array.Copy(m_values, s, acc.m_values, 0, n);
- return acc;
- }
- catch (ArgumentOutOfRangeException)
- {
- throw IndexErr.make(r).val;
- }
- }
- public bool contains(object val)
- {
- return index(val) != null;
- }
- public bool containsAll(List list)
- {
- for (int i=0; i<list.sz(); i++)
- if (index(list.get(i)) == null)
- return false;
- return true;
- }
- public bool containsAny(List list)
- {
- for (int i=0; i<list.sz(); i++)
- if (index(list.get(i)) != null)
- return true;
- return false;
- }
- public Long index(object val) { return index(val, 0); }
- public Long index(object val, long off)
- {
- if (m_size == 0) return null;
- int start = (int)off;
- if (start < 0) start = m_size + start;
- if (start >= m_size) throw IndexErr.make(off).val;
- try
- {
- if (val == null)
- {
- for (int i=start; i<m_size; i++)
- if (m_values[i] == null)
- return Long.valueOf(i);
- }
- else
- {
- for (int i=start; i<m_size; i++)
- {
- object obj = m_values[i];
- if (obj != null && obj.Equals(val))
- return Long.valueOf(i);
- }
- }
- return null;
- }
- catch (IndexOutOfRangeException)
- {
- throw IndexErr.make(off).val;
- }
- }
- public Long indexr(object val) { return indexr(val, -1); }
- public Long indexr(object val, long off)
- {
- if (m_size == 0) return null;
- int start = (int)off;
- if (start < 0) start = m_size + start;
- if (start >= m_size) throw IndexErr.make(off).val;
- try
- {
- if (val == null)
- {
- for (int i=start; i>=0; --i)
- if (m_values[i] == null)
- return Long.valueOf(i);
- }
- else
- {
- for (int i=start; i>=0; --i)
- {
- object obj = m_values[i];
- if (obj != null && obj.Equals(val))
- return Long.valueOf(i);
- }
- }
- return null;
- }
- catch (IndexOutOfRangeException)
- {
- throw IndexErr.make(off).val;
- }
- }
- public Long indexSame(object val) { return indexSame(val, 0); }
- public Long indexSame(object val, long off)
- {
- if (m_size == 0) return null;
- int start = (int)off;
- if (start < 0) start = m_size + start;
- if (start >= m_size) throw IndexErr.make(off).val;
- try
- {
- for (int i=start; i<m_size; i++)
- if (val == m_values[i])
- return Long.valueOf(i);
- return null;
- }
- catch (IndexOutOfRangeException)
- {
- throw IndexErr.make(off).val;
- }
- }
- public object first()
- {
- if (m_size == 0) return null;
- return m_values[0];
- }
- public object last()
- {
- if (m_size == 0) return null;
- return m_values[m_size-1];
- }
- public List dup()
- {
- object[] dup = new object[m_size];
- Array.Copy(m_values, 0, dup, 0, m_size);
- return new List(m_of, dup);
- }
- public override int GetHashCode() { return (int)hash(); }
- public override long hash()
- {
- long hash = 33;
- for (int i=0; i<m_size; i++)
- {
- object obj = m_values[i];
- hash = (31 * hash) + (obj == null ? 0 : FanObj.hash(obj));
- }
- return hash;
- }
- public override bool Equals(object that)
- {
- if (that is List)
- {
- List x = (List)that;
- if (!m_of.Equals(x.m_of)) return false;
- if (m_size != x.m_size) return false;
- for (int i=0; i<m_size; i++)
- if (!OpUtil.compareEQ(m_values[i], x.m_values[i])) return false;
- return true;
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- // Modification
- //////////////////////////////////////////////////////////////////////////
- public List set(long index, object val)
- {
- modify();
- try
- {
- int i = (int)index;
- if (i < 0) i = m_size + i;
- if (i >= m_size) throw IndexErr.make(index).val;
- m_values[i] = val;
- return this;
- }
- catch (IndexOutOfRangeException)
- {
- throw IndexErr.make(index).val;
- }
- }
- public List add(object val)
- {
- // modify in insert(int, object)
- return insert(m_size, val);
- }
- public List addAll(List list)
- {
- // modify in insertAll(int, List)
- return insertAll(m_size, list);
- }
- public List insert(long index, object val)
- {
- // modify in insert(int, object)
- int i = (int)index;
- if (i < 0) i = m_size + i;
- if (i > m_size) throw IndexErr.make(index).val;
- return insert(i, val);
- }
- private List insert(int i, object val)
- {
- modify();
- if (m_values.Length <= m_size)
- grow(m_size+1);
- if (i < m_size)
- Array.Copy(m_values, i, m_values, i+1, m_size-i);
- m_values[i] = val;
- m_size++;
- return this;
- }
- public List insertAll(long index, List list)
- {
- // modify in insertAll(int, List)
- int i = (int)index;
- if (i < 0) i = m_size + i;
- if (i > m_size || i < 0) throw IndexErr.make(index).val;
- return insertAll(i, list);
- }
- private List insertAll(int i, List list)
- {
- modify();
- if (list.m_size == 0) return this;
- if (m_values.Length < m_size+list.m_size)
- grow(m_size+list.m_size);
- if (i < m_size)
- Array.Copy(m_values, i, m_values, i+list.m_size, m_size-i);
- Array.Copy(list.m_values, 0, m_values, i, list.m_size);
- m_size += list.m_size;
- return this;
- }
- public object remove(object val)
- {
- // modify in removeAt(long)
- Long i = index(val);
- if (i == null) return null;
- return removeAt(i.longValue());
- }
- public object removeSame(object val)
- {
- // modify in removeAt(long)
- Long i = indexSame(val);
- if (i == null) return null;
- return removeAt(i.longValue());
- }
- public object removeAt(long index)
- {
- modify();
- int i = (int)index;
- if (i < 0) i = m_size + i;
- if (i >= m_size) throw IndexErr.make(index).val;
- object old = m_values[i];
- if (i < m_size-1)
- Array.Copy(m_values, i+1, m_values, i, m_size-i-1);
- m_size--;
- return old;
- }
- public List removeRange(Range r)
- {
- modify();
- int s = r.start(m_size);
- int e = r.end(m_size);
- int n = e - s + 1;
- if (n < 0) throw IndexErr.make(r).val;
- int shift = m_size-s-n;
- if (shift > 0) Array.Copy(m_values, s+n, m_values, s, shift);
- m_size -= n;
- for (int i=m_size; i<m_size+n; ++i) m_values[i] = null;
- return this;
- }
- public List removeAll(List toRemove)
- {
- // optimize special cases
- modify();
- if (toRemove.sz() == 0) { return this; }
- if (toRemove.sz() == 1) { remove(toRemove.get(0)); return this; }
- // rebuild the backing store array, implementation
- // assumes that this list is bigger than toRemove list
- object[] newValues = new object[m_values.Length];
- int newSize = 0;
- for (int i=0; i<m_size; ++i)
- {
- object val = m_values[i];
- if (!toRemove.contains(val)) newValues[newSize++] = val;
- }
- this.m_values = newValues;
- this.m_size = newSize;
- return this;
- }
- private void grow(int desiredSize)
- {
- int desired = (int)desiredSize;
- if (desired < 1) throw Err.make("desired " + desired + " < 1").val;
- int newSize = Math.Max(desired, m_size*2);
- if (newSize < 10) newSize = 10;
- object[] temp = new object[newSize];
- Array.Copy(m_values, temp, m_size);
- m_values = temp;
- }
- public List trim()
- {
- modify();
- if (m_size == 0)
- {
- m_values = m_empty;
- }
- else if (m_size != m_values.Length)
- {
- object[] temp = new object[m_size];
- Array.Copy(m_values, temp, m_size);
- m_values = temp;
- }
- return this;
- }
- public List fill(object val, long times)
- {
- modify();
- int t = (int)times;
- if (m_values.Length < m_size+t) grow(m_size+t);
- for (int i=0; i<t; ++i) add(val);
- return this;
- }
- public List clear()
- {
- modify();
- for (int i=0; i<m_size; i++)
- m_values[i] = null;
- m_size = 0;
- return this;
- }
- //////////////////////////////////////////////////////////////////////////
- // Stack
- //////////////////////////////////////////////////////////////////////////
- public object peek()
- {
- if (m_size == 0) return null;
- return m_values[m_size-1];
- }
- public object pop()
- {
- // modify in removeAt()
- if (m_size == 0) return null;
- return removeAt(-1);
- }
- public List push(object obj)
- {
- // modify in add()
- return add(obj);
- }
- //////////////////////////////////////////////////////////////////////////
- // Iterators
- //////////////////////////////////////////////////////////////////////////
- public void each(Func f)
- {
- if (f.arity() == 1)
- {
- for (int i=0; i<m_size; i++)
- f.call(m_values[i]);
- }
- else
- {
- for (int i=0; i<m_size; i++)
- f.call(m_values[i], i);
- }
- }
- public void eachr(Func f)
- {
- if (f.arity() == 1)
- {
- for (int i=m_size-1; i>=0; i--)
- f.call(m_values[i]);
- }
- else
- {
- for (int i=m_size-1; i>=0; i--)
- f.call(m_values[i], i);
- }
- }
- public void eachRange(Range r, Func f)
- {
- int s = r.start(m_size);
- int e = r.end(m_size);
- int n = e - s + 1;
- if (n < 0) throw IndexErr.make(r).val;
- if (f.arity() == 1)
- {
- for (int i=s; i<=e; ++i)
- f.call(m_values[i]);
- }
- else
- {
- for (int i=s; i<=e; ++i)
- f.call(m_values[i], i);
- }
- }
- public object eachWhile(Func f)
- {
- for (int i=0; i<m_size; i++)
- {
- object r = f.call(m_values[i], i);
- if (r != null) return r;
- }
- return null;
- }
- public object eachrWhile(Func f)
- {
- for (int i=m_size-1; i>=0; i--)
- {
- object r = f.call(m_values[i], i);
- if (r != null) return r;
- }
- return null;
- }
- public object find(Func f)
- {
- for (int i=0; i<m_size; i++)
- if (f.call(m_values[i], i) == Boolean.True)
- return m_values[i];
- return null;
- }
- public Long findIndex(Func f)
- {
- for (int i=0; i<m_size; ++i)
- {
- long pos = i;
- if (f.call(m_values[i], pos) == Boolean.True)
- return Long.valueOf(pos);
- }
- return null;
- }
- public List findAll(Func f)
- {
- List acc = new List(m_of, m_size);
- for (int i=0; i<m_size; i++)
- if (f.call(m_values[i], i) == Boolean.True)
- acc.add(m_values[i]);
- return acc;
- }
- public List findType(Type t)
- {
- List acc = new List(t, m_size);
- for (int i=0; i<m_size; i++)
- {
- object item = m_values[i];
- if (item != null && @typeof(item).@is(t))
- acc.add(item);
- }
- return acc;
- }
- public List exclude(Func f)
- {
- List acc = new List(m_of, m_size);
- for (int i=0; i<m_size; i++)
- if (f.call(m_values[i], i) == Boolean.False)
- acc.add(m_values[i]);
- return acc;
- }
- public bool any(Func f)
- {
- for (int i=0; i<m_size; i++)
- if (f.call(m_values[i], i) == Boolean.True)
- return true;
- return false;
- }
- public bool all(Func f)
- {
- for (int i=0; i<m_size; i++)
- if (f.call(m_values[i], i) == Boolean.False)
- return false;
- return true;
- }
- public object reduce(object reduction, Func f)
- {
- for (int i=0; i<m_size; i++)
- reduction = f.call(reduction, m_values[i], i);
- return reduction;
- }
- public List map(Func f)
- {
- Type r = f.returns();
- if (r == Sys.VoidType) r = Sys.ObjType.toNullable();
- List acc = new List(r, (int)size());
- for (int i=0; i<m_size; i++)
- acc.add(f.call(m_values[i], i));
- return acc;
- }
- public object max() { return max(null); }
- public object max(Func f)
- {
- if (m_size == 0) return null;
- IComparer c = toComparer(f);
- object max = m_values[0];
- for (int i=1; i<m_size; i++)
- if (c.Compare(m_values[i], max) > 0)
- max = m_values[i];
- return max;
- }
- public object min() { return min(null); }
- public object min(Func f)
- {
- if (m_size == 0) return null;
- IComparer c = toComparer(f);
- object min = m_values[0];
- for (int i=1; i<m_size; i++)
- if (c.Compare(m_values[i], min) < 0)
- min = m_values[i];
- return min;
- }
- public List unique()
- {
- Hashtable dups = new Hashtable(m_size*3);
- List acc = new List(m_of, m_size);
- bool hasNull = false;
- for (int i=0; i<m_size; i++)
- {
- object v = m_values[i];
- if (v == null && !hasNull)
- {
- hasNull = true;
- acc.add(v);
- }
- else if (v != null && dups[v] == null)
- {
- dups[v] = this;
- acc.add(v);
- }
- }
- return acc;
- }
- public List union(List that)
- {
- int capacity = m_size + that.m_size;
- Hashtable dups = new Hashtable(capacity*3);
- List acc = new List(m_of, capacity);
- bool hasNull = false;
- // first me
- for (int i=0; i<m_size; i++)
- {
- object v = m_values[i];
- if (v == null && !hasNull)
- {
- hasNull = true;
- acc.add(v);
- }
- else if (v != null && dups[v] == null)
- {
- dups[v] = this;
- acc.add(v);
- }
- }
- // then him
- for (int i=0; i<that.m_size; i++)
- {
- object v = that.m_values[i];
- if (v == null && !hasNull)
- {
- hasNull = true;
- acc.add(v);
- }
- else if (v != null && dups[v] == null)
- {
- dups[v] = this;
- acc.add(v);
- }
- }
- return acc;
- }
- public List intersection(List that)
- {
- // put other list into map
- Hashtable dups = new Hashtable(that.m_size*3);
- bool hasNull = false;
- for (int i=0; i<that.m_size; ++i)
- {
- object v = that.m_values[i];
- if (v == null) hasNull = true;
- else dups[v] = this;
- }
- // now walk this list and accumulate
- // everything found in the dups map
- List acc = new List(m_of, m_size);
- for (int i=0; i<m_size; i++)
- {
- object v = m_values[i];
- if (v == null && hasNull)
- {
- acc.add(v);
- hasNull = false;
- }
- else if (v != null && dups[v] != null)
- {
- acc.add(v);
- dups.Remove(v);
- }
- }
- return acc;
- }
- //////////////////////////////////////////////////////////////////////////
- // Utils
- //////////////////////////////////////////////////////////////////////////
- public List sort() { return sort(null); }
- public List sort(Func f)
- {
- modify();
- Array.Sort(m_values, 0, m_size, toComparer(f));
- return this;
- }
- public List sortr() { return sortr(null); }
- public List sortr(Func f)
- {
- modify();
- Array.Sort(m_values, 0, m_size, toReverseComparer(f));
- return this;
- }
- public long binarySearch(object key) { return binarySearch(key, null); }
- public long binarySearch(object key, Func f)
- {
- IComparer c = toComparer(f);
- object[] values = m_values;
- int low = 0, high = m_size-1;
- while (low <= high)
- {
- int probe = (low + high) >> 1;
- int cmp = c.Compare(values[probe], key);
- if (cmp < 0)
- low = probe + 1;
- else if (cmp > 0)
- high = probe - 1;
- else
- return probe;
- }
- return -(low + 1);
- }
- public long binaryFind(Func f)
- {
- object[] values = this.m_values;
- int low = 0, high = m_size-1;
- bool oneArg = f.arity() == 1;
- while (low <= high)
- {
- int probe = (low + high) >> 1;
- object val = values[probe];
- object res = oneArg ? f.call(val) : f.call(val, Long.valueOf(probe));
- long cmp = ((Long)res).longValue();
- if (cmp > 0)
- low = probe + 1;
- else if (cmp < 0)
- high = probe - 1;
- else
- return probe;
- }
- return -(low + 1);
- }
- public List reverse()
- {
- modify();
- object[] m_values = this.m_values;
- int m_size = this.m_size;
- int mid = m_size/2;
- for (int i=0; i<mid; i++)
- {
- object a = m_values[i];
- object b = m_values[m_size-i-1];
- m_values[i] = b;
- m_values[m_size-i-1] = a;
- }
- return this;
- }
- public List swap(long a, long b)
- {
- // modify in set()
- object temp = get(a);
- set(a, get(b));
- set(b, temp);
- return this;
- }
- public List moveTo(object item, long toIndex)
- {
- modify();
- Long curIndex = index(item);
- if (curIndex == null) return this;
- if (curIndex.longValue() == toIndex) return this;
- removeAt(curIndex.longValue());
- if (toIndex == -1) return add(item);
- if (toIndex < 0) ++toIndex;
- return insert(toIndex, item);
- }
- public List flatten()
- {
- List acc = new List(Sys.ObjType.toNullable(), m_size*2);
- doFlatten(acc);
- return acc;
- }
- private void doFlatten(List acc)
- {
- for (int i=0; i<m_size; ++i)
- {
- object item = m_values[i];
- if (item is List)
- ((List)item).doFlatten(acc);
- else
- acc.add(item);
- }
- }
- public object random()
- {
- if (m_size == 0) return null;
- int i = (int)FanInt.random();
- if (i < 0) i = -i;
- return m_values[i % m_size];
- }
- public List shuffle()
- {
- modify();
- for (int i=0; i<m_size; ++i)
- {
- int randi = (int)FanInt.random() % m_size;
- if (randi < 0) randi = -randi;
- object temp = m_values[i];
- m_values[i] = m_values[randi];
- m_values[randi] = temp;
- }
- return this;
- }
- //////////////////////////////////////////////////////////////////////////
- // Conversion
- //////////////////////////////////////////////////////////////////////////
- public string join() { return join(string.Empty, null); }
- public string join(string sep) { return join(sep, null); }
- public string join(string sep, Func f)
- {
- if (m_size == 0) return "";
- if (m_size == 1)
- {
- object v = m_values[0];
- if (f != null) return (string)f.call(v, 0);
- if (v == null) return "null";
- return toStr(v);
- }
- StringBuilder s = new StringBuilder(32+m_size*32);
- for (int i=0; i<m_size; i++)
- {
- if (i > 0) s.Append(sep);
- if (f == null)
- {
- if (m_values[i] == null) s.Append("null");
- else s.Append(m_values[i]);
- }
- else
- {
- s.Append(f.call(m_values[i], i));
- }
- }
- return s.ToString();
- }
- public override string toStr()
- {
- if (m_size == 0) return "[,]";
- StringBuilder s = new StringBuilder(32+m_size*32);
- s.Append("[");
- for (int i=0; i<m_size; i++)
- {
- if (i > 0) s.Append(", ");
- if (m_values[i] == null) s.Append("null");
- else s.Append(m_values[i]);
- }
- s.Append("]");
- return s.ToString();
- }
- public string toCode()
- {
- StringBuilder s = new StringBuilder(32+m_size*32);
- s.Append(m_of.signature());
- s.Append('[');
- if (m_size == 0) s.Append(',');
- for (int i=0; i<m_size; ++i)
- {
- if (i > 0) s.Append(',').Append(' ');
- s.Append(FanObj.trap(m_values[i], "toCode", null));
- }
- s.Append(']');
- return s.ToString();
- }
- public void encode(ObjEncoder @out)
- {
- // route back to obj encoder
- @out.writeList(this);
- }
- //////////////////////////////////////////////////////////////////////////
- // Runtime Utils
- //////////////////////////////////////////////////////////////////////////
- public int sz()
- {
- return m_size;
- }
- public object get(int i)
- {
- try
- {
- if (i >= m_size) throw IndexErr.make(""+i).val;
- return m_values[i];
- }
- catch (IndexOutOfRangeException)
- {
- throw IndexErr.make(""+i).val;
- }
- }
- public object[] toArray()
- {
- if (m_values.Length == m_size) return m_values;
- object[] r = new object[m_size];
- Array.Copy(m_values, 0, r, 0, m_size);
- return r;
- }
- public object[] toArray(object[] a)
- {
- try
- {
- Array.Copy(m_values, 0, a, 0, m_size);
- return a;
- }
- catch (IndexOutOfRangeException)
- {
- throw IndexErr.make().val;
- }
- }
- public object[] toArray(object[] a, int start, int len)
- {
- try
- {
- Array.Copy(m_values, start, a, 0, len);
- return a;
- }
- catch (IndexOutOfRangeException)
- {
- throw IndexErr.make().val;
- }
- }
- public object[] copyInto(object[] a, int off, int len)
- {
- try
- {
- Array.Copy(m_values, 0, a, off, len);
- return a;
- }
- catch (IndexOutOfRangeException)
- {
- throw IndexErr.make().val;
- }
- }
- public string[] toStrings()
- {
- string[] a = new string[m_size];
- for (int i=0; i<m_size; ++i)
- {
- object obj = get(i);
- if (obj == null) a[i] = "null";
- else a[i] = toStr(obj);
- }
- return a;
- }
- /*
- public int[] toInts()
- {
- int[] a = new int[size];
- for (int i=0; i<size; ++i) a[i] = ((long)get(i)).intValue();
- return a;
- }
- */
- //////////////////////////////////////////////////////////////////////////
- // Comparators
- //////////////////////////////////////////////////////////////////////////
- // normal
- static IComparer toComparer(Func f)
- {
- if (f == null) return defaultComparer;
- return new Comparer(f);
- }
- sealed class Comparer : IComparer
- {
- public Comparer(Func f) { this.f = f; }
- public int Compare(object a, object b) { return ((Long)f.call(a, b)).intValue(); }
- private Func f;
- }
- sealed class DefaultComparer : IComparer
- {
- public int Compare(object a, object b) { return (int)OpUtil.compare(a, b); }
- }
- static DefaultComparer defaultComparer = new DefaultComparer();
- // reverse
- static IComparer toReverseComparer(Func f)
- {
- if (f == null) return defaultReverseComparer;
- return new ReverseComparer(f);
- }
- sealed class ReverseComparer : IComparer
- {
- public ReverseComparer(Func f) { this.f = f; }
- public int Compare(object a, object b) { return ((Long)f.call(b, a)).intValue(); }
- private Func f;
- }
- sealed class DefaultReverseComparer : IComparer
- {
- public int Compare(object a, object b) { return (int)OpUtil.compare(b, a); }
- }
- static DefaultReverseComparer defaultReverseComparer = new DefaultReverseComparer();
- //////////////////////////////////////////////////////////////////////////
- // Readonly
- //////////////////////////////////////////////////////////////////////////
- public bool isRW()
- {
- return !m_isReadonly;
- }
- public bool isRO()
- {
- return m_isReadonly;
- }
- public List rw()
- {
- if (!m_isReadonly) return this;
- object[] temp = new object[m_size];
- Array.Copy(m_values, temp, m_size);
- List rw = new List(m_of);
- rw.m_values = temp;
- rw.m_size = m_size;
- rw.m_isReadonly = false;
- rw.m_readonlyList = this;
- return rw;
- }
- public List ro()
- {
- if (m_isReadonly) return this;
- if (m_readonlyList == null)
- {
- List ro = new List(m_of);
- ro.m_values = m_values;
- ro.m_size = m_size;
- ro.m_isReadonly = true;
- m_readonlyList = ro;
- }
- return m_readonlyList;
- }
- public override bool isImmutable()
- {
- return m_immutable;
- }
- public override object toImmutable()
- {
- if (m_immutable) return this;
- // make safe copy
- object[] temp = new object[m_size];
- for (int i=0; i<m_size; i++)
- {
- object item = m_values[i];
- if (item != null)
- {
- if (item is List)
- item = ((List)item).toImmutable();
- else if (item is Map)
- item = ((Map)item).toImmutable();
- else if (!isImmutable(item))
- throw NotImmutableErr.make("Item [" + i + "] not immutable " + @typeof(item)).val;
- }
- temp[i] = item;
- }
- // return new immutable list
- List ro = new List(m_of, temp);
- ro.m_isReadonly = true;
- ro.m_immutable = true;
- return ro;
- }
- private void modify()
- {
- // if readonly then throw readonly exception
- if (m_isReadonly)
- throw ReadonlyErr.make("List is readonly").val;
- // if we have a cached readonlyList, then detach
- // it so it remains immutable
- if (m_readonlyList != null)
- {
- object[] temp = new object[m_size];
- Array.Copy(m_values, temp, m_size);
- m_readonlyList.m_values = temp;
- m_readonlyList = null;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // Fields
- //////////////////////////////////////////////////////////////////////////
- private static readonly object[] m_empty = new object[0];
- private Type m_of;
- private object[] m_values;
- private int m_size;
- private bool m_isReadonly;
- private bool m_immutable;
- private List m_readonlyList;
- }
- }