From 65edb5389272392fb56bbc82305cd89465da1e0e Mon Sep 17 00:00:00 2001 From: Alexander Corrado Date: Thu, 6 Jan 2011 20:14:26 -0800 Subject: [PATCH] Fix issues when base class virtual methods are prepended into primary vtable. --- src/Mono.VisualC.Interop/CppTypeInfo.cs | 4 +- .../Util/LazyGeneratedList.cs | 68 +++++++++++++++++-- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/src/Mono.VisualC.Interop/CppTypeInfo.cs b/src/Mono.VisualC.Interop/CppTypeInfo.cs index 19224721..a7bb814b 100644 --- a/src/Mono.VisualC.Interop/CppTypeInfo.cs +++ b/src/Mono.VisualC.Interop/CppTypeInfo.cs @@ -103,8 +103,8 @@ namespace Mono.VisualC.Interop { VirtualMethods.Insert (BaseVTableSlots + i, baseType.VirtualMethods [i]); BaseVTableSlots += newVirtualMethodCount; - VTableDelegateTypes.Skew (newVirtualMethodCount); - VTableOverrides.Skew (newVirtualMethodCount); + VTableDelegateTypes.PrependLast (baseType.VTableDelegateTypes); + VTableOverrides.PrependLast (baseType.VTableOverrides); } field_offset_padding += baseType.native_size + diff --git a/src/Mono.VisualC.Interop/Util/LazyGeneratedList.cs b/src/Mono.VisualC.Interop/Util/LazyGeneratedList.cs index 7054ab32..08eb63c7 100644 --- a/src/Mono.VisualC.Interop/Util/LazyGeneratedList.cs +++ b/src/Mono.VisualC.Interop/Util/LazyGeneratedList.cs @@ -37,13 +37,16 @@ namespace Mono.VisualC.Interop.Util { private TItem [] cache; private Func generator; - private int skew; + private LazyGeneratedList previous; + private LazyGeneratedList next; + private int lead, follow; public LazyGeneratedList (int count, Func generator) { this.cache = new TItem [count]; this.generator = generator; - this.skew = 0; + this.lead = 0; + this.follow = 0; } public IEnumerator GetEnumerator () @@ -57,7 +60,7 @@ namespace Mono.VisualC.Interop.Util { } public int Count { - get { return cache.Length + skew; } + get { return lead + cache.Length + follow; } } public bool IsReadOnly { @@ -66,8 +69,19 @@ namespace Mono.VisualC.Interop.Util { public TItem this [int index] { get { - int realIndex = index - skew; - if (realIndex < 0) return null; + if (index < lead) { + if (previous != null && index > 0) + return previous [index]; + throw new IndexOutOfRangeException (index.ToString ()); + } + + int realIndex = index - lead; + if (realIndex > cache.Length) { + int followIndex = realIndex - cache.Length; + if (next != null && followIndex < follow) + return next [followIndex]; + throw new IndexOutOfRangeException (index.ToString ()); + } if (cache [realIndex] == null) cache [realIndex] = generator (realIndex); @@ -79,9 +93,49 @@ namespace Mono.VisualC.Interop.Util { } } - public void Skew (int skew) + /* Visual aid for the behavior of the following methods: + + || + ^ ^ ^ ^ + PrependFirst PrependLast AppendFirst AppendLast + */ + + public void AppendFirst (LazyGeneratedList list) + { + follow += list.Count; + if (next != null) + list.AppendLast (next); + + next = list; + } + + public void AppendLast (LazyGeneratedList list) { - this.skew += skew; + if (next == null) + next = list; + else + next.AppendLast (list); + + follow += list.Count; + } + + public void PrependFirst (LazyGeneratedList list) + { + if (previous == null) + previous = list; + else + previous.PrependFirst (list); + + lead += list.Count; + } + + public void PrependLast (LazyGeneratedList list) + { + lead += list.Count; + if (previous != null) + list.PrependFirst (previous); + + previous = list; } // FIXME: Should probably implement these 3 at some point