You've already forked linux-packaging-mono
Imported Upstream version 4.2.0.179
Former-commit-id: 4610231f55806d2a05ed69e5ff3faa7336cc1479
This commit is contained in:
committed by
Jo Shields
parent
aa7da660d6
commit
c042cd0c52
@@ -43,8 +43,7 @@ namespace System
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
public abstract class MulticastDelegate : Delegate
|
||||
{
|
||||
MulticastDelegate prev;
|
||||
MulticastDelegate kpm_next;
|
||||
Delegate[] delegates;
|
||||
|
||||
protected MulticastDelegate (object target, string method)
|
||||
: base (target, method)
|
||||
@@ -61,13 +60,18 @@ namespace System
|
||||
base.GetObjectData (info, context);
|
||||
}
|
||||
|
||||
|
||||
protected sealed override object DynamicInvokeImpl (object[] args)
|
||||
{
|
||||
if (prev != null)
|
||||
prev.DynamicInvokeImpl (args);
|
||||
|
||||
return base.DynamicInvokeImpl (args);
|
||||
if (delegates == null) {
|
||||
return base.DynamicInvokeImpl (args);
|
||||
} else {
|
||||
object r;
|
||||
int i = 0, len = delegates.Length;
|
||||
do {
|
||||
r = delegates [i].DynamicInvoke (args);
|
||||
} while (++i < len);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
// <remarks>
|
||||
@@ -83,19 +87,21 @@ namespace System
|
||||
if (d == null)
|
||||
return false;
|
||||
|
||||
MulticastDelegate this_prev = this.prev;
|
||||
MulticastDelegate obj_prev = d.prev;
|
||||
|
||||
do {
|
||||
if (this_prev == null)
|
||||
return obj_prev == null;
|
||||
|
||||
if (!this_prev.Compare (obj_prev))
|
||||
if (delegates == null && d.delegates == null) {
|
||||
return true;
|
||||
} else if (delegates == null ^ d.delegates == null) {
|
||||
return false;
|
||||
} else {
|
||||
if (delegates.Length != d.delegates.Length)
|
||||
return false;
|
||||
|
||||
this_prev = this_prev.prev;
|
||||
obj_prev = obj_prev.prev;
|
||||
} while (true);
|
||||
|
||||
for (int i = 0; i < delegates.Length; ++i) {
|
||||
if (!delegates [i].Equals (d.delegates [i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -112,27 +118,10 @@ namespace System
|
||||
// </summary>
|
||||
public sealed override Delegate[] GetInvocationList ()
|
||||
{
|
||||
MulticastDelegate d;
|
||||
d = (MulticastDelegate) this.Clone ();
|
||||
for (d.kpm_next = null; d.prev != null; d = d.prev)
|
||||
d.prev.kpm_next = d;
|
||||
|
||||
if (d.kpm_next == null) {
|
||||
MulticastDelegate other = (MulticastDelegate) d.Clone ();
|
||||
other.prev = null;
|
||||
other.kpm_next = null;
|
||||
return new Delegate [1] { other };
|
||||
}
|
||||
|
||||
var list = new List<Delegate> ();
|
||||
for (; d != null; d = d.kpm_next) {
|
||||
MulticastDelegate other = (MulticastDelegate) d.Clone ();
|
||||
other.prev = null;
|
||||
other.kpm_next = null;
|
||||
list.Add (other);
|
||||
}
|
||||
|
||||
return list.ToArray ();
|
||||
if (delegates != null)
|
||||
return (Delegate[]) delegates.Clone ();
|
||||
else
|
||||
return new Delegate[1] { this };
|
||||
}
|
||||
|
||||
// <summary>
|
||||
@@ -146,91 +135,30 @@ namespace System
|
||||
if (follow == null)
|
||||
return this;
|
||||
|
||||
MulticastDelegate combined, orig, clone;
|
||||
MulticastDelegate other = (MulticastDelegate) follow;
|
||||
|
||||
if (this.GetType() != follow.GetType ())
|
||||
throw new ArgumentException (Locale.GetText ("Incompatible Delegate Types. First is {0} second is {1}.", this.GetType ().FullName, follow.GetType ().FullName));
|
||||
MulticastDelegate ret = AllocDelegateLike_internal (this);
|
||||
|
||||
combined = (MulticastDelegate)follow.Clone ();
|
||||
combined.SetMulticastInvoke ();
|
||||
if (delegates == null && other.delegates == null) {
|
||||
ret.delegates = new Delegate [2] { this, other };
|
||||
} else if (delegates == null) {
|
||||
ret.delegates = new Delegate [1 + other.delegates.Length];
|
||||
|
||||
for (clone = combined, orig = ((MulticastDelegate)follow).prev; orig != null; orig = orig.prev) {
|
||||
|
||||
clone.prev = (MulticastDelegate)orig.Clone ();
|
||||
clone = clone.prev;
|
||||
ret.delegates [0] = this;
|
||||
Array.Copy (other.delegates, 0, ret.delegates, 1, other.delegates.Length);
|
||||
} else if (other.delegates == null) {
|
||||
ret.delegates = new Delegate [delegates.Length + 1];
|
||||
|
||||
Array.Copy (delegates, 0, ret.delegates, 0, delegates.Length);
|
||||
ret.delegates [ret.delegates.Length - 1] = other;
|
||||
} else {
|
||||
ret.delegates = new Delegate [delegates.Length + other.delegates.Length];
|
||||
|
||||
Array.Copy (delegates, 0, ret.delegates, 0, delegates.Length);
|
||||
Array.Copy (other.delegates, 0, ret.delegates, delegates.Length, other.delegates.Length);
|
||||
}
|
||||
|
||||
clone.SetMulticastInvoke ();
|
||||
clone.prev = (MulticastDelegate)this.Clone ();
|
||||
|
||||
for (clone = clone.prev, orig = this.prev; orig != null; orig = orig.prev) {
|
||||
|
||||
clone.prev = (MulticastDelegate)orig.Clone ();
|
||||
clone = clone.prev;
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
private bool BaseEquals (MulticastDelegate value)
|
||||
{
|
||||
return base.Equals (value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a slightly crippled version of
|
||||
* Knuth-Pratt-Morris over MulticastDelegate chains.
|
||||
* Border values are set as pointers in kpm_next;
|
||||
* Generally, KPM border arrays are length n+1 for
|
||||
* strings of n. This one works with length n at the
|
||||
* expense of a few additional comparisions.
|
||||
*/
|
||||
private static MulticastDelegate KPM (MulticastDelegate needle, MulticastDelegate haystack,
|
||||
out MulticastDelegate tail)
|
||||
{
|
||||
MulticastDelegate nx, hx;
|
||||
|
||||
// preprocess
|
||||
hx = needle;
|
||||
nx = needle.kpm_next = null;
|
||||
do {
|
||||
while ((nx != null) && (!nx.BaseEquals (hx)))
|
||||
nx = nx.kpm_next;
|
||||
|
||||
hx = hx.prev;
|
||||
if (hx == null)
|
||||
break;
|
||||
|
||||
nx = nx == null ? needle : nx.prev;
|
||||
if (hx.BaseEquals (nx))
|
||||
hx.kpm_next = nx.kpm_next;
|
||||
else
|
||||
hx.kpm_next = nx;
|
||||
|
||||
} while (true);
|
||||
|
||||
// match
|
||||
MulticastDelegate match = haystack;
|
||||
nx = needle;
|
||||
hx = haystack;
|
||||
do {
|
||||
while (nx != null && !nx.BaseEquals (hx)) {
|
||||
nx = nx.kpm_next;
|
||||
match = match.prev;
|
||||
}
|
||||
|
||||
nx = nx == null ? needle : nx.prev;
|
||||
if (nx == null) {
|
||||
// bingo
|
||||
tail = hx.prev;
|
||||
return match;
|
||||
}
|
||||
|
||||
hx = hx.prev;
|
||||
} while (hx != null);
|
||||
|
||||
tail = null;
|
||||
return null;
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected sealed override Delegate RemoveImpl (Delegate value)
|
||||
@@ -238,41 +166,87 @@ namespace System
|
||||
if (value == null)
|
||||
return this;
|
||||
|
||||
// match this with value
|
||||
MulticastDelegate head, tail;
|
||||
head = KPM ((MulticastDelegate)value, this, out tail);
|
||||
if (head == null)
|
||||
MulticastDelegate other = (MulticastDelegate) value;
|
||||
|
||||
if (delegates == null && other.delegates == null) {
|
||||
/* if they are not equal and the current one is not
|
||||
* a multicastdelegate then we cannot delete it */
|
||||
return this.Equals (other) ? null : this;
|
||||
} else if (delegates == null) {
|
||||
foreach (var d in other.delegates) {
|
||||
if (this.Equals (d))
|
||||
return null;
|
||||
}
|
||||
return this;
|
||||
} else if (other.delegates == null) {
|
||||
int idx = Array.LastIndexOf (delegates, other);
|
||||
if (idx == -1)
|
||||
return this;
|
||||
|
||||
// duplicate chain without head..tail
|
||||
MulticastDelegate prev = null, retval = null, orig;
|
||||
for (orig = this; (object)orig != (object)head; orig = orig.prev) {
|
||||
MulticastDelegate clone = (MulticastDelegate)orig.Clone ();
|
||||
if (prev != null)
|
||||
prev.prev = clone;
|
||||
else
|
||||
retval = clone;
|
||||
prev = clone;
|
||||
}
|
||||
for (orig = tail; (object)orig != null; orig = orig.prev) {
|
||||
MulticastDelegate clone = (MulticastDelegate)orig.Clone ();
|
||||
if (prev != null)
|
||||
prev.prev = clone;
|
||||
else
|
||||
retval = clone;
|
||||
prev = clone;
|
||||
}
|
||||
if (prev != null)
|
||||
prev.prev = null;
|
||||
if (delegates.Length <= 1) {
|
||||
/* delegates.Length should never be equal or
|
||||
* lower than 1, it should be 2 or greater */
|
||||
throw new InvalidOperationException ();
|
||||
}
|
||||
|
||||
return retval;
|
||||
if (delegates.Length == 2)
|
||||
return delegates [idx == 0 ? 1 : 0];
|
||||
|
||||
MulticastDelegate ret = AllocDelegateLike_internal (this);
|
||||
ret.delegates = new Delegate [delegates.Length - 1];
|
||||
|
||||
Array.Copy (delegates, ret.delegates, idx);
|
||||
Array.Copy (delegates, idx + 1, ret.delegates, idx, delegates.Length - idx - 1);
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
/* wild case : remove MulticastDelegate from MulticastDelegate
|
||||
* complexity is O(m * n), with n the number of elements in
|
||||
* this.delegates and m the number of elements in other.delegates */
|
||||
MulticastDelegate ret = AllocDelegateLike_internal (this);
|
||||
ret.delegates = new Delegate [delegates.Length];
|
||||
|
||||
/* we should use a set with O(1) lookup complexity
|
||||
* but HashSet is implemented in System.Core.dll */
|
||||
List<Delegate> other_delegates = new List<Delegate> ();
|
||||
for (int i = 0; i < other.delegates.Length; ++i)
|
||||
other_delegates.Add (other.delegates [i]);
|
||||
|
||||
int idx = delegates.Length;
|
||||
|
||||
/* we need to remove elements from the end to the beginning, as
|
||||
* the addition and removal of delegates behaves like a stack */
|
||||
for (int i = delegates.Length - 1; i >= 0; --i) {
|
||||
/* if delegates[i] is not in other_delegates,
|
||||
* then we can safely add it to ret.delegates
|
||||
* otherwise we remove it from other_delegates */
|
||||
if (!other_delegates.Remove (delegates [i]))
|
||||
ret.delegates [--idx] = delegates [i];
|
||||
}
|
||||
|
||||
/* the elements are at the end of the array, we
|
||||
* need to move them back to the beginning of it */
|
||||
int count = delegates.Length - idx;
|
||||
Array.Copy (ret.delegates, idx, ret.delegates, 0, count);
|
||||
|
||||
if (count == 0)
|
||||
return null;
|
||||
|
||||
if (count == 1)
|
||||
return ret.delegates [0];
|
||||
|
||||
if (count != delegates.Length)
|
||||
Array.Resize (ref ret.delegates, count);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool operator == (MulticastDelegate d1, MulticastDelegate d2)
|
||||
{
|
||||
if (d1 == null)
|
||||
return d2 == null;
|
||||
|
||||
return d2 == null;
|
||||
|
||||
return d1.Equals (d2);
|
||||
}
|
||||
|
||||
@@ -280,7 +254,7 @@ namespace System
|
||||
{
|
||||
if (d1 == null)
|
||||
return d2 != null;
|
||||
|
||||
|
||||
return !d1.Equals (d2);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user