summaryrefslogtreecommitdiff
path: root/modules/mono/glue
diff options
context:
space:
mode:
authorIgnacio Roldán Etcheverry <ignalfonsore@gmail.com>2022-05-28 04:56:54 +0200
committerIgnacio Roldán Etcheverry <ignalfonsore@gmail.com>2022-08-22 03:36:51 +0200
commitf033764ffe5892f963a9416e8cbcfd0fb5225103 (patch)
treeae71faafaea830c8ed32e63381e4d3ab8af65804 /modules/mono/glue
parente235cef09f71d0cd752ba4931640be24dcb551ab (diff)
C#: Refactor Array & Dictionary interface implementations
Diffstat (limited to 'modules/mono/glue')
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs93
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs208
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs4
4 files changed, 217 insertions, 90 deletions
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
index a09ba09e95..3a1a8ac563 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
@@ -14,7 +14,9 @@ namespace Godot.Collections
/// such as <see cref="System.Array"/> or <see cref="List{T}"/>.
/// </summary>
public sealed class Array :
- IList,
+ IList<object>,
+ IReadOnlyList<object>,
+ ICollection,
IDisposable
{
internal godot_array.movable NativeValue;
@@ -163,12 +165,6 @@ namespace Godot.Collections
return newArray;
}
- // IList
-
- bool IList.IsReadOnly => false;
-
- bool IList.IsFixedSize => false;
-
/// <summary>
/// Returns the object at the given <paramref name="index"/>.
/// </summary>
@@ -194,21 +190,21 @@ namespace Godot.Collections
/// Adds an object to the end of this <see cref="Array"/>.
/// This is the same as <c>append</c> or <c>push_back</c> in GDScript.
/// </summary>
- /// <param name="value">The object to add.</param>
+ /// <param name="item">The object to add.</param>
/// <returns>The new size after adding the object.</returns>
- public int Add(object value)
+ public void Add(object item)
{
- using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(value);
+ using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(item);
var self = (godot_array)NativeValue;
- return NativeFuncs.godotsharp_array_add(ref self, variantValue);
+ _ = NativeFuncs.godotsharp_array_add(ref self, variantValue);
}
/// <summary>
/// Checks if this <see cref="Array"/> contains the given object.
/// </summary>
- /// <param name="value">The item to look for.</param>
+ /// <param name="item">The item to look for.</param>
/// <returns>Whether or not this array contains the given object.</returns>
- public bool Contains(object value) => IndexOf(value) != -1;
+ public bool Contains(object item) => IndexOf(item) != -1;
/// <summary>
/// Erases all items from this <see cref="Array"/>.
@@ -219,11 +215,11 @@ namespace Godot.Collections
/// Searches this <see cref="Array"/> for an object
/// and returns its index or -1 if not found.
/// </summary>
- /// <param name="value">The object to search for.</param>
+ /// <param name="item">The object to search for.</param>
/// <returns>The index of the object, or -1 if not found.</returns>
- public int IndexOf(object value)
+ public int IndexOf(object item)
{
- using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(value);
+ using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(item);
var self = (godot_array)NativeValue;
return NativeFuncs.godotsharp_array_index_of(ref self, variantValue);
}
@@ -235,27 +231,32 @@ namespace Godot.Collections
/// Existing items will be moved to the right.
/// </summary>
/// <param name="index">The index to insert at.</param>
- /// <param name="value">The object to insert.</param>
- public void Insert(int index, object value)
+ /// <param name="item">The object to insert.</param>
+ public void Insert(int index, object item)
{
if (index < 0 || index > Count)
throw new ArgumentOutOfRangeException(nameof(index));
- using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(value);
+ using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(item);
var self = (godot_array)NativeValue;
NativeFuncs.godotsharp_array_insert(ref self, index, variantValue);
}
/// <summary>
- /// Removes the first occurrence of the specified <paramref name="value"/>
+ /// Removes the first occurrence of the specified <paramref name="item"/>
/// from this <see cref="Array"/>.
/// </summary>
- /// <param name="value">The value to remove.</param>
- public void Remove(object value)
+ /// <param name="item">The value to remove.</param>
+ public bool Remove(object item)
{
- int index = IndexOf(value);
+ int index = IndexOf(item);
if (index >= 0)
+ {
RemoveAt(index);
+ return true;
+ }
+
+ return false;
}
/// <summary>
@@ -280,17 +281,49 @@ namespace Godot.Collections
/// <returns>The number of elements.</returns>
public int Count => NativeValue.DangerousSelfRef.Size;
- object ICollection.SyncRoot => this;
+ public bool IsSynchronized => false;
- bool ICollection.IsSynchronized => false;
+ public object SyncRoot => false;
+
+ public bool IsReadOnly => false;
/// <summary>
/// Copies the elements of this <see cref="Array"/> to the given
/// untyped C# array, starting at the given index.
/// </summary>
/// <param name="array">The array to copy to.</param>
- /// <param name="index">The index to start at.</param>
- public void CopyTo(System.Array array, int index)
+ /// <param name="arrayIndex">The index to start at.</param>
+ public void CopyTo(object[] array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException(nameof(array), "Value cannot be null.");
+
+ if (arrayIndex < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(arrayIndex),
+ "Number was less than the array's lower bound in the first dimension.");
+ }
+
+ int count = Count;
+
+ if (array.Length < (arrayIndex + count))
+ {
+ throw new ArgumentException(
+ "Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
+ }
+
+ unsafe
+ {
+ for (int i = 0; i < count; i++)
+ {
+ object obj = Marshaling.ConvertVariantToManagedObject(NativeValue.DangerousSelfRef.Elements[i]);
+ array[arrayIndex] = obj;
+ arrayIndex++;
+ }
+ }
+ }
+
+ void ICollection.CopyTo(System.Array array, int index)
{
if (array == null)
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
@@ -357,7 +390,7 @@ namespace Godot.Collections
/// Gets an enumerator for this <see cref="Array"/>.
/// </summary>
/// <returns>An enumerator.</returns>
- public IEnumerator GetEnumerator()
+ public IEnumerator<object> GetEnumerator()
{
int count = Count;
@@ -367,6 +400,8 @@ namespace Godot.Collections
}
}
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+
/// <summary>
/// Converts this <see cref="Array"/> to a string.
/// </summary>
@@ -632,7 +667,7 @@ namespace Godot.Collections
/// <param name="array">The C# array to copy to.</param>
/// <param name="arrayIndex">The index to start at.</param>
public void CopyTo(T[] array, int arrayIndex) =>
- _underlyingArray.CopyToGeneric<T>(array, arrayIndex, TypeOfElements);
+ _underlyingArray.CopyToGeneric(array, arrayIndex, TypeOfElements);
/// <summary>
/// Removes the first occurrence of the specified value
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
index 2523728c8b..13aae72660 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
@@ -4,6 +4,7 @@ using System.Collections;
using Godot.NativeInterop;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
+using System.Linq;
namespace Godot.Collections
{
@@ -13,7 +14,9 @@ namespace Godot.Collections
/// interfacing with the engine.
/// </summary>
public sealed class Dictionary :
+ IDictionary<object, object>,
IDictionary,
+ IReadOnlyDictionary<object, object>,
IDisposable
{
internal godot_dictionary.movable NativeValue;
@@ -94,7 +97,7 @@ namespace Godot.Collections
/// <summary>
/// Gets the collection of keys in this <see cref="Dictionary"/>.
/// </summary>
- public ICollection Keys
+ public ICollection<object> Keys
{
get
{
@@ -108,7 +111,7 @@ namespace Godot.Collections
/// <summary>
/// Gets the collection of elements in this <see cref="Dictionary"/>.
/// </summary>
- public ICollection Values
+ public ICollection<object> Values
{
get
{
@@ -119,6 +122,14 @@ namespace Godot.Collections
}
}
+ IEnumerable<object> IReadOnlyDictionary<object, object>.Keys => Keys;
+
+ IEnumerable<object> IReadOnlyDictionary<object, object>.Values => Values;
+
+ ICollection IDictionary.Keys => Keys.ToList();
+
+ ICollection IDictionary.Values => Values.ToList();
+
private (Array keys, Array values, int count) GetKeyValuePairs()
{
var self = (godot_dictionary)NativeValue;
@@ -189,6 +200,9 @@ namespace Godot.Collections
NativeFuncs.godotsharp_dictionary_add(ref self, variantKey, variantValue);
}
+ void ICollection<KeyValuePair<object, object>>.Add(KeyValuePair<object, object> item)
+ => Add(item.Key, item.Value);
+
/// <summary>
/// Erases all items from this <see cref="Dictionary"/>.
/// </summary>
@@ -203,28 +217,72 @@ namespace Godot.Collections
/// </summary>
/// <param name="key">The key to look for.</param>
/// <returns>Whether or not this dictionary contains the given key.</returns>
- public bool Contains(object key)
+ public bool ContainsKey(object key)
{
using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
var self = (godot_dictionary)NativeValue;
return NativeFuncs.godotsharp_dictionary_contains_key(ref self, variantKey).ToBool();
}
- /// <summary>
- /// Gets an enumerator for this <see cref="Dictionary"/>.
- /// </summary>
- /// <returns>An enumerator.</returns>
- public IDictionaryEnumerator GetEnumerator() => new DictionaryEnumerator(this);
+ public bool Contains(KeyValuePair<object, object> item)
+ {
+ using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(item.Key);
+ var self = (godot_dictionary)NativeValue;
+ bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
+ variantKey, out godot_variant retValue).ToBool();
+
+ using (retValue)
+ {
+ if (!found)
+ return false;
+
+ using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(item.Value);
+ return NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool();
+ }
+ }
+
+ bool IDictionary.Contains(object key)
+ {
+ throw new NotImplementedException();
+ }
/// <summary>
/// Removes an element from this <see cref="Dictionary"/> by key.
/// </summary>
/// <param name="key">The key of the element to remove.</param>
- public void Remove(object key)
+ public bool Remove(object key)
{
using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
var self = (godot_dictionary)NativeValue;
- NativeFuncs.godotsharp_dictionary_remove_key(ref self, variantKey);
+ return NativeFuncs.godotsharp_dictionary_remove_key(ref self, variantKey).ToBool();
+ }
+
+ public bool Remove(KeyValuePair<object, object> item)
+ {
+ using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(item.Key);
+ var self = (godot_dictionary)NativeValue;
+ bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
+ variantKey, out godot_variant retValue).ToBool();
+
+ using (retValue)
+ {
+ if (!found)
+ return false;
+
+ using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(item.Value);
+ if (NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool())
+ {
+ return NativeFuncs.godotsharp_dictionary_remove_key(
+ ref self, variantKey).ToBool();
+ }
+
+ return false;
+ }
+ }
+
+ void IDictionary.Remove(object key)
+ {
+ _ = Remove(key);
}
// ICollection
@@ -247,38 +305,91 @@ namespace Godot.Collections
}
}
+ public bool IsReadOnly => false;
+
+ public bool TryGetValue(object key, out object value)
+ {
+ using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(key);
+ var self = (godot_dictionary)NativeValue;
+ bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
+ variantKey, out godot_variant retValue).ToBool();
+
+ using (retValue)
+ {
+ value = found ? Marshaling.ConvertVariantToManagedObject(retValue) : default;
+ }
+
+ return found;
+ }
+
/// <summary>
- /// Copies the elements of this <see cref="Dictionary"/> to the given
- /// untyped C# array, starting at the given index.
+ /// Copies the elements of this <see cref="Dictionary"/> to the given untyped
+ /// <see cref="KeyValuePair{TKey, TValue}"/> array, starting at the given index.
/// </summary>
/// <param name="array">The array to copy to.</param>
- /// <param name="index">The index to start at.</param>
- public void CopyTo(System.Array array, int index)
+ /// <param name="arrayIndex">The index to start at.</param>
+ public void CopyTo(KeyValuePair<object, object>[] array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException(nameof(array), "Value cannot be null.");
+
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(arrayIndex),
+ "Number was less than the array's lower bound in the first dimension.");
+
+ var (keys, values, count) = GetKeyValuePairs();
+
+ if (array.Length < (arrayIndex + count))
+ throw new ArgumentException(
+ "Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
+
+ for (int i = 0; i < count; i++)
+ {
+ array[arrayIndex] = new(keys[i], values[i]);
+ arrayIndex++;
+ }
+ }
+
+ void ICollection.CopyTo(System.Array array, int arrayIndex)
{
if (array == null)
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
- if (index < 0)
- throw new ArgumentOutOfRangeException(nameof(index),
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(arrayIndex),
"Number was less than the array's lower bound in the first dimension.");
var (keys, values, count) = GetKeyValuePairs();
- if (array.Length < (index + count))
+ if (array.Length < (arrayIndex + count))
throw new ArgumentException(
"Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
for (int i = 0; i < count; i++)
{
- array.SetValue(new DictionaryEntry(keys[i], values[i]), index);
- index++;
+ array.SetValue(new DictionaryEntry(keys[i], values[i]), arrayIndex);
+ arrayIndex++;
}
}
// IEnumerable
+ /// <summary>
+ /// Gets an enumerator for this <see cref="Dictionary"/>.
+ /// </summary>
+ /// <returns>An enumerator.</returns>
+ public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
+ {
+ for (int i = 0; i < Count; i++)
+ {
+ yield return GetKeyValuePair(i);
+ }
+ }
+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+ IDictionaryEnumerator IDictionary.GetEnumerator() => new DictionaryEnumerator(this);
+
private class DictionaryEnumerator : IDictionaryEnumerator
{
private readonly Dictionary _dictionary;
@@ -343,6 +454,20 @@ namespace Godot.Collections
}
}
+ private KeyValuePair<object, object> GetKeyValuePair(int index)
+ {
+ var self = (godot_dictionary)NativeValue;
+ NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref self, index,
+ out godot_variant key,
+ out godot_variant value);
+ using (key)
+ using (value)
+ {
+ return new KeyValuePair<object, object>(Marshaling.ConvertVariantToManagedObject(key),
+ Marshaling.ConvertVariantToManagedObject(value));
+ }
+ }
+
/// <summary>
/// Converts this <see cref="Dictionary"/> to a string.
/// </summary>
@@ -518,8 +643,9 @@ namespace Godot.Collections
using (key)
using (value)
{
- return new KeyValuePair<TKey, TValue>((TKey)Marshaling.ConvertVariantToManagedObject(key),
- (TValue)Marshaling.ConvertVariantToManagedObject(value));
+ return new KeyValuePair<TKey, TValue>(
+ (TKey)Marshaling.ConvertVariantToManagedObjectOfType(key, TypeOfKeys),
+ (TValue)Marshaling.ConvertVariantToManagedObjectOfType(value, TypeOfValues));
}
}
@@ -541,7 +667,7 @@ namespace Godot.Collections
/// <returns>Whether or not this dictionary contains the given key.</returns>
public bool ContainsKey(TKey key)
{
- return _underlyingDict.Contains(key);
+ return _underlyingDict.ContainsKey(key);
}
/// <summary>
@@ -621,21 +747,7 @@ namespace Godot.Collections
}
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
- {
- using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(item.Key);
- var self = (godot_dictionary)_underlyingDict.NativeValue;
- bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
- variantKey, out godot_variant retValue).ToBool();
-
- using (retValue)
- {
- if (!found)
- return false;
-
- using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(item.Value);
- return NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool();
- }
- }
+ => _underlyingDict.Contains(new(item.Key, item.Value));
/// <summary>
/// Copies the elements of this <see cref="Dictionary{TKey, TValue}"/> to the given
@@ -666,27 +778,7 @@ namespace Godot.Collections
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
- {
- using godot_variant variantKey = Marshaling.ConvertManagedObjectToVariant(item.Key);
- var self = (godot_dictionary)_underlyingDict.NativeValue;
- bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref self,
- variantKey, out godot_variant retValue).ToBool();
-
- using (retValue)
- {
- if (!found)
- return false;
-
- using godot_variant variantValue = Marshaling.ConvertManagedObjectToVariant(item.Value);
- if (NativeFuncs.godotsharp_variant_equals(variantValue, retValue).ToBool())
- {
- return NativeFuncs.godotsharp_dictionary_remove_key(
- ref self, variantKey).ToBool();
- }
-
- return false;
- }
- }
+ => _underlyingDict.Remove(new(item.Key, item.Value));
// IEnumerable<KeyValuePair<TKey, TValue>>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
index 1a0d9946d2..563af91ae5 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs
@@ -686,7 +686,7 @@ namespace Godot.NativeInterop
/* capacity: */ godotDictionary.Count
}, null)!;
- foreach (System.Collections.DictionaryEntry pair in godotDictionary)
+ foreach (KeyValuePair<object, object> pair in godotDictionary)
dictionary.Add(pair.Key, pair.Value);
return dictionary;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
index 72be871f16..7aa27c2867 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/VariantUtils.cs
@@ -703,8 +703,8 @@ namespace Godot.NativeInterop
var res = new System.Collections.Generic.Dictionary<TKey, TValue>(godotDictionary.Count);
- foreach (System.Collections.Generic.KeyValuePair<TKey, TValue> pair in godotDictionary)
- res.Add(pair.Key, pair.Value);
+ foreach (System.Collections.Generic.KeyValuePair<object, object> pair in godotDictionary)
+ res.Add((TKey)pair.Key, (TValue)pair.Value);
return res;
}