Permalink
Browse files

Adding more support for Array, Dictionary, Console, and Object

  • Loading branch information...
1 parent ce1fae0 commit b50658f9138ac60e638a7578218f3de949ed53fe Frank Laub committed Mar 15, 2010
View
@@ -26,13 +26,15 @@ namespace System
{
[UseSystem]
[JsNamespace]
- [JsCamelCase]
- public class Array : JsObject
+ [JsAugment("Array")]
+ public class Array
{
private Array() {
}
+ [JsCamelCase]
public extern int Length { get; }
+
public extern object this[int index] { get; set; }
#if !HOSTED_MODE
@@ -68,11 +70,46 @@ public class Array : JsObject
if (destinationIndex < 0)
throw new ArgumentOutOfRangeException("destinationIndex", "Value has to be >= 0.");
- var jsSource = new JsArray(sourceArray);
- var jsTarget = new JsArray(destinationArray);
+ for (int i = 0; i < length; i++) {
+ destinationArray[destinationIndex + i] = sourceArray[sourceIndex + i];
+ }
+ }
+
+ /// <summary>
+ /// Sets a range of elements in the Array to zero, to false, or to null, depending on the element type.
+ /// </summary>
+ /// <param name="array">The Array whose elements need to be cleared.</param>
+ /// <param name="index">The starting index of the range of elements to clear.</param>
+ /// <param name="length">The number of elements to clear.</param>
+ /// <exception cref="System.ArgumentNullException">array is null.</exception>
+ /// <exception cref="System.IndexOutOfRangeException">
+ /// index is less than the lower bound of array.
+ /// -or-
+ /// length is less than zero.
+ /// -or-
+ /// The sum of index and length is greater than the size of the Array.
+ /// </exception>
+ /// <remarks>
+ /// Reference-type elements are set to null. Boolean-type elements are set to false. Other value-type elements are set to zero.
+ /// The range of cleared elements wrap from row to row in a multi-dimensional array.
+ /// This method only clears the values of the elements; it does not delete the elements themselves. An Array has a fixed size; therefore, elements cannot be added or removed.
+ /// This method is an O(n) operation, where n is length.
+ /// </remarks>
+ public static void Clear(Array array, int index, int length) {
+ if (array == null)
+ throw new ArgumentNullException("array");
+ if (length < 0)
+ throw new IndexOutOfRangeException("length < 0");
+ if (index < 0)
+ throw new IndexOutOfRangeException("index < lower bound");
+
+ // re-ordered to avoid possible integer overflow
+ if (index > array.Length - length)
+ throw new IndexOutOfRangeException("index + length > size");
+ var jsArray = new JsArray(array);
for (int i = 0; i < length; i++) {
- jsTarget[destinationIndex + i] = jsSource[sourceIndex + i];
+ jsArray[index + i] = 0;
}
}
#endif
@@ -28,7 +28,7 @@ namespace System.Collections.Generic
#endif
{
[JsAnonymous]
- internal struct Link
+ internal class Link
{
public int HashCode;
public int Next;
@@ -139,7 +139,6 @@ public Dictionary(IDictionary<TKey, TValue> dictionary)
}
private void InitArrays(int size) {
- JsDebug.Log("InitArrays: " + size);
table = new int[size];
linkSlots = new Link[size];
@@ -152,14 +151,13 @@ public Dictionary(IDictionary<TKey, TValue> dictionary)
threshold = (int)(table.Length * DEFAULT_LOAD_FACTOR);
if (threshold == 0 && table.Length > 0)
threshold = 1;
- JsDebug.Log("threshold: " + threshold);
}
#endregion
#region IDictionary<TKey,TValue> Members
public void Add(TKey key, TValue value) {
- throw new NotImplementedException();
+ PutImpl(key, value);
}
public bool ContainsKey(TKey key) {
@@ -196,11 +194,23 @@ public Dictionary(IDictionary<TKey, TValue> dictionary)
#region ICollection<KeyValuePair<TKey,TValue>> Members
public void Add(KeyValuePair<TKey, TValue> item) {
- throw new NotImplementedException();
+ PutImpl(item.Key, item.Value);
}
public void Clear() {
- throw new NotImplementedException();
+ count = 0;
+ // clear the hash table
+ SysArray.Clear(table, 0, table.Length);
+ // clear arrays
+ SysArray.Clear(keySlots, 0, keySlots.Length);
+ SysArray.Clear(valueSlots, 0, valueSlots.Length);
+ SysArray.Clear(linkSlots, 0, linkSlots.Length);
+
+ // empty the "empty slots chain"
+ emptySlot = NO_SLOT;
+
+ touchedSlots = 0;
+ generation++;
}
public bool Contains(KeyValuePair<TKey, TValue> item) {
@@ -216,7 +226,7 @@ public Dictionary(IDictionary<TKey, TValue> dictionary)
}
public int Count {
- get { throw new NotImplementedException(); }
+ get { return this.count; }
}
public bool IsReadOnly {
@@ -228,7 +238,7 @@ public Dictionary(IDictionary<TKey, TValue> dictionary)
#region IEnumerable<KeyValuePair<TKey,TValue>> Members
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
- throw new NotImplementedException();
+ return new Enumerator(this);
}
#endregion
@@ -265,7 +275,7 @@ public Dictionary(IDictionary<TKey, TValue> dictionary)
}
public void Add(object key, object value) {
- throw new NotImplementedException();
+ PutImpl((TKey)key, (TValue)value);
}
public bool Contains(object key) {
@@ -302,6 +312,18 @@ public Dictionary(IDictionary<TKey, TValue> dictionary)
public override string ToString() {
var result = new StringBuilder();
result.Append("{");
+ var isFirst = true;
+ foreach (var item in this) {
+ if (isFirst) {
+ isFirst = false;
+ }
+ else {
+ result.Append(", ");
+ }
+ result.Append(item.Key);
+ result.Append(": ");
+ result.Append(item.Value);
+ }
result.Append("}");
return result.ToString();
}
@@ -341,12 +363,21 @@ public Dictionary(IDictionary<TKey, TValue> dictionary)
private void PutImpl(TKey key, TValue value) {
if (key == null)
throw new ArgumentNullException("key");
+
+ //JsDebug.Log("key: " + key);
+ //JsDebug.Log("value: " + value);
// get first item of linked list corresponding to given key
int hashCode = hcp.GetHashCode(key) | HASH_FLAG;
int index = (hashCode & int.MaxValue) % table.Length;
int cur = table[index] - 1;
-
+
+ //JsDebug.Log("hashCode: " + hashCode);
+ //JsDebug.Log("index: " + index);
+ //JsDebug.Log("table: " + table);
+ //JsDebug.Log("table[index]: " + table[index]);
+ //JsDebug.Log("cur: " + cur);
+
// walk linked list until end is reached (throw an exception if a
// existing slot is found having an equivalent key)
while (cur != NO_SLOT) {
@@ -369,30 +400,42 @@ public Dictionary(IDictionary<TKey, TValue> dictionary)
else
emptySlot = linkSlots[cur].Next;
+ //JsDebug.Log("cur: " + cur);
+
// store the hash code of the added item,
// prepend the added item to its linked list,
// update the hash table
+ //JsDebug.Log("linkSlots[cur]: " + linkSlots[cur]);
+ if (linkSlots[cur] == null) {
+ linkSlots[cur] = new Link();
+ }
linkSlots[cur].HashCode = hashCode;
linkSlots[cur].Next = table[index] - 1;
+ //JsDebug.Log("linkSlots[cur]: " + linkSlots[cur]);
table[index] = cur + 1;
+ //JsDebug.Log("table: " + table);
// store item's data
keySlots[cur] = key;
valueSlots[cur] = value;
+ //JsDebug.Log("keySlots: " + keySlots);
+ //JsDebug.Log("valueSlots: " + valueSlots);
+
generation++;
}
private void Resize() {
+ //JsDebug.Log("Resize");
// From the SDK docs:
// Hashtable is automatically increased
// to the smallest prime number that is larger
// than twice the current number of Hashtable buckets
- int newSize = ToPrime((table.Length << 1) | 1);
+ var newSize = ToPrime((table.Length << 1) | 1);
// allocate new hash table and link slots array
- int[] newTable = new int[newSize];
- Link[] newLinkSlots = new Link[newSize];
+ var newTable = new int[newSize];
+ var newLinkSlots = new Link[newSize];
for (int i = 0; i < table.Length; i++) {
int cur = table[i] - 1;
@@ -408,15 +451,128 @@ public Dictionary(IDictionary<TKey, TValue> dictionary)
linkSlots = newLinkSlots;
// allocate new data slots, copy data
- TKey[] newKeySlots = new TKey[newSize];
- TValue[] newValueSlots = new TValue[newSize];
+ var newKeySlots = new TKey[newSize];
+ var newValueSlots = new TValue[newSize];
SysArray.Copy(keySlots, 0, newKeySlots, 0, touchedSlots);
SysArray.Copy(valueSlots, 0, newValueSlots, 0, touchedSlots);
keySlots = newKeySlots;
valueSlots = newValueSlots;
threshold = (int)(newSize * DEFAULT_LOAD_FACTOR);
}
- #endregion
+ #endregion
+
+ public class Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>, IDictionaryEnumerator
+ {
+ Dictionary<TKey, TValue> dictionary;
+ int next;
+ int stamp;
+
+ internal KeyValuePair<TKey, TValue> current;
+
+ internal Enumerator(Dictionary<TKey, TValue> dictionary) {
+ //JsDebug.Log("Enumerator");
+ this.dictionary = dictionary;
+ stamp = dictionary.generation;
+ }
+
+ #region IEnumerator<KeyValuePair<TKey,TValue>> Members
+
+ public KeyValuePair<TKey, TValue> Current {
+ get {
+ //JsDebug.Log("Current");
+ return this.current;
+ }
+ }
+
+ #endregion
+
+ #region IDisposable Members
+
+ public void Dispose() {
+ //JsDebug.Log("Dispose");
+ this.dictionary = null;
+ }
+
+ #endregion
+
+ #region IEnumerator Members
+
+ public bool MoveNext() {
+ VerifyState();
+
+ if (next < 0) {
+ return false;
+ }
+
+ while (next < dictionary.touchedSlots) {
+ int cur = next++;
+ var link = dictionary.linkSlots[cur];
+ if ((link.HashCode & HASH_FLAG) != 0) {
+ var key = dictionary.keySlots[cur];
+ var value = dictionary.valueSlots[cur];
+ this.current = new KeyValuePair<TKey, TValue>(key, value);
+ return true;
+ }
+ }
+
+ next = -1;
+ return false;
+ }
+
+ object IEnumerator.Current {
+ get {
+ //JsDebug.Log("IEnumerator.Current");
+ VerifyCurrent();
+ return this.current;
+ }
+ }
+
+ public void Reset() {
+ VerifyState();
+ next = 0;
+ }
+
+ #endregion
+
+ #region IDictionaryEnumerator Members
+
+ public DictionaryEntry Entry {
+ get {
+ VerifyCurrent();
+ return new DictionaryEntry(current.Key, current.Value);
+ }
+ }
+
+ public object Key {
+ get {
+ VerifyCurrent();
+ return current.Key;
+ }
+ }
+
+ public object Value {
+ get {
+ VerifyCurrent();
+ return current.Value;
+ }
+ }
+
+ #endregion
+
+ void VerifyState() {
+ //if (dictionary == null)
+ // throw new ObjectDisposedException(null);
+ if (dictionary.generation != stamp)
+ throw new InvalidOperationException("out of sync");
+ }
+
+ void VerifyCurrent() {
+ VerifyState();
+ if (next <= 0)
+ throw new InvalidOperationException("Current is not valid");
+ }
+ }
+
}
}
@@ -30,14 +30,19 @@ public static class Console
public static extern void Write(int value);
[JsCode("console.log(value);")]
- public static extern void Write(object value);
-
- [JsCode("console.log(value);")]
- public static extern void WriteLine(object value);
+ public static extern void Write(string value);
[JsCode("console.log(value);")]
public static extern void WriteLine(string value);
+ public static void Write(object value) {
+ Write(value.ToString());
+ }
+
+ public static void WriteLine(object value) {
+ WriteLine(value.ToString());
+ }
+
public static void WriteLine(string format, params object[] args) {
WriteLine(string.Format(format, args));
}
Oops, something went wrong.

0 comments on commit b50658f

Please sign in to comment.